LCOV - code coverage report
Current view: top level - src/backend/utils/adt - name.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 92.9 % 113 105
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 20 20
Legend: Lines:     hit not hit

            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-2026, 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 cstring 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
      48       500154 : namein(PG_FUNCTION_ARGS)
      49              : {
      50       500154 :     char       *s = PG_GETARG_CSTRING(0);
      51              :     Name        result;
      52              :     int         len;
      53              : 
      54       500154 :     len = strlen(s);
      55              : 
      56              :     /* Truncate oversize input */
      57       500154 :     if (len >= NAMEDATALEN)
      58           27 :         len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
      59              : 
      60              :     /* We use palloc0 here to ensure result is zero-padded */
      61       500154 :     result = (Name) palloc0(NAMEDATALEN);
      62       500154 :     memcpy(NameStr(*result), s, len);
      63              : 
      64       500154 :     PG_RETURN_NAME(result);
      65              : }
      66              : 
      67              : /*
      68              :  *      nameout - converts internal representation to cstring
      69              :  */
      70              : Datum
      71      1278220 : nameout(PG_FUNCTION_ARGS)
      72              : {
      73      1278220 :     Name        s = PG_GETARG_NAME(0);
      74              : 
      75      1278220 :     PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
      76              : }
      77              : 
      78              : /*
      79              :  *      namerecv            - converts external binary format to name
      80              :  */
      81              : Datum
      82            3 : namerecv(PG_FUNCTION_ARGS)
      83              : {
      84            3 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      85              :     Name        result;
      86              :     char       *str;
      87              :     int         nbytes;
      88              : 
      89            3 :     str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
      90            3 :     if (nbytes >= NAMEDATALEN)
      91            0 :         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            3 :     result = (NameData *) palloc0(NAMEDATALEN);
      97            3 :     memcpy(result, str, nbytes);
      98            3 :     pfree(str);
      99            3 :     PG_RETURN_NAME(result);
     100              : }
     101              : 
     102              : /*
     103              :  *      namesend            - converts name to binary format
     104              :  */
     105              : Datum
     106            3 : namesend(PG_FUNCTION_ARGS)
     107              : {
     108            3 :     Name        s = PG_GETARG_NAME(0);
     109              :     StringInfoData buf;
     110              : 
     111            3 :     pq_begintypsend(&buf);
     112            3 :     pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
     113            3 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     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     19972602 : namecmp(Name arg1, Name arg2, Oid collid)
     136              : {
     137              :     /* Fast path for common case used in system catalogs */
     138     19972602 :     if (collid == C_COLLATION_OID)
     139     19972602 :         return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN);
     140              : 
     141              :     /* Else rely on the varstr infrastructure */
     142            0 :     return varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)),
     143            0 :                       NameStr(*arg2), strlen(NameStr(*arg2)),
     144              :                       collid);
     145              : }
     146              : 
     147              : Datum
     148      7600012 : nameeq(PG_FUNCTION_ARGS)
     149              : {
     150      7600012 :     Name        arg1 = PG_GETARG_NAME(0);
     151      7600012 :     Name        arg2 = PG_GETARG_NAME(1);
     152              : 
     153      7600012 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
     154              : }
     155              : 
     156              : Datum
     157        24821 : namene(PG_FUNCTION_ARGS)
     158              : {
     159        24821 :     Name        arg1 = PG_GETARG_NAME(0);
     160        24821 :     Name        arg2 = PG_GETARG_NAME(1);
     161              : 
     162        24821 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
     163              : }
     164              : 
     165              : Datum
     166        51995 : namelt(PG_FUNCTION_ARGS)
     167              : {
     168        51995 :     Name        arg1 = PG_GETARG_NAME(0);
     169        51995 :     Name        arg2 = PG_GETARG_NAME(1);
     170              : 
     171        51995 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
     172              : }
     173              : 
     174              : Datum
     175         7695 : namele(PG_FUNCTION_ARGS)
     176              : {
     177         7695 :     Name        arg1 = PG_GETARG_NAME(0);
     178         7695 :     Name        arg2 = PG_GETARG_NAME(1);
     179              : 
     180         7695 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
     181              : }
     182              : 
     183              : Datum
     184         3934 : namegt(PG_FUNCTION_ARGS)
     185              : {
     186         3934 :     Name        arg1 = PG_GETARG_NAME(0);
     187         3934 :     Name        arg2 = PG_GETARG_NAME(1);
     188              : 
     189         3934 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
     190              : }
     191              : 
     192              : Datum
     193         9072 : namege(PG_FUNCTION_ARGS)
     194              : {
     195         9072 :     Name        arg1 = PG_GETARG_NAME(0);
     196         9072 :     Name        arg2 = PG_GETARG_NAME(1);
     197              : 
     198         9072 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
     199              : }
     200              : 
     201              : Datum
     202     12275073 : btnamecmp(PG_FUNCTION_ARGS)
     203              : {
     204     12275073 :     Name        arg1 = PG_GETARG_NAME(0);
     205     12275073 :     Name        arg2 = PG_GETARG_NAME(1);
     206              : 
     207     12275073 :     PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
     208              : }
     209              : 
     210              : Datum
     211        25216 : btnamesortsupport(PG_FUNCTION_ARGS)
     212              : {
     213        25216 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     214        25216 :     Oid         collid = ssup->ssup_collation;
     215              :     MemoryContext oldcontext;
     216              : 
     217        25216 :     oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
     218              : 
     219              :     /* Use generic string SortSupport */
     220        25216 :     varstr_sortsupport(ssup, NAMEOID, collid);
     221              : 
     222        25216 :     MemoryContextSwitchTo(oldcontext);
     223              : 
     224        25216 :     PG_RETURN_VOID();
     225              : }
     226              : 
     227              : 
     228              : /*****************************************************************************
     229              :  *   MISCELLANEOUS PUBLIC ROUTINES                                           *
     230              :  *****************************************************************************/
     231              : 
     232              : void
     233      5845903 : namestrcpy(Name name, const char *str)
     234              : {
     235              :     /* NB: We need to zero-pad the destination. */
     236      5845903 :     strncpy(NameStr(*name), str, NAMEDATALEN);
     237      5845903 :     NameStr(*name)[NAMEDATALEN - 1] = '\0';
     238      5845903 : }
     239              : 
     240              : /*
     241              :  * Compare a NAME to a C string
     242              :  *
     243              :  * Assumes C collation always; be careful when using this for
     244              :  * anything but equality checks!
     245              :  */
     246              : int
     247      5185190 : namestrcmp(Name name, const char *str)
     248              : {
     249      5185190 :     if (!name && !str)
     250            0 :         return 0;
     251      5185190 :     if (!name)
     252            0 :         return -1;              /* NULL < anything */
     253      5185190 :     if (!str)
     254            0 :         return 1;               /* NULL < anything */
     255      5185190 :     return strncmp(NameStr(*name), str, NAMEDATALEN);
     256              : }
     257              : 
     258              : 
     259              : /*
     260              :  * SQL-functions CURRENT_USER, SESSION_USER
     261              :  */
     262              : Datum
     263         9180 : current_user(PG_FUNCTION_ARGS)
     264              : {
     265         9180 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
     266              : }
     267              : 
     268              : Datum
     269          305 : session_user(PG_FUNCTION_ARGS)
     270              : {
     271          305 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
     272              : }
     273              : 
     274              : 
     275              : /*
     276              :  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
     277              :  */
     278              : Datum
     279           17 : current_schema(PG_FUNCTION_ARGS)
     280              : {
     281           17 :     List       *search_path = fetch_search_path(false);
     282              :     char       *nspname;
     283              : 
     284           17 :     if (search_path == NIL)
     285            3 :         PG_RETURN_NULL();
     286           14 :     nspname = get_namespace_name(linitial_oid(search_path));
     287           14 :     list_free(search_path);
     288           14 :     if (!nspname)
     289            0 :         PG_RETURN_NULL();       /* recently-deleted namespace? */
     290           14 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
     291              : }
     292              : 
     293              : Datum
     294          271 : current_schemas(PG_FUNCTION_ARGS)
     295              : {
     296          271 :     List       *search_path = fetch_search_path(PG_GETARG_BOOL(0));
     297              :     ListCell   *l;
     298              :     Datum      *names;
     299              :     int         i;
     300              :     ArrayType  *array;
     301              : 
     302          271 :     names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
     303          271 :     i = 0;
     304          436 :     foreach(l, search_path)
     305              :     {
     306              :         char       *nspname;
     307              : 
     308          165 :         nspname = get_namespace_name(lfirst_oid(l));
     309          165 :         if (nspname)            /* watch out for deleted namespace */
     310              :         {
     311          165 :             names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
     312          165 :             i++;
     313              :         }
     314              :     }
     315          271 :     list_free(search_path);
     316              : 
     317          271 :     array = construct_array_builtin(names, i, NAMEOID);
     318              : 
     319          271 :     PG_RETURN_POINTER(array);
     320              : }
     321              : 
     322              : /*
     323              :  * SQL-function nameconcatoid(name, oid) returns name
     324              :  *
     325              :  * This is used in the information_schema to produce specific_name columns,
     326              :  * which are supposed to be unique per schema.  We achieve that (in an ugly
     327              :  * way) by appending the object's OID.  The result is the same as
     328              :  *      ($1::text || '_' || $2::text)::name
     329              :  * except that, if it would not fit in NAMEDATALEN, we make it do so by
     330              :  * truncating the name input (not the oid).
     331              :  */
     332              : Datum
     333        18042 : nameconcatoid(PG_FUNCTION_ARGS)
     334              : {
     335        18042 :     Name        nam = PG_GETARG_NAME(0);
     336        18042 :     Oid         oid = PG_GETARG_OID(1);
     337              :     Name        result;
     338              :     char        suffix[20];
     339              :     int         suflen;
     340              :     int         namlen;
     341              : 
     342        18042 :     suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
     343        18042 :     namlen = strlen(NameStr(*nam));
     344              : 
     345              :     /* Truncate oversize input by truncating name part, not suffix */
     346        18042 :     if (namlen + suflen >= NAMEDATALEN)
     347            0 :         namlen = pg_mbcliplen(NameStr(*nam), namlen, NAMEDATALEN - 1 - suflen);
     348              : 
     349              :     /* We use palloc0 here to ensure result is zero-padded */
     350        18042 :     result = (Name) palloc0(NAMEDATALEN);
     351        18042 :     memcpy(NameStr(*result), NameStr(*nam), namlen);
     352        18042 :     memcpy(NameStr(*result) + namlen, suffix, suflen);
     353              : 
     354        18042 :     PG_RETURN_NAME(result);
     355              : }
        

Generated by: LCOV version 2.0-1