Coverage Report

Created: 2026-11-12 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/adt/oid.c
Line
Count
Source
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
0
#define OidVectorSize(n)  (offsetof(oidvector, values) + (n) * sizeof(Oid))
30
31
32
/*****************************************************************************
33
 *   USER I/O ROUTINES                             *
34
 *****************************************************************************/
35
36
Datum
37
oidin(PG_FUNCTION_ARGS)
38
0
{
39
0
  char     *s = PG_GETARG_CSTRING(0);
40
0
  Oid     result;
41
42
0
  result = uint32in_subr(s, NULL, "oid", fcinfo->context);
43
0
  PG_RETURN_OID(result);
44
0
}
45
46
Datum
47
oidout(PG_FUNCTION_ARGS)
48
0
{
49
0
  Oid     o = PG_GETARG_OID(0);
50
0
  char     *result = (char *) palloc(12);
51
52
0
  snprintf(result, 12, "%u", o);
53
0
  PG_RETURN_CSTRING(result);
54
0
}
55
56
/*
57
 *    oidrecv     - converts external binary format to oid
58
 */
59
Datum
60
oidrecv(PG_FUNCTION_ARGS)
61
0
{
62
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
63
64
0
  PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
65
0
}
66
67
/*
68
 *    oidsend     - converts oid to binary format
69
 */
70
Datum
71
oidsend(PG_FUNCTION_ARGS)
72
0
{
73
0
  Oid     arg1 = PG_GETARG_OID(0);
74
0
  StringInfoData buf;
75
76
0
  pq_begintypsend(&buf);
77
0
  pq_sendint32(&buf, arg1);
78
0
  PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
79
0
}
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
buildoidvector(const Oid *oids, int n)
88
0
{
89
0
  oidvector  *result;
90
91
0
  result = (oidvector *) palloc0(OidVectorSize(n));
92
93
0
  if (n > 0 && oids)
94
0
    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
0
  SET_VARSIZE(result, OidVectorSize(n));
101
0
  result->ndim = 1;
102
0
  result->dataoffset = 0;   /* never any nulls */
103
0
  result->elemtype = OIDOID;
104
0
  result->dim1 = n;
105
0
  result->lbound1 = 0;
106
107
0
  return result;
108
0
}
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
check_valid_oidvector(const oidvector *oidArray)
119
0
{
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
0
  if (oidArray->ndim != 1 ||
127
0
    oidArray->dataoffset != 0 ||
128
0
    oidArray->elemtype != OIDOID)
129
0
    ereport(ERROR,
130
0
        (errcode(ERRCODE_DATATYPE_MISMATCH),
131
0
         errmsg("array is not a valid oidvector")));
132
0
}
133
134
/*
135
 *    oidvectorin     - converts "num num ..." to internal form
136
 */
137
Datum
138
oidvectorin(PG_FUNCTION_ARGS)
139
0
{
140
0
  char     *oidString = PG_GETARG_CSTRING(0);
141
0
  Node     *escontext = fcinfo->context;
142
0
  oidvector  *result;
143
0
  int     nalloc;
144
0
  int     n;
145
146
0
  nalloc = 32;        /* arbitrary initial size guess */
147
0
  result = (oidvector *) palloc0(OidVectorSize(nalloc));
148
149
0
  for (n = 0;; n++)
150
0
  {
151
0
    while (*oidString && isspace((unsigned char) *oidString))
152
0
      oidString++;
153
0
    if (*oidString == '\0')
154
0
      break;
155
156
0
    if (n >= nalloc)
157
0
    {
158
0
      nalloc *= 2;
159
0
      result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
160
0
    }
161
162
0
    result->values[n] = uint32in_subr(oidString, &oidString,
163
0
                      "oid", escontext);
164
0
    if (SOFT_ERROR_OCCURRED(escontext))
165
0
      PG_RETURN_NULL();
166
0
  }
167
168
0
  SET_VARSIZE(result, OidVectorSize(n));
169
0
  result->ndim = 1;
170
0
  result->dataoffset = 0;   /* never any nulls */
171
0
  result->elemtype = OIDOID;
172
0
  result->dim1 = n;
173
0
  result->lbound1 = 0;
174
175
0
  PG_RETURN_POINTER(result);
176
0
}
177
178
/*
179
 *    oidvectorout - converts internal form to "num num ..."
180
 */
181
Datum
182
oidvectorout(PG_FUNCTION_ARGS)
183
0
{
184
0
  oidvector  *oidArray = (oidvector *) PG_GETARG_POINTER(0);
185
0
  int     num,
186
0
        nnums;
187
0
  char     *rp;
188
0
  char     *result;
189
190
  /* validate input before fetching dim1 */
191
0
  check_valid_oidvector(oidArray);
192
0
  nnums = oidArray->dim1;
193
194
  /* assumes sign, 10 digits, ' ' */
195
0
  rp = result = (char *) palloc(nnums * 12 + 1);
196
0
  for (num = 0; num < nnums; num++)
197
0
  {
198
0
    if (num != 0)
199
0
      *rp++ = ' ';
200
0
    sprintf(rp, "%u", oidArray->values[num]);
201
0
    while (*++rp != '\0')
202
0
      ;
203
0
  }
204
0
  *rp = '\0';
205
0
  PG_RETURN_CSTRING(result);
206
0
}
207
208
/*
209
 *    oidvectorrecv     - converts external binary format to oidvector
210
 */
211
Datum
212
oidvectorrecv(PG_FUNCTION_ARGS)
213
0
{
214
0
  LOCAL_FCINFO(locfcinfo, 3);
215
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
216
0
  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
0
               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
0
  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
0
        (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
245
0
         errmsg("invalid oidvector data")));
246
247
0
  PG_RETURN_POINTER(result);
248
0
}
249
250
/*
251
 *    oidvectorsend     - converts oidvector to binary format
252
 */
253
Datum
254
oidvectorsend(PG_FUNCTION_ARGS)
255
0
{
256
  /* We don't do check_valid_oidvector, since array_send won't care */
257
0
  return array_send(fcinfo);
258
0
}
259
260
/*
261
 *    oidparse        - get OID from ICONST/FCONST node
262
 */
263
Oid
264
oidparse(Node *node)
265
0
{
266
0
  switch (nodeTag(node))
267
0
  {
268
0
    case T_Integer:
269
0
      return intVal(node);
270
0
    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
0
      return uint32in_subr(castNode(Float, node)->fval, NULL,
278
0
                 "oid", NULL);
279
0
    default:
280
0
      elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
281
0
  }
282
0
  return InvalidOid;     /* keep compiler quiet */
283
0
}
284
285
/* qsort comparison function for Oids */
286
int
287
oid_cmp(const void *p1, const void *p2)
288
0
{
289
0
  Oid     v1 = *((const Oid *) p1);
290
0
  Oid     v2 = *((const Oid *) p2);
291
292
0
  return pg_cmp_u32(v1, v2);
293
0
}
294
295
296
/*****************************************************************************
297
 *   PUBLIC ROUTINES                             *
298
 *****************************************************************************/
299
300
Datum
301
oideq(PG_FUNCTION_ARGS)
302
0
{
303
0
  Oid     arg1 = PG_GETARG_OID(0);
304
0
  Oid     arg2 = PG_GETARG_OID(1);
305
306
0
  PG_RETURN_BOOL(arg1 == arg2);
307
0
}
308
309
Datum
310
oidne(PG_FUNCTION_ARGS)
311
0
{
312
0
  Oid     arg1 = PG_GETARG_OID(0);
313
0
  Oid     arg2 = PG_GETARG_OID(1);
314
315
0
  PG_RETURN_BOOL(arg1 != arg2);
316
0
}
317
318
Datum
319
oidlt(PG_FUNCTION_ARGS)
320
0
{
321
0
  Oid     arg1 = PG_GETARG_OID(0);
322
0
  Oid     arg2 = PG_GETARG_OID(1);
323
324
0
  PG_RETURN_BOOL(arg1 < arg2);
325
0
}
326
327
Datum
328
oidle(PG_FUNCTION_ARGS)
329
0
{
330
0
  Oid     arg1 = PG_GETARG_OID(0);
331
0
  Oid     arg2 = PG_GETARG_OID(1);
332
333
0
  PG_RETURN_BOOL(arg1 <= arg2);
334
0
}
335
336
Datum
337
oidge(PG_FUNCTION_ARGS)
338
0
{
339
0
  Oid     arg1 = PG_GETARG_OID(0);
340
0
  Oid     arg2 = PG_GETARG_OID(1);
341
342
0
  PG_RETURN_BOOL(arg1 >= arg2);
343
0
}
344
345
Datum
346
oidgt(PG_FUNCTION_ARGS)
347
0
{
348
0
  Oid     arg1 = PG_GETARG_OID(0);
349
0
  Oid     arg2 = PG_GETARG_OID(1);
350
351
0
  PG_RETURN_BOOL(arg1 > arg2);
352
0
}
353
354
Datum
355
oidlarger(PG_FUNCTION_ARGS)
356
0
{
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
0
}
362
363
Datum
364
oidsmaller(PG_FUNCTION_ARGS)
365
0
{
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
0
}
371
372
Datum
373
oidvectoreq(PG_FUNCTION_ARGS)
374
0
{
375
0
  int32   cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
376
377
0
  PG_RETURN_BOOL(cmp == 0);
378
0
}
379
380
Datum
381
oidvectorne(PG_FUNCTION_ARGS)
382
0
{
383
0
  int32   cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
384
385
0
  PG_RETURN_BOOL(cmp != 0);
386
0
}
387
388
Datum
389
oidvectorlt(PG_FUNCTION_ARGS)
390
0
{
391
0
  int32   cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
392
393
0
  PG_RETURN_BOOL(cmp < 0);
394
0
}
395
396
Datum
397
oidvectorle(PG_FUNCTION_ARGS)
398
0
{
399
0
  int32   cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
400
401
0
  PG_RETURN_BOOL(cmp <= 0);
402
0
}
403
404
Datum
405
oidvectorge(PG_FUNCTION_ARGS)
406
0
{
407
0
  int32   cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
408
409
0
  PG_RETURN_BOOL(cmp >= 0);
410
0
}
411
412
Datum
413
oidvectorgt(PG_FUNCTION_ARGS)
414
0
{
415
0
  int32   cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
416
417
0
  PG_RETURN_BOOL(cmp > 0);
418
0
}