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