LCOV - code coverage report
Current view: top level - src/backend/utils/adt - name.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 109 119 91.6 %
Date: 2019-06-18 07:06:57 Functions: 21 21 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-2019, 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     2758200 : namein(PG_FUNCTION_ARGS)
      49             : {
      50     2758200 :     char       *s = PG_GETARG_CSTRING(0);
      51             :     Name        result;
      52             :     int         len;
      53             : 
      54     2758200 :     len = strlen(s);
      55             : 
      56             :     /* Truncate oversize input */
      57     2758200 :     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     2758200 :     result = (Name) palloc0(NAMEDATALEN);
      62     2758200 :     memcpy(NameStr(*result), s, len);
      63             : 
      64     2758200 :     PG_RETURN_NAME(result);
      65             : }
      66             : 
      67             : /*
      68             :  *      nameout - converts internal representation to "..."
      69             :  */
      70             : Datum
      71     1213172 : nameout(PG_FUNCTION_ARGS)
      72             : {
      73     1213172 :     Name        s = PG_GETARG_NAME(0);
      74             : 
      75     1213172 :     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    39369188 : namecmp(Name arg1, Name arg2, Oid collid)
     136             : {
     137             :     /* Fast path for common case used in system catalogs */
     138    39369188 :     if (collid == C_COLLATION_OID)
     139    39369188 :         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    26450386 : nameeq(PG_FUNCTION_ARGS)
     149             : {
     150    26450386 :     Name        arg1 = PG_GETARG_NAME(0);
     151    26450386 :     Name        arg2 = PG_GETARG_NAME(1);
     152             : 
     153    26450386 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) == 0);
     154             : }
     155             : 
     156             : Datum
     157       16768 : namene(PG_FUNCTION_ARGS)
     158             : {
     159       16768 :     Name        arg1 = PG_GETARG_NAME(0);
     160       16768 :     Name        arg2 = PG_GETARG_NAME(1);
     161             : 
     162       16768 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) != 0);
     163             : }
     164             : 
     165             : Datum
     166       80188 : namelt(PG_FUNCTION_ARGS)
     167             : {
     168       80188 :     Name        arg1 = PG_GETARG_NAME(0);
     169       80188 :     Name        arg2 = PG_GETARG_NAME(1);
     170             : 
     171       80188 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) < 0);
     172             : }
     173             : 
     174             : Datum
     175        7384 : namele(PG_FUNCTION_ARGS)
     176             : {
     177        7384 :     Name        arg1 = PG_GETARG_NAME(0);
     178        7384 :     Name        arg2 = PG_GETARG_NAME(1);
     179             : 
     180        7384 :     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       21794 : namege(PG_FUNCTION_ARGS)
     194             : {
     195       21794 :     Name        arg1 = PG_GETARG_NAME(0);
     196       21794 :     Name        arg2 = PG_GETARG_NAME(1);
     197             : 
     198       21794 :     PG_RETURN_BOOL(namecmp(arg1, arg2, PG_GET_COLLATION()) >= 0);
     199             : }
     200             : 
     201             : Datum
     202    12790548 : btnamecmp(PG_FUNCTION_ARGS)
     203             : {
     204    12790548 :     Name        arg1 = PG_GETARG_NAME(0);
     205    12790548 :     Name        arg2 = PG_GETARG_NAME(1);
     206             : 
     207    12790548 :     PG_RETURN_INT32(namecmp(arg1, arg2, PG_GET_COLLATION()));
     208             : }
     209             : 
     210             : Datum
     211       44026 : btnamesortsupport(PG_FUNCTION_ARGS)
     212             : {
     213       44026 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     214       44026 :     Oid         collid = ssup->ssup_collation;
     215             :     MemoryContext oldcontext;
     216             : 
     217       44026 :     oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
     218             : 
     219             :     /* Use generic string SortSupport */
     220       44026 :     varstr_sortsupport(ssup, NAMEOID, collid);
     221             : 
     222       44026 :     MemoryContextSwitchTo(oldcontext);
     223             : 
     224       44026 :     PG_RETURN_VOID();
     225             : }
     226             : 
     227             : 
     228             : /*****************************************************************************
     229             :  *   MISCELLANEOUS PUBLIC ROUTINES                                           *
     230             :  *****************************************************************************/
     231             : 
     232             : int
     233      112480 : namecpy(Name n1, const NameData *n2)
     234             : {
     235      112480 :     if (!n1 || !n2)
     236           0 :         return -1;
     237      112480 :     StrNCpy(NameStr(*n1), NameStr(*n2), NAMEDATALEN);
     238      112480 :     return 0;
     239             : }
     240             : 
     241             : #ifdef NOT_USED
     242             : int
     243             : namecat(Name n1, Name n2)
     244             : {
     245             :     return namestrcat(n1, NameStr(*n2));    /* n2 can't be any longer than n1 */
     246             : }
     247             : #endif
     248             : 
     249             : int
     250     5374366 : namestrcpy(Name name, const char *str)
     251             : {
     252     5374366 :     if (!name || !str)
     253           0 :         return -1;
     254     5374366 :     StrNCpy(NameStr(*name), str, NAMEDATALEN);
     255     5374366 :     return 0;
     256             : }
     257             : 
     258             : #ifdef NOT_USED
     259             : int
     260             : namestrcat(Name name, const char *str)
     261             : {
     262             :     int         i;
     263             :     char       *p,
     264             :                *q;
     265             : 
     266             :     if (!name || !str)
     267             :         return -1;
     268             :     for (i = 0, p = NameStr(*name); i < NAMEDATALEN && *p; ++i, ++p)
     269             :         ;
     270             :     for (q = str; i < NAMEDATALEN; ++i, ++p, ++q)
     271             :     {
     272             :         *p = *q;
     273             :         if (!*q)
     274             :             break;
     275             :     }
     276             :     return 0;
     277             : }
     278             : #endif
     279             : 
     280             : /*
     281             :  * Compare a NAME to a C string
     282             :  *
     283             :  * Assumes C collation always; be careful when using this for
     284             :  * anything but equality checks!
     285             :  */
     286             : int
     287     5211168 : namestrcmp(Name name, const char *str)
     288             : {
     289     5211168 :     if (!name && !str)
     290           0 :         return 0;
     291     5211168 :     if (!name)
     292           0 :         return -1;              /* NULL < anything */
     293     5211168 :     if (!str)
     294           0 :         return 1;               /* NULL < anything */
     295     5211168 :     return strncmp(NameStr(*name), str, NAMEDATALEN);
     296             : }
     297             : 
     298             : 
     299             : /*
     300             :  * SQL-functions CURRENT_USER, SESSION_USER
     301             :  */
     302             : Datum
     303        4110 : current_user(PG_FUNCTION_ARGS)
     304             : {
     305        4110 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
     306             : }
     307             : 
     308             : Datum
     309          88 : session_user(PG_FUNCTION_ARGS)
     310             : {
     311          88 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
     312             : }
     313             : 
     314             : 
     315             : /*
     316             :  * SQL-functions CURRENT_SCHEMA, CURRENT_SCHEMAS
     317             :  */
     318             : Datum
     319          16 : current_schema(PG_FUNCTION_ARGS)
     320             : {
     321          16 :     List       *search_path = fetch_search_path(false);
     322             :     char       *nspname;
     323             : 
     324          16 :     if (search_path == NIL)
     325           4 :         PG_RETURN_NULL();
     326          12 :     nspname = get_namespace_name(linitial_oid(search_path));
     327          12 :     list_free(search_path);
     328          12 :     if (!nspname)
     329           0 :         PG_RETURN_NULL();       /* recently-deleted namespace? */
     330          12 :     PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(nspname)));
     331             : }
     332             : 
     333             : Datum
     334         174 : current_schemas(PG_FUNCTION_ARGS)
     335             : {
     336         174 :     List       *search_path = fetch_search_path(PG_GETARG_BOOL(0));
     337             :     ListCell   *l;
     338             :     Datum      *names;
     339             :     int         i;
     340             :     ArrayType  *array;
     341             : 
     342         174 :     names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
     343         174 :     i = 0;
     344         190 :     foreach(l, search_path)
     345             :     {
     346             :         char       *nspname;
     347             : 
     348          16 :         nspname = get_namespace_name(lfirst_oid(l));
     349          16 :         if (nspname)            /* watch out for deleted namespace */
     350             :         {
     351          16 :             names[i] = DirectFunctionCall1(namein, CStringGetDatum(nspname));
     352          16 :             i++;
     353             :         }
     354             :     }
     355         174 :     list_free(search_path);
     356             : 
     357         174 :     array = construct_array(names, i,
     358             :                             NAMEOID,
     359             :                             NAMEDATALEN,    /* sizeof(Name) */
     360             :                             false,  /* Name is not by-val */
     361             :                             'c');   /* alignment of Name */
     362             : 
     363         174 :     PG_RETURN_POINTER(array);
     364             : }
     365             : 
     366             : /*
     367             :  * SQL-function nameconcatoid(name, oid) returns name
     368             :  *
     369             :  * This is used in the information_schema to produce specific_name columns,
     370             :  * which are supposed to be unique per schema.  We achieve that (in an ugly
     371             :  * way) by appending the object's OID.  The result is the same as
     372             :  *      ($1::text || '_' || $2::text)::name
     373             :  * except that, if it would not fit in NAMEDATALEN, we make it do so by
     374             :  * truncating the name input (not the oid).
     375             :  */
     376             : Datum
     377       12268 : nameconcatoid(PG_FUNCTION_ARGS)
     378             : {
     379       12268 :     Name        nam = PG_GETARG_NAME(0);
     380       12268 :     Oid         oid = PG_GETARG_OID(1);
     381             :     Name        result;
     382             :     char        suffix[20];
     383             :     int         suflen;
     384             :     int         namlen;
     385             : 
     386       12268 :     suflen = snprintf(suffix, sizeof(suffix), "_%u", oid);
     387       12268 :     namlen = strlen(NameStr(*nam));
     388             : 
     389             :     /* Truncate oversize input by truncating name part, not suffix */
     390       12268 :     if (namlen + suflen >= NAMEDATALEN)
     391           0 :         namlen = pg_mbcliplen(NameStr(*nam), namlen, NAMEDATALEN - 1 - suflen);
     392             : 
     393             :     /* We use palloc0 here to ensure result is zero-padded */
     394       12268 :     result = (Name) palloc0(NAMEDATALEN);
     395       12268 :     memcpy(NameStr(*result), NameStr(*nam), namlen);
     396       12268 :     memcpy(NameStr(*result) + namlen, suffix, suflen);
     397             : 
     398       12268 :     PG_RETURN_NAME(result);
     399             : }

Generated by: LCOV version 1.13