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

Generated by: LCOV version 1.13