Coverage Report

Created: 2026-08-13 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/adt/int8.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * int8.c
4
 *    Internal 64-bit integer operations
5
 *
6
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 * IDENTIFICATION
10
 *    src/backend/utils/adt/int8.c
11
 *
12
 *-------------------------------------------------------------------------
13
 */
14
#include "postgres.h"
15
16
#include <ctype.h>
17
#include <limits.h>
18
#include <math.h>
19
20
#include "common/int.h"
21
#include "funcapi.h"
22
#include "libpq/pqformat.h"
23
#include "nodes/nodeFuncs.h"
24
#include "nodes/supportnodes.h"
25
#include "optimizer/optimizer.h"
26
#include "utils/builtins.h"
27
#include "utils/fmgroids.h"
28
29
typedef struct
30
{
31
  int64   current;
32
  int64   finish;
33
  int64   step;
34
} generate_series_fctx;
35
36
37
/***********************************************************************
38
 **
39
 **   Routines for 64-bit integers.
40
 **
41
 ***********************************************************************/
42
43
/*----------------------------------------------------------
44
 * Formatting and conversion routines.
45
 *---------------------------------------------------------*/
46
47
/*
48
 * int8in()
49
 */
50
Datum
51
int8in(PG_FUNCTION_ARGS)
52
0
{
53
0
  char     *num = PG_GETARG_CSTRING(0);
54
55
0
  PG_RETURN_INT64(pg_strtoint64_safe(num, fcinfo->context));
56
0
}
57
58
59
/*
60
 * int8out()
61
 */
62
Datum
63
int8out(PG_FUNCTION_ARGS)
64
0
{
65
0
  int64   val = PG_GETARG_INT64(0);
66
0
  char    buf[MAXINT8LEN + 1];
67
0
  char     *result;
68
0
  int     len;
69
70
0
  len = pg_lltoa(val, buf) + 1;
71
72
  /*
73
   * Since the length is already known, we do a manual palloc() and memcpy()
74
   * to avoid the strlen() call that would otherwise be done in pstrdup().
75
   */
76
0
  result = palloc(len);
77
0
  memcpy(result, buf, len);
78
0
  PG_RETURN_CSTRING(result);
79
0
}
80
81
/*
82
 *    int8recv      - converts external binary format to int8
83
 */
84
Datum
85
int8recv(PG_FUNCTION_ARGS)
86
0
{
87
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
88
89
0
  PG_RETURN_INT64(pq_getmsgint64(buf));
90
0
}
91
92
/*
93
 *    int8send      - converts int8 to binary format
94
 */
95
Datum
96
int8send(PG_FUNCTION_ARGS)
97
0
{
98
0
  int64   arg1 = PG_GETARG_INT64(0);
99
0
  StringInfoData buf;
100
101
0
  pq_begintypsend(&buf);
102
0
  pq_sendint64(&buf, arg1);
103
0
  PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
104
0
}
105
106
107
/*----------------------------------------------------------
108
 *  Relational operators for int8s, including cross-data-type comparisons.
109
 *---------------------------------------------------------*/
110
111
/*
112
 * int8relop()
113
 * Is val1 relop val2?
114
 */
115
Datum
116
int8eq(PG_FUNCTION_ARGS)
117
0
{
118
0
  int64   val1 = PG_GETARG_INT64(0);
119
0
  int64   val2 = PG_GETARG_INT64(1);
120
121
0
  PG_RETURN_BOOL(val1 == val2);
122
0
}
123
124
Datum
125
int8ne(PG_FUNCTION_ARGS)
126
0
{
127
0
  int64   val1 = PG_GETARG_INT64(0);
128
0
  int64   val2 = PG_GETARG_INT64(1);
129
130
0
  PG_RETURN_BOOL(val1 != val2);
131
0
}
132
133
Datum
134
int8lt(PG_FUNCTION_ARGS)
135
0
{
136
0
  int64   val1 = PG_GETARG_INT64(0);
137
0
  int64   val2 = PG_GETARG_INT64(1);
138
139
0
  PG_RETURN_BOOL(val1 < val2);
140
0
}
141
142
Datum
143
int8gt(PG_FUNCTION_ARGS)
144
0
{
145
0
  int64   val1 = PG_GETARG_INT64(0);
146
0
  int64   val2 = PG_GETARG_INT64(1);
147
148
0
  PG_RETURN_BOOL(val1 > val2);
149
0
}
150
151
Datum
152
int8le(PG_FUNCTION_ARGS)
153
0
{
154
0
  int64   val1 = PG_GETARG_INT64(0);
155
0
  int64   val2 = PG_GETARG_INT64(1);
156
157
0
  PG_RETURN_BOOL(val1 <= val2);
158
0
}
159
160
Datum
161
int8ge(PG_FUNCTION_ARGS)
162
0
{
163
0
  int64   val1 = PG_GETARG_INT64(0);
164
0
  int64   val2 = PG_GETARG_INT64(1);
165
166
0
  PG_RETURN_BOOL(val1 >= val2);
167
0
}
168
169
/*
170
 * int84relop()
171
 * Is 64-bit val1 relop 32-bit val2?
172
 */
173
Datum
174
int84eq(PG_FUNCTION_ARGS)
175
0
{
176
0
  int64   val1 = PG_GETARG_INT64(0);
177
0
  int32   val2 = PG_GETARG_INT32(1);
178
179
0
  PG_RETURN_BOOL(val1 == val2);
180
0
}
181
182
Datum
183
int84ne(PG_FUNCTION_ARGS)
184
0
{
185
0
  int64   val1 = PG_GETARG_INT64(0);
186
0
  int32   val2 = PG_GETARG_INT32(1);
187
188
0
  PG_RETURN_BOOL(val1 != val2);
189
0
}
190
191
Datum
192
int84lt(PG_FUNCTION_ARGS)
193
0
{
194
0
  int64   val1 = PG_GETARG_INT64(0);
195
0
  int32   val2 = PG_GETARG_INT32(1);
196
197
0
  PG_RETURN_BOOL(val1 < val2);
198
0
}
199
200
Datum
201
int84gt(PG_FUNCTION_ARGS)
202
0
{
203
0
  int64   val1 = PG_GETARG_INT64(0);
204
0
  int32   val2 = PG_GETARG_INT32(1);
205
206
0
  PG_RETURN_BOOL(val1 > val2);
207
0
}
208
209
Datum
210
int84le(PG_FUNCTION_ARGS)
211
0
{
212
0
  int64   val1 = PG_GETARG_INT64(0);
213
0
  int32   val2 = PG_GETARG_INT32(1);
214
215
0
  PG_RETURN_BOOL(val1 <= val2);
216
0
}
217
218
Datum
219
int84ge(PG_FUNCTION_ARGS)
220
0
{
221
0
  int64   val1 = PG_GETARG_INT64(0);
222
0
  int32   val2 = PG_GETARG_INT32(1);
223
224
0
  PG_RETURN_BOOL(val1 >= val2);
225
0
}
226
227
/*
228
 * int48relop()
229
 * Is 32-bit val1 relop 64-bit val2?
230
 */
231
Datum
232
int48eq(PG_FUNCTION_ARGS)
233
0
{
234
0
  int32   val1 = PG_GETARG_INT32(0);
235
0
  int64   val2 = PG_GETARG_INT64(1);
236
237
0
  PG_RETURN_BOOL(val1 == val2);
238
0
}
239
240
Datum
241
int48ne(PG_FUNCTION_ARGS)
242
0
{
243
0
  int32   val1 = PG_GETARG_INT32(0);
244
0
  int64   val2 = PG_GETARG_INT64(1);
245
246
0
  PG_RETURN_BOOL(val1 != val2);
247
0
}
248
249
Datum
250
int48lt(PG_FUNCTION_ARGS)
251
0
{
252
0
  int32   val1 = PG_GETARG_INT32(0);
253
0
  int64   val2 = PG_GETARG_INT64(1);
254
255
0
  PG_RETURN_BOOL(val1 < val2);
256
0
}
257
258
Datum
259
int48gt(PG_FUNCTION_ARGS)
260
0
{
261
0
  int32   val1 = PG_GETARG_INT32(0);
262
0
  int64   val2 = PG_GETARG_INT64(1);
263
264
0
  PG_RETURN_BOOL(val1 > val2);
265
0
}
266
267
Datum
268
int48le(PG_FUNCTION_ARGS)
269
0
{
270
0
  int32   val1 = PG_GETARG_INT32(0);
271
0
  int64   val2 = PG_GETARG_INT64(1);
272
273
0
  PG_RETURN_BOOL(val1 <= val2);
274
0
}
275
276
Datum
277
int48ge(PG_FUNCTION_ARGS)
278
0
{
279
0
  int32   val1 = PG_GETARG_INT32(0);
280
0
  int64   val2 = PG_GETARG_INT64(1);
281
282
0
  PG_RETURN_BOOL(val1 >= val2);
283
0
}
284
285
/*
286
 * int82relop()
287
 * Is 64-bit val1 relop 16-bit val2?
288
 */
289
Datum
290
int82eq(PG_FUNCTION_ARGS)
291
0
{
292
0
  int64   val1 = PG_GETARG_INT64(0);
293
0
  int16   val2 = PG_GETARG_INT16(1);
294
295
0
  PG_RETURN_BOOL(val1 == val2);
296
0
}
297
298
Datum
299
int82ne(PG_FUNCTION_ARGS)
300
0
{
301
0
  int64   val1 = PG_GETARG_INT64(0);
302
0
  int16   val2 = PG_GETARG_INT16(1);
303
304
0
  PG_RETURN_BOOL(val1 != val2);
305
0
}
306
307
Datum
308
int82lt(PG_FUNCTION_ARGS)
309
0
{
310
0
  int64   val1 = PG_GETARG_INT64(0);
311
0
  int16   val2 = PG_GETARG_INT16(1);
312
313
0
  PG_RETURN_BOOL(val1 < val2);
314
0
}
315
316
Datum
317
int82gt(PG_FUNCTION_ARGS)
318
0
{
319
0
  int64   val1 = PG_GETARG_INT64(0);
320
0
  int16   val2 = PG_GETARG_INT16(1);
321
322
0
  PG_RETURN_BOOL(val1 > val2);
323
0
}
324
325
Datum
326
int82le(PG_FUNCTION_ARGS)
327
0
{
328
0
  int64   val1 = PG_GETARG_INT64(0);
329
0
  int16   val2 = PG_GETARG_INT16(1);
330
331
0
  PG_RETURN_BOOL(val1 <= val2);
332
0
}
333
334
Datum
335
int82ge(PG_FUNCTION_ARGS)
336
0
{
337
0
  int64   val1 = PG_GETARG_INT64(0);
338
0
  int16   val2 = PG_GETARG_INT16(1);
339
340
0
  PG_RETURN_BOOL(val1 >= val2);
341
0
}
342
343
/*
344
 * int28relop()
345
 * Is 16-bit val1 relop 64-bit val2?
346
 */
347
Datum
348
int28eq(PG_FUNCTION_ARGS)
349
0
{
350
0
  int16   val1 = PG_GETARG_INT16(0);
351
0
  int64   val2 = PG_GETARG_INT64(1);
352
353
0
  PG_RETURN_BOOL(val1 == val2);
354
0
}
355
356
Datum
357
int28ne(PG_FUNCTION_ARGS)
358
0
{
359
0
  int16   val1 = PG_GETARG_INT16(0);
360
0
  int64   val2 = PG_GETARG_INT64(1);
361
362
0
  PG_RETURN_BOOL(val1 != val2);
363
0
}
364
365
Datum
366
int28lt(PG_FUNCTION_ARGS)
367
0
{
368
0
  int16   val1 = PG_GETARG_INT16(0);
369
0
  int64   val2 = PG_GETARG_INT64(1);
370
371
0
  PG_RETURN_BOOL(val1 < val2);
372
0
}
373
374
Datum
375
int28gt(PG_FUNCTION_ARGS)
376
0
{
377
0
  int16   val1 = PG_GETARG_INT16(0);
378
0
  int64   val2 = PG_GETARG_INT64(1);
379
380
0
  PG_RETURN_BOOL(val1 > val2);
381
0
}
382
383
Datum
384
int28le(PG_FUNCTION_ARGS)
385
0
{
386
0
  int16   val1 = PG_GETARG_INT16(0);
387
0
  int64   val2 = PG_GETARG_INT64(1);
388
389
0
  PG_RETURN_BOOL(val1 <= val2);
390
0
}
391
392
Datum
393
int28ge(PG_FUNCTION_ARGS)
394
0
{
395
0
  int16   val1 = PG_GETARG_INT16(0);
396
0
  int64   val2 = PG_GETARG_INT64(1);
397
398
0
  PG_RETURN_BOOL(val1 >= val2);
399
0
}
400
401
/*
402
 * in_range support function for int8.
403
 *
404
 * Note: we needn't supply int8_int4 or int8_int2 variants, as implicit
405
 * coercion of the offset value takes care of those scenarios just as well.
406
 */
407
Datum
408
in_range_int8_int8(PG_FUNCTION_ARGS)
409
0
{
410
0
  int64   val = PG_GETARG_INT64(0);
411
0
  int64   base = PG_GETARG_INT64(1);
412
0
  int64   offset = PG_GETARG_INT64(2);
413
0
  bool    sub = PG_GETARG_BOOL(3);
414
0
  bool    less = PG_GETARG_BOOL(4);
415
0
  int64   sum;
416
417
0
  if (offset < 0)
418
0
    ereport(ERROR,
419
0
        (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
420
0
         errmsg("invalid preceding or following size in window function")));
421
422
0
  if (sub)
423
0
    offset = -offset;   /* cannot overflow */
424
425
0
  if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
426
0
  {
427
    /*
428
     * If sub is false, the true sum is surely more than val, so correct
429
     * answer is the same as "less".  If sub is true, the true sum is
430
     * surely less than val, so the answer is "!less".
431
     */
432
0
    PG_RETURN_BOOL(sub ? !less : less);
433
0
  }
434
435
0
  if (less)
436
0
    PG_RETURN_BOOL(val <= sum);
437
0
  else
438
0
    PG_RETURN_BOOL(val >= sum);
439
0
}
440
441
442
/*----------------------------------------------------------
443
 *  Arithmetic operators on 64-bit integers.
444
 *---------------------------------------------------------*/
445
446
Datum
447
int8um(PG_FUNCTION_ARGS)
448
0
{
449
0
  int64   arg = PG_GETARG_INT64(0);
450
0
  int64   result;
451
452
0
  if (unlikely(arg == PG_INT64_MIN))
453
0
    ereport(ERROR,
454
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
455
0
         errmsg("bigint out of range")));
456
0
  result = -arg;
457
0
  PG_RETURN_INT64(result);
458
0
}
459
460
Datum
461
int8up(PG_FUNCTION_ARGS)
462
0
{
463
0
  int64   arg = PG_GETARG_INT64(0);
464
465
0
  PG_RETURN_INT64(arg);
466
0
}
467
468
Datum
469
int8pl(PG_FUNCTION_ARGS)
470
0
{
471
0
  int64   arg1 = PG_GETARG_INT64(0);
472
0
  int64   arg2 = PG_GETARG_INT64(1);
473
0
  int64   result;
474
475
0
  if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
476
0
    ereport(ERROR,
477
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
478
0
         errmsg("bigint out of range")));
479
0
  PG_RETURN_INT64(result);
480
0
}
481
482
Datum
483
int8mi(PG_FUNCTION_ARGS)
484
0
{
485
0
  int64   arg1 = PG_GETARG_INT64(0);
486
0
  int64   arg2 = PG_GETARG_INT64(1);
487
0
  int64   result;
488
489
0
  if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
490
0
    ereport(ERROR,
491
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
492
0
         errmsg("bigint out of range")));
493
0
  PG_RETURN_INT64(result);
494
0
}
495
496
Datum
497
int8mul(PG_FUNCTION_ARGS)
498
0
{
499
0
  int64   arg1 = PG_GETARG_INT64(0);
500
0
  int64   arg2 = PG_GETARG_INT64(1);
501
0
  int64   result;
502
503
0
  if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
504
0
    ereport(ERROR,
505
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
506
0
         errmsg("bigint out of range")));
507
0
  PG_RETURN_INT64(result);
508
0
}
509
510
Datum
511
int8div(PG_FUNCTION_ARGS)
512
0
{
513
0
  int64   arg1 = PG_GETARG_INT64(0);
514
0
  int64   arg2 = PG_GETARG_INT64(1);
515
0
  int64   result;
516
517
0
  if (arg2 == 0)
518
0
  {
519
0
    ereport(ERROR,
520
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
521
0
         errmsg("division by zero")));
522
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
523
0
    PG_RETURN_NULL();
524
0
  }
525
526
  /*
527
   * INT64_MIN / -1 is problematic, since the result can't be represented on
528
   * a two's-complement machine.  Some machines produce INT64_MIN, some
529
   * produce zero, some throw an exception.  We can dodge the problem by
530
   * recognizing that division by -1 is the same as negation.
531
   */
532
0
  if (arg2 == -1)
533
0
  {
534
0
    if (unlikely(arg1 == PG_INT64_MIN))
535
0
      ereport(ERROR,
536
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
537
0
           errmsg("bigint out of range")));
538
0
    result = -arg1;
539
0
    PG_RETURN_INT64(result);
540
0
  }
541
542
  /* No overflow is possible */
543
544
0
  result = arg1 / arg2;
545
546
0
  PG_RETURN_INT64(result);
547
0
}
548
549
/*
550
 * int8abs()
551
 * Absolute value
552
 */
553
Datum
554
int8abs(PG_FUNCTION_ARGS)
555
0
{
556
0
  int64   arg1 = PG_GETARG_INT64(0);
557
0
  int64   result;
558
559
0
  if (unlikely(arg1 == PG_INT64_MIN))
560
0
    ereport(ERROR,
561
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
562
0
         errmsg("bigint out of range")));
563
0
  result = (arg1 < 0) ? -arg1 : arg1;
564
0
  PG_RETURN_INT64(result);
565
0
}
566
567
/*
568
 * int8mod()
569
 * Modulo operation.
570
 */
571
Datum
572
int8mod(PG_FUNCTION_ARGS)
573
0
{
574
0
  int64   arg1 = PG_GETARG_INT64(0);
575
0
  int64   arg2 = PG_GETARG_INT64(1);
576
577
0
  if (unlikely(arg2 == 0))
578
0
  {
579
0
    ereport(ERROR,
580
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
581
0
         errmsg("division by zero")));
582
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
583
0
    PG_RETURN_NULL();
584
0
  }
585
586
  /*
587
   * Some machines throw a floating-point exception for INT64_MIN % -1,
588
   * which is a bit silly since the correct answer is perfectly
589
   * well-defined, namely zero.
590
   */
591
0
  if (arg2 == -1)
592
0
    PG_RETURN_INT64(0);
593
594
  /* No overflow is possible */
595
596
0
  PG_RETURN_INT64(arg1 % arg2);
597
0
}
598
599
/*
600
 * Greatest Common Divisor
601
 *
602
 * Returns the largest positive integer that exactly divides both inputs.
603
 * Special cases:
604
 *   - gcd(x, 0) = gcd(0, x) = abs(x)
605
 *      because 0 is divisible by anything
606
 *   - gcd(0, 0) = 0
607
 *      complies with the previous definition and is a common convention
608
 *
609
 * Special care must be taken if either input is INT64_MIN ---
610
 * gcd(0, INT64_MIN), gcd(INT64_MIN, 0) and gcd(INT64_MIN, INT64_MIN) are
611
 * all equal to abs(INT64_MIN), which cannot be represented as a 64-bit signed
612
 * integer.
613
 */
614
static int64
615
int8gcd_internal(int64 arg1, int64 arg2)
616
0
{
617
0
  int64   swap;
618
0
  int64   a1,
619
0
        a2;
620
621
  /*
622
   * Put the greater absolute value in arg1.
623
   *
624
   * This would happen automatically in the loop below, but avoids an
625
   * expensive modulo operation, and simplifies the special-case handling
626
   * for INT64_MIN below.
627
   *
628
   * We do this in negative space in order to handle INT64_MIN.
629
   */
630
0
  a1 = (arg1 < 0) ? arg1 : -arg1;
631
0
  a2 = (arg2 < 0) ? arg2 : -arg2;
632
0
  if (a1 > a2)
633
0
  {
634
0
    swap = arg1;
635
0
    arg1 = arg2;
636
0
    arg2 = swap;
637
0
  }
638
639
  /* Special care needs to be taken with INT64_MIN.  See comments above. */
640
0
  if (arg1 == PG_INT64_MIN)
641
0
  {
642
0
    if (arg2 == 0 || arg2 == PG_INT64_MIN)
643
0
      ereport(ERROR,
644
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
645
0
           errmsg("bigint out of range")));
646
647
    /*
648
     * Some machines throw a floating-point exception for INT64_MIN % -1,
649
     * which is a bit silly since the correct answer is perfectly
650
     * well-defined, namely zero.  Guard against this and just return the
651
     * result, gcd(INT64_MIN, -1) = 1.
652
     */
653
0
    if (arg2 == -1)
654
0
      return 1;
655
0
  }
656
657
  /* Use the Euclidean algorithm to find the GCD */
658
0
  while (arg2 != 0)
659
0
  {
660
0
    swap = arg2;
661
0
    arg2 = arg1 % arg2;
662
0
    arg1 = swap;
663
0
  }
664
665
  /*
666
   * Make sure the result is positive. (We know we don't have INT64_MIN
667
   * anymore).
668
   */
669
0
  if (arg1 < 0)
670
0
    arg1 = -arg1;
671
672
0
  return arg1;
673
0
}
674
675
Datum
676
int8gcd(PG_FUNCTION_ARGS)
677
0
{
678
0
  int64   arg1 = PG_GETARG_INT64(0);
679
0
  int64   arg2 = PG_GETARG_INT64(1);
680
0
  int64   result;
681
682
0
  result = int8gcd_internal(arg1, arg2);
683
684
0
  PG_RETURN_INT64(result);
685
0
}
686
687
/*
688
 * Least Common Multiple
689
 */
690
Datum
691
int8lcm(PG_FUNCTION_ARGS)
692
0
{
693
0
  int64   arg1 = PG_GETARG_INT64(0);
694
0
  int64   arg2 = PG_GETARG_INT64(1);
695
0
  int64   gcd;
696
0
  int64   result;
697
698
  /*
699
   * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case.  This prevents a
700
   * division-by-zero error below when x is zero, and an overflow error from
701
   * the GCD computation when x = INT64_MIN.
702
   */
703
0
  if (arg1 == 0 || arg2 == 0)
704
0
    PG_RETURN_INT64(0);
705
706
  /* lcm(x, y) = abs(x / gcd(x, y) * y) */
707
0
  gcd = int8gcd_internal(arg1, arg2);
708
0
  arg1 = arg1 / gcd;
709
710
0
  if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
711
0
    ereport(ERROR,
712
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
713
0
         errmsg("bigint out of range")));
714
715
  /* If the result is INT64_MIN, it cannot be represented. */
716
0
  if (unlikely(result == PG_INT64_MIN))
717
0
    ereport(ERROR,
718
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
719
0
         errmsg("bigint out of range")));
720
721
0
  if (result < 0)
722
0
    result = -result;
723
724
0
  PG_RETURN_INT64(result);
725
0
}
726
727
Datum
728
int8inc(PG_FUNCTION_ARGS)
729
0
{
730
0
  int64   arg = PG_GETARG_INT64(0);
731
0
  int64   result;
732
733
0
  if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
734
0
    ereport(ERROR,
735
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
736
0
         errmsg("bigint out of range")));
737
738
0
  PG_RETURN_INT64(result);
739
0
}
740
741
Datum
742
int8dec(PG_FUNCTION_ARGS)
743
0
{
744
0
  int64   arg = PG_GETARG_INT64(0);
745
0
  int64   result;
746
747
0
  if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
748
0
    ereport(ERROR,
749
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
750
0
         errmsg("bigint out of range")));
751
752
0
  PG_RETURN_INT64(result);
753
0
}
754
755
756
/*
757
 * These functions are exactly like int8inc/int8dec but are used for
758
 * aggregates that count only non-null values.  Since the functions are
759
 * declared strict, the null checks happen before we ever get here, and all we
760
 * need do is increment the state value.  We could actually make these pg_proc
761
 * entries point right at int8inc/int8dec, but then the opr_sanity regression
762
 * test would complain about mismatched entries for a built-in function.
763
 */
764
765
Datum
766
int8inc_any(PG_FUNCTION_ARGS)
767
0
{
768
0
  return int8inc(fcinfo);
769
0
}
770
771
Datum
772
int8inc_float8_float8(PG_FUNCTION_ARGS)
773
0
{
774
0
  return int8inc(fcinfo);
775
0
}
776
777
Datum
778
int8dec_any(PG_FUNCTION_ARGS)
779
0
{
780
0
  return int8dec(fcinfo);
781
0
}
782
783
/*
784
 * int8inc_support
785
 *    prosupport function for int8inc() and int8inc_any()
786
 */
787
Datum
788
int8inc_support(PG_FUNCTION_ARGS)
789
0
{
790
0
  Node     *rawreq = (Node *) PG_GETARG_POINTER(0);
791
792
0
  if (IsA(rawreq, SupportRequestWFuncMonotonic))
793
0
  {
794
0
    SupportRequestWFuncMonotonic *req = (SupportRequestWFuncMonotonic *) rawreq;
795
0
    MonotonicFunction monotonic = MONOTONICFUNC_NONE;
796
0
    int     frameOptions = req->window_clause->frameOptions;
797
798
    /*
799
     * Because an EXCLUDE clauses in the window definition can exclude
800
     * rows that have previously been included in the aggregate result for
801
     * prior rows, this can break the monotonic properties that might
802
     * otherwise be guaranteed.  There's a narrow set of circumstances
803
     * that can be guaranteed, which we check for below.
804
     */
805
0
    if (frameOptions & FRAMEOPTION_EXCLUSION)
806
0
    {
807
0
      WindowFunc *wfunc = req->window_func;
808
809
      /*
810
       * To add handling for all valid monotonic cases with an EXCLUDE
811
       * clause is complex and likely not worth troubling over.  For
812
       * now, just bail unless we see EXCLUDE CURRENT ROW with COUNT(*)
813
       * and no FILTER.  Excluding the current row is fine when using
814
       * COUNT(*) as this always reduces the count by 1.  The same isn't
815
       * true for COUNY(ANY) as a NULL won't be counted, and a
816
       * subsequent non-NULL could make the count decrease.
817
       */
818
0
      if ((frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) == 0 ||
819
0
        wfunc->winfnoid != F_COUNT_ ||
820
0
        wfunc->aggfilter != NULL)
821
0
      {
822
0
        req->monotonic = MONOTONICFUNC_NONE;
823
0
        PG_RETURN_POINTER(req);
824
0
      }
825
0
    }
826
827
    /* No ORDER BY clause and RANGE mode means all rows are peers. */
828
0
    if (req->window_clause->orderClause == NIL &&
829
0
      (frameOptions & FRAMEOPTION_RANGE))
830
0
      monotonic = MONOTONICFUNC_BOTH;
831
0
    else
832
0
    {
833
      /*
834
       * Otherwise take into account the frame options.  When the frame
835
       * bound is the start of the window then the resulting value can
836
       * never decrease, therefore is monotonically increasing
837
       */
838
0
      if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
839
0
        monotonic |= MONOTONICFUNC_INCREASING;
840
841
      /*
842
       * Likewise, if the frame bound is the end of the window then the
843
       * resulting value can never decrease.
844
       */
845
0
      if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
846
0
        monotonic |= MONOTONICFUNC_DECREASING;
847
0
    }
848
849
0
    req->monotonic = monotonic;
850
0
    PG_RETURN_POINTER(req);
851
0
  }
852
853
0
  if (IsA(rawreq, SupportRequestSimplifyAggref))
854
0
  {
855
0
    SupportRequestSimplifyAggref *req = (SupportRequestSimplifyAggref *) rawreq;
856
0
    Aggref     *agg = req->aggref;
857
858
    /*
859
     * Check for COUNT(ANY) and try to convert to COUNT(*). The input
860
     * argument cannot be NULL, we can't have an ORDER BY / DISTINCT in
861
     * the aggregate, and agglevelsup must be 0.
862
     *
863
     * Technically COUNT(ANY) must have 1 arg, but be paranoid and check.
864
     */
865
0
    if (agg->aggfnoid == F_COUNT_ANY && list_length(agg->args) == 1)
866
0
    {
867
0
      TargetEntry *tle = (TargetEntry *) linitial(agg->args);
868
0
      Expr     *arg = tle->expr;
869
870
      /* Check for unsupported cases */
871
0
      if (agg->aggdistinct != NIL || agg->aggorder != NIL ||
872
0
        agg->agglevelsup != 0)
873
0
        PG_RETURN_POINTER(NULL);
874
875
      /* If the arg isn't NULLable, do the conversion */
876
0
      if (expr_is_nonnullable(req->root, arg, NOTNULL_SOURCE_HASHTABLE))
877
0
      {
878
0
        Aggref     *newagg;
879
880
        /* We don't expect these to have been set yet */
881
0
        Assert(agg->aggtransno == -1);
882
0
        Assert(agg->aggtranstype == InvalidOid);
883
884
        /* Convert COUNT(ANY) to COUNT(*) by making a new Aggref */
885
0
        newagg = makeNode(Aggref);
886
0
        memcpy(newagg, agg, sizeof(Aggref));
887
0
        newagg->aggfnoid = F_COUNT_;
888
889
        /* count(*) has no args */
890
0
        newagg->aggargtypes = NULL;
891
0
        newagg->args = NULL;
892
0
        newagg->aggstar = true;
893
0
        newagg->location = -1;
894
895
0
        PG_RETURN_POINTER(newagg);
896
0
      }
897
0
    }
898
0
  }
899
900
0
  PG_RETURN_POINTER(NULL);
901
0
}
902
903
904
Datum
905
int8larger(PG_FUNCTION_ARGS)
906
0
{
907
0
  int64   arg1 = PG_GETARG_INT64(0);
908
0
  int64   arg2 = PG_GETARG_INT64(1);
909
0
  int64   result;
910
911
0
  result = ((arg1 > arg2) ? arg1 : arg2);
912
913
0
  PG_RETURN_INT64(result);
914
0
}
915
916
Datum
917
int8smaller(PG_FUNCTION_ARGS)
918
0
{
919
0
  int64   arg1 = PG_GETARG_INT64(0);
920
0
  int64   arg2 = PG_GETARG_INT64(1);
921
0
  int64   result;
922
923
0
  result = ((arg1 < arg2) ? arg1 : arg2);
924
925
0
  PG_RETURN_INT64(result);
926
0
}
927
928
Datum
929
int84pl(PG_FUNCTION_ARGS)
930
0
{
931
0
  int64   arg1 = PG_GETARG_INT64(0);
932
0
  int32   arg2 = PG_GETARG_INT32(1);
933
0
  int64   result;
934
935
0
  if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
936
0
    ereport(ERROR,
937
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
938
0
         errmsg("bigint out of range")));
939
0
  PG_RETURN_INT64(result);
940
0
}
941
942
Datum
943
int84mi(PG_FUNCTION_ARGS)
944
0
{
945
0
  int64   arg1 = PG_GETARG_INT64(0);
946
0
  int32   arg2 = PG_GETARG_INT32(1);
947
0
  int64   result;
948
949
0
  if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
950
0
    ereport(ERROR,
951
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
952
0
         errmsg("bigint out of range")));
953
0
  PG_RETURN_INT64(result);
954
0
}
955
956
Datum
957
int84mul(PG_FUNCTION_ARGS)
958
0
{
959
0
  int64   arg1 = PG_GETARG_INT64(0);
960
0
  int32   arg2 = PG_GETARG_INT32(1);
961
0
  int64   result;
962
963
0
  if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
964
0
    ereport(ERROR,
965
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
966
0
         errmsg("bigint out of range")));
967
0
  PG_RETURN_INT64(result);
968
0
}
969
970
Datum
971
int84div(PG_FUNCTION_ARGS)
972
0
{
973
0
  int64   arg1 = PG_GETARG_INT64(0);
974
0
  int32   arg2 = PG_GETARG_INT32(1);
975
0
  int64   result;
976
977
0
  if (arg2 == 0)
978
0
  {
979
0
    ereport(ERROR,
980
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
981
0
         errmsg("division by zero")));
982
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
983
0
    PG_RETURN_NULL();
984
0
  }
985
986
  /*
987
   * INT64_MIN / -1 is problematic, since the result can't be represented on
988
   * a two's-complement machine.  Some machines produce INT64_MIN, some
989
   * produce zero, some throw an exception.  We can dodge the problem by
990
   * recognizing that division by -1 is the same as negation.
991
   */
992
0
  if (arg2 == -1)
993
0
  {
994
0
    if (unlikely(arg1 == PG_INT64_MIN))
995
0
      ereport(ERROR,
996
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
997
0
           errmsg("bigint out of range")));
998
0
    result = -arg1;
999
0
    PG_RETURN_INT64(result);
1000
0
  }
1001
1002
  /* No overflow is possible */
1003
1004
0
  result = arg1 / arg2;
1005
1006
0
  PG_RETURN_INT64(result);
1007
0
}
1008
1009
Datum
1010
int48pl(PG_FUNCTION_ARGS)
1011
0
{
1012
0
  int32   arg1 = PG_GETARG_INT32(0);
1013
0
  int64   arg2 = PG_GETARG_INT64(1);
1014
0
  int64   result;
1015
1016
0
  if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
1017
0
    ereport(ERROR,
1018
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1019
0
         errmsg("bigint out of range")));
1020
0
  PG_RETURN_INT64(result);
1021
0
}
1022
1023
Datum
1024
int48mi(PG_FUNCTION_ARGS)
1025
0
{
1026
0
  int32   arg1 = PG_GETARG_INT32(0);
1027
0
  int64   arg2 = PG_GETARG_INT64(1);
1028
0
  int64   result;
1029
1030
0
  if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
1031
0
    ereport(ERROR,
1032
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1033
0
         errmsg("bigint out of range")));
1034
0
  PG_RETURN_INT64(result);
1035
0
}
1036
1037
Datum
1038
int48mul(PG_FUNCTION_ARGS)
1039
0
{
1040
0
  int32   arg1 = PG_GETARG_INT32(0);
1041
0
  int64   arg2 = PG_GETARG_INT64(1);
1042
0
  int64   result;
1043
1044
0
  if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1045
0
    ereport(ERROR,
1046
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1047
0
         errmsg("bigint out of range")));
1048
0
  PG_RETURN_INT64(result);
1049
0
}
1050
1051
Datum
1052
int48div(PG_FUNCTION_ARGS)
1053
0
{
1054
0
  int32   arg1 = PG_GETARG_INT32(0);
1055
0
  int64   arg2 = PG_GETARG_INT64(1);
1056
1057
0
  if (unlikely(arg2 == 0))
1058
0
  {
1059
0
    ereport(ERROR,
1060
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1061
0
         errmsg("division by zero")));
1062
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1063
0
    PG_RETURN_NULL();
1064
0
  }
1065
1066
  /* No overflow is possible */
1067
0
  PG_RETURN_INT64((int64) arg1 / arg2);
1068
0
}
1069
1070
Datum
1071
int82pl(PG_FUNCTION_ARGS)
1072
0
{
1073
0
  int64   arg1 = PG_GETARG_INT64(0);
1074
0
  int16   arg2 = PG_GETARG_INT16(1);
1075
0
  int64   result;
1076
1077
0
  if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
1078
0
    ereport(ERROR,
1079
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1080
0
         errmsg("bigint out of range")));
1081
0
  PG_RETURN_INT64(result);
1082
0
}
1083
1084
Datum
1085
int82mi(PG_FUNCTION_ARGS)
1086
0
{
1087
0
  int64   arg1 = PG_GETARG_INT64(0);
1088
0
  int16   arg2 = PG_GETARG_INT16(1);
1089
0
  int64   result;
1090
1091
0
  if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
1092
0
    ereport(ERROR,
1093
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1094
0
         errmsg("bigint out of range")));
1095
0
  PG_RETURN_INT64(result);
1096
0
}
1097
1098
Datum
1099
int82mul(PG_FUNCTION_ARGS)
1100
0
{
1101
0
  int64   arg1 = PG_GETARG_INT64(0);
1102
0
  int16   arg2 = PG_GETARG_INT16(1);
1103
0
  int64   result;
1104
1105
0
  if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
1106
0
    ereport(ERROR,
1107
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1108
0
         errmsg("bigint out of range")));
1109
0
  PG_RETURN_INT64(result);
1110
0
}
1111
1112
Datum
1113
int82div(PG_FUNCTION_ARGS)
1114
0
{
1115
0
  int64   arg1 = PG_GETARG_INT64(0);
1116
0
  int16   arg2 = PG_GETARG_INT16(1);
1117
0
  int64   result;
1118
1119
0
  if (unlikely(arg2 == 0))
1120
0
  {
1121
0
    ereport(ERROR,
1122
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1123
0
         errmsg("division by zero")));
1124
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1125
0
    PG_RETURN_NULL();
1126
0
  }
1127
1128
  /*
1129
   * INT64_MIN / -1 is problematic, since the result can't be represented on
1130
   * a two's-complement machine.  Some machines produce INT64_MIN, some
1131
   * produce zero, some throw an exception.  We can dodge the problem by
1132
   * recognizing that division by -1 is the same as negation.
1133
   */
1134
0
  if (arg2 == -1)
1135
0
  {
1136
0
    if (unlikely(arg1 == PG_INT64_MIN))
1137
0
      ereport(ERROR,
1138
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1139
0
           errmsg("bigint out of range")));
1140
0
    result = -arg1;
1141
0
    PG_RETURN_INT64(result);
1142
0
  }
1143
1144
  /* No overflow is possible */
1145
1146
0
  result = arg1 / arg2;
1147
1148
0
  PG_RETURN_INT64(result);
1149
0
}
1150
1151
Datum
1152
int28pl(PG_FUNCTION_ARGS)
1153
0
{
1154
0
  int16   arg1 = PG_GETARG_INT16(0);
1155
0
  int64   arg2 = PG_GETARG_INT64(1);
1156
0
  int64   result;
1157
1158
0
  if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
1159
0
    ereport(ERROR,
1160
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1161
0
         errmsg("bigint out of range")));
1162
0
  PG_RETURN_INT64(result);
1163
0
}
1164
1165
Datum
1166
int28mi(PG_FUNCTION_ARGS)
1167
0
{
1168
0
  int16   arg1 = PG_GETARG_INT16(0);
1169
0
  int64   arg2 = PG_GETARG_INT64(1);
1170
0
  int64   result;
1171
1172
0
  if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
1173
0
    ereport(ERROR,
1174
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1175
0
         errmsg("bigint out of range")));
1176
0
  PG_RETURN_INT64(result);
1177
0
}
1178
1179
Datum
1180
int28mul(PG_FUNCTION_ARGS)
1181
0
{
1182
0
  int16   arg1 = PG_GETARG_INT16(0);
1183
0
  int64   arg2 = PG_GETARG_INT64(1);
1184
0
  int64   result;
1185
1186
0
  if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1187
0
    ereport(ERROR,
1188
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1189
0
         errmsg("bigint out of range")));
1190
0
  PG_RETURN_INT64(result);
1191
0
}
1192
1193
Datum
1194
int28div(PG_FUNCTION_ARGS)
1195
0
{
1196
0
  int16   arg1 = PG_GETARG_INT16(0);
1197
0
  int64   arg2 = PG_GETARG_INT64(1);
1198
1199
0
  if (unlikely(arg2 == 0))
1200
0
  {
1201
0
    ereport(ERROR,
1202
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1203
0
         errmsg("division by zero")));
1204
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1205
0
    PG_RETURN_NULL();
1206
0
  }
1207
1208
  /* No overflow is possible */
1209
0
  PG_RETURN_INT64((int64) arg1 / arg2);
1210
0
}
1211
1212
/*
1213
 * Binary arithmetics
1214
 *
1215
 *    int8and   - returns arg1 & arg2
1216
 *    int8or    - returns arg1 | arg2
1217
 *    int8xor   - returns arg1 # arg2
1218
 *    int8not   - returns ~arg1
1219
 *    int8shl   - returns arg1 << arg2
1220
 *    int8shr   - returns arg1 >> arg2
1221
 */
1222
1223
Datum
1224
int8and(PG_FUNCTION_ARGS)
1225
0
{
1226
0
  int64   arg1 = PG_GETARG_INT64(0);
1227
0
  int64   arg2 = PG_GETARG_INT64(1);
1228
1229
0
  PG_RETURN_INT64(arg1 & arg2);
1230
0
}
1231
1232
Datum
1233
int8or(PG_FUNCTION_ARGS)
1234
0
{
1235
0
  int64   arg1 = PG_GETARG_INT64(0);
1236
0
  int64   arg2 = PG_GETARG_INT64(1);
1237
1238
0
  PG_RETURN_INT64(arg1 | arg2);
1239
0
}
1240
1241
Datum
1242
int8xor(PG_FUNCTION_ARGS)
1243
0
{
1244
0
  int64   arg1 = PG_GETARG_INT64(0);
1245
0
  int64   arg2 = PG_GETARG_INT64(1);
1246
1247
0
  PG_RETURN_INT64(arg1 ^ arg2);
1248
0
}
1249
1250
Datum
1251
int8not(PG_FUNCTION_ARGS)
1252
0
{
1253
0
  int64   arg1 = PG_GETARG_INT64(0);
1254
1255
0
  PG_RETURN_INT64(~arg1);
1256
0
}
1257
1258
Datum
1259
int8shl(PG_FUNCTION_ARGS)
1260
0
{
1261
0
  int64   arg1 = PG_GETARG_INT64(0);
1262
0
  int32   arg2 = PG_GETARG_INT32(1);
1263
1264
0
  PG_RETURN_INT64(arg1 << arg2);
1265
0
}
1266
1267
Datum
1268
int8shr(PG_FUNCTION_ARGS)
1269
0
{
1270
0
  int64   arg1 = PG_GETARG_INT64(0);
1271
0
  int32   arg2 = PG_GETARG_INT32(1);
1272
1273
0
  PG_RETURN_INT64(arg1 >> arg2);
1274
0
}
1275
1276
/*----------------------------------------------------------
1277
 *  Conversion operators.
1278
 *---------------------------------------------------------*/
1279
1280
Datum
1281
int48(PG_FUNCTION_ARGS)
1282
0
{
1283
0
  int32   arg = PG_GETARG_INT32(0);
1284
1285
0
  PG_RETURN_INT64((int64) arg);
1286
0
}
1287
1288
Datum
1289
int84(PG_FUNCTION_ARGS)
1290
0
{
1291
0
  int64   arg = PG_GETARG_INT64(0);
1292
1293
0
  if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
1294
0
    ereturn(fcinfo->context, (Datum) 0,
1295
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1296
0
         errmsg("integer out of range")));
1297
1298
0
  PG_RETURN_INT32((int32) arg);
1299
0
}
1300
1301
Datum
1302
int28(PG_FUNCTION_ARGS)
1303
0
{
1304
0
  int16   arg = PG_GETARG_INT16(0);
1305
1306
0
  PG_RETURN_INT64((int64) arg);
1307
0
}
1308
1309
Datum
1310
int82(PG_FUNCTION_ARGS)
1311
0
{
1312
0
  int64   arg = PG_GETARG_INT64(0);
1313
1314
0
  if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
1315
0
    ereturn(fcinfo->context, (Datum) 0,
1316
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1317
0
         errmsg("smallint out of range")));
1318
1319
0
  PG_RETURN_INT16((int16) arg);
1320
0
}
1321
1322
Datum
1323
i8tod(PG_FUNCTION_ARGS)
1324
0
{
1325
0
  int64   arg = PG_GETARG_INT64(0);
1326
0
  float8    result;
1327
1328
0
  result = arg;
1329
1330
0
  PG_RETURN_FLOAT8(result);
1331
0
}
1332
1333
/*
1334
 * dtoi8()
1335
 * Convert float8 to 8-byte integer.
1336
 */
1337
Datum
1338
dtoi8(PG_FUNCTION_ARGS)
1339
0
{
1340
0
  float8    num = PG_GETARG_FLOAT8(0);
1341
1342
  /*
1343
   * Get rid of any fractional part in the input.  This is so we don't fail
1344
   * on just-out-of-range values that would round into range.  Note
1345
   * assumption that rint() will pass through a NaN or Inf unchanged.
1346
   */
1347
0
  num = rint(num);
1348
1349
  /* Range check */
1350
0
  if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
1351
0
    ereturn(fcinfo->context, (Datum) 0,
1352
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1353
0
         errmsg("bigint out of range")));
1354
1355
0
  PG_RETURN_INT64((int64) num);
1356
0
}
1357
1358
Datum
1359
i8tof(PG_FUNCTION_ARGS)
1360
0
{
1361
0
  int64   arg = PG_GETARG_INT64(0);
1362
0
  float4    result;
1363
1364
0
  result = arg;
1365
1366
0
  PG_RETURN_FLOAT4(result);
1367
0
}
1368
1369
/*
1370
 * ftoi8()
1371
 * Convert float4 to 8-byte integer.
1372
 */
1373
Datum
1374
ftoi8(PG_FUNCTION_ARGS)
1375
0
{
1376
0
  float4    num = PG_GETARG_FLOAT4(0);
1377
1378
  /*
1379
   * Get rid of any fractional part in the input.  This is so we don't fail
1380
   * on just-out-of-range values that would round into range.  Note
1381
   * assumption that rint() will pass through a NaN or Inf unchanged.
1382
   */
1383
0
  num = rint(num);
1384
1385
  /* Range check */
1386
0
  if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
1387
0
    ereturn(fcinfo->context, (Datum) 0,
1388
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1389
0
         errmsg("bigint out of range")));
1390
1391
0
  PG_RETURN_INT64((int64) num);
1392
0
}
1393
1394
Datum
1395
i8tooid(PG_FUNCTION_ARGS)
1396
0
{
1397
0
  int64   arg = PG_GETARG_INT64(0);
1398
1399
0
  if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
1400
0
    ereturn(fcinfo->context, (Datum) 0,
1401
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1402
0
         errmsg("OID out of range")));
1403
1404
0
  PG_RETURN_OID((Oid) arg);
1405
0
}
1406
1407
Datum
1408
oidtoi8(PG_FUNCTION_ARGS)
1409
0
{
1410
0
  Oid     arg = PG_GETARG_OID(0);
1411
1412
0
  PG_RETURN_INT64((int64) arg);
1413
0
}
1414
1415
Datum
1416
oidtooid8(PG_FUNCTION_ARGS)
1417
0
{
1418
0
  Oid     arg = PG_GETARG_OID(0);
1419
1420
0
  PG_RETURN_OID8((Oid8) arg);
1421
0
}
1422
1423
/*
1424
 * non-persistent numeric series generator
1425
 */
1426
Datum
1427
generate_series_int8(PG_FUNCTION_ARGS)
1428
0
{
1429
0
  return generate_series_step_int8(fcinfo);
1430
0
}
1431
1432
Datum
1433
generate_series_step_int8(PG_FUNCTION_ARGS)
1434
0
{
1435
0
  FuncCallContext *funcctx;
1436
0
  generate_series_fctx *fctx;
1437
0
  int64   result;
1438
0
  MemoryContext oldcontext;
1439
1440
  /* stuff done only on the first call of the function */
1441
0
  if (SRF_IS_FIRSTCALL())
1442
0
  {
1443
0
    int64   start = PG_GETARG_INT64(0);
1444
0
    int64   finish = PG_GETARG_INT64(1);
1445
0
    int64   step = 1;
1446
1447
    /* see if we were given an explicit step size */
1448
0
    if (PG_NARGS() == 3)
1449
0
      step = PG_GETARG_INT64(2);
1450
0
    if (step == 0)
1451
0
      ereport(ERROR,
1452
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1453
0
           errmsg("step size cannot equal zero")));
1454
1455
    /* create a function context for cross-call persistence */
1456
0
    funcctx = SRF_FIRSTCALL_INIT();
1457
1458
    /*
1459
     * switch to memory context appropriate for multiple function calls
1460
     */
1461
0
    oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1462
1463
    /* allocate memory for user context */
1464
0
    fctx = palloc_object(generate_series_fctx);
1465
1466
    /*
1467
     * Use fctx to keep state from call to call. Seed current with the
1468
     * original start value
1469
     */
1470
0
    fctx->current = start;
1471
0
    fctx->finish = finish;
1472
0
    fctx->step = step;
1473
1474
0
    funcctx->user_fctx = fctx;
1475
0
    MemoryContextSwitchTo(oldcontext);
1476
0
  }
1477
1478
  /* stuff done on every call of the function */
1479
0
  funcctx = SRF_PERCALL_SETUP();
1480
1481
  /*
1482
   * get the saved state and use current as the result for this iteration
1483
   */
1484
0
  fctx = funcctx->user_fctx;
1485
0
  result = fctx->current;
1486
1487
0
  if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1488
0
    (fctx->step < 0 && fctx->current >= fctx->finish))
1489
0
  {
1490
    /*
1491
     * Increment current in preparation for next iteration. If next-value
1492
     * computation overflows, this is the final result.
1493
     */
1494
0
    if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
1495
0
      fctx->step = 0;
1496
1497
    /* do when there is more left to send */
1498
0
    SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1499
0
  }
1500
0
  else
1501
    /* do when there is no more left */
1502
0
    SRF_RETURN_DONE(funcctx);
1503
0
}
1504
1505
/*
1506
 * Planner support function for generate_series(int8, int8 [, int8])
1507
 */
1508
Datum
1509
generate_series_int8_support(PG_FUNCTION_ARGS)
1510
0
{
1511
0
  Node     *rawreq = (Node *) PG_GETARG_POINTER(0);
1512
0
  Node     *ret = NULL;
1513
1514
0
  if (IsA(rawreq, SupportRequestRows))
1515
0
  {
1516
    /* Try to estimate the number of rows returned */
1517
0
    SupportRequestRows *req = (SupportRequestRows *) rawreq;
1518
1519
0
    if (is_funcclause(req->node)) /* be paranoid */
1520
0
    {
1521
0
      List     *args = ((FuncExpr *) req->node)->args;
1522
0
      Node     *arg1,
1523
0
             *arg2,
1524
0
             *arg3;
1525
1526
      /* We can use estimated argument values here */
1527
0
      arg1 = estimate_expression_value(req->root, linitial(args));
1528
0
      arg2 = estimate_expression_value(req->root, lsecond(args));
1529
0
      if (list_length(args) >= 3)
1530
0
        arg3 = estimate_expression_value(req->root, lthird(args));
1531
0
      else
1532
0
        arg3 = NULL;
1533
1534
      /*
1535
       * If any argument is constant NULL, we can safely assume that
1536
       * zero rows are returned.  Otherwise, if they're all non-NULL
1537
       * constants, we can calculate the number of rows that will be
1538
       * returned.  Use double arithmetic to avoid overflow hazards.
1539
       */
1540
0
      if ((IsA(arg1, Const) &&
1541
0
         ((Const *) arg1)->constisnull) ||
1542
0
        (IsA(arg2, Const) &&
1543
0
         ((Const *) arg2)->constisnull) ||
1544
0
        (arg3 != NULL && IsA(arg3, Const) &&
1545
0
         ((Const *) arg3)->constisnull))
1546
0
      {
1547
0
        req->rows = 0;
1548
0
        ret = (Node *) req;
1549
0
      }
1550
0
      else if (IsA(arg1, Const) &&
1551
0
           IsA(arg2, Const) &&
1552
0
           (arg3 == NULL || IsA(arg3, Const)))
1553
0
      {
1554
0
        double    start,
1555
0
              finish,
1556
0
              step;
1557
1558
0
        start = DatumGetInt64(((Const *) arg1)->constvalue);
1559
0
        finish = DatumGetInt64(((Const *) arg2)->constvalue);
1560
0
        step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
1561
1562
        /* This equation works for either sign of step */
1563
0
        if (step != 0)
1564
0
        {
1565
0
          req->rows = floor((finish - start + step) / step);
1566
0
          ret = (Node *) req;
1567
0
        }
1568
0
      }
1569
0
    }
1570
0
  }
1571
1572
  PG_RETURN_POINTER(ret);
1573
0
}