1 /*-------------------------------------------------------------------------
4 * Functions for the built-in type "name".
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
12 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
19 *-------------------------------------------------------------------------
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"
33 /*****************************************************************************
34 * USER I/O ROUTINES (none) *
35 *****************************************************************************/
39 * namein - converts "..." to internal representation
42 * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls
43 * Now, always NULL terminated
46 namein(PG_FUNCTION_ARGS
)
48 char *s
= PG_GETARG_CSTRING(0);
53 len
= pg_mbcliplen(s
, len
, NAMEDATALEN
- 1);
55 result
= (NameData
*) palloc0(NAMEDATALEN
);
56 memcpy(NameStr(*result
), s
, len
);
58 PG_RETURN_NAME(result
);
62 * nameout - converts internal representation to "..."
65 nameout(PG_FUNCTION_ARGS
)
67 Name s
= PG_GETARG_NAME(0);
69 PG_RETURN_CSTRING(pstrdup(NameStr(*s
)));
73 * namerecv - converts external binary format to name
76 namerecv(PG_FUNCTION_ARGS
)
78 StringInfo buf
= (StringInfo
) PG_GETARG_POINTER(0);
83 str
= pq_getmsgtext(buf
, buf
->len
- buf
->cursor
, &nbytes
);
84 if (nbytes
>= NAMEDATALEN
)
86 (errcode(ERRCODE_NAME_TOO_LONG
),
87 errmsg("identifier too long"),
88 errdetail("Identifier must be less than %d characters.",
90 result
= (NameData
*) palloc0(NAMEDATALEN
);
91 memcpy(result
, str
, nbytes
);
93 PG_RETURN_NAME(result
);
97 * namesend - converts name to binary format
100 namesend(PG_FUNCTION_ARGS
)
102 Name s
= PG_GETARG_NAME(0);
105 pq_begintypsend(&buf
);
106 pq_sendtext(&buf
, NameStr(*s
), strlen(NameStr(*s
)));
107 PG_RETURN_BYTEA_P(pq_endtypsend(&buf
));
111 /*****************************************************************************
113 *****************************************************************************/
116 * nameeq - returns 1 iff arguments are equal
117 * namene - returns 1 iff arguments are not equal
120 * Assumes that "xy\0\0a" should be equal to "xy\0b".
121 * If not, can do the comparison backwards for efficiency.
123 * namelt - returns 1 iff a < b
124 * namele - returns 1 iff a <= b
125 * namegt - returns 1 iff a > b
126 * namege - returns 1 iff a >= b
130 nameeq(PG_FUNCTION_ARGS
)
132 Name arg1
= PG_GETARG_NAME(0);
133 Name arg2
= PG_GETARG_NAME(1);
135 PG_RETURN_BOOL(strncmp(NameStr(*arg1
), NameStr(*arg2
), NAMEDATALEN
) == 0);
139 namene(PG_FUNCTION_ARGS
)
141 Name arg1
= PG_GETARG_NAME(0);
142 Name arg2
= PG_GETARG_NAME(1);
144 PG_RETURN_BOOL(strncmp(NameStr(*arg1
), NameStr(*arg2
), NAMEDATALEN
) != 0);
148 namelt(PG_FUNCTION_ARGS
)
150 Name arg1
= PG_GETARG_NAME(0);
151 Name arg2
= PG_GETARG_NAME(1);
153 PG_RETURN_BOOL(strncmp(NameStr(*arg1
), NameStr(*arg2
), NAMEDATALEN
) < 0);
157 namele(PG_FUNCTION_ARGS
)
159 Name arg1
= PG_GETARG_NAME(0);
160 Name arg2
= PG_GETARG_NAME(1);
162 PG_RETURN_BOOL(strncmp(NameStr(*arg1
), NameStr(*arg2
), NAMEDATALEN
) <= 0);
166 namegt(PG_FUNCTION_ARGS
)
168 Name arg1
= PG_GETARG_NAME(0);
169 Name arg2
= PG_GETARG_NAME(1);
171 PG_RETURN_BOOL(strncmp(NameStr(*arg1
), NameStr(*arg2
), NAMEDATALEN
) > 0);
175 namege(PG_FUNCTION_ARGS
)
177 Name arg1
= PG_GETARG_NAME(0);
178 Name arg2
= PG_GETARG_NAME(1);
180 PG_RETURN_BOOL(strncmp(NameStr(*arg1
), NameStr(*arg2
), NAMEDATALEN
) >= 0);
184 /* (see char.c for comparison/operation routines) */
187 namecpy(Name n1
, Name n2
)
191 strncpy(NameStr(*n1
), NameStr(*n2
), NAMEDATALEN
);
197 namecat(Name n1
, Name n2
)
199 return namestrcat(n1
, NameStr(*n2
)); /* n2 can't be any longer than
206 namecmp(Name n1
, Name n2
)
208 return strncmp(NameStr(*n1
), NameStr(*n2
), NAMEDATALEN
);
213 namestrcpy(Name name
, const char *str
)
217 StrNCpy(NameStr(*name
), str
, NAMEDATALEN
);
223 namestrcat(Name name
, const char *str
)
231 for (i
= 0, p
= NameStr(*name
); i
< NAMEDATALEN
&& *p
; ++i
, ++p
)
233 for (q
= str
; i
< NAMEDATALEN
; ++i
, ++p
, ++q
)
244 namestrcmp(Name name
, const char *str
)
249 return -1; /* NULL < anything */
251 return 1; /* NULL < anything */
252 return strncmp(NameStr(*name
), str
, NAMEDATALEN
);
257 * SQL-functions CURRENT_USER, SESSION_USER
260 current_user(PG_FUNCTION_ARGS
)
262 PG_RETURN_DATUM(DirectFunctionCall1(namein
, CStringGetDatum(GetUserNameFromId(GetUserId()))));
266 session_user(PG_FUNCTION_ARGS
)
268 PG_RETURN_DATUM(DirectFunctionCall1(namein
, CStringGetDatum(GetUserNameFromId(GetSessionUserId()))));
273 * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
276 current_schema(PG_FUNCTION_ARGS
)
278 List
*search_path
= fetch_search_path(false);
281 if (search_path
== NIL
)
283 nspname
= get_namespace_name(linitial_oid(search_path
));
284 list_free(search_path
);
286 PG_RETURN_NULL(); /* recently-deleted namespace? */
287 PG_RETURN_DATUM(DirectFunctionCall1(namein
, CStringGetDatum(nspname
)));
291 current_schemas(PG_FUNCTION_ARGS
)
293 List
*search_path
= fetch_search_path(PG_GETARG_BOOL(0));
299 names
= (Datum
*) palloc(list_length(search_path
) * sizeof(Datum
));
301 foreach(l
, search_path
)
305 nspname
= get_namespace_name(lfirst_oid(l
));
306 if (nspname
) /* watch out for deleted namespace */
308 names
[i
] = DirectFunctionCall1(namein
, CStringGetDatum(nspname
));
312 list_free(search_path
);
314 array
= construct_array(names
, i
,
316 NAMEDATALEN
, /* sizeof(Name) */
317 false, /* Name is not by-val */
318 'c'); /* alignment of Name */
320 PG_RETURN_POINTER(array
);