LCOV - code coverage report
Current view: top level - src/backend/utils/adt - name.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 105 113 92.9 %
Date: 2024-04-25 11:11:38 Functions: 20 20 100.0 %
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-2024, 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      832538 : namein(PG_FUNCTION_ARGS)
      49             : {
      50      832538 :     char       *s = PG_GETARG_CSTRING(0);
      51             :     Name        result;
      52             :     int         len;
      53             : 
      54      832538 :     len = strlen(s);
      55             : 
      56             :     /* Truncate oversize input */
      57      832538 :     if (len >= NAMEDATALEN)
      58          54 :         len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
      59             : 
      60             :     /* We use palloc0 here to ensure result is zero-padded */
      61      832538 :     result = (Name) palloc0(NAMEDATALEN);
      62      832538 :     memcpy(NameStr(*result), s, len);
      63             : 
      64      832538 :     PG_RETURN_NAME(result);
      65             : }
      66             : 
      67             : /*
      68             :  *      nameout - converts internal representation to cstring
      69             :  */
      70             : Datum
      71     2071226 : nameout(PG_FUNCTION_ARGS)
      72             : {
      73     2071226 :     Name        s = PG_GETARG_NAME(0);
      74             : 
      75     2071226 :     PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
      76             : }
      77             : 
      78             : /*
      79             :  *      namerecv            - converts external binary format to name
      80             :  */
      81             : Datum
      82           6 : namerecv(PG_FUNCTION_ARGS)
      83             : {
      84           6 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      85             :     Name        result;
      86             :     char       *str;
      87             :     int         nbytes;
      88             : 
      89           6 :     str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
      90           6 :     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           6 :     result = (NameData *) palloc0(NAMEDATALEN);
      97           6 :     memcpy(result, str, nbytes);
      98           6 :     pfree(str);
      99           6 :     PG_RETURN_NAME(result);
     100             : }
     101             : 
     102             : /*
     103             :  *      namesend            - converts name to binary format
     104             :  */
     105             : Datum
     106           6 : namesend(PG_FUNCTION_ARGS)
     107             : {
     108           6 :     Name        s = PG_GETARG_NAME(0);
     109             :     StringInfoData buf;
     110             : 
     111           6 :     pq_begintypsend(&buf);
     112           6 :     pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
     113           6 :     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    31767598 : namecmp(Name arg1, Name arg2, Oid collid)
     136             : {
     137             :     /* Fast path for common case used in system catalogs */
     138    31767598 :     if (collid == C_COLLATION_OID)
     139    31767598 :         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    11846056 : nameeq(PG_FUNCTION_ARGS)
     149             : {
     150    11846056 :     Name        arg1 = PG_GETARG_NAME(0);
     151    11846056 :     Name        arg2 = PG_GETARG_NAME(1);
     152             : 
     153    11846056 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
     154             : }
     155             : 
     156             : Datum
     157       50400 : namene(PG_FUNCTION_ARGS)
     158             : {
     159       50400 :     Name        arg1 = PG_GETARG_NAME(0);
     160       50400 :     Name        arg2 = PG_GETARG_NAME(1);
     161             : 
     162       50400 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
     163             : }
     164             : 
     165             : Datum
     166       90670 : namelt(PG_FUNCTION_ARGS)
     167             : {
     168       90670 :     Name        arg1 = PG_GETARG_NAME(0);
     169       90670 :     Name        arg2 = PG_GETARG_NAME(1);
     170             : 
     171       90670 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
     172             : }
     173             : 
     174             : Datum
     175       11460 : namele(PG_FUNCTION_ARGS)
     176             : {
     177       11460 :     Name        arg1 = PG_GETARG_NAME(0);
     178       11460 :     Name        arg2 = PG_GETARG_NAME(1);
     179             : 
     180       11460 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) <= 0);
     181             : }
     182             : 
     183             : Datum
     184        4016 : namegt(PG_FUNCTION_ARGS)
     185             : {
     186        4016 :     Name        arg1 = PG_GETARG_NAME(0);
     187        4016 :     Name        arg2 = PG_GETARG_NAME(1);
     188             : 
     189        4016 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) > 0);
     190             : }
     191             : 
     192             : Datum
     193       14280 : namege(PG_FUNCTION_ARGS)
     194             : {
     195       14280 :     Name        arg1 = PG_GETARG_NAME(0);
     196       14280 :     Name        arg2 = PG_GETARG_NAME(1);
     197             : 
     198       14280 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
     199             : }
     200             : 
     201             : Datum
     202    19750716 : btnamecmp(PG_FUNCTION_ARGS)
     203             : {
     204    19750716 :     Name        arg1 = PG_GETARG_NAME(0);
     205    19750716 :     Name        arg2 = PG_GETARG_NAME(1);
     206             : 
     207    19750716 :     PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
     208             : }
     209             : 
     210             : Datum
     211       35290 : btnamesortsupport(PG_FUNCTION_ARGS)
     212             : {
     213       35290 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     214       35290 :     Oid         collid = ssup->ssup_collation;
     215             :     MemoryContext oldcontext;
     216             : 
     217       35290 :     oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
     218             : 
     219             :     /* Use generic string SortSupport */
     220       35290 :     varstr_sortsupport(ssup, NAMEOID, collid);
     221             : 
     222       35290 :     MemoryContextSwitchTo(oldcontext);
     223             : 
     224       35290 :     PG_RETURN_VOID();
     225             : }
     226             : 
     227             : 
     228             : /*****************************************************************************
     229             :  *   MISCELLANEOUS PUBLIC ROUTINES                                           *
     230             :  *****************************************************************************/
     231             : 
     232             : void
     233     8207000 : namestrcpy(Name name, const char *str)
     234             : {
     235             :     /* NB: We need to zero-pad the destination. */
     236     8207000 :     strncpy(NameStr(*name), str, NAMEDATALEN);
     237     8207000 :     NameStr(*name)[NAMEDATALEN - 1] = '\0';
     238     8207000 : }
     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    10258634 : namestrcmp(Name name, const char *str)
     248             : {
     249    10258634 :     if (!name && !str)
     250           0 :         return 0;
     251    10258634 :     if (!name)
     252           0 :         return -1;              /* NULL < anything */
     253    10258634 :     if (!str)
     254           0 :         return 1;               /* NULL < anything */
     255    10258634 :     return strncmp(NameStr(*name), str, NAMEDATALEN);
     256             : }
     257             : 
     258             : 
     259             : /*
     260             :  * SQL-functions CURRENT_USER, SESSION_USER
     261             :  */
     262             : Datum
     263       16534 : current_user(PG_FUNCTION_ARGS)
     264             : {
     265       16534 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
     266             : }
     267             : 
     268             : Datum
     269         480 : session_user(PG_FUNCTION_ARGS)
     270             : {
     271         480 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
     272             : }
     273             : 
     274             : 
     275             : /*
     276             :  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
     277             :  */
     278             : Datum
     279          34 : current_schema(PG_FUNCTION_ARGS)
     280             : {
     281          34 :     List       *search_path = fetch_search_path(false);
     282             :     char       *nspname;
     283             : 
     284          34 :     if (search_path == NIL)
     285           6 :         PG_RETURN_NULL();
     286          28 :     nspname = get_namespace_name(linitial_oid(search_path));
     287          28 :     list_free(search_path);
     288          28 :     if (!nspname)
     289           0 :         PG_RETURN_NULL();       /* recently-deleted namespace? */
     290          28 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
     291             : }
     292             : 
     293             : Datum
     294         472 : current_schemas(PG_FUNCTION_ARGS)
     295             : {
     296         472 :     List       *search_path = fetch_search_path(PG_GETARG_BOOL(0));
     297             :     ListCell   *l;
     298             :     Datum      *names;
     299             :     int         i;
     300             :     ArrayType  *array;
     301             : 
     302         472 :     names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
     303         472 :     i = 0;
     304         802 :     foreach(l, search_path)
     305             :     {
     306             :         char       *nspname;
     307             : 
     308         330 :         nspname = get_namespace_name(lfirst_oid(l));
     309         330 :         if (nspname)            /* watch out for deleted namespace */
     310             :         {
     311         330 :             names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
     312         330 :             i++;
     313             :         }
     314             :     }
     315         472 :     list_free(search_path);
     316             : 
     317         472 :     array = construct_array_builtin(names, i, NAMEOID);
     318             : 
     319         472 :     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       34880 : nameconcatoid(PG_FUNCTION_ARGS)
     334             : {
     335       34880 :     Name        nam = PG_GETARG_NAME(0);
     336       34880 :     Oid         oid = PG_GETARG_OID(1);
     337             :     Name        result;
     338             :     char        suffix[20];
     339             :     int         suflen;
     340             :     int         namlen;
     341             : 
     342       34880 :     suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
     343       34880 :     namlen = strlen(NameStr(*nam));
     344             : 
     345             :     /* Truncate oversize input by truncating name part, not suffix */
     346       34880 :     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       34880 :     result = (Name) palloc0(NAMEDATALEN);
     351       34880 :     memcpy(NameStr(*result), NameStr(*nam), namlen);
     352       34880 :     memcpy(NameStr(*result) + namlen, suffix, suflen);
     353             : 
     354       34880 :     PG_RETURN_NAME(result);
     355             : }

Generated by: LCOV version 1.14