⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 numeric.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
Datumnumeric_int4(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	NumericVar	x;	int32		result;	/* XXX would it be better to return NULL? */	if (NUMERIC_IS_NAN(num))		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot convert NaN to integer")));	/* Convert to variable format, then convert to int4 */	init_var(&x);	set_var_from_num(num, &x);	result = numericvar_to_int4(&x);	free_var(&x);	PG_RETURN_INT32(result);}/* * Given a NumericVar, convert it to an int32. If the NumericVar * exceeds the range of an int32, raise the appropriate error via * ereport(). The input NumericVar is *not* free'd. */static int32numericvar_to_int4(NumericVar *var){	int32		result;	int64		val;	if (!numericvar_to_int8(var, &val))		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("integer out of range")));	/* Down-convert to int4 */	result = (int32) val;	/* Test for overflow by reverse-conversion. */	if ((int64) result != val)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("integer out of range")));	return result;}Datumint8_numeric(PG_FUNCTION_ARGS){	int64		val = PG_GETARG_INT64(0);	Numeric		res;	NumericVar	result;	init_var(&result);	int8_to_numericvar(val, &result);	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}Datumnumeric_int8(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	NumericVar	x;	int64		result;	/* XXX would it be better to return NULL? */	if (NUMERIC_IS_NAN(num))		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot convert NaN to bigint")));	/* Convert to variable format and thence to int8 */	init_var(&x);	set_var_from_num(num, &x);	if (!numericvar_to_int8(&x, &result))		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	free_var(&x);	PG_RETURN_INT64(result);}Datumint2_numeric(PG_FUNCTION_ARGS){	int16		val = PG_GETARG_INT16(0);	Numeric		res;	NumericVar	result;	init_var(&result);	int8_to_numericvar((int64) val, &result);	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}Datumnumeric_int2(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	NumericVar	x;	int64		val;	int16		result;	/* XXX would it be better to return NULL? */	if (NUMERIC_IS_NAN(num))		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot convert NaN to smallint")));	/* Convert to variable format and thence to int8 */	init_var(&x);	set_var_from_num(num, &x);	if (!numericvar_to_int8(&x, &val))		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("smallint out of range")));	free_var(&x);	/* Down-convert to int2 */	result = (int16) val;	/* Test for overflow by reverse-conversion. */	if ((int64) result != val)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("smallint out of range")));	PG_RETURN_INT16(result);}Datumfloat8_numeric(PG_FUNCTION_ARGS){	float8		val = PG_GETARG_FLOAT8(0);	Numeric		res;	NumericVar	result;	char		buf[DBL_DIG + 100];	if (isnan(val))		PG_RETURN_NUMERIC(make_result(&const_nan));	sprintf(buf, "%.*g", DBL_DIG, val);	init_var(&result);	set_var_from_str(buf, &result);	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}Datumnumeric_float8(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	char	   *tmp;	Datum		result;	if (NUMERIC_IS_NAN(num))		PG_RETURN_FLOAT8(get_float8_nan());	tmp = DatumGetCString(DirectFunctionCall1(numeric_out,											  NumericGetDatum(num)));	result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));	pfree(tmp);	PG_RETURN_DATUM(result);}/* Convert numeric to float8; if out of range, return +/- HUGE_VAL */Datumnumeric_float8_no_overflow(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	double		val;	if (NUMERIC_IS_NAN(num))		PG_RETURN_FLOAT8(get_float8_nan());	val = numeric_to_double_no_overflow(num);	PG_RETURN_FLOAT8(val);}Datumfloat4_numeric(PG_FUNCTION_ARGS){	float4		val = PG_GETARG_FLOAT4(0);	Numeric		res;	NumericVar	result;	char		buf[FLT_DIG + 100];	if (isnan(val))		PG_RETURN_NUMERIC(make_result(&const_nan));	sprintf(buf, "%.*g", FLT_DIG, val);	init_var(&result);	set_var_from_str(buf, &result);	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}Datumnumeric_float4(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	char	   *tmp;	Datum		result;	if (NUMERIC_IS_NAN(num))		PG_RETURN_FLOAT4(get_float4_nan());	tmp = DatumGetCString(DirectFunctionCall1(numeric_out,											  NumericGetDatum(num)));	result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));	pfree(tmp);	PG_RETURN_DATUM(result);}Datumtext_numeric(PG_FUNCTION_ARGS){	text	   *str = PG_GETARG_TEXT_P(0);	int			len;	char	   *s;	Datum		result;	len = (VARSIZE(str) - VARHDRSZ);	s = palloc(len + 1);	memcpy(s, VARDATA(str), len);	*(s + len) = '\0';	result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),								 ObjectIdGetDatum(0), Int32GetDatum(-1));	pfree(s);	return result;}Datumnumeric_text(PG_FUNCTION_ARGS){	/* val is numeric, but easier to leave it as Datum */	Datum		val = PG_GETARG_DATUM(0);	char	   *s;	int			len;	text	   *result;	s = DatumGetCString(DirectFunctionCall1(numeric_out, val));	len = strlen(s);	result = (text *) palloc(VARHDRSZ + len);	VARATT_SIZEP(result) = len + VARHDRSZ;	memcpy(VARDATA(result), s, len);	pfree(s);	PG_RETURN_TEXT_P(result);}/* ---------------------------------------------------------------------- * * Aggregate functions * * The transition datatype for all these aggregates is a 3-element array * of Numeric, holding the values N, sum(X), sum(X*X) in that order. * * We represent N as a numeric mainly to avoid having to build a special * datatype; it's unlikely it'd overflow an int4, but ... * * ---------------------------------------------------------------------- */static ArrayType *do_numeric_accum(ArrayType *transarray, Numeric newval){	Datum	   *transdatums;	int			ndatums;	Datum		N,				sumX,				sumX2;	ArrayType  *result;	/* We assume the input is array of numeric */	deconstruct_array(transarray,					  NUMERICOID, -1, false, 'i',					  &transdatums, &ndatums);	if (ndatums != 3)		elog(ERROR, "expected 3-element numeric array");	N = transdatums[0];	sumX = transdatums[1];	sumX2 = transdatums[2];	N = DirectFunctionCall1(numeric_inc, N);	sumX = DirectFunctionCall2(numeric_add, sumX,							   NumericGetDatum(newval));	sumX2 = DirectFunctionCall2(numeric_add, sumX2,								DirectFunctionCall2(numeric_mul,													NumericGetDatum(newval),													NumericGetDatum(newval)));	transdatums[0] = N;	transdatums[1] = sumX;	transdatums[2] = sumX2;	result = construct_array(transdatums, 3,							 NUMERICOID, -1, false, 'i');	return result;}Datumnumeric_accum(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Numeric		newval = PG_GETARG_NUMERIC(1);	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));}/* * Integer data types all use Numeric accumulators to share code and * avoid risk of overflow.	For int2 and int4 inputs, Numeric accumulation * is overkill for the N and sum(X) values, but definitely not overkill * for the sum(X*X) value.	Hence, we use int2_accum and int4_accum only * for stddev/variance --- there are faster special-purpose accumulator * routines for SUM and AVG of these datatypes. */Datumint2_accum(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum		newval2 = PG_GETARG_DATUM(1);	Numeric		newval;	newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));}Datumint4_accum(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum		newval4 = PG_GETARG_DATUM(1);	Numeric		newval;	newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));}Datumint8_accum(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum		newval8 = PG_GETARG_DATUM(1);	Numeric		newval;	newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));}Datumnumeric_avg(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum	   *transdatums;	int			ndatums;	Numeric		N,				sumX;	/* We assume the input is array of numeric */	deconstruct_array(transarray,					  NUMERICOID, -1, false, 'i',					  &transdatums, &ndatums);	if (ndatums != 3)		elog(ERROR, "expected 3-element numeric array");	N = DatumGetNumeric(transdatums[0]);	sumX = DatumGetNumeric(transdatums[1]);	/* ignore sumX2 */	/* SQL92 defines AVG of no values to be NULL */	/* N is zero iff no digits (cf. numeric_uminus) */	if (N->varlen == NUMERIC_HDRSZ)		PG_RETURN_NULL();	PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,										NumericGetDatum(sumX),										NumericGetDatum(N)));}Datumnumeric_variance(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum	   *transdatums;	int			ndatums;	Numeric		N,				sumX,				sumX2,				res;	NumericVar	vN,				vsumX,				vsumX2,				vNminus1;	int			rscale;	/* We assume the input is array of numeric */	deconstruct_array(transarray,					  NUMERICOID, -1, false, 'i',					  &transdatums, &ndatums);	if (ndatums != 3)		elog(ERROR, "expected 3-element numeric array");	N = DatumGetNumeric(transdatums[0]);	sumX = DatumGetNumeric(transdatums[1]);	sumX2 = DatumGetNumeric(transdatums[2]);	if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))		PG_RETURN_NUMERIC(make_result(&const_nan));	/* Sample variance is undefined when N is 0 or 1, so return NULL */	init_var(&vN);	set_var_from_num(N, &vN);	if (cmp_var(&vN, &const_one) <= 0)	{		free_var(&vN);		PG_RETURN_NULL();	}	init_var(&vNminus1);	sub_var(&vN, &const_one, &vNminus1);	init_var(&vsumX);	set_var_from_num(sumX, &vsumX);	init_var(&vsumX2);	set_var_from_num(sumX2, &vsumX2);	/* compute rscale for mul_var calls */	rscale = vsumX.dscale * 2;	mul_var(&vsumX, &vsumX, &vsumX, rscale);	/* vsumX = sumX * sumX */	mul_var(&vN, &vsumX2, &vsumX2, rscale);		/* vsumX2 = N * sumX2 */	sub_var(&vsumX2, &vsumX, &vsumX2);	/* N * sumX2 - sumX * sumX */	if (cmp_var(&vsumX2, &const_zero) <= 0)	{		/* Watch out for roundoff error producing a negative numerator */		res = make_result(&const_zero);	}	else	{		mul_var(&vN, &vNminus1, &vNminus1, 0);	/* N * (N - 1) */		rscale = select_div_scale(&vsumX2, &vNminus1);		div_var(&vsumX2, &vNminus1, &vsumX, rscale, true);		/* variance */		res = make_result(&vsumX);	}	free_var(&vN);	free_var(&vNminus1);	free_var(&vsumX);	free_var(&vsumX2);	PG_RETURN_NUMERIC(res);}Datumnumeric_stddev(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum	   *transdatums;	int			ndatums;	Numeric		N,				sumX,				sumX2,				res;	NumericVar	vN,				vsumX,				vsumX2,				vNminus1;	int			rscale;	/* We assume the input is array of numeric */	deconstruct_array(transarray,					  NUMERICOID, -1, false, 'i',					  &transdatums, &ndatums);	if (ndatums != 3)		elog(ERROR, "expected 3-element numeric array");	N = DatumGetNumeric(transdatums[0]);	sumX = DatumGetNumeric(transdatums[1]);	sumX2 = DatumGetNumeric(transdatums[2]);	if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))		PG_RETURN_NUMERIC(make_result(&const_nan));	/* Sample stddev is undefined when N is 0 or 1, so return NULL */	init_var(&vN);	set_var_from_num(N, &vN);	if (cmp_var(&vN, &const_one) <= 0)	{		free_var(&vN);		PG_RETURN_NULL();	}	init_var(&vNminus1);	sub_var(&vN, &const_one, &vNminus1);	init_var(&vsumX);	set_var_from_num(sumX, &vsumX);	init_var(&vsumX2);	set_var_from_num(sumX2, &vsumX2);	/* compute rscale for mul_var calls */	rscale = vsumX.dscale * 2;	mul_var(&vsumX, &vsumX, &vsumX, rscale);	/* vsumX = sumX * sumX */	mul_var(&vN, &vsumX2, &vsumX2, rscale);		/* vsumX2 = N * sumX2 */	sub_var(&vsumX2, &vsumX, &vsumX2);	/* N * sumX2 - sumX * sumX */	if (cmp_var(&vsumX2, &const_zero) <= 0)	{		/* Watch out for roundoff error producing a negative numerator */		res = make_result(&const_zero);	}	else	{		mul_var(&vN, &vNminus1, &vNminus1, 0);	/* N * (N - 1) */		rscale = select_div_scale(&vsumX2, &vNminus1);		div_var(&vsumX2, &vNminus1, &vsumX, rscale, true);		/* variance */		sqrt_var(&vsumX, &vsumX, rscale);		/* stddev */		res = make_result(&vsumX);	}

⌨️ 快捷键说明

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