LCOV - code coverage report
Current view: top level - src/backend/utils/adt - oid.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 113 150 75.3 %
Date: 2026-02-13 19:18:24 Functions: 20 26 76.9 %
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     6149322 : oidin(PG_FUNCTION_ARGS)
      38             : {
      39     6149322 :     char       *s = PG_GETARG_CSTRING(0);
      40             :     Oid         result;
      41             : 
      42     6149322 :     result = uint32in_subr(s, NULL, "oid", fcinfo->context);
      43     6149262 :     PG_RETURN_OID(result);
      44             : }
      45             : 
      46             : Datum
      47    16566244 : oidout(PG_FUNCTION_ARGS)
      48             : {
      49    16566244 :     Oid         o = PG_GETARG_OID(0);
      50    16566244 :     char       *result = (char *) palloc(12);
      51             : 
      52    16566244 :     snprintf(result, 12, "%u", o);
      53    16566244 :     PG_RETURN_CSTRING(result);
      54             : }
      55             : 
      56             : /*
      57             :  *      oidrecv         - converts external binary format to oid
      58             :  */
      59             : Datum
      60         206 : oidrecv(PG_FUNCTION_ARGS)
      61             : {
      62         206 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      63             : 
      64         206 :     PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
      65             : }
      66             : 
      67             : /*
      68             :  *      oidsend         - converts oid to binary format
      69             :  */
      70             : Datum
      71          14 : oidsend(PG_FUNCTION_ARGS)
      72             : {
      73          14 :     Oid         arg1 = PG_GETARG_OID(0);
      74             :     StringInfoData buf;
      75             : 
      76          14 :     pq_begintypsend(&buf);
      77          14 :     pq_sendint32(&buf, arg1);
      78          14 :     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      138076 : buildoidvector(const Oid *oids, int n)
      88             : {
      89             :     oidvector  *result;
      90             : 
      91      138076 :     result = (oidvector *) palloc0(OidVectorSize(n));
      92             : 
      93      138076 :     if (n > 0 && oids)
      94      133078 :         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      138076 :     SET_VARSIZE(result, OidVectorSize(n));
     101      138076 :     result->ndim = 1;
     102      138076 :     result->dataoffset = 0;      /* never any nulls */
     103      138076 :     result->elemtype = OIDOID;
     104      138076 :     result->dim1 = n;
     105      138076 :     result->lbound1 = 0;
     106             : 
     107      138076 :     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    16908296 : 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    16908296 :     if (oidArray->ndim != 1 ||
     127    16908290 :         oidArray->dataoffset != 0 ||
     128    16908290 :         oidArray->elemtype != OIDOID)
     129           6 :         ereport(ERROR,
     130             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     131             :                  errmsg("array is not a valid oidvector")));
     132    16908290 : }
     133             : 
     134             : /*
     135             :  *      oidvectorin         - converts "num num ..." to internal form
     136             :  */
     137             : Datum
     138      350640 : oidvectorin(PG_FUNCTION_ARGS)
     139             : {
     140      350640 :     char       *oidString = PG_GETARG_CSTRING(0);
     141      350640 :     Node       *escontext = fcinfo->context;
     142             :     oidvector  *result;
     143             :     int         nalloc;
     144             :     int         n;
     145             : 
     146      350640 :     nalloc = 32;                /* arbitrary initial size guess */
     147      350640 :     result = (oidvector *) palloc0(OidVectorSize(nalloc));
     148             : 
     149      350640 :     for (n = 0;; n++)
     150             :     {
     151     1292448 :         while (*oidString && isspace((unsigned char) *oidString))
     152      304326 :             oidString++;
     153      988122 :         if (*oidString == '\0')
     154      350616 :             break;
     155             : 
     156      637506 :         if (n >= nalloc)
     157             :         {
     158           0 :             nalloc *= 2;
     159           0 :             result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
     160             :         }
     161             : 
     162      637506 :         result->values[n] = uint32in_subr(oidString, &oidString,
     163             :                                           "oid", escontext);
     164      637506 :         if (SOFT_ERROR_OCCURRED(escontext))
     165          24 :             PG_RETURN_NULL();
     166             :     }
     167             : 
     168      350616 :     SET_VARSIZE(result, OidVectorSize(n));
     169      350616 :     result->ndim = 1;
     170      350616 :     result->dataoffset = 0;      /* never any nulls */
     171      350616 :     result->elemtype = OIDOID;
     172      350616 :     result->dim1 = n;
     173      350616 :     result->lbound1 = 0;
     174             : 
     175      350616 :     PG_RETURN_POINTER(result);
     176             : }
     177             : 
     178             : /*
     179             :  *      oidvectorout - converts internal form to "num num ..."
     180             :  */
     181             : Datum
     182       41630 : oidvectorout(PG_FUNCTION_ARGS)
     183             : {
     184       41630 :     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       41630 :     check_valid_oidvector(oidArray);
     192       41624 :     nnums = oidArray->dim1;
     193             : 
     194             :     /* assumes sign, 10 digits, ' ' */
     195       41624 :     rp = result = (char *) palloc(nnums * 12 + 1);
     196      110072 :     for (num = 0; num < nnums; num++)
     197             :     {
     198       68448 :         if (num != 0)
     199       30592 :             *rp++ = ' ';
     200       68448 :         sprintf(rp, "%u", oidArray->values[num]);
     201      195370 :         while (*++rp != '\0')
     202             :             ;
     203             :     }
     204       41624 :     *rp = '\0';
     205       41624 :     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         188 : oidparse(Node *node)
     265             : {
     266         188 :     switch (nodeTag(node))
     267             :     {
     268         176 :         case T_Integer:
     269         176 :             return intVal(node);
     270          12 :         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          12 :             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      442798 : oid_cmp(const void *p1, const void *p2)
     288             : {
     289      442798 :     Oid         v1 = *((const Oid *) p1);
     290      442798 :     Oid         v2 = *((const Oid *) p2);
     291             : 
     292      442798 :     return pg_cmp_u32(v1, v2);
     293             : }
     294             : 
     295             : 
     296             : /*****************************************************************************
     297             :  *   PUBLIC ROUTINES                                                         *
     298             :  *****************************************************************************/
     299             : 
     300             : Datum
     301   151044100 : oideq(PG_FUNCTION_ARGS)
     302             : {
     303   151044100 :     Oid         arg1 = PG_GETARG_OID(0);
     304   151044100 :     Oid         arg2 = PG_GETARG_OID(1);
     305             : 
     306   151044100 :     PG_RETURN_BOOL(arg1 == arg2);
     307             : }
     308             : 
     309             : Datum
     310     2821872 : oidne(PG_FUNCTION_ARGS)
     311             : {
     312     2821872 :     Oid         arg1 = PG_GETARG_OID(0);
     313     2821872 :     Oid         arg2 = PG_GETARG_OID(1);
     314             : 
     315     2821872 :     PG_RETURN_BOOL(arg1 != arg2);
     316             : }
     317             : 
     318             : Datum
     319     5937292 : oidlt(PG_FUNCTION_ARGS)
     320             : {
     321     5937292 :     Oid         arg1 = PG_GETARG_OID(0);
     322     5937292 :     Oid         arg2 = PG_GETARG_OID(1);
     323             : 
     324     5937292 :     PG_RETURN_BOOL(arg1 < arg2);
     325             : }
     326             : 
     327             : Datum
     328     2098274 : oidle(PG_FUNCTION_ARGS)
     329             : {
     330     2098274 :     Oid         arg1 = PG_GETARG_OID(0);
     331     2098274 :     Oid         arg2 = PG_GETARG_OID(1);
     332             : 
     333     2098274 :     PG_RETURN_BOOL(arg1 <= arg2);
     334             : }
     335             : 
     336             : Datum
     337       29856 : oidge(PG_FUNCTION_ARGS)
     338             : {
     339       29856 :     Oid         arg1 = PG_GETARG_OID(0);
     340       29856 :     Oid         arg2 = PG_GETARG_OID(1);
     341             : 
     342       29856 :     PG_RETURN_BOOL(arg1 >= arg2);
     343             : }
     344             : 
     345             : Datum
     346      378276 : oidgt(PG_FUNCTION_ARGS)
     347             : {
     348      378276 :     Oid         arg1 = PG_GETARG_OID(0);
     349      378276 :     Oid         arg2 = PG_GETARG_OID(1);
     350             : 
     351      378276 :     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       37938 : oidvectoreq(PG_FUNCTION_ARGS)
     374             : {
     375       37938 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     376             : 
     377       37938 :     PG_RETURN_BOOL(cmp == 0);
     378             : }
     379             : 
     380             : Datum
     381       22504 : oidvectorne(PG_FUNCTION_ARGS)
     382             : {
     383       22504 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     384             : 
     385       22504 :     PG_RETURN_BOOL(cmp != 0);
     386             : }
     387             : 
     388             : Datum
     389        3684 : oidvectorlt(PG_FUNCTION_ARGS)
     390             : {
     391        3684 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     392             : 
     393        3684 :     PG_RETURN_BOOL(cmp < 0);
     394             : }
     395             : 
     396             : Datum
     397        1272 : oidvectorle(PG_FUNCTION_ARGS)
     398             : {
     399        1272 :     int32       cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
     400             : 
     401        1272 :     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 1.16