PostgreSQL Source Code  git master
oid.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * oid.c
4  * Functions for the built-in type Oid ... also oidvector.
5  *
6  * Portions Copyright (c) 1996-2017, 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 "libpq/pqformat.h"
22 #include "nodes/value.h"
23 #include "utils/array.h"
24 #include "utils/builtins.h"
25 
26 
27 #define OidVectorSize(n) (offsetof(oidvector, values) + (n) * sizeof(Oid))
28 
29 
30 /*****************************************************************************
31  * USER I/O ROUTINES *
32  *****************************************************************************/
33 
34 static Oid
35 oidin_subr(const char *s, char **endloc)
36 {
37  unsigned long cvt;
38  char *endptr;
39  Oid result;
40 
41  if (*s == '\0')
42  ereport(ERROR,
43  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
44  errmsg("invalid input syntax for type %s: \"%s\"",
45  "oid", s)));
46 
47  errno = 0;
48  cvt = strtoul(s, &endptr, 10);
49 
50  /*
51  * strtoul() normally only sets ERANGE. On some systems it also may set
52  * EINVAL, which simply means it couldn't parse the input string. This is
53  * handled by the second "if" consistent across platforms.
54  */
55  if (errno && errno != ERANGE && errno != EINVAL)
56  ereport(ERROR,
57  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
58  errmsg("invalid input syntax for type %s: \"%s\"",
59  "oid", s)));
60 
61  if (endptr == s && *s != '\0')
62  ereport(ERROR,
63  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
64  errmsg("invalid input syntax for type %s: \"%s\"",
65  "oid", s)));
66 
67  if (errno == ERANGE)
68  ereport(ERROR,
69  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
70  errmsg("value \"%s\" is out of range for type %s",
71  s, "oid")));
72 
73  if (endloc)
74  {
75  /* caller wants to deal with rest of string */
76  *endloc = endptr;
77  }
78  else
79  {
80  /* allow only whitespace after number */
81  while (*endptr && isspace((unsigned char) *endptr))
82  endptr++;
83  if (*endptr)
84  ereport(ERROR,
85  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
86  errmsg("invalid input syntax for type %s: \"%s\"",
87  "oid", s)));
88  }
89 
90  result = (Oid) cvt;
91 
92  /*
93  * Cope with possibility that unsigned long is wider than Oid, in which
94  * case strtoul will not raise an error for some values that are out of
95  * the range of Oid.
96  *
97  * For backwards compatibility, we want to accept inputs that are given
98  * with a minus sign, so allow the input value if it matches after either
99  * signed or unsigned extension to long.
100  *
101  * To ensure consistent results on 32-bit and 64-bit platforms, make sure
102  * the error message is the same as if strtoul() had returned ERANGE.
103  */
104 #if OID_MAX != ULONG_MAX
105  if (cvt != (unsigned long) result &&
106  cvt != (unsigned long) ((int) result))
107  ereport(ERROR,
108  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109  errmsg("value \"%s\" is out of range for type %s",
110  s, "oid")));
111 #endif
112 
113  return result;
114 }
115 
116 Datum
118 {
119  char *s = PG_GETARG_CSTRING(0);
120  Oid result;
121 
122  result = oidin_subr(s, NULL);
123  PG_RETURN_OID(result);
124 }
125 
126 Datum
128 {
129  Oid o = PG_GETARG_OID(0);
130  char *result = (char *) palloc(12);
131 
132  snprintf(result, 12, "%u", o);
133  PG_RETURN_CSTRING(result);
134 }
135 
136 /*
137  * oidrecv - converts external binary format to oid
138  */
139 Datum
141 {
143 
144  PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
145 }
146 
147 /*
148  * oidsend - converts oid to binary format
149  */
150 Datum
152 {
153  Oid arg1 = PG_GETARG_OID(0);
155 
156  pq_begintypsend(&buf);
157  pq_sendint32(&buf, arg1);
159 }
160 
161 /*
162  * construct oidvector given a raw array of Oids
163  *
164  * If oids is NULL then caller must fill values[] afterward
165  */
166 oidvector *
167 buildoidvector(const Oid *oids, int n)
168 {
169  oidvector *result;
170 
171  result = (oidvector *) palloc0(OidVectorSize(n));
172 
173  if (n > 0 && oids)
174  memcpy(result->values, oids, n * sizeof(Oid));
175 
176  /*
177  * Attach standard array header. For historical reasons, we set the index
178  * lower bound to 0 not 1.
179  */
180  SET_VARSIZE(result, OidVectorSize(n));
181  result->ndim = 1;
182  result->dataoffset = 0; /* never any nulls */
183  result->elemtype = OIDOID;
184  result->dim1 = n;
185  result->lbound1 = 0;
186 
187  return result;
188 }
189 
190 /*
191  * oidvectorin - converts "num num ..." to internal form
192  */
193 Datum
195 {
196  char *oidString = PG_GETARG_CSTRING(0);
197  oidvector *result;
198  int n;
199 
201 
202  for (n = 0; n < FUNC_MAX_ARGS; n++)
203  {
204  while (*oidString && isspace((unsigned char) *oidString))
205  oidString++;
206  if (*oidString == '\0')
207  break;
208  result->values[n] = oidin_subr(oidString, &oidString);
209  }
210  while (*oidString && isspace((unsigned char) *oidString))
211  oidString++;
212  if (*oidString)
213  ereport(ERROR,
214  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
215  errmsg("oidvector has too many elements")));
216 
217  SET_VARSIZE(result, OidVectorSize(n));
218  result->ndim = 1;
219  result->dataoffset = 0; /* never any nulls */
220  result->elemtype = OIDOID;
221  result->dim1 = n;
222  result->lbound1 = 0;
223 
224  PG_RETURN_POINTER(result);
225 }
226 
227 /*
228  * oidvectorout - converts internal form to "num num ..."
229  */
230 Datum
232 {
233  oidvector *oidArray = (oidvector *) PG_GETARG_POINTER(0);
234  int num,
235  nnums = oidArray->dim1;
236  char *rp;
237  char *result;
238 
239  /* assumes sign, 10 digits, ' ' */
240  rp = result = (char *) palloc(nnums * 12 + 1);
241  for (num = 0; num < nnums; num++)
242  {
243  if (num != 0)
244  *rp++ = ' ';
245  sprintf(rp, "%u", oidArray->values[num]);
246  while (*++rp != '\0')
247  ;
248  }
249  *rp = '\0';
250  PG_RETURN_CSTRING(result);
251 }
252 
253 /*
254  * oidvectorrecv - converts external binary format to oidvector
255  */
256 Datum
258 {
260  FunctionCallInfoData locfcinfo;
261  oidvector *result;
262 
263  /*
264  * Normally one would call array_recv() using DirectFunctionCall3, but
265  * that does not work since array_recv wants to cache some data using
266  * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
267  * parameter.
268  */
269  InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
270  InvalidOid, NULL, NULL);
271 
272  locfcinfo.arg[0] = PointerGetDatum(buf);
273  locfcinfo.arg[1] = ObjectIdGetDatum(OIDOID);
274  locfcinfo.arg[2] = Int32GetDatum(-1);
275  locfcinfo.argnull[0] = false;
276  locfcinfo.argnull[1] = false;
277  locfcinfo.argnull[2] = false;
278 
279  result = (oidvector *) DatumGetPointer(array_recv(&locfcinfo));
280 
281  Assert(!locfcinfo.isnull);
282 
283  /* sanity checks: oidvector must be 1-D, 0-based, no nulls */
284  if (ARR_NDIM(result) != 1 ||
285  ARR_HASNULL(result) ||
286  ARR_ELEMTYPE(result) != OIDOID ||
287  ARR_LBOUND(result)[0] != 0)
288  ereport(ERROR,
289  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
290  errmsg("invalid oidvector data")));
291 
292  /* check length for consistency with oidvectorin() */
293  if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
294  ereport(ERROR,
295  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
296  errmsg("oidvector has too many elements")));
297 
298  PG_RETURN_POINTER(result);
299 }
300 
301 /*
302  * oidvectorsend - converts oidvector to binary format
303  */
304 Datum
306 {
307  return array_send(fcinfo);
308 }
309 
310 /*
311  * oidparse - get OID from IConst/FConst node
312  */
313 Oid
315 {
316  switch (nodeTag(node))
317  {
318  case T_Integer:
319  return intVal(node);
320  case T_Float:
321 
322  /*
323  * Values too large for int4 will be represented as Float
324  * constants by the lexer. Accept these if they are valid OID
325  * strings.
326  */
327  return oidin_subr(strVal(node), NULL);
328  default:
329  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
330  }
331  return InvalidOid; /* keep compiler quiet */
332 }
333 
334 /* qsort comparison function for Oids */
335 int
336 oid_cmp(const void *p1, const void *p2)
337 {
338  Oid v1 = *((const Oid *) p1);
339  Oid v2 = *((const Oid *) p2);
340 
341  if (v1 < v2)
342  return -1;
343  if (v1 > v2)
344  return 1;
345  return 0;
346 }
347 
348 
349 /*****************************************************************************
350  * PUBLIC ROUTINES *
351  *****************************************************************************/
352 
353 Datum
355 {
356  Oid arg1 = PG_GETARG_OID(0);
357  Oid arg2 = PG_GETARG_OID(1);
358 
359  PG_RETURN_BOOL(arg1 == arg2);
360 }
361 
362 Datum
364 {
365  Oid arg1 = PG_GETARG_OID(0);
366  Oid arg2 = PG_GETARG_OID(1);
367 
368  PG_RETURN_BOOL(arg1 != arg2);
369 }
370 
371 Datum
373 {
374  Oid arg1 = PG_GETARG_OID(0);
375  Oid arg2 = PG_GETARG_OID(1);
376 
377  PG_RETURN_BOOL(arg1 < arg2);
378 }
379 
380 Datum
382 {
383  Oid arg1 = PG_GETARG_OID(0);
384  Oid arg2 = PG_GETARG_OID(1);
385 
386  PG_RETURN_BOOL(arg1 <= arg2);
387 }
388 
389 Datum
391 {
392  Oid arg1 = PG_GETARG_OID(0);
393  Oid arg2 = PG_GETARG_OID(1);
394 
395  PG_RETURN_BOOL(arg1 >= arg2);
396 }
397 
398 Datum
400 {
401  Oid arg1 = PG_GETARG_OID(0);
402  Oid arg2 = PG_GETARG_OID(1);
403 
404  PG_RETURN_BOOL(arg1 > arg2);
405 }
406 
407 Datum
409 {
410  Oid arg1 = PG_GETARG_OID(0);
411  Oid arg2 = PG_GETARG_OID(1);
412 
413  PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
414 }
415 
416 Datum
418 {
419  Oid arg1 = PG_GETARG_OID(0);
420  Oid arg2 = PG_GETARG_OID(1);
421 
422  PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
423 }
424 
425 Datum
427 {
429 
430  PG_RETURN_BOOL(cmp == 0);
431 }
432 
433 Datum
435 {
437 
438  PG_RETURN_BOOL(cmp != 0);
439 }
440 
441 Datum
443 {
445 
446  PG_RETURN_BOOL(cmp < 0);
447 }
448 
449 Datum
451 {
453 
454  PG_RETURN_BOOL(cmp <= 0);
455 }
456 
457 Datum
459 {
461 
462  PG_RETURN_BOOL(cmp >= 0);
463 }
464 
465 Datum
467 {
469 
470  PG_RETURN_BOOL(cmp > 0);
471 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: c.h:526
Datum oideq(PG_FUNCTION_ARGS)
Definition: oid.c:354
Datum array_send(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:1535
Oid oidparse(Node *node)
Definition: oid.c:314
Datum oidsmaller(PG_FUNCTION_ARGS)
Definition: oid.c:417
#define DatumGetInt32(X)
Definition: postgres.h:478
#define OIDOID
Definition: pg_type.h:328
static void pq_sendint32(StringInfo buf, int32 i)
Definition: pqformat.h:148
#define PointerGetDatum(X)
Definition: postgres.h:562
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
Datum oidvectorle(PG_FUNCTION_ARGS)
Definition: oid.c:450
Datum oidvectorne(PG_FUNCTION_ARGS)
Definition: oid.c:434
StringInfoData * StringInfo
Definition: stringinfo.h:43
Datum oidgt(PG_FUNCTION_ARGS)
Definition: oid.c:399
static Oid oidin_subr(const char *s, char **endloc)
Definition: oid.c:35
Definition: nodes.h:510
#define strVal(v)
Definition: value.h:54
int32 dataoffset
Definition: c.h:530
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum array_recv(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:1255
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:330
unsigned int Oid
Definition: postgres_ext.h:31
Datum oidout(PG_FUNCTION_ARGS)
Definition: oid.c:127
Datum oidge(PG_FUNCTION_ARGS)
Definition: oid.c:390
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
signed int int32
Definition: c.h:284
Datum oidsend(PG_FUNCTION_ARGS)
Definition: oid.c:151
Datum oidlarger(PG_FUNCTION_ARGS)
Definition: oid.c:408
#define ARR_LBOUND(a)
Definition: array.h:281
#define FUNC_MAX_ARGS
Datum oidrecv(PG_FUNCTION_ARGS)
Definition: oid.c:140
#define OidVectorSize(n)
Definition: oid.c:27
FmgrInfo * flinfo
Definition: fmgr.h:79
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Datum oidvectorge(PG_FUNCTION_ARGS)
Definition: oid.c:458
#define ARR_DIMS(a)
Definition: array.h:279
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:534
int dim1
Definition: c.h:532
Datum btoidvectorcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:287
#define ARR_HASNULL(a)
Definition: array.h:276
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
Datum oidvectorgt(PG_FUNCTION_ARGS)
Definition: oid.c:466
Datum oidvectorlt(PG_FUNCTION_ARGS)
Definition: oid.c:442
void * palloc0(Size size)
Definition: mcxt.c:877
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
Datum oidle(PG_FUNCTION_ARGS)
Definition: oid.c:381
#define InvalidOid
Definition: postgres_ext.h:36
Datum oidvectorrecv(PG_FUNCTION_ARGS)
Definition: oid.c:257
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define Assert(condition)
Definition: c.h:670
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
int oid_cmp(const void *p1, const void *p2)
Definition: oid.c:336
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
int lbound1
Definition: c.h:533
#define ARR_NDIM(a)
Definition: array.h:275
#define nodeTag(nodeptr)
Definition: nodes.h:515
#define DatumGetPointer(X)
Definition: postgres.h:555
Datum oidne(PG_FUNCTION_ARGS)
Definition: oid.c:363
Definition: nodes.h:283
#define Int32GetDatum(X)
Definition: postgres.h:485
#define intVal(v)
Definition: value.h:52
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid elemtype
Definition: c.h:531
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
Datum oidlt(PG_FUNCTION_ARGS)
Definition: oid.c:372
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
Datum oidin(PG_FUNCTION_ARGS)
Definition: oid.c:117
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define elog
Definition: elog.h:219
Datum oidvectorsend(PG_FUNCTION_ARGS)
Definition: oid.c:305
Datum oidvectorin(PG_FUNCTION_ARGS)
Definition: oid.c:194
Datum oidvectoreq(PG_FUNCTION_ARGS)
Definition: oid.c:426
int ndim
Definition: c.h:529
#define PG_RETURN_OID(x)
Definition: fmgr.h:320
#define ARR_ELEMTYPE(a)
Definition: array.h:277
Datum oidvectorout(PG_FUNCTION_ARGS)
Definition: oid.c:231
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742