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