]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/oid.c
sum() on int2 and int4 columns now uses an int8, not numeric, accumulator
[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-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.46 2001/08/14 22:21:58 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <limits.h>
20
21 #include "utils/builtins.h"
22
23 /*****************************************************************************
24  *       USER I/O ROUTINES                                                                                                               *
25  *****************************************************************************/
26
27 static Oid
28 oidin_subr(const char *funcname, const char *s, char **endloc)
29 {
30         unsigned long cvt;
31         char       *endptr;
32         Oid                     result;
33
34         errno = 0;
35
36         cvt = strtoul(s, &endptr, 10);
37
38         /*
39          * strtoul() normally only sets ERANGE.  On some systems it also may
40          * set EINVAL, which simply means it couldn't parse the input string.
41          * This is handled by the second "if" consistent across platforms.
42          * Note that for historical reasons we accept an empty string as
43          * meaning 0.
44          */
45         if (errno && errno != EINVAL)
46                 elog(ERROR, "%s: error reading \"%s\": %m",
47                          funcname, s);
48         if (endptr == s && *endptr)
49                 elog(ERROR, "%s: error in \"%s\": can't parse \"%s\"",
50                          funcname, s, endptr);
51
52         if (endloc)
53         {
54                 /* caller wants to deal with rest of string */
55                 *endloc = endptr;
56         }
57         else
58         {
59                 /* allow only whitespace after number */
60                 while (*endptr && isspace((unsigned char) *endptr))
61                         endptr++;
62                 if (*endptr)
63                         elog(ERROR, "%s: error in \"%s\": can't parse \"%s\"",
64                                  funcname, s, endptr);
65         }
66
67         result = (Oid) cvt;
68
69         /*
70          * Cope with possibility that unsigned long is wider than Oid, in
71          * which case strtoul will not raise an error for some values that are
72          * out of the range of Oid.
73          *
74          * For backwards compatibility, we want to accept inputs that are given
75          * with a minus sign, so allow the input value if it matches after
76          * either signed or unsigned extension to long.
77          *
78          * To ensure consistent results on 32-bit and 64-bit platforms, make sure
79          * the error message is the same as if strtoul() had returned ERANGE.
80          */
81 #if OID_MAX != ULONG_MAX
82         if (cvt != (unsigned long) result &&
83                 cvt != (unsigned long) ((int) result))
84                 elog(ERROR, "%s: error reading \"%s\": %s",
85                          funcname, s, strerror(ERANGE));
86 #endif
87
88         return result;
89 }
90
91 Datum
92 oidin(PG_FUNCTION_ARGS)
93 {
94         char       *s = PG_GETARG_CSTRING(0);
95         Oid                     result;
96
97         result = oidin_subr("oidin", s, NULL);
98         PG_RETURN_OID(result);
99 }
100
101 Datum
102 oidout(PG_FUNCTION_ARGS)
103 {
104         Oid                     o = PG_GETARG_OID(0);
105         char       *result = (char *) palloc(12);
106
107         snprintf(result, 12, "%u", o);
108         PG_RETURN_CSTRING(result);
109 }
110
111
112 /*
113  *              oidvectorin                     - converts "num num ..." to internal form
114  *
115  *              Note:
116  *                              Fills any unsupplied positions with InvalidOid.
117  */
118 Datum
119 oidvectorin(PG_FUNCTION_ARGS)
120 {
121         char       *oidString = PG_GETARG_CSTRING(0);
122         Oid                *result;
123         int                     slot;
124
125         result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
126
127         for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
128         {
129                 while (*oidString && isspace((unsigned char) *oidString))
130                         oidString++;
131                 if (*oidString == '\0')
132                         break;
133                 result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
134         }
135         while (*oidString && isspace((unsigned char) *oidString))
136                 oidString++;
137         if (*oidString)
138                 elog(ERROR, "oidvector value has too many values");
139         while (slot < INDEX_MAX_KEYS)
140                 result[slot++] = InvalidOid;
141
142         PG_RETURN_POINTER(result);
143 }
144
145 /*
146  *              oidvectorout - converts internal form to "num num ..."
147  */
148 Datum
149 oidvectorout(PG_FUNCTION_ARGS)
150 {
151         Oid                *oidArray = (Oid *) PG_GETARG_POINTER(0);
152         int                     num,
153                                 maxnum;
154         char       *rp;
155         char       *result;
156
157         /* find last non-zero value in vector */
158         for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
159                 if (oidArray[maxnum] != 0)
160                         break;
161
162         /* assumes sign, 10 digits, ' ' */
163         rp = result = (char *) palloc((maxnum + 1) * 12 + 1);
164         for (num = 0; num <= maxnum; num++)
165         {
166                 if (num != 0)
167                         *rp++ = ' ';
168                 sprintf(rp, "%u", oidArray[num]);
169                 while (*++rp != '\0')
170                         ;
171         }
172         *rp = '\0';
173         PG_RETURN_CSTRING(result);
174 }
175
176 /*****************************************************************************
177  *       PUBLIC ROUTINES                                                                                                                 *
178  *****************************************************************************/
179
180 Datum
181 oideq(PG_FUNCTION_ARGS)
182 {
183         Oid                     arg1 = PG_GETARG_OID(0);
184         Oid                     arg2 = PG_GETARG_OID(1);
185
186         PG_RETURN_BOOL(arg1 == arg2);
187 }
188
189 Datum
190 oidne(PG_FUNCTION_ARGS)
191 {
192         Oid                     arg1 = PG_GETARG_OID(0);
193         Oid                     arg2 = PG_GETARG_OID(1);
194
195         PG_RETURN_BOOL(arg1 != arg2);
196 }
197
198 Datum
199 oidlt(PG_FUNCTION_ARGS)
200 {
201         Oid                     arg1 = PG_GETARG_OID(0);
202         Oid                     arg2 = PG_GETARG_OID(1);
203
204         PG_RETURN_BOOL(arg1 < arg2);
205 }
206
207 Datum
208 oidle(PG_FUNCTION_ARGS)
209 {
210         Oid                     arg1 = PG_GETARG_OID(0);
211         Oid                     arg2 = PG_GETARG_OID(1);
212
213         PG_RETURN_BOOL(arg1 <= arg2);
214 }
215
216 Datum
217 oidge(PG_FUNCTION_ARGS)
218 {
219         Oid                     arg1 = PG_GETARG_OID(0);
220         Oid                     arg2 = PG_GETARG_OID(1);
221
222         PG_RETURN_BOOL(arg1 >= arg2);
223 }
224
225 Datum
226 oidgt(PG_FUNCTION_ARGS)
227 {
228         Oid                     arg1 = PG_GETARG_OID(0);
229         Oid                     arg2 = PG_GETARG_OID(1);
230
231         PG_RETURN_BOOL(arg1 > arg2);
232 }
233
234 Datum
235 oidlarger(PG_FUNCTION_ARGS)
236 {
237         Oid                     arg1 = PG_GETARG_OID(0);
238         Oid                     arg2 = PG_GETARG_OID(1);
239
240         PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2);
241 }
242
243 Datum
244 oidsmaller(PG_FUNCTION_ARGS)
245 {
246         Oid                     arg1 = PG_GETARG_OID(0);
247         Oid                     arg2 = PG_GETARG_OID(1);
248
249         PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2);
250 }
251
252 Datum
253 oidvectoreq(PG_FUNCTION_ARGS)
254 {
255         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
256         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
257
258         PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(Oid)) == 0);
259 }
260
261 Datum
262 oidvectorne(PG_FUNCTION_ARGS)
263 {
264         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
265         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
266
267         PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(Oid)) != 0);
268 }
269
270 Datum
271 oidvectorlt(PG_FUNCTION_ARGS)
272 {
273         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
274         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
275         int                     i;
276
277         for (i = 0; i < INDEX_MAX_KEYS; i++)
278                 if (arg1[i] != arg2[i])
279                         PG_RETURN_BOOL(arg1[i] < arg2[i]);
280         PG_RETURN_BOOL(false);
281 }
282
283 Datum
284 oidvectorle(PG_FUNCTION_ARGS)
285 {
286         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
287         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
288         int                     i;
289
290         for (i = 0; i < INDEX_MAX_KEYS; i++)
291                 if (arg1[i] != arg2[i])
292                         PG_RETURN_BOOL(arg1[i] <= arg2[i]);
293         PG_RETURN_BOOL(true);
294 }
295
296 Datum
297 oidvectorge(PG_FUNCTION_ARGS)
298 {
299         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
300         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
301         int                     i;
302
303         for (i = 0; i < INDEX_MAX_KEYS; i++)
304                 if (arg1[i] != arg2[i])
305                         PG_RETURN_BOOL(arg1[i] >= arg2[i]);
306         PG_RETURN_BOOL(true);
307 }
308
309 Datum
310 oidvectorgt(PG_FUNCTION_ARGS)
311 {
312         Oid                *arg1 = (Oid *) PG_GETARG_POINTER(0);
313         Oid                *arg2 = (Oid *) PG_GETARG_POINTER(1);
314         int                     i;
315
316         for (i = 0; i < INDEX_MAX_KEYS; i++)
317                 if (arg1[i] != arg2[i])
318                         PG_RETURN_BOOL(arg1[i] > arg2[i]);
319         PG_RETURN_BOOL(false);
320 }
321
322 Datum
323 oid_text(PG_FUNCTION_ARGS)
324 {
325         Oid                     oid = PG_GETARG_OID(0);
326         text       *result;
327         int                     len;
328         char       *str;
329
330         str = DatumGetCString(DirectFunctionCall1(oidout,
331                                                                                           ObjectIdGetDatum(oid)));
332         len = strlen(str) + VARHDRSZ;
333
334         result = (text *) palloc(len);
335
336         VARATT_SIZEP(result) = len;
337         memcpy(VARDATA(result), str, (len - VARHDRSZ));
338         pfree(str);
339
340         PG_RETURN_TEXT_P(result);
341 }
342
343 Datum
344 text_oid(PG_FUNCTION_ARGS)
345 {
346         text       *string = PG_GETARG_TEXT_P(0);
347         Oid                     result;
348         int                     len;
349         char       *str;
350
351         len = (VARSIZE(string) - VARHDRSZ);
352
353         str = palloc(len + 1);
354         memcpy(str, VARDATA(string), len);
355         *(str + len) = '\0';
356
357         result = oidin_subr("text_oid", str, NULL);
358
359         pfree(str);
360
361         PG_RETURN_OID(result);
362 }