Code

Added initial version of the CData data type.
authorSebastian Harl <sh@tokkee.org>
Sat, 28 Apr 2012 17:35:57 +0000 (19:35 +0200)
committerSebastian Harl <sh@tokkee.org>
Sat, 28 Apr 2012 17:35:57 +0000 (19:35 +0200)
For now, the type provides simple input and output functions only.

src/Makefile.pgxs.in
src/cdata.c [new file with mode: 0644]
src/postrr.h.in
src/postrr.sql.in

index 0ccc4f189b508e5c2ceeb79215c1b3a4876543ca..f223061c439fa8fde40b8bdc29cac92cb2d8ff27 100644 (file)
@@ -28,6 +28,7 @@ MODULE_big=postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@
 MODULEDIR=contrib/$(MODULE)
 
 PG_OBJS=base.o \
+               cdata.o \
                rrtimeslice.o \
                utils/pg_spi.o
 
diff --git a/src/cdata.c b/src/cdata.c
new file mode 100644 (file)
index 0000000..b929e3a
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * PostRR - src/cdata.c
+ * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * A PostgreSQL data-type providing consolidated data points.
+ */
+
+#include "postrr.h"
+
+#include <errno.h>
+
+#include <postgres.h>
+#include <fmgr.h>
+
+/* Postgres utilities */
+#include <utils/array.h>
+
+/*
+ * data type
+ */
+
+struct cdata {
+       double value;
+       int32 undef_num;
+       int32 val_num;
+       int32 cf;
+};
+
+/*
+ * prototypes for PostgreSQL functions
+ */
+
+PG_FUNCTION_INFO_V1(cdata_validate);
+
+PG_FUNCTION_INFO_V1(cdata_in);
+PG_FUNCTION_INFO_V1(cdata_out);
+PG_FUNCTION_INFO_V1(cdata_typmodin);
+PG_FUNCTION_INFO_V1(cdata_typmodout);
+
+PG_FUNCTION_INFO_V1(cdata_to_cdata);
+
+/*
+ * public API
+ */
+
+Datum
+cdata_validate(PG_FUNCTION_ARGS)
+{
+       char   type_info[1024];
+       char  *result;
+       size_t req_len;
+       size_t len;
+
+       if (PG_NARGS() != 1)
+               ereport(ERROR, (
+                                       errmsg("cdata_validate() expect one argument"),
+                                       errhint("Usage cdata_validate(expected_size)")
+                               ));
+
+       req_len = (size_t)PG_GETARG_UINT32(0);
+       len = sizeof(cdata_t);
+
+       if (req_len != len)
+               ereport(ERROR, (
+                                       errmsg("length of the cdata type "
+                                               "does not match the expected length"),
+                                       errhint("Please report a bug against PostRR")
+                               ));
+
+       snprintf(type_info, sizeof(type_info),
+                       "cdata validated successfully; type length = %zu", len);
+       type_info[sizeof(type_info) - 1] = '\0';
+
+       result = pstrdup(type_info);
+       PG_RETURN_CSTRING(result);
+} /* cdata_validate */
+
+Datum
+cdata_in(PG_FUNCTION_ARGS)
+{
+       cdata_t *data;
+       int32 typmod;
+
+       char *val_str, *orig;
+       char *endptr = NULL;
+
+       if (PG_NARGS() != 3)
+               ereport(ERROR, (
+                                       errmsg("cdata_in() expects three arguments"),
+                                       errhint("Usage: cdata_in(col_name, oid, typmod)")
+                               ));
+
+       data = (cdata_t *)palloc0(sizeof(*data));
+
+       val_str = PG_GETARG_CSTRING(0);
+       typmod  = PG_GETARG_INT32(2);
+
+       orig = val_str;
+       while ((*val_str != '\0') && isspace((int)*val_str))
+               ++val_str;
+
+       if (*val_str == '\0')
+               ereport(ERROR, (
+                                       errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                       errmsg("invalid input syntax for cdata: \"%s\"", orig)
+                               ));
+
+       errno = 0;
+       data->value   = strtod(val_str, &endptr);
+       data->val_num = 1;
+
+       if ((endptr == val_str) || errno)
+               ereport(ERROR, (
+                                       errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                       errmsg("invalid input syntax for cdata: \"%s\"", orig)
+                               ));
+
+       while ((*endptr != '\0') && isspace((int)*endptr))
+               ereport(ERROR, (
+                                       errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                       errmsg("invalid input syntax for cdata: \"%s\"", orig)
+                               ));
+
+       if (typmod > 0)
+               data->cf = typmod;
+       else
+               data->cf = 0;
+
+       PG_RETURN_RRTIMESLICE_P(data);
+} /* cdata_in */
+
+Datum
+cdata_out(PG_FUNCTION_ARGS)
+{
+       cdata_t *data;
+
+       char  cd_str[1024];
+       char *result;
+
+       if (PG_NARGS() != 1)
+               ereport(ERROR, (
+                                       errmsg("cdata_out() expects one argument"),
+                                       errhint("Usage: cdata_out(cdata)")
+                               ));
+
+       data = PG_GETARG_CDATA_P(0);
+
+       snprintf(cd_str, sizeof(cd_str), "%g (U:%i/%i)",
+                       data->value, data->undef_num, data->val_num);
+
+       result = pstrdup(cd_str);
+       PG_RETURN_CSTRING(result);
+} /* cdata_out */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
index 3db5045169ffe7817244b9ce40137c71665faf64..b2c9ad2483ab65a4a365c1aa86a05c7fed58665e 100644 (file)
@@ -102,6 +102,25 @@ rrtimeslice_cmp(PG_FUNCTION_ARGS);
 int
 rrtimeslice_cmp_internal(rrtimeslice_t *ts1, rrtimeslice_t *ts2);
 
+/*
+ * CData data type
+ */
+
+struct cdata;
+typedef struct cdata cdata_t;
+
+#define PG_GETARG_CDATA_P(n) (cdata_t *)PG_GETARG_POINTER(n)
+#define PG_RETURN_CDATA_P(p) PG_RETURN_POINTER(p)
+
+Datum
+cdata_validate(PG_FUNCTION_ARGS);
+
+/* I/O functions */
+Datum
+cdata_in(PG_FUNCTION_ARGS);
+Datum
+cdata_out(PG_FUNCTION_ARGS);
+
 #endif /* ! POSTRR_H */
 
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */
index bc0d20af0fd810b5f659703abeac4c68786d0cba..22ce15ca3eaa2affab83f5188a30a25244fa63b2 100644 (file)
@@ -198,6 +198,35 @@ CREATE OPERATOR CLASS rrtimeslice_ops
                OPERATOR 5 > ,
                FUNCTION 1 RRTimeslice_cmp(rrtimeslice, rrtimeslice);
 
+CREATE TYPE CData;
+
+CREATE OR REPLACE FUNCTION CData_validate(integer)
+       RETURNS cstring
+       AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'cdata_validate'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- this will abort the transaction in case the expected internal length does
+-- not match the actual length
+SELECT CData_validate(24);
+
+CREATE OR REPLACE FUNCTION CData_in(cstring, oid, integer)
+       RETURNS CData
+       AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'cdata_in'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION CData_out(CData)
+       RETURNS cstring
+       AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'cdata_out'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE TYPE CData (
+       INTERNALLENGTH = 24,
+       INPUT          = CData_in,
+       OUTPUT         = CData_out,
+       ALIGNMENT      = double,
+       STORAGE        = plain
+);
+
 COMMIT;
 
 SET client_min_messages TO DEFAULT;