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-2017, 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_type.h"
25 : #include "libpq/pqformat.h"
26 : #include "mb/pg_wchar.h"
27 : #include "miscadmin.h"
28 : #include "utils/array.h"
29 : #include "utils/builtins.h"
30 : #include "utils/lsyscache.h"
31 :
32 :
33 : /*****************************************************************************
34 : * USER I/O ROUTINES (none) *
35 : *****************************************************************************/
36 :
37 :
38 : /*
39 : * namein - converts "..." to internal representation
40 : *
41 : * Note:
42 : * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls
43 : * Now, always NULL terminated
44 : */
45 : Datum
46 80940 : namein(PG_FUNCTION_ARGS)
47 : {
48 80940 : char *s = PG_GETARG_CSTRING(0);
49 : Name result;
50 : int len;
51 :
52 80940 : len = strlen(s);
53 :
54 : /* Truncate oversize input */
55 80940 : if (len >= NAMEDATALEN)
56 9 : len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
57 :
58 : /* We use palloc0 here to ensure result is zero-padded */
59 80940 : result = (Name) palloc0(NAMEDATALEN);
60 80940 : memcpy(NameStr(*result), s, len);
61 :
62 80940 : PG_RETURN_NAME(result);
63 : }
64 :
65 : /*
66 : * nameout - converts internal representation to "..."
67 : */
68 : Datum
69 16622 : nameout(PG_FUNCTION_ARGS)
70 : {
71 16622 : Name s = PG_GETARG_NAME(0);
72 :
73 16622 : PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
74 : }
75 :
76 : /*
77 : * namerecv - converts external binary format to name
78 : */
79 : Datum
80 1 : namerecv(PG_FUNCTION_ARGS)
81 : {
82 1 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
83 : Name result;
84 : char *str;
85 : int nbytes;
86 :
87 1 : str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
88 1 : if (nbytes >= NAMEDATALEN)
89 0 : ereport(ERROR,
90 : (errcode(ERRCODE_NAME_TOO_LONG),
91 : errmsg("identifier too long"),
92 : errdetail("Identifier must be less than %d characters.",
93 : NAMEDATALEN)));
94 1 : result = (NameData *) palloc0(NAMEDATALEN);
95 1 : memcpy(result, str, nbytes);
96 1 : pfree(str);
97 1 : PG_RETURN_NAME(result);
98 : }
99 :
100 : /*
101 : * namesend - converts name to binary format
102 : */
103 : Datum
104 1 : namesend(PG_FUNCTION_ARGS)
105 : {
106 1 : Name s = PG_GETARG_NAME(0);
107 : StringInfoData buf;
108 :
109 1 : pq_begintypsend(&buf);
110 1 : pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
111 1 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
112 : }
113 :
114 :
115 : /*****************************************************************************
116 : * PUBLIC ROUTINES *
117 : *****************************************************************************/
118 :
119 : /*
120 : * nameeq - returns 1 iff arguments are equal
121 : * namene - returns 1 iff arguments are not equal
122 : *
123 : * BUGS:
124 : * Assumes that "xy\0\0a" should be equal to "xy\0b".
125 : * If not, can do the comparison backwards for efficiency.
126 : *
127 : * namelt - returns 1 iff a < b
128 : * namele - returns 1 iff a <= b
129 : * namegt - returns 1 iff a > b
130 : * namege - returns 1 iff a >= b
131 : *
132 : */
133 : Datum
134 328031 : nameeq(PG_FUNCTION_ARGS)
135 : {
136 328031 : Name arg1 = PG_GETARG_NAME(0);
137 328031 : Name arg2 = PG_GETARG_NAME(1);
138 :
139 328031 : PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) == 0);
140 : }
141 :
142 : Datum
143 830 : namene(PG_FUNCTION_ARGS)
144 : {
145 830 : Name arg1 = PG_GETARG_NAME(0);
146 830 : Name arg2 = PG_GETARG_NAME(1);
147 :
148 830 : PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) != 0);
149 : }
150 :
151 : Datum
152 22231 : namelt(PG_FUNCTION_ARGS)
153 : {
154 22231 : Name arg1 = PG_GETARG_NAME(0);
155 22231 : Name arg2 = PG_GETARG_NAME(1);
156 :
157 22231 : PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) < 0);
158 : }
159 :
160 : Datum
161 1798 : namele(PG_FUNCTION_ARGS)
162 : {
163 1798 : Name arg1 = PG_GETARG_NAME(0);
164 1798 : Name arg2 = PG_GETARG_NAME(1);
165 :
166 1798 : PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) <= 0);
167 : }
168 :
169 : Datum
170 527 : namegt(PG_FUNCTION_ARGS)
171 : {
172 527 : Name arg1 = PG_GETARG_NAME(0);
173 527 : Name arg2 = PG_GETARG_NAME(1);
174 :
175 527 : PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) > 0);
176 : }
177 :
178 : Datum
179 8627 : namege(PG_FUNCTION_ARGS)
180 : {
181 8627 : Name arg1 = PG_GETARG_NAME(0);
182 8627 : Name arg2 = PG_GETARG_NAME(1);
183 :
184 8627 : PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) >= 0);
185 : }
186 :
187 :
188 : /* (see char.c for comparison/operation routines) */
189 :
190 : int
191 0 : namecpy(Name n1, Name n2)
192 : {
193 0 : if (!n1 || !n2)
194 0 : return -1;
195 0 : StrNCpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
196 0 : return 0;
197 : }
198 :
199 : #ifdef NOT_USED
200 : int
201 : namecat(Name n1, Name n2)
202 : {
203 : return namestrcat(n1, NameStr(*n2)); /* n2 can't be any longer than n1 */
204 : }
205 : #endif
206 :
207 : #ifdef NOT_USED
208 : int
209 : namecmp(Name n1, Name n2)
210 : {
211 : return strncmp(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
212 : }
213 : #endif
214 :
215 : int
216 153882 : namestrcpy(Name name, const char *str)
217 : {
218 153882 : if (!name || !str)
219 0 : return -1;
220 153882 : StrNCpy(NameStr(*name), str, NAMEDATALEN);
221 153882 : return 0;
222 : }
223 :
224 : #ifdef NOT_USED
225 : int
226 : namestrcat(Name name, const char *str)
227 : {
228 : int i;
229 : char *p,
230 : *q;
231 :
232 : if (!name || !str)
233 : return -1;
234 : for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p)
235 : ;
236 : for (q = str; i < NAMEDATALEN; ++i, ++p, ++q)
237 : {
238 : *p = *q;
239 : if (!*q)
240 : break;
241 : }
242 : return 0;
243 : }
244 : #endif
245 :
246 : int
247 31008 : namestrcmp(Name name, const char *str)
248 : {
249 31008 : if (!name && !str)
250 0 : return 0;
251 31008 : if (!name)
252 0 : return -1; /* NULL < anything */
253 31008 : if (!str)
254 0 : return 1; /* NULL < anything */
255 31008 : return strncmp(NameStr(*name), str, NAMEDATALEN);
256 : }
257 :
258 :
259 : /*
260 : * SQL-functions CURRENT_USER, SESSION_USER
261 : */
262 : Datum
263 813 : current_user(PG_FUNCTION_ARGS)
264 : {
265 813 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
266 : }
267 :
268 : Datum
269 25 : session_user(PG_FUNCTION_ARGS)
270 : {
271 25 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
272 : }
273 :
274 :
275 : /*
276 : * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
277 : */
278 : Datum
279 3 : current_schema(PG_FUNCTION_ARGS)
280 : {
281 3 : List *search_path = fetch_search_path(false);
282 : char *nspname;
283 :
284 3 : if (search_path == NIL)
285 1 : PG_RETURN_NULL();
286 2 : nspname = get_namespace_name(linitial_oid(search_path));
287 2 : list_free(search_path);
288 2 : if (!nspname)
289 0 : PG_RETURN_NULL(); /* recently-deleted namespace? */
290 2 : PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
291 : }
292 :
293 : Datum
294 3 : current_schemas(PG_FUNCTION_ARGS)
295 : {
296 3 : List *search_path = fetch_search_path(PG_GETARG_BOOL(0));
297 : ListCell *l;
298 : Datum *names;
299 : int i;
300 : ArrayType *array;
301 :
302 3 : names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
303 3 : i = 0;
304 7 : foreach(l, search_path)
305 : {
306 : char *nspname;
307 :
308 4 : nspname = get_namespace_name(lfirst_oid(l));
309 4 : if (nspname) /* watch out for deleted namespace */
310 : {
311 4 : names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
312 4 : i++;
313 : }
314 : }
315 3 : list_free(search_path);
316 :
317 3 : array = construct_array(names, i,
318 : NAMEOID,
319 : NAMEDATALEN, /* sizeof(Name) */
320 : false, /* Name is not by-val */
321 : 'c'); /* alignment of Name */
322 :
323 3 : PG_RETURN_POINTER(array);
324 : }
|