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

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * oid.c
       4              :  *    Functions for the built-in type Oid ... also oidvector.
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  *
      10              :  * IDENTIFICATION
      11              :  *    src/backend/utils/adt/oid.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : #include "postgres.h"
      16              : 
      17              : #include <ctype.h>
      18              : #include <limits.h>
      19              : 
      20              : #include "catalog/pg_type.h"
      21              : #include "common/int.h"
      22              : #include "libpq/pqformat.h"
      23              : #include "nodes/miscnodes.h"
      24              : #include "nodes/value.h"
      25              : #include "utils/array.h"
      26              : #include "utils/builtins.h"
      27              : 
      28              : 
      29              : #define OidVectorSize(n)    (offsetof(oidvector, values) + (n) * sizeof(Oid))
      30              : 
      31              : 
      32              : /*****************************************************************************
      33              :  *   USER I/O ROUTINES                                                       *
      34              :  *****************************************************************************/
      35              : 
      36              : Datum
      37      3074611 : oidin(PG_FUNCTION_ARGS)
      38              : {
      39      3074611 :     char       *s = PG_GETARG_CSTRING(0);
      40              :     Oid         result;
      41              : 
      42      3074611 :     result = uint32in_subr(s, NULL, "oid", fcinfo->context);
      43      3074581 :     PG_RETURN_OID(result);
      44              : }
      45              : 
      46              : Datum
      47      8353774 : oidout(PG_FUNCTION_ARGS)
      48              : {
      49      8353774 :     Oid         o = PG_GETARG_OID(0);
      50      8353774 :     char       *result = (char *) palloc(12);
      51              : 
      52      8353774 :     snprintf(result, 12, "%u", o);
      53      8353774 :     PG_RETURN_CSTRING(result);
      54              : }
      55              : 
      56              : /*
      57              :  *      oidrecv         - converts external binary format to oid
      58              :  */
      59              : Datum
      60          103 : oidrecv(PG_FUNCTION_ARGS)
      61              : {
      62          103 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      63              : 
      64          103 :     PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
      65              : }
      66              : 
      67              : /*
      68              :  *      oidsend         - converts oid to binary format
      69              :  */
      70              : Datum
      71            7 : oidsend(PG_FUNCTION_ARGS)
      72              : {
      73            7 :     Oid         arg1 = PG_GETARG_OID(0);
      74              :     StringInfoData buf;
      75              : 
      76            7 :     pq_begintypsend(&buf);
      77            7 :     pq_sendint32(&buf, arg1);
      78            7 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
      79              : }
      80              : 
      81              : /*
      82              :  * construct oidvector given a raw array of Oids
      83              :  *
      84              :  * If oids is NULL then caller must fill values[] afterward
      85              :  */
      86              : oidvector *
      87        69000 : buildoidvector(const Oid *oids, int n)
      88              : {
      89              :     oidvector  *result;
      90              : 
      91        69000 :     result = (oidvector *) palloc0(OidVectorSize(n));
      92              : 
      93        69000 :     if (n > 0 && oids)
      94        66505 :         memcpy(result->values, oids, n * sizeof(Oid));
      95              : 
      96              :     /*
      97              :      * Attach standard array header.  For historical reasons, we set the index
      98              :      * lower bound to 0 not 1.
      99              :      */
     100        69000 :     SET_VARSIZE(result, OidVectorSize(n));
     101        69000 :     result->ndim = 1;
     102        69000 :     result->dataoffset = 0;      /* never any nulls */
     103        69000 :     result->elemtype = OIDOID;
     104        69000 :     result->dim1 = n;
     105        69000 :     result->lbound1 = 0;
     106              : 
     107        69000 :     return result;
     108              : }
     109              : 
     110              : /*
     111              :  * validate that an array object meets the restrictions of oidvector
     112              :  *
     113              :  * We need this because there are pathways by which a general oid[] array can
     114              :  * be cast to oidvector, allowing the type's restrictions to be violated.
     115              :  * All code that receives an oidvector as a SQL parameter should check this.
     116              :  */
     117              : void
     118      8446037 : check_valid_oidvector(const oidvector *oidArray)
     119              : {
     120              :     /*
     121              :      * We insist on ndim == 1 and dataoffset == 0 (that is, no nulls) because
     122              :      * otherwise the array's layout will not be what calling code expects.  We
     123              :      * needn't be picky about the index lower bound though.  Checking elemtype
     124              :      * is just paranoia.
     125              :      */
     126      8446037 :     if (oidArray->ndim != 1 ||
     127      8446034 :         oidArray->dataoffset != 0 ||
     128      8446034 :         oidArray->elemtype != OIDOID)
     129            3 :         ereport(ERROR,
     130              :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     131              :                  errmsg("array is not a valid oidvector")));
     132      8446034 : }
     133              : 
     134              : /*
     135              :  *      oidvectorin         - converts "num num ..." to internal form
     136              :  */
     137              : Datum
     138       175320 : oidvectorin(PG_FUNCTION_ARGS)
     139              : {
     140       175320 :     char       *oidString = PG_GETARG_CSTRING(0);
     141       175320 :     Node       *escontext = fcinfo->context;
     142              :     oidvector  *result;
     143              :     int         nalloc;
     144              :     int         n;
     145              : 
     146       175320 :     nalloc = 32;                /* arbitrary initial size guess */
     147       175320 :     result = (oidvector *) palloc0(OidVectorSize(nalloc));
     148              : 
     149       175320 :     for (n = 0;; n++)
     150              :     {
     151       646224 :         while (*oidString && isspace((unsigned char) *oidString))
     152       152163 :             oidString++;
     153       494061 :         if (*oidString == '\0')
     154       175308 :             break;
     155              : 
     156       318753 :         if (n >= nalloc)
     157              :         {
     158            0 :             nalloc *= 2;
     159            0 :             result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
     160              :         }
     161              : 
     162       318753 :         result->values[n] = uint32in_subr(oidString, &oidString,
     163              :                                           "oid", escontext);
     164       318753 :         if (SOFT_ERROR_OCCURRED(escontext))
     165           12 :             PG_RETURN_NULL();
     166              :     }
     167              : 
     168       175308 :     SET_VARSIZE(result, OidVectorSize(n));
     169       175308 :     result->ndim = 1;
     170       175308 :     result->dataoffset = 0;      /* never any nulls */
     171       175308 :     result->elemtype = OIDOID;
     172       175308 :     result->dim1 = n;
     173       175308 :     result->lbound1 = 0;
     174              : 
     175       175308 :     PG_RETURN_POINTER(result);
     176              : }
     177              : 
     178              : /*
     179              :  *      oidvectorout - converts internal form to "num num ..."
     180              :  */
     181              : Datum
     182        20797 : oidvectorout(PG_FUNCTION_ARGS)
     183              : {
     184        20797 :     oidvector  *oidArray = (oidvector *) PG_GETARG_POINTER(0);
     185              :     int         num,
     186              :                 nnums;
     187              :     char       *rp;
     188              :     char       *result;
     189              : 
     190              :     /* validate input before fetching dim1 */
     191        20797 :     check_valid_oidvector(oidArray);
     192        20794 :     nnums = oidArray->dim1;
     193              : 
     194              :     /* assumes sign, 10 digits, ' ' */
     195        20794 :     rp = result = (char *) palloc(nnums * 12 + 1);
     196        54989 :     for (num = 0; num < nnums; num++)
     197              :     {
     198        34195 :         if (num != 0)
     199        15285 :             *rp++ = ' ';
     200        34195 :         sprintf(rp, "%u", oidArray->values[num]);
     201        97635 :         while (*++rp != '\0')
     202              :             ;
     203              :     }
     204        20794 :     *rp = '\0';
     205        20794 :     PG_RETURN_CSTRING(result);
     206              : }
     207              : 
     208              : /*
     209              :  *      oidvectorrecv           - converts external binary format to oidvector
     210              :  */
     211              : Datum
     212            0 : oidvectorrecv(PG_FUNCTION_ARGS)
     213              : {
     214            0 :     LOCAL_FCINFO(locfcinfo, 3);
     215            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     216              :     oidvector  *result;
     217              : 
     218              :     /*
     219              :      * Normally one would call array_recv() using DirectFunctionCall3, but
     220              :      * that does not work since array_recv wants to cache some data using
     221              :      * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
     222              :      * parameter.
     223              :      */
     224            0 :     InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
     225              :                              InvalidOid, NULL, NULL);
     226              : 
     227            0 :     locfcinfo->args[0].value = PointerGetDatum(buf);
     228            0 :     locfcinfo->args[0].isnull = false;
     229            0 :     locfcinfo->args[1].value = ObjectIdGetDatum(OIDOID);
     230            0 :     locfcinfo->args[1].isnull = false;
     231            0 :     locfcinfo->args[2].value = Int32GetDatum(-1);
     232            0 :     locfcinfo->args[2].isnull = false;
     233              : 
     234            0 :     result = (oidvector *) DatumGetPointer(array_recv(locfcinfo));
     235              : 
     236              :     Assert(!locfcinfo->isnull);
     237              : 
     238              :     /* sanity checks: oidvector must be 1-D, 0-based, no nulls */
     239            0 :     if (ARR_NDIM(result) != 1 ||
     240            0 :         ARR_HASNULL(result) ||
     241            0 :         ARR_ELEMTYPE(result) != OIDOID ||
     242            0 :         ARR_LBOUND(result)[0] != 0)
     243            0 :         ereport(ERROR,
     244              :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     245              :                  errmsg("invalid oidvector data")));
     246              : 
     247            0 :     PG_RETURN_POINTER(result);
     248              : }
     249              : 
     250              : /*
     251              :  *      oidvectorsend           - converts oidvector to binary format
     252              :  */
     253              : Datum
     254            0 : oidvectorsend(PG_FUNCTION_ARGS)
     255              : {
     256              :     /* We don't do check_valid_oidvector, since array_send won't care */
     257            0 :     return array_send(fcinfo);
     258              : }
     259              : 
     260              : /*
     261              :  *      oidparse                - get OID from ICONST/FCONST node
     262              :  */
     263              : Oid
     264           95 : oidparse(Node *node)
     265              : {
     266           95 :     switch (nodeTag(node))
     267              :     {
     268           89 :         case T_Integer:
     269           89 :             return intVal(node);
     270            6 :         case T_Float:
     271              : 
     272              :             /*
     273              :              * Values too large for int4 will be represented as Float
     274              :              * constants by the lexer.  Accept these if they are valid OID
     275              :              * strings.
     276              :              */
     277            6 :             return uint32in_subr(castNode(Float, node)->fval, NULL,
     278              :                                  "oid", NULL);
     279            0 :         default:
     280            0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     281              :     }
     282              :     return InvalidOid;          /* keep compiler quiet */
     283              : }
     284              : 
     285              : /* qsort comparison function for Oids */
     286              : int
     287       223071 : oid_cmp(const void *p1, const void *p2)
     288              : {
     289       223071 :     Oid         v1 = *((const Oid *) p1);
     290       223071 :     Oid         v2 = *((const Oid *) p2);
     291              : 
     292       223071 :     return pg_cmp_u32(v1, v2);
     293              : }
     294              : 
     295              : 
     296              : /*****************************************************************************
     297              :  *   PUBLIC ROUTINES                                                         *
     298              :  *****************************************************************************/
     299              : 
     300              : Datum
     301     74939825 : oideq(PG_FUNCTION_ARGS)
     302              : {
     303     74939825 :     Oid         arg1 = PG_GETARG_OID(0);
     304     74939825 :     Oid         arg2 = PG_GETARG_OID(1);
     305              : 
     306     74939825 :     PG_RETURN_BOOL(arg1 == arg2);
     307              : }
     308              : 
     309              : Datum
     310      1408226 : oidne(PG_FUNCTION_ARGS)
     311              : {
     312      1408226 :     Oid         arg1 = PG_GETARG_OID(0);
     313      1408226 :     Oid         arg2 = PG_GETARG_OID(1);
     314              : 
     315      1408226 :     PG_RETURN_BOOL(arg1 != arg2);
     316              : }
     317              : 
     318              : Datum
     319      2947324 : oidlt(PG_FUNCTION_ARGS)
     320              : {
     321      2947324 :     Oid         arg1 = PG_GETARG_OID(0);
     322      2947324 :     Oid         arg2 = PG_GETARG_OID(1);
     323              : 
     324      2947324 :     PG_RETURN_BOOL(arg1 < arg2);
     325              : }
     326              : 
     327              : Datum
     328      1039390 : oidle(PG_FUNCTION_ARGS)
     329              : {
     330      1039390 :     Oid         arg1 = PG_GETARG_OID(0);
     331      1039390 :     Oid         arg2 = PG_GETARG_OID(1);
     332              : 
     333      1039390 :     PG_RETURN_BOOL(arg1 <= arg2);
     334              : }
     335              : 
     336              : Datum
     337        14131 : oidge(PG_FUNCTION_ARGS)
     338              : {
     339        14131 :     Oid         arg1 = PG_GETARG_OID(0);
     340        14131 :     Oid         arg2 = PG_GETARG_OID(1);
     341              : 
     342        14131 :     PG_RETURN_BOOL(arg1 >= arg2);
     343              : }
     344              : 
     345              : Datum
     346       189138 : oidgt(PG_FUNCTION_ARGS)
     347              : {
     348       189138 :     Oid         arg1 = PG_GETARG_OID(0);
     349       189138 :     Oid         arg2 = PG_GETARG_OID(1);
     350              : 
     351       189138 :     PG_RETURN_BOOL(arg1 > arg2);
     352              : }
     353              : 
     354              : Datum
     355            0 : oidlarger(PG_FUNCTION_ARGS)
     356              : {
     357            0 :     Oid         arg1 = PG_GETARG_OID(0);
     358            0 :     Oid         arg2 = PG_GETARG_OID(1);
     359              : 
     360            0 :     PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
     361              : }
     362              : 
     363              : Datum
     364            0 : oidsmaller(PG_FUNCTION_ARGS)
     365              : {
     366            0 :     Oid         arg1 = PG_GETARG_OID(0);
     367            0 :     Oid         arg2 = PG_GETARG_OID(1);
     368              : 
     369            0 :     PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
     370              : }
     371              : 
     372              : Datum
     373        18938 : oidvectoreq(PG_FUNCTION_ARGS)
     374              : {
     375        18938 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     376              : 
     377        18938 :     PG_RETURN_BOOL(cmp == 0);
     378              : }
     379              : 
     380              : Datum
     381        11220 : oidvectorne(PG_FUNCTION_ARGS)
     382              : {
     383        11220 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     384              : 
     385        11220 :     PG_RETURN_BOOL(cmp != 0);
     386              : }
     387              : 
     388              : Datum
     389         1842 : oidvectorlt(PG_FUNCTION_ARGS)
     390              : {
     391         1842 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     392              : 
     393         1842 :     PG_RETURN_BOOL(cmp < 0);
     394              : }
     395              : 
     396              : Datum
     397          636 : oidvectorle(PG_FUNCTION_ARGS)
     398              : {
     399          636 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     400              : 
     401          636 :     PG_RETURN_BOOL(cmp <= 0);
     402              : }
     403              : 
     404              : Datum
     405            0 : oidvectorge(PG_FUNCTION_ARGS)
     406              : {
     407            0 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     408              : 
     409            0 :     PG_RETURN_BOOL(cmp >= 0);
     410              : }
     411              : 
     412              : Datum
     413            0 : oidvectorgt(PG_FUNCTION_ARGS)
     414              : {
     415            0 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     416              : 
     417            0 :     PG_RETURN_BOOL(cmp > 0);
     418              : }
        

Generated by: LCOV version 2.0-1