1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * int.c |
4 | * Functions for the built-in integer types (except int8). |
5 | * |
6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
7 | * Portions Copyright (c) 1994, Regents of the University of California |
8 | * |
9 | * |
10 | * IDENTIFICATION |
11 | * src/backend/utils/adt/int.c |
12 | * |
13 | *------------------------------------------------------------------------- |
14 | */ |
15 | /* |
16 | * OLD COMMENTS |
17 | * I/O routines: |
18 | * int2in, int2out, int2recv, int2send |
19 | * int4in, int4out, int4recv, int4send |
20 | * int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend |
21 | * Boolean operators: |
22 | * inteq, intne, intlt, intle, intgt, intge |
23 | * Arithmetic operators: |
24 | * intpl, intmi, int4mul, intdiv |
25 | * |
26 | * Arithmetic operators: |
27 | * intmod |
28 | */ |
29 | #include "postgres.h" |
30 | |
31 | #include <ctype.h> |
32 | #include <limits.h> |
33 | #include <math.h> |
34 | |
35 | #include "catalog/pg_type.h" |
36 | #include "common/int.h" |
37 | #include "funcapi.h" |
38 | #include "libpq/pqformat.h" |
39 | #include "nodes/nodeFuncs.h" |
40 | #include "nodes/supportnodes.h" |
41 | #include "optimizer/optimizer.h" |
42 | #include "utils/array.h" |
43 | #include "utils/builtins.h" |
44 | |
45 | #define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16)) |
46 | |
47 | typedef struct |
48 | { |
49 | int32 current; |
50 | int32 finish; |
51 | int32 step; |
52 | } generate_series_fctx; |
53 | |
54 | |
55 | /***************************************************************************** |
56 | * USER I/O ROUTINES * |
57 | *****************************************************************************/ |
58 | |
59 | /* |
60 | * int2in - converts "num" to short |
61 | */ |
62 | Datum |
63 | int2in(PG_FUNCTION_ARGS) |
64 | { |
65 | char *num = PG_GETARG_CSTRING(0); |
66 | |
67 | PG_RETURN_INT16(pg_strtoint16(num)); |
68 | } |
69 | |
70 | /* |
71 | * int2out - converts short to "num" |
72 | */ |
73 | Datum |
74 | int2out(PG_FUNCTION_ARGS) |
75 | { |
76 | int16 arg1 = PG_GETARG_INT16(0); |
77 | char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */ |
78 | |
79 | pg_itoa(arg1, result); |
80 | PG_RETURN_CSTRING(result); |
81 | } |
82 | |
83 | /* |
84 | * int2recv - converts external binary format to int2 |
85 | */ |
86 | Datum |
87 | int2recv(PG_FUNCTION_ARGS) |
88 | { |
89 | StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); |
90 | |
91 | PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16))); |
92 | } |
93 | |
94 | /* |
95 | * int2send - converts int2 to binary format |
96 | */ |
97 | Datum |
98 | int2send(PG_FUNCTION_ARGS) |
99 | { |
100 | int16 arg1 = PG_GETARG_INT16(0); |
101 | StringInfoData buf; |
102 | |
103 | pq_begintypsend(&buf); |
104 | pq_sendint16(&buf, arg1); |
105 | PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); |
106 | } |
107 | |
108 | /* |
109 | * construct int2vector given a raw array of int2s |
110 | * |
111 | * If int2s is NULL then caller must fill values[] afterward |
112 | */ |
113 | int2vector * |
114 | buildint2vector(const int16 *int2s, int n) |
115 | { |
116 | int2vector *result; |
117 | |
118 | result = (int2vector *) palloc0(Int2VectorSize(n)); |
119 | |
120 | if (n > 0 && int2s) |
121 | memcpy(result->values, int2s, n * sizeof(int16)); |
122 | |
123 | /* |
124 | * Attach standard array header. For historical reasons, we set the index |
125 | * lower bound to 0 not 1. |
126 | */ |
127 | SET_VARSIZE(result, Int2VectorSize(n)); |
128 | result->ndim = 1; |
129 | result->dataoffset = 0; /* never any nulls */ |
130 | result->elemtype = INT2OID; |
131 | result->dim1 = n; |
132 | result->lbound1 = 0; |
133 | |
134 | return result; |
135 | } |
136 | |
137 | /* |
138 | * int2vectorin - converts "num num ..." to internal form |
139 | */ |
140 | Datum |
141 | int2vectorin(PG_FUNCTION_ARGS) |
142 | { |
143 | char *intString = PG_GETARG_CSTRING(0); |
144 | int2vector *result; |
145 | int n; |
146 | |
147 | result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS)); |
148 | |
149 | for (n = 0; *intString && n < FUNC_MAX_ARGS; n++) |
150 | { |
151 | while (*intString && isspace((unsigned char) *intString)) |
152 | intString++; |
153 | if (*intString == '\0') |
154 | break; |
155 | result->values[n] = pg_atoi(intString, sizeof(int16), ' '); |
156 | while (*intString && !isspace((unsigned char) *intString)) |
157 | intString++; |
158 | } |
159 | while (*intString && isspace((unsigned char) *intString)) |
160 | intString++; |
161 | if (*intString) |
162 | ereport(ERROR, |
163 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
164 | errmsg("int2vector has too many elements" ))); |
165 | |
166 | SET_VARSIZE(result, Int2VectorSize(n)); |
167 | result->ndim = 1; |
168 | result->dataoffset = 0; /* never any nulls */ |
169 | result->elemtype = INT2OID; |
170 | result->dim1 = n; |
171 | result->lbound1 = 0; |
172 | |
173 | PG_RETURN_POINTER(result); |
174 | } |
175 | |
176 | /* |
177 | * int2vectorout - converts internal form to "num num ..." |
178 | */ |
179 | Datum |
180 | int2vectorout(PG_FUNCTION_ARGS) |
181 | { |
182 | int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0); |
183 | int num, |
184 | nnums = int2Array->dim1; |
185 | char *rp; |
186 | char *result; |
187 | |
188 | /* assumes sign, 5 digits, ' ' */ |
189 | rp = result = (char *) palloc(nnums * 7 + 1); |
190 | for (num = 0; num < nnums; num++) |
191 | { |
192 | if (num != 0) |
193 | *rp++ = ' '; |
194 | pg_itoa(int2Array->values[num], rp); |
195 | while (*++rp != '\0') |
196 | ; |
197 | } |
198 | *rp = '\0'; |
199 | PG_RETURN_CSTRING(result); |
200 | } |
201 | |
202 | /* |
203 | * int2vectorrecv - converts external binary format to int2vector |
204 | */ |
205 | Datum |
206 | int2vectorrecv(PG_FUNCTION_ARGS) |
207 | { |
208 | LOCAL_FCINFO(locfcinfo, 3); |
209 | StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); |
210 | int2vector *result; |
211 | |
212 | /* |
213 | * Normally one would call array_recv() using DirectFunctionCall3, but |
214 | * that does not work since array_recv wants to cache some data using |
215 | * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo |
216 | * parameter. |
217 | */ |
218 | InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3, |
219 | InvalidOid, NULL, NULL); |
220 | |
221 | locfcinfo->args[0].value = PointerGetDatum(buf); |
222 | locfcinfo->args[0].isnull = false; |
223 | locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID); |
224 | locfcinfo->args[1].isnull = false; |
225 | locfcinfo->args[2].value = Int32GetDatum(-1); |
226 | locfcinfo->args[2].isnull = false; |
227 | |
228 | result = (int2vector *) DatumGetPointer(array_recv(locfcinfo)); |
229 | |
230 | Assert(!locfcinfo->isnull); |
231 | |
232 | /* sanity checks: int2vector must be 1-D, 0-based, no nulls */ |
233 | if (ARR_NDIM(result) != 1 || |
234 | ARR_HASNULL(result) || |
235 | ARR_ELEMTYPE(result) != INT2OID || |
236 | ARR_LBOUND(result)[0] != 0) |
237 | ereport(ERROR, |
238 | (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), |
239 | errmsg("invalid int2vector data" ))); |
240 | |
241 | /* check length for consistency with int2vectorin() */ |
242 | if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS) |
243 | ereport(ERROR, |
244 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
245 | errmsg("oidvector has too many elements" ))); |
246 | |
247 | PG_RETURN_POINTER(result); |
248 | } |
249 | |
250 | /* |
251 | * int2vectorsend - converts int2vector to binary format |
252 | */ |
253 | Datum |
254 | int2vectorsend(PG_FUNCTION_ARGS) |
255 | { |
256 | return array_send(fcinfo); |
257 | } |
258 | |
259 | |
260 | /***************************************************************************** |
261 | * PUBLIC ROUTINES * |
262 | *****************************************************************************/ |
263 | |
264 | /* |
265 | * int4in - converts "num" to int4 |
266 | */ |
267 | Datum |
268 | int4in(PG_FUNCTION_ARGS) |
269 | { |
270 | char *num = PG_GETARG_CSTRING(0); |
271 | |
272 | PG_RETURN_INT32(pg_strtoint32(num)); |
273 | } |
274 | |
275 | /* |
276 | * int4out - converts int4 to "num" |
277 | */ |
278 | Datum |
279 | int4out(PG_FUNCTION_ARGS) |
280 | { |
281 | int32 arg1 = PG_GETARG_INT32(0); |
282 | char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */ |
283 | |
284 | pg_ltoa(arg1, result); |
285 | PG_RETURN_CSTRING(result); |
286 | } |
287 | |
288 | /* |
289 | * int4recv - converts external binary format to int4 |
290 | */ |
291 | Datum |
292 | int4recv(PG_FUNCTION_ARGS) |
293 | { |
294 | StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); |
295 | |
296 | PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32))); |
297 | } |
298 | |
299 | /* |
300 | * int4send - converts int4 to binary format |
301 | */ |
302 | Datum |
303 | int4send(PG_FUNCTION_ARGS) |
304 | { |
305 | int32 arg1 = PG_GETARG_INT32(0); |
306 | StringInfoData buf; |
307 | |
308 | pq_begintypsend(&buf); |
309 | pq_sendint32(&buf, arg1); |
310 | PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); |
311 | } |
312 | |
313 | |
314 | /* |
315 | * =================== |
316 | * CONVERSION ROUTINES |
317 | * =================== |
318 | */ |
319 | |
320 | Datum |
321 | i2toi4(PG_FUNCTION_ARGS) |
322 | { |
323 | int16 arg1 = PG_GETARG_INT16(0); |
324 | |
325 | PG_RETURN_INT32((int32) arg1); |
326 | } |
327 | |
328 | Datum |
329 | i4toi2(PG_FUNCTION_ARGS) |
330 | { |
331 | int32 arg1 = PG_GETARG_INT32(0); |
332 | |
333 | if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX)) |
334 | ereport(ERROR, |
335 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
336 | errmsg("smallint out of range" ))); |
337 | |
338 | PG_RETURN_INT16((int16) arg1); |
339 | } |
340 | |
341 | /* Cast int4 -> bool */ |
342 | Datum |
343 | int4_bool(PG_FUNCTION_ARGS) |
344 | { |
345 | if (PG_GETARG_INT32(0) == 0) |
346 | PG_RETURN_BOOL(false); |
347 | else |
348 | PG_RETURN_BOOL(true); |
349 | } |
350 | |
351 | /* Cast bool -> int4 */ |
352 | Datum |
353 | bool_int4(PG_FUNCTION_ARGS) |
354 | { |
355 | if (PG_GETARG_BOOL(0) == false) |
356 | PG_RETURN_INT32(0); |
357 | else |
358 | PG_RETURN_INT32(1); |
359 | } |
360 | |
361 | /* |
362 | * ============================ |
363 | * COMPARISON OPERATOR ROUTINES |
364 | * ============================ |
365 | */ |
366 | |
367 | /* |
368 | * inteq - returns 1 iff arg1 == arg2 |
369 | * intne - returns 1 iff arg1 != arg2 |
370 | * intlt - returns 1 iff arg1 < arg2 |
371 | * intle - returns 1 iff arg1 <= arg2 |
372 | * intgt - returns 1 iff arg1 > arg2 |
373 | * intge - returns 1 iff arg1 >= arg2 |
374 | */ |
375 | |
376 | Datum |
377 | int4eq(PG_FUNCTION_ARGS) |
378 | { |
379 | int32 arg1 = PG_GETARG_INT32(0); |
380 | int32 arg2 = PG_GETARG_INT32(1); |
381 | |
382 | PG_RETURN_BOOL(arg1 == arg2); |
383 | } |
384 | |
385 | Datum |
386 | int4ne(PG_FUNCTION_ARGS) |
387 | { |
388 | int32 arg1 = PG_GETARG_INT32(0); |
389 | int32 arg2 = PG_GETARG_INT32(1); |
390 | |
391 | PG_RETURN_BOOL(arg1 != arg2); |
392 | } |
393 | |
394 | Datum |
395 | int4lt(PG_FUNCTION_ARGS) |
396 | { |
397 | int32 arg1 = PG_GETARG_INT32(0); |
398 | int32 arg2 = PG_GETARG_INT32(1); |
399 | |
400 | PG_RETURN_BOOL(arg1 < arg2); |
401 | } |
402 | |
403 | Datum |
404 | int4le(PG_FUNCTION_ARGS) |
405 | { |
406 | int32 arg1 = PG_GETARG_INT32(0); |
407 | int32 arg2 = PG_GETARG_INT32(1); |
408 | |
409 | PG_RETURN_BOOL(arg1 <= arg2); |
410 | } |
411 | |
412 | Datum |
413 | int4gt(PG_FUNCTION_ARGS) |
414 | { |
415 | int32 arg1 = PG_GETARG_INT32(0); |
416 | int32 arg2 = PG_GETARG_INT32(1); |
417 | |
418 | PG_RETURN_BOOL(arg1 > arg2); |
419 | } |
420 | |
421 | Datum |
422 | int4ge(PG_FUNCTION_ARGS) |
423 | { |
424 | int32 arg1 = PG_GETARG_INT32(0); |
425 | int32 arg2 = PG_GETARG_INT32(1); |
426 | |
427 | PG_RETURN_BOOL(arg1 >= arg2); |
428 | } |
429 | |
430 | Datum |
431 | int2eq(PG_FUNCTION_ARGS) |
432 | { |
433 | int16 arg1 = PG_GETARG_INT16(0); |
434 | int16 arg2 = PG_GETARG_INT16(1); |
435 | |
436 | PG_RETURN_BOOL(arg1 == arg2); |
437 | } |
438 | |
439 | Datum |
440 | int2ne(PG_FUNCTION_ARGS) |
441 | { |
442 | int16 arg1 = PG_GETARG_INT16(0); |
443 | int16 arg2 = PG_GETARG_INT16(1); |
444 | |
445 | PG_RETURN_BOOL(arg1 != arg2); |
446 | } |
447 | |
448 | Datum |
449 | int2lt(PG_FUNCTION_ARGS) |
450 | { |
451 | int16 arg1 = PG_GETARG_INT16(0); |
452 | int16 arg2 = PG_GETARG_INT16(1); |
453 | |
454 | PG_RETURN_BOOL(arg1 < arg2); |
455 | } |
456 | |
457 | Datum |
458 | int2le(PG_FUNCTION_ARGS) |
459 | { |
460 | int16 arg1 = PG_GETARG_INT16(0); |
461 | int16 arg2 = PG_GETARG_INT16(1); |
462 | |
463 | PG_RETURN_BOOL(arg1 <= arg2); |
464 | } |
465 | |
466 | Datum |
467 | int2gt(PG_FUNCTION_ARGS) |
468 | { |
469 | int16 arg1 = PG_GETARG_INT16(0); |
470 | int16 arg2 = PG_GETARG_INT16(1); |
471 | |
472 | PG_RETURN_BOOL(arg1 > arg2); |
473 | } |
474 | |
475 | Datum |
476 | int2ge(PG_FUNCTION_ARGS) |
477 | { |
478 | int16 arg1 = PG_GETARG_INT16(0); |
479 | int16 arg2 = PG_GETARG_INT16(1); |
480 | |
481 | PG_RETURN_BOOL(arg1 >= arg2); |
482 | } |
483 | |
484 | Datum |
485 | int24eq(PG_FUNCTION_ARGS) |
486 | { |
487 | int16 arg1 = PG_GETARG_INT16(0); |
488 | int32 arg2 = PG_GETARG_INT32(1); |
489 | |
490 | PG_RETURN_BOOL(arg1 == arg2); |
491 | } |
492 | |
493 | Datum |
494 | int24ne(PG_FUNCTION_ARGS) |
495 | { |
496 | int16 arg1 = PG_GETARG_INT16(0); |
497 | int32 arg2 = PG_GETARG_INT32(1); |
498 | |
499 | PG_RETURN_BOOL(arg1 != arg2); |
500 | } |
501 | |
502 | Datum |
503 | int24lt(PG_FUNCTION_ARGS) |
504 | { |
505 | int16 arg1 = PG_GETARG_INT16(0); |
506 | int32 arg2 = PG_GETARG_INT32(1); |
507 | |
508 | PG_RETURN_BOOL(arg1 < arg2); |
509 | } |
510 | |
511 | Datum |
512 | int24le(PG_FUNCTION_ARGS) |
513 | { |
514 | int16 arg1 = PG_GETARG_INT16(0); |
515 | int32 arg2 = PG_GETARG_INT32(1); |
516 | |
517 | PG_RETURN_BOOL(arg1 <= arg2); |
518 | } |
519 | |
520 | Datum |
521 | int24gt(PG_FUNCTION_ARGS) |
522 | { |
523 | int16 arg1 = PG_GETARG_INT16(0); |
524 | int32 arg2 = PG_GETARG_INT32(1); |
525 | |
526 | PG_RETURN_BOOL(arg1 > arg2); |
527 | } |
528 | |
529 | Datum |
530 | int24ge(PG_FUNCTION_ARGS) |
531 | { |
532 | int16 arg1 = PG_GETARG_INT16(0); |
533 | int32 arg2 = PG_GETARG_INT32(1); |
534 | |
535 | PG_RETURN_BOOL(arg1 >= arg2); |
536 | } |
537 | |
538 | Datum |
539 | int42eq(PG_FUNCTION_ARGS) |
540 | { |
541 | int32 arg1 = PG_GETARG_INT32(0); |
542 | int16 arg2 = PG_GETARG_INT16(1); |
543 | |
544 | PG_RETURN_BOOL(arg1 == arg2); |
545 | } |
546 | |
547 | Datum |
548 | int42ne(PG_FUNCTION_ARGS) |
549 | { |
550 | int32 arg1 = PG_GETARG_INT32(0); |
551 | int16 arg2 = PG_GETARG_INT16(1); |
552 | |
553 | PG_RETURN_BOOL(arg1 != arg2); |
554 | } |
555 | |
556 | Datum |
557 | int42lt(PG_FUNCTION_ARGS) |
558 | { |
559 | int32 arg1 = PG_GETARG_INT32(0); |
560 | int16 arg2 = PG_GETARG_INT16(1); |
561 | |
562 | PG_RETURN_BOOL(arg1 < arg2); |
563 | } |
564 | |
565 | Datum |
566 | int42le(PG_FUNCTION_ARGS) |
567 | { |
568 | int32 arg1 = PG_GETARG_INT32(0); |
569 | int16 arg2 = PG_GETARG_INT16(1); |
570 | |
571 | PG_RETURN_BOOL(arg1 <= arg2); |
572 | } |
573 | |
574 | Datum |
575 | int42gt(PG_FUNCTION_ARGS) |
576 | { |
577 | int32 arg1 = PG_GETARG_INT32(0); |
578 | int16 arg2 = PG_GETARG_INT16(1); |
579 | |
580 | PG_RETURN_BOOL(arg1 > arg2); |
581 | } |
582 | |
583 | Datum |
584 | int42ge(PG_FUNCTION_ARGS) |
585 | { |
586 | int32 arg1 = PG_GETARG_INT32(0); |
587 | int16 arg2 = PG_GETARG_INT16(1); |
588 | |
589 | PG_RETURN_BOOL(arg1 >= arg2); |
590 | } |
591 | |
592 | |
593 | /*---------------------------------------------------------- |
594 | * in_range functions for int4 and int2, |
595 | * including cross-data-type comparisons. |
596 | * |
597 | * Note: we provide separate intN_int8 functions for performance |
598 | * reasons. This forces also providing intN_int2, else cases with a |
599 | * smallint offset value would fail to resolve which function to use. |
600 | * But that's an unlikely situation, so don't duplicate code for it. |
601 | *---------------------------------------------------------*/ |
602 | |
603 | Datum |
604 | in_range_int4_int4(PG_FUNCTION_ARGS) |
605 | { |
606 | int32 val = PG_GETARG_INT32(0); |
607 | int32 base = PG_GETARG_INT32(1); |
608 | int32 offset = PG_GETARG_INT32(2); |
609 | bool sub = PG_GETARG_BOOL(3); |
610 | bool less = PG_GETARG_BOOL(4); |
611 | int32 sum; |
612 | |
613 | if (offset < 0) |
614 | ereport(ERROR, |
615 | (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), |
616 | errmsg("invalid preceding or following size in window function" ))); |
617 | |
618 | if (sub) |
619 | offset = -offset; /* cannot overflow */ |
620 | |
621 | if (unlikely(pg_add_s32_overflow(base, offset, &sum))) |
622 | { |
623 | /* |
624 | * If sub is false, the true sum is surely more than val, so correct |
625 | * answer is the same as "less". If sub is true, the true sum is |
626 | * surely less than val, so the answer is "!less". |
627 | */ |
628 | PG_RETURN_BOOL(sub ? !less : less); |
629 | } |
630 | |
631 | if (less) |
632 | PG_RETURN_BOOL(val <= sum); |
633 | else |
634 | PG_RETURN_BOOL(val >= sum); |
635 | } |
636 | |
637 | Datum |
638 | in_range_int4_int2(PG_FUNCTION_ARGS) |
639 | { |
640 | /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */ |
641 | return DirectFunctionCall5(in_range_int4_int4, |
642 | PG_GETARG_DATUM(0), |
643 | PG_GETARG_DATUM(1), |
644 | Int32GetDatum((int32) PG_GETARG_INT16(2)), |
645 | PG_GETARG_DATUM(3), |
646 | PG_GETARG_DATUM(4)); |
647 | } |
648 | |
649 | Datum |
650 | in_range_int4_int8(PG_FUNCTION_ARGS) |
651 | { |
652 | /* We must do all the math in int64 */ |
653 | int64 val = (int64) PG_GETARG_INT32(0); |
654 | int64 base = (int64) PG_GETARG_INT32(1); |
655 | int64 offset = PG_GETARG_INT64(2); |
656 | bool sub = PG_GETARG_BOOL(3); |
657 | bool less = PG_GETARG_BOOL(4); |
658 | int64 sum; |
659 | |
660 | if (offset < 0) |
661 | ereport(ERROR, |
662 | (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), |
663 | errmsg("invalid preceding or following size in window function" ))); |
664 | |
665 | if (sub) |
666 | offset = -offset; /* cannot overflow */ |
667 | |
668 | if (unlikely(pg_add_s64_overflow(base, offset, &sum))) |
669 | { |
670 | /* |
671 | * If sub is false, the true sum is surely more than val, so correct |
672 | * answer is the same as "less". If sub is true, the true sum is |
673 | * surely less than val, so the answer is "!less". |
674 | */ |
675 | PG_RETURN_BOOL(sub ? !less : less); |
676 | } |
677 | |
678 | if (less) |
679 | PG_RETURN_BOOL(val <= sum); |
680 | else |
681 | PG_RETURN_BOOL(val >= sum); |
682 | } |
683 | |
684 | Datum |
685 | in_range_int2_int4(PG_FUNCTION_ARGS) |
686 | { |
687 | /* We must do all the math in int32 */ |
688 | int32 val = (int32) PG_GETARG_INT16(0); |
689 | int32 base = (int32) PG_GETARG_INT16(1); |
690 | int32 offset = PG_GETARG_INT32(2); |
691 | bool sub = PG_GETARG_BOOL(3); |
692 | bool less = PG_GETARG_BOOL(4); |
693 | int32 sum; |
694 | |
695 | if (offset < 0) |
696 | ereport(ERROR, |
697 | (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), |
698 | errmsg("invalid preceding or following size in window function" ))); |
699 | |
700 | if (sub) |
701 | offset = -offset; /* cannot overflow */ |
702 | |
703 | if (unlikely(pg_add_s32_overflow(base, offset, &sum))) |
704 | { |
705 | /* |
706 | * If sub is false, the true sum is surely more than val, so correct |
707 | * answer is the same as "less". If sub is true, the true sum is |
708 | * surely less than val, so the answer is "!less". |
709 | */ |
710 | PG_RETURN_BOOL(sub ? !less : less); |
711 | } |
712 | |
713 | if (less) |
714 | PG_RETURN_BOOL(val <= sum); |
715 | else |
716 | PG_RETURN_BOOL(val >= sum); |
717 | } |
718 | |
719 | Datum |
720 | in_range_int2_int2(PG_FUNCTION_ARGS) |
721 | { |
722 | /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */ |
723 | return DirectFunctionCall5(in_range_int2_int4, |
724 | PG_GETARG_DATUM(0), |
725 | PG_GETARG_DATUM(1), |
726 | Int32GetDatum((int32) PG_GETARG_INT16(2)), |
727 | PG_GETARG_DATUM(3), |
728 | PG_GETARG_DATUM(4)); |
729 | } |
730 | |
731 | Datum |
732 | in_range_int2_int8(PG_FUNCTION_ARGS) |
733 | { |
734 | /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */ |
735 | return DirectFunctionCall5(in_range_int4_int8, |
736 | Int32GetDatum((int32) PG_GETARG_INT16(0)), |
737 | Int32GetDatum((int32) PG_GETARG_INT16(1)), |
738 | PG_GETARG_DATUM(2), |
739 | PG_GETARG_DATUM(3), |
740 | PG_GETARG_DATUM(4)); |
741 | } |
742 | |
743 | |
744 | /* |
745 | * int[24]pl - returns arg1 + arg2 |
746 | * int[24]mi - returns arg1 - arg2 |
747 | * int[24]mul - returns arg1 * arg2 |
748 | * int[24]div - returns arg1 / arg2 |
749 | */ |
750 | |
751 | Datum |
752 | int4um(PG_FUNCTION_ARGS) |
753 | { |
754 | int32 arg = PG_GETARG_INT32(0); |
755 | |
756 | if (unlikely(arg == PG_INT32_MIN)) |
757 | ereport(ERROR, |
758 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
759 | errmsg("integer out of range" ))); |
760 | PG_RETURN_INT32(-arg); |
761 | } |
762 | |
763 | Datum |
764 | int4up(PG_FUNCTION_ARGS) |
765 | { |
766 | int32 arg = PG_GETARG_INT32(0); |
767 | |
768 | PG_RETURN_INT32(arg); |
769 | } |
770 | |
771 | Datum |
772 | int4pl(PG_FUNCTION_ARGS) |
773 | { |
774 | int32 arg1 = PG_GETARG_INT32(0); |
775 | int32 arg2 = PG_GETARG_INT32(1); |
776 | int32 result; |
777 | |
778 | if (unlikely(pg_add_s32_overflow(arg1, arg2, &result))) |
779 | ereport(ERROR, |
780 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
781 | errmsg("integer out of range" ))); |
782 | PG_RETURN_INT32(result); |
783 | } |
784 | |
785 | Datum |
786 | int4mi(PG_FUNCTION_ARGS) |
787 | { |
788 | int32 arg1 = PG_GETARG_INT32(0); |
789 | int32 arg2 = PG_GETARG_INT32(1); |
790 | int32 result; |
791 | |
792 | if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result))) |
793 | ereport(ERROR, |
794 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
795 | errmsg("integer out of range" ))); |
796 | PG_RETURN_INT32(result); |
797 | } |
798 | |
799 | Datum |
800 | int4mul(PG_FUNCTION_ARGS) |
801 | { |
802 | int32 arg1 = PG_GETARG_INT32(0); |
803 | int32 arg2 = PG_GETARG_INT32(1); |
804 | int32 result; |
805 | |
806 | if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result))) |
807 | ereport(ERROR, |
808 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
809 | errmsg("integer out of range" ))); |
810 | PG_RETURN_INT32(result); |
811 | } |
812 | |
813 | Datum |
814 | int4div(PG_FUNCTION_ARGS) |
815 | { |
816 | int32 arg1 = PG_GETARG_INT32(0); |
817 | int32 arg2 = PG_GETARG_INT32(1); |
818 | int32 result; |
819 | |
820 | if (arg2 == 0) |
821 | { |
822 | ereport(ERROR, |
823 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
824 | errmsg("division by zero" ))); |
825 | /* ensure compiler realizes we mustn't reach the division (gcc bug) */ |
826 | PG_RETURN_NULL(); |
827 | } |
828 | |
829 | /* |
830 | * INT_MIN / -1 is problematic, since the result can't be represented on a |
831 | * two's-complement machine. Some machines produce INT_MIN, some produce |
832 | * zero, some throw an exception. We can dodge the problem by recognizing |
833 | * that division by -1 is the same as negation. |
834 | */ |
835 | if (arg2 == -1) |
836 | { |
837 | if (unlikely(arg1 == PG_INT32_MIN)) |
838 | ereport(ERROR, |
839 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
840 | errmsg("integer out of range" ))); |
841 | result = -arg1; |
842 | PG_RETURN_INT32(result); |
843 | } |
844 | |
845 | /* No overflow is possible */ |
846 | |
847 | result = arg1 / arg2; |
848 | |
849 | PG_RETURN_INT32(result); |
850 | } |
851 | |
852 | Datum |
853 | int4inc(PG_FUNCTION_ARGS) |
854 | { |
855 | int32 arg = PG_GETARG_INT32(0); |
856 | int32 result; |
857 | |
858 | if (unlikely(pg_add_s32_overflow(arg, 1, &result))) |
859 | ereport(ERROR, |
860 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
861 | errmsg("integer out of range" ))); |
862 | |
863 | PG_RETURN_INT32(result); |
864 | } |
865 | |
866 | Datum |
867 | int2um(PG_FUNCTION_ARGS) |
868 | { |
869 | int16 arg = PG_GETARG_INT16(0); |
870 | |
871 | if (unlikely(arg == PG_INT16_MIN)) |
872 | ereport(ERROR, |
873 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
874 | errmsg("smallint out of range" ))); |
875 | PG_RETURN_INT16(-arg); |
876 | } |
877 | |
878 | Datum |
879 | int2up(PG_FUNCTION_ARGS) |
880 | { |
881 | int16 arg = PG_GETARG_INT16(0); |
882 | |
883 | PG_RETURN_INT16(arg); |
884 | } |
885 | |
886 | Datum |
887 | int2pl(PG_FUNCTION_ARGS) |
888 | { |
889 | int16 arg1 = PG_GETARG_INT16(0); |
890 | int16 arg2 = PG_GETARG_INT16(1); |
891 | int16 result; |
892 | |
893 | if (unlikely(pg_add_s16_overflow(arg1, arg2, &result))) |
894 | ereport(ERROR, |
895 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
896 | errmsg("smallint out of range" ))); |
897 | PG_RETURN_INT16(result); |
898 | } |
899 | |
900 | Datum |
901 | int2mi(PG_FUNCTION_ARGS) |
902 | { |
903 | int16 arg1 = PG_GETARG_INT16(0); |
904 | int16 arg2 = PG_GETARG_INT16(1); |
905 | int16 result; |
906 | |
907 | if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result))) |
908 | ereport(ERROR, |
909 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
910 | errmsg("smallint out of range" ))); |
911 | PG_RETURN_INT16(result); |
912 | } |
913 | |
914 | Datum |
915 | int2mul(PG_FUNCTION_ARGS) |
916 | { |
917 | int16 arg1 = PG_GETARG_INT16(0); |
918 | int16 arg2 = PG_GETARG_INT16(1); |
919 | int16 result; |
920 | |
921 | if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result))) |
922 | ereport(ERROR, |
923 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
924 | errmsg("smallint out of range" ))); |
925 | |
926 | PG_RETURN_INT16(result); |
927 | } |
928 | |
929 | Datum |
930 | int2div(PG_FUNCTION_ARGS) |
931 | { |
932 | int16 arg1 = PG_GETARG_INT16(0); |
933 | int16 arg2 = PG_GETARG_INT16(1); |
934 | int16 result; |
935 | |
936 | if (arg2 == 0) |
937 | { |
938 | ereport(ERROR, |
939 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
940 | errmsg("division by zero" ))); |
941 | /* ensure compiler realizes we mustn't reach the division (gcc bug) */ |
942 | PG_RETURN_NULL(); |
943 | } |
944 | |
945 | /* |
946 | * SHRT_MIN / -1 is problematic, since the result can't be represented on |
947 | * a two's-complement machine. Some machines produce SHRT_MIN, some |
948 | * produce zero, some throw an exception. We can dodge the problem by |
949 | * recognizing that division by -1 is the same as negation. |
950 | */ |
951 | if (arg2 == -1) |
952 | { |
953 | if (unlikely(arg1 == PG_INT16_MIN)) |
954 | ereport(ERROR, |
955 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
956 | errmsg("smallint out of range" ))); |
957 | result = -arg1; |
958 | PG_RETURN_INT16(result); |
959 | } |
960 | |
961 | /* No overflow is possible */ |
962 | |
963 | result = arg1 / arg2; |
964 | |
965 | PG_RETURN_INT16(result); |
966 | } |
967 | |
968 | Datum |
969 | int24pl(PG_FUNCTION_ARGS) |
970 | { |
971 | int16 arg1 = PG_GETARG_INT16(0); |
972 | int32 arg2 = PG_GETARG_INT32(1); |
973 | int32 result; |
974 | |
975 | if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result))) |
976 | ereport(ERROR, |
977 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
978 | errmsg("integer out of range" ))); |
979 | PG_RETURN_INT32(result); |
980 | } |
981 | |
982 | Datum |
983 | int24mi(PG_FUNCTION_ARGS) |
984 | { |
985 | int16 arg1 = PG_GETARG_INT16(0); |
986 | int32 arg2 = PG_GETARG_INT32(1); |
987 | int32 result; |
988 | |
989 | if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result))) |
990 | ereport(ERROR, |
991 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
992 | errmsg("integer out of range" ))); |
993 | PG_RETURN_INT32(result); |
994 | } |
995 | |
996 | Datum |
997 | int24mul(PG_FUNCTION_ARGS) |
998 | { |
999 | int16 arg1 = PG_GETARG_INT16(0); |
1000 | int32 arg2 = PG_GETARG_INT32(1); |
1001 | int32 result; |
1002 | |
1003 | if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result))) |
1004 | ereport(ERROR, |
1005 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1006 | errmsg("integer out of range" ))); |
1007 | PG_RETURN_INT32(result); |
1008 | } |
1009 | |
1010 | Datum |
1011 | int24div(PG_FUNCTION_ARGS) |
1012 | { |
1013 | int16 arg1 = PG_GETARG_INT16(0); |
1014 | int32 arg2 = PG_GETARG_INT32(1); |
1015 | |
1016 | if (unlikely(arg2 == 0)) |
1017 | { |
1018 | ereport(ERROR, |
1019 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
1020 | errmsg("division by zero" ))); |
1021 | /* ensure compiler realizes we mustn't reach the division (gcc bug) */ |
1022 | PG_RETURN_NULL(); |
1023 | } |
1024 | |
1025 | /* No overflow is possible */ |
1026 | PG_RETURN_INT32((int32) arg1 / arg2); |
1027 | } |
1028 | |
1029 | Datum |
1030 | int42pl(PG_FUNCTION_ARGS) |
1031 | { |
1032 | int32 arg1 = PG_GETARG_INT32(0); |
1033 | int16 arg2 = PG_GETARG_INT16(1); |
1034 | int32 result; |
1035 | |
1036 | if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result))) |
1037 | ereport(ERROR, |
1038 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1039 | errmsg("integer out of range" ))); |
1040 | PG_RETURN_INT32(result); |
1041 | } |
1042 | |
1043 | Datum |
1044 | int42mi(PG_FUNCTION_ARGS) |
1045 | { |
1046 | int32 arg1 = PG_GETARG_INT32(0); |
1047 | int16 arg2 = PG_GETARG_INT16(1); |
1048 | int32 result; |
1049 | |
1050 | if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result))) |
1051 | ereport(ERROR, |
1052 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1053 | errmsg("integer out of range" ))); |
1054 | PG_RETURN_INT32(result); |
1055 | } |
1056 | |
1057 | Datum |
1058 | int42mul(PG_FUNCTION_ARGS) |
1059 | { |
1060 | int32 arg1 = PG_GETARG_INT32(0); |
1061 | int16 arg2 = PG_GETARG_INT16(1); |
1062 | int32 result; |
1063 | |
1064 | if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result))) |
1065 | ereport(ERROR, |
1066 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1067 | errmsg("integer out of range" ))); |
1068 | PG_RETURN_INT32(result); |
1069 | } |
1070 | |
1071 | Datum |
1072 | int42div(PG_FUNCTION_ARGS) |
1073 | { |
1074 | int32 arg1 = PG_GETARG_INT32(0); |
1075 | int16 arg2 = PG_GETARG_INT16(1); |
1076 | int32 result; |
1077 | |
1078 | if (unlikely(arg2 == 0)) |
1079 | { |
1080 | ereport(ERROR, |
1081 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
1082 | errmsg("division by zero" ))); |
1083 | /* ensure compiler realizes we mustn't reach the division (gcc bug) */ |
1084 | PG_RETURN_NULL(); |
1085 | } |
1086 | |
1087 | /* |
1088 | * INT_MIN / -1 is problematic, since the result can't be represented on a |
1089 | * two's-complement machine. Some machines produce INT_MIN, some produce |
1090 | * zero, some throw an exception. We can dodge the problem by recognizing |
1091 | * that division by -1 is the same as negation. |
1092 | */ |
1093 | if (arg2 == -1) |
1094 | { |
1095 | if (unlikely(arg1 == PG_INT32_MIN)) |
1096 | ereport(ERROR, |
1097 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1098 | errmsg("integer out of range" ))); |
1099 | result = -arg1; |
1100 | PG_RETURN_INT32(result); |
1101 | } |
1102 | |
1103 | /* No overflow is possible */ |
1104 | |
1105 | result = arg1 / arg2; |
1106 | |
1107 | PG_RETURN_INT32(result); |
1108 | } |
1109 | |
1110 | Datum |
1111 | int4mod(PG_FUNCTION_ARGS) |
1112 | { |
1113 | int32 arg1 = PG_GETARG_INT32(0); |
1114 | int32 arg2 = PG_GETARG_INT32(1); |
1115 | |
1116 | if (unlikely(arg2 == 0)) |
1117 | { |
1118 | ereport(ERROR, |
1119 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
1120 | errmsg("division by zero" ))); |
1121 | /* ensure compiler realizes we mustn't reach the division (gcc bug) */ |
1122 | PG_RETURN_NULL(); |
1123 | } |
1124 | |
1125 | /* |
1126 | * Some machines throw a floating-point exception for INT_MIN % -1, which |
1127 | * is a bit silly since the correct answer is perfectly well-defined, |
1128 | * namely zero. |
1129 | */ |
1130 | if (arg2 == -1) |
1131 | PG_RETURN_INT32(0); |
1132 | |
1133 | /* No overflow is possible */ |
1134 | |
1135 | PG_RETURN_INT32(arg1 % arg2); |
1136 | } |
1137 | |
1138 | Datum |
1139 | int2mod(PG_FUNCTION_ARGS) |
1140 | { |
1141 | int16 arg1 = PG_GETARG_INT16(0); |
1142 | int16 arg2 = PG_GETARG_INT16(1); |
1143 | |
1144 | if (unlikely(arg2 == 0)) |
1145 | { |
1146 | ereport(ERROR, |
1147 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
1148 | errmsg("division by zero" ))); |
1149 | /* ensure compiler realizes we mustn't reach the division (gcc bug) */ |
1150 | PG_RETURN_NULL(); |
1151 | } |
1152 | |
1153 | /* |
1154 | * Some machines throw a floating-point exception for INT_MIN % -1, which |
1155 | * is a bit silly since the correct answer is perfectly well-defined, |
1156 | * namely zero. (It's not clear this ever happens when dealing with |
1157 | * int16, but we might as well have the test for safety.) |
1158 | */ |
1159 | if (arg2 == -1) |
1160 | PG_RETURN_INT16(0); |
1161 | |
1162 | /* No overflow is possible */ |
1163 | |
1164 | PG_RETURN_INT16(arg1 % arg2); |
1165 | } |
1166 | |
1167 | |
1168 | /* int[24]abs() |
1169 | * Absolute value |
1170 | */ |
1171 | Datum |
1172 | int4abs(PG_FUNCTION_ARGS) |
1173 | { |
1174 | int32 arg1 = PG_GETARG_INT32(0); |
1175 | int32 result; |
1176 | |
1177 | if (unlikely(arg1 == PG_INT32_MIN)) |
1178 | ereport(ERROR, |
1179 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1180 | errmsg("integer out of range" ))); |
1181 | result = (arg1 < 0) ? -arg1 : arg1; |
1182 | PG_RETURN_INT32(result); |
1183 | } |
1184 | |
1185 | Datum |
1186 | int2abs(PG_FUNCTION_ARGS) |
1187 | { |
1188 | int16 arg1 = PG_GETARG_INT16(0); |
1189 | int16 result; |
1190 | |
1191 | if (unlikely(arg1 == PG_INT16_MIN)) |
1192 | ereport(ERROR, |
1193 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
1194 | errmsg("smallint out of range" ))); |
1195 | result = (arg1 < 0) ? -arg1 : arg1; |
1196 | PG_RETURN_INT16(result); |
1197 | } |
1198 | |
1199 | Datum |
1200 | int2larger(PG_FUNCTION_ARGS) |
1201 | { |
1202 | int16 arg1 = PG_GETARG_INT16(0); |
1203 | int16 arg2 = PG_GETARG_INT16(1); |
1204 | |
1205 | PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2); |
1206 | } |
1207 | |
1208 | Datum |
1209 | int2smaller(PG_FUNCTION_ARGS) |
1210 | { |
1211 | int16 arg1 = PG_GETARG_INT16(0); |
1212 | int16 arg2 = PG_GETARG_INT16(1); |
1213 | |
1214 | PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2); |
1215 | } |
1216 | |
1217 | Datum |
1218 | int4larger(PG_FUNCTION_ARGS) |
1219 | { |
1220 | int32 arg1 = PG_GETARG_INT32(0); |
1221 | int32 arg2 = PG_GETARG_INT32(1); |
1222 | |
1223 | PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2); |
1224 | } |
1225 | |
1226 | Datum |
1227 | int4smaller(PG_FUNCTION_ARGS) |
1228 | { |
1229 | int32 arg1 = PG_GETARG_INT32(0); |
1230 | int32 arg2 = PG_GETARG_INT32(1); |
1231 | |
1232 | PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2); |
1233 | } |
1234 | |
1235 | /* |
1236 | * Bit-pushing operators |
1237 | * |
1238 | * int[24]and - returns arg1 & arg2 |
1239 | * int[24]or - returns arg1 | arg2 |
1240 | * int[24]xor - returns arg1 # arg2 |
1241 | * int[24]not - returns ~arg1 |
1242 | * int[24]shl - returns arg1 << arg2 |
1243 | * int[24]shr - returns arg1 >> arg2 |
1244 | */ |
1245 | |
1246 | Datum |
1247 | int4and(PG_FUNCTION_ARGS) |
1248 | { |
1249 | int32 arg1 = PG_GETARG_INT32(0); |
1250 | int32 arg2 = PG_GETARG_INT32(1); |
1251 | |
1252 | PG_RETURN_INT32(arg1 & arg2); |
1253 | } |
1254 | |
1255 | Datum |
1256 | int4or(PG_FUNCTION_ARGS) |
1257 | { |
1258 | int32 arg1 = PG_GETARG_INT32(0); |
1259 | int32 arg2 = PG_GETARG_INT32(1); |
1260 | |
1261 | PG_RETURN_INT32(arg1 | arg2); |
1262 | } |
1263 | |
1264 | Datum |
1265 | int4xor(PG_FUNCTION_ARGS) |
1266 | { |
1267 | int32 arg1 = PG_GETARG_INT32(0); |
1268 | int32 arg2 = PG_GETARG_INT32(1); |
1269 | |
1270 | PG_RETURN_INT32(arg1 ^ arg2); |
1271 | } |
1272 | |
1273 | Datum |
1274 | int4shl(PG_FUNCTION_ARGS) |
1275 | { |
1276 | int32 arg1 = PG_GETARG_INT32(0); |
1277 | int32 arg2 = PG_GETARG_INT32(1); |
1278 | |
1279 | PG_RETURN_INT32(arg1 << arg2); |
1280 | } |
1281 | |
1282 | Datum |
1283 | int4shr(PG_FUNCTION_ARGS) |
1284 | { |
1285 | int32 arg1 = PG_GETARG_INT32(0); |
1286 | int32 arg2 = PG_GETARG_INT32(1); |
1287 | |
1288 | PG_RETURN_INT32(arg1 >> arg2); |
1289 | } |
1290 | |
1291 | Datum |
1292 | int4not(PG_FUNCTION_ARGS) |
1293 | { |
1294 | int32 arg1 = PG_GETARG_INT32(0); |
1295 | |
1296 | PG_RETURN_INT32(~arg1); |
1297 | } |
1298 | |
1299 | Datum |
1300 | int2and(PG_FUNCTION_ARGS) |
1301 | { |
1302 | int16 arg1 = PG_GETARG_INT16(0); |
1303 | int16 arg2 = PG_GETARG_INT16(1); |
1304 | |
1305 | PG_RETURN_INT16(arg1 & arg2); |
1306 | } |
1307 | |
1308 | Datum |
1309 | int2or(PG_FUNCTION_ARGS) |
1310 | { |
1311 | int16 arg1 = PG_GETARG_INT16(0); |
1312 | int16 arg2 = PG_GETARG_INT16(1); |
1313 | |
1314 | PG_RETURN_INT16(arg1 | arg2); |
1315 | } |
1316 | |
1317 | Datum |
1318 | int2xor(PG_FUNCTION_ARGS) |
1319 | { |
1320 | int16 arg1 = PG_GETARG_INT16(0); |
1321 | int16 arg2 = PG_GETARG_INT16(1); |
1322 | |
1323 | PG_RETURN_INT16(arg1 ^ arg2); |
1324 | } |
1325 | |
1326 | Datum |
1327 | int2not(PG_FUNCTION_ARGS) |
1328 | { |
1329 | int16 arg1 = PG_GETARG_INT16(0); |
1330 | |
1331 | PG_RETURN_INT16(~arg1); |
1332 | } |
1333 | |
1334 | |
1335 | Datum |
1336 | int2shl(PG_FUNCTION_ARGS) |
1337 | { |
1338 | int16 arg1 = PG_GETARG_INT16(0); |
1339 | int32 arg2 = PG_GETARG_INT32(1); |
1340 | |
1341 | PG_RETURN_INT16(arg1 << arg2); |
1342 | } |
1343 | |
1344 | Datum |
1345 | int2shr(PG_FUNCTION_ARGS) |
1346 | { |
1347 | int16 arg1 = PG_GETARG_INT16(0); |
1348 | int32 arg2 = PG_GETARG_INT32(1); |
1349 | |
1350 | PG_RETURN_INT16(arg1 >> arg2); |
1351 | } |
1352 | |
1353 | /* |
1354 | * non-persistent numeric series generator |
1355 | */ |
1356 | Datum |
1357 | generate_series_int4(PG_FUNCTION_ARGS) |
1358 | { |
1359 | return generate_series_step_int4(fcinfo); |
1360 | } |
1361 | |
1362 | Datum |
1363 | generate_series_step_int4(PG_FUNCTION_ARGS) |
1364 | { |
1365 | FuncCallContext *funcctx; |
1366 | generate_series_fctx *fctx; |
1367 | int32 result; |
1368 | MemoryContext oldcontext; |
1369 | |
1370 | /* stuff done only on the first call of the function */ |
1371 | if (SRF_IS_FIRSTCALL()) |
1372 | { |
1373 | int32 start = PG_GETARG_INT32(0); |
1374 | int32 finish = PG_GETARG_INT32(1); |
1375 | int32 step = 1; |
1376 | |
1377 | /* see if we were given an explicit step size */ |
1378 | if (PG_NARGS() == 3) |
1379 | step = PG_GETARG_INT32(2); |
1380 | if (step == 0) |
1381 | ereport(ERROR, |
1382 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1383 | errmsg("step size cannot equal zero" ))); |
1384 | |
1385 | /* create a function context for cross-call persistence */ |
1386 | funcctx = SRF_FIRSTCALL_INIT(); |
1387 | |
1388 | /* |
1389 | * switch to memory context appropriate for multiple function calls |
1390 | */ |
1391 | oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); |
1392 | |
1393 | /* allocate memory for user context */ |
1394 | fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx)); |
1395 | |
1396 | /* |
1397 | * Use fctx to keep state from call to call. Seed current with the |
1398 | * original start value |
1399 | */ |
1400 | fctx->current = start; |
1401 | fctx->finish = finish; |
1402 | fctx->step = step; |
1403 | |
1404 | funcctx->user_fctx = fctx; |
1405 | MemoryContextSwitchTo(oldcontext); |
1406 | } |
1407 | |
1408 | /* stuff done on every call of the function */ |
1409 | funcctx = SRF_PERCALL_SETUP(); |
1410 | |
1411 | /* |
1412 | * get the saved state and use current as the result for this iteration |
1413 | */ |
1414 | fctx = funcctx->user_fctx; |
1415 | result = fctx->current; |
1416 | |
1417 | if ((fctx->step > 0 && fctx->current <= fctx->finish) || |
1418 | (fctx->step < 0 && fctx->current >= fctx->finish)) |
1419 | { |
1420 | /* |
1421 | * Increment current in preparation for next iteration. If next-value |
1422 | * computation overflows, this is the final result. |
1423 | */ |
1424 | if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current)) |
1425 | fctx->step = 0; |
1426 | |
1427 | /* do when there is more left to send */ |
1428 | SRF_RETURN_NEXT(funcctx, Int32GetDatum(result)); |
1429 | } |
1430 | else |
1431 | /* do when there is no more left */ |
1432 | SRF_RETURN_DONE(funcctx); |
1433 | } |
1434 | |
1435 | /* |
1436 | * Planner support function for generate_series(int4, int4 [, int4]) |
1437 | */ |
1438 | Datum |
1439 | generate_series_int4_support(PG_FUNCTION_ARGS) |
1440 | { |
1441 | Node *rawreq = (Node *) PG_GETARG_POINTER(0); |
1442 | Node *ret = NULL; |
1443 | |
1444 | if (IsA(rawreq, SupportRequestRows)) |
1445 | { |
1446 | /* Try to estimate the number of rows returned */ |
1447 | SupportRequestRows *req = (SupportRequestRows *) rawreq; |
1448 | |
1449 | if (is_funcclause(req->node)) /* be paranoid */ |
1450 | { |
1451 | List *args = ((FuncExpr *) req->node)->args; |
1452 | Node *arg1, |
1453 | *arg2, |
1454 | *arg3; |
1455 | |
1456 | /* We can use estimated argument values here */ |
1457 | arg1 = estimate_expression_value(req->root, linitial(args)); |
1458 | arg2 = estimate_expression_value(req->root, lsecond(args)); |
1459 | if (list_length(args) >= 3) |
1460 | arg3 = estimate_expression_value(req->root, lthird(args)); |
1461 | else |
1462 | arg3 = NULL; |
1463 | |
1464 | /* |
1465 | * If any argument is constant NULL, we can safely assume that |
1466 | * zero rows are returned. Otherwise, if they're all non-NULL |
1467 | * constants, we can calculate the number of rows that will be |
1468 | * returned. Use double arithmetic to avoid overflow hazards. |
1469 | */ |
1470 | if ((IsA(arg1, Const) && |
1471 | ((Const *) arg1)->constisnull) || |
1472 | (IsA(arg2, Const) && |
1473 | ((Const *) arg2)->constisnull) || |
1474 | (arg3 != NULL && IsA(arg3, Const) && |
1475 | ((Const *) arg3)->constisnull)) |
1476 | { |
1477 | req->rows = 0; |
1478 | ret = (Node *) req; |
1479 | } |
1480 | else if (IsA(arg1, Const) && |
1481 | IsA(arg2, Const) && |
1482 | (arg3 == NULL || IsA(arg3, Const))) |
1483 | { |
1484 | double start, |
1485 | finish, |
1486 | step; |
1487 | |
1488 | start = DatumGetInt32(((Const *) arg1)->constvalue); |
1489 | finish = DatumGetInt32(((Const *) arg2)->constvalue); |
1490 | step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1; |
1491 | |
1492 | /* This equation works for either sign of step */ |
1493 | if (step != 0) |
1494 | { |
1495 | req->rows = floor((finish - start + step) / step); |
1496 | ret = (Node *) req; |
1497 | } |
1498 | } |
1499 | } |
1500 | } |
1501 | |
1502 | PG_RETURN_POINTER(ret); |
1503 | } |
1504 | |