Age Owner Branch data TLA Line data Source code
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-2025, 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_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"
33 : :
34 : :
35 : : /*****************************************************************************
36 : : * USER I/O ROUTINES (none) *
37 : : *****************************************************************************/
38 : :
39 : :
40 : : /*
41 : : * namein - converts cstring to internal representation
42 : : *
43 : : * Note:
44 : : * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls
45 : : * Now, always NULL terminated
46 : : */
47 : : Datum
9165 tgl@sss.pgh.pa.us 48 :CBC 487708 : namein(PG_FUNCTION_ARGS)
49 : : {
50 : 487708 : char *s = PG_GETARG_CSTRING(0);
51 : : Name result;
52 : : int len;
53 : :
8486 ishii@postgresql.org 54 : 487708 : len = strlen(s);
55 : :
56 : : /* Truncate oversize input */
4852 tgl@sss.pgh.pa.us 57 [ + + ]: 487708 : if (len >= NAMEDATALEN)
58 : 27 : len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
59 : :
60 : : /* We use palloc0 here to ensure result is zero-padded */
61 : 487708 : result = (Name) palloc0(NAMEDATALEN);
8486 ishii@postgresql.org 62 : 487708 : memcpy(NameStr(*result), s, len);
63 : :
9165 tgl@sss.pgh.pa.us 64 : 487708 : PG_RETURN_NAME(result);
65 : : }
66 : :
67 : : /*
68 : : * nameout - converts internal representation to cstring
69 : : */
70 : : Datum
71 : 1382067 : nameout(PG_FUNCTION_ARGS)
72 : : {
73 : 1382067 : Name s = PG_GETARG_NAME(0);
74 : :
75 : 1382067 : PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
76 : : }
77 : :
78 : : /*
79 : : * namerecv - converts external binary format to name
80 : : */
81 : : Datum
8156 82 : 3 : namerecv(PG_FUNCTION_ARGS)
83 : : {
84 : 3 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
85 : : Name result;
86 : : char *str;
87 : : int nbytes;
88 : :
89 : 3 : str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
90 [ - + ]: 3 : if (nbytes >= NAMEDATALEN)
8077 tgl@sss.pgh.pa.us 91 [ # # ]:UBC 0 : ereport(ERROR,
92 : : (errcode(ERRCODE_NAME_TOO_LONG),
93 : : errmsg("identifier too long"),
94 : : errdetail("Identifier must be less than %d characters.",
95 : : NAMEDATALEN)));
8156 tgl@sss.pgh.pa.us 96 :CBC 3 : result = (NameData *) palloc0(NAMEDATALEN);
97 : 3 : memcpy(result, str, nbytes);
98 : 3 : pfree(str);
99 : 3 : PG_RETURN_NAME(result);
100 : : }
101 : :
102 : : /*
103 : : * namesend - converts name to binary format
104 : : */
105 : : Datum
106 : 3 : namesend(PG_FUNCTION_ARGS)
107 : : {
108 : 3 : Name s = PG_GETARG_NAME(0);
109 : : StringInfoData buf;
110 : :
111 : 3 : pq_begintypsend(&buf);
112 : 3 : pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
113 : 3 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
114 : : }
115 : :
116 : :
117 : : /*****************************************************************************
118 : : * COMPARISON/SORTING ROUTINES *
119 : : *****************************************************************************/
120 : :
121 : : /*
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
128 : : *
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.
133 : : */
134 : : static int
2360 peter@eisentraut.org 135 : 21012617 : namecmp(Name arg1, Name arg2, Oid collid)
136 : : {
137 : : /* Fast path for common case used in system catalogs */
138 [ + - ]: 21012617 : if (collid == C_COLLATION_OID)
139 : 21012617 : return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN);
140 : :
141 : : /* Else rely on the varstr infrastructure */
2360 peter@eisentraut.org 142 :UBC 0 : return varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)),
143 : 0 : NameStr(*arg2), strlen(NameStr(*arg2)),
144 : : collid);
145 : : }
146 : :
147 : : Datum
9165 tgl@sss.pgh.pa.us 148 :CBC 7465302 : nameeq(PG_FUNCTION_ARGS)
149 : : {
150 : 7465302 : Name arg1 = PG_GETARG_NAME(0);
151 : 7465302 : Name arg2 = PG_GETARG_NAME(1);
152 : :
2360 peter@eisentraut.org 153 : 7465302 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
154 : : }
155 : :
156 : : Datum
9165 tgl@sss.pgh.pa.us 157 : 28926 : namene(PG_FUNCTION_ARGS)
158 : : {
159 : 28926 : Name arg1 = PG_GETARG_NAME(0);
160 : 28926 : Name arg2 = PG_GETARG_NAME(1);
161 : :
2360 peter@eisentraut.org 162 : 28926 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
163 : : }
164 : :
165 : : Datum
9165 tgl@sss.pgh.pa.us 166 : 52475 : namelt(PG_FUNCTION_ARGS)
167 : : {
168 : 52475 : Name arg1 = PG_GETARG_NAME(0);
169 : 52475 : Name arg2 = PG_GETARG_NAME(1);
170 : :
2453 171 : 52475 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
172 : : }
173 : :
174 : : Datum
9165 175 : 7659 : namele(PG_FUNCTION_ARGS)
176 : : {
177 : 7659 : Name arg1 = PG_GETARG_NAME(0);
178 : 7659 : Name arg2 = PG_GETARG_NAME(1);
179 : :
2453 180 : 7659 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
181 : : }
182 : :
183 : : Datum
9165 184 : 3934 : namegt(PG_FUNCTION_ARGS)
185 : : {
186 : 3934 : Name arg1 = PG_GETARG_NAME(0);
187 : 3934 : Name arg2 = PG_GETARG_NAME(1);
188 : :
2453 189 : 3934 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
190 : : }
191 : :
192 : : Datum
9165 193 : 9072 : namege(PG_FUNCTION_ARGS)
194 : : {
195 : 9072 : Name arg1 = PG_GETARG_NAME(0);
196 : 9072 : Name arg2 = PG_GETARG_NAME(1);
197 : :
2453 198 : 9072 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
199 : : }
200 : :
201 : : Datum
202 : 13445249 : btnamecmp(PG_FUNCTION_ARGS)
203 : : {
204 : 13445249 : Name arg1 = PG_GETARG_NAME(0);
205 : 13445249 : Name arg2 = PG_GETARG_NAME(1);
206 : :
207 : 13445249 : PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
208 : : }
209 : :
210 : : Datum
211 : 24209 : btnamesortsupport(PG_FUNCTION_ARGS)
212 : : {
213 : 24209 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
214 : 24209 : Oid collid = ssup->ssup_collation;
215 : : MemoryContext oldcontext;
216 : :
217 : 24209 : oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
218 : :
219 : : /* Use generic string SortSupport */
220 : 24209 : varstr_sortsupport(ssup, NAMEOID, collid);
221 : :
222 : 24209 : MemoryContextSwitchTo(oldcontext);
223 : :
224 : 24209 : PG_RETURN_VOID();
225 : : }
226 : :
227 : :
228 : : /*****************************************************************************
229 : : * MISCELLANEOUS PUBLIC ROUTINES *
230 : : *****************************************************************************/
231 : :
232 : : void
9359 peter_e@gmx.net 233 : 4962732 : namestrcpy(Name name, const char *str)
234 : : {
235 : : /* NB: We need to zero-pad the destination. */
1853 peter@eisentraut.org 236 : 4962732 : strncpy(NameStr(*name), str, NAMEDATALEN);
1578 tgl@sss.pgh.pa.us 237 : 4962732 : NameStr(*name)[NAMEDATALEN - 1] = '\0';
10651 scrappy@hub.org 238 : 4962732 : }
239 : :
240 : : /*
241 : : * Compare a NAME to a C string
242 : : *
243 : : * Assumes C collation always; be careful when using this for
244 : : * anything but equality checks!
245 : : */
246 : : int
9359 peter_e@gmx.net 247 : 5174216 : namestrcmp(Name name, const char *str)
248 : : {
10226 bruce@momjian.us 249 [ - + - - ]: 5174216 : if (!name && !str)
9867 bruce@momjian.us 250 :UBC 0 : return 0;
10226 bruce@momjian.us 251 [ - + ]:CBC 5174216 : if (!name)
9867 bruce@momjian.us 252 :UBC 0 : return -1; /* NULL < anything */
10226 bruce@momjian.us 253 [ - + ]:CBC 5174216 : if (!str)
9867 bruce@momjian.us 254 :UBC 0 : return 1; /* NULL < anything */
9435 bruce@momjian.us 255 :CBC 5174216 : return strncmp(NameStr(*name), str, NAMEDATALEN);
256 : : }
257 : :
258 : :
259 : : /*
260 : : * SQL-functions CURRENT_USER, SESSION_USER
261 : : */
262 : : Datum
9118 peter_e@gmx.net 263 : 9201 : current_user(PG_FUNCTION_ARGS)
264 : : {
3773 andrew@dunslane.net 265 : 9201 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
266 : : }
267 : :
268 : : Datum
9118 peter_e@gmx.net 269 : 299 : session_user(PG_FUNCTION_ARGS)
270 : : {
3773 andrew@dunslane.net 271 : 299 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
272 : : }
273 : :
274 : :
275 : : /*
276 : : * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
277 : : */
278 : : Datum
8534 tgl@sss.pgh.pa.us 279 : 17 : current_schema(PG_FUNCTION_ARGS)
280 : : {
8403 bruce@momjian.us 281 : 17 : List *search_path = fetch_search_path(false);
282 : : char *nspname;
283 : :
8534 tgl@sss.pgh.pa.us 284 [ + + ]: 17 : if (search_path == NIL)
285 : 3 : PG_RETURN_NULL();
7773 neilc@samurai.com 286 : 14 : nspname = get_namespace_name(linitial_oid(search_path));
287 : 14 : list_free(search_path);
8168 tgl@sss.pgh.pa.us 288 [ - + ]: 14 : if (!nspname)
8168 tgl@sss.pgh.pa.us 289 :UBC 0 : PG_RETURN_NULL(); /* recently-deleted namespace? */
8534 tgl@sss.pgh.pa.us 290 :CBC 14 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
291 : : }
292 : :
293 : : Datum
294 : 268 : current_schemas(PG_FUNCTION_ARGS)
295 : : {
8403 bruce@momjian.us 296 : 268 : List *search_path = fetch_search_path(PG_GETARG_BOOL(0));
297 : : ListCell *l;
298 : : Datum *names;
299 : : int i;
300 : : ArrayType *array;
301 : :
7763 tgl@sss.pgh.pa.us 302 : 268 : names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
8534 303 : 268 : i = 0;
7773 neilc@samurai.com 304 [ + + + + : 433 : foreach(l, search_path)
+ + ]
305 : : {
306 : : char *nspname;
307 : :
308 : 165 : nspname = get_namespace_name(lfirst_oid(l));
8168 tgl@sss.pgh.pa.us 309 [ + - ]: 165 : if (nspname) /* watch out for deleted namespace */
310 : : {
311 : 165 : names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
312 : 165 : i++;
313 : : }
314 : : }
7773 neilc@samurai.com 315 : 268 : list_free(search_path);
316 : :
1163 peter@eisentraut.org 317 : 268 : array = construct_array_builtin(names, i, NAMEOID);
318 : :
8534 tgl@sss.pgh.pa.us 319 : 268 : PG_RETURN_POINTER(array);
320 : : }
321 : :
322 : : /*
323 : : * SQL-function nameconcatoid(name, oid) returns name
324 : : *
325 : : * This is used in the information_schema to produce specific_name columns,
326 : : * which are supposed to be unique per schema. We achieve that (in an ugly
327 : : * way) by appending the object's OID. The result is the same as
328 : : * ($1::text || '_' || $2::text)::name
329 : : * except that, if it would not fit in NAMEDATALEN, we make it do so by
330 : : * truncating the name input (not the oid).
331 : : */
332 : : Datum
2452 333 : 17878 : nameconcatoid(PG_FUNCTION_ARGS)
334 : : {
335 : 17878 : Name nam = PG_GETARG_NAME(0);
336 : 17878 : Oid oid = PG_GETARG_OID(1);
337 : : Name result;
338 : : char suffix[20];
339 : : int suflen;
340 : : int namlen;
341 : :
342 : 17878 : suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
343 : 17878 : namlen = strlen(NameStr(*nam));
344 : :
345 : : /* Truncate oversize input by truncating name part, not suffix */
346 [ - + ]: 17878 : if (namlen + suflen >= NAMEDATALEN)
2452 tgl@sss.pgh.pa.us 347 :UBC 0 : namlen = pg_mbcliplen(NameStr(*nam), namlen, NAMEDATALEN - 1 - suflen);
348 : :
349 : : /* We use palloc0 here to ensure result is zero-padded */
2452 tgl@sss.pgh.pa.us 350 :CBC 17878 : result = (Name) palloc0(NAMEDATALEN);
351 : 17878 : memcpy(NameStr(*result), NameStr(*nam), namlen);
352 : 17878 : memcpy(NameStr(*result) + namlen, suffix, suflen);
353 : :
354 : 17878 : PG_RETURN_NAME(result);
355 : : }
|