int8.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,221 行 · 第 1/2 页
C
1,221 行
/*------------------------------------------------------------------------- * * int8.c * Internal 64-bit integer operations * * 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/int8.c,v 1.68 2008/01/01 19:45:52 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include <limits.h>#include <math.h>#include "funcapi.h"#include "libpq/pqformat.h"#include "nodes/nodes.h"#include "utils/int8.h"#define MAXINT8LEN 25#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))typedef struct{ int64 current; int64 finish; int64 step;} generate_series_fctx;/*********************************************************************** ** ** Routines for 64-bit integers. ** ***********************************************************************//*---------------------------------------------------------- * Formatting and conversion routines. *---------------------------------------------------------*//* * scanint8 --- try to parse a string into an int8. * * If errorOK is false, ereport a useful error message if the string is bad. * If errorOK is true, just return "false" for bad input. */boolscanint8(const char *str, bool errorOK, int64 *result){ const char *ptr = str; int64 tmp = 0; int sign = 1; /* * Do our own scan, rather than relying on sscanf which might be broken * for long long. */ /* skip leading spaces */ while (*ptr && isspace((unsigned char) *ptr)) ptr++; /* handle sign */ if (*ptr == '-') { ptr++; /* * Do an explicit check for INT64_MIN. Ugly though this is, it's * cleaner than trying to get the loop below to handle it portably. */#ifndef INT64_IS_BUSTED if (strncmp(ptr, "9223372036854775808", 19) == 0) { tmp = -INT64CONST(0x7fffffffffffffff) - 1; ptr += 19; goto gotdigits; }#endif sign = -1; } else if (*ptr == '+') ptr++; /* require at least one digit */ if (!isdigit((unsigned char) *ptr)) { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", str))); } /* process digits */ while (*ptr && isdigit((unsigned char) *ptr)) { int64 newtmp = tmp * 10 + (*ptr++ - '0'); if ((newtmp / 10) != tmp) /* overflow? */ { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value \"%s\" is out of range for type bigint", str))); } tmp = newtmp; }gotdigits: /* allow trailing whitespace, but not other trailing chars */ while (*ptr != '\0' && isspace((unsigned char) *ptr)) ptr++; if (*ptr != '\0') { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", str))); } *result = (sign < 0) ? -tmp : tmp; return true;}/* int8in() */Datumint8in(PG_FUNCTION_ARGS){ char *str = PG_GETARG_CSTRING(0); int64 result; (void) scanint8(str, false, &result); PG_RETURN_INT64(result);}/* int8out() */Datumint8out(PG_FUNCTION_ARGS){ int64 val = PG_GETARG_INT64(0); char *result; int len; char buf[MAXINT8LEN + 1]; if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0) elog(ERROR, "could not format int8"); result = pstrdup(buf); PG_RETURN_CSTRING(result);}/* * int8recv - converts external binary format to int8 */Datumint8recv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_INT64(pq_getmsgint64(buf));}/* * int8send - converts int8 to binary format */Datumint8send(PG_FUNCTION_ARGS){ int64 arg1 = PG_GETARG_INT64(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint64(&buf, arg1); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/*---------------------------------------------------------- * Relational operators for int8s, including cross-data-type comparisons. *---------------------------------------------------------*//* int8relop() * Is val1 relop val2? */Datumint8eq(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 == val2);}Datumint8ne(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 != val2);}Datumint8lt(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 < val2);}Datumint8gt(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 > val2);}Datumint8le(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 <= val2);}Datumint8ge(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 >= val2);}/* int84relop() * Is 64-bit val1 relop 32-bit val2? */Datumint84eq(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int32 val2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(val1 == val2);}Datumint84ne(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int32 val2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(val1 != val2);}Datumint84lt(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int32 val2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(val1 < val2);}Datumint84gt(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int32 val2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(val1 > val2);}Datumint84le(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int32 val2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(val1 <= val2);}Datumint84ge(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int32 val2 = PG_GETARG_INT32(1); PG_RETURN_BOOL(val1 >= val2);}/* int48relop() * Is 32-bit val1 relop 64-bit val2? */Datumint48eq(PG_FUNCTION_ARGS){ int32 val1 = PG_GETARG_INT32(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 == val2);}Datumint48ne(PG_FUNCTION_ARGS){ int32 val1 = PG_GETARG_INT32(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 != val2);}Datumint48lt(PG_FUNCTION_ARGS){ int32 val1 = PG_GETARG_INT32(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 < val2);}Datumint48gt(PG_FUNCTION_ARGS){ int32 val1 = PG_GETARG_INT32(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 > val2);}Datumint48le(PG_FUNCTION_ARGS){ int32 val1 = PG_GETARG_INT32(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 <= val2);}Datumint48ge(PG_FUNCTION_ARGS){ int32 val1 = PG_GETARG_INT32(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 >= val2);}/* int82relop() * Is 64-bit val1 relop 16-bit val2? */Datumint82eq(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int16 val2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(val1 == val2);}Datumint82ne(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int16 val2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(val1 != val2);}Datumint82lt(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int16 val2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(val1 < val2);}Datumint82gt(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int16 val2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(val1 > val2);}Datumint82le(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int16 val2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(val1 <= val2);}Datumint82ge(PG_FUNCTION_ARGS){ int64 val1 = PG_GETARG_INT64(0); int16 val2 = PG_GETARG_INT16(1); PG_RETURN_BOOL(val1 >= val2);}/* int28relop() * Is 16-bit val1 relop 64-bit val2? */Datumint28eq(PG_FUNCTION_ARGS){ int16 val1 = PG_GETARG_INT16(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 == val2);}Datumint28ne(PG_FUNCTION_ARGS){ int16 val1 = PG_GETARG_INT16(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 != val2);}Datumint28lt(PG_FUNCTION_ARGS){ int16 val1 = PG_GETARG_INT16(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 < val2);}Datumint28gt(PG_FUNCTION_ARGS){ int16 val1 = PG_GETARG_INT16(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 > val2);}Datumint28le(PG_FUNCTION_ARGS){ int16 val1 = PG_GETARG_INT16(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 <= val2);}Datumint28ge(PG_FUNCTION_ARGS){ int16 val1 = PG_GETARG_INT16(0); int64 val2 = PG_GETARG_INT64(1); PG_RETURN_BOOL(val1 >= val2);}/*---------------------------------------------------------- * Arithmetic operators on 64-bit integers. *---------------------------------------------------------*/Datumint8um(PG_FUNCTION_ARGS){ int64 arg = PG_GETARG_INT64(0); int64 result; result = -arg; /* overflow check (needed for INT64_MIN) */ if (arg != 0 && SAMESIGN(result, arg)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); PG_RETURN_INT64(result);}Datumint8up(PG_FUNCTION_ARGS){ int64 arg = PG_GETARG_INT64(0); PG_RETURN_INT64(arg);}Datumint8pl(PG_FUNCTION_ARGS){ int64 arg1 = PG_GETARG_INT64(0); int64 arg2 = PG_GETARG_INT64(1); int64 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("bigint out of range"))); PG_RETURN_INT64(result);}Datumint8mi(PG_FUNCTION_ARGS){ int64 arg1 = PG_GETARG_INT64(0); int64 arg2 = PG_GETARG_INT64(1); int64 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("bigint out of range"))); PG_RETURN_INT64(result);}Datumint8mul(PG_FUNCTION_ARGS){ int64 arg1 = PG_GETARG_INT64(0); int64 arg2 = PG_GETARG_INT64(1); int64 result; 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 = INT64_MIN, arg2 = -1 (where the division itself * will overflow and thus incorrectly match). * * Since the division is likely much more expensive than the actual * 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 int32 * range; if so, no overflow is possible. (But that only works if we * really have a 64-bit int64 datatype...) */#ifndef INT64_IS_BUSTED if (arg1 != (int64) ((int32) arg1) || arg2 != (int64) ((int32) arg2))#endif { if (arg2 != 0 && (result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0))) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); } PG_RETURN_INT64(result);}Datumint8div(PG_FUNCTION_ARGS){ int64 arg1 = PG_GETARG_INT64(0); int64 arg2 = PG_GETARG_INT64(1); int64 result; if (arg2 == 0) ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO), errmsg("division by zero"))); result = arg1 / arg2; /* * Overflow check. The only possible overflow case is for arg1 = * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which * can't be represented on a two's-complement machine.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?