]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/oid.c
Pgindent run for 8.0.
[postgresql] / src / backend / utils / adt / oid.c
1 /*-------------------------------------------------------------------------
2  *
3  * oid.c
4  *        Functions for the built-in type Oid ... also oidvector.
5  *
6  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.59 2004/08/29 05:06:49 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <limits.h>
20
21 #include "libpq/pqformat.h"
22 #include "utils/builtins.h"
23
24
25 /*****************************************************************************
26  *       USER I/O ROUTINES                                                                                                               *
27  *****************************************************************************/
28
29 static Oid
30 oidin_subr(const char *funcname, const char *s, char **endloc)
31 {
32         unsigned long cvt;
33         char       *endptr;
34         Oid                     result;
35
36         /*
37          * In releases prior to 8.0, we accepted an empty string as valid
38          * input (yielding an OID of 0). In 8.0, we accept empty strings, but
39          * emit a warning noting that the feature is deprecated. In 8.1+, the
40          * warning should be replaced by an error.
41          */
42         if (*s == '\0')
43                 ereport(WARNING,
44                                 (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
45                                  errmsg("deprecated input syntax for type oid: \"\""),
46                                  errdetail("This input will be rejected in "
47                                                    "a future release of PostgreSQL.")));
48
49         errno = 0;
50         cvt = strtoul(s, &endptr, 10);
51
52         /*
53          * strtoul() normally only sets ERANGE.  On some systems it also may
54          * set EINVAL, which simply means it couldn't parse the input string.
55          * This is handled by the second "if" consistent across platforms.
56          */
57         if (errno && errno != ERANGE && errno != EINVAL)
58                 ereport(ERROR,
59                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
60                                  errmsg("invalid input syntax for type oid: \"%s\"",
61                                                 s)));
62
63         if (endptr == s && *s != '\0')
64                 ereport(ERROR,
65                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
66                                  errmsg("invalid input syntax for type oid: \"%s\"",
67                                                 s)));
68
69         if (errno == ERANGE)
70                 ereport(ERROR,
71                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
72                                  errmsg("value \"%s\" is out of range for type oid", s)));
73
74         if (endloc)
75         {
76                 /* caller wants to deal with rest of string */
77                 *endloc = endptr;
78         }
79         else
80         {
81                 /* allow only whitespace after number */
82                 while (*endptr && isspace((unsigned char) *endptr))
83                         endptr++;
84                 if (*endptr)
85                         ereport(ERROR,
86                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
87                                          errmsg("invalid input syntax for type oid: \"%s\"",
88                                                         s)));
89         }
90
91         result = (Oid) cvt;
92
93         /*
94          * Cope with possibility that unsigned long is wider than Oid, in
95          * which case strtoul will not raise an error for some values that are
96          * out of the range of Oid.
97          *
98          * For backwards compatibility, we want to accept inputs that are given
99          * with a minus sign, so allow the input value if it matches after
100          * either signed or unsigned extension to long.
101          *
102          * To ensure consistent results on 32-bit and 64-bit platforms, make sure
103          * the error message is the same as if strtoul() had returned ERANGE.
104          */
105 #if OID_MAX != ULONG_MAX
106         if (cvt != (unsigned long) result &&
107                 cvt != (unsigned long) ((int) result))
108                 ereport(ERROR,
109                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
110                                  errmsg("value \"%s\" is out of range for type oid", s)));
111 #endif
112
113         return result;
114 }
115
116 Datum
117 oidin(PG_FUNCTION_ARGS)
118 {
119         char       *s = PG_GETARG_CSTRING(0);
120         Oid                     result;
121
122         result = oidin_subr("oidin", s, NULL);
123         PG_RETURN_OID(result);
124 }
125
126 Datum
127 oidout(PG_FUNCTION_ARGS)
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
140 oidrecv(PG_FUNCTION_ARGS)
141 {
142         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
143
144         PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
145 }
146
147 /*
148  *              oidsend                 - converts oid to binary format
149  */
150 Datum
151 oidsend(PG_FUNCTION_ARGS)
152 {
153         Oid                     arg1 = PG_GETARG_OID(0);
154         StringInfoData buf;
155
156         pq_begintypsend(&buf);
157         pq_sendint(&buf, arg1, sizeof(Oid));
158         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
159 }
160
161
162 /*
163  *              oidvectorin                     - converts "num num ..." to internal form
164  *
165  *              Note:
166  *                              Fills any unsupplied positions with InvalidOid.
167  */
168 Datum
169 oidvectorin(PG_FUNCTION_ARGS)
170 {
171         char       *oidString = PG_GETARG_CSTRING(0);
172         Oid                *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
173         int                     slot;
174
175         for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
176         {
177                 while (*oidString && isspace((unsigned char) *oidString))
178                         oidString++;
179                 if (*oidString == '\0')
180                         break;
181                 result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
182         }
183         while (*oidString && isspace((unsigned char) *oidString))
184                 oidString++;
185         if (*oidString)
186                 ereport(ERROR,
187                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
188                                  errmsg("oidvector has too many elements")));
189         while (slot < INDEX_MAX_KEYS)
190                 result[slot++] = InvalidOid;
191
192         PG_RETURN_POINTER(result);
193 }
194
195 /*
196  *              oidvectorout - converts internal form to "num num ..."
197  */
198 Datum
199 oidvectorout(PG_FUNCTION_ARGS)
200 {
201         Oid                *oidArray = (Oid *) PG_GETARG_POINTER(0);
202         int                     num,
203                                 maxnum;
204         char       *rp;
205         char       *result;
206
207         /* find last non-zero value in vector */
208         for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
209                 if (oidArray[maxnum] != 0)
210                         break;
211
212         /* assumes sign, 10 digits, ' ' */
213         rp = result = (char *) palloc((maxnum + 1) * 12 + 1);
214         for (num = 0; num <= maxnum; num++)
215         {
216                 if (num != 0)
217                         *rp++ = ' ';
218                 sprintf(rp, "%u", oidArray[num]);
219                 while (*++rp != '\0')
220                         ;
221         }
222         *rp = '\0';
223         PG_RETURN_CSTRING(result);
224 }
225
226 /*
227  *              oidvectorrecv                   - converts external binary format to oidvector
228  */
229 Datum
230 oidvectorrecv(PG_FUNCTION_ARGS)
231 {
232         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
233         Oid                *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
234         int                     slot;
235
236         for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
237                 result[slot] = (Oid) pq_getmsgint(buf, sizeof(Oid));
238         PG_RETURN_POINTER(result);
239 }
240
241 /*
242  *              oidvectorsend                   - converts oidvector to binary format
243  */
244 Datum
245 oidvectorsend(PG_FUNCTION_ARGS)
246 {
247         Oid                *oidArray = (Oid *) PG_GETARG_POINTER(0);
248         StringInfoData buf;
249         int                     slot;
250
251         pq_begintypsend(&buf);
252         for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
253                 pq_sendint(&buf, oidArray[slot], sizeof(Oid));
254         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
255 }
256
257
258 /*****************************************************************************
259  *       PUBLIC ROUTINES                                                                                                                 *
260  *****************************************************************************/
261
262 Datum
263 oideq(PG_FUNCTION_ARGS)
264 {
265         Oid                     arg1 = PG_GETARG_OID(0);
266         Oid                     arg2 = PG_GETARG_OID(1);
267
268         PG_RETURN_BOOL(arg1 == arg2);
269 }
270
271 Datum
272 oidne(PG_FUNCTION_ARGS)
273 {
274         Oid                     arg1 = PG_GETARG_OID(0);
275         Oid                     arg2 = PG_GETARG_OID(1);
276
277         PG_RETURN_BOOL(arg1 != arg2);
278 }
279
280 Datum
281 oidlt(PG_FUNCTION_ARGS)
282 {
283         Oid                     arg1 = PG_GETARG_OID(0);
284         Oid                     arg2 = PG_GETARG_OID(1);
285
286         PG_RETURN_BOOL(arg1 < arg2);
287 }
288
289 Datum
290 oidle(PG_FUNCTION_ARGS)
291 {
292         Oid                     arg1 = PG_GETARG_OID(0);
293         Oid                     arg2 = PG_GETARG_OID(1);
294
295         PG_RETURN_BOOL(arg1 <= arg2);
296 }
297
298 Datum
299 oidge(PG_FUNCTION_ARGS)
300 {
301         Oid                     arg1 = PG_GETARG_OID(0);
302         Oid                     arg2 = PG_GETARG_OID(1);
303
304         PG_RETURN_BOOL(arg1 >= arg2);
305 }
306
307 Datum
308 oidgt(PG_FUNCTION_ARGS)
309 {
310         Oid                     arg1 = PG_GETARG_OID(0);
311         Oid                     arg2 = PG_GETARG_OID(1);
312
313         PG_RETURN_BOOL(arg1 > arg2);
314 }
315
316 Datum
317 oidlarger(PG_FUNCTION_ARGS)
318 {
319         Oid                     arg1 = PG_GETARG_OID(0);
320         Oid                     arg2 = PG_GETARG_OID(1);
321
322         PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
323 }
324
325 Datum
326 oidsmaller(PG_FUNCTION_ARGS)
327 {
328         Oid                     arg1 = PG_GETARG_OID(0);
329         Oid                     arg2 = PG_GETARG_OID(1);
330
331         PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
332 }
333
334 Datum
335 oidvectoreq(PG_FUNCTION_ARGS)
336 {
337         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
338         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
339
340         PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(Oid)) == 0);
341 }
342
343 Datum
344 oidvectorne(PG_FUNCTION_ARGS)
345 {
346         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
347         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
348
349         PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(Oid)) != 0);
350 }
351
352 Datum
353 oidvectorlt(PG_FUNCTION_ARGS)
354 {
355         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
356         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
357         int                     i;
358
359         for (i = 0; i < INDEX_MAX_KEYS; i++)
360                 if (arg1[i] != arg2[i])
361                         PG_RETURN_BOOL(arg1[i] < arg2[i]);
362         PG_RETURN_BOOL(false);
363 }
364
365 Datum
366 oidvectorle(PG_FUNCTION_ARGS)
367 {
368         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
369         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
370         int                     i;
371
372         for (i = 0; i < INDEX_MAX_KEYS; i++)
373                 if (arg1[i] != arg2[i])
374                         PG_RETURN_BOOL(arg1[i] <= arg2[i]);
375         PG_RETURN_BOOL(true);
376 }
377
378 Datum
379 oidvectorge(PG_FUNCTION_ARGS)
380 {
381         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
382         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
383         int                     i;
384
385         for (i = 0; i < INDEX_MAX_KEYS; i++)
386                 if (arg1[i] != arg2[i])
387                         PG_RETURN_BOOL(arg1[i] >= arg2[i]);
388         PG_RETURN_BOOL(true);
389 }
390
391 Datum
392 oidvectorgt(PG_FUNCTION_ARGS)
393 {
394         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
395         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
396         int                     i;
397
398         for (i = 0; i < INDEX_MAX_KEYS; i++)
399                 if (arg1[i] != arg2[i])
400                         PG_RETURN_BOOL(arg1[i] > arg2[i]);
401         PG_RETURN_BOOL(false);
402 }
403
404 Datum
405 oid_text(PG_FUNCTION_ARGS)
406 {
407         Oid                     oid = PG_GETARG_OID(0);
408         text       *result;
409         int                     len;
410         char       *str;
411
412         str = DatumGetCString(DirectFunctionCall1(oidout,
413                                                                                           ObjectIdGetDatum(oid)));
414         len = strlen(str) + VARHDRSZ;
415
416         result = (text *) palloc(len);
417
418         VARATT_SIZEP(result) = len;
419         memcpy(VARDATA(result), str, (len - VARHDRSZ));
420         pfree(str);
421
422         PG_RETURN_TEXT_P(result);
423 }
424
425 Datum
426 text_oid(PG_FUNCTION_ARGS)
427 {
428         text       *string = PG_GETARG_TEXT_P(0);
429         Oid                     result;
430         int                     len;
431         char       *str;
432
433         len = (VARSIZE(string) - VARHDRSZ);
434
435         str = palloc(len + 1);
436         memcpy(str, VARDATA(string), len);
437         *(str + len) = '\0';
438
439         result = oidin_subr("text_oid", str, NULL);
440
441         pfree(str);
442
443         PG_RETURN_OID(result);
444 }