/*------------------------------------------------------------------------- * * name.c * Functions for the built-in type "name". * name replaces char16 and is carefully implemented so that it * is a string of length NAMEDATALEN. DO NOT use hard-coded constants anywhere * always use NAMEDATALEN as the symbolic constant! - jolly 8/21/95 * * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.43 2003/03/10 22:28:18 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "mb/pg_wchar.h" /***************************************************************************** * USER I/O ROUTINES (none) * *****************************************************************************/ /* * namein - converts "..." to internal representation * * Note: * [Old] Currently if strlen(s) < NAMEDATALEN, the extra chars are nulls * Now, always NULL terminated */ Datum namein(PG_FUNCTION_ARGS) { char *s = PG_GETARG_CSTRING(0); NameData *result; int len; char *ermsg; /* verify encoding */ len = strlen(s); if ((ermsg = pg_verifymbstr(s, len))) elog(ERROR, "%s", ermsg); len = pg_mbcliplen(s, len, NAMEDATALEN - 1); result = (NameData *) palloc(NAMEDATALEN); /* always keep it null-padded */ memset(result, 0, NAMEDATALEN); memcpy(NameStr(*result), s, len); PG_RETURN_NAME(result); } /* * nameout - converts internal representation to "..." */ Datum nameout(PG_FUNCTION_ARGS) { Name s = PG_GETARG_NAME(0); PG_RETURN_CSTRING(pstrdup(NameStr(*s))); } /***************************************************************************** * PUBLIC ROUTINES * *****************************************************************************/ /* * nameeq - returns 1 iff arguments are equal * namene - returns 1 iff arguments are not equal * * BUGS: * Assumes that "xy\0\0a" should be equal to "xy\0b". * If not, can do the comparison backwards for efficiency. * * namelt - returns 1 iff a < b * namele - returns 1 iff a <= b * namegt - returns 1 iff a < b * namege - returns 1 iff a <= b * */ Datum nameeq(PG_FUNCTION_ARGS) { Name arg1 = PG_GETARG_NAME(0); Name arg2 = PG_GETARG_NAME(1); PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) == 0); } Datum namene(PG_FUNCTION_ARGS) { Name arg1 = PG_GETARG_NAME(0); Name arg2 = PG_GETARG_NAME(1); PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) != 0); } Datum namelt(PG_FUNCTION_ARGS) { Name arg1 = PG_GETARG_NAME(0); Name arg2 = PG_GETARG_NAME(1); PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) < 0); } Datum namele(PG_FUNCTION_ARGS) { Name arg1 = PG_GETARG_NAME(0); Name arg2 = PG_GETARG_NAME(1); PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) <= 0); } Datum namegt(PG_FUNCTION_ARGS) { Name arg1 = PG_GETARG_NAME(0); Name arg2 = PG_GETARG_NAME(1); PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) > 0); } Datum namege(PG_FUNCTION_ARGS) { Name arg1 = PG_GETARG_NAME(0); Name arg2 = PG_GETARG_NAME(1); PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) >= 0); } /* (see char.c for comparison/operation routines) */ int namecpy(Name n1, Name n2) { if (!n1 || !n2) return -1; strncpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN); return 0; } #ifdef NOT_USED int namecat(Name n1, Name n2) { return namestrcat(n1, NameStr(*n2)); /* n2 can't be any longer * than n1 */ } #endif #ifdef NOT_USED int namecmp(Name n1, Name n2) { return strncmp(NameStr(*n1), NameStr(*n2), NAMEDATALEN); } #endif int namestrcpy(Name name, const char *str) { if (!name || !str) return -1; StrNCpy(NameStr(*name), str, NAMEDATALEN); return 0; } #ifdef NOT_USED int namestrcat(Name name, const char *str) { int i; char *p, *q; if (!name || !str) return -1; for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p) ; for (q = str; i < NAMEDATALEN; ++i, ++p, ++q) { *p = *q; if (!*q) break; } return 0; } #endif int namestrcmp(Name name, const char *str) { if (!name && !str) return 0; if (!name) return -1; /* NULL < anything */ if (!str) return 1; /* NULL < anything */ return strncmp(NameStr(*name), str, NAMEDATALEN); } /* * SQL-functions CURRENT_USER, SESSION_USER */ Datum current_user(PG_FUNCTION_ARGS) { PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId())))); } Datum session_user(PG_FUNCTION_ARGS) { PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId())))); } /* * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS */ Datum current_schema(PG_FUNCTION_ARGS) { List *search_path = fetch_search_path(false); char *nspname; if (search_path == NIL) PG_RETURN_NULL(); nspname = get_namespace_name(lfirsto(search_path)); PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname))); } Datum current_schemas(PG_FUNCTION_ARGS) { List *search_path = fetch_search_path(PG_GETARG_BOOL(0)); int nnames = length(search_path); Datum *names; int i; ArrayType *array; /* +1 here is just to avoid palloc(0) error */ names = (Datum *) palloc((nnames + 1) * sizeof(Datum)); i = 0; while (search_path) { char *nspname; nspname = get_namespace_name(lfirsto(search_path)); names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname)); i++; search_path = lnext(search_path); } array = construct_array(names, nnames, NAMEOID, NAMEDATALEN, /* sizeof(Name) */ false, /* Name is not by-val */ 'i'); /* alignment of Name */ PG_RETURN_POINTER(array); } /***************************************************************************** * PRIVATE ROUTINES * *****************************************************************************/ #ifdef NOT_USED uint32 NameComputeLength(Name name) { char *charP; int length; for (length = 0, charP = NameStr(*name); length < NAMEDATALEN && *charP != '\0'; length++, charP++) ; return (uint32) length; } #endif