~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/int.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
 * int.c
 
4
 *        Functions for the built-in integer types (except int8).
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.64 2004-12-31 22:01:22 pgsql Exp $
 
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
 *              Conversion routines:
 
22
 *               itoi, int2_text, int4_text
 
23
 *              Boolean operators:
 
24
 *               inteq, intne, intlt, intle, intgt, intge
 
25
 *              Arithmetic operators:
 
26
 *               intpl, intmi, int4mul, intdiv
 
27
 *
 
28
 *              Arithmetic operators:
 
29
 *               intmod
 
30
 */
 
31
#include "postgres.h"
 
32
 
 
33
#include <ctype.h>
 
34
#include <limits.h>
 
35
 
 
36
#include "funcapi.h"
 
37
#include "libpq/pqformat.h"
 
38
#include "utils/builtins.h"
 
39
 
 
40
 
 
41
#ifndef SHRT_MAX
 
42
#define SHRT_MAX (0x7FFF)
 
43
#endif
 
44
#ifndef SHRT_MIN
 
45
#define SHRT_MIN (-0x8000)
 
46
#endif
 
47
 
 
48
#define SAMESIGN(a,b)   (((a) < 0) == ((b) < 0))
 
49
 
 
50
typedef struct
 
51
{
 
52
        int32           current;
 
53
        int32           finish;
 
54
        int32           step;
 
55
} generate_series_fctx;
 
56
 
 
57
 
 
58
/*****************************************************************************
 
59
 *       USER I/O ROUTINES                                                                                                               *
 
60
 *****************************************************************************/
 
61
 
 
62
/*
 
63
 *              int2in                  - converts "num" to short
 
64
 */
 
65
Datum
 
66
int2in(PG_FUNCTION_ARGS)
 
67
{
 
68
        char       *num = PG_GETARG_CSTRING(0);
 
69
 
 
70
        PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
 
71
}
 
72
 
 
73
/*
 
74
 *              int2out                 - converts short to "num"
 
75
 */
 
76
Datum
 
77
int2out(PG_FUNCTION_ARGS)
 
78
{
 
79
        int16           arg1 = PG_GETARG_INT16(0);
 
80
        char       *result = (char *) palloc(7);        /* sign, 5 digits, '\0' */
 
81
 
 
82
        pg_itoa(arg1, result);
 
83
        PG_RETURN_CSTRING(result);
 
84
}
 
85
 
 
86
/*
 
87
 *              int2recv                        - converts external binary format to int2
 
88
 */
 
89
Datum
 
90
int2recv(PG_FUNCTION_ARGS)
 
91
{
 
92
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
93
 
 
94
        PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
 
95
}
 
96
 
 
97
/*
 
98
 *              int2send                        - converts int2 to binary format
 
99
 */
 
100
Datum
 
101
int2send(PG_FUNCTION_ARGS)
 
102
{
 
103
        int16           arg1 = PG_GETARG_INT16(0);
 
104
        StringInfoData buf;
 
105
 
 
106
        pq_begintypsend(&buf);
 
107
        pq_sendint(&buf, arg1, sizeof(int16));
 
108
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 
109
}
 
110
 
 
111
/*
 
112
 *              int2vectorin                    - converts "num num ..." to internal form
 
113
 *
 
114
 *              Note: Fills any missing slots with zeroes.
 
115
 */
 
116
Datum
 
117
int2vectorin(PG_FUNCTION_ARGS)
 
118
{
 
119
        char       *intString = PG_GETARG_CSTRING(0);
 
120
        int16      *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS]));
 
121
        int                     slot;
 
122
 
 
123
        for (slot = 0; *intString && slot < INDEX_MAX_KEYS; slot++)
 
124
        {
 
125
                if (sscanf(intString, "%hd", &result[slot]) != 1)
 
126
                        break;
 
127
                while (*intString && isspace((unsigned char) *intString))
 
128
                        intString++;
 
129
                while (*intString && !isspace((unsigned char) *intString))
 
130
                        intString++;
 
131
        }
 
132
        while (*intString && isspace((unsigned char) *intString))
 
133
                intString++;
 
134
        if (*intString)
 
135
                ereport(ERROR,
 
136
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
137
                                 errmsg("int2vector has too many elements")));
 
138
 
 
139
        while (slot < INDEX_MAX_KEYS)
 
140
                result[slot++] = 0;
 
141
 
 
142
        PG_RETURN_POINTER(result);
 
143
}
 
144
 
 
145
/*
 
146
 *              int2vectorout           - converts internal form to "num num ..."
 
147
 */
 
148
Datum
 
149
int2vectorout(PG_FUNCTION_ARGS)
 
150
{
 
151
        int16      *int2Array = (int16 *) PG_GETARG_POINTER(0);
 
152
        int                     num,
 
153
                                maxnum;
 
154
        char       *rp;
 
155
        char       *result;
 
156
 
 
157
        /* find last non-zero value in vector */
 
158
        for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
 
159
                if (int2Array[maxnum] != 0)
 
160
                        break;
 
161
 
 
162
        /* assumes sign, 5 digits, ' ' */
 
163
        rp = result = (char *) palloc((maxnum + 1) * 7 + 1);
 
164
        for (num = 0; num <= maxnum; num++)
 
165
        {
 
166
                if (num != 0)
 
167
                        *rp++ = ' ';
 
168
                pg_itoa(int2Array[num], rp);
 
169
                while (*++rp != '\0')
 
170
                        ;
 
171
        }
 
172
        *rp = '\0';
 
173
        PG_RETURN_CSTRING(result);
 
174
}
 
175
 
 
176
/*
 
177
 *              int2vectorrecv                  - converts external binary format to int2vector
 
178
 */
 
179
Datum
 
180
int2vectorrecv(PG_FUNCTION_ARGS)
 
181
{
 
182
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
183
        int16      *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS]));
 
184
        int                     slot;
 
185
 
 
186
        for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
 
187
                result[slot] = (int16) pq_getmsgint(buf, sizeof(int16));
 
188
        PG_RETURN_POINTER(result);
 
189
}
 
190
 
 
191
/*
 
192
 *              int2vectorsend                  - converts int2vector to binary format
 
193
 */
 
194
Datum
 
195
int2vectorsend(PG_FUNCTION_ARGS)
 
196
{
 
197
        int16      *int2Array = (int16 *) PG_GETARG_POINTER(0);
 
198
        StringInfoData buf;
 
199
        int                     slot;
 
200
 
 
201
        pq_begintypsend(&buf);
 
202
        for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
 
203
                pq_sendint(&buf, int2Array[slot], sizeof(int16));
 
204
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 
205
}
 
206
 
 
207
/*
 
208
 * We don't have a complete set of int2vector support routines,
 
209
 * but we need int2vectoreq for catcache indexing.
 
210
 */
 
211
Datum
 
212
int2vectoreq(PG_FUNCTION_ARGS)
 
213
{
 
214
        int16      *arg1 = (int16 *) PG_GETARG_POINTER(0);
 
215
        int16      *arg2 = (int16 *) PG_GETARG_POINTER(1);
 
216
 
 
217
        PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(int16)) == 0);
 
218
}
 
219
 
 
220
 
 
221
/*****************************************************************************
 
222
 *       PUBLIC ROUTINES                                                                                                                 *
 
223
 *****************************************************************************/
 
224
 
 
225
/*
 
226
 *              int4in                  - converts "num" to int4
 
227
 */
 
228
Datum
 
229
int4in(PG_FUNCTION_ARGS)
 
230
{
 
231
        char       *num = PG_GETARG_CSTRING(0);
 
232
 
 
233
        PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
 
234
}
 
235
 
 
236
/*
 
237
 *              int4out                 - converts int4 to "num"
 
238
 */
 
239
Datum
 
240
int4out(PG_FUNCTION_ARGS)
 
241
{
 
242
        int32           arg1 = PG_GETARG_INT32(0);
 
243
        char       *result = (char *) palloc(12);       /* sign, 10 digits, '\0' */
 
244
 
 
245
        pg_ltoa(arg1, result);
 
246
        PG_RETURN_CSTRING(result);
 
247
}
 
248
 
 
249
/*
 
250
 *              int4recv                        - converts external binary format to int4
 
251
 */
 
252
Datum
 
253
int4recv(PG_FUNCTION_ARGS)
 
254
{
 
255
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
256
 
 
257
        PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
 
258
}
 
259
 
 
260
/*
 
261
 *              int4send                        - converts int4 to binary format
 
262
 */
 
263
Datum
 
264
int4send(PG_FUNCTION_ARGS)
 
265
{
 
266
        int32           arg1 = PG_GETARG_INT32(0);
 
267
        StringInfoData buf;
 
268
 
 
269
        pq_begintypsend(&buf);
 
270
        pq_sendint(&buf, arg1, sizeof(int32));
 
271
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 
272
}
 
273
 
 
274
 
 
275
/*
 
276
 *              ===================
 
277
 *              CONVERSION ROUTINES
 
278
 *              ===================
 
279
 */
 
280
 
 
281
Datum
 
282
i2toi4(PG_FUNCTION_ARGS)
 
283
{
 
284
        int16           arg1 = PG_GETARG_INT16(0);
 
285
 
 
286
        PG_RETURN_INT32((int32) arg1);
 
287
}
 
288
 
 
289
Datum
 
290
i4toi2(PG_FUNCTION_ARGS)
 
291
{
 
292
        int32           arg1 = PG_GETARG_INT32(0);
 
293
 
 
294
        if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
 
295
                ereport(ERROR,
 
296
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
297
                                 errmsg("smallint out of range")));
 
298
 
 
299
        PG_RETURN_INT16((int16) arg1);
 
300
}
 
301
 
 
302
Datum
 
303
int2_text(PG_FUNCTION_ARGS)
 
304
{
 
305
        int16           arg1 = PG_GETARG_INT16(0);
 
306
        text       *result = (text *) palloc(7 + VARHDRSZ); /* sign,5 digits, '\0' */
 
307
 
 
308
        pg_itoa(arg1, VARDATA(result));
 
309
        VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
 
310
        PG_RETURN_TEXT_P(result);
 
311
}
 
312
 
 
313
Datum
 
314
text_int2(PG_FUNCTION_ARGS)
 
315
{
 
316
        text       *string = PG_GETARG_TEXT_P(0);
 
317
        Datum           result;
 
318
        int                     len;
 
319
        char       *str;
 
320
 
 
321
        len = VARSIZE(string) - VARHDRSZ;
 
322
 
 
323
        str = palloc(len + 1);
 
324
        memcpy(str, VARDATA(string), len);
 
325
        *(str + len) = '\0';
 
326
 
 
327
        result = DirectFunctionCall1(int2in, CStringGetDatum(str));
 
328
        pfree(str);
 
329
 
 
330
        return result;
 
331
}
 
332
 
 
333
Datum
 
334
int4_text(PG_FUNCTION_ARGS)
 
335
{
 
336
        int32           arg1 = PG_GETARG_INT32(0);
 
337
        text       *result = (text *) palloc(12 + VARHDRSZ);            /* sign,10 digits,'\0' */
 
338
 
 
339
        pg_ltoa(arg1, VARDATA(result));
 
340
        VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
 
341
        PG_RETURN_TEXT_P(result);
 
342
}
 
343
 
 
344
Datum
 
345
text_int4(PG_FUNCTION_ARGS)
 
346
{
 
347
        text       *string = PG_GETARG_TEXT_P(0);
 
348
        Datum           result;
 
349
        int                     len;
 
350
        char       *str;
 
351
 
 
352
        len = VARSIZE(string) - VARHDRSZ;
 
353
 
 
354
        str = palloc(len + 1);
 
355
        memcpy(str, VARDATA(string), len);
 
356
        *(str + len) = '\0';
 
357
 
 
358
        result = DirectFunctionCall1(int4in, CStringGetDatum(str));
 
359
        pfree(str);
 
360
 
 
361
        return result;
 
362
}
 
363
 
 
364
 
 
365
/*
 
366
 *              ============================
 
367
 *              COMPARISON OPERATOR ROUTINES
 
368
 *              ============================
 
369
 */
 
370
 
 
371
/*
 
372
 *              inteq                   - returns 1 iff arg1 == arg2
 
373
 *              intne                   - returns 1 iff arg1 != arg2
 
374
 *              intlt                   - returns 1 iff arg1 < arg2
 
375
 *              intle                   - returns 1 iff arg1 <= arg2
 
376
 *              intgt                   - returns 1 iff arg1 > arg2
 
377
 *              intge                   - returns 1 iff arg1 >= arg2
 
378
 */
 
379
 
 
380
Datum
 
381
int4eq(PG_FUNCTION_ARGS)
 
382
{
 
383
        int32           arg1 = PG_GETARG_INT32(0);
 
384
        int32           arg2 = PG_GETARG_INT32(1);
 
385
 
 
386
        PG_RETURN_BOOL(arg1 == arg2);
 
387
}
 
388
 
 
389
Datum
 
390
int4ne(PG_FUNCTION_ARGS)
 
391
{
 
392
        int32           arg1 = PG_GETARG_INT32(0);
 
393
        int32           arg2 = PG_GETARG_INT32(1);
 
394
 
 
395
        PG_RETURN_BOOL(arg1 != arg2);
 
396
}
 
397
 
 
398
Datum
 
399
int4lt(PG_FUNCTION_ARGS)
 
400
{
 
401
        int32           arg1 = PG_GETARG_INT32(0);
 
402
        int32           arg2 = PG_GETARG_INT32(1);
 
403
 
 
404
        PG_RETURN_BOOL(arg1 < arg2);
 
405
}
 
406
 
 
407
Datum
 
408
int4le(PG_FUNCTION_ARGS)
 
409
{
 
410
        int32           arg1 = PG_GETARG_INT32(0);
 
411
        int32           arg2 = PG_GETARG_INT32(1);
 
412
 
 
413
        PG_RETURN_BOOL(arg1 <= arg2);
 
414
}
 
415
 
 
416
Datum
 
417
int4gt(PG_FUNCTION_ARGS)
 
418
{
 
419
        int32           arg1 = PG_GETARG_INT32(0);
 
420
        int32           arg2 = PG_GETARG_INT32(1);
 
421
 
 
422
        PG_RETURN_BOOL(arg1 > arg2);
 
423
}
 
424
 
 
425
Datum
 
426
int4ge(PG_FUNCTION_ARGS)
 
427
{
 
428
        int32           arg1 = PG_GETARG_INT32(0);
 
429
        int32           arg2 = PG_GETARG_INT32(1);
 
430
 
 
431
        PG_RETURN_BOOL(arg1 >= arg2);
 
432
}
 
433
 
 
434
Datum
 
435
int2eq(PG_FUNCTION_ARGS)
 
436
{
 
437
        int16           arg1 = PG_GETARG_INT16(0);
 
438
        int16           arg2 = PG_GETARG_INT16(1);
 
439
 
 
440
        PG_RETURN_BOOL(arg1 == arg2);
 
441
}
 
442
 
 
443
Datum
 
444
int2ne(PG_FUNCTION_ARGS)
 
445
{
 
446
        int16           arg1 = PG_GETARG_INT16(0);
 
447
        int16           arg2 = PG_GETARG_INT16(1);
 
448
 
 
449
        PG_RETURN_BOOL(arg1 != arg2);
 
450
}
 
451
 
 
452
Datum
 
453
int2lt(PG_FUNCTION_ARGS)
 
454
{
 
455
        int16           arg1 = PG_GETARG_INT16(0);
 
456
        int16           arg2 = PG_GETARG_INT16(1);
 
457
 
 
458
        PG_RETURN_BOOL(arg1 < arg2);
 
459
}
 
460
 
 
461
Datum
 
462
int2le(PG_FUNCTION_ARGS)
 
463
{
 
464
        int16           arg1 = PG_GETARG_INT16(0);
 
465
        int16           arg2 = PG_GETARG_INT16(1);
 
466
 
 
467
        PG_RETURN_BOOL(arg1 <= arg2);
 
468
}
 
469
 
 
470
Datum
 
471
int2gt(PG_FUNCTION_ARGS)
 
472
{
 
473
        int16           arg1 = PG_GETARG_INT16(0);
 
474
        int16           arg2 = PG_GETARG_INT16(1);
 
475
 
 
476
        PG_RETURN_BOOL(arg1 > arg2);
 
477
}
 
478
 
 
479
Datum
 
480
int2ge(PG_FUNCTION_ARGS)
 
481
{
 
482
        int16           arg1 = PG_GETARG_INT16(0);
 
483
        int16           arg2 = PG_GETARG_INT16(1);
 
484
 
 
485
        PG_RETURN_BOOL(arg1 >= arg2);
 
486
}
 
487
 
 
488
Datum
 
489
int24eq(PG_FUNCTION_ARGS)
 
490
{
 
491
        int16           arg1 = PG_GETARG_INT16(0);
 
492
        int32           arg2 = PG_GETARG_INT32(1);
 
493
 
 
494
        PG_RETURN_BOOL(arg1 == arg2);
 
495
}
 
496
 
 
497
Datum
 
498
int24ne(PG_FUNCTION_ARGS)
 
499
{
 
500
        int16           arg1 = PG_GETARG_INT16(0);
 
501
        int32           arg2 = PG_GETARG_INT32(1);
 
502
 
 
503
        PG_RETURN_BOOL(arg1 != arg2);
 
504
}
 
505
 
 
506
Datum
 
507
int24lt(PG_FUNCTION_ARGS)
 
508
{
 
509
        int16           arg1 = PG_GETARG_INT16(0);
 
510
        int32           arg2 = PG_GETARG_INT32(1);
 
511
 
 
512
        PG_RETURN_BOOL(arg1 < arg2);
 
513
}
 
514
 
 
515
Datum
 
516
int24le(PG_FUNCTION_ARGS)
 
517
{
 
518
        int16           arg1 = PG_GETARG_INT16(0);
 
519
        int32           arg2 = PG_GETARG_INT32(1);
 
520
 
 
521
        PG_RETURN_BOOL(arg1 <= arg2);
 
522
}
 
523
 
 
524
Datum
 
525
int24gt(PG_FUNCTION_ARGS)
 
526
{
 
527
        int16           arg1 = PG_GETARG_INT16(0);
 
528
        int32           arg2 = PG_GETARG_INT32(1);
 
529
 
 
530
        PG_RETURN_BOOL(arg1 > arg2);
 
531
}
 
532
 
 
533
Datum
 
534
int24ge(PG_FUNCTION_ARGS)
 
535
{
 
536
        int16           arg1 = PG_GETARG_INT16(0);
 
537
        int32           arg2 = PG_GETARG_INT32(1);
 
538
 
 
539
        PG_RETURN_BOOL(arg1 >= arg2);
 
540
}
 
541
 
 
542
Datum
 
543
int42eq(PG_FUNCTION_ARGS)
 
544
{
 
545
        int32           arg1 = PG_GETARG_INT32(0);
 
546
        int16           arg2 = PG_GETARG_INT16(1);
 
547
 
 
548
        PG_RETURN_BOOL(arg1 == arg2);
 
549
}
 
550
 
 
551
Datum
 
552
int42ne(PG_FUNCTION_ARGS)
 
553
{
 
554
        int32           arg1 = PG_GETARG_INT32(0);
 
555
        int16           arg2 = PG_GETARG_INT16(1);
 
556
 
 
557
        PG_RETURN_BOOL(arg1 != arg2);
 
558
}
 
559
 
 
560
Datum
 
561
int42lt(PG_FUNCTION_ARGS)
 
562
{
 
563
        int32           arg1 = PG_GETARG_INT32(0);
 
564
        int16           arg2 = PG_GETARG_INT16(1);
 
565
 
 
566
        PG_RETURN_BOOL(arg1 < arg2);
 
567
}
 
568
 
 
569
Datum
 
570
int42le(PG_FUNCTION_ARGS)
 
571
{
 
572
        int32           arg1 = PG_GETARG_INT32(0);
 
573
        int16           arg2 = PG_GETARG_INT16(1);
 
574
 
 
575
        PG_RETURN_BOOL(arg1 <= arg2);
 
576
}
 
577
 
 
578
Datum
 
579
int42gt(PG_FUNCTION_ARGS)
 
580
{
 
581
        int32           arg1 = PG_GETARG_INT32(0);
 
582
        int16           arg2 = PG_GETARG_INT16(1);
 
583
 
 
584
        PG_RETURN_BOOL(arg1 > arg2);
 
585
}
 
586
 
 
587
Datum
 
588
int42ge(PG_FUNCTION_ARGS)
 
589
{
 
590
        int32           arg1 = PG_GETARG_INT32(0);
 
591
        int16           arg2 = PG_GETARG_INT16(1);
 
592
 
 
593
        PG_RETURN_BOOL(arg1 >= arg2);
 
594
}
 
595
 
 
596
/*
 
597
 *              int[24]pl               - returns arg1 + arg2
 
598
 *              int[24]mi               - returns arg1 - arg2
 
599
 *              int[24]mul              - returns arg1 * arg2
 
600
 *              int[24]div              - returns arg1 / arg2
 
601
 */
 
602
 
 
603
Datum
 
604
int4um(PG_FUNCTION_ARGS)
 
605
{
 
606
        int32           arg = PG_GETARG_INT32(0);
 
607
        int32           result;
 
608
 
 
609
        result = -arg;
 
610
        /* overflow check (needed for INT_MIN) */
 
611
        if (arg != 0 && SAMESIGN(result, arg))
 
612
                ereport(ERROR,
 
613
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
614
                                 errmsg("integer out of range")));
 
615
        PG_RETURN_INT32(result);
 
616
}
 
617
 
 
618
Datum
 
619
int4up(PG_FUNCTION_ARGS)
 
620
{
 
621
        int32           arg = PG_GETARG_INT32(0);
 
622
 
 
623
        PG_RETURN_INT32(arg);
 
624
}
 
625
 
 
626
Datum
 
627
int4pl(PG_FUNCTION_ARGS)
 
628
{
 
629
        int32           arg1 = PG_GETARG_INT32(0);
 
630
        int32           arg2 = PG_GETARG_INT32(1);
 
631
        int32           result;
 
632
 
 
633
        result = arg1 + arg2;
 
634
        /*
 
635
         * Overflow check.  If the inputs are of different signs then their sum
 
636
         * cannot overflow.  If the inputs are of the same sign, their sum
 
637
         * had better be that sign too.
 
638
         */
 
639
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
640
                ereport(ERROR,
 
641
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
642
                                 errmsg("integer out of range")));
 
643
        PG_RETURN_INT32(result);
 
644
}
 
645
 
 
646
Datum
 
647
int4mi(PG_FUNCTION_ARGS)
 
648
{
 
649
        int32           arg1 = PG_GETARG_INT32(0);
 
650
        int32           arg2 = PG_GETARG_INT32(1);
 
651
        int32           result;
 
652
 
 
653
        result = arg1 - arg2;
 
654
        /*
 
655
         * Overflow check.  If the inputs are of the same sign then their
 
656
         * difference cannot overflow.  If they are of different signs then
 
657
         * the result should be of the same sign as the first input.
 
658
         */
 
659
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
660
                ereport(ERROR,
 
661
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
662
                                 errmsg("integer out of range")));
 
663
        PG_RETURN_INT32(result);
 
664
}
 
665
 
 
666
Datum
 
667
int4mul(PG_FUNCTION_ARGS)
 
668
{
 
669
        int32           arg1 = PG_GETARG_INT32(0);
 
670
        int32           arg2 = PG_GETARG_INT32(1);
 
671
        int32           result;
 
672
 
 
673
        result = arg1 * arg2;
 
674
        /*
 
675
         * Overflow check.  We basically check to see if result / arg2 gives
 
676
         * arg1 again.  There are two cases where this fails: arg2 = 0 (which
 
677
         * cannot overflow) and arg1 = INT_MIN, arg2 = -1 (where the division
 
678
         * itself will overflow and thus incorrectly match).
 
679
         *
 
680
         * Since the division is likely much more expensive than the actual
 
681
         * multiplication, we'd like to skip it where possible.  The best
 
682
         * bang for the buck seems to be to check whether both inputs are in
 
683
         * the int16 range; if so, no overflow is possible.
 
684
         */
 
685
        if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
 
686
                  arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
 
687
                arg2 != 0 &&
 
688
                (result/arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
 
689
                ereport(ERROR,
 
690
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
691
                                 errmsg("integer out of range")));
 
692
        PG_RETURN_INT32(result);
 
693
}
 
694
 
 
695
Datum
 
696
int4div(PG_FUNCTION_ARGS)
 
697
{
 
698
        int32           arg1 = PG_GETARG_INT32(0);
 
699
        int32           arg2 = PG_GETARG_INT32(1);
 
700
        int32           result;
 
701
 
 
702
        if (arg2 == 0)
 
703
                ereport(ERROR,
 
704
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
705
                                 errmsg("division by zero")));
 
706
 
 
707
        result = arg1 / arg2;
 
708
        /*
 
709
         * Overflow check.  The only possible overflow case is for
 
710
         * arg1 = INT_MIN, arg2 = -1, where the correct result is -INT_MIN,
 
711
         * which can't be represented on a two's-complement machine.
 
712
         */
 
713
        if (arg2 == -1 && arg1 < 0 && result < 0)
 
714
                ereport(ERROR,
 
715
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
716
                                 errmsg("integer out of range")));
 
717
        PG_RETURN_INT32(result);
 
718
}
 
719
 
 
720
Datum
 
721
int4inc(PG_FUNCTION_ARGS)
 
722
{
 
723
        int32           arg = PG_GETARG_INT32(0);
 
724
        int32           result;
 
725
 
 
726
        result = arg + 1;
 
727
        /* Overflow check */
 
728
        if (arg > 0 && result < 0)
 
729
                ereport(ERROR,
 
730
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
731
                                 errmsg("integer out of range")));
 
732
 
 
733
        PG_RETURN_INT32(result);
 
734
}
 
735
 
 
736
Datum
 
737
int2um(PG_FUNCTION_ARGS)
 
738
{
 
739
        int16           arg = PG_GETARG_INT16(0);
 
740
        int16           result;
 
741
 
 
742
        result = -arg;
 
743
        /* overflow check (needed for SHRT_MIN) */
 
744
        if (arg != 0 && SAMESIGN(result, arg))
 
745
                ereport(ERROR,
 
746
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
747
                                 errmsg("smallint out of range")));
 
748
        PG_RETURN_INT16(result);
 
749
}
 
750
 
 
751
Datum
 
752
int2up(PG_FUNCTION_ARGS)
 
753
{
 
754
        int16           arg = PG_GETARG_INT16(0);
 
755
 
 
756
        PG_RETURN_INT16(arg);
 
757
}
 
758
 
 
759
Datum
 
760
int2pl(PG_FUNCTION_ARGS)
 
761
{
 
762
        int16           arg1 = PG_GETARG_INT16(0);
 
763
        int16           arg2 = PG_GETARG_INT16(1);
 
764
        int16           result;
 
765
 
 
766
        result = arg1 + arg2;
 
767
        /*
 
768
         * Overflow check.  If the inputs are of different signs then their sum
 
769
         * cannot overflow.  If the inputs are of the same sign, their sum
 
770
         * had better be that sign too.
 
771
         */
 
772
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
773
                ereport(ERROR,
 
774
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
775
                                 errmsg("smallint out of range")));
 
776
        PG_RETURN_INT16(result);
 
777
}
 
778
 
 
779
Datum
 
780
int2mi(PG_FUNCTION_ARGS)
 
781
{
 
782
        int16           arg1 = PG_GETARG_INT16(0);
 
783
        int16           arg2 = PG_GETARG_INT16(1);
 
784
        int16           result;
 
785
 
 
786
        result = arg1 - arg2;
 
787
        /*
 
788
         * Overflow check.  If the inputs are of the same sign then their
 
789
         * difference cannot overflow.  If they are of different signs then
 
790
         * the result should be of the same sign as the first input.
 
791
         */
 
792
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
793
                ereport(ERROR,
 
794
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
795
                                 errmsg("smallint out of range")));
 
796
        PG_RETURN_INT16(result);
 
797
}
 
798
 
 
799
Datum
 
800
int2mul(PG_FUNCTION_ARGS)
 
801
{
 
802
        int16           arg1 = PG_GETARG_INT16(0);
 
803
        int16           arg2 = PG_GETARG_INT16(1);
 
804
        int32           result32;
 
805
 
 
806
        /*
 
807
         * The most practical way to detect overflow is to do the arithmetic
 
808
         * in int32 (so that the result can't overflow) and then do a range
 
809
         * check.
 
810
         */
 
811
        result32 = (int32) arg1 * (int32) arg2;
 
812
        if (result32 < SHRT_MIN || result32 > SHRT_MAX)
 
813
                ereport(ERROR,
 
814
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
815
                                 errmsg("smallint out of range")));
 
816
 
 
817
        PG_RETURN_INT16((int16) result32);
 
818
}
 
819
 
 
820
Datum
 
821
int2div(PG_FUNCTION_ARGS)
 
822
{
 
823
        int16           arg1 = PG_GETARG_INT16(0);
 
824
        int16           arg2 = PG_GETARG_INT16(1);
 
825
        int16           result;
 
826
 
 
827
        if (arg2 == 0)
 
828
                ereport(ERROR,
 
829
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
830
                                 errmsg("division by zero")));
 
831
 
 
832
        result = arg1 / arg2;
 
833
        /*
 
834
         * Overflow check.  The only possible overflow case is for
 
835
         * arg1 = SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN,
 
836
         * which can't be represented on a two's-complement machine.
 
837
         */
 
838
        if (arg2 == -1 && arg1 < 0 && result < 0)
 
839
                ereport(ERROR,
 
840
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
841
                                 errmsg("smallint out of range")));
 
842
        PG_RETURN_INT16(result);
 
843
}
 
844
 
 
845
Datum
 
846
int24pl(PG_FUNCTION_ARGS)
 
847
{
 
848
        int16           arg1 = PG_GETARG_INT16(0);
 
849
        int32           arg2 = PG_GETARG_INT32(1);
 
850
        int32           result;
 
851
 
 
852
        result = arg1 + arg2;
 
853
        /*
 
854
         * Overflow check.  If the inputs are of different signs then their sum
 
855
         * cannot overflow.  If the inputs are of the same sign, their sum
 
856
         * had better be that sign too.
 
857
         */
 
858
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
859
                ereport(ERROR,
 
860
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
861
                                 errmsg("integer out of range")));
 
862
        PG_RETURN_INT32(result);
 
863
}
 
864
 
 
865
Datum
 
866
int24mi(PG_FUNCTION_ARGS)
 
867
{
 
868
        int16           arg1 = PG_GETARG_INT16(0);
 
869
        int32           arg2 = PG_GETARG_INT32(1);
 
870
        int32           result;
 
871
 
 
872
        result = arg1 - arg2;
 
873
        /*
 
874
         * Overflow check.  If the inputs are of the same sign then their
 
875
         * difference cannot overflow.  If they are of different signs then
 
876
         * the result should be of the same sign as the first input.
 
877
         */
 
878
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
879
                ereport(ERROR,
 
880
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
881
                                 errmsg("integer out of range")));
 
882
        PG_RETURN_INT32(result);
 
883
}
 
884
 
 
885
Datum
 
886
int24mul(PG_FUNCTION_ARGS)
 
887
{
 
888
        int16           arg1 = PG_GETARG_INT16(0);
 
889
        int32           arg2 = PG_GETARG_INT32(1);
 
890
        int32           result;
 
891
 
 
892
        result = arg1 * arg2;
 
893
        /*
 
894
         * Overflow check.  We basically check to see if result / arg2 gives
 
895
         * arg1 again.  There is one case where this fails: arg2 = 0 (which
 
896
         * cannot overflow).
 
897
         *
 
898
         * Since the division is likely much more expensive than the actual
 
899
         * multiplication, we'd like to skip it where possible.  The best
 
900
         * bang for the buck seems to be to check whether both inputs are in
 
901
         * the int16 range; if so, no overflow is possible.
 
902
         */
 
903
        if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
 
904
                result/arg2 != arg1)
 
905
                ereport(ERROR,
 
906
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
907
                                 errmsg("integer out of range")));
 
908
        PG_RETURN_INT32(result);
 
909
}
 
910
 
 
911
Datum
 
912
int24div(PG_FUNCTION_ARGS)
 
913
{
 
914
        int16           arg1 = PG_GETARG_INT16(0);
 
915
        int32           arg2 = PG_GETARG_INT32(1);
 
916
 
 
917
        if (arg2 == 0)
 
918
                ereport(ERROR,
 
919
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
920
                                 errmsg("division by zero")));
 
921
        /* No overflow is possible */
 
922
        PG_RETURN_INT32((int32) arg1 / arg2);
 
923
}
 
924
 
 
925
Datum
 
926
int42pl(PG_FUNCTION_ARGS)
 
927
{
 
928
        int32           arg1 = PG_GETARG_INT32(0);
 
929
        int16           arg2 = PG_GETARG_INT16(1);
 
930
        int32           result;
 
931
 
 
932
        result = arg1 + arg2;
 
933
        /*
 
934
         * Overflow check.  If the inputs are of different signs then their sum
 
935
         * cannot overflow.  If the inputs are of the same sign, their sum
 
936
         * had better be that sign too.
 
937
         */
 
938
        if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
939
                ereport(ERROR,
 
940
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
941
                                 errmsg("integer out of range")));
 
942
        PG_RETURN_INT32(result);
 
943
}
 
944
 
 
945
Datum
 
946
int42mi(PG_FUNCTION_ARGS)
 
947
{
 
948
        int32           arg1 = PG_GETARG_INT32(0);
 
949
        int16           arg2 = PG_GETARG_INT16(1);
 
950
        int32           result;
 
951
 
 
952
        result = arg1 - arg2;
 
953
        /*
 
954
         * Overflow check.  If the inputs are of the same sign then their
 
955
         * difference cannot overflow.  If they are of different signs then
 
956
         * the result should be of the same sign as the first input.
 
957
         */
 
958
        if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
 
959
                ereport(ERROR,
 
960
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
961
                                 errmsg("integer out of range")));
 
962
        PG_RETURN_INT32(result);
 
963
}
 
964
 
 
965
Datum
 
966
int42mul(PG_FUNCTION_ARGS)
 
967
{
 
968
        int32           arg1 = PG_GETARG_INT32(0);
 
969
        int16           arg2 = PG_GETARG_INT16(1);
 
970
        int32           result;
 
971
 
 
972
        result = arg1 * arg2;
 
973
        /*
 
974
         * Overflow check.  We basically check to see if result / arg1 gives
 
975
         * arg2 again.  There is one case where this fails: arg1 = 0 (which
 
976
         * cannot overflow).
 
977
         *
 
978
         * Since the division is likely much more expensive than the actual
 
979
         * multiplication, we'd like to skip it where possible.  The best
 
980
         * bang for the buck seems to be to check whether both inputs are in
 
981
         * the int16 range; if so, no overflow is possible.
 
982
         */
 
983
        if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
 
984
                result/arg1 != arg2)
 
985
                ereport(ERROR,
 
986
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
987
                                 errmsg("integer out of range")));
 
988
        PG_RETURN_INT32(result);
 
989
}
 
990
 
 
991
Datum
 
992
int42div(PG_FUNCTION_ARGS)
 
993
{
 
994
        int32           arg1 = PG_GETARG_INT32(0);
 
995
        int16           arg2 = PG_GETARG_INT16(1);
 
996
        int32           result;
 
997
 
 
998
        if (arg2 == 0)
 
999
                ereport(ERROR,
 
1000
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
1001
                                 errmsg("division by zero")));
 
1002
 
 
1003
        result = arg1 / arg2;
 
1004
        /*
 
1005
         * Overflow check.  The only possible overflow case is for
 
1006
         * arg1 = INT_MIN, arg2 = -1, where the correct result is -INT_MIN,
 
1007
         * which can't be represented on a two's-complement machine.
 
1008
         */
 
1009
        if (arg2 == -1 && arg1 < 0 && result < 0)
 
1010
                ereport(ERROR,
 
1011
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1012
                                 errmsg("integer out of range")));
 
1013
        PG_RETURN_INT32(result);
 
1014
}
 
1015
 
 
1016
Datum
 
1017
int4mod(PG_FUNCTION_ARGS)
 
1018
{
 
1019
        int32           arg1 = PG_GETARG_INT32(0);
 
1020
        int32           arg2 = PG_GETARG_INT32(1);
 
1021
 
 
1022
        if (arg2 == 0)
 
1023
                ereport(ERROR,
 
1024
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
1025
                                 errmsg("division by zero")));
 
1026
        /* No overflow is possible */
 
1027
 
 
1028
        PG_RETURN_INT32(arg1 % arg2);
 
1029
}
 
1030
 
 
1031
Datum
 
1032
int2mod(PG_FUNCTION_ARGS)
 
1033
{
 
1034
        int16           arg1 = PG_GETARG_INT16(0);
 
1035
        int16           arg2 = PG_GETARG_INT16(1);
 
1036
 
 
1037
        if (arg2 == 0)
 
1038
                ereport(ERROR,
 
1039
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
1040
                                 errmsg("division by zero")));
 
1041
        /* No overflow is possible */
 
1042
 
 
1043
        PG_RETURN_INT16(arg1 % arg2);
 
1044
}
 
1045
 
 
1046
Datum
 
1047
int24mod(PG_FUNCTION_ARGS)
 
1048
{
 
1049
        int16           arg1 = PG_GETARG_INT16(0);
 
1050
        int32           arg2 = PG_GETARG_INT32(1);
 
1051
 
 
1052
        if (arg2 == 0)
 
1053
                ereport(ERROR,
 
1054
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
1055
                                 errmsg("division by zero")));
 
1056
        /* No overflow is possible */
 
1057
 
 
1058
        PG_RETURN_INT32(arg1 % arg2);
 
1059
}
 
1060
 
 
1061
Datum
 
1062
int42mod(PG_FUNCTION_ARGS)
 
1063
{
 
1064
        int32           arg1 = PG_GETARG_INT32(0);
 
1065
        int16           arg2 = PG_GETARG_INT16(1);
 
1066
 
 
1067
        if (arg2 == 0)
 
1068
                ereport(ERROR,
 
1069
                                (errcode(ERRCODE_DIVISION_BY_ZERO),
 
1070
                                 errmsg("division by zero")));
 
1071
        /* No overflow is possible */
 
1072
 
 
1073
        PG_RETURN_INT32(arg1 % arg2);
 
1074
}
 
1075
 
 
1076
 
 
1077
/* int[24]abs()
 
1078
 * Absolute value
 
1079
 */
 
1080
Datum
 
1081
int4abs(PG_FUNCTION_ARGS)
 
1082
{
 
1083
        int32           arg1 = PG_GETARG_INT32(0);
 
1084
        int32           result;
 
1085
 
 
1086
        result = (arg1 < 0) ? -arg1 : arg1;
 
1087
        /* overflow check (needed for INT_MIN) */
 
1088
        if (result < 0)
 
1089
                ereport(ERROR,
 
1090
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1091
                                 errmsg("integer out of range")));
 
1092
        PG_RETURN_INT32(result);
 
1093
}
 
1094
 
 
1095
Datum
 
1096
int2abs(PG_FUNCTION_ARGS)
 
1097
{
 
1098
        int16           arg1 = PG_GETARG_INT16(0);
 
1099
        int16           result;
 
1100
 
 
1101
        result = (arg1 < 0) ? -arg1 : arg1;
 
1102
        /* overflow check (needed for SHRT_MIN) */
 
1103
        if (result < 0)
 
1104
                ereport(ERROR,
 
1105
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1106
                                 errmsg("smallint out of range")));
 
1107
        PG_RETURN_INT16(result);
 
1108
}
 
1109
 
 
1110
Datum
 
1111
int2larger(PG_FUNCTION_ARGS)
 
1112
{
 
1113
        int16           arg1 = PG_GETARG_INT16(0);
 
1114
        int16           arg2 = PG_GETARG_INT16(1);
 
1115
 
 
1116
        PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
 
1117
}
 
1118
 
 
1119
Datum
 
1120
int2smaller(PG_FUNCTION_ARGS)
 
1121
{
 
1122
        int16           arg1 = PG_GETARG_INT16(0);
 
1123
        int16           arg2 = PG_GETARG_INT16(1);
 
1124
 
 
1125
        PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
 
1126
}
 
1127
 
 
1128
Datum
 
1129
int4larger(PG_FUNCTION_ARGS)
 
1130
{
 
1131
        int32           arg1 = PG_GETARG_INT32(0);
 
1132
        int32           arg2 = PG_GETARG_INT32(1);
 
1133
 
 
1134
        PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
 
1135
}
 
1136
 
 
1137
Datum
 
1138
int4smaller(PG_FUNCTION_ARGS)
 
1139
{
 
1140
        int32           arg1 = PG_GETARG_INT32(0);
 
1141
        int32           arg2 = PG_GETARG_INT32(1);
 
1142
 
 
1143
        PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
 
1144
}
 
1145
 
 
1146
/*
 
1147
 * Bit-pushing operators
 
1148
 *
 
1149
 *              int[24]and              - returns arg1 & arg2
 
1150
 *              int[24]or               - returns arg1 | arg2
 
1151
 *              int[24]xor              - returns arg1 # arg2
 
1152
 *              int[24]not              - returns ~arg1
 
1153
 *              int[24]shl              - returns arg1 << arg2
 
1154
 *              int[24]shr              - returns arg1 >> arg2
 
1155
 */
 
1156
 
 
1157
Datum
 
1158
int4and(PG_FUNCTION_ARGS)
 
1159
{
 
1160
        int32           arg1 = PG_GETARG_INT32(0);
 
1161
        int32           arg2 = PG_GETARG_INT32(1);
 
1162
 
 
1163
        PG_RETURN_INT32(arg1 & arg2);
 
1164
}
 
1165
 
 
1166
Datum
 
1167
int4or(PG_FUNCTION_ARGS)
 
1168
{
 
1169
        int32           arg1 = PG_GETARG_INT32(0);
 
1170
        int32           arg2 = PG_GETARG_INT32(1);
 
1171
 
 
1172
        PG_RETURN_INT32(arg1 | arg2);
 
1173
}
 
1174
 
 
1175
Datum
 
1176
int4xor(PG_FUNCTION_ARGS)
 
1177
{
 
1178
        int32           arg1 = PG_GETARG_INT32(0);
 
1179
        int32           arg2 = PG_GETARG_INT32(1);
 
1180
 
 
1181
        PG_RETURN_INT32(arg1 ^ arg2);
 
1182
}
 
1183
 
 
1184
Datum
 
1185
int4shl(PG_FUNCTION_ARGS)
 
1186
{
 
1187
        int32           arg1 = PG_GETARG_INT32(0);
 
1188
        int32           arg2 = PG_GETARG_INT32(1);
 
1189
 
 
1190
        PG_RETURN_INT32(arg1 << arg2);
 
1191
}
 
1192
 
 
1193
Datum
 
1194
int4shr(PG_FUNCTION_ARGS)
 
1195
{
 
1196
        int32           arg1 = PG_GETARG_INT32(0);
 
1197
        int32           arg2 = PG_GETARG_INT32(1);
 
1198
 
 
1199
        PG_RETURN_INT32(arg1 >> arg2);
 
1200
}
 
1201
 
 
1202
Datum
 
1203
int4not(PG_FUNCTION_ARGS)
 
1204
{
 
1205
        int32           arg1 = PG_GETARG_INT32(0);
 
1206
 
 
1207
        PG_RETURN_INT32(~arg1);
 
1208
}
 
1209
 
 
1210
Datum
 
1211
int2and(PG_FUNCTION_ARGS)
 
1212
{
 
1213
        int16           arg1 = PG_GETARG_INT16(0);
 
1214
        int16           arg2 = PG_GETARG_INT16(1);
 
1215
 
 
1216
        PG_RETURN_INT16(arg1 & arg2);
 
1217
}
 
1218
 
 
1219
Datum
 
1220
int2or(PG_FUNCTION_ARGS)
 
1221
{
 
1222
        int16           arg1 = PG_GETARG_INT16(0);
 
1223
        int16           arg2 = PG_GETARG_INT16(1);
 
1224
 
 
1225
        PG_RETURN_INT16(arg1 | arg2);
 
1226
}
 
1227
 
 
1228
Datum
 
1229
int2xor(PG_FUNCTION_ARGS)
 
1230
{
 
1231
        int16           arg1 = PG_GETARG_INT16(0);
 
1232
        int16           arg2 = PG_GETARG_INT16(1);
 
1233
 
 
1234
        PG_RETURN_INT16(arg1 ^ arg2);
 
1235
}
 
1236
 
 
1237
Datum
 
1238
int2not(PG_FUNCTION_ARGS)
 
1239
{
 
1240
        int16           arg1 = PG_GETARG_INT16(0);
 
1241
 
 
1242
        PG_RETURN_INT16(~arg1);
 
1243
}
 
1244
 
 
1245
 
 
1246
Datum
 
1247
int2shl(PG_FUNCTION_ARGS)
 
1248
{
 
1249
        int16           arg1 = PG_GETARG_INT16(0);
 
1250
        int32           arg2 = PG_GETARG_INT32(1);
 
1251
 
 
1252
        PG_RETURN_INT16(arg1 << arg2);
 
1253
}
 
1254
 
 
1255
Datum
 
1256
int2shr(PG_FUNCTION_ARGS)
 
1257
{
 
1258
        int16           arg1 = PG_GETARG_INT16(0);
 
1259
        int32           arg2 = PG_GETARG_INT32(1);
 
1260
 
 
1261
        PG_RETURN_INT16(arg1 >> arg2);
 
1262
}
 
1263
 
 
1264
/*
 
1265
 * non-persistent numeric series generator
 
1266
 */
 
1267
Datum
 
1268
generate_series_int4(PG_FUNCTION_ARGS)
 
1269
{
 
1270
        return generate_series_step_int4(fcinfo);
 
1271
}
 
1272
 
 
1273
Datum
 
1274
generate_series_step_int4(PG_FUNCTION_ARGS)
 
1275
{
 
1276
        FuncCallContext *funcctx;
 
1277
        generate_series_fctx *fctx;
 
1278
        int32           result;
 
1279
        MemoryContext oldcontext;
 
1280
 
 
1281
        /* stuff done only on the first call of the function */
 
1282
        if (SRF_IS_FIRSTCALL())
 
1283
        {
 
1284
                int32           start = PG_GETARG_INT32(0);
 
1285
                int32           finish = PG_GETARG_INT32(1);
 
1286
                int32           step = 1;
 
1287
 
 
1288
                /* see if we were given an explicit step size */
 
1289
                if (PG_NARGS() == 3)
 
1290
                        step = PG_GETARG_INT32(2);
 
1291
                if (step == 0)
 
1292
                        ereport(ERROR,
 
1293
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
1294
                                         errmsg("step size may not equal zero")));
 
1295
 
 
1296
                /* create a function context for cross-call persistence */
 
1297
                funcctx = SRF_FIRSTCALL_INIT();
 
1298
 
 
1299
                /*
 
1300
                 * switch to memory context appropriate for multiple function
 
1301
                 * calls
 
1302
                 */
 
1303
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
1304
 
 
1305
                /* allocate memory for user context */
 
1306
                fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
 
1307
 
 
1308
                /*
 
1309
                 * Use fctx to keep state from call to call. Seed current with the
 
1310
                 * original start value
 
1311
                 */
 
1312
                fctx->current = start;
 
1313
                fctx->finish = finish;
 
1314
                fctx->step = step;
 
1315
 
 
1316
                funcctx->user_fctx = fctx;
 
1317
                MemoryContextSwitchTo(oldcontext);
 
1318
        }
 
1319
 
 
1320
        /* stuff done on every call of the function */
 
1321
        funcctx = SRF_PERCALL_SETUP();
 
1322
 
 
1323
        /*
 
1324
         * get the saved state and use current as the result for this
 
1325
         * iteration
 
1326
         */
 
1327
        fctx = funcctx->user_fctx;
 
1328
        result = fctx->current;
 
1329
 
 
1330
        if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
 
1331
                (fctx->step < 0 && fctx->current >= fctx->finish))
 
1332
        {
 
1333
                /* increment current in preparation for next iteration */
 
1334
                fctx->current += fctx->step;
 
1335
 
 
1336
                /* do when there is more left to send */
 
1337
                SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
 
1338
        }
 
1339
        else
 
1340
                /* do when there is no more left */
 
1341
                SRF_RETURN_DONE(funcctx);
 
1342
}