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
48 893024 : namein(PG_FUNCTION_ARGS)
49 : {
50 893024 : char *s = PG_GETARG_CSTRING(0);
51 : Name result;
52 : int len;
53 :
54 893024 : len = strlen(s);
55 :
56 : /* Truncate oversize input */
57 893024 : if (len >= NAMEDATALEN)
58 54 : len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
59 :
60 : /* We use palloc0 here to ensure result is zero-padded */
61 893024 : result = (Name) palloc0(NAMEDATALEN);
62 893024 : memcpy(NameStr(*result), s, len);
63 :
64 893024 : PG_RETURN_NAME(result);
65 : }
66 :
67 : /*
68 : * nameout - converts internal representation to cstring
69 : */
70 : Datum
71 2225122 : nameout(PG_FUNCTION_ARGS)
72 : {
73 2225122 : Name s = PG_GETARG_NAME(0);
74 :
75 2225122 : PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
76 : }
77 :
78 : /*
79 : * namerecv - converts external binary format to name
80 : */
81 : Datum
82 6 : namerecv(PG_FUNCTION_ARGS)
83 : {
84 6 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
85 : Name result;
86 : char *str;
87 : int nbytes;
88 :
89 6 : str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
90 6 : if (nbytes >= NAMEDATALEN)
91 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)));
96 6 : result = (NameData *) palloc0(NAMEDATALEN);
97 6 : memcpy(result, str, nbytes);
98 6 : pfree(str);
99 6 : PG_RETURN_NAME(result);
100 : }
101 :
102 : /*
103 : * namesend - converts name to binary format
104 : */
105 : Datum
106 6 : namesend(PG_FUNCTION_ARGS)
107 : {
108 6 : Name s = PG_GETARG_NAME(0);
109 : StringInfoData buf;
110 :
111 6 : pq_begintypsend(&buf);
112 6 : pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
113 6 : 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
135 34611368 : namecmp(Name arg1, Name arg2, Oid collid)
136 : {
137 : /* Fast path for common case used in system catalogs */
138 34611368 : if (collid == C_COLLATION_OID)
139 34611368 : return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN);
140 :
141 : /* Else rely on the varstr infrastructure */
142 0 : return varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)),
143 0 : NameStr(*arg2), strlen(NameStr(*arg2)),
144 : collid);
145 : }
146 :
147 : Datum
148 13104078 : nameeq(PG_FUNCTION_ARGS)
149 : {
150 13104078 : Name arg1 = PG_GETARG_NAME(0);
151 13104078 : Name arg2 = PG_GETARG_NAME(1);
152 :
153 13104078 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
154 : }
155 :
156 : Datum
157 45284 : namene(PG_FUNCTION_ARGS)
158 : {
159 45284 : Name arg1 = PG_GETARG_NAME(0);
160 45284 : Name arg2 = PG_GETARG_NAME(1);
161 :
162 45284 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
163 : }
164 :
165 : Datum
166 98214 : namelt(PG_FUNCTION_ARGS)
167 : {
168 98214 : Name arg1 = PG_GETARG_NAME(0);
169 98214 : Name arg2 = PG_GETARG_NAME(1);
170 :
171 98214 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
172 : }
173 :
174 : Datum
175 11460 : namele(PG_FUNCTION_ARGS)
176 : {
177 11460 : Name arg1 = PG_GETARG_NAME(0);
178 11460 : Name arg2 = PG_GETARG_NAME(1);
179 :
180 11460 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
181 : }
182 :
183 : Datum
184 4016 : namegt(PG_FUNCTION_ARGS)
185 : {
186 4016 : Name arg1 = PG_GETARG_NAME(0);
187 4016 : Name arg2 = PG_GETARG_NAME(1);
188 :
189 4016 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
190 : }
191 :
192 : Datum
193 14280 : namege(PG_FUNCTION_ARGS)
194 : {
195 14280 : Name arg1 = PG_GETARG_NAME(0);
196 14280 : Name arg2 = PG_GETARG_NAME(1);
197 :
198 14280 : PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
199 : }
200 :
201 : Datum
202 21334036 : btnamecmp(PG_FUNCTION_ARGS)
203 : {
204 21334036 : Name arg1 = PG_GETARG_NAME(0);
205 21334036 : Name arg2 = PG_GETARG_NAME(1);
206 :
207 21334036 : PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
208 : }
209 :
210 : Datum
211 37242 : btnamesortsupport(PG_FUNCTION_ARGS)
212 : {
213 37242 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
214 37242 : Oid collid = ssup->ssup_collation;
215 : MemoryContext oldcontext;
216 :
217 37242 : oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
218 :
219 : /* Use generic string SortSupport */
220 37242 : varstr_sortsupport(ssup, NAMEOID, collid);
221 :
222 37242 : MemoryContextSwitchTo(oldcontext);
223 :
224 37242 : PG_RETURN_VOID();
225 : }
226 :
227 :
228 : /*****************************************************************************
229 : * MISCELLANEOUS PUBLIC ROUTINES *
230 : *****************************************************************************/
231 :
232 : void
233 9062340 : namestrcpy(Name name, const char *str)
234 : {
235 : /* NB: We need to zero-pad the destination. */
236 9062340 : strncpy(NameStr(*name), str, NAMEDATALEN);
237 9062340 : NameStr(*name)[NAMEDATALEN - 1] = '\0';
238 9062340 : }
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
247 10304942 : namestrcmp(Name name, const char *str)
248 : {
249 10304942 : if (!name && !str)
250 0 : return 0;
251 10304942 : if (!name)
252 0 : return -1; /* NULL < anything */
253 10304942 : if (!str)
254 0 : return 1; /* NULL < anything */
255 10304942 : return strncmp(NameStr(*name), str, NAMEDATALEN);
256 : }
257 :
258 :
259 : /*
260 : * SQL-functions CURRENT_USER, SESSION_USER
261 : */
262 : Datum
263 17786 : current_user(PG_FUNCTION_ARGS)
264 : {
265 17786 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
266 : }
267 :
268 : Datum
269 562 : session_user(PG_FUNCTION_ARGS)
270 : {
271 562 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
272 : }
273 :
274 :
275 : /*
276 : * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
277 : */
278 : Datum
279 34 : current_schema(PG_FUNCTION_ARGS)
280 : {
281 34 : List *search_path = fetch_search_path(false);
282 : char *nspname;
283 :
284 34 : if (search_path == NIL)
285 6 : PG_RETURN_NULL();
286 28 : nspname = get_namespace_name(linitial_oid(search_path));
287 28 : list_free(search_path);
288 28 : if (!nspname)
289 0 : PG_RETURN_NULL(); /* recently-deleted namespace? */
290 28 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
291 : }
292 :
293 : Datum
294 476 : current_schemas(PG_FUNCTION_ARGS)
295 : {
296 476 : List *search_path = fetch_search_path(PG_GETARG_BOOL(0));
297 : ListCell *l;
298 : Datum *names;
299 : int i;
300 : ArrayType *array;
301 :
302 476 : names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
303 476 : i = 0;
304 806 : foreach(l, search_path)
305 : {
306 : char *nspname;
307 :
308 330 : nspname = get_namespace_name(lfirst_oid(l));
309 330 : if (nspname) /* watch out for deleted namespace */
310 : {
311 330 : names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
312 330 : i++;
313 : }
314 : }
315 476 : list_free(search_path);
316 :
317 476 : array = construct_array_builtin(names, i, NAMEOID);
318 :
319 476 : 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
333 35236 : nameconcatoid(PG_FUNCTION_ARGS)
334 : {
335 35236 : Name nam = PG_GETARG_NAME(0);
336 35236 : Oid oid = PG_GETARG_OID(1);
337 : Name result;
338 : char suffix[20];
339 : int suflen;
340 : int namlen;
341 :
342 35236 : suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
343 35236 : namlen = strlen(NameStr(*nam));
344 :
345 : /* Truncate oversize input by truncating name part, not suffix */
346 35236 : if (namlen + suflen >= NAMEDATALEN)
347 0 : namlen = pg_mbcliplen(NameStr(*nam), namlen, NAMEDATALEN - 1 - suflen);
348 :
349 : /* We use palloc0 here to ensure result is zero-padded */
350 35236 : result = (Name) palloc0(NAMEDATALEN);
351 35236 : memcpy(NameStr(*result), NameStr(*nam), namlen);
352 35236 : memcpy(NameStr(*result) + namlen, suffix, suflen);
353 :
354 35236 : PG_RETURN_NAME(result);
355 : }
|