]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/name.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / utils / adt / name.c
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-2019, 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 "..." 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 namein(PG_FUNCTION_ARGS)
49 {
50         char       *s = PG_GETARG_CSTRING(0);
51         Name            result;
52         int                     len;
53
54         len = strlen(s);
55
56         /* Truncate oversize input */
57         if (len >= NAMEDATALEN)
58                 len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
59
60         /* We use palloc0 here to ensure result is zero-padded */
61         result = (Name) palloc0(NAMEDATALEN);
62         memcpy(NameStr(*result), s, len);
63
64         PG_RETURN_NAME(result);
65 }
66
67 /*
68  *              nameout - converts internal representation to "..."
69  */
70 Datum
71 nameout(PG_FUNCTION_ARGS)
72 {
73         Name            s = PG_GETARG_NAME(0);
74
75         PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
76 }
77
78 /*
79  *              namerecv                        - converts external binary format to name
80  */
81 Datum
82 namerecv(PG_FUNCTION_ARGS)
83 {
84         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
85         Name            result;
86         char       *str;
87         int                     nbytes;
88
89         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
90         if (nbytes >= NAMEDATALEN)
91                 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         result = (NameData *) palloc0(NAMEDATALEN);
97         memcpy(result, str, nbytes);
98         pfree(str);
99         PG_RETURN_NAME(result);
100 }
101
102 /*
103  *              namesend                        - converts name to binary format
104  */
105 Datum
106 namesend(PG_FUNCTION_ARGS)
107 {
108         Name            s = PG_GETARG_NAME(0);
109         StringInfoData buf;
110
111         pq_begintypsend(&buf);
112         pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
113         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 namecmp(Name arg1, Name arg2, Oid collid)
136 {
137         /* Fast path for common case used in system catalogs */
138         if (collid == C_COLLATION_OID)
139                 return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN);
140
141         /* Else rely on the varstr infrastructure */
142         return varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)),
143                                           NameStr(*arg2), strlen(NameStr(*arg2)),
144                                           collid);
145 }
146
147 Datum
148 nameeq(PG_FUNCTION_ARGS)
149 {
150         Name            arg1 = PG_GETARG_NAME(0);
151         Name            arg2 = PG_GETARG_NAME(1);
152
153         PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
154 }
155
156 Datum
157 namene(PG_FUNCTION_ARGS)
158 {
159         Name            arg1 = PG_GETARG_NAME(0);
160         Name            arg2 = PG_GETARG_NAME(1);
161
162         PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
163 }
164
165 Datum
166 namelt(PG_FUNCTION_ARGS)
167 {
168         Name            arg1 = PG_GETARG_NAME(0);
169         Name            arg2 = PG_GETARG_NAME(1);
170
171         PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
172 }
173
174 Datum
175 namele(PG_FUNCTION_ARGS)
176 {
177         Name            arg1 = PG_GETARG_NAME(0);
178         Name            arg2 = PG_GETARG_NAME(1);
179
180         PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
181 }
182
183 Datum
184 namegt(PG_FUNCTION_ARGS)
185 {
186         Name            arg1 = PG_GETARG_NAME(0);
187         Name            arg2 = PG_GETARG_NAME(1);
188
189         PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
190 }
191
192 Datum
193 namege(PG_FUNCTION_ARGS)
194 {
195         Name            arg1 = PG_GETARG_NAME(0);
196         Name            arg2 = PG_GETARG_NAME(1);
197
198         PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
199 }
200
201 Datum
202 btnamecmp(PG_FUNCTION_ARGS)
203 {
204         Name            arg1 = PG_GETARG_NAME(0);
205         Name            arg2 = PG_GETARG_NAME(1);
206
207         PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
208 }
209
210 Datum
211 btnamesortsupport(PG_FUNCTION_ARGS)
212 {
213         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
214         Oid                     collid = ssup->ssup_collation;
215         MemoryContext oldcontext;
216
217         oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
218
219         /* Use generic string SortSupport */
220         varstr_sortsupport(ssup, NAMEOID, collid);
221
222         MemoryContextSwitchTo(oldcontext);
223
224         PG_RETURN_VOID();
225 }
226
227
228 /*****************************************************************************
229  *       MISCELLANEOUS PUBLIC ROUTINES                                                                                   *
230  *****************************************************************************/
231
232 int
233 namecpy(Name n1, const NameData *n2)
234 {
235         if (!n1 || !n2)
236                 return -1;
237         StrNCpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
238         return 0;
239 }
240
241 #ifdef NOT_USED
242 int
243 namecat(Name n1, Name n2)
244 {
245         return namestrcat(n1, NameStr(*n2));    /* n2 can't be any longer than n1 */
246 }
247 #endif
248
249 int
250 namestrcpy(Name name, const char *str)
251 {
252         if (!name || !str)
253                 return -1;
254         StrNCpy(NameStr(*name), str, NAMEDATALEN);
255         return 0;
256 }
257
258 #ifdef NOT_USED
259 int
260 namestrcat(Name name, const char *str)
261 {
262         int                     i;
263         char       *p,
264                            *q;
265
266         if (!name || !str)
267                 return -1;
268         for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p)
269                 ;
270         for (q = str; i < NAMEDATALEN; ++i, ++p, ++q)
271         {
272                 *p = *q;
273                 if (!*q)
274                         break;
275         }
276         return 0;
277 }
278 #endif
279
280 /*
281  * Compare a NAME to a C string
282  *
283  * Assumes C collation always; be careful when using this for
284  * anything but equality checks!
285  */
286 int
287 namestrcmp(Name name, const char *str)
288 {
289         if (!name && !str)
290                 return 0;
291         if (!name)
292                 return -1;                              /* NULL < anything */
293         if (!str)
294                 return 1;                               /* NULL < anything */
295         return strncmp(NameStr(*name), str, NAMEDATALEN);
296 }
297
298
299 /*
300  * SQL-functions CURRENT_USER, SESSION_USER
301  */
302 Datum
303 current_user(PG_FUNCTION_ARGS)
304 {
305         PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
306 }
307
308 Datum
309 session_user(PG_FUNCTION_ARGS)
310 {
311         PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
312 }
313
314
315 /*
316  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
317  */
318 Datum
319 current_schema(PG_FUNCTION_ARGS)
320 {
321         List       *search_path = fetch_search_path(false);
322         char       *nspname;
323
324         if (search_path == NIL)
325                 PG_RETURN_NULL();
326         nspname = get_namespace_name(linitial_oid(search_path));
327         list_free(search_path);
328         if (!nspname)
329                 PG_RETURN_NULL();               /* recently-deleted namespace? */
330         PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
331 }
332
333 Datum
334 current_schemas(PG_FUNCTION_ARGS)
335 {
336         List       *search_path = fetch_search_path(PG_GETARG_BOOL(0));
337         ListCell   *l;
338         Datum      *names;
339         int                     i;
340         ArrayType  *array;
341
342         names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
343         i = 0;
344         foreach(l, search_path)
345         {
346                 char       *nspname;
347
348                 nspname = get_namespace_name(lfirst_oid(l));
349                 if (nspname)                    /* watch out for deleted namespace */
350                 {
351                         names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
352                         i++;
353                 }
354         }
355         list_free(search_path);
356
357         array = construct_array(names, i,
358                                                         NAMEOID,
359                                                         NAMEDATALEN,    /* sizeof(Name) */
360                                                         false,  /* Name is not by-val */
361                                                         'c');   /* alignment of Name */
362
363         PG_RETURN_POINTER(array);
364 }
365
366 /*
367  * SQL-function nameconcatoid(name, oid) returns name
368  *
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).
375  */
376 Datum
377 nameconcatoid(PG_FUNCTION_ARGS)
378 {
379         Name            nam = PG_GETARG_NAME(0);
380         Oid                     oid = PG_GETARG_OID(1);
381         Name            result;
382         char            suffix[20];
383         int                     suflen;
384         int                     namlen;
385
386         suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
387         namlen = strlen(NameStr(*nam));
388
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);
392
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);
397
398         PG_RETURN_NAME(result);
399 }