Age Owner 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-2023, 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
8343 tgl 63 CBC 2839236 : int2in(PG_FUNCTION_ARGS)
64 : {
65 2839236 : char *num = PG_GETARG_CSTRING(0);
66 :
121 tgl 67 GNC 2839236 : PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
68 : }
69 :
70 : /*
71 : * int2out - converts short to "num"
72 : */
73 : Datum
8343 tgl 74 CBC 113118 : int2out(PG_FUNCTION_ARGS)
75 : {
76 113118 : int16 arg1 = PG_GETARG_INT16(0);
8053 bruce 77 113118 : char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
78 :
8286 tgl 79 113118 : pg_itoa(arg1, result);
8343 80 113118 : PG_RETURN_CSTRING(result);
81 : }
82 :
83 : /*
84 : * int2recv - converts external binary format to int2
85 : */
86 : Datum
7275 tgl 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
7275 tgl 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);
2006 andres 104 2 : pq_sendint16(&buf, arg1);
7275 tgl 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 *
3940 peter_e 114 137840 : buildint2vector(const int16 *int2s, int n)
115 : {
116 : int2vector *result;
117 :
6585 tgl 118 137840 : result = (int2vector *) palloc0(Int2VectorSize(n));
119 :
120 137840 : if (n > 0 && int2s)
3940 peter_e 121 67627 : 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 : */
5885 tgl 127 137840 : SET_VARSIZE(result, Int2VectorSize(n));
6585 128 137840 : result->ndim = 1;
6352 129 137840 : result->dataoffset = 0; /* never any nulls */
6585 130 137840 : result->elemtype = INT2OID;
131 137840 : result->dim1 = n;
132 137840 : result->lbound1 = 0;
133 :
134 137840 : return result;
135 : }
136 :
137 : /*
138 : * int2vectorin - converts "num num ..." to internal form
139 : */
140 : Datum
8343 141 271 : int2vectorin(PG_FUNCTION_ARGS)
142 : {
143 271 : char *intString = PG_GETARG_CSTRING(0);
116 tgl 144 GNC 271 : Node *escontext = fcinfo->context;
6585 tgl 145 ECB : int2vector *result;
146 : int nalloc;
147 : int n;
148 :
84 tgl 149 GIC 271 : nalloc = 32; /* arbitrary initial size guess */
84 tgl 150 CBC 271 : result = (int2vector *) palloc0(Int2VectorSize(nalloc));
9345 bruce 151 ECB :
84 tgl 152 GIC 271 : for (n = 0;; n++)
9345 bruce 153 CBC 469 : {
419 peter 154 ECB : long l;
155 : char *endp;
156 :
8162 tgl 157 GIC 953 : while (*intString && isspace((unsigned char) *intString))
8490 bruce 158 CBC 213 : intString++;
4848 rhaas 159 740 : if (*intString == '\0')
4790 bruce 160 265 : break;
419 peter 161 ECB :
84 tgl 162 GIC 475 : if (n >= nalloc)
84 tgl 163 ECB : {
84 tgl 164 UIC 0 : nalloc *= 2;
84 tgl 165 UBC 0 : result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
84 tgl 166 EUB : }
167 :
419 peter 168 GIC 475 : errno = 0;
419 peter 169 CBC 475 : l = strtol(intString, &endp, 10);
419 peter 170 ECB :
419 peter 171 GIC 475 : if (intString == endp)
116 tgl 172 GNC 6 : ereturn(escontext, (Datum) 0,
419 peter 173 ECB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
174 : errmsg("invalid input syntax for type %s: \"%s\"",
175 : "smallint", intString)));
176 :
419 peter 177 GIC 472 : if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
116 tgl 178 GNC 3 : ereturn(escontext, (Datum) 0,
419 peter 179 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
180 : errmsg("value \"%s\" is out of range for type %s", intString,
181 : "smallint")));
182 :
419 peter 183 GIC 469 : if (*endp && *endp != ' ')
116 tgl 184 UNC 0 : ereturn(escontext, (Datum) 0,
419 peter 185 EUB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
186 : errmsg("invalid input syntax for type %s: \"%s\"",
187 : "smallint", intString)));
188 :
419 peter 189 GIC 469 : result->values[n] = l;
419 peter 190 CBC 469 : intString = endp;
9345 bruce 191 ECB : }
192 :
5885 tgl 193 GIC 265 : SET_VARSIZE(result, Int2VectorSize(n));
6585 tgl 194 CBC 265 : result->ndim = 1;
6352 195 265 : result->dataoffset = 0; /* never any nulls */
6585 196 265 : result->elemtype = INT2OID;
197 265 : result->dim1 = n;
198 265 : result->lbound1 = 0;
8490 bruce 199 ECB :
8343 tgl 200 GIC 265 : PG_RETURN_POINTER(result);
9770 scrappy 201 ECB : }
202 :
203 : /*
204 : * int2vectorout - converts internal form to "num num ..."
205 : */
206 : Datum
8343 tgl 207 GIC 2112 : int2vectorout(PG_FUNCTION_ARGS)
9345 bruce 208 ECB : {
6585 tgl 209 GIC 2112 : int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
8397 bruce 210 ECB : int num,
6585 tgl 211 GIC 2112 : nnums = int2Array->dim1;
9173 bruce 212 ECB : char *rp;
213 : char *result;
214 :
215 : /* assumes sign, 5 digits, ' ' */
6585 tgl 216 GIC 2112 : rp = result = (char *) palloc(nnums * 7 + 1);
6585 tgl 217 CBC 5592 : for (num = 0; num < nnums; num++)
9345 bruce 218 ECB : {
8490 bruce 219 GIC 3480 : if (num != 0)
8490 bruce 220 CBC 1368 : *rp++ = ' ';
1030 drowley 221 3480 : rp += pg_itoa(int2Array->values[num], rp);
9345 bruce 222 ECB : }
8490 bruce 223 GIC 2112 : *rp = '\0';
8343 tgl 224 CBC 2112 : PG_RETURN_CSTRING(result);
9770 scrappy 225 ECB : }
226 :
227 : /*
228 : * int2vectorrecv - converts external binary format to int2vector
229 : */
230 : Datum
7275 tgl 231 UIC 0 : int2vectorrecv(PG_FUNCTION_ARGS)
7275 tgl 232 EUB : {
1534 andres 233 UIC 0 : LOCAL_FCINFO(locfcinfo, 3);
7275 tgl 234 UBC 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
6385 bruce 235 EUB : 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 : */
1534 andres 243 UIC 0 : InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
4380 tgl 244 EUB : InvalidOid, NULL, NULL);
245 :
1534 andres 246 UIC 0 : locfcinfo->args[0].value = PointerGetDatum(buf);
1534 andres 247 UBC 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;
6247 tgl 252 EUB :
1534 andres 253 UIC 0 : result = (int2vector *) DatumGetPointer(array_recv(locfcinfo));
6247 tgl 254 EUB :
1534 andres 255 UIC 0 : Assert(!locfcinfo->isnull);
6247 tgl 256 EUB :
257 : /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
6352 tgl 258 UIC 0 : if (ARR_NDIM(result) != 1 ||
6352 tgl 259 UBC 0 : ARR_HASNULL(result) ||
4965 heikki.linnakangas 260 0 : ARR_ELEMTYPE(result) != INT2OID ||
261 0 : ARR_LBOUND(result)[0] != 0)
6585 tgl 262 0 : ereport(ERROR,
6585 tgl 263 EUB : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
264 : errmsg("invalid int2vector data")));
265 :
7275 tgl 266 UIC 0 : PG_RETURN_POINTER(result);
7275 tgl 267 EUB : }
268 :
269 : /*
270 : * int2vectorsend - converts int2vector to binary format
271 : */
272 : Datum
7275 tgl 273 UIC 0 : int2vectorsend(PG_FUNCTION_ARGS)
7275 tgl 274 EUB : {
6585 tgl 275 UIC 0 : return array_send(fcinfo);
7275 tgl 276 EUB : }
277 :
278 :
279 : /*****************************************************************************
280 : * PUBLIC ROUTINES *
281 : *****************************************************************************/
282 :
283 : /*
284 : * int4in - converts "num" to int4
285 : */
286 : Datum
8343 tgl 287 GIC 3478435 : int4in(PG_FUNCTION_ARGS)
9770 scrappy 288 ECB : {
8343 tgl 289 GIC 3478435 : char *num = PG_GETARG_CSTRING(0);
8343 tgl 290 ECB :
121 tgl 291 GNC 3478435 : PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
9770 scrappy 292 ECB : }
293 :
294 : /*
295 : * int4out - converts int4 to "num"
296 : */
297 : Datum
8343 tgl 298 GIC 8918775 : int4out(PG_FUNCTION_ARGS)
9770 scrappy 299 ECB : {
8343 tgl 300 GIC 8918775 : int32 arg1 = PG_GETARG_INT32(0);
8053 bruce 301 CBC 8918775 : char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
9345 bruce 302 ECB :
8286 tgl 303 GIC 8918775 : pg_ltoa(arg1, result);
8343 tgl 304 CBC 8918775 : PG_RETURN_CSTRING(result);
9770 scrappy 305 ECB : }
306 :
307 : /*
308 : * int4recv - converts external binary format to int4
309 : */
310 : Datum
7275 tgl 311 GIC 101435 : int4recv(PG_FUNCTION_ARGS)
7275 tgl 312 ECB : {
7275 tgl 313 GIC 101435 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
7275 tgl 314 ECB :
7275 tgl 315 GIC 101435 : PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
7275 tgl 316 ECB : }
317 :
318 : /*
319 : * int4send - converts int4 to binary format
320 : */
321 : Datum
7275 tgl 322 GIC 84072 : int4send(PG_FUNCTION_ARGS)
7275 tgl 323 ECB : {
7275 tgl 324 GIC 84072 : int32 arg1 = PG_GETARG_INT32(0);
7275 tgl 325 ECB : StringInfoData buf;
326 :
7275 tgl 327 GIC 84072 : pq_begintypsend(&buf);
2006 andres 328 CBC 84072 : pq_sendint32(&buf, arg1);
7275 tgl 329 84072 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
7275 tgl 330 ECB : }
331 :
332 :
333 : /*
334 : * ===================
335 : * CONVERSION ROUTINES
336 : * ===================
337 : */
338 :
339 : Datum
8343 tgl 340 GIC 20649 : i2toi4(PG_FUNCTION_ARGS)
9770 scrappy 341 ECB : {
8343 tgl 342 GIC 20649 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 343 ECB :
8343 tgl 344 GIC 20649 : PG_RETURN_INT32((int32) arg1);
9770 scrappy 345 ECB : }
346 :
347 : Datum
8343 tgl 348 GIC 1951 : i4toi2(PG_FUNCTION_ARGS)
9770 scrappy 349 ECB : {
8343 tgl 350 GIC 1951 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 351 ECB :
1944 andres 352 GIC 1951 : if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
7196 tgl 353 CBC 14 : ereport(ERROR,
7196 tgl 354 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
355 : errmsg("smallint out of range")));
356 :
8343 tgl 357 GIC 1937 : PG_RETURN_INT16((int16) arg1);
9770 scrappy 358 ECB : }
359 :
360 : /* Cast int4 -> bool */
361 : Datum
6615 neilc 362 UIC 0 : int4_bool(PG_FUNCTION_ARGS)
6615 neilc 363 EUB : {
6615 neilc 364 UIC 0 : if (PG_GETARG_INT32(0) == 0)
6615 neilc 365 UBC 0 : PG_RETURN_BOOL(false);
6615 neilc 366 EUB : else
6615 neilc 367 UIC 0 : PG_RETURN_BOOL(true);
6615 neilc 368 EUB : }
369 :
370 : /* Cast bool -> int4 */
371 : Datum
6615 neilc 372 GIC 737 : bool_int4(PG_FUNCTION_ARGS)
6615 neilc 373 ECB : {
6615 neilc 374 GIC 737 : if (PG_GETARG_BOOL(0) == false)
6615 neilc 375 CBC 373 : PG_RETURN_INT32(0);
6615 neilc 376 ECB : else
6615 neilc 377 GIC 364 : PG_RETURN_INT32(1);
6615 neilc 378 ECB : }
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
8343 tgl 396 GIC 18273345 : int4eq(PG_FUNCTION_ARGS)
9345 bruce 397 ECB : {
8343 tgl 398 GIC 18273345 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 399 CBC 18273345 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 400 ECB :
8343 tgl 401 GIC 18273345 : PG_RETURN_BOOL(arg1 == arg2);
9345 bruce 402 ECB : }
403 :
404 : Datum
8343 tgl 405 GIC 214016 : int4ne(PG_FUNCTION_ARGS)
9345 bruce 406 ECB : {
8343 tgl 407 GIC 214016 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 408 CBC 214016 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 409 ECB :
8343 tgl 410 GIC 214016 : PG_RETURN_BOOL(arg1 != arg2);
9345 bruce 411 ECB : }
412 :
413 : Datum
8343 tgl 414 GIC 110223409 : int4lt(PG_FUNCTION_ARGS)
9345 bruce 415 ECB : {
8343 tgl 416 GIC 110223409 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 417 CBC 110223409 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 418 ECB :
8343 tgl 419 GIC 110223409 : PG_RETURN_BOOL(arg1 < arg2);
9345 bruce 420 ECB : }
421 :
422 : Datum
8343 tgl 423 GIC 551927 : int4le(PG_FUNCTION_ARGS)
9345 bruce 424 ECB : {
8343 tgl 425 GIC 551927 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 426 CBC 551927 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 427 ECB :
8343 tgl 428 GIC 551927 : PG_RETURN_BOOL(arg1 <= arg2);
9345 bruce 429 ECB : }
430 :
431 : Datum
8343 tgl 432 GIC 1573183 : int4gt(PG_FUNCTION_ARGS)
9345 bruce 433 ECB : {
8343 tgl 434 GIC 1573183 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 435 CBC 1573183 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 436 ECB :
8343 tgl 437 GIC 1573183 : PG_RETURN_BOOL(arg1 > arg2);
9345 bruce 438 ECB : }
439 :
440 : Datum
8343 tgl 441 GIC 265957 : int4ge(PG_FUNCTION_ARGS)
9345 bruce 442 ECB : {
8343 tgl 443 GIC 265957 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 444 CBC 265957 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 445 ECB :
8343 tgl 446 GIC 265957 : PG_RETURN_BOOL(arg1 >= arg2);
9345 bruce 447 ECB : }
448 :
449 : Datum
8343 tgl 450 GIC 1288410 : int2eq(PG_FUNCTION_ARGS)
9345 bruce 451 ECB : {
8343 tgl 452 GIC 1288410 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 453 CBC 1288410 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 454 ECB :
8343 tgl 455 GIC 1288410 : PG_RETURN_BOOL(arg1 == arg2);
9345 bruce 456 ECB : }
457 :
458 : Datum
8343 tgl 459 GIC 14939 : int2ne(PG_FUNCTION_ARGS)
9345 bruce 460 ECB : {
8343 tgl 461 GIC 14939 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 462 CBC 14939 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 463 ECB :
8343 tgl 464 GIC 14939 : PG_RETURN_BOOL(arg1 != arg2);
9345 bruce 465 ECB : }
466 :
467 : Datum
8343 tgl 468 GIC 267202 : int2lt(PG_FUNCTION_ARGS)
9345 bruce 469 ECB : {
8343 tgl 470 GIC 267202 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 471 CBC 267202 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 472 ECB :
8343 tgl 473 GIC 267202 : PG_RETURN_BOOL(arg1 < arg2);
9345 bruce 474 ECB : }
475 :
476 : Datum
8343 tgl 477 GIC 2393 : int2le(PG_FUNCTION_ARGS)
9345 bruce 478 ECB : {
8343 tgl 479 GIC 2393 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 480 CBC 2393 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 481 ECB :
8343 tgl 482 GIC 2393 : PG_RETURN_BOOL(arg1 <= arg2);
9345 bruce 483 ECB : }
484 :
485 : Datum
8343 tgl 486 GIC 3856887 : int2gt(PG_FUNCTION_ARGS)
9345 bruce 487 ECB : {
8343 tgl 488 GIC 3856887 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 489 CBC 3856887 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 490 ECB :
8343 tgl 491 GIC 3856887 : PG_RETURN_BOOL(arg1 > arg2);
9345 bruce 492 ECB : }
493 :
494 : Datum
8343 tgl 495 GIC 1857 : int2ge(PG_FUNCTION_ARGS)
9345 bruce 496 ECB : {
8343 tgl 497 GIC 1857 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 498 CBC 1857 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 499 ECB :
8343 tgl 500 GIC 1857 : PG_RETURN_BOOL(arg1 >= arg2);
9345 bruce 501 ECB : }
502 :
503 : Datum
8343 tgl 504 GIC 60330 : int24eq(PG_FUNCTION_ARGS)
9345 bruce 505 ECB : {
8343 tgl 506 GIC 60330 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 507 CBC 60330 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 508 ECB :
8343 tgl 509 GIC 60330 : PG_RETURN_BOOL(arg1 == arg2);
9345 bruce 510 ECB : }
511 :
512 : Datum
8343 tgl 513 GIC 37200 : int24ne(PG_FUNCTION_ARGS)
9345 bruce 514 ECB : {
8343 tgl 515 GIC 37200 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 516 CBC 37200 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 517 ECB :
8343 tgl 518 GIC 37200 : PG_RETURN_BOOL(arg1 != arg2);
9345 bruce 519 ECB : }
520 :
521 : Datum
8343 tgl 522 GIC 63441 : int24lt(PG_FUNCTION_ARGS)
9345 bruce 523 ECB : {
8343 tgl 524 GIC 63441 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 525 CBC 63441 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 526 ECB :
8343 tgl 527 GIC 63441 : PG_RETURN_BOOL(arg1 < arg2);
9345 bruce 528 ECB : }
529 :
530 : Datum
8343 tgl 531 GIC 26492 : int24le(PG_FUNCTION_ARGS)
9345 bruce 532 ECB : {
8343 tgl 533 GIC 26492 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 534 CBC 26492 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 535 ECB :
8343 tgl 536 GIC 26492 : PG_RETURN_BOOL(arg1 <= arg2);
9345 bruce 537 ECB : }
538 :
539 : Datum
8343 tgl 540 GIC 232933 : int24gt(PG_FUNCTION_ARGS)
9345 bruce 541 ECB : {
8343 tgl 542 GIC 232933 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 543 CBC 232933 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 544 ECB :
8343 tgl 545 GIC 232933 : PG_RETURN_BOOL(arg1 > arg2);
9345 bruce 546 ECB : }
547 :
548 : Datum
8343 tgl 549 GIC 11285 : int24ge(PG_FUNCTION_ARGS)
9345 bruce 550 ECB : {
8343 tgl 551 GIC 11285 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 552 CBC 11285 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 553 ECB :
8343 tgl 554 GIC 11285 : PG_RETURN_BOOL(arg1 >= arg2);
9345 bruce 555 ECB : }
556 :
557 : Datum
8343 tgl 558 GIC 62694 : int42eq(PG_FUNCTION_ARGS)
9345 bruce 559 ECB : {
8343 tgl 560 GIC 62694 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 561 CBC 62694 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 562 ECB :
8343 tgl 563 GIC 62694 : PG_RETURN_BOOL(arg1 == arg2);
9345 bruce 564 ECB : }
565 :
566 : Datum
8343 tgl 567 GIC 15 : int42ne(PG_FUNCTION_ARGS)
9345 bruce 568 ECB : {
8343 tgl 569 GIC 15 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 570 CBC 15 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 571 ECB :
8343 tgl 572 GIC 15 : PG_RETURN_BOOL(arg1 != arg2);
9345 bruce 573 ECB : }
574 :
575 : Datum
8343 tgl 576 GIC 7202 : int42lt(PG_FUNCTION_ARGS)
9345 bruce 577 ECB : {
8343 tgl 578 GIC 7202 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 579 CBC 7202 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 580 ECB :
8343 tgl 581 GIC 7202 : PG_RETURN_BOOL(arg1 < arg2);
9345 bruce 582 ECB : }
583 :
584 : Datum
8343 tgl 585 GIC 7162 : int42le(PG_FUNCTION_ARGS)
9345 bruce 586 ECB : {
8343 tgl 587 GIC 7162 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 588 CBC 7162 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 589 ECB :
8343 tgl 590 GIC 7162 : PG_RETURN_BOOL(arg1 <= arg2);
9345 bruce 591 ECB : }
592 :
593 : Datum
8343 tgl 594 GIC 1614 : int42gt(PG_FUNCTION_ARGS)
9345 bruce 595 ECB : {
8343 tgl 596 GIC 1614 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 597 CBC 1614 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 598 ECB :
8343 tgl 599 GIC 1614 : PG_RETURN_BOOL(arg1 > arg2);
9345 bruce 600 ECB : }
601 :
602 : Datum
8343 tgl 603 GIC 1728 : int42ge(PG_FUNCTION_ARGS)
9345 bruce 604 ECB : {
8343 tgl 605 GIC 1728 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 606 CBC 1728 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 607 ECB :
8343 tgl 608 GIC 1728 : PG_RETURN_BOOL(arg1 >= arg2);
9345 bruce 609 ECB : }
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
1887 tgl 623 GIC 1599 : in_range_int4_int4(PG_FUNCTION_ARGS)
1887 tgl 624 ECB : {
1887 tgl 625 GIC 1599 : int32 val = PG_GETARG_INT32(0);
1887 tgl 626 CBC 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);
1887 tgl 630 ECB : int32 sum;
631 :
1887 tgl 632 GIC 1599 : if (offset < 0)
1887 tgl 633 CBC 6 : ereport(ERROR,
1763 peter_e 634 ECB : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
635 : errmsg("invalid preceding or following size in window function")));
636 :
1887 tgl 637 GIC 1593 : if (sub)
1887 tgl 638 CBC 720 : offset = -offset; /* cannot overflow */
1887 tgl 639 ECB :
1887 tgl 640 GIC 1593 : if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
1887 tgl 641 ECB : {
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 : */
1887 tgl 647 GIC 18 : PG_RETURN_BOOL(sub ? !less : less);
1887 tgl 648 ECB : }
649 :
1887 tgl 650 GIC 1575 : if (less)
1887 tgl 651 CBC 930 : PG_RETURN_BOOL(val <= sum);
1887 tgl 652 ECB : else
1887 tgl 653 GIC 645 : PG_RETURN_BOOL(val >= sum);
1887 tgl 654 ECB : }
655 :
656 : Datum
1887 tgl 657 GIC 453 : in_range_int4_int2(PG_FUNCTION_ARGS)
1887 tgl 658 ECB : {
659 : /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
1887 tgl 660 GIC 453 : return DirectFunctionCall5(in_range_int4_int4,
1887 tgl 661 ECB : 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
1887 tgl 669 GIC 381 : in_range_int4_int8(PG_FUNCTION_ARGS)
1887 tgl 670 ECB : {
671 : /* We must do all the math in int64 */
1887 tgl 672 GIC 381 : int64 val = (int64) PG_GETARG_INT32(0);
1887 tgl 673 CBC 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);
1887 tgl 677 ECB : int64 sum;
678 :
1887 tgl 679 GIC 381 : if (offset < 0)
1887 tgl 680 LBC 0 : ereport(ERROR,
1763 peter_e 681 EUB : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
682 : errmsg("invalid preceding or following size in window function")));
683 :
1887 tgl 684 GIC 381 : if (sub)
1887 tgl 685 CBC 345 : offset = -offset; /* cannot overflow */
1887 tgl 686 ECB :
1887 tgl 687 GIC 381 : if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
1887 tgl 688 ECB : {
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 : */
1887 tgl 694 UIC 0 : PG_RETURN_BOOL(sub ? !less : less);
1887 tgl 695 EUB : }
696 :
1887 tgl 697 GIC 381 : if (less)
1887 tgl 698 CBC 36 : PG_RETURN_BOOL(val <= sum);
1887 tgl 699 ECB : else
1887 tgl 700 GIC 345 : PG_RETURN_BOOL(val >= sum);
1887 tgl 701 ECB : }
702 :
703 : Datum
1887 tgl 704 GIC 18 : in_range_int2_int4(PG_FUNCTION_ARGS)
1887 tgl 705 ECB : {
706 : /* We must do all the math in int32 */
1887 tgl 707 GIC 18 : int32 val = (int32) PG_GETARG_INT16(0);
1887 tgl 708 CBC 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);
1887 tgl 712 ECB : int32 sum;
713 :
1887 tgl 714 GIC 18 : if (offset < 0)
1887 tgl 715 LBC 0 : ereport(ERROR,
1763 peter_e 716 EUB : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
717 : errmsg("invalid preceding or following size in window function")));
718 :
1887 tgl 719 GIC 18 : if (sub)
1887 tgl 720 CBC 9 : offset = -offset; /* cannot overflow */
1887 tgl 721 ECB :
1887 tgl 722 GIC 18 : if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
1887 tgl 723 ECB : {
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 : */
1887 tgl 729 GIC 18 : PG_RETURN_BOOL(sub ? !less : less);
1887 tgl 730 ECB : }
731 :
1887 tgl 732 UIC 0 : if (less)
1887 tgl 733 UBC 0 : PG_RETURN_BOOL(val <= sum);
1887 tgl 734 EUB : else
1887 tgl 735 UIC 0 : PG_RETURN_BOOL(val >= sum);
1887 tgl 736 EUB : }
737 :
738 : Datum
1887 tgl 739 UIC 0 : in_range_int2_int2(PG_FUNCTION_ARGS)
1887 tgl 740 EUB : {
741 : /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
1887 tgl 742 UIC 0 : return DirectFunctionCall5(in_range_int2_int4,
1887 tgl 743 EUB : 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
1887 tgl 751 UIC 0 : in_range_int2_int8(PG_FUNCTION_ARGS)
1887 tgl 752 EUB : {
753 : /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
1887 tgl 754 UIC 0 : return DirectFunctionCall5(in_range_int4_int8,
1887 tgl 755 EUB : 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
8343 tgl 771 GIC 25866 : int4um(PG_FUNCTION_ARGS)
9345 bruce 772 ECB : {
8343 tgl 773 GIC 25866 : int32 arg = PG_GETARG_INT32(0);
8343 tgl 774 ECB :
1944 andres 775 GIC 25866 : if (unlikely(arg == PG_INT32_MIN))
6761 tgl 776 LBC 0 : ereport(ERROR,
6761 tgl 777 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
778 : errmsg("integer out of range")));
1944 andres 779 GIC 25866 : PG_RETURN_INT32(-arg);
9345 bruce 780 ECB : }
781 :
782 : Datum
7976 bruce 783 GIC 3 : int4up(PG_FUNCTION_ARGS)
7976 bruce 784 ECB : {
7976 bruce 785 GIC 3 : int32 arg = PG_GETARG_INT32(0);
7976 bruce 786 ECB :
7976 bruce 787 GIC 3 : PG_RETURN_INT32(arg);
7976 bruce 788 ECB : }
789 :
790 : Datum
8343 tgl 791 GIC 1636336 : int4pl(PG_FUNCTION_ARGS)
9345 bruce 792 ECB : {
8343 tgl 793 GIC 1636336 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 794 CBC 1636336 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 795 ECB : int32 result;
796 :
1944 andres 797 GIC 1636336 : if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
6761 tgl 798 CBC 3 : ereport(ERROR,
6761 tgl 799 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
800 : errmsg("integer out of range")));
6761 tgl 801 GIC 1636333 : PG_RETURN_INT32(result);
9345 bruce 802 ECB : }
803 :
804 : Datum
8343 tgl 805 GIC 699968 : int4mi(PG_FUNCTION_ARGS)
9345 bruce 806 ECB : {
8343 tgl 807 GIC 699968 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 808 CBC 699968 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 809 ECB : int32 result;
810 :
1944 andres 811 GIC 699968 : if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
6761 tgl 812 CBC 3 : ereport(ERROR,
6761 tgl 813 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
814 : errmsg("integer out of range")));
6761 tgl 815 GIC 699965 : PG_RETURN_INT32(result);
9345 bruce 816 ECB : }
817 :
818 : Datum
8343 tgl 819 GIC 1411530 : int4mul(PG_FUNCTION_ARGS)
9345 bruce 820 ECB : {
8343 tgl 821 GIC 1411530 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 822 CBC 1411530 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 823 ECB : int32 result;
824 :
1944 andres 825 GIC 1411530 : if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
6761 tgl 826 CBC 9 : ereport(ERROR,
6761 tgl 827 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
828 : errmsg("integer out of range")));
6761 tgl 829 GIC 1411521 : PG_RETURN_INT32(result);
9345 bruce 830 ECB : }
831 :
832 : Datum
8343 tgl 833 GIC 730087 : int4div(PG_FUNCTION_ARGS)
9345 bruce 834 ECB : {
8343 tgl 835 GIC 730087 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 836 CBC 730087 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 837 ECB : int32 result;
838 :
7334 tgl 839 GIC 730087 : if (arg2 == 0)
4412 tgl 840 ECB : {
7196 tgl 841 GIC 130 : ereport(ERROR,
7196 tgl 842 ECB : (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 : */
3793 tgl 854 GIC 729957 : if (arg2 == -1)
3793 tgl 855 ECB : {
1944 andres 856 GIC 8 : if (unlikely(arg1 == PG_INT32_MIN))
3793 tgl 857 CBC 3 : ereport(ERROR,
3793 tgl 858 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
859 : errmsg("integer out of range")));
1944 andres 860 GIC 5 : result = -arg1;
3793 tgl 861 CBC 5 : PG_RETURN_INT32(result);
3793 tgl 862 ECB : }
863 :
864 : /* No overflow is possible */
865 :
6761 tgl 866 GIC 729949 : result = arg1 / arg2;
6385 bruce 867 ECB :
6761 tgl 868 GIC 729949 : PG_RETURN_INT32(result);
9345 bruce 869 ECB : }
870 :
871 : Datum
8343 tgl 872 UIC 0 : int4inc(PG_FUNCTION_ARGS)
9345 bruce 873 EUB : {
8343 tgl 874 UIC 0 : int32 arg = PG_GETARG_INT32(0);
6761 tgl 875 EUB : int32 result;
876 :
1944 andres 877 UIC 0 : if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
6761 tgl 878 UBC 0 : ereport(ERROR,
6761 tgl 879 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
880 : errmsg("integer out of range")));
881 :
6761 tgl 882 UIC 0 : PG_RETURN_INT32(result);
9345 bruce 883 EUB : }
884 :
885 : Datum
8343 tgl 886 GIC 9 : int2um(PG_FUNCTION_ARGS)
9345 bruce 887 ECB : {
8343 tgl 888 GIC 9 : int16 arg = PG_GETARG_INT16(0);
8343 tgl 889 ECB :
1944 andres 890 GIC 9 : if (unlikely(arg == PG_INT16_MIN))
6761 tgl 891 LBC 0 : ereport(ERROR,
6761 tgl 892 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
893 : errmsg("smallint out of range")));
1944 andres 894 GIC 9 : PG_RETURN_INT16(-arg);
9345 bruce 895 ECB : }
896 :
897 : Datum
7976 bruce 898 UIC 0 : int2up(PG_FUNCTION_ARGS)
7976 bruce 899 EUB : {
7976 bruce 900 UIC 0 : int16 arg = PG_GETARG_INT16(0);
7976 bruce 901 EUB :
7976 bruce 902 UIC 0 : PG_RETURN_INT16(arg);
7976 bruce 903 EUB : }
904 :
905 : Datum
8343 tgl 906 GIC 27 : int2pl(PG_FUNCTION_ARGS)
9345 bruce 907 ECB : {
8343 tgl 908 GIC 27 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 909 CBC 27 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 910 ECB : int16 result;
911 :
1944 andres 912 GIC 27 : if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
6761 tgl 913 CBC 3 : ereport(ERROR,
6761 tgl 914 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
915 : errmsg("smallint out of range")));
6761 tgl 916 GIC 24 : PG_RETURN_INT16(result);
9345 bruce 917 ECB : }
918 :
919 : Datum
8343 tgl 920 GIC 60 : int2mi(PG_FUNCTION_ARGS)
9345 bruce 921 ECB : {
8343 tgl 922 GIC 60 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 923 CBC 60 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 924 ECB : int16 result;
925 :
1944 andres 926 GIC 60 : if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
6761 tgl 927 CBC 3 : ereport(ERROR,
6761 tgl 928 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
929 : errmsg("smallint out of range")));
6761 tgl 930 GIC 57 : PG_RETURN_INT16(result);
9345 bruce 931 ECB : }
932 :
933 : Datum
8343 tgl 934 GIC 27 : int2mul(PG_FUNCTION_ARGS)
9345 bruce 935 ECB : {
8343 tgl 936 GIC 27 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 937 CBC 27 : int16 arg2 = PG_GETARG_INT16(1);
1944 andres 938 ECB : int16 result;
939 :
1944 andres 940 GIC 27 : if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
6761 tgl 941 CBC 6 : ereport(ERROR,
6761 tgl 942 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
943 : errmsg("smallint out of range")));
944 :
1944 andres 945 GIC 21 : PG_RETURN_INT16(result);
9345 bruce 946 ECB : }
947 :
948 : Datum
8343 tgl 949 GIC 21 : int2div(PG_FUNCTION_ARGS)
9345 bruce 950 ECB : {
8343 tgl 951 GIC 21 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 952 CBC 21 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 953 ECB : int16 result;
954 :
7334 tgl 955 GIC 21 : if (arg2 == 0)
4412 tgl 956 ECB : {
7196 tgl 957 UIC 0 : ereport(ERROR,
7196 tgl 958 EUB : (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 : */
3793 tgl 970 GIC 21 : if (arg2 == -1)
3793 tgl 971 ECB : {
1944 andres 972 GIC 3 : if (unlikely(arg1 == PG_INT16_MIN))
3793 tgl 973 CBC 3 : ereport(ERROR,
3793 tgl 974 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
975 : errmsg("smallint out of range")));
1944 andres 976 UIC 0 : result = -arg1;
3793 tgl 977 UBC 0 : PG_RETURN_INT16(result);
3793 tgl 978 EUB : }
979 :
980 : /* No overflow is possible */
981 :
3793 tgl 982 GIC 18 : result = arg1 / arg2;
3793 tgl 983 ECB :
6761 tgl 984 GIC 18 : PG_RETURN_INT16(result);
9345 bruce 985 ECB : }
986 :
987 : Datum
8343 tgl 988 GIC 1104 : int24pl(PG_FUNCTION_ARGS)
9345 bruce 989 ECB : {
8343 tgl 990 GIC 1104 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 991 CBC 1104 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 992 ECB : int32 result;
993 :
1944 andres 994 GIC 1104 : if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
6761 tgl 995 LBC 0 : ereport(ERROR,
6761 tgl 996 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
997 : errmsg("integer out of range")));
6761 tgl 998 GIC 1104 : PG_RETURN_INT32(result);
9345 bruce 999 ECB : }
1000 :
1001 : Datum
8343 tgl 1002 GIC 12810 : int24mi(PG_FUNCTION_ARGS)
9345 bruce 1003 ECB : {
8343 tgl 1004 GIC 12810 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 1005 CBC 12810 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 1006 ECB : int32 result;
1007 :
1944 andres 1008 GIC 12810 : if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
6761 tgl 1009 LBC 0 : ereport(ERROR,
6761 tgl 1010 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1011 : errmsg("integer out of range")));
6761 tgl 1012 GIC 12810 : PG_RETURN_INT32(result);
9345 bruce 1013 ECB : }
1014 :
1015 : Datum
8343 tgl 1016 GIC 18 : int24mul(PG_FUNCTION_ARGS)
9345 bruce 1017 ECB : {
8343 tgl 1018 GIC 18 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 1019 CBC 18 : int32 arg2 = PG_GETARG_INT32(1);
6761 tgl 1020 ECB : int32 result;
1021 :
1944 andres 1022 GIC 18 : if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
6761 tgl 1023 LBC 0 : ereport(ERROR,
6761 tgl 1024 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1025 : errmsg("integer out of range")));
6761 tgl 1026 GIC 18 : PG_RETURN_INT32(result);
9345 bruce 1027 ECB : }
1028 :
1029 : Datum
8343 tgl 1030 GIC 21 : int24div(PG_FUNCTION_ARGS)
9345 bruce 1031 ECB : {
8343 tgl 1032 GIC 21 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 1033 CBC 21 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 1034 ECB :
1944 andres 1035 GIC 21 : if (unlikely(arg2 == 0))
4966 tgl 1036 ECB : {
7196 tgl 1037 GIC 3 : ereport(ERROR,
7196 tgl 1038 ECB : (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 */
6761 tgl 1045 GIC 18 : PG_RETURN_INT32((int32) arg1 / arg2);
9345 bruce 1046 ECB : }
1047 :
1048 : Datum
8343 tgl 1049 GIC 24 : int42pl(PG_FUNCTION_ARGS)
9345 bruce 1050 ECB : {
8343 tgl 1051 GIC 24 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1052 CBC 24 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 1053 ECB : int32 result;
1054 :
1944 andres 1055 GIC 24 : if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
6761 tgl 1056 CBC 3 : ereport(ERROR,
6761 tgl 1057 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1058 : errmsg("integer out of range")));
6761 tgl 1059 GIC 21 : PG_RETURN_INT32(result);
9345 bruce 1060 ECB : }
1061 :
1062 : Datum
8343 tgl 1063 GIC 27 : int42mi(PG_FUNCTION_ARGS)
9345 bruce 1064 ECB : {
8343 tgl 1065 GIC 27 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1066 CBC 27 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 1067 ECB : int32 result;
1068 :
1944 andres 1069 GIC 27 : if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
6761 tgl 1070 CBC 3 : ereport(ERROR,
6761 tgl 1071 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1072 : errmsg("integer out of range")));
6761 tgl 1073 GIC 24 : PG_RETURN_INT32(result);
9345 bruce 1074 ECB : }
1075 :
1076 : Datum
8343 tgl 1077 GIC 27 : int42mul(PG_FUNCTION_ARGS)
9345 bruce 1078 ECB : {
8343 tgl 1079 GIC 27 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1080 CBC 27 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 1081 ECB : int32 result;
1082 :
1944 andres 1083 GIC 27 : if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
6761 tgl 1084 CBC 6 : ereport(ERROR,
6761 tgl 1085 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1086 : errmsg("integer out of range")));
6761 tgl 1087 GIC 21 : PG_RETURN_INT32(result);
9345 bruce 1088 ECB : }
1089 :
1090 : Datum
8343 tgl 1091 GIC 24 : int42div(PG_FUNCTION_ARGS)
9345 bruce 1092 ECB : {
8343 tgl 1093 GIC 24 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1094 CBC 24 : int16 arg2 = PG_GETARG_INT16(1);
6761 tgl 1095 ECB : int32 result;
1096 :
1944 andres 1097 GIC 24 : if (unlikely(arg2 == 0))
4412 tgl 1098 ECB : {
7196 tgl 1099 GIC 3 : ereport(ERROR,
7196 tgl 1100 ECB : (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 : */
3793 tgl 1112 GIC 21 : if (arg2 == -1)
3793 tgl 1113 ECB : {
1944 andres 1114 GIC 3 : if (unlikely(arg1 == PG_INT32_MIN))
3793 tgl 1115 CBC 3 : ereport(ERROR,
3793 tgl 1116 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1117 : errmsg("integer out of range")));
1944 andres 1118 UIC 0 : result = -arg1;
3793 tgl 1119 UBC 0 : PG_RETURN_INT32(result);
3793 tgl 1120 EUB : }
1121 :
1122 : /* No overflow is possible */
1123 :
3793 tgl 1124 GIC 18 : result = arg1 / arg2;
3793 tgl 1125 ECB :
6761 tgl 1126 GIC 18 : PG_RETURN_INT32(result);
9345 bruce 1127 ECB : }
1128 :
1129 : Datum
8343 tgl 1130 GIC 3552563 : int4mod(PG_FUNCTION_ARGS)
9345 bruce 1131 ECB : {
8343 tgl 1132 GIC 3552563 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1133 CBC 3552563 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 1134 ECB :
1944 andres 1135 GIC 3552563 : if (unlikely(arg2 == 0))
4412 tgl 1136 ECB : {
7196 tgl 1137 UIC 0 : ereport(ERROR,
7196 tgl 1138 EUB : (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 : */
3798 tgl 1149 GIC 3552563 : if (arg2 == -1)
5941 bruce 1150 CBC 6 : PG_RETURN_INT32(0);
5941 bruce 1151 ECB :
1152 : /* No overflow is possible */
1153 :
8343 tgl 1154 GIC 3552557 : PG_RETURN_INT32(arg1 % arg2);
9345 bruce 1155 ECB : }
1156 :
1157 : Datum
8343 tgl 1158 GIC 18 : int2mod(PG_FUNCTION_ARGS)
9345 bruce 1159 ECB : {
8343 tgl 1160 GIC 18 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 1161 CBC 18 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 1162 ECB :
1944 andres 1163 GIC 18 : if (unlikely(arg2 == 0))
4412 tgl 1164 ECB : {
7196 tgl 1165 UIC 0 : ereport(ERROR,
7196 tgl 1166 EUB : (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 : */
3798 tgl 1178 GIC 18 : if (arg2 == -1)
3798 tgl 1179 CBC 3 : PG_RETURN_INT16(0);
3798 tgl 1180 ECB :
1181 : /* No overflow is possible */
1182 :
8343 tgl 1183 GIC 15 : PG_RETURN_INT16(arg1 % arg2);
9345 bruce 1184 ECB : }
1185 :
1186 :
1187 : /* int[24]abs()
1188 : * Absolute value
1189 : */
1190 : Datum
8343 tgl 1191 GIC 64405 : int4abs(PG_FUNCTION_ARGS)
8426 lockhart 1192 ECB : {
8343 tgl 1193 GIC 64405 : int32 arg1 = PG_GETARG_INT32(0);
6761 tgl 1194 ECB : int32 result;
1195 :
1944 andres 1196 GIC 64405 : if (unlikely(arg1 == PG_INT32_MIN))
6761 tgl 1197 LBC 0 : ereport(ERROR,
6761 tgl 1198 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1199 : errmsg("integer out of range")));
1944 andres 1200 GIC 64405 : result = (arg1 < 0) ? -arg1 : arg1;
6761 tgl 1201 CBC 64405 : PG_RETURN_INT32(result);
8426 lockhart 1202 ECB : }
1203 :
1204 : Datum
8343 tgl 1205 GIC 15 : int2abs(PG_FUNCTION_ARGS)
8426 lockhart 1206 ECB : {
8343 tgl 1207 GIC 15 : int16 arg1 = PG_GETARG_INT16(0);
6761 tgl 1208 ECB : int16 result;
1209 :
1944 andres 1210 GIC 15 : if (unlikely(arg1 == PG_INT16_MIN))
6761 tgl 1211 LBC 0 : ereport(ERROR,
6761 tgl 1212 EUB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1213 : errmsg("smallint out of range")));
1944 andres 1214 GIC 15 : result = (arg1 < 0) ? -arg1 : arg1;
6761 tgl 1215 CBC 15 : PG_RETURN_INT16(result);
8426 lockhart 1216 ECB : }
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
1170 dean.a.rasheed 1233 GIC 132 : int4gcd_internal(int32 arg1, int32 arg2)
1170 dean.a.rasheed 1234 ECB : {
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 : */
1170 dean.a.rasheed 1248 GIC 132 : a1 = (arg1 < 0) ? arg1 : -arg1;
1170 dean.a.rasheed 1249 CBC 132 : a2 = (arg2 < 0) ? arg2 : -arg2;
1250 132 : if (a1 > a2)
1170 dean.a.rasheed 1251 ECB : {
1170 dean.a.rasheed 1252 GIC 48 : swap = arg1;
1170 dean.a.rasheed 1253 CBC 48 : arg1 = arg2;
1254 48 : arg2 = swap;
1170 dean.a.rasheed 1255 ECB : }
1256 :
1257 : /* Special care needs to be taken with INT_MIN. See comments above. */
1170 dean.a.rasheed 1258 GIC 132 : if (arg1 == PG_INT32_MIN)
1170 dean.a.rasheed 1259 ECB : {
1170 dean.a.rasheed 1260 GIC 45 : if (arg2 == 0 || arg2 == PG_INT32_MIN)
1170 dean.a.rasheed 1261 CBC 6 : ereport(ERROR,
1170 dean.a.rasheed 1262 ECB : (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 : */
1170 dean.a.rasheed 1271 GIC 39 : if (arg2 == -1)
1170 dean.a.rasheed 1272 CBC 6 : return 1;
1170 dean.a.rasheed 1273 ECB : }
1274 :
1275 : /* Use the Euclidean algorithm to find the GCD */
1170 dean.a.rasheed 1276 GIC 471 : while (arg2 != 0)
1170 dean.a.rasheed 1277 ECB : {
1170 dean.a.rasheed 1278 GIC 351 : swap = arg2;
1170 dean.a.rasheed 1279 CBC 351 : arg2 = arg1 % arg2;
1280 351 : arg1 = swap;
1170 dean.a.rasheed 1281 ECB : }
1282 :
1283 : /*
1284 : * Make sure the result is positive. (We know we don't have INT_MIN
1285 : * anymore).
1286 : */
1170 dean.a.rasheed 1287 GIC 120 : if (arg1 < 0)
1170 dean.a.rasheed 1288 CBC 51 : arg1 = -arg1;
1170 dean.a.rasheed 1289 ECB :
1170 dean.a.rasheed 1290 GIC 120 : return arg1;
1170 dean.a.rasheed 1291 ECB : }
1292 :
1293 : Datum
1170 dean.a.rasheed 1294 GIC 90 : int4gcd(PG_FUNCTION_ARGS)
1170 dean.a.rasheed 1295 ECB : {
1060 tgl 1296 GIC 90 : int32 arg1 = PG_GETARG_INT32(0);
1060 tgl 1297 CBC 90 : int32 arg2 = PG_GETARG_INT32(1);
1060 tgl 1298 ECB : int32 result;
1299 :
1170 dean.a.rasheed 1300 GIC 90 : result = int4gcd_internal(arg1, arg2);
1170 dean.a.rasheed 1301 ECB :
1170 dean.a.rasheed 1302 GIC 84 : PG_RETURN_INT32(result);
1170 dean.a.rasheed 1303 ECB : }
1304 :
1305 : /*
1306 : * Least Common Multiple
1307 : */
1308 : Datum
1170 dean.a.rasheed 1309 GIC 78 : int4lcm(PG_FUNCTION_ARGS)
1170 dean.a.rasheed 1310 ECB : {
1060 tgl 1311 GIC 78 : int32 arg1 = PG_GETARG_INT32(0);
1060 tgl 1312 CBC 78 : int32 arg2 = PG_GETARG_INT32(1);
1060 tgl 1313 ECB : 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 : */
1170 dean.a.rasheed 1321 GIC 78 : if (arg1 == 0 || arg2 == 0)
1170 dean.a.rasheed 1322 CBC 36 : PG_RETURN_INT32(0);
1170 dean.a.rasheed 1323 ECB :
1324 : /* lcm(x, y) = abs(x / gcd(x, y) * y) */
1170 dean.a.rasheed 1325 GIC 42 : gcd = int4gcd_internal(arg1, arg2);
1170 dean.a.rasheed 1326 CBC 42 : arg1 = arg1 / gcd;
1170 dean.a.rasheed 1327 ECB :
1170 dean.a.rasheed 1328 GIC 42 : if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
1170 dean.a.rasheed 1329 CBC 3 : ereport(ERROR,
1170 dean.a.rasheed 1330 ECB : (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. */
1170 dean.a.rasheed 1334 GIC 39 : if (unlikely(result == PG_INT32_MIN))
1170 dean.a.rasheed 1335 CBC 3 : ereport(ERROR,
1170 dean.a.rasheed 1336 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1337 : errmsg("integer out of range")));
1338 :
1170 dean.a.rasheed 1339 GIC 36 : if (result < 0)
1170 dean.a.rasheed 1340 CBC 18 : result = -result;
1170 dean.a.rasheed 1341 ECB :
1170 dean.a.rasheed 1342 GIC 36 : PG_RETURN_INT32(result);
1170 dean.a.rasheed 1343 ECB : }
1344 :
1345 : Datum
8343 tgl 1346 GIC 201 : int2larger(PG_FUNCTION_ARGS)
9770 scrappy 1347 ECB : {
8343 tgl 1348 GIC 201 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 1349 CBC 201 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 1350 ECB :
8343 tgl 1351 GIC 201 : PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
9770 scrappy 1352 ECB : }
1353 :
1354 : Datum
8343 tgl 1355 UIC 0 : int2smaller(PG_FUNCTION_ARGS)
9770 scrappy 1356 EUB : {
8343 tgl 1357 UIC 0 : int16 arg1 = PG_GETARG_INT16(0);
8343 tgl 1358 UBC 0 : int16 arg2 = PG_GETARG_INT16(1);
8343 tgl 1359 EUB :
8343 tgl 1360 UIC 0 : PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
9770 scrappy 1361 EUB : }
1362 :
1363 : Datum
8343 tgl 1364 GIC 160196 : int4larger(PG_FUNCTION_ARGS)
9770 scrappy 1365 ECB : {
8343 tgl 1366 GIC 160196 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1367 CBC 160196 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 1368 ECB :
8343 tgl 1369 GIC 160196 : PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
9770 scrappy 1370 ECB : }
1371 :
1372 : Datum
8343 tgl 1373 GIC 125166 : int4smaller(PG_FUNCTION_ARGS)
9770 scrappy 1374 ECB : {
8343 tgl 1375 GIC 125166 : int32 arg1 = PG_GETARG_INT32(0);
8343 tgl 1376 CBC 125166 : int32 arg2 = PG_GETARG_INT32(1);
8343 tgl 1377 ECB :
8343 tgl 1378 GIC 125166 : PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
9770 scrappy 1379 ECB : }
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
8202 peter_e 1393 GIC 1770 : int4and(PG_FUNCTION_ARGS)
8202 peter_e 1394 ECB : {
8202 peter_e 1395 GIC 1770 : int32 arg1 = PG_GETARG_INT32(0);
8202 peter_e 1396 CBC 1770 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1397 ECB :
8202 peter_e 1398 GIC 1770 : PG_RETURN_INT32(arg1 & arg2);
8202 peter_e 1399 ECB : }
1400 :
1401 : Datum
8202 peter_e 1402 GIC 9 : int4or(PG_FUNCTION_ARGS)
8202 peter_e 1403 ECB : {
8202 peter_e 1404 GIC 9 : int32 arg1 = PG_GETARG_INT32(0);
8202 peter_e 1405 CBC 9 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1406 ECB :
8202 peter_e 1407 GIC 9 : PG_RETURN_INT32(arg1 | arg2);
8202 peter_e 1408 ECB : }
1409 :
1410 : Datum
8202 peter_e 1411 GIC 9 : int4xor(PG_FUNCTION_ARGS)
8202 peter_e 1412 ECB : {
8202 peter_e 1413 GIC 9 : int32 arg1 = PG_GETARG_INT32(0);
8202 peter_e 1414 CBC 9 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1415 ECB :
8202 peter_e 1416 GIC 9 : PG_RETURN_INT32(arg1 ^ arg2);
8202 peter_e 1417 ECB : }
1418 :
1419 : Datum
8202 peter_e 1420 GIC 6 : int4shl(PG_FUNCTION_ARGS)
8202 peter_e 1421 ECB : {
8202 peter_e 1422 GIC 6 : int32 arg1 = PG_GETARG_INT32(0);
8202 peter_e 1423 CBC 6 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1424 ECB :
8202 peter_e 1425 GIC 6 : PG_RETURN_INT32(arg1 << arg2);
8202 peter_e 1426 ECB : }
1427 :
1428 : Datum
8202 peter_e 1429 UIC 0 : int4shr(PG_FUNCTION_ARGS)
8202 peter_e 1430 EUB : {
8202 peter_e 1431 UIC 0 : int32 arg1 = PG_GETARG_INT32(0);
8202 peter_e 1432 UBC 0 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1433 EUB :
8202 peter_e 1434 UIC 0 : PG_RETURN_INT32(arg1 >> arg2);
8202 peter_e 1435 EUB : }
1436 :
1437 : Datum
8202 peter_e 1438 UIC 0 : int4not(PG_FUNCTION_ARGS)
8202 peter_e 1439 EUB : {
8202 peter_e 1440 UIC 0 : int32 arg1 = PG_GETARG_INT32(0);
8202 peter_e 1441 EUB :
8202 peter_e 1442 UIC 0 : PG_RETURN_INT32(~arg1);
8202 peter_e 1443 EUB : }
1444 :
1445 : Datum
8202 peter_e 1446 GIC 12 : int2and(PG_FUNCTION_ARGS)
8202 peter_e 1447 ECB : {
8202 peter_e 1448 GIC 12 : int16 arg1 = PG_GETARG_INT16(0);
8202 peter_e 1449 CBC 12 : int16 arg2 = PG_GETARG_INT16(1);
8202 peter_e 1450 ECB :
8202 peter_e 1451 GIC 12 : PG_RETURN_INT16(arg1 & arg2);
8202 peter_e 1452 ECB : }
1453 :
1454 : Datum
8202 peter_e 1455 GIC 12 : int2or(PG_FUNCTION_ARGS)
8202 peter_e 1456 ECB : {
8202 peter_e 1457 GIC 12 : int16 arg1 = PG_GETARG_INT16(0);
8202 peter_e 1458 CBC 12 : int16 arg2 = PG_GETARG_INT16(1);
8202 peter_e 1459 ECB :
8202 peter_e 1460 GIC 12 : PG_RETURN_INT16(arg1 | arg2);
8202 peter_e 1461 ECB : }
1462 :
1463 : Datum
8202 peter_e 1464 GIC 12 : int2xor(PG_FUNCTION_ARGS)
8202 peter_e 1465 ECB : {
8202 peter_e 1466 GIC 12 : int16 arg1 = PG_GETARG_INT16(0);
8202 peter_e 1467 CBC 12 : int16 arg2 = PG_GETARG_INT16(1);
8202 peter_e 1468 ECB :
8202 peter_e 1469 GIC 12 : PG_RETURN_INT16(arg1 ^ arg2);
8202 peter_e 1470 ECB : }
1471 :
1472 : Datum
8202 peter_e 1473 UIC 0 : int2not(PG_FUNCTION_ARGS)
8202 peter_e 1474 EUB : {
8202 peter_e 1475 UIC 0 : int16 arg1 = PG_GETARG_INT16(0);
8202 peter_e 1476 EUB :
8202 peter_e 1477 UIC 0 : PG_RETURN_INT16(~arg1);
8202 peter_e 1478 EUB : }
1479 :
1480 :
1481 : Datum
8202 peter_e 1482 GIC 6 : int2shl(PG_FUNCTION_ARGS)
8202 peter_e 1483 ECB : {
8202 peter_e 1484 GIC 6 : int16 arg1 = PG_GETARG_INT16(0);
8202 peter_e 1485 CBC 6 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1486 ECB :
8202 peter_e 1487 GIC 6 : PG_RETURN_INT16(arg1 << arg2);
8202 peter_e 1488 ECB : }
1489 :
1490 : Datum
8202 peter_e 1491 UIC 0 : int2shr(PG_FUNCTION_ARGS)
8202 peter_e 1492 EUB : {
8202 peter_e 1493 UIC 0 : int16 arg1 = PG_GETARG_INT16(0);
8202 peter_e 1494 UBC 0 : int32 arg2 = PG_GETARG_INT32(1);
8202 peter_e 1495 EUB :
8202 peter_e 1496 UIC 0 : PG_RETURN_INT16(arg1 >> arg2);
8202 peter_e 1497 EUB : }
1498 :
1499 : /*
1500 : * non-persistent numeric series generator
1501 : */
1502 : Datum
7005 mail 1503 GIC 7141854 : generate_series_int4(PG_FUNCTION_ARGS)
7005 mail 1504 ECB : {
7005 mail 1505 GIC 7141854 : return generate_series_step_int4(fcinfo);
7005 mail 1506 ECB : }
1507 :
1508 : Datum
7005 mail 1509 GIC 7323514 : generate_series_step_int4(PG_FUNCTION_ARGS)
7005 mail 1510 ECB : {
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 */
7005 mail 1517 GIC 7323514 : if (SRF_IS_FIRSTCALL())
7005 mail 1518 ECB : {
6797 bruce 1519 GIC 6142 : int32 start = PG_GETARG_INT32(0);
6797 bruce 1520 CBC 6142 : int32 finish = PG_GETARG_INT32(1);
1521 6142 : int32 step = 1;
7005 mail 1522 ECB :
1523 : /* see if we were given an explicit step size */
7005 mail 1524 GIC 6142 : if (PG_NARGS() == 3)
7005 mail 1525 CBC 269 : step = PG_GETARG_INT32(2);
1526 6142 : if (step == 0)
7005 mail 1527 LBC 0 : ereport(ERROR,
7005 mail 1528 EUB : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1529 : errmsg("step size cannot equal zero")));
1530 :
1531 : /* create a function context for cross-call persistence */
7005 mail 1532 GIC 6142 : funcctx = SRF_FIRSTCALL_INIT();
7005 mail 1533 ECB :
1534 : /*
1535 : * switch to memory context appropriate for multiple function calls
1536 : */
7005 mail 1537 GIC 6142 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
7005 mail 1538 ECB :
1539 : /* allocate memory for user context */
7005 mail 1540 GIC 6142 : fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
7005 mail 1541 ECB :
1542 : /*
1543 : * Use fctx to keep state from call to call. Seed current with the
1544 : * original start value
1545 : */
7005 mail 1546 GIC 6142 : fctx->current = start;
7005 mail 1547 CBC 6142 : fctx->finish = finish;
1548 6142 : fctx->step = step;
7005 mail 1549 ECB :
7005 mail 1550 GIC 6142 : funcctx->user_fctx = fctx;
7005 mail 1551 CBC 6142 : MemoryContextSwitchTo(oldcontext);
7005 mail 1552 ECB : }
1553 :
1554 : /* stuff done on every call of the function */
7005 mail 1555 GIC 7323514 : funcctx = SRF_PERCALL_SETUP();
7005 mail 1556 ECB :
1557 : /*
1558 : * get the saved state and use current as the result for this iteration
1559 : */
7005 mail 1560 GIC 7323514 : fctx = funcctx->user_fctx;
7005 mail 1561 CBC 7323514 : result = fctx->current;
7005 mail 1562 ECB :
7005 mail 1563 GIC 7323514 : if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
7005 mail 1564 CBC 106123 : (fctx->step < 0 && fctx->current >= fctx->finish))
7005 mail 1565 ECB : {
1566 : /*
1567 : * Increment current in preparation for next iteration. If next-value
1568 : * computation overflows, this is the final result.
1569 : */
1944 andres 1570 GIC 7317396 : if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
4314 rhaas 1571 LBC 0 : fctx->step = 0;
4314 rhaas 1572 EUB :
1573 : /* do when there is more left to send */
7005 mail 1574 GIC 7317396 : SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
7005 mail 1575 ECB : }
1576 : else
1577 : /* do when there is no more left */
7005 mail 1578 GIC 6118 : SRF_RETURN_DONE(funcctx);
7005 mail 1579 ECB : }
1580 :
1581 : /*
1582 : * Planner support function for generate_series(int4, int4 [, int4])
1583 : */
1584 : Datum
1520 tgl 1585 GIC 15306 : generate_series_int4_support(PG_FUNCTION_ARGS)
1520 tgl 1586 ECB : {
1520 tgl 1587 GIC 15306 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1520 tgl 1588 CBC 15306 : Node *ret = NULL;
1520 tgl 1589 ECB :
1520 tgl 1590 GIC 15306 : if (IsA(rawreq, SupportRequestRows))
1520 tgl 1591 ECB : {
1592 : /* Try to estimate the number of rows returned */
1520 tgl 1593 GIC 5025 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1520 tgl 1594 ECB :
1520 tgl 1595 GIC 5025 : if (is_funcclause(req->node)) /* be paranoid */
1520 tgl 1596 ECB : {
1520 tgl 1597 GIC 5025 : List *args = ((FuncExpr *) req->node)->args;
1520 tgl 1598 ECB : Node *arg1,
1599 : *arg2,
1600 : *arg3;
1601 :
1602 : /* We can use estimated argument values here */
1520 tgl 1603 GIC 5025 : arg1 = estimate_expression_value(req->root, linitial(args));
1520 tgl 1604 CBC 5025 : arg2 = estimate_expression_value(req->root, lsecond(args));
1605 5025 : if (list_length(args) >= 3)
1606 203 : arg3 = estimate_expression_value(req->root, lthird(args));
1520 tgl 1607 ECB : else
1520 tgl 1608 GIC 4822 : arg3 = NULL;
1520 tgl 1609 ECB :
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 : */
1520 tgl 1616 GIC 5025 : if ((IsA(arg1, Const) &&
1520 tgl 1617 CBC 4947 : ((Const *) arg1)->constisnull) ||
1618 5025 : (IsA(arg2, Const) &&
1619 5025 : ((Const *) arg2)->constisnull) ||
1620 203 : (arg3 != NULL && IsA(arg3, Const) &&
1621 203 : ((Const *) arg3)->constisnull))
1520 tgl 1622 ECB : {
1520 tgl 1623 UIC 0 : req->rows = 0;
1520 tgl 1624 UBC 0 : ret = (Node *) req;
1520 tgl 1625 EUB : }
1520 tgl 1626 GIC 5025 : else if (IsA(arg1, Const) &&
1520 tgl 1627 CBC 4947 : IsA(arg2, Const) &&
1628 200 : (arg3 == NULL || IsA(arg3, Const)))
1520 tgl 1629 ECB : {
1630 : double start,
1631 : finish,
1632 : step;
1633 :
1520 tgl 1634 GIC 3497 : start = DatumGetInt32(((Const *) arg1)->constvalue);
1520 tgl 1635 CBC 3497 : finish = DatumGetInt32(((Const *) arg2)->constvalue);
1636 3497 : step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
1520 tgl 1637 ECB :
1638 : /* This equation works for either sign of step */
1520 tgl 1639 GIC 3497 : if (step != 0)
1520 tgl 1640 ECB : {
1520 tgl 1641 GIC 3497 : req->rows = floor((finish - start + step) / step);
1520 tgl 1642 CBC 3497 : ret = (Node *) req;
1520 tgl 1643 ECB : }
1644 : }
1645 : }
1646 : }
1647 :
1520 tgl 1648 GIC 15306 : PG_RETURN_POINTER(ret);
1520 tgl 1649 ECB : }
|