📄 int.c
字号:
/*------------------------------------------------------------------------- * * int.c * Functions for the built-in integer types (except int8). * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.81 2008/01/01 19:45:52 momjian Exp $ * *------------------------------------------------------------------------- *//* * OLD COMMENTS * I/O routines: * int2in, int2out, int2recv, int2send * int4in, int4out, int4recv, int4send * int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend * Boolean operators: * inteq, intne, intlt, intle, intgt, intge * Arithmetic operators: * intpl, intmi, int4mul, intdiv * * Arithmetic operators: * intmod */#include "postgres.h"#include <ctype.h>#include <limits.h>#include "catalog/pg_type.h"#include "funcapi.h"#include "libpq/pqformat.h"#include "utils/array.h"#include "utils/builtins.h"#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))#define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int2))typedef struct{ int32 current; int32 finish; int32 step;} generate_series_fctx;/***************************************************************************** * USER I/O ROUTINES * *****************************************************************************//* * int2in - converts "num" to short */Datumint2in(PG_FUNCTION_ARGS){ char *num = PG_GETARG_CSTRING(0); PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));}/* * int2out - converts short to "num" */Datumint2out(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */ pg_itoa(arg1, result); PG_RETURN_CSTRING(result);}/* * int2recv - converts external binary format to int2 */Datumint2recv(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 */Datumint2send(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));}/* * construct int2vector given a raw array of int2s * * If int2s is NULL then caller must fill values[] afterward */int2vector *buildint2vector(const int2 *int2s, int n){ int2vector *result; result = (int2vector *) palloc0(Int2VectorSize(n)); if (n > 0 && int2s) memcpy(result->values, int2s, n * sizeof(int2)); /* * Attach standard array header. For historical reasons, we set the index * lower bound to 0 not 1. */ SET_VARSIZE(result, Int2VectorSize(n)); result->ndim = 1; result->dataoffset = 0; /* never any nulls */ result->elemtype = INT2OID; result->dim1 = n; result->lbound1 = 0; return result;}/* * int2vectorin - converts "num num ..." to internal form */Datumint2vectorin(PG_FUNCTION_ARGS){ char *intString = PG_GETARG_CSTRING(0); int2vector *result; int n; result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS)); for (n = 0; *intString && n < FUNC_MAX_ARGS; n++) { if (sscanf(intString, "%hd", &result->values[n]) != 1) break; while (*intString && isspace((unsigned char) *intString)) intString++; while (*intString && !isspace((unsigned char) *intString)) intString++; } while (*intString && isspace((unsigned char) *intString)) intString++; if (*intString) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("int2vector has too many elements"))); SET_VARSIZE(result, Int2VectorSize(n)); result->ndim = 1; result->dataoffset = 0; /* never any nulls */ result->elemtype = INT2OID; result->dim1 = n; result->lbound1 = 0; PG_RETURN_POINTER(result);}/* * int2vectorout - converts internal form to "num num ..." */Datumint2vectorout(PG_FUNCTION_ARGS){ int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0); int num, nnums = int2Array->dim1; char *rp; char *result; /* assumes sign, 5 digits, ' ' */ rp = result = (char *) palloc(nnums * 7 + 1); for (num = 0; num < nnums; num++) { if (num != 0) *rp++ = ' '; pg_itoa(int2Array->values[num], rp); while (*++rp != '\0') ; } *rp = '\0'; PG_RETURN_CSTRING(result);}/* * int2vectorrecv - converts external binary format to int2vector */Datumint2vectorrecv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); FunctionCallInfoData locfcinfo; int2vector *result; /* * 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. */ InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, NULL, NULL); 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); /* sanity checks: int2vector must be 1-D, no nulls */ if (ARR_NDIM(result) != 1 || ARR_HASNULL(result) || ARR_ELEMTYPE(result) != INT2OID) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid int2vector data"))); PG_RETURN_POINTER(result);}/* * int2vectorsend - converts int2vector to binary format */Datumint2vectorsend(PG_FUNCTION_ARGS){ return array_send(fcinfo);}/* * We don't have a complete set of int2vector support routines, * but we need int2vectoreq for catcache indexing. */Datumint2vectoreq(PG_FUNCTION_ARGS){ int2vector *a = (int2vector *) PG_GETARG_POINTER(0); int2vector *b = (int2vector *) PG_GETARG_POINTER(1); if (a->dim1 != b->dim1) PG_RETURN_BOOL(false); PG_RETURN_BOOL(memcmp(a->values, b->values, a->dim1 * sizeof(int2)) == 0);}/***************************************************************************** * PUBLIC ROUTINES * *****************************************************************************//* * int4in - converts "num" to int4 */Datumint4in(PG_FUNCTION_ARGS){ char *num = PG_GETARG_CSTRING(0); PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));}/* * int4out - converts int4 to "num" */Datumint4out(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */ pg_ltoa(arg1, result); PG_RETURN_CSTRING(result);}/* * int4recv - converts external binary format to int4 */Datumint4recv(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 */Datumint4send(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));}/* * =================== * CONVERSION ROUTINES * =================== */Datumi2toi4(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); PG_RETURN_INT32((int32) arg1);}Datumi4toi2(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); if (arg1 < SHRT_MIN || arg1 > SHRT_MAX) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); PG_RETURN_INT16((int16) arg1);}/* Cast int4 -> bool */Datumint4_bool(PG_FUNCTION_ARGS){ if (PG_GETARG_INT32(0) == 0) PG_RETURN_BOOL(false); else PG_RETURN_BOOL(true);}/* Cast bool -> int4 */Datumbool_int4(PG_FUNCTION_ARGS){ if (PG_GETARG_BOOL(0) == false) PG_RETURN_INT32(0); else PG_RETURN_INT32(1);}/* * ============================ * COMPARISON OPERATOR ROUTINES * ============================ *//* * 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 */Datumint4eq(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 == arg2);}Datumint4ne(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 != arg2);}Datumint4lt(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 < arg2);}Datumint4le(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 <= arg2);}Datumint4gt(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 > arg2);}Datumint4ge(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 >= arg2);}Datumint2eq(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 == arg2);}Datumint2ne(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 != arg2);}Datumint2lt(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 < arg2);}Datumint2le(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 <= arg2);}Datumint2gt(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 > arg2);}Datumint2ge(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 >= arg2);}Datumint24eq(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 == arg2);}Datumint24ne(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 != arg2);}Datumint24lt(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 < arg2);}Datumint24le(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 <= arg2);}Datumint24gt(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 > arg2);}Datumint24ge(PG_FUNCTION_ARGS){ int16 arg1 = PG_GETARG_INT16(0); int32 arg2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(arg1 >= arg2);}Datumint42eq(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 == arg2);}Datumint42ne(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 != arg2);}Datumint42lt(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 < arg2);}Datumint42le(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 <= arg2);}Datumint42gt(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 > arg2);}Datumint42ge(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int16 arg2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(arg1 >= arg2);}/* * int[24]pl - returns arg1 + arg2 * int[24]mi - returns arg1 - arg2 * int[24]mul - returns arg1 * arg2 * int[24]div - returns arg1 / arg2 */Datumint4um(PG_FUNCTION_ARGS){ int32 arg = PG_GETARG_INT32(0); int32 result; 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);}Datumint4up(PG_FUNCTION_ARGS){ int32 arg = PG_GETARG_INT32(0); PG_RETURN_INT32(arg);}Datumint4pl(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); int32 result; result = arg1 + arg2; /* * Overflow check. If the inputs are of different signs then their sum * cannot overflow. If the inputs are of the same sign, their sum had * better be that sign too. */ 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);}Datumint4mi(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); int32 result; result = arg1 - arg2; /* * Overflow check. If the inputs are of the same sign then their * difference cannot overflow. If they are of different signs then the * result should be of the same sign as the first input. */ 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);}Datumint4mul(PG_FUNCTION_ARGS){ int32 arg1 = PG_GETARG_INT32(0); int32 arg2 = PG_GETARG_INT32(1); int32 result;#ifdef WIN32 /* * Win32 doesn't throw a catchable exception for SELECT -2147483648 * * (-1); -- INT_MIN */ if (arg2 == -1 && arg1 == INT_MIN) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range")));#endif result = arg1 * arg2; /* * Overflow check. We basically check to see if result / arg2 gives arg1 * 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).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -