1 /*-------------------------------------------------------------------------
4 * Functions for the built-in type "name".
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
12 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
17 * src/backend/utils/adt/name.c
19 *-------------------------------------------------------------------------
23 #include "catalog/namespace.h"
24 #include "catalog/pg_collation.h"
25 #include "catalog/pg_type.h"
26 #include "libpq/pqformat.h"
27 #include "mb/pg_wchar.h"
28 #include "miscadmin.h"
29 #include "utils/array.h"
30 #include "utils/builtins.h"
31 #include "utils/lsyscache.h"
32 #include "utils/varlena.h"
35 /*****************************************************************************
36 * USER I/O ROUTINES (none) *
37 *****************************************************************************/
41 * namein - converts "..." to internal representation
44 * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls
45 * Now, always NULL terminated
48 namein(PG_FUNCTION_ARGS)
50 char *s = PG_GETARG_CSTRING(0);
56 /* Truncate oversize input */
57 if (len >= NAMEDATALEN)
58 len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
60 /* We use palloc0 here to ensure result is zero-padded */
61 result = (Name) palloc0(NAMEDATALEN);
62 memcpy(NameStr(*result), s, len);
64 PG_RETURN_NAME(result);
68 * nameout - converts internal representation to "..."
71 nameout(PG_FUNCTION_ARGS)
73 Name s = PG_GETARG_NAME(0);
75 PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
79 * namerecv - converts external binary format to name
82 namerecv(PG_FUNCTION_ARGS)
84 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
89 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
90 if (nbytes >= NAMEDATALEN)
92 (errcode(ERRCODE_NAME_TOO_LONG),
93 errmsg("identifier too long"),
94 errdetail("Identifier must be less than %d characters.",
96 result = (NameData *) palloc0(NAMEDATALEN);
97 memcpy(result, str, nbytes);
99 PG_RETURN_NAME(result);
103 * namesend - converts name to binary format
106 namesend(PG_FUNCTION_ARGS)
108 Name s = PG_GETARG_NAME(0);
111 pq_begintypsend(&buf);
112 pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
113 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
117 /*****************************************************************************
118 * COMPARISON/SORTING ROUTINES *
119 *****************************************************************************/
122 * nameeq - returns 1 iff arguments are equal
123 * namene - returns 1 iff arguments are not equal
124 * namelt - returns 1 iff a < b
125 * namele - returns 1 iff a <= b
126 * namegt - returns 1 iff a > b
127 * namege - returns 1 iff a >= b
129 * Note that the use of strncmp with NAMEDATALEN limit is mostly historical;
130 * strcmp would do as well, because we do not allow NAME values that don't
131 * have a '\0' terminator. Whatever might be past the terminator is not
132 * considered relevant to comparisons.
135 namecmp(Name arg1, Name arg2, Oid collid)
137 /* Fast path for common case used in system catalogs */
138 if (collid == C_COLLATION_OID)
139 return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN);
141 /* Else rely on the varstr infrastructure */
142 return varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)),
143 NameStr(*arg2), strlen(NameStr(*arg2)),
148 nameeq(PG_FUNCTION_ARGS)
150 Name arg1 = PG_GETARG_NAME(0);
151 Name arg2 = PG_GETARG_NAME(1);
153 PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
157 namene(PG_FUNCTION_ARGS)
159 Name arg1 = PG_GETARG_NAME(0);
160 Name arg2 = PG_GETARG_NAME(1);
162 PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
166 namelt(PG_FUNCTION_ARGS)
168 Name arg1 = PG_GETARG_NAME(0);
169 Name arg2 = PG_GETARG_NAME(1);
171 PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
175 namele(PG_FUNCTION_ARGS)
177 Name arg1 = PG_GETARG_NAME(0);
178 Name arg2 = PG_GETARG_NAME(1);
180 PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
184 namegt(PG_FUNCTION_ARGS)
186 Name arg1 = PG_GETARG_NAME(0);
187 Name arg2 = PG_GETARG_NAME(1);
189 PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
193 namege(PG_FUNCTION_ARGS)
195 Name arg1 = PG_GETARG_NAME(0);
196 Name arg2 = PG_GETARG_NAME(1);
198 PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
202 btnamecmp(PG_FUNCTION_ARGS)
204 Name arg1 = PG_GETARG_NAME(0);
205 Name arg2 = PG_GETARG_NAME(1);
207 PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
211 btnamesortsupport(PG_FUNCTION_ARGS)
213 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
214 Oid collid = ssup->ssup_collation;
215 MemoryContext oldcontext;
217 oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
219 /* Use generic string SortSupport */
220 varstr_sortsupport(ssup, NAMEOID, collid);
222 MemoryContextSwitchTo(oldcontext);
228 /*****************************************************************************
229 * MISCELLANEOUS PUBLIC ROUTINES *
230 *****************************************************************************/
233 namecpy(Name n1, const NameData *n2)
237 StrNCpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
243 namecat(Name n1, Name n2)
245 return namestrcat(n1, NameStr(*n2)); /* n2 can't be any longer than n1 */
250 namestrcpy(Name name, const char *str)
254 StrNCpy(NameStr(*name), str, NAMEDATALEN);
260 namestrcat(Name name, const char *str)
268 for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p)
270 for (q = str; i < NAMEDATALEN; ++i, ++p, ++q)
281 * Compare a NAME to a C string
283 * Assumes C collation always; be careful when using this for
284 * anything but equality checks!
287 namestrcmp(Name name, const char *str)
292 return -1; /* NULL < anything */
294 return 1; /* NULL < anything */
295 return strncmp(NameStr(*name), str, NAMEDATALEN);
300 * SQL-functions CURRENT_USER, SESSION_USER
303 current_user(PG_FUNCTION_ARGS)
305 PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
309 session_user(PG_FUNCTION_ARGS)
311 PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
316 * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
319 current_schema(PG_FUNCTION_ARGS)
321 List *search_path = fetch_search_path(false);
324 if (search_path == NIL)
326 nspname = get_namespace_name(linitial_oid(search_path));
327 list_free(search_path);
329 PG_RETURN_NULL(); /* recently-deleted namespace? */
330 PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
334 current_schemas(PG_FUNCTION_ARGS)
336 List *search_path = fetch_search_path(PG_GETARG_BOOL(0));
342 names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
344 foreach(l, search_path)
348 nspname = get_namespace_name(lfirst_oid(l));
349 if (nspname) /* watch out for deleted namespace */
351 names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
355 list_free(search_path);
357 array = construct_array(names, i,
359 NAMEDATALEN, /* sizeof(Name) */
360 false, /* Name is not by-val */
361 'c'); /* alignment of Name */
363 PG_RETURN_POINTER(array);
367 * SQL-function nameconcatoid(name, oid) returns name
369 * This is used in the information_schema to produce specific_name columns,
370 * which are supposed to be unique per schema. We achieve that (in an ugly
371 * way) by appending the object's OID. The result is the same as
372 * ($1::text || '_' || $2::text)::name
373 * except that, if it would not fit in NAMEDATALEN, we make it do so by
374 * truncating the name input (not the oid).
377 nameconcatoid(PG_FUNCTION_ARGS)
379 Name nam = PG_GETARG_NAME(0);
380 Oid oid = PG_GETARG_OID(1);
386 suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
387 namlen = strlen(NameStr(*nam));
389 /* Truncate oversize input by truncating name part, not suffix */
390 if (namlen + suflen >= NAMEDATALEN)
391 namlen = pg_mbcliplen(NameStr(*nam), namlen, NAMEDATALEN - 1 - suflen);
393 /* We use palloc0 here to ensure result is zero-padded */
394 result = (Name) palloc0(NAMEDATALEN);
395 memcpy(NameStr(*result), NameStr(*nam), namlen);
396 memcpy(NameStr(*result) + namlen, suffix, suflen);
398 PG_RETURN_NAME(result);