1 /*-------------------------------------------------------------------------
4 * Functions for the built-in type Oid ... also oidvector.
6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/adt/oid.c
13 *-------------------------------------------------------------------------
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"
27 #define OidVectorSize(n) (offsetof(oidvector, values) + (n) * sizeof(Oid))
30 /*****************************************************************************
32 *****************************************************************************/
35 oidin_subr(const char *s, char **endloc)
43 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
44 errmsg("invalid input syntax for type %s: \"%s\"",
48 cvt = strtoul(s, &endptr, 10);
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.
55 if (errno && errno != ERANGE && errno != EINVAL)
57 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
58 errmsg("invalid input syntax for type %s: \"%s\"",
61 if (endptr == s && *s != '\0')
63 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
64 errmsg("invalid input syntax for type %s: \"%s\"",
69 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
70 errmsg("value \"%s\" is out of range for type %s",
75 /* caller wants to deal with rest of string */
80 /* allow only whitespace after number */
81 while (*endptr && isspace((unsigned char) *endptr))
85 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
86 errmsg("invalid input syntax for type %s: \"%s\"",
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
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.
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.
104 #if OID_MAX != ULONG_MAX
105 if (cvt != (unsigned long) result &&
106 cvt != (unsigned long) ((int) result))
108 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109 errmsg("value \"%s\" is out of range for type %s",
117 oidin(PG_FUNCTION_ARGS)
119 char *s = PG_GETARG_CSTRING(0);
122 result = oidin_subr(s, NULL);
123 PG_RETURN_OID(result);
127 oidout(PG_FUNCTION_ARGS)
129 Oid o = PG_GETARG_OID(0);
130 char *result = (char *) palloc(12);
132 snprintf(result, 12, "%u", o);
133 PG_RETURN_CSTRING(result);
137 * oidrecv - converts external binary format to oid
140 oidrecv(PG_FUNCTION_ARGS)
142 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
144 PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
148 * oidsend - converts oid to binary format
151 oidsend(PG_FUNCTION_ARGS)
153 Oid arg1 = PG_GETARG_OID(0);
156 pq_begintypsend(&buf);
157 pq_sendint(&buf, arg1, sizeof(Oid));
158 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
162 * construct oidvector given a raw array of Oids
164 * If oids is NULL then caller must fill values[] afterward
167 buildoidvector(const Oid *oids, int n)
171 result = (oidvector *) palloc0(OidVectorSize(n));
174 memcpy(result->values, oids, n * sizeof(Oid));
177 * Attach standard array header. For historical reasons, we set the index
178 * lower bound to 0 not 1.
180 SET_VARSIZE(result, OidVectorSize(n));
182 result->dataoffset = 0; /* never any nulls */
183 result->elemtype = OIDOID;
191 * oidvectorin - converts "num num ..." to internal form
194 oidvectorin(PG_FUNCTION_ARGS)
196 char *oidString = PG_GETARG_CSTRING(0);
200 result = (oidvector *) palloc0(OidVectorSize(FUNC_MAX_ARGS));
202 for (n = 0; n < FUNC_MAX_ARGS; n++)
204 while (*oidString && isspace((unsigned char) *oidString))
206 if (*oidString == '\0')
208 result->values[n] = oidin_subr(oidString, &oidString);
210 while (*oidString && isspace((unsigned char) *oidString))
214 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
215 errmsg("oidvector has too many elements")));
217 SET_VARSIZE(result, OidVectorSize(n));
219 result->dataoffset = 0; /* never any nulls */
220 result->elemtype = OIDOID;
224 PG_RETURN_POINTER(result);
228 * oidvectorout - converts internal form to "num num ..."
231 oidvectorout(PG_FUNCTION_ARGS)
233 oidvector *oidArray = (oidvector *) PG_GETARG_POINTER(0);
235 nnums = oidArray->dim1;
239 /* assumes sign, 10 digits, ' ' */
240 rp = result = (char *) palloc(nnums * 12 + 1);
241 for (num = 0; num < nnums; num++)
245 sprintf(rp, "%u", oidArray->values[num]);
246 while (*++rp != '\0')
250 PG_RETURN_CSTRING(result);
254 * oidvectorrecv - converts external binary format to oidvector
257 oidvectorrecv(PG_FUNCTION_ARGS)
259 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
260 FunctionCallInfoData locfcinfo;
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
269 InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
270 InvalidOid, NULL, NULL);
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;
279 result = (oidvector *) DatumGetPointer(array_recv(&locfcinfo));
281 Assert(!locfcinfo.isnull);
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)
289 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
290 errmsg("invalid oidvector data")));
292 /* check length for consistency with oidvectorin() */
293 if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
295 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
296 errmsg("oidvector has too many elements")));
298 PG_RETURN_POINTER(result);
302 * oidvectorsend - converts oidvector to binary format
305 oidvectorsend(PG_FUNCTION_ARGS)
307 return array_send(fcinfo);
311 * oidparse - get OID from IConst/FConst node
316 switch (nodeTag(node))
323 * Values too large for int4 will be represented as Float
324 * constants by the lexer. Accept these if they are valid OID
327 return oidin_subr(strVal(node), NULL);
329 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
331 return InvalidOid; /* keep compiler quiet */
334 /* qsort comparison function for Oids */
336 oid_cmp(const void *p1, const void *p2)
338 Oid v1 = *((const Oid *) p1);
339 Oid v2 = *((const Oid *) p2);
349 /*****************************************************************************
351 *****************************************************************************/
354 oideq(PG_FUNCTION_ARGS)
356 Oid arg1 = PG_GETARG_OID(0);
357 Oid arg2 = PG_GETARG_OID(1);
359 PG_RETURN_BOOL(arg1 == arg2);
363 oidne(PG_FUNCTION_ARGS)
365 Oid arg1 = PG_GETARG_OID(0);
366 Oid arg2 = PG_GETARG_OID(1);
368 PG_RETURN_BOOL(arg1 != arg2);
372 oidlt(PG_FUNCTION_ARGS)
374 Oid arg1 = PG_GETARG_OID(0);
375 Oid arg2 = PG_GETARG_OID(1);
377 PG_RETURN_BOOL(arg1 < arg2);
381 oidle(PG_FUNCTION_ARGS)
383 Oid arg1 = PG_GETARG_OID(0);
384 Oid arg2 = PG_GETARG_OID(1);
386 PG_RETURN_BOOL(arg1 <= arg2);
390 oidge(PG_FUNCTION_ARGS)
392 Oid arg1 = PG_GETARG_OID(0);
393 Oid arg2 = PG_GETARG_OID(1);
395 PG_RETURN_BOOL(arg1 >= arg2);
399 oidgt(PG_FUNCTION_ARGS)
401 Oid arg1 = PG_GETARG_OID(0);
402 Oid arg2 = PG_GETARG_OID(1);
404 PG_RETURN_BOOL(arg1 > arg2);
408 oidlarger(PG_FUNCTION_ARGS)
410 Oid arg1 = PG_GETARG_OID(0);
411 Oid arg2 = PG_GETARG_OID(1);
413 PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
417 oidsmaller(PG_FUNCTION_ARGS)
419 Oid arg1 = PG_GETARG_OID(0);
420 Oid arg2 = PG_GETARG_OID(1);
422 PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
426 oidvectoreq(PG_FUNCTION_ARGS)
428 int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
430 PG_RETURN_BOOL(cmp == 0);
434 oidvectorne(PG_FUNCTION_ARGS)
436 int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
438 PG_RETURN_BOOL(cmp != 0);
442 oidvectorlt(PG_FUNCTION_ARGS)
444 int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
446 PG_RETURN_BOOL(cmp < 0);
450 oidvectorle(PG_FUNCTION_ARGS)
452 int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
454 PG_RETURN_BOOL(cmp <= 0);
458 oidvectorge(PG_FUNCTION_ARGS)
460 int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
462 PG_RETURN_BOOL(cmp >= 0);
466 oidvectorgt(PG_FUNCTION_ARGS)
468 int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
470 PG_RETURN_BOOL(cmp > 0);