PostgreSQL Source Code  git master
name.c
Go to the documentation of this file.
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
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
72 {
73  Name s = PG_GETARG_NAME(0);
74 
76 }
77 
78 /*
79  * namerecv - converts external binary format to name
80  */
81 Datum
83 {
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
107 {
108  Name s = PG_GETARG_NAME(0);
110 
111  pq_begintypsend(&buf);
112  pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
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
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
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
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
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
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
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
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
212 {
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
304 {
306 }
307 
308 Datum
310 {
312 }
313 
314 
315 /*
316  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
317  */
318 Datum
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? */
331 }
332 
333 Datum
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
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 }
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define NIL
Definition: pg_list.h:65
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
Datum current_schema(PG_FUNCTION_ARGS)
Definition: name.c:319
Datum namene(PG_FUNCTION_ARGS)
Definition: name.c:157
Oid GetUserId(void)
Definition: miscinit.c:380
int namecpy(Name n1, const NameData *n2)
Definition: name.c:233
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
char * pstrdup(const char *in)
Definition: mcxt.c:1186
StringInfoData * StringInfo
Definition: stringinfo.h:44
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3291
int errcode(int sqlerrcode)
Definition: elog.c:608
int namestrcmp(Name name, const char *str)
Definition: name.c:287
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:250
Datum namege(PG_FUNCTION_ARGS)
Definition: name.c:193
Datum namelt(PG_FUNCTION_ARGS)
Definition: name.c:166
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
Oid GetSessionUserId(void)
Definition: miscinit.c:414
#define PG_GET_COLLATION()
Definition: fmgr.h:193
Datum namesend(PG_FUNCTION_ARGS)
Definition: name.c:106
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1482
Datum btnamecmp(PG_FUNCTION_ARGS)
Definition: name.c:202
Datum btnamesortsupport(PG_FUNCTION_ARGS)
Definition: name.c:211
MemoryContext ssup_cxt
Definition: sortsupport.h:66
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:862
Definition: c.h:610
void varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid)
Definition: varlena.c:1967
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
static char * buf
Definition: pg_test_fsync.c:67
Datum current_user(PG_FUNCTION_ARGS)
Definition: name.c:303
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define CStringGetDatum(X)
Definition: postgres.h:578
Datum current_schemas(PG_FUNCTION_ARGS)
Definition: name.c:334
#define ereport(elevel, rest)
Definition: elog.h:141
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
Datum namegt(PG_FUNCTION_ARGS)
Definition: name.c:184
Datum session_user(PG_FUNCTION_ARGS)
Definition: name.c:309
void * palloc0(Size size)
Definition: mcxt.c:980
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
Datum namerecv(PG_FUNCTION_ARGS)
Definition: name.c:82
static int namecmp(Name arg1, Name arg2, Oid collid)
Definition: name.c:135
#define PG_RETURN_VOID()
Definition: fmgr.h:339
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:795
#define StrNCpy(dst, src, len)
Definition: c.h:935
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352
#define linitial_oid(l)
Definition: pg_list.h:197
static int list_length(const List *l)
Definition: pg_list.h:169
const char * name
Definition: encode.c:521
Datum namele(PG_FUNCTION_ARGS)
Definition: name.c:175
Datum nameconcatoid(PG_FUNCTION_ARGS)
Definition: name.c:377
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
void list_free(List *list)
Definition: list.c:1377
int i
#define NameStr(name)
Definition: c.h:616
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:272
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
Datum nameout(PG_FUNCTION_ARGS)
Definition: name.c:71
NameData * Name
Definition: c.h:614
Definition: pg_list.h:50
#define snprintf
Definition: port.h:192
List * fetch_search_path(bool includeImplicit)
Definition: namespace.c:4305
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_RETURN_NAME(x)
Definition: fmgr.h:353
#define PG_GETARG_NAME(n)
Definition: fmgr.h:273
#define lfirst_oid(lc)
Definition: pg_list.h:192
Datum nameeq(PG_FUNCTION_ARGS)
Definition: name.c:148