076b037bbe903d4c73b43528018b21288b6c1486
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)
104 {
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_CDATA_P(data);
154 } /* cdata_in */
156 Datum
157 cdata_out(PG_FUNCTION_ARGS)
158 {
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 : */