PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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_sendint(&buf, arg1, sizeof(Oid));
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 
335 /*****************************************************************************
336  * PUBLIC ROUTINES *
337  *****************************************************************************/
338 
339 Datum
341 {
342  Oid arg1 = PG_GETARG_OID(0);
343  Oid arg2 = PG_GETARG_OID(1);
344 
345  PG_RETURN_BOOL(arg1 == arg2);
346 }
347 
348 Datum
350 {
351  Oid arg1 = PG_GETARG_OID(0);
352  Oid arg2 = PG_GETARG_OID(1);
353 
354  PG_RETURN_BOOL(arg1 != arg2);
355 }
356 
357 Datum
359 {
360  Oid arg1 = PG_GETARG_OID(0);
361  Oid arg2 = PG_GETARG_OID(1);
362 
363  PG_RETURN_BOOL(arg1 < arg2);
364 }
365 
366 Datum
368 {
369  Oid arg1 = PG_GETARG_OID(0);
370  Oid arg2 = PG_GETARG_OID(1);
371 
372  PG_RETURN_BOOL(arg1 <= arg2);
373 }
374 
375 Datum
377 {
378  Oid arg1 = PG_GETARG_OID(0);
379  Oid arg2 = PG_GETARG_OID(1);
380 
381  PG_RETURN_BOOL(arg1 >= arg2);
382 }
383 
384 Datum
386 {
387  Oid arg1 = PG_GETARG_OID(0);
388  Oid arg2 = PG_GETARG_OID(1);
389 
390  PG_RETURN_BOOL(arg1 > arg2);
391 }
392 
393 Datum
395 {
396  Oid arg1 = PG_GETARG_OID(0);
397  Oid arg2 = PG_GETARG_OID(1);
398 
399  PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
400 }
401 
402 Datum
404 {
405  Oid arg1 = PG_GETARG_OID(0);
406  Oid arg2 = PG_GETARG_OID(1);
407 
408  PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
409 }
410 
411 Datum
413 {
415 
416  PG_RETURN_BOOL(cmp == 0);
417 }
418 
419 Datum
421 {
423 
424  PG_RETURN_BOOL(cmp != 0);
425 }
426 
427 Datum
429 {
431 
432  PG_RETURN_BOOL(cmp < 0);
433 }
434 
435 Datum
437 {
439 
440  PG_RETURN_BOOL(cmp <= 0);
441 }
442 
443 Datum
445 {
447 
448  PG_RETURN_BOOL(cmp >= 0);
449 }
450 
451 Datum
453 {
455 
456  PG_RETURN_BOOL(cmp > 0);
457 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Definition: c.h:473
Datum oideq(PG_FUNCTION_ARGS)
Definition: oid.c:340
Datum array_send(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:1534
Oid oidparse(Node *node)
Definition: oid.c:314
Datum oidsmaller(PG_FUNCTION_ARGS)
Definition: oid.c:403
#define DatumGetInt32(X)
Definition: postgres.h:480
#define OIDOID
Definition: pg_type.h:328
#define PointerGetDatum(X)
Definition: postgres.h:564
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:359
Datum oidvectorle(PG_FUNCTION_ARGS)
Definition: oid.c:436
Datum oidvectorne(PG_FUNCTION_ARGS)
Definition: oid.c:420
StringInfoData * StringInfo
Definition: stringinfo.h:46
Datum oidgt(PG_FUNCTION_ARGS)
Definition: oid.c:385
static Oid oidin_subr(const char *s, char **endloc)
Definition: oid.c:35
Definition: nodes.h:508
#define strVal(v)
Definition: value.h:54
int32 dataoffset
Definition: c.h:477
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:232
Datum array_recv(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:1254
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:313
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:376
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:379
signed int int32
Definition: c.h:253
Datum oidsend(PG_FUNCTION_ARGS)
Definition: oid.c:151
Datum oidlarger(PG_FUNCTION_ARGS)
Definition: oid.c:394
#define ARR_LBOUND(a)
Definition: array.h:277
#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:71
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Datum oidvectorge(PG_FUNCTION_ARGS)
Definition: oid.c:444
#define ARR_DIMS(a)
Definition: array.h:275
static char * buf
Definition: pg_test_fsync.c:65
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:481
int dim1
Definition: c.h:479
Datum btoidvectorcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:287
#define ARR_HASNULL(a)
Definition: array.h:272
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define ereport(elevel, rest)
Definition: elog.h:122
Datum oidvectorgt(PG_FUNCTION_ARGS)
Definition: oid.c:452
Datum oidvectorlt(PG_FUNCTION_ARGS)
Definition: oid.c:428
void * palloc0(Size size)
Definition: mcxt.c:920
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
uintptr_t Datum
Definition: postgres.h:374
Datum oidle(PG_FUNCTION_ARGS)
Definition: oid.c:367
#define InvalidOid
Definition: postgres_ext.h:36
Datum oidvectorrecv(PG_FUNCTION_ARGS)
Definition: oid.c:257
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#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:306
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
int lbound1
Definition: c.h:480
#define ARR_NDIM(a)
Definition: array.h:271
#define nodeTag(nodeptr)
Definition: nodes.h:513
#define DatumGetPointer(X)
Definition: postgres.h:557
Datum oidne(PG_FUNCTION_ARGS)
Definition: oid.c:349
Definition: nodes.h:287
#define Int32GetDatum(X)
Definition: postgres.h:487
#define intVal(v)
Definition: value.h:52
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid elemtype
Definition: c.h:478
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:233
Datum oidlt(PG_FUNCTION_ARGS)
Definition: oid.c:358
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
Datum oidin(PG_FUNCTION_ARGS)
Definition: oid.c:117
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:448
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#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:412
int ndim
Definition: c.h:476
#define PG_RETURN_OID(x)
Definition: fmgr.h:304
#define ARR_ELEMTYPE(a)
Definition: array.h:273
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