1 /*------------------------------------------------------------------------- 2 * 3 * name.c 4 * Functions for the built-in type "name". 5 * 6 * name replaces char16 and is carefully implemented so that it 7 * is a string of physical length NAMEDATALEN. 8 * DO NOT use hard-coded constants anywhere 9 * always use NAMEDATALEN as the symbolic constant! - jolly 8/21/95 10 * 11 * 12 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group 13 * Portions Copyright (c) 1994, Regents of the University of California 14 * 15 * 16 * IDENTIFICATION 17 * src/backend/utils/adt/name.c 18 * 19 *------------------------------------------------------------------------- 20 */ 21 #include "postgres.h" 22 23 #include "catalog/namespace.h" 24 #include "catalog/pg_type.h" 25 #include "libpq/pqformat.h" 26 #include "mb/pg_wchar.h" 27 #include "miscadmin.h" 28 #include "utils/array.h" 29 #include "utils/builtins.h" 30 #include "utils/lsyscache.h" 31 32 33 /***************************************************************************** 34 * USER I/O ROUTINES (none) * 35 *****************************************************************************/ 36 37 38 /* 39 * namein - converts "..." to internal representation 40 * 41 * Note: 42 * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls 43 * Now, always NULL terminated 44 */ 45 Datum 46 namein(PG_FUNCTION_ARGS) 47 { 48 char *s = PG_GETARG_CSTRING(0); 49 Name result; 50 int len; 51 52 len = strlen(s); 53 54 /* Truncate oversize input */ 55 if (len >= NAMEDATALEN) 56 len = pg_mbcliplen(s, len, NAMEDATALEN - 1); 57 58 /* We use palloc0 here to ensure result is zero-padded */ 59 result = (Name) palloc0(NAMEDATALEN); 60 memcpy(NameStr(*result), s, len); 61 62 PG_RETURN_NAME(result); 63 } 64 65 /* 66 * nameout - converts internal representation to "..." 67 */ 68 Datum 69 nameout(PG_FUNCTION_ARGS) 70 { 71 Name s = PG_GETARG_NAME(0); 72 73 PG_RETURN_CSTRING(pstrdup(NameStr(*s))); 74 } 75 76 /* 77 * namerecv - converts external binary format to name 78 */ 79 Datum 80 namerecv(PG_FUNCTION_ARGS) 81 { 82 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); 83 Name result; 84 char *str; 85 int nbytes; 86 87 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); 88 if (nbytes >= NAMEDATALEN) 89 ereport(ERROR, 90 (errcode(ERRCODE_NAME_TOO_LONG), 91 errmsg("identifier too long"), 92 errdetail("Identifier must be less than %d characters.", 93 NAMEDATALEN))); 94 result = (NameData *) palloc0(NAMEDATALEN); 95 memcpy(result, str, nbytes); 96 pfree(str); 97 PG_RETURN_NAME(result); 98 } 99 100 /* 101 * namesend - converts name to binary format 102 */ 103 Datum 104 namesend(PG_FUNCTION_ARGS) 105 { 106 Name s = PG_GETARG_NAME(0); 107 StringInfoData buf; 108 109 pq_begintypsend(&buf); 110 pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s))); 111 PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); 112 } 113 114 115 /***************************************************************************** 116 * PUBLIC ROUTINES * 117 *****************************************************************************/ 118 119 /* 120 * nameeq - returns 1 iff arguments are equal 121 * namene - returns 1 iff arguments are not equal 122 * 123 * BUGS: 124 * Assumes that "xy\0\0a" should be equal to "xy\0b". 125 * If not, can do the comparison backwards for efficiency. 126 * 127 * namelt - returns 1 iff a < b 128 * namele - returns 1 iff a <= b 129 * namegt - returns 1 iff a > b 130 * namege - returns 1 iff a >= b 131 * 132 */ 133 Datum 134 nameeq(PG_FUNCTION_ARGS) 135 { 136 Name arg1 = PG_GETARG_NAME(0); 137 Name arg2 = PG_GETARG_NAME(1); 138 139 PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) == 0); 140 } 141 142 Datum 143 namene(PG_FUNCTION_ARGS) 144 { 145 Name arg1 = PG_GETARG_NAME(0); 146 Name arg2 = PG_GETARG_NAME(1); 147 148 PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) != 0); 149 } 150 151 Datum 152 namelt(PG_FUNCTION_ARGS) 153 { 154 Name arg1 = PG_GETARG_NAME(0); 155 Name arg2 = PG_GETARG_NAME(1); 156 157 PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) < 0); 158 } 159 160 Datum 161 namele(PG_FUNCTION_ARGS) 162 { 163 Name arg1 = PG_GETARG_NAME(0); 164 Name arg2 = PG_GETARG_NAME(1); 165 166 PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) <= 0); 167 } 168 169 Datum 170 namegt(PG_FUNCTION_ARGS) 171 { 172 Name arg1 = PG_GETARG_NAME(0); 173 Name arg2 = PG_GETARG_NAME(1); 174 175 PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) > 0); 176 } 177 178 Datum 179 namege(PG_FUNCTION_ARGS) 180 { 181 Name arg1 = PG_GETARG_NAME(0); 182 Name arg2 = PG_GETARG_NAME(1); 183 184 PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) >= 0); 185 } 186 187 188 /* (see char.c for comparison/operation routines) */ 189 190 int 191 namecpy(Name n1, Name n2) 192 { 193 if (!n1 || !n2) 194 return -1; 195 StrNCpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN); 196 return 0; 197 } 198 199 #ifdef NOT_USED 200 int 201 namecat(Name n1, Name n2) 202 { 203 return namestrcat(n1, NameStr(*n2)); /* n2 can't be any longer than n1 */ 204 } 205 #endif 206 207 #ifdef NOT_USED 208 int 209 namecmp(Name n1, Name n2) 210 { 211 return strncmp(NameStr(*n1), NameStr(*n2), NAMEDATALEN); 212 } 213 #endif 214 215 int 216 namestrcpy(Name name, const char *str) 217 { 218 if (!name || !str) 219 return -1; 220 StrNCpy(NameStr(*name), str, NAMEDATALEN); 221 return 0; 222 } 223 224 #ifdef NOT_USED 225 int 226 namestrcat(Name name, const char *str) 227 { 228 int i; 229 char *p, 230 *q; 231 232 if (!name || !str) 233 return -1; 234 for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p) 235 ; 236 for (q = str; i < NAMEDATALEN; ++i, ++p, ++q) 237 { 238 *p = *q; 239 if (!*q) 240 break; 241 } 242 return 0; 243 } 244 #endif 245 246 int 247 namestrcmp(Name name, const char *str) 248 { 249 if (!name && !str) 250 return 0; 251 if (!name) 252 return -1; /* NULL < anything */ 253 if (!str) 254 return 1; /* NULL < anything */ 255 return strncmp(NameStr(*name), str, NAMEDATALEN); 256 } 257 258 259 /* 260 * SQL-functions CURRENT_USER, SESSION_USER 261 */ 262 Datum 263 current_user(PG_FUNCTION_ARGS) 264 { 265 PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false)))); 266 } 267 268 Datum 269 session_user(PG_FUNCTION_ARGS) 270 { 271 PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false)))); 272 } 273 274 275 /* 276 * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS 277 */ 278 Datum 279 current_schema(PG_FUNCTION_ARGS) 280 { 281 List *search_path = fetch_search_path(false); 282 char *nspname; 283 284 if (search_path == NIL) 285 PG_RETURN_NULL(); 286 nspname = get_namespace_name(linitial_oid(search_path)); 287 list_free(search_path); 288 if (!nspname) 289 PG_RETURN_NULL(); /* recently-deleted namespace? */ 290 PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname))); 291 } 292 293 Datum 294 current_schemas(PG_FUNCTION_ARGS) 295 { 296 List *search_path = fetch_search_path(PG_GETARG_BOOL(0)); 297 ListCell *l; 298 Datum *names; 299 int i; 300 ArrayType *array; 301 302 names = (Datum *) palloc(list_length(search_path) * sizeof(Datum)); 303 i = 0; 304 foreach(l, search_path) 305 { 306 char *nspname; 307 308 nspname = get_namespace_name(lfirst_oid(l)); 309 if (nspname) /* watch out for deleted namespace */ 310 { 311 names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname)); 312 i++; 313 } 314 } 315 list_free(search_path); 316 317 array = construct_array(names, i, 318 NAMEOID, 319 NAMEDATALEN, /* sizeof(Name) */ 320 false, /* Name is not by-val */ 321 'c'); /* alignment of Name */ 322 323 PG_RETURN_POINTER(array); 324 } 325