1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* int.c
|
2000-06-05 09:29:25 +02:00
|
|
|
* Functions for the built-in integer types (except int8).
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2016-01-02 19:33:40 +01:00
|
|
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/utils/adt/int.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* OLD COMMENTS
|
1997-09-07 07:04:48 +02:00
|
|
|
* I/O routines:
|
2003-05-09 17:44:42 +02:00
|
|
|
* int2in, int2out, int2recv, int2send
|
|
|
|
* int4in, int4out, int4recv, int4send
|
|
|
|
* int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
|
1997-09-07 07:04:48 +02:00
|
|
|
* Boolean operators:
|
|
|
|
* inteq, intne, intlt, intle, intgt, intge
|
|
|
|
* Arithmetic operators:
|
|
|
|
* intpl, intmi, int4mul, intdiv
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Arithmetic operators:
|
2003-12-01 22:52:38 +01:00
|
|
|
* intmod
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "postgres.h"
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2000-07-13 00:59:15 +02:00
|
|
|
#include <ctype.h>
|
1997-11-17 17:24:17 +01:00
|
|
|
#include <limits.h>
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2005-03-29 02:17:27 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2004-02-03 09:29:57 +01:00
|
|
|
#include "funcapi.h"
|
2003-05-09 17:44:42 +02:00
|
|
|
#include "libpq/pqformat.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "utils/array.h"
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "utils/builtins.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
|
|
|
|
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
|
|
|
|
|
2012-06-25 00:51:46 +02:00
|
|
|
#define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16))
|
2005-03-29 02:17:27 +02:00
|
|
|
|
2004-02-03 09:29:57 +01:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int32 current;
|
|
|
|
int32 finish;
|
|
|
|
int32 step;
|
2004-08-29 07:07:03 +02:00
|
|
|
} generate_series_fctx;
|
2004-02-03 09:29:57 +01:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* USER I/O ROUTINES *
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* int2in - converts "num" to short
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2in(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
char *num = PG_GETARG_CSTRING(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* int2out - converts short to "num"
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2out(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
2001-03-22 05:01:46 +01:00
|
|
|
char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-08-01 20:29:35 +02:00
|
|
|
pg_itoa(arg1, result);
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-09 17:44:42 +02:00
|
|
|
/*
|
|
|
|
* int2recv - converts external binary format to int2
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
int2recv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* int2send - converts int2 to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
int2send(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
StringInfoData buf;
|
|
|
|
|
|
|
|
pq_begintypsend(&buf);
|
|
|
|
pq_sendint(&buf, arg1, sizeof(int16));
|
|
|
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2005-03-29 02:17:27 +02:00
|
|
|
* construct int2vector given a raw array of int2s
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2005-03-29 02:17:27 +02:00
|
|
|
* If int2s is NULL then caller must fill values[] afterward
|
|
|
|
*/
|
|
|
|
int2vector *
|
2012-06-25 00:51:46 +02:00
|
|
|
buildint2vector(const int16 *int2s, int n)
|
2005-03-29 02:17:27 +02:00
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
int2vector *result;
|
2005-03-29 02:17:27 +02:00
|
|
|
|
|
|
|
result = (int2vector *) palloc0(Int2VectorSize(n));
|
|
|
|
|
|
|
|
if (n > 0 && int2s)
|
2012-06-25 00:51:46 +02:00
|
|
|
memcpy(result->values, int2s, n * sizeof(int16));
|
2005-03-29 02:17:27 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Attach standard array header. For historical reasons, we set the index
|
|
|
|
* lower bound to 0 not 1.
|
2005-03-29 02:17:27 +02:00
|
|
|
*/
|
2007-02-28 00:48:10 +01:00
|
|
|
SET_VARSIZE(result, Int2VectorSize(n));
|
2005-03-29 02:17:27 +02:00
|
|
|
result->ndim = 1;
|
2005-11-17 23:14:56 +01:00
|
|
|
result->dataoffset = 0; /* never any nulls */
|
2005-03-29 02:17:27 +02:00
|
|
|
result->elemtype = INT2OID;
|
|
|
|
result->dim1 = n;
|
|
|
|
result->lbound1 = 0;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* int2vectorin - converts "num num ..." to internal form
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2vectorin(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
char *intString = PG_GETARG_CSTRING(0);
|
2005-03-29 02:17:27 +02:00
|
|
|
int2vector *result;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2005-03-29 02:17:27 +02:00
|
|
|
for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-12-03 21:45:40 +01:00
|
|
|
while (*intString && isspace((unsigned char) *intString))
|
2000-01-10 16:41:34 +01:00
|
|
|
intString++;
|
2009-12-30 02:29:22 +01:00
|
|
|
if (*intString == '\0')
|
2010-02-26 03:01:40 +01:00
|
|
|
break;
|
2009-12-30 02:29:22 +01:00
|
|
|
result->values[n] = pg_atoi(intString, sizeof(int16), ' ');
|
2000-12-03 21:45:40 +01:00
|
|
|
while (*intString && !isspace((unsigned char) *intString))
|
2000-01-10 06:20:26 +01:00
|
|
|
intString++;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2000-12-03 21:45:40 +01:00
|
|
|
while (*intString && isspace((unsigned char) *intString))
|
2000-01-10 16:41:34 +01:00
|
|
|
intString++;
|
|
|
|
if (*intString)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("int2vector has too many elements")));
|
|
|
|
|
2007-02-28 00:48:10 +01:00
|
|
|
SET_VARSIZE(result, Int2VectorSize(n));
|
2005-03-29 02:17:27 +02:00
|
|
|
result->ndim = 1;
|
2005-11-17 23:14:56 +01:00
|
|
|
result->dataoffset = 0; /* never any nulls */
|
2005-03-29 02:17:27 +02:00
|
|
|
result->elemtype = INT2OID;
|
|
|
|
result->dim1 = n;
|
|
|
|
result->lbound1 = 0;
|
2000-01-10 06:20:26 +01:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_POINTER(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-01-10 17:13:23 +01:00
|
|
|
* int2vectorout - converts internal form to "num num ..."
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2vectorout(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2005-03-29 02:17:27 +02:00
|
|
|
int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
|
2000-04-12 19:17:23 +02:00
|
|
|
int num,
|
2005-03-29 02:17:27 +02:00
|
|
|
nnums = int2Array->dim1;
|
1998-02-26 05:46:47 +01:00
|
|
|
char *rp;
|
1997-09-08 04:41:22 +02:00
|
|
|
char *result;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-01-10 16:41:34 +01:00
|
|
|
/* assumes sign, 5 digits, ' ' */
|
2005-03-29 02:17:27 +02:00
|
|
|
rp = result = (char *) palloc(nnums * 7 + 1);
|
|
|
|
for (num = 0; num < nnums; num++)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-01-10 16:41:34 +01:00
|
|
|
if (num != 0)
|
|
|
|
*rp++ = ' ';
|
2005-03-29 02:17:27 +02:00
|
|
|
pg_itoa(int2Array->values[num], rp);
|
1997-09-07 07:04:48 +02:00
|
|
|
while (*++rp != '\0')
|
|
|
|
;
|
|
|
|
}
|
2000-01-10 16:41:34 +01:00
|
|
|
*rp = '\0';
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-09 17:44:42 +02:00
|
|
|
/*
|
|
|
|
* int2vectorrecv - converts external binary format to int2vector
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
int2vectorrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
2006-03-02 22:13:04 +01:00
|
|
|
FunctionCallInfoData locfcinfo;
|
2005-10-15 04:49:52 +02:00
|
|
|
int2vector *result;
|
2003-05-09 17:44:42 +02:00
|
|
|
|
2006-03-02 22:13:04 +01:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Normally one would call array_recv() using DirectFunctionCall3, but
|
|
|
|
* that does not work since array_recv wants to cache some data using
|
|
|
|
* fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
|
|
|
|
* parameter.
|
2006-03-02 22:13:04 +01:00
|
|
|
*/
|
2011-04-13 01:19:24 +02:00
|
|
|
InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
|
|
|
|
InvalidOid, NULL, NULL);
|
2006-03-02 22:13:04 +01:00
|
|
|
|
|
|
|
locfcinfo.arg[0] = PointerGetDatum(buf);
|
|
|
|
locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
|
|
|
|
locfcinfo.arg[2] = Int32GetDatum(-1);
|
|
|
|
locfcinfo.argnull[0] = false;
|
|
|
|
locfcinfo.argnull[1] = false;
|
|
|
|
locfcinfo.argnull[2] = false;
|
|
|
|
|
|
|
|
result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
|
|
|
|
|
|
|
|
Assert(!locfcinfo.isnull);
|
|
|
|
|
2009-09-04 13:20:23 +02:00
|
|
|
/* sanity checks: int2vector must be 1-D, 0-based, no nulls */
|
2005-11-17 23:14:56 +01:00
|
|
|
if (ARR_NDIM(result) != 1 ||
|
|
|
|
ARR_HASNULL(result) ||
|
2009-09-04 13:20:23 +02:00
|
|
|
ARR_ELEMTYPE(result) != INT2OID ||
|
|
|
|
ARR_LBOUND(result)[0] != 0)
|
2005-03-29 02:17:27 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
|
|
|
errmsg("invalid int2vector data")));
|
2009-09-04 13:20:23 +02:00
|
|
|
|
|
|
|
/* check length for consistency with int2vectorin() */
|
|
|
|
if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("oidvector has too many elements")));
|
|
|
|
|
2003-05-09 17:44:42 +02:00
|
|
|
PG_RETURN_POINTER(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* int2vectorsend - converts int2vector to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
int2vectorsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2005-03-29 02:17:27 +02:00
|
|
|
return array_send(fcinfo);
|
2003-05-09 17:44:42 +02:00
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* PUBLIC ROUTINES *
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* int4in - converts "num" to int4
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4in(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
char *num = PG_GETARG_CSTRING(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* int4out - converts int4 to "num"
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4out(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
2001-03-22 05:01:46 +01:00
|
|
|
char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-08-01 20:29:35 +02:00
|
|
|
pg_ltoa(arg1, result);
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-09 17:44:42 +02:00
|
|
|
/*
|
|
|
|
* int4recv - converts external binary format to int4
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
int4recv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* int4send - converts int4 to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
int4send(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
StringInfoData buf;
|
|
|
|
|
|
|
|
pq_begintypsend(&buf);
|
|
|
|
pq_sendint(&buf, arg1, sizeof(int32));
|
|
|
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* ===================
|
|
|
|
* CONVERSION ROUTINES
|
|
|
|
* ===================
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
i2toi4(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32((int32) arg1);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
i4toi2(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
|
2003-07-27 06:53:12 +02:00
|
|
|
if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
2004-10-04 16:42:48 +02:00
|
|
|
errmsg("smallint out of range")));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_INT16((int16) arg1);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2005-02-27 09:31:30 +01:00
|
|
|
/* Cast int4 -> bool */
|
|
|
|
Datum
|
|
|
|
int4_bool(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
if (PG_GETARG_INT32(0) == 0)
|
|
|
|
PG_RETURN_BOOL(false);
|
|
|
|
else
|
|
|
|
PG_RETURN_BOOL(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cast bool -> int4 */
|
|
|
|
Datum
|
|
|
|
bool_int4(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
if (PG_GETARG_BOOL(0) == false)
|
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
else
|
|
|
|
PG_RETURN_INT32(1);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
2000-06-05 09:29:25 +02:00
|
|
|
* ============================
|
|
|
|
* COMPARISON OPERATOR ROUTINES
|
|
|
|
* ============================
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* inteq - returns 1 iff arg1 == arg2
|
|
|
|
* intne - returns 1 iff arg1 != arg2
|
|
|
|
* intlt - returns 1 iff arg1 < arg2
|
|
|
|
* intle - returns 1 iff arg1 <= arg2
|
|
|
|
* intgt - returns 1 iff arg1 > arg2
|
|
|
|
* intge - returns 1 iff arg1 >= arg2
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
|
|
|
|
Datum
|
|
|
|
int4eq(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 == arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4ne(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 != arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4lt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 < arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4le(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 <= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4gt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 > arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4ge(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 >= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2eq(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 == arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2ne(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 != arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2lt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 < arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2le(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 <= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2gt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 > arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2ge(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 >= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24eq(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 == arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24ne(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 != arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24lt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 < arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24le(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 <= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24gt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 > arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24ge(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 >= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42eq(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 == arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42ne(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 != arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42lt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 < arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42le(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 <= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42gt(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 > arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42ge(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(arg1 >= arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* int[24]pl - returns arg1 + arg2
|
|
|
|
* int[24]mi - returns arg1 - arg2
|
|
|
|
* int[24]mul - returns arg1 * arg2
|
|
|
|
* int[24]div - returns arg1 / arg2
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
|
|
|
|
Datum
|
|
|
|
int4um(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg = PG_GETARG_INT32(0);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
result = -arg;
|
|
|
|
/* overflow check (needed for INT_MIN) */
|
|
|
|
if (arg != 0 && SAMESIGN(result, arg))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2001-06-07 02:09:32 +02:00
|
|
|
Datum
|
|
|
|
int4up(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg = PG_GETARG_INT32(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(arg);
|
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4pl(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 + arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of different signs then their sum
|
2005-10-15 04:49:52 +02:00
|
|
|
* cannot overflow. If the inputs are of the same sign, their sum had
|
|
|
|
* better be that sign too.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4mi(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 - arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of the same sign then their
|
|
|
|
* difference cannot overflow. If they are of different signs then the
|
2005-10-15 04:49:52 +02:00
|
|
|
* result should be of the same sign as the first input.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4mul(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 * arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. We basically check to see if result / arg2 gives arg1
|
2005-10-15 04:49:52 +02:00
|
|
|
* again. There are two cases where this fails: arg2 = 0 (which cannot
|
|
|
|
* overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
|
|
|
|
* overflow and thus incorrectly match).
|
2004-10-04 16:42:48 +02:00
|
|
|
*
|
|
|
|
* Since the division is likely much more expensive than the actual
|
2005-10-15 04:49:52 +02:00
|
|
|
* multiplication, we'd like to skip it where possible. The best bang for
|
|
|
|
* the buck seems to be to check whether both inputs are in the int16
|
|
|
|
* range; if so, no overflow is possible.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
|
|
|
|
arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
|
|
|
|
arg2 != 0 &&
|
2012-11-19 18:24:25 +01:00
|
|
|
((arg2 == -1 && arg1 < 0 && result < 0) ||
|
|
|
|
result / arg2 != arg1))
|
2004-10-04 16:42:48 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4div(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2003-03-11 22:01:33 +01:00
|
|
|
if (arg2 == 0)
|
2011-03-12 01:04:02 +01:00
|
|
|
{
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
|
|
errmsg("division by zero")));
|
2011-03-12 01:04:02 +01:00
|
|
|
/* ensure compiler realizes we mustn't reach the division (gcc bug) */
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
2003-03-11 22:01:33 +01:00
|
|
|
|
2006-06-12 18:09:11 +02:00
|
|
|
/*
|
2012-11-19 18:24:25 +01:00
|
|
|
* INT_MIN / -1 is problematic, since the result can't be represented on a
|
|
|
|
* two's-complement machine. Some machines produce INT_MIN, some produce
|
|
|
|
* zero, some throw an exception. We can dodge the problem by recognizing
|
|
|
|
* that division by -1 is the same as negation.
|
2006-06-12 18:09:11 +02:00
|
|
|
*/
|
2012-11-19 18:24:25 +01:00
|
|
|
if (arg2 == -1)
|
|
|
|
{
|
|
|
|
result = -arg1;
|
|
|
|
/* overflow check (needed for INT_MIN) */
|
|
|
|
if (arg1 != 0 && SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No overflow is possible */
|
2006-06-12 18:09:11 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
result = arg1 / arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4inc(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg = PG_GETARG_INT32(0);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
result = arg + 1;
|
|
|
|
/* Overflow check */
|
|
|
|
if (arg > 0 && result < 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2um(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg = PG_GETARG_INT16(0);
|
2004-10-04 16:42:48 +02:00
|
|
|
int16 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
result = -arg;
|
|
|
|
/* overflow check (needed for SHRT_MIN) */
|
|
|
|
if (arg != 0 && SAMESIGN(result, arg))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("smallint out of range")));
|
|
|
|
PG_RETURN_INT16(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2001-06-07 02:09:32 +02:00
|
|
|
Datum
|
|
|
|
int2up(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg = PG_GETARG_INT16(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(arg);
|
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2pl(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int16 result;
|
|
|
|
|
|
|
|
result = arg1 + arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of different signs then their sum
|
2005-10-15 04:49:52 +02:00
|
|
|
* cannot overflow. If the inputs are of the same sign, their sum had
|
|
|
|
* better be that sign too.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("smallint out of range")));
|
|
|
|
PG_RETURN_INT16(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2mi(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int16 result;
|
|
|
|
|
|
|
|
result = arg1 - arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of the same sign then their
|
|
|
|
* difference cannot overflow. If they are of different signs then the
|
2005-10-15 04:49:52 +02:00
|
|
|
* result should be of the same sign as the first input.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("smallint out of range")));
|
|
|
|
PG_RETURN_INT16(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2mul(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result32;
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* The most practical way to detect overflow is to do the arithmetic in
|
|
|
|
* int32 (so that the result can't overflow) and then do a range check.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
2005-10-15 04:49:52 +02:00
|
|
|
result32 = (int32) arg1 *(int32) arg2;
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
if (result32 < SHRT_MIN || result32 > SHRT_MAX)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("smallint out of range")));
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
PG_RETURN_INT16((int16) result32);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2div(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int16 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2003-03-11 22:01:33 +01:00
|
|
|
if (arg2 == 0)
|
2011-03-12 01:04:02 +01:00
|
|
|
{
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
|
|
errmsg("division by zero")));
|
2011-03-12 01:04:02 +01:00
|
|
|
/* ensure compiler realizes we mustn't reach the division (gcc bug) */
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
2003-03-11 22:01:33 +01:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2012-11-19 18:24:25 +01:00
|
|
|
* SHRT_MIN / -1 is problematic, since the result can't be represented on
|
|
|
|
* a two's-complement machine. Some machines produce SHRT_MIN, some
|
|
|
|
* produce zero, some throw an exception. We can dodge the problem by
|
|
|
|
* recognizing that division by -1 is the same as negation.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
2012-11-19 18:24:25 +01:00
|
|
|
if (arg2 == -1)
|
|
|
|
{
|
|
|
|
result = -arg1;
|
|
|
|
/* overflow check (needed for SHRT_MIN) */
|
|
|
|
if (arg1 != 0 && SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("smallint out of range")));
|
|
|
|
PG_RETURN_INT16(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No overflow is possible */
|
|
|
|
|
|
|
|
result = arg1 / arg2;
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
PG_RETURN_INT16(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24pl(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 + arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of different signs then their sum
|
2005-10-15 04:49:52 +02:00
|
|
|
* cannot overflow. If the inputs are of the same sign, their sum had
|
|
|
|
* better be that sign too.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24mi(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 - arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of the same sign then their
|
|
|
|
* difference cannot overflow. If they are of different signs then the
|
2005-10-15 04:49:52 +02:00
|
|
|
* result should be of the same sign as the first input.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24mul(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 * arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. We basically check to see if result / arg2 gives arg1
|
2005-10-15 04:49:52 +02:00
|
|
|
* again. There is one case where this fails: arg2 = 0 (which cannot
|
|
|
|
* overflow).
|
2004-10-04 16:42:48 +02:00
|
|
|
*
|
|
|
|
* Since the division is likely much more expensive than the actual
|
2005-10-15 04:49:52 +02:00
|
|
|
* multiplication, we'd like to skip it where possible. The best bang for
|
|
|
|
* the buck seems to be to check whether both inputs are in the int16
|
|
|
|
* range; if so, no overflow is possible.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
|
2005-10-15 04:49:52 +02:00
|
|
|
result / arg2 != arg1)
|
2004-10-04 16:42:48 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int24div(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
2003-03-11 22:01:33 +01:00
|
|
|
if (arg2 == 0)
|
2009-09-03 20:48:14 +02:00
|
|
|
{
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
|
|
errmsg("division by zero")));
|
2009-09-03 20:48:14 +02:00
|
|
|
/* ensure compiler realizes we mustn't reach the division (gcc bug) */
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/* No overflow is possible */
|
|
|
|
PG_RETURN_INT32((int32) arg1 / arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42pl(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 + arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of different signs then their sum
|
2005-10-15 04:49:52 +02:00
|
|
|
* cannot overflow. If the inputs are of the same sign, their sum had
|
|
|
|
* better be that sign too.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42mi(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 - arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. If the inputs are of the same sign then their
|
|
|
|
* difference cannot overflow. If they are of different signs then the
|
2005-10-15 04:49:52 +02:00
|
|
|
* result should be of the same sign as the first input.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42mul(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
|
|
|
|
|
|
|
result = arg1 * arg2;
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Overflow check. We basically check to see if result / arg1 gives arg2
|
2005-10-15 04:49:52 +02:00
|
|
|
* again. There is one case where this fails: arg1 = 0 (which cannot
|
|
|
|
* overflow).
|
2004-10-04 16:42:48 +02:00
|
|
|
*
|
|
|
|
* Since the division is likely much more expensive than the actual
|
2005-10-15 04:49:52 +02:00
|
|
|
* multiplication, we'd like to skip it where possible. The best bang for
|
|
|
|
* the buck seems to be to check whether both inputs are in the int16
|
|
|
|
* range; if so, no overflow is possible.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
|
|
|
if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
|
2005-10-15 04:49:52 +02:00
|
|
|
result / arg1 != arg2)
|
2004-10-04 16:42:48 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int42div(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2003-03-11 22:01:33 +01:00
|
|
|
if (arg2 == 0)
|
2011-03-12 01:04:02 +01:00
|
|
|
{
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
|
|
errmsg("division by zero")));
|
2011-03-12 01:04:02 +01:00
|
|
|
/* ensure compiler realizes we mustn't reach the division (gcc bug) */
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
2003-03-11 22:01:33 +01:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
2012-11-19 18:24:25 +01:00
|
|
|
* INT_MIN / -1 is problematic, since the result can't be represented on a
|
|
|
|
* two's-complement machine. Some machines produce INT_MIN, some produce
|
|
|
|
* zero, some throw an exception. We can dodge the problem by recognizing
|
|
|
|
* that division by -1 is the same as negation.
|
2004-10-04 16:42:48 +02:00
|
|
|
*/
|
2012-11-19 18:24:25 +01:00
|
|
|
if (arg2 == -1)
|
|
|
|
{
|
|
|
|
result = -arg1;
|
|
|
|
/* overflow check (needed for INT_MIN) */
|
|
|
|
if (arg1 != 0 && SAMESIGN(result, arg1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No overflow is possible */
|
|
|
|
|
|
|
|
result = arg1 / arg2;
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
PG_RETURN_INT32(result);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4mod(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
2003-03-11 22:01:33 +01:00
|
|
|
if (arg2 == 0)
|
2011-03-12 01:04:02 +01:00
|
|
|
{
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
|
|
errmsg("division by zero")));
|
2011-03-12 01:04:02 +01:00
|
|
|
/* ensure compiler realizes we mustn't reach the division (gcc bug) */
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
2007-01-02 21:00:50 +01:00
|
|
|
|
2012-11-14 23:30:00 +01:00
|
|
|
/*
|
|
|
|
* Some machines throw a floating-point exception for INT_MIN % -1, which
|
|
|
|
* is a bit silly since the correct answer is perfectly well-defined,
|
|
|
|
* namely zero.
|
|
|
|
*/
|
|
|
|
if (arg2 == -1)
|
2007-01-02 21:00:50 +01:00
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/* No overflow is possible */
|
2003-03-11 22:01:33 +01:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_INT32(arg1 % arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2mod(PG_FUNCTION_ARGS)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
2003-03-11 22:01:33 +01:00
|
|
|
if (arg2 == 0)
|
2011-03-12 01:04:02 +01:00
|
|
|
{
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
|
|
errmsg("division by zero")));
|
2011-03-12 01:04:02 +01:00
|
|
|
/* ensure compiler realizes we mustn't reach the division (gcc bug) */
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2012-11-14 23:30:00 +01:00
|
|
|
/*
|
|
|
|
* Some machines throw a floating-point exception for INT_MIN % -1, which
|
|
|
|
* is a bit silly since the correct answer is perfectly well-defined,
|
|
|
|
* namely zero. (It's not clear this ever happens when dealing with
|
|
|
|
* int16, but we might as well have the test for safety.)
|
|
|
|
*/
|
|
|
|
if (arg2 == -1)
|
|
|
|
PG_RETURN_INT16(0);
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/* No overflow is possible */
|
2003-03-11 22:01:33 +01:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_INT16(arg1 % arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-09-08 22:59:27 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-03-15 00:06:59 +01:00
|
|
|
/* int[24]abs()
|
|
|
|
* Absolute value
|
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4abs(PG_FUNCTION_ARGS)
|
2000-03-15 00:06:59 +01:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
2004-10-04 16:42:48 +02:00
|
|
|
int32 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
result = (arg1 < 0) ? -arg1 : arg1;
|
|
|
|
/* overflow check (needed for INT_MIN) */
|
|
|
|
if (result < 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("integer out of range")));
|
|
|
|
PG_RETURN_INT32(result);
|
2000-03-15 00:06:59 +01:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2abs(PG_FUNCTION_ARGS)
|
2000-03-15 00:06:59 +01:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
2004-10-04 16:42:48 +02:00
|
|
|
int16 result;
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
result = (arg1 < 0) ? -arg1 : arg1;
|
|
|
|
/* overflow check (needed for SHRT_MIN) */
|
|
|
|
if (result < 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("smallint out of range")));
|
|
|
|
PG_RETURN_INT16(result);
|
2000-03-15 00:06:59 +01:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2larger(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int2smaller(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4larger(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
int4smaller(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2000-10-24 22:16:48 +02:00
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
/*
|
|
|
|
* Bit-pushing operators
|
2000-10-24 22:16:48 +02:00
|
|
|
*
|
|
|
|
* int[24]and - returns arg1 & arg2
|
|
|
|
* int[24]or - returns arg1 | arg2
|
|
|
|
* int[24]xor - returns arg1 # arg2
|
|
|
|
* int[24]not - returns ~arg1
|
|
|
|
* int[24]shl - returns arg1 << arg2
|
|
|
|
* int[24]shr - returns arg1 >> arg2
|
|
|
|
*/
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int4and(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(arg1 & arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int4or(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(arg1 | arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int4xor(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(arg1 ^ arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int4shl(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(arg1 << arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int4shr(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(arg1 >> arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int4not(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 arg1 = PG_GETARG_INT32(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(~arg1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int2and(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(arg1 & arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int2or(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(arg1 | arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int2xor(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int16 arg2 = PG_GETARG_INT16(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(arg1 ^ arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int2not(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(~arg1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int2shl(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(arg1 << arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
int2shr(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int16 arg1 = PG_GETARG_INT16(0);
|
|
|
|
int32 arg2 = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT16(arg1 >> arg2);
|
|
|
|
}
|
2004-02-03 09:29:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* non-persistent numeric series generator
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
generate_series_int4(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
return generate_series_step_int4(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
generate_series_step_int4(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
FuncCallContext *funcctx;
|
|
|
|
generate_series_fctx *fctx;
|
|
|
|
int32 result;
|
|
|
|
MemoryContext oldcontext;
|
2004-02-03 09:29:57 +01:00
|
|
|
|
|
|
|
/* stuff done only on the first call of the function */
|
|
|
|
if (SRF_IS_FIRSTCALL())
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
int32 start = PG_GETARG_INT32(0);
|
|
|
|
int32 finish = PG_GETARG_INT32(1);
|
|
|
|
int32 step = 1;
|
2004-02-03 09:29:57 +01:00
|
|
|
|
|
|
|
/* see if we were given an explicit step size */
|
|
|
|
if (PG_NARGS() == 3)
|
|
|
|
step = PG_GETARG_INT32(2);
|
|
|
|
if (step == 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
Wording cleanup for error messages. Also change can't -> cannot.
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
2007-02-01 20:10:30 +01:00
|
|
|
errmsg("step size cannot equal zero")));
|
2004-02-03 09:29:57 +01:00
|
|
|
|
|
|
|
/* create a function context for cross-call persistence */
|
|
|
|
funcctx = SRF_FIRSTCALL_INIT();
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* switch to memory context appropriate for multiple function calls
|
2004-02-03 09:29:57 +01:00
|
|
|
*/
|
|
|
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
|
|
|
|
|
|
/* allocate memory for user context */
|
|
|
|
fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
|
|
|
|
|
|
|
|
/*
|
2004-08-29 07:07:03 +02:00
|
|
|
* Use fctx to keep state from call to call. Seed current with the
|
|
|
|
* original start value
|
2004-02-03 09:29:57 +01:00
|
|
|
*/
|
|
|
|
fctx->current = start;
|
|
|
|
fctx->finish = finish;
|
|
|
|
fctx->step = step;
|
|
|
|
|
|
|
|
funcctx->user_fctx = fctx;
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stuff done on every call of the function */
|
|
|
|
funcctx = SRF_PERCALL_SETUP();
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* get the saved state and use current as the result for this iteration
|
2004-02-03 09:29:57 +01:00
|
|
|
*/
|
|
|
|
fctx = funcctx->user_fctx;
|
|
|
|
result = fctx->current;
|
|
|
|
|
|
|
|
if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
|
|
|
|
(fctx->step < 0 && fctx->current >= fctx->finish))
|
|
|
|
{
|
|
|
|
/* increment current in preparation for next iteration */
|
|
|
|
fctx->current += fctx->step;
|
|
|
|
|
2011-06-17 20:28:45 +02:00
|
|
|
/* if next-value computation overflows, this is the final result */
|
|
|
|
if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
|
|
|
|
fctx->step = 0;
|
|
|
|
|
2004-02-03 09:29:57 +01:00
|
|
|
/* do when there is more left to send */
|
|
|
|
SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* do when there is no more left */
|
|
|
|
SRF_RETURN_DONE(funcctx);
|
|
|
|
}
|