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-2024, 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
8655 tgl@sss.pgh.pa.us 48 :CBC 410487 : namein(PG_FUNCTION_ARGS)
49 : : {
50 : 410487 : char *s = PG_GETARG_CSTRING(0);
51 : : Name result;
52 : : int len;
53 : :
7976 ishii@postgresql.org 54 : 410487 : len = strlen(s);
55 : :
56 : : /* Truncate oversize input */
4342 tgl@sss.pgh.pa.us 57 [ + + ]: 410487 : 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 : 410487 : result = (Name) palloc0(NAMEDATALEN);
7976 ishii@postgresql.org 62 : 410487 : memcpy(NameStr(*result), s, len);
63 : :
8655 tgl@sss.pgh.pa.us 64 : 410487 : PG_RETURN_NAME(result);
65 : : }
66 : :
67 : : /*
68 : : * nameout - converts internal representation to cstring
69 : : */
70 : : Datum
71 : 1146000 : nameout(PG_FUNCTION_ARGS)
72 : : {
73 : 1146000 : Name s = PG_GETARG_NAME(0);
74 : :
75 : 1146000 : PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
76 : : }
77 : :
78 : : /*
79 : : * namerecv - converts external binary format to name
80 : : */
81 : : Datum
7646 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)
7567 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)));
7646 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
1850 peter@eisentraut.org 135 : 17862578 : namecmp(Name arg1, Name arg2, Oid collid)
136 : : {
137 : : /* Fast path for common case used in system catalogs */
138 [ + - ]: 17862578 : if (collid == C_COLLATION_OID)
139 : 17862578 : return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN);
140 : :
141 : : /* Else rely on the varstr infrastructure */
1850 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
8655 tgl@sss.pgh.pa.us 148 :CBC 6469874 : nameeq(PG_FUNCTION_ARGS)
149 : : {
150 : 6469874 : Name arg1 = PG_GETARG_NAME(0);
151 : 6469874 : Name arg2 = PG_GETARG_NAME(1);
152 : :
1850 peter@eisentraut.org 153 : 6469874 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
154 : : }
155 : :
156 : : Datum
8655 tgl@sss.pgh.pa.us 157 : 26456 : namene(PG_FUNCTION_ARGS)
158 : : {
159 : 26456 : Name arg1 = PG_GETARG_NAME(0);
160 : 26456 : Name arg2 = PG_GETARG_NAME(1);
161 : :
1850 peter@eisentraut.org 162 : 26456 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
163 : : }
164 : :
165 : : Datum
8655 tgl@sss.pgh.pa.us 166 : 45618 : namelt(PG_FUNCTION_ARGS)
167 : : {
168 : 45618 : Name arg1 = PG_GETARG_NAME(0);
169 : 45618 : Name arg2 = PG_GETARG_NAME(1);
170 : :
1943 171 : 45618 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
172 : : }
173 : :
174 : : Datum
8655 175 : 5763 : namele(PG_FUNCTION_ARGS)
176 : : {
177 : 5763 : Name arg1 = PG_GETARG_NAME(0);
178 : 5763 : Name arg2 = PG_GETARG_NAME(1);
179 : :
1943 180 : 5763 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
181 : : }
182 : :
183 : : Datum
8655 184 : 2008 : namegt(PG_FUNCTION_ARGS)
185 : : {
186 : 2008 : Name arg1 = PG_GETARG_NAME(0);
187 : 2008 : Name arg2 = PG_GETARG_NAME(1);
188 : :
1943 189 : 2008 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
190 : : }
191 : :
192 : : Datum
8655 193 : 7140 : namege(PG_FUNCTION_ARGS)
194 : : {
195 : 7140 : Name arg1 = PG_GETARG_NAME(0);
196 : 7140 : Name arg2 = PG_GETARG_NAME(1);
197 : :
1943 198 : 7140 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
199 : : }
200 : :
201 : : Datum
202 : 11305719 : btnamecmp(PG_FUNCTION_ARGS)
203 : : {
204 : 11305719 : Name arg1 = PG_GETARG_NAME(0);
205 : 11305719 : Name arg2 = PG_GETARG_NAME(1);
206 : :
207 : 11305719 : PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
208 : : }
209 : :
210 : : Datum
211 : 17443 : btnamesortsupport(PG_FUNCTION_ARGS)
212 : : {
213 : 17443 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
214 : 17443 : Oid collid = ssup->ssup_collation;
215 : : MemoryContext oldcontext;
216 : :
217 : 17443 : oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
218 : :
219 : : /* Use generic string SortSupport */
220 : 17443 : varstr_sortsupport(ssup, NAMEOID, collid);
221 : :
222 : 17443 : MemoryContextSwitchTo(oldcontext);
223 : :
224 : 17443 : PG_RETURN_VOID();
225 : : }
226 : :
227 : :
228 : : /*****************************************************************************
229 : : * MISCELLANEOUS PUBLIC ROUTINES *
230 : : *****************************************************************************/
231 : :
232 : : void
8849 peter_e@gmx.net 233 : 4464194 : namestrcpy(Name name, const char *str)
234 : : {
235 : : /* NB: We need to zero-pad the destination. */
1343 peter@eisentraut.org 236 : 4464194 : strncpy(NameStr(*name), str, NAMEDATALEN);
1068 tgl@sss.pgh.pa.us 237 : 4464194 : NameStr(*name)[NAMEDATALEN - 1] = '\0';
10141 scrappy@hub.org 238 : 4464194 : }
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
8849 peter_e@gmx.net 247 : 5128569 : namestrcmp(Name name, const char *str)
248 : : {
9716 bruce@momjian.us 249 [ - + - - ]: 5128569 : if (!name && !str)
9357 bruce@momjian.us 250 :UBC 0 : return 0;
9716 bruce@momjian.us 251 [ - + ]:CBC 5128569 : if (!name)
9357 bruce@momjian.us 252 :UBC 0 : return -1; /* NULL < anything */
9716 bruce@momjian.us 253 [ - + ]:CBC 5128569 : if (!str)
9357 bruce@momjian.us 254 :UBC 0 : return 1; /* NULL < anything */
8925 bruce@momjian.us 255 :CBC 5128569 : return strncmp(NameStr(*name), str, NAMEDATALEN);
256 : : }
257 : :
258 : :
259 : : /*
260 : : * SQL-functions CURRENT_USER, SESSION_USER
261 : : */
262 : : Datum
8608 peter_e@gmx.net 263 : 8339 : current_user(PG_FUNCTION_ARGS)
264 : : {
3263 andrew@dunslane.net 265 : 8339 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
266 : : }
267 : :
268 : : Datum
8608 peter_e@gmx.net 269 : 252 : session_user(PG_FUNCTION_ARGS)
270 : : {
3263 andrew@dunslane.net 271 : 252 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
272 : : }
273 : :
274 : :
275 : : /*
276 : : * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
277 : : */
278 : : Datum
8024 tgl@sss.pgh.pa.us 279 : 17 : current_schema(PG_FUNCTION_ARGS)
280 : : {
7893 bruce@momjian.us 281 : 17 : List *search_path = fetch_search_path(false);
282 : : char *nspname;
283 : :
8024 tgl@sss.pgh.pa.us 284 [ + + ]: 17 : if (search_path == NIL)
285 : 3 : PG_RETURN_NULL();
7263 neilc@samurai.com 286 : 14 : nspname = get_namespace_name(linitial_oid(search_path));
287 : 14 : list_free(search_path);
7658 tgl@sss.pgh.pa.us 288 [ - + ]: 14 : if (!nspname)
7658 tgl@sss.pgh.pa.us 289 :UBC 0 : PG_RETURN_NULL(); /* recently-deleted namespace? */
8024 tgl@sss.pgh.pa.us 290 :CBC 14 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
291 : : }
292 : :
293 : : Datum
294 : 238 : current_schemas(PG_FUNCTION_ARGS)
295 : : {
7893 bruce@momjian.us 296 : 238 : List *search_path = fetch_search_path(PG_GETARG_BOOL(0));
297 : : ListCell *l;
298 : : Datum *names;
299 : : int i;
300 : : ArrayType *array;
301 : :
7253 tgl@sss.pgh.pa.us 302 : 238 : names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
8024 303 : 238 : i = 0;
7263 neilc@samurai.com 304 [ + + + + : 403 : foreach(l, search_path)
+ + ]
305 : : {
306 : : char *nspname;
307 : :
308 : 165 : nspname = get_namespace_name(lfirst_oid(l));
7658 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 : : }
7263 neilc@samurai.com 315 : 238 : list_free(search_path);
316 : :
653 peter@eisentraut.org 317 : 238 : array = construct_array_builtin(names, i, NAMEOID);
318 : :
8024 tgl@sss.pgh.pa.us 319 : 238 : 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
1942 333 : 17429 : nameconcatoid(PG_FUNCTION_ARGS)
334 : : {
335 : 17429 : Name nam = PG_GETARG_NAME(0);
336 : 17429 : Oid oid = PG_GETARG_OID(1);
337 : : Name result;
338 : : char suffix[20];
339 : : int suflen;
340 : : int namlen;
341 : :
342 : 17429 : suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
343 : 17429 : namlen = strlen(NameStr(*nam));
344 : :
345 : : /* Truncate oversize input by truncating name part, not suffix */
346 [ - + ]: 17429 : if (namlen + suflen >= NAMEDATALEN)
1942 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 */
1942 tgl@sss.pgh.pa.us 350 :CBC 17429 : result = (Name) palloc0(NAMEDATALEN);
351 : 17429 : memcpy(NameStr(*result), NameStr(*nam), namlen);
352 : 17429 : memcpy(NameStr(*result) + namlen, suffix, suflen);
353 : :
354 : 17429 : PG_RETURN_NAME(result);
355 : : }
|