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-2018, 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 namein(PG_FUNCTION_ARGS)
47 {
48 	char	   *s = PG_GETARG_CSTRING(0);
49 	Name		result;
50 	int			len;
51 
52 	len = strlen(s);
53 
54 	/* Truncate oversize input */
55 	if (len >= NAMEDATALEN)
56 		len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
57 
58 	/* We use palloc0 here to ensure result is zero-padded */
59 	result = (Name) palloc0(NAMEDATALEN);
60 	memcpy(NameStr(*result), s, len);
61 
62 	PG_RETURN_NAME(result);
63 }
64 
65 /*
66  *		nameout - converts internal representation to "..."
67  */
68 Datum
69 nameout(PG_FUNCTION_ARGS)
70 {
71 	Name		s = PG_GETARG_NAME(0);
72 
73 	PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
74 }
75 
76 /*
77  *		namerecv			- converts external binary format to name
78  */
79 Datum
80 namerecv(PG_FUNCTION_ARGS)
81 {
82 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
83 	Name		result;
84 	char	   *str;
85 	int			nbytes;
86 
87 	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
88 	if (nbytes >= NAMEDATALEN)
89 		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 	result = (NameData *) palloc0(NAMEDATALEN);
95 	memcpy(result, str, nbytes);
96 	pfree(str);
97 	PG_RETURN_NAME(result);
98 }
99 
100 /*
101  *		namesend			- converts name to binary format
102  */
103 Datum
104 namesend(PG_FUNCTION_ARGS)
105 {
106 	Name		s = PG_GETARG_NAME(0);
107 	StringInfoData buf;
108 
109 	pq_begintypsend(&buf);
110 	pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
111 	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 nameeq(PG_FUNCTION_ARGS)
135 {
136 	Name		arg1 = PG_GETARG_NAME(0);
137 	Name		arg2 = PG_GETARG_NAME(1);
138 
139 	PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) == 0);
140 }
141 
142 Datum
143 namene(PG_FUNCTION_ARGS)
144 {
145 	Name		arg1 = PG_GETARG_NAME(0);
146 	Name		arg2 = PG_GETARG_NAME(1);
147 
148 	PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) != 0);
149 }
150 
151 Datum
152 namelt(PG_FUNCTION_ARGS)
153 {
154 	Name		arg1 = PG_GETARG_NAME(0);
155 	Name		arg2 = PG_GETARG_NAME(1);
156 
157 	PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) < 0);
158 }
159 
160 Datum
161 namele(PG_FUNCTION_ARGS)
162 {
163 	Name		arg1 = PG_GETARG_NAME(0);
164 	Name		arg2 = PG_GETARG_NAME(1);
165 
166 	PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) <= 0);
167 }
168 
169 Datum
170 namegt(PG_FUNCTION_ARGS)
171 {
172 	Name		arg1 = PG_GETARG_NAME(0);
173 	Name		arg2 = PG_GETARG_NAME(1);
174 
175 	PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) > 0);
176 }
177 
178 Datum
179 namege(PG_FUNCTION_ARGS)
180 {
181 	Name		arg1 = PG_GETARG_NAME(0);
182 	Name		arg2 = PG_GETARG_NAME(1);
183 
184 	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 namecpy(Name n1, Name n2)
192 {
193 	if (!n1 || !n2)
194 		return -1;
195 	StrNCpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
196 	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 namestrcpy(Name name, const char *str)
217 {
218 	if (!name || !str)
219 		return -1;
220 	StrNCpy(NameStr(*name), str, NAMEDATALEN);
221 	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 namestrcmp(Name name, const char *str)
248 {
249 	if (!name && !str)
250 		return 0;
251 	if (!name)
252 		return -1;				/* NULL < anything */
253 	if (!str)
254 		return 1;				/* NULL < anything */
255 	return strncmp(NameStr(*name), str, NAMEDATALEN);
256 }
257 
258 
259 /*
260  * SQL-functions CURRENT_USER, SESSION_USER
261  */
262 Datum
263 current_user(PG_FUNCTION_ARGS)
264 {
265 	PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
266 }
267 
268 Datum
269 session_user(PG_FUNCTION_ARGS)
270 {
271 	PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
272 }
273 
274 
275 /*
276  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
277  */
278 Datum
279 current_schema(PG_FUNCTION_ARGS)
280 {
281 	List	   *search_path = fetch_search_path(false);
282 	char	   *nspname;
283 
284 	if (search_path == NIL)
285 		PG_RETURN_NULL();
286 	nspname = get_namespace_name(linitial_oid(search_path));
287 	list_free(search_path);
288 	if (!nspname)
289 		PG_RETURN_NULL();		/* recently-deleted namespace? */
290 	PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
291 }
292 
293 Datum
294 current_schemas(PG_FUNCTION_ARGS)
295 {
296 	List	   *search_path = fetch_search_path(PG_GETARG_BOOL(0));
297 	ListCell   *l;
298 	Datum	   *names;
299 	int			i;
300 	ArrayType  *array;
301 
302 	names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
303 	i = 0;
304 	foreach(l, search_path)
305 	{
306 		char	   *nspname;
307 
308 		nspname = get_namespace_name(lfirst_oid(l));
309 		if (nspname)			/* watch out for deleted namespace */
310 		{
311 			names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
312 			i++;
313 		}
314 	}
315 	list_free(search_path);
316 
317 	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 	PG_RETURN_POINTER(array);
324 }
325