Code

Added initial version of the CData data type.
[postrr.git] / src / cdata.c
1 /*
2  * PostRR - src/cdata.c
3  * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 /*
29  * A PostgreSQL data-type providing consolidated data points.
30  */
32 #include "postrr.h"
34 #include <errno.h>
36 #include <postgres.h>
37 #include <fmgr.h>
39 /* Postgres utilities */
40 #include <utils/array.h>
42 /*
43  * data type
44  */
46 struct cdata {
47         double value;
48         int32 undef_num;
49         int32 val_num;
50         int32 cf;
51 };
53 /*
54  * prototypes for PostgreSQL functions
55  */
57 PG_FUNCTION_INFO_V1(cdata_validate);
59 PG_FUNCTION_INFO_V1(cdata_in);
60 PG_FUNCTION_INFO_V1(cdata_out);
61 PG_FUNCTION_INFO_V1(cdata_typmodin);
62 PG_FUNCTION_INFO_V1(cdata_typmodout);
64 PG_FUNCTION_INFO_V1(cdata_to_cdata);
66 /*
67  * public API
68  */
70 Datum
71 cdata_validate(PG_FUNCTION_ARGS)
72 {
73         char   type_info[1024];
74         char  *result;
75         size_t req_len;
76         size_t len;
78         if (PG_NARGS() != 1)
79                 ereport(ERROR, (
80                                         errmsg("cdata_validate() expect one argument"),
81                                         errhint("Usage cdata_validate(expected_size)")
82                                 ));
84         req_len = (size_t)PG_GETARG_UINT32(0);
85         len = sizeof(cdata_t);
87         if (req_len != len)
88                 ereport(ERROR, (
89                                         errmsg("length of the cdata type "
90                                                 "does not match the expected length"),
91                                         errhint("Please report a bug against PostRR")
92                                 ));
94         snprintf(type_info, sizeof(type_info),
95                         "cdata validated successfully; type length = %zu", len);
96         type_info[sizeof(type_info) - 1] = '\0';
98         result = pstrdup(type_info);
99         PG_RETURN_CSTRING(result);
100 } /* cdata_validate */
102 Datum
103 cdata_in(PG_FUNCTION_ARGS)
105         cdata_t *data;
106         int32 typmod;
108         char *val_str, *orig;
109         char *endptr = NULL;
111         if (PG_NARGS() != 3)
112                 ereport(ERROR, (
113                                         errmsg("cdata_in() expects three arguments"),
114                                         errhint("Usage: cdata_in(col_name, oid, typmod)")
115                                 ));
117         data = (cdata_t *)palloc0(sizeof(*data));
119         val_str = PG_GETARG_CSTRING(0);
120         typmod  = PG_GETARG_INT32(2);
122         orig = val_str;
123         while ((*val_str != '\0') && isspace((int)*val_str))
124                 ++val_str;
126         if (*val_str == '\0')
127                 ereport(ERROR, (
128                                         errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
129                                         errmsg("invalid input syntax for cdata: \"%s\"", orig)
130                                 ));
132         errno = 0;
133         data->value   = strtod(val_str, &endptr);
134         data->val_num = 1;
136         if ((endptr == val_str) || errno)
137                 ereport(ERROR, (
138                                         errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
139                                         errmsg("invalid input syntax for cdata: \"%s\"", orig)
140                                 ));
142         while ((*endptr != '\0') && isspace((int)*endptr))
143                 ereport(ERROR, (
144                                         errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
145                                         errmsg("invalid input syntax for cdata: \"%s\"", orig)
146                                 ));
148         if (typmod > 0)
149                 data->cf = typmod;
150         else
151                 data->cf = 0;
153         PG_RETURN_RRTIMESLICE_P(data);
154 } /* cdata_in */
156 Datum
157 cdata_out(PG_FUNCTION_ARGS)
159         cdata_t *data;
161         char  cd_str[1024];
162         char *result;
164         if (PG_NARGS() != 1)
165                 ereport(ERROR, (
166                                         errmsg("cdata_out() expects one argument"),
167                                         errhint("Usage: cdata_out(cdata)")
168                                 ));
170         data = PG_GETARG_CDATA_P(0);
172         snprintf(cd_str, sizeof(cd_str), "%g (U:%i/%i)",
173                         data->value, data->undef_num, data->val_num);
175         result = pstrdup(cd_str);
176         PG_RETURN_CSTRING(result);
177 } /* cdata_out */
179 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */