int8.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,221 行 · 第 1/2 页

C
1,221
字号
	 */	if (arg2 == -1 && arg1 < 0 && result < 0)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}/* int8abs() * Absolute value */Datumint8abs(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		result;	result = (arg1 < 0) ? -arg1 : arg1;	/* overflow check (needed for INT64_MIN) */	if (result < 0)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}/* int8mod() * Modulo operation. */Datumint8mod(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		arg2 = PG_GETARG_INT64(1);	if (arg2 == 0)		ereport(ERROR,				(errcode(ERRCODE_DIVISION_BY_ZERO),				 errmsg("division by zero")));	/* No overflow is possible */	PG_RETURN_INT64(arg1 % arg2);}Datumint8inc(PG_FUNCTION_ARGS){	if (fcinfo->context && IsA(fcinfo->context, AggState))	{		/*		 * Special case to avoid palloc overhead for COUNT(): when called from		 * nodeAgg, we know that the argument is modifiable local storage, so		 * just update it in-place.		 *		 * Note: this assumes int8 is a pass-by-ref type; if we ever support		 * pass-by-val int8, this should be ifdef'd out when int8 is		 * pass-by-val.		 */		int64	   *arg = (int64 *) PG_GETARG_POINTER(0);		int64		result;		result = *arg + 1;		/* Overflow check */		if (result < 0 && *arg > 0)			ereport(ERROR,					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),					 errmsg("bigint out of range")));		*arg = result;		PG_RETURN_POINTER(arg);	}	else	{		/* Not called by nodeAgg, so just do it the dumb way */		int64		arg = PG_GETARG_INT64(0);		int64		result;		result = arg + 1;		/* Overflow check */		if (result < 0 && arg > 0)			ereport(ERROR,					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),					 errmsg("bigint out of range")));		PG_RETURN_INT64(result);	}}/* * These functions are exactly like int8inc but are used for aggregates that * count only non-null values.	Since the functions are declared strict, * the null checks happen before we ever get here, and all we need do is * increment the state value.  We could actually make these pg_proc entries * point right at int8inc, but then the opr_sanity regression test would * complain about mismatched entries for a built-in function. */Datumint8inc_any(PG_FUNCTION_ARGS){	return int8inc(fcinfo);}Datumint8inc_float8_float8(PG_FUNCTION_ARGS){	return int8inc(fcinfo);}Datumint8larger(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		arg2 = PG_GETARG_INT64(1);	int64		result;	result = ((arg1 > arg2) ? arg1 : arg2);	PG_RETURN_INT64(result);}Datumint8smaller(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		arg2 = PG_GETARG_INT64(1);	int64		result;	result = ((arg1 < arg2) ? arg1 : arg2);	PG_RETURN_INT64(result);}Datumint84pl(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int32		arg2 = PG_GETARG_INT32(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);}Datumint84mi(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int32		arg2 = PG_GETARG_INT32(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);}Datumint84mul(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int32		arg2 = PG_GETARG_INT32(1);	int64		result;	result = arg1 * arg2;	/*	 * Overflow check.	We basically check to see if result / arg1 gives arg2	 * again.  There is one case where this fails: arg1 = 0 (which cannot	 * overflow).	 *	 * 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.	 */	if (arg1 != (int64) ((int32) arg1) &&		result / arg1 != arg2)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}Datumint84div(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int32		arg2 = PG_GETARG_INT32(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.	 */	if (arg2 == -1 && arg1 < 0 && result < 0)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}Datumint48pl(PG_FUNCTION_ARGS){	int32		arg1 = PG_GETARG_INT32(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);}Datumint48mi(PG_FUNCTION_ARGS){	int32		arg1 = PG_GETARG_INT32(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);}Datumint48mul(PG_FUNCTION_ARGS){	int32		arg1 = PG_GETARG_INT32(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 is one case where this fails: arg2 = 0 (which cannot	 * overflow).	 *	 * 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.	 */	if (arg2 != (int64) ((int32) arg2) &&		result / arg2 != arg1)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}Datumint48div(PG_FUNCTION_ARGS){	int32		arg1 = PG_GETARG_INT32(0);	int64		arg2 = PG_GETARG_INT64(1);	if (arg2 == 0)		ereport(ERROR,				(errcode(ERRCODE_DIVISION_BY_ZERO),				 errmsg("division by zero")));	/* No overflow is possible */	PG_RETURN_INT64((int64) arg1 / arg2);}/* Binary arithmetics * *		int8and		- returns arg1 & arg2 *		int8or		- returns arg1 | arg2 *		int8xor		- returns arg1 # arg2 *		int8not		- returns ~arg1 *		int8shl		- returns arg1 << arg2 *		int8shr		- returns arg1 >> arg2 */Datumint8and(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		arg2 = PG_GETARG_INT64(1);	PG_RETURN_INT64(arg1 & arg2);}Datumint8or(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		arg2 = PG_GETARG_INT64(1);	PG_RETURN_INT64(arg1 | arg2);}Datumint8xor(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int64		arg2 = PG_GETARG_INT64(1);	PG_RETURN_INT64(arg1 ^ arg2);}Datumint8not(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	PG_RETURN_INT64(~arg1);}Datumint8shl(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int32		arg2 = PG_GETARG_INT32(1);	PG_RETURN_INT64(arg1 << arg2);}Datumint8shr(PG_FUNCTION_ARGS){	int64		arg1 = PG_GETARG_INT64(0);	int32		arg2 = PG_GETARG_INT32(1);	PG_RETURN_INT64(arg1 >> arg2);}/*---------------------------------------------------------- *	Conversion operators. *---------------------------------------------------------*/Datumint48(PG_FUNCTION_ARGS){	int32		arg = PG_GETARG_INT32(0);	PG_RETURN_INT64((int64) arg);}Datumint84(PG_FUNCTION_ARGS){	int64		arg = PG_GETARG_INT64(0);	int32		result;	result = (int32) arg;	/* Test for overflow by reverse-conversion. */	if ((int64) result != arg)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("integer out of range")));	PG_RETURN_INT32(result);}Datumint28(PG_FUNCTION_ARGS){	int16		arg = PG_GETARG_INT16(0);	PG_RETURN_INT64((int64) arg);}Datumint82(PG_FUNCTION_ARGS){	int64		arg = PG_GETARG_INT64(0);	int16		result;	result = (int16) arg;	/* Test for overflow by reverse-conversion. */	if ((int64) result != arg)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("smallint out of range")));	PG_RETURN_INT16(result);}Datumi8tod(PG_FUNCTION_ARGS){	int64		arg = PG_GETARG_INT64(0);	float8		result;	result = arg;	PG_RETURN_FLOAT8(result);}/* dtoi8() * Convert float8 to 8-byte integer. */Datumdtoi8(PG_FUNCTION_ARGS){	float8		arg = PG_GETARG_FLOAT8(0);	int64		result;	/* Round arg to nearest integer (but it's still in float form) */	arg = rint(arg);	/*	 * Does it fit in an int64?  Avoid assuming that we have handy constants	 * defined for the range boundaries, instead test for overflow by	 * reverse-conversion.	 */	result = (int64) arg;	if ((float8) result != arg)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}Datumi8tof(PG_FUNCTION_ARGS){	int64		arg = PG_GETARG_INT64(0);	float4		result;	result = arg;	PG_RETURN_FLOAT4(result);}/* ftoi8() * Convert float4 to 8-byte integer. */Datumftoi8(PG_FUNCTION_ARGS){	float4		arg = PG_GETARG_FLOAT4(0);	int64		result;	float8		darg;	/* Round arg to nearest integer (but it's still in float form) */	darg = rint(arg);	/*	 * Does it fit in an int64?  Avoid assuming that we have handy constants	 * defined for the range boundaries, instead test for overflow by	 * reverse-conversion.	 */	result = (int64) darg;	if ((float8) result != darg)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	PG_RETURN_INT64(result);}Datumi8tooid(PG_FUNCTION_ARGS){	int64		arg = PG_GETARG_INT64(0);	Oid			result;	result = (Oid) arg;	/* Test for overflow by reverse-conversion. */	if ((int64) result != arg)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("OID out of range")));	PG_RETURN_OID(result);}Datumoidtoi8(PG_FUNCTION_ARGS){	Oid			arg = PG_GETARG_OID(0);	PG_RETURN_INT64((int64) arg);}/* * non-persistent numeric series generator */Datumgenerate_series_int8(PG_FUNCTION_ARGS){	return generate_series_step_int8(fcinfo);}Datumgenerate_series_step_int8(PG_FUNCTION_ARGS){	FuncCallContext *funcctx;	generate_series_fctx *fctx;	int64		result;	MemoryContext oldcontext;	/* stuff done only on the first call of the function */	if (SRF_IS_FIRSTCALL())	{		int64		start = PG_GETARG_INT64(0);		int64		finish = PG_GETARG_INT64(1);		int64		step = 1;		/* see if we were given an explicit step size */		if (PG_NARGS() == 3)			step = PG_GETARG_INT64(2);		if (step == 0)			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("step size cannot equal zero")));		/* create a function context for cross-call persistence */		funcctx = SRF_FIRSTCALL_INIT();		/*		 * switch to memory context appropriate for multiple function calls		 */		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);		/* allocate memory for user context */		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));		/*		 * Use fctx to keep state from call to call. Seed current with the		 * original start value		 */		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();	/*	 * get the saved state and use current as the result for this iteration	 */	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;		/* do when there is more left to send */		SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));	}	else		/* do when there is no more left */		SRF_RETURN_DONE(funcctx);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?