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-2024, 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 5307686 : oidin(PG_FUNCTION_ARGS)
38 : {
39 5307686 : char *s = PG_GETARG_CSTRING(0);
40 : Oid result;
41 :
42 5307686 : result = uint32in_subr(s, NULL, "oid", fcinfo->context);
43 5307626 : PG_RETURN_OID(result);
44 : }
45 :
46 : Datum
47 12992674 : oidout(PG_FUNCTION_ARGS)
48 : {
49 12992674 : Oid o = PG_GETARG_OID(0);
50 12992674 : char *result = (char *) palloc(12);
51 :
52 12992674 : snprintf(result, 12, "%u", o);
53 12992674 : PG_RETURN_CSTRING(result);
54 : }
55 :
56 : /*
57 : * oidrecv - converts external binary format to oid
58 : */
59 : Datum
60 192 : oidrecv(PG_FUNCTION_ARGS)
61 : {
62 192 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
63 :
64 192 : 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 122690 : buildoidvector(const Oid *oids, int n)
88 : {
89 : oidvector *result;
90 :
91 122690 : result = (oidvector *) palloc0(OidVectorSize(n));
92 :
93 122690 : if (n > 0 && oids)
94 118126 : 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 122690 : SET_VARSIZE(result, OidVectorSize(n));
101 122690 : result->ndim = 1;
102 122690 : result->dataoffset = 0; /* never any nulls */
103 122690 : result->elemtype = OIDOID;
104 122690 : result->dim1 = n;
105 122690 : result->lbound1 = 0;
106 :
107 122690 : return result;
108 : }
109 :
110 : /*
111 : * oidvectorin - converts "num num ..." to internal form
112 : */
113 : Datum
114 302220 : oidvectorin(PG_FUNCTION_ARGS)
115 : {
116 302220 : char *oidString = PG_GETARG_CSTRING(0);
117 302220 : Node *escontext = fcinfo->context;
118 : oidvector *result;
119 : int nalloc;
120 : int n;
121 :
122 302220 : nalloc = 32; /* arbitrary initial size guess */
123 302220 : result = (oidvector *) palloc0(OidVectorSize(nalloc));
124 :
125 857454 : for (n = 0;; n++)
126 : {
127 1125000 : while (*oidString && isspace((unsigned char) *oidString))
128 267546 : oidString++;
129 857454 : if (*oidString == '\0')
130 302196 : break;
131 :
132 555258 : if (n >= nalloc)
133 : {
134 0 : nalloc *= 2;
135 0 : result = (oidvector *) repalloc(result, OidVectorSize(nalloc));
136 : }
137 :
138 555258 : result->values[n] = uint32in_subr(oidString, &oidString,
139 : "oid", escontext);
140 555258 : if (SOFT_ERROR_OCCURRED(escontext))
141 24 : PG_RETURN_NULL();
142 : }
143 :
144 302196 : SET_VARSIZE(result, OidVectorSize(n));
145 302196 : result->ndim = 1;
146 302196 : result->dataoffset = 0; /* never any nulls */
147 302196 : result->elemtype = OIDOID;
148 302196 : result->dim1 = n;
149 302196 : result->lbound1 = 0;
150 :
151 302196 : PG_RETURN_POINTER(result);
152 : }
153 :
154 : /*
155 : * oidvectorout - converts internal form to "num num ..."
156 : */
157 : Datum
158 39380 : oidvectorout(PG_FUNCTION_ARGS)
159 : {
160 39380 : oidvector *oidArray = (oidvector *) PG_GETARG_POINTER(0);
161 : int num,
162 39380 : nnums = oidArray->dim1;
163 : char *rp;
164 : char *result;
165 :
166 : /* assumes sign, 10 digits, ' ' */
167 39380 : rp = result = (char *) palloc(nnums * 12 + 1);
168 104240 : for (num = 0; num < nnums; num++)
169 : {
170 64860 : if (num != 0)
171 29026 : *rp++ = ' ';
172 64860 : sprintf(rp, "%u", oidArray->values[num]);
173 185512 : while (*++rp != '\0')
174 : ;
175 : }
176 39380 : *rp = '\0';
177 39380 : PG_RETURN_CSTRING(result);
178 : }
179 :
180 : /*
181 : * oidvectorrecv - converts external binary format to oidvector
182 : */
183 : Datum
184 0 : oidvectorrecv(PG_FUNCTION_ARGS)
185 : {
186 0 : LOCAL_FCINFO(locfcinfo, 3);
187 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
188 : oidvector *result;
189 :
190 : /*
191 : * Normally one would call array_recv() using DirectFunctionCall3, but
192 : * that does not work since array_recv wants to cache some data using
193 : * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
194 : * parameter.
195 : */
196 0 : InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
197 : InvalidOid, NULL, NULL);
198 :
199 0 : locfcinfo->args[0].value = PointerGetDatum(buf);
200 0 : locfcinfo->args[0].isnull = false;
201 0 : locfcinfo->args[1].value = ObjectIdGetDatum(OIDOID);
202 0 : locfcinfo->args[1].isnull = false;
203 0 : locfcinfo->args[2].value = Int32GetDatum(-1);
204 0 : locfcinfo->args[2].isnull = false;
205 :
206 0 : result = (oidvector *) DatumGetPointer(array_recv(locfcinfo));
207 :
208 : Assert(!locfcinfo->isnull);
209 :
210 : /* sanity checks: oidvector must be 1-D, 0-based, no nulls */
211 0 : if (ARR_NDIM(result) != 1 ||
212 0 : ARR_HASNULL(result) ||
213 0 : ARR_ELEMTYPE(result) != OIDOID ||
214 0 : ARR_LBOUND(result)[0] != 0)
215 0 : ereport(ERROR,
216 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
217 : errmsg("invalid oidvector data")));
218 :
219 0 : PG_RETURN_POINTER(result);
220 : }
221 :
222 : /*
223 : * oidvectorsend - converts oidvector to binary format
224 : */
225 : Datum
226 0 : oidvectorsend(PG_FUNCTION_ARGS)
227 : {
228 0 : return array_send(fcinfo);
229 : }
230 :
231 : /*
232 : * oidparse - get OID from ICONST/FCONST node
233 : */
234 : Oid
235 134 : oidparse(Node *node)
236 : {
237 134 : switch (nodeTag(node))
238 : {
239 122 : case T_Integer:
240 122 : return intVal(node);
241 12 : case T_Float:
242 :
243 : /*
244 : * Values too large for int4 will be represented as Float
245 : * constants by the lexer. Accept these if they are valid OID
246 : * strings.
247 : */
248 12 : return uint32in_subr(castNode(Float, node)->fval, NULL,
249 : "oid", NULL);
250 0 : default:
251 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
252 : }
253 : return InvalidOid; /* keep compiler quiet */
254 : }
255 :
256 : /* qsort comparison function for Oids */
257 : int
258 422898 : oid_cmp(const void *p1, const void *p2)
259 : {
260 422898 : Oid v1 = *((const Oid *) p1);
261 422898 : Oid v2 = *((const Oid *) p2);
262 :
263 422898 : return pg_cmp_u32(v1, v2);
264 : }
265 :
266 :
267 : /*****************************************************************************
268 : * PUBLIC ROUTINES *
269 : *****************************************************************************/
270 :
271 : Datum
272 125431044 : oideq(PG_FUNCTION_ARGS)
273 : {
274 125431044 : Oid arg1 = PG_GETARG_OID(0);
275 125431044 : Oid arg2 = PG_GETARG_OID(1);
276 :
277 125431044 : PG_RETURN_BOOL(arg1 == arg2);
278 : }
279 :
280 : Datum
281 2474832 : oidne(PG_FUNCTION_ARGS)
282 : {
283 2474832 : Oid arg1 = PG_GETARG_OID(0);
284 2474832 : Oid arg2 = PG_GETARG_OID(1);
285 :
286 2474832 : PG_RETURN_BOOL(arg1 != arg2);
287 : }
288 :
289 : Datum
290 4791266 : oidlt(PG_FUNCTION_ARGS)
291 : {
292 4791266 : Oid arg1 = PG_GETARG_OID(0);
293 4791266 : Oid arg2 = PG_GETARG_OID(1);
294 :
295 4791266 : PG_RETURN_BOOL(arg1 < arg2);
296 : }
297 :
298 : Datum
299 1713072 : oidle(PG_FUNCTION_ARGS)
300 : {
301 1713072 : Oid arg1 = PG_GETARG_OID(0);
302 1713072 : Oid arg2 = PG_GETARG_OID(1);
303 :
304 1713072 : PG_RETURN_BOOL(arg1 <= arg2);
305 : }
306 :
307 : Datum
308 15710 : oidge(PG_FUNCTION_ARGS)
309 : {
310 15710 : Oid arg1 = PG_GETARG_OID(0);
311 15710 : Oid arg2 = PG_GETARG_OID(1);
312 :
313 15710 : PG_RETURN_BOOL(arg1 >= arg2);
314 : }
315 :
316 : Datum
317 353840 : oidgt(PG_FUNCTION_ARGS)
318 : {
319 353840 : Oid arg1 = PG_GETARG_OID(0);
320 353840 : Oid arg2 = PG_GETARG_OID(1);
321 :
322 353840 : PG_RETURN_BOOL(arg1 > arg2);
323 : }
324 :
325 : Datum
326 0 : oidlarger(PG_FUNCTION_ARGS)
327 : {
328 0 : Oid arg1 = PG_GETARG_OID(0);
329 0 : Oid arg2 = PG_GETARG_OID(1);
330 :
331 0 : PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
332 : }
333 :
334 : Datum
335 0 : oidsmaller(PG_FUNCTION_ARGS)
336 : {
337 0 : Oid arg1 = PG_GETARG_OID(0);
338 0 : Oid arg2 = PG_GETARG_OID(1);
339 :
340 0 : PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
341 : }
342 :
343 : Datum
344 32618 : oidvectoreq(PG_FUNCTION_ARGS)
345 : {
346 32618 : int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
347 :
348 32618 : PG_RETURN_BOOL(cmp == 0);
349 : }
350 :
351 : Datum
352 21828 : oidvectorne(PG_FUNCTION_ARGS)
353 : {
354 21828 : int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
355 :
356 21828 : PG_RETURN_BOOL(cmp != 0);
357 : }
358 :
359 : Datum
360 3684 : oidvectorlt(PG_FUNCTION_ARGS)
361 : {
362 3684 : int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
363 :
364 3684 : PG_RETURN_BOOL(cmp < 0);
365 : }
366 :
367 : Datum
368 1272 : oidvectorle(PG_FUNCTION_ARGS)
369 : {
370 1272 : int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
371 :
372 1272 : PG_RETURN_BOOL(cmp <= 0);
373 : }
374 :
375 : Datum
376 0 : oidvectorge(PG_FUNCTION_ARGS)
377 : {
378 0 : int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
379 :
380 0 : PG_RETURN_BOOL(cmp >= 0);
381 : }
382 :
383 : Datum
384 0 : oidvectorgt(PG_FUNCTION_ARGS)
385 : {
386 0 : int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
387 :
388 0 : PG_RETURN_BOOL(cmp > 0);
389 : }
|