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 + -
显示快捷键?