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