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