diff --git a/src/cdata.c b/src/cdata.c
index 6d202e20da6f525c63c470038f5015edcdd1c001..2630e733d35d10200e9938adc5082ff6bc200ea2 100644 (file)
--- a/src/cdata.c
+++ b/src/cdata.c
PG_FUNCTION_INFO_V1(cdata_typmodout);
PG_FUNCTION_INFO_V1(cdata_to_cdata);
+PG_FUNCTION_INFO_V1(int32_to_cdata);
+PG_FUNCTION_INFO_V1(cdata_to_float8);
+
+PG_FUNCTION_INFO_V1(cdata_update);
/*
* public API
));
while ((*endptr != '\0') && isspace((int)*endptr))
+ ++endptr;
+
+ if (*endptr != '\0')
ereport(ERROR, (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for cdata: \"%s\"", orig)
+ errmsg("invalid input syntax for cdata: \"%s\"", orig),
+ errdetail("garbage found after number: \"%s\"", endptr)
));
if (typmod > 0)
data = PG_GETARG_CDATA_P(0);
- snprintf(cd_str, sizeof(cd_str), "%g (U:%i/%i)",
- data->value, data->undef_num, data->val_num);
+ snprintf(cd_str, sizeof(cd_str), "%g (%s U:%i/%i)",
+ data->value, CF_TO_STR(data->cf),
+ data->undef_num, data->val_num);
result = pstrdup(cd_str);
PG_RETURN_CSTRING(result);
PG_RETURN_CDATA_P(data);
} /* cdata_to_cdata */
+Datum
+int32_to_cdata(PG_FUNCTION_ARGS)
+{
+ int32 i_val;
+ int32 typmod;
+
+ cdata_t *data;
+
+ if (PG_NARGS() != 3)
+ ereport(ERROR, (
+ errmsg("int32_to_cdata() expects three arguments"),
+ errhint("Usage: int32_to_cdata"
+ "(integer, typmod, is_explicit)")
+ ));
+
+ i_val = PG_GETARG_INT32(0);
+ typmod = PG_GETARG_INT32(1);
+
+ data = (cdata_t *)palloc0(sizeof(*data));
+
+ data->value = (float8)i_val;
+ data->undef_num = 0;
+ data->val_num = 1;
+
+ if (typmod >= 0)
+ data->cf = typmod;
+ else
+ data->cf = CF_AVG;
+
+ PG_RETURN_CDATA_P(data);
+} /* int32_to_cdata */
+
+Datum
+cdata_to_float8(PG_FUNCTION_ARGS)
+{
+ cdata_t *data;
+
+ if (PG_NARGS() != 1)
+ ereport(ERROR, (
+ errmsg("cdata_to_float8() expects one argument"),
+ errhint("Usage: cdata_to_float8(cdata)")
+ ));
+
+ data = PG_GETARG_CDATA_P(0);
+ PG_RETURN_FLOAT8(data->value);
+} /* cdata_to_float8 */
+
+Datum
+cdata_update(PG_FUNCTION_ARGS)
+{
+ cdata_t *data;
+ cdata_t *update;
+
+ if (PG_NARGS() != 2)
+ ereport(ERROR, (
+ errmsg("cdata_update() expects two arguments"),
+ errhint("Usage: cdata_update(cdata, cdata)")
+ ));
+
+ data = PG_GETARG_CDATA_P(0);
+ update = PG_GETARG_CDATA_P(1);
+
+ if (! data)
+ PG_RETURN_CDATA_P(update);
+
+ if (! update)
+ PG_RETURN_CDATA_P(data);
+
+ if ((data->cf != update->cf) && (update->val_num > 1))
+ ereport(ERROR, (
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid update value: incompatible "
+ "consolidation function")
+ ));
+
+ switch (data->cf) {
+ case CF_AVG:
+ data->value = (data->value * (data->val_num - data->undef_num))
+ + (update->value * (update->val_num - update->undef_num));
+ data->value /= (data->val_num - data->undef_num)
+ + (update->val_num - update->undef_num);
+ break;
+ case CF_MIN:
+ data->value = (data->value <= update->value)
+ ? data->value : update->value;
+ break;
+ case CF_MAX:
+ data->value = (data->value >= update->value)
+ ? data->value : update->value;
+ break;
+ default:
+ ereport(ERROR, (
+ errcode(ERRCODE_DATA_CORRUPTED),
+ errmsg("unknown consolidation function %d",
+ data->cf)
+ ));
+ break;
+ }
+
+ data->undef_num += update->undef_num;
+ data->val_num += update->val_num;
+ PG_RETURN_CDATA_P(data);
+} /* cdata_update */
+
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */