~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/int8.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * int8.c
 
4
 *        Internal 64-bit integer operations
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *        $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.57 2004-12-31 22:01:22 pgsql Exp $
 
11
 *
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#include "postgres.h"
 
15
 
 
16
#include <ctype.h>
 
17
#include <limits.h>
 
18
#include <math.h>
 
19
 
 
20
#include "funcapi.h"
 
21
#include "libpq/pqformat.h"
 
22
#include "utils/int8.h"
 
23
 
 
24
 
 
25
#define MAXINT8LEN              25
 
26
 
 
27
#define SAMESIGN(a,b)   (((a) < 0) == ((b) < 0))
 
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
 * scanint8 --- try to parse a string into an int8.
 
49
 *
 
50
 * If errorOK is false, ereport a useful error message if the string is bad.
 
51
 * If errorOK is true, just return "false" for bad input.
 
52
 */
 
53
bool
 
54
scanint8(const char *str, bool errorOK, int64 *result)
 
55
{
 
56
        const char *ptr = str;
 
57
        int64           tmp = 0;
 
58
        int                     sign = 1;
 
59
 
 
60
        /*
 
61
         * Do our own scan, rather than relying on sscanf which might be
 
62
         * broken for long long.
 
63
         */
 
64
 
 
65
        /* skip leading spaces */
 
66
        while (*ptr && isspace((unsigned char) *ptr))
 
67
                ptr++;
 
68
 
 
69
        /* handle sign */
 
70
        if (*ptr == '-')
 
71
        {
 
72
                ptr++;
 
73
 
 
74
                /*
 
75
                 * Do an explicit check for INT64_MIN.  Ugly though this is, it's
 
76
                 * cleaner than trying to get the loop below to handle it
 
77
                 * portably.
 
78
                 */
 
79
#ifndef INT64_IS_BUSTED
 
80
                if (strncmp(ptr, "9223372036854775808", 19) == 0)
 
81
                {
 
82
                        tmp = -INT64CONST(0x7fffffffffffffff) - 1;
 
83
                        ptr += 19;
 
84
                        goto gotdigits;
 
85
                }
 
86
#endif
 
87
 
 
88
                sign = -1;
 
89
        }
 
90
        else if (*ptr == '+')
 
91
                ptr++;
 
92
 
 
93
        /* require at least one digit */
 
94
        if (!isdigit((unsigned char) *ptr))
 
95
        {
 
96
                if (errorOK)
 
97
                        return false;
 
98
                else
 
99
                        ereport(ERROR,
 
100
                                        (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
101
                                         errmsg("invalid input syntax for integer: \"%s\"",
 
102
                                                        str)));
 
103
        }
 
104
 
 
105
        /* process digits */
 
106
        while (*ptr && isdigit((unsigned char) *ptr))
 
107
        {
 
108
                int64           newtmp = tmp * 10 + (*ptr++ - '0');
 
109
 
 
110
                if ((newtmp / 10) != tmp)               /* overflow? */
 
111
                {
 
112
                        if (errorOK)
 
113
                                return false;
 
114
                        else
 
115
                                ereport(ERROR,
 
116
                                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
117
                                                 errmsg("value \"%s\" is out of range for type bigint",
 
118
                                                                str)));
 
119
                }
 
120
                tmp = newtmp;
 
121
        }
 
122
 
 
123
gotdigits:
 
124
 
 
125
        /* allow trailing whitespace, but not other trailing chars */
 
126
        while (*ptr != '\0' && isspace((unsigned char) *ptr))
 
127
                ptr++;
 
128
 
 
129
        if (*ptr != '\0')
 
130
        {
 
131
                if (errorOK)
 
132
                        return false;
 
133
                else
 
134
                        ereport(ERROR,
 
135
                                        (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
136
                                         errmsg("invalid input syntax for integer: \"%s\"",
 
137
                                                        str)));
 
138
        }
 
139
 
 
140
        *result = (sign < 0) ? -tmp : tmp;
 
141
 
 
142
        return true;
 
143
}
 
144
 
 
145
/* int8in()
 
146
 */
 
147
Datum
 
148
int8in(PG_FUNCTION_ARGS)
 
149
{
 
150
        char       *str = PG_GETARG_CSTRING(0);
 
151
        int64           result;
 
152
 
 
153
        (void) scanint8(str, false, &result);
 
154
        PG_RETURN_INT64(result);
 
155
}
 
156
 
 
157
 
 
158
/* int8out()
 
159
 */
 
160
Datum
 
161
int8out(PG_FUNCTION_ARGS)
 
162
{
 
163
        int64           val = PG_GETARG_INT64(0);
 
164
        char       *result;
 
165
        int                     len;
 
166
        char            buf[MAXINT8LEN + 1];
 
167
 
 
168
        if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0)
 
169
                elog(ERROR, "could not format int8");
 
170
 
 
171
        result = pstrdup(buf);
 
172
        PG_RETURN_CSTRING(result);
 
173
}
 
174
 
 
175
/*
 
176
 *              int8recv                        - converts external binary format to int8
 
177
 */
 
178
Datum
 
179
int8recv(PG_FUNCTION_ARGS)
 
180
{
 
181
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
182
 
 
183
        PG_RETURN_INT64(pq_getmsgint64(buf));
 
184
}
 
185
 
 
186
/*
 
187
 *              int8send                        - converts int8 to binary format
 
188
 */
 
189
Datum
 
190
int8send(PG_FUNCTION_ARGS)
 
191
{
 
192
        int64           arg1 = PG_GETARG_INT64(0);
 
193
        StringInfoData buf;
 
194
 
 
195
        pq_begintypsend(&buf);
 
196
        pq_sendint64(&buf, arg1);
 
197
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 
198
}
 
199
 
 
200
 
 
201
/*----------------------------------------------------------
 
202
 *      Relational operators for int8s, including cross-data-type comparisons.
 
203
 *---------------------------------------------------------*/
 
204
 
 
205
/* int8relop()
 
206
 * Is val1 relop val2?
 
207
 */
 
208
Datum
 
209
int8eq(PG_FUNCTION_ARGS)
 
210
{
 
211
        int64           val1 = PG_GETARG_INT64(0);
 
212
        int64           val2 = PG_GETARG_INT64(1);
 
213
 
 
214
        PG_RETURN_BOOL(val1 == val2);
 
215
}
 
216
 
 
217
Datum
 
218
int8ne(PG_FUNCTION_ARGS)
 
219
{
 
220
        int64           val1 = PG_GETARG_INT64(0);
 
221
        int64           val2 = PG_GETARG_INT64(1);
 
222
 
 
223
        PG_RETURN_BOOL(val1 != val2);
 
224
}
 
225
 
 
226
Datum
 
227
int8lt(PG_FUNCTION_ARGS)
 
228
{
 
229
        int64           val1 = PG_GETARG_INT64(0);
 
230
        int64           val2 = PG_GETARG_INT64(1);
 
231
 
 
232
        PG_RETURN_BOOL(val1 < val2);
 
233
}
 
234
 
 
235
Datum
 
236
int8gt(PG_FUNCTION_ARGS)
 
237
{
 
238
        int64           val1 = PG_GETARG_INT64(0);
 
239
        int64           val2 = PG_GETARG_INT64(1);
 
240
 
 
241
        PG_RETURN_BOOL(val1 > val2);
 
242
}
 
243
 
 
244
Datum
 
245
int8le(PG_FUNCTION_ARGS)
 
246
{
 
247
        int64           val1 = PG_GETARG_INT64(0);
 
248
        int64           val2 = PG_GETARG_INT64(1);
 
249
 
 
250
        PG_RETURN_BOOL(val1 <= val2);
 
251
}
 
252
 
 
253
Datum
 
254
int8ge(PG_FUNCTION_ARGS)
 
255
{
 
256
        int64           val1 = PG_GETARG_INT64(0);
 
257
        int64           val2 = PG_GETARG_INT64(1);
 
258
 
 
259
        PG_RETURN_BOOL(val1 >= val2);
 
260
}
 
261
 
 
262
/* int84relop()
 
263
 * Is 64-bit val1 relop 32-bit val2?
 
264
 */
 
265
Datum
 
266
int84eq(PG_FUNCTION_ARGS)
 
267
{
 
268
        int64           val1 = PG_GETARG_INT64(0);
 
269
        int32           val2 = PG_GETARG_INT32(1);
 
270
 
 
271
        PG_RETURN_BOOL(val1 == val2);
 
272
}
 
273
 
 
274
Datum
 
275
int84ne(PG_FUNCTION_ARGS)
 
276
{
 
277
        int64           val1 = PG_GETARG_INT64(0);
 
278
        int32           val2 = PG_GETARG_INT32(1);
 
279
 
 
280
        PG_RETURN_BOOL(val1 != val2);
 
281
}
 
282
 
 
283
Datum
 
284
int84lt(PG_FUNCTION_ARGS)
 
285
{
 
286
        int64           val1 = PG_GETARG_INT64(0);
 
287
        int32           val2 = PG_GETARG_INT32(1);
 
288
 
 
289
        PG_RETURN_BOOL(val1 < val2);
 
290
}
 
291
 
 
292
Datum
 
293
int84gt(PG_FUNCTION_ARGS)
 
294
{
 
295
        int64           val1 = PG_GETARG_INT64(0);
 
296
        int32           val2 = PG_GETARG_INT32(1);
 
297
 
 
298
        PG_RETURN_BOOL(val1 > val2);
 
299
}
 
300
 
 
301
Datum
 
302
int84le(PG_FUNCTION_ARGS)
 
303
{
 
304
        int64           val1 = PG_GETARG_INT64(0);
 
305
        int32           val2 = PG_GETARG_INT32(1);
 
306
 
 
307
        PG_RETURN_BOOL(val1 <= val2);
 
308
}
 
309
 
 
310
Datum
 
311
int84ge(PG_FUNCTION_ARGS)
 
312
{
 
313
        int64           val1 = PG_GETARG_INT64(0);
 
314
        int32           val2 = PG_GETARG_INT32(1);
 
315
 
 
316
        PG_RETURN_BOOL(val1 >= val2);
 
317
}
 
318
 
 
319
/* int48relop()
 
320
 * Is 32-bit val1 relop 64-bit val2?
 
321
 */
 
322
Datum
 
323
int48eq(PG_FUNCTION_ARGS)
 
324
{
 
325
        int32           val1 = PG_GETARG_INT32(0);
 
326
        int64           val2 = PG_GETARG_INT64(1);
 
327
 
 
328
        PG_RETURN_BOOL(val1 == val2);
 
329
}
 
330
 
 
331
Datum
 
332
int48ne(PG_FUNCTION_ARGS)
 
333
{
 
334
        int32           val1 = PG_GETARG_INT32(0);
 
335
        int64           val2 = PG_GETARG_INT64(1);
 
336
 
 
337
        PG_RETURN_BOOL(val1 != val2);
 
338
}
 
339
 
 
340
Datum
 
341
int48lt(PG_FUNCTION_ARGS)
 
342
{
 
343
        int32           val1 = PG_GETARG_INT32(0);
 
344
        int64           val2 = PG_GETARG_INT64(1);
 
345
 
 
346
        PG_RETURN_BOOL(val1 < val2);
 
347
}
 
348
 
 
349
Datum
 
350
int48gt(PG_FUNCTION_ARGS)
 
351
{
 
352
        int32           val1 = PG_GETARG_INT32(0);
 
353
        int64           val2 = PG_GETARG_INT64(1);
 
354
 
 
355
        PG_RETURN_BOOL(val1 > val2);
 
356
}
 
357
 
 
358
Datum
 
359
int48le(PG_FUNCTION_ARGS)
 
360
{
 
361
        int32           val1 = PG_GETARG_INT32(0);
 
362
        int64           val2 = PG_GETARG_INT64(1);
 
363
 
 
364
        PG_RETURN_BOOL(val1 <= val2);
 
365
}
 
366
 
 
367
Datum
 
368
int48ge(PG_FUNCTION_ARGS)
 
369
{
 
370
        int32           val1 = PG_GETARG_INT32(0);
 
371
        int64           val2 = PG_GETARG_INT64(1);
 
372
 
 
373
        PG_RETURN_BOOL(val1 >= val2);
 
374
}
 
375
 
 
376
/* int82relop()
 
377
 * Is 64-bit val1 relop 16-bit val2?
 
378
 */
 
379
Datum
 
380
int82eq(PG_FUNCTION_ARGS)
 
381
{
 
382
        int64           val1 = PG_GETARG_INT64(0);
 
383
        int16           val2 = PG_GETARG_INT16(1);
 
384
 
 
385
        PG_RETURN_BOOL(val1 == val2);
 
386
}
 
387
 
 
388
Datum
 
389
int82ne(PG_FUNCTION_ARGS)
 
390
{
 
391
        int64           val1 = PG_GETARG_INT64(0);
 
392
        int16           val2 = PG_GETARG_INT16(1);
 
393
 
 
394
        PG_RETURN_BOOL(val1 != val2);
 
395
}
 
396
 
 
397
Datum
 
398
int82lt(PG_FUNCTION_ARGS)
 
399
{
 
400
        int64           val1 = PG_GETARG_INT64(0);
 
401
        int16           val2 = PG_GETARG_INT16(1);
 
402
 
 
403
        PG_RETURN_BOOL(val1 < val2);
 
404
}
 
405
 
 
406
Datum
 
407
int82gt(PG_FUNCTION_ARGS)
 
408
{
 
409
        int64           val1 = PG_GETARG_INT64(0);
 
410
        int16           val2 = PG_GETARG_INT16(1);
 
411
 
 
412
        PG_RETURN_BOOL(val1 > val2);
 
413
}
 
414
 
 
415
Datum
 
416
int82le(PG_FUNCTION_ARGS)
 
417
{
 
418
        int64           val1 = PG_GETARG_INT64(0);
 
419
        int16           val2 = PG_GETARG_INT16(1);
 
420
 
 
421
        PG_RETURN_BOOL(val1 <= val2);
 
422
}
 
423
 
 
424
Datum
 
425
int82ge(PG_FUNCTION_ARGS)
 
426
{
 
427
        int64           val1 = PG_GETARG_INT64(0);
 
428
        int16           val2 = PG_GETARG_INT16(1);
 
429
 
 
430
        PG_RETURN_BOOL(val1 >= val2);
 
431
}
 
432
 
 
433
/* int28relop()
 
434
 * Is 16-bit val1 relop 64-bit val2?
 
435
 */
 
436
Datum
 
437
int28eq(PG_FUNCTION_ARGS)
 
438
{
 
439
        int16           val1 = PG_GETARG_INT16(0);
 
440
        int64           val2 = PG_GETARG_INT64(1);
 
441
 
 
442
        PG_RETURN_BOOL(val1 == val2);
 
443
}
 
444
 
 
445
Datum
 
446
int28ne(PG_FUNCTION_ARGS)
 
447
{
 
448
        int16           val1 = PG_GETARG_INT16(0);
 
449
        int64           val2 = PG_GETARG_INT64(1);
 
450
 
 
451
        PG_RETURN_BOOL(val1 != val2);
 
452
}
 
453
 
 
454
Datum
 
455
int28lt(PG_FUNCTION_ARGS)
 
456
{
 
457
        int16           val1 = PG_GETARG_INT16(0);
 
458
        int64           val2 = PG_GETARG_INT64(1);
 
459
 
 
460
        PG_RETURN_BOOL(val1 < val2);
 
461
}
 
462
 
 
463
Datum
 
464
int28gt(PG_FUNCTION_ARGS)
 
465
{
 
466
        int16           val1 = PG_GETARG_INT16(0);
 
467
        int64           val2 = PG_GETARG_INT64(1);
 
468
 
 
469
        PG_RETURN_BOOL(val1 > val2);
 
470
}
 
471
 
 
472
Datum
 
473
int28le(PG_FUNCTION_ARGS)
 
474
{
 
475
        int16           val1 = PG_GETARG_INT16(0);
 
476
        int64           val2 = PG_GETARG_INT64(1);
 
477
 
 
478
        PG_RETURN_BOOL(val1 <= val2);
 
479
}
 
480
 
 
481
Datum
 
482
int28ge(PG_FUNCTION_ARGS)
 
483
{
 
484
        int16           val1 = PG_GETARG_INT16(0);
 
485
        int64           val2 = PG_GETARG_INT64(1);
 
486
 
 
487
        PG_RETURN_BOOL(val1 >= val2);
 
488
}
 
489
 
 
490
 
 
491
/*----------------------------------------------------------
 
492
 *      Arithmetic operators on 64-bit integers.
 
493
 *---------------------------------------------------------*/
 
494
 
 
495
Datum
 
496
int8um(PG_FUNCTION_ARGS)
 
497
{
 
498
        int64           arg = PG_GETARG_INT64(0);
 
499
        int64           result;
 
500
 
 
501
        result = -arg;
 
502
        /* overflow check (needed for INT64_MIN) */
 
503
        if (arg != 0 && SAMESIGN(result, arg))
 
504
                ereport(ERROR,
 
505
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
506
                                 errmsg("bigint out of range")));
 
507
        PG_RETURN_INT64(result);
 
508
}
 
509
 
 
510
Datum
 
511
int8up(PG_FUNCTION_ARGS)
 
512
{
 
513
        int64           arg = PG_GETARG_INT64(0);
 
514
 
 
515
        PG_RETURN_INT64(arg);
 
516
}
 
517
 
 
518
Datum
 
519
int8pl(PG_FUNCTION_ARGS)
 
520
{
 
521
        int64           arg1 = PG_GETARG_INT64(0);
 
522
        int64           arg2 = PG_GETARG_INT64(1);
 
523
        int64           result;
 
524
 
 
525
        result = arg1 + arg2;
 
526
        /*
 
527
         * Overflow check.  If the inputs are of different signs then their sum
 
528
         * cannot overflow.  If the inputs are of the same sign, their sum
 
529
         * had better be that sign too.
 
530
         */
 
531
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
532
                ereport(ERROR,
 
533
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
534
                                 errmsg("bigint out of range")));
 
535
        PG_RETURN_INT64(result);
 
536
}
 
537
 
 
538
Datum
 
539
int8mi(PG_FUNCTION_ARGS)
 
540
{
 
541
        int64           arg1 = PG_GETARG_INT64(0);
 
542
        int64           arg2 = PG_GETARG_INT64(1);
 
543
        int64           result;
 
544
 
 
545
        result = arg1 - arg2;
 
546
        /*
 
547
         * Overflow check.  If the inputs are of the same sign then their
 
548
         * difference cannot overflow.  If they are of different signs then
 
549
         * the result should be of the same sign as the first input.
 
550
         */
 
551
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
552
                ereport(ERROR,
 
553
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
554
                                 errmsg("bigint out of range")));
 
555
        PG_RETURN_INT64(result);
 
556
}
 
557
 
 
558
Datum
 
559
int8mul(PG_FUNCTION_ARGS)
 
560
{
 
561
        int64           arg1 = PG_GETARG_INT64(0);
 
562
        int64           arg2 = PG_GETARG_INT64(1);
 
563
        int64           result;
 
564
 
 
565
        result = arg1 * arg2;
 
566
        /*
 
567
         * Overflow check.  We basically check to see if result / arg2 gives
 
568
         * arg1 again.  There are two cases where this fails: arg2 = 0 (which
 
569
         * cannot overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division
 
570
         * itself will overflow and thus incorrectly match).
 
571
         *
 
572
         * Since the division is likely much more expensive than the actual
 
573
         * multiplication, we'd like to skip it where possible.  The best
 
574
         * bang for the buck seems to be to check whether both inputs are in
 
575
         * the int32 range; if so, no overflow is possible.
 
576
         */
 
577
        if (!(arg1 == (int64) ((int32) arg1) &&
 
578
                  arg2 == (int64) ((int32) arg2)) &&
 
579
                arg2 != 0 &&
 
580
                (result/arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
 
581
                ereport(ERROR,
 
582
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
583
                                 errmsg("bigint out of range")));
 
584
        PG_RETURN_INT64(result);
 
585
}
 
586
 
 
587
Datum
 
588
int8div(PG_FUNCTION_ARGS)
 
589
{
 
590
        int64           arg1 = PG_GETARG_INT64(0);
 
591
        int64           arg2 = PG_GETARG_INT64(1);
 
592
        int64           result;
 
593
 
 
594
        if (arg2 == 0)
 
595
                ereport(ERROR,
 
596
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
597
                                 errmsg("division by zero")));
 
598
 
 
599
        result = arg1 / arg2;
 
600
        /*
 
601
         * Overflow check.  The only possible overflow case is for
 
602
         * arg1 = INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN,
 
603
         * which can't be represented on a two's-complement machine.
 
604
         */
 
605
        if (arg2 == -1 && arg1 < 0 && result < 0)
 
606
                ereport(ERROR,
 
607
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
608
                                 errmsg("bigint out of range")));
 
609
        PG_RETURN_INT64(result);
 
610
}
 
611
 
 
612
/* int8abs()
 
613
 * Absolute value
 
614
 */
 
615
Datum
 
616
int8abs(PG_FUNCTION_ARGS)
 
617
{
 
618
        int64           arg1 = PG_GETARG_INT64(0);
 
619
        int64           result;
 
620
 
 
621
        result = (arg1 < 0) ? -arg1 : arg1;
 
622
        /* overflow check (needed for INT64_MIN) */
 
623
        if (result < 0)
 
624
                ereport(ERROR,
 
625
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
626
                                 errmsg("bigint out of range")));
 
627
        PG_RETURN_INT64(result);
 
628
}
 
629
 
 
630
/* int8mod()
 
631
 * Modulo operation.
 
632
 */
 
633
Datum
 
634
int8mod(PG_FUNCTION_ARGS)
 
635
{
 
636
        int64           arg1 = PG_GETARG_INT64(0);
 
637
        int64           arg2 = PG_GETARG_INT64(1);
 
638
 
 
639
        if (arg2 == 0)
 
640
                ereport(ERROR,
 
641
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
642
                                 errmsg("division by zero")));
 
643
        /* No overflow is possible */
 
644
 
 
645
        PG_RETURN_INT64(arg1 % arg2);
 
646
}
 
647
 
 
648
 
 
649
Datum
 
650
int8inc(PG_FUNCTION_ARGS)
 
651
{
 
652
        int64           arg = PG_GETARG_INT64(0);
 
653
        int64           result;
 
654
 
 
655
        result = arg + 1;
 
656
        /* Overflow check */
 
657
        if (arg > 0 && result < 0)
 
658
                ereport(ERROR,
 
659
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
660
                                 errmsg("bigint out of range")));
 
661
 
 
662
        PG_RETURN_INT64(result);
 
663
}
 
664
 
 
665
Datum
 
666
int8larger(PG_FUNCTION_ARGS)
 
667
{
 
668
        int64           arg1 = PG_GETARG_INT64(0);
 
669
        int64           arg2 = PG_GETARG_INT64(1);
 
670
        int64           result;
 
671
 
 
672
        result = ((arg1 > arg2) ? arg1 : arg2);
 
673
 
 
674
        PG_RETURN_INT64(result);
 
675
}
 
676
 
 
677
Datum
 
678
int8smaller(PG_FUNCTION_ARGS)
 
679
{
 
680
        int64           arg1 = PG_GETARG_INT64(0);
 
681
        int64           arg2 = PG_GETARG_INT64(1);
 
682
        int64           result;
 
683
 
 
684
        result = ((arg1 < arg2) ? arg1 : arg2);
 
685
 
 
686
        PG_RETURN_INT64(result);
 
687
}
 
688
 
 
689
Datum
 
690
int84pl(PG_FUNCTION_ARGS)
 
691
{
 
692
        int64           arg1 = PG_GETARG_INT64(0);
 
693
        int32           arg2 = PG_GETARG_INT32(1);
 
694
        int64           result;
 
695
 
 
696
        result = arg1 + arg2;
 
697
        /*
 
698
         * Overflow check.  If the inputs are of different signs then their sum
 
699
         * cannot overflow.  If the inputs are of the same sign, their sum
 
700
         * had better be that sign too.
 
701
         */
 
702
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
703
                ereport(ERROR,
 
704
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
705
                                 errmsg("bigint out of range")));
 
706
        PG_RETURN_INT64(result);
 
707
}
 
708
 
 
709
Datum
 
710
int84mi(PG_FUNCTION_ARGS)
 
711
{
 
712
        int64           arg1 = PG_GETARG_INT64(0);
 
713
        int32           arg2 = PG_GETARG_INT32(1);
 
714
        int64           result;
 
715
 
 
716
        result = arg1 - arg2;
 
717
        /*
 
718
         * Overflow check.  If the inputs are of the same sign then their
 
719
         * difference cannot overflow.  If they are of different signs then
 
720
         * the result should be of the same sign as the first input.
 
721
         */
 
722
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
723
                ereport(ERROR,
 
724
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
725
                                 errmsg("bigint out of range")));
 
726
        PG_RETURN_INT64(result);
 
727
}
 
728
 
 
729
Datum
 
730
int84mul(PG_FUNCTION_ARGS)
 
731
{
 
732
        int64           arg1 = PG_GETARG_INT64(0);
 
733
        int32           arg2 = PG_GETARG_INT32(1);
 
734
        int64           result;
 
735
 
 
736
        result = arg1 * arg2;
 
737
        /*
 
738
         * Overflow check.  We basically check to see if result / arg1 gives
 
739
         * arg2 again.  There is one case where this fails: arg1 = 0 (which
 
740
         * cannot overflow).
 
741
         *
 
742
         * Since the division is likely much more expensive than the actual
 
743
         * multiplication, we'd like to skip it where possible.  The best
 
744
         * bang for the buck seems to be to check whether both inputs are in
 
745
         * the int32 range; if so, no overflow is possible.
 
746
         */
 
747
        if (arg1 != (int64) ((int32) arg1) &&
 
748
                result/arg1 != arg2)
 
749
                ereport(ERROR,
 
750
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
751
                                 errmsg("bigint out of range")));
 
752
        PG_RETURN_INT64(result);
 
753
}
 
754
 
 
755
Datum
 
756
int84div(PG_FUNCTION_ARGS)
 
757
{
 
758
        int64           arg1 = PG_GETARG_INT64(0);
 
759
        int32           arg2 = PG_GETARG_INT32(1);
 
760
        int64           result;
 
761
 
 
762
        if (arg2 == 0)
 
763
                ereport(ERROR,
 
764
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
765
                                 errmsg("division by zero")));
 
766
 
 
767
        result = arg1 / arg2;
 
768
        /*
 
769
         * Overflow check.  The only possible overflow case is for
 
770
         * arg1 = INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN,
 
771
         * which can't be represented on a two's-complement machine.
 
772
         */
 
773
        if (arg2 == -1 && arg1 < 0 && result < 0)
 
774
                ereport(ERROR,
 
775
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
776
                                 errmsg("bigint out of range")));
 
777
        PG_RETURN_INT64(result);
 
778
}
 
779
 
 
780
Datum
 
781
int48pl(PG_FUNCTION_ARGS)
 
782
{
 
783
        int32           arg1 = PG_GETARG_INT32(0);
 
784
        int64           arg2 = PG_GETARG_INT64(1);
 
785
        int64           result;
 
786
 
 
787
        result = arg1 + arg2;
 
788
        /*
 
789
         * Overflow check.  If the inputs are of different signs then their sum
 
790
         * cannot overflow.  If the inputs are of the same sign, their sum
 
791
         * had better be that sign too.
 
792
         */
 
793
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
794
                ereport(ERROR,
 
795
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
796
                                 errmsg("bigint out of range")));
 
797
        PG_RETURN_INT64(result);
 
798
}
 
799
 
 
800
Datum
 
801
int48mi(PG_FUNCTION_ARGS)
 
802
{
 
803
        int32           arg1 = PG_GETARG_INT32(0);
 
804
        int64           arg2 = PG_GETARG_INT64(1);
 
805
        int64           result;
 
806
 
 
807
        result = arg1 - arg2;
 
808
        /*
 
809
         * Overflow check.  If the inputs are of the same sign then their
 
810
         * difference cannot overflow.  If they are of different signs then
 
811
         * the result should be of the same sign as the first input.
 
812
         */
 
813
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
814
                ereport(ERROR,
 
815
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
816
                                 errmsg("bigint out of range")));
 
817
        PG_RETURN_INT64(result);
 
818
}
 
819
 
 
820
Datum
 
821
int48mul(PG_FUNCTION_ARGS)
 
822
{
 
823
        int32           arg1 = PG_GETARG_INT32(0);
 
824
        int64           arg2 = PG_GETARG_INT64(1);
 
825
        int64           result;
 
826
 
 
827
        result = arg1 * arg2;
 
828
        /*
 
829
         * Overflow check.  We basically check to see if result / arg2 gives
 
830
         * arg1 again.  There is one case where this fails: arg2 = 0 (which
 
831
         * cannot overflow).
 
832
         *
 
833
         * Since the division is likely much more expensive than the actual
 
834
         * multiplication, we'd like to skip it where possible.  The best
 
835
         * bang for the buck seems to be to check whether both inputs are in
 
836
         * the int32 range; if so, no overflow is possible.
 
837
         */
 
838
        if (arg2 != (int64) ((int32) arg2) &&
 
839
                result/arg2 != arg1)
 
840
                ereport(ERROR,
 
841
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
842
                                 errmsg("bigint out of range")));
 
843
        PG_RETURN_INT64(result);
 
844
}
 
845
 
 
846
Datum
 
847
int48div(PG_FUNCTION_ARGS)
 
848
{
 
849
        int32           arg1 = PG_GETARG_INT32(0);
 
850
        int64           arg2 = PG_GETARG_INT64(1);
 
851
 
 
852
        if (arg2 == 0)
 
853
                ereport(ERROR,
 
854
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
855
                                 errmsg("division by zero")));
 
856
        /* No overflow is possible */
 
857
        PG_RETURN_INT64((int64) arg1 / arg2);
 
858
}
 
859
 
 
860
/* Binary arithmetics
 
861
 *
 
862
 *              int8and         - returns arg1 & arg2
 
863
 *              int8or          - returns arg1 | arg2
 
864
 *              int8xor         - returns arg1 # arg2
 
865
 *              int8not         - returns ~arg1
 
866
 *              int8shl         - returns arg1 << arg2
 
867
 *              int8shr         - returns arg1 >> arg2
 
868
 */
 
869
 
 
870
Datum
 
871
int8and(PG_FUNCTION_ARGS)
 
872
{
 
873
        int64           arg1 = PG_GETARG_INT64(0);
 
874
        int64           arg2 = PG_GETARG_INT64(1);
 
875
 
 
876
        PG_RETURN_INT64(arg1 & arg2);
 
877
}
 
878
 
 
879
Datum
 
880
int8or(PG_FUNCTION_ARGS)
 
881
{
 
882
        int64           arg1 = PG_GETARG_INT64(0);
 
883
        int64           arg2 = PG_GETARG_INT64(1);
 
884
 
 
885
        PG_RETURN_INT64(arg1 | arg2);
 
886
}
 
887
 
 
888
Datum
 
889
int8xor(PG_FUNCTION_ARGS)
 
890
{
 
891
        int64           arg1 = PG_GETARG_INT64(0);
 
892
        int64           arg2 = PG_GETARG_INT64(1);
 
893
 
 
894
        PG_RETURN_INT64(arg1 ^ arg2);
 
895
}
 
896
 
 
897
Datum
 
898
int8not(PG_FUNCTION_ARGS)
 
899
{
 
900
        int64           arg1 = PG_GETARG_INT64(0);
 
901
 
 
902
        PG_RETURN_INT64(~arg1);
 
903
}
 
904
 
 
905
Datum
 
906
int8shl(PG_FUNCTION_ARGS)
 
907
{
 
908
        int64           arg1 = PG_GETARG_INT64(0);
 
909
        int32           arg2 = PG_GETARG_INT32(1);
 
910
 
 
911
        PG_RETURN_INT64(arg1 << arg2);
 
912
}
 
913
 
 
914
Datum
 
915
int8shr(PG_FUNCTION_ARGS)
 
916
{
 
917
        int64           arg1 = PG_GETARG_INT64(0);
 
918
        int32           arg2 = PG_GETARG_INT32(1);
 
919
 
 
920
        PG_RETURN_INT64(arg1 >> arg2);
 
921
}
 
922
 
 
923
/*----------------------------------------------------------
 
924
 *      Conversion operators.
 
925
 *---------------------------------------------------------*/
 
926
 
 
927
Datum
 
928
int48(PG_FUNCTION_ARGS)
 
929
{
 
930
        int32           arg = PG_GETARG_INT32(0);
 
931
 
 
932
        PG_RETURN_INT64((int64) arg);
 
933
}
 
934
 
 
935
Datum
 
936
int84(PG_FUNCTION_ARGS)
 
937
{
 
938
        int64           arg = PG_GETARG_INT64(0);
 
939
        int32           result;
 
940
 
 
941
        result = (int32) arg;
 
942
 
 
943
        /* Test for overflow by reverse-conversion. */
 
944
        if ((int64) result != arg)
 
945
                ereport(ERROR,
 
946
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
947
                                 errmsg("integer out of range")));
 
948
 
 
949
        PG_RETURN_INT32(result);
 
950
}
 
951
 
 
952
Datum
 
953
int28(PG_FUNCTION_ARGS)
 
954
{
 
955
        int16           arg = PG_GETARG_INT16(0);
 
956
 
 
957
        PG_RETURN_INT64((int64) arg);
 
958
}
 
959
 
 
960
Datum
 
961
int82(PG_FUNCTION_ARGS)
 
962
{
 
963
        int64           arg = PG_GETARG_INT64(0);
 
964
        int16           result;
 
965
 
 
966
        result = (int16) arg;
 
967
 
 
968
        /* Test for overflow by reverse-conversion. */
 
969
        if ((int64) result != arg)
 
970
                ereport(ERROR,
 
971
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
972
                                 errmsg("smallint out of range")));
 
973
 
 
974
        PG_RETURN_INT16(result);
 
975
}
 
976
 
 
977
Datum
 
978
i8tod(PG_FUNCTION_ARGS)
 
979
{
 
980
        int64           arg = PG_GETARG_INT64(0);
 
981
        float8          result;
 
982
 
 
983
        result = arg;
 
984
 
 
985
        PG_RETURN_FLOAT8(result);
 
986
}
 
987
 
 
988
/* dtoi8()
 
989
 * Convert float8 to 8-byte integer.
 
990
 */
 
991
Datum
 
992
dtoi8(PG_FUNCTION_ARGS)
 
993
{
 
994
        float8          arg = PG_GETARG_FLOAT8(0);
 
995
        int64           result;
 
996
 
 
997
        /* Round arg to nearest integer (but it's still in float form) */
 
998
        arg = rint(arg);
 
999
 
 
1000
        /*
 
1001
         * Does it fit in an int64?  Avoid assuming that we have handy
 
1002
         * constants defined for the range boundaries, instead test for
 
1003
         * overflow by reverse-conversion.
 
1004
         */
 
1005
        result = (int64) arg;
 
1006
 
 
1007
        if ((float8) result != arg)
 
1008
                ereport(ERROR,
 
1009
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1010
                                 errmsg("bigint out of range")));
 
1011
 
 
1012
        PG_RETURN_INT64(result);
 
1013
}
 
1014
 
 
1015
Datum
 
1016
i8tof(PG_FUNCTION_ARGS)
 
1017
{
 
1018
        int64           arg = PG_GETARG_INT64(0);
 
1019
        float4          result;
 
1020
 
 
1021
        result = arg;
 
1022
 
 
1023
        PG_RETURN_FLOAT4(result);
 
1024
}
 
1025
 
 
1026
/* ftoi8()
 
1027
 * Convert float4 to 8-byte integer.
 
1028
 */
 
1029
Datum
 
1030
ftoi8(PG_FUNCTION_ARGS)
 
1031
{
 
1032
        float4          arg = PG_GETARG_FLOAT4(0);
 
1033
        int64           result;
 
1034
        float8          darg;
 
1035
 
 
1036
        /* Round arg to nearest integer (but it's still in float form) */
 
1037
        darg = rint(arg);
 
1038
 
 
1039
        /*
 
1040
         * Does it fit in an int64?  Avoid assuming that we have handy
 
1041
         * constants defined for the range boundaries, instead test for
 
1042
         * overflow by reverse-conversion.
 
1043
         */
 
1044
        result = (int64) darg;
 
1045
 
 
1046
        if ((float8) result != darg)
 
1047
                ereport(ERROR,
 
1048
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1049
                                 errmsg("bigint out of range")));
 
1050
 
 
1051
        PG_RETURN_INT64(result);
 
1052
}
 
1053
 
 
1054
Datum
 
1055
i8tooid(PG_FUNCTION_ARGS)
 
1056
{
 
1057
        int64           arg = PG_GETARG_INT64(0);
 
1058
        Oid                     result;
 
1059
 
 
1060
        result = (Oid) arg;
 
1061
 
 
1062
        /* Test for overflow by reverse-conversion. */
 
1063
        if ((int64) result != arg)
 
1064
                ereport(ERROR,
 
1065
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1066
                                 errmsg("OID out of range")));
 
1067
 
 
1068
        PG_RETURN_OID(result);
 
1069
}
 
1070
 
 
1071
Datum
 
1072
oidtoi8(PG_FUNCTION_ARGS)
 
1073
{
 
1074
        Oid                     arg = PG_GETARG_OID(0);
 
1075
 
 
1076
        PG_RETURN_INT64((int64) arg);
 
1077
}
 
1078
 
 
1079
Datum
 
1080
text_int8(PG_FUNCTION_ARGS)
 
1081
{
 
1082
        text       *str = PG_GETARG_TEXT_P(0);
 
1083
        int                     len;
 
1084
        char       *s;
 
1085
        Datum           result;
 
1086
 
 
1087
        len = (VARSIZE(str) - VARHDRSZ);
 
1088
        s = palloc(len + 1);
 
1089
        memcpy(s, VARDATA(str), len);
 
1090
        *(s + len) = '\0';
 
1091
 
 
1092
        result = DirectFunctionCall1(int8in, CStringGetDatum(s));
 
1093
 
 
1094
        pfree(s);
 
1095
 
 
1096
        return result;
 
1097
}
 
1098
 
 
1099
Datum
 
1100
int8_text(PG_FUNCTION_ARGS)
 
1101
{
 
1102
        /* arg is int64, but easier to leave it as Datum */
 
1103
        Datum           arg = PG_GETARG_DATUM(0);
 
1104
        char       *s;
 
1105
        int                     len;
 
1106
        text       *result;
 
1107
 
 
1108
        s = DatumGetCString(DirectFunctionCall1(int8out, arg));
 
1109
        len = strlen(s);
 
1110
 
 
1111
        result = (text *) palloc(VARHDRSZ + len);
 
1112
 
 
1113
        VARATT_SIZEP(result) = len + VARHDRSZ;
 
1114
        memcpy(VARDATA(result), s, len);
 
1115
 
 
1116
        pfree(s);
 
1117
 
 
1118
        PG_RETURN_TEXT_P(result);
 
1119
}
 
1120
 
 
1121
/*
 
1122
 * non-persistent numeric series generator
 
1123
 */
 
1124
Datum
 
1125
generate_series_int8(PG_FUNCTION_ARGS)
 
1126
{
 
1127
        return generate_series_step_int8(fcinfo);
 
1128
}
 
1129
 
 
1130
Datum
 
1131
generate_series_step_int8(PG_FUNCTION_ARGS)
 
1132
{
 
1133
        FuncCallContext *funcctx;
 
1134
        generate_series_fctx *fctx;
 
1135
        int64           result;
 
1136
        MemoryContext oldcontext;
 
1137
 
 
1138
        /* stuff done only on the first call of the function */
 
1139
        if (SRF_IS_FIRSTCALL())
 
1140
        {
 
1141
                int64           start = PG_GETARG_INT64(0);
 
1142
                int64           finish = PG_GETARG_INT64(1);
 
1143
                int64           step = 1;
 
1144
 
 
1145
                /* see if we were given an explicit step size */
 
1146
                if (PG_NARGS() == 3)
 
1147
                        step = PG_GETARG_INT64(2);
 
1148
                if (step == 0)
 
1149
                        ereport(ERROR,
 
1150
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
1151
                                         errmsg("step size may not equal zero")));
 
1152
 
 
1153
                /* create a function context for cross-call persistence */
 
1154
                funcctx = SRF_FIRSTCALL_INIT();
 
1155
 
 
1156
                /*
 
1157
                 * switch to memory context appropriate for multiple function
 
1158
                 * calls
 
1159
                 */
 
1160
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
1161
 
 
1162
                /* allocate memory for user context */
 
1163
                fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
 
1164
 
 
1165
                /*
 
1166
                 * Use fctx to keep state from call to call. Seed current with the
 
1167
                 * original start value
 
1168
                 */
 
1169
                fctx->current = start;
 
1170
                fctx->finish = finish;
 
1171
                fctx->step = step;
 
1172
 
 
1173
                funcctx->user_fctx = fctx;
 
1174
                MemoryContextSwitchTo(oldcontext);
 
1175
        }
 
1176
 
 
1177
        /* stuff done on every call of the function */
 
1178
        funcctx = SRF_PERCALL_SETUP();
 
1179
 
 
1180
        /*
 
1181
         * get the saved state and use current as the result for this
 
1182
         * iteration
 
1183
         */
 
1184
        fctx = funcctx->user_fctx;
 
1185
        result = fctx->current;
 
1186
 
 
1187
        if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
 
1188
                (fctx->step < 0 && fctx->current >= fctx->finish))
 
1189
        {
 
1190
                /* increment current in preparation for next iteration */
 
1191
                fctx->current += fctx->step;
 
1192
 
 
1193
                /* do when there is more left to send */
 
1194
                SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
 
1195
        }
 
1196
        else
 
1197
                /* do when there is no more left */
 
1198
                SRF_RETURN_DONE(funcctx);
 
1199
}