summaryrefslogtreecommitdiff
path: root/src/pq
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-02-05 22:24:10 +0000
committerChristian Grothoff <christian@grothoff.org>2016-02-05 22:24:10 +0000
commitd75a2de4e9a450269291a47593f2e50c37eca733 (patch)
tree915d9cf6f76d8cfb2e7fb80f948aa362e72a944f /src/pq
parent522bd40f4cee9e5546d15128f76d18799017220c (diff)
downloadgnunet-d75a2de4e9a450269291a47593f2e50c37eca733.tar.gz
gnunet-d75a2de4e9a450269291a47593f2e50c37eca733.zip
creating libgnunetpq library
Diffstat (limited to 'src/pq')
-rw-r--r--src/pq/Makefile.am39
-rw-r--r--src/pq/pq.c169
-rw-r--r--src/pq/pq_query_helper.c386
-rw-r--r--src/pq/pq_result_helper.c674
-rw-r--r--src/pq/test_pq.c288
5 files changed, 1556 insertions, 0 deletions
diff --git a/src/pq/Makefile.am b/src/pq/Makefile.am
new file mode 100644
index 000000000..66f57838e
--- /dev/null
+++ b/src/pq/Makefile.am
@@ -0,0 +1,39 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS)
3
4if MINGW
5 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
6endif
7
8if USE_COVERAGE
9 AM_CFLAGS = --coverage
10endif
11
12if HAVE_POSTGRESQL
13lib_LTLIBRARIES = libgnunetpq.la
14endif
15
16libgnunetpq_la_SOURCES = \
17 pq.c \
18 pq_query_helper.c \
19 pq_result_helper.c
20libgnunetpq_la_LIBADD = -lpq \
21 $(top_builddir)/src/util/libgnunetutil.la
22libgnunetpq_la_LDFLAGS = \
23 $(POSTGRESQL_LDFLAGS) \
24 $(GN_LIB_LDFLAGS) \
25 -version-info 0:0:0
26
27
28TESTS = \
29 test_pq
30
31check_PROGRAMS= \
32 test_pq
33
34test_pq_SOURCES = \
35 test_pq.c
36test_pq_LDADD = \
37 libgnunetpq.la \
38 $(top_builddir)/src/util/libgnunetutil.la \
39 -lpq $(XLIB)
diff --git a/src/pq/pq.c b/src/pq/pq.c
new file mode 100644
index 000000000..fe796044e
--- /dev/null
+++ b/src/pq/pq.c
@@ -0,0 +1,169 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file pq/pq.c
18 * @brief helper functions for libpq (PostGres) interactions
19 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
20 * @author Florian Dold
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include "gnunet_pq_lib.h"
26
27
28/**
29 * Execute a prepared statement.
30 *
31 * @param db_conn database connection
32 * @param name name of the prepared statement
33 * @param params parameters to the statement
34 * @return postgres result
35 */
36PGresult *
37GNUNET_PQ_exec_prepared (PGconn *db_conn,
38 const char *name,
39 const struct GNUNET_PQ_QueryParam *params)
40{
41 unsigned int len;
42 unsigned int i;
43
44 /* count the number of parameters */
45 len = 0;
46 for (i=0;0 != params[i].num_params;i++)
47 len += params[i].num_params;
48
49 /* new scope to allow stack allocation without alloca */
50 {
51 /* Scratch buffer for temporary storage */
52 void *scratch[len];
53 /* Parameter array we are building for the query */
54 void *param_values[len];
55 int param_lengths[len];
56 int param_formats[len];
57 unsigned int off;
58 /* How many entries in the scratch buffer are in use? */
59 unsigned int soff;
60 PGresult *res;
61 int ret;
62
63 off = 0;
64 soff = 0;
65 for (i=0;0 != params[i].num_params;i++)
66 {
67 const struct GNUNET_PQ_QueryParam *x = &params[i];
68
69 ret = x->conv (x->conv_cls,
70 x->data,
71 x->size,
72 &param_values[off],
73 &param_lengths[off],
74 &param_formats[off],
75 x->num_params,
76 &scratch[soff],
77 len - soff);
78 if (ret < 0)
79 {
80 for (off = 0; off < soff; off++)
81 GNUNET_free (scratch[off]);
82 return NULL;
83 }
84 soff += ret;
85 off += x->num_params;
86 }
87 GNUNET_assert (off == len);
88 res = PQexecPrepared (db_conn,
89 name,
90 len,
91 (const char **) param_values,
92 param_lengths,
93 param_formats,
94 1);
95 for (off = 0; off < soff; off++)
96 GNUNET_free (scratch[off]);
97 return res;
98 }
99}
100
101
102/**
103 * Free all memory that was allocated in @a rs during
104 * #GNUNET_PQ_extract_result().
105 *
106 * @param rs reult specification to clean up
107 */
108void
109GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs)
110{
111 unsigned int i;
112
113 for (i=0; NULL != rs[i].conv; i++)
114 if (NULL != rs[i].cleaner)
115 rs[i].cleaner (rs[i].cls,
116 rs[i].dst);
117}
118
119
120/**
121 * Extract results from a query result according to the given
122 * specification. If colums are NULL, the destination is not
123 * modified, and #GNUNET_NO is returned.
124 *
125 * @param result result to process
126 * @param[in,out] rs result specification to extract for
127 * @param row row from the result to extract
128 * @return
129 * #GNUNET_YES if all results could be extracted
130 * #GNUNET_NO if at least one result was NULL
131 * #GNUNET_SYSERR if a result was invalid (non-existing field)
132 */
133int
134GNUNET_PQ_extract_result (PGresult *result,
135 struct GNUNET_PQ_ResultSpec *rs,
136 int row)
137{
138 unsigned int i;
139 int had_null = GNUNET_NO;
140 int ret;
141
142 for (i=0; NULL != rs[i].conv; i++)
143 {
144 struct GNUNET_PQ_ResultSpec *spec;
145
146 spec = &rs[i];
147 ret = spec->conv (spec->cls,
148 result,
149 row,
150 spec->fname,
151 &spec->dst_size,
152 spec->dst);
153 if (GNUNET_SYSERR == ret)
154 return GNUNET_SYSERR;
155 if (GNUNET_NO == ret)
156 {
157 had_null = GNUNET_YES;
158 continue;
159 }
160 if (NULL != spec->result_size)
161 *spec->result_size = spec->dst_size;
162 }
163 if (GNUNET_YES == had_null)
164 return GNUNET_NO;
165 return GNUNET_OK;
166}
167
168
169/* end of pq/pq.c */
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
new file mode 100644
index 000000000..5f2764b62
--- /dev/null
+++ b/src/pq/pq_query_helper.c
@@ -0,0 +1,386 @@
1 /*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file pq/pq_query_helper.c
18 * @brief functions to initialize parameter arrays
19 * @author Christian Grothoff
20 */
21#include "platform.h"
22#include <gnunet/gnunet_util_lib.h>
23#include "gnunet_pq_lib.h"
24
25
26/**
27 * Function called to convert input argument into SQL parameters.
28 *
29 * @param cls closure
30 * @param data pointer to input argument
31 * @param data_len number of bytes in @a data (if applicable)
32 * @param[out] param_values SQL data to set
33 * @param[out] param_lengths SQL length data to set
34 * @param[out] param_formats SQL format data to set
35 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
36 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
37 * @param scratch_length number of entries left in @a scratch
38 * @return -1 on error, number of offsets used in @a scratch otherwise
39 */
40static int
41qconv_fixed (void *cls,
42 const void *data,
43 size_t data_len,
44 void *param_values[],
45 int param_lengths[],
46 int param_formats[],
47 unsigned int param_length,
48 void *scratch[],
49 unsigned int scratch_length)
50{
51 GNUNET_break (NULL == cls);
52 if (1 != param_length)
53 return -1;
54 param_values[0] = (void *) data;
55 param_lengths[0] = data_len;
56 param_formats[0] = 1;
57 return 0;
58}
59
60
61/**
62 * Generate query parameter for a buffer @a ptr of
63 * @a ptr_size bytes.
64 *
65 * @param ptr pointer to the query parameter to pass
66 * @oaran ptr_size number of bytes in @a ptr
67 */
68struct GNUNET_PQ_QueryParam
69GNUNET_PQ_query_param_fixed_size (const void *ptr,
70 size_t ptr_size)
71{
72 struct GNUNET_PQ_QueryParam res =
73 { &qconv_fixed, NULL, ptr, ptr_size, 1 };
74 return res;
75}
76
77
78/**
79 * Function called to convert input argument into SQL parameters.
80 *
81 * @param cls closure
82 * @param data pointer to input argument
83 * @param data_len number of bytes in @a data (if applicable)
84 * @param[out] param_values SQL data to set
85 * @param[out] param_lengths SQL length data to set
86 * @param[out] param_formats SQL format data to set
87 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
88 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
89 * @param scratch_length number of entries left in @a scratch
90 * @return -1 on error, number of offsets used in @a scratch otherwise
91 */
92static int
93qconv_uint16 (void *cls,
94 const void *data,
95 size_t data_len,
96 void *param_values[],
97 int param_lengths[],
98 int param_formats[],
99 unsigned int param_length,
100 void *scratch[],
101 unsigned int scratch_length)
102{
103 const uint16_t *u_hbo = data;
104 uint16_t *u_nbo;
105
106 GNUNET_break (NULL == cls);
107 if (1 != param_length)
108 return -1;
109 u_nbo = GNUNET_new (uint16_t);
110 scratch[0] = u_nbo;
111 *u_nbo = htons (*u_hbo);
112 param_values[0] = (void *) u_nbo;
113 param_lengths[0] = sizeof (uint16_t);
114 param_formats[0] = 1;
115 return 1;
116}
117
118
119/**
120 * Generate query parameter for an uint16_t in host byte order.
121 *
122 * @param x pointer to the query parameter to pass
123 */
124struct GNUNET_PQ_QueryParam
125GNUNET_PQ_query_param_uint16 (const uint16_t *x)
126{
127 struct GNUNET_PQ_QueryParam res =
128 { &qconv_uint16, NULL, x, sizeof (*x), 1 };
129 return res;
130}
131
132
133/**
134 * Function called to convert input argument into SQL parameters.
135 *
136 * @param cls closure
137 * @param data pointer to input argument
138 * @param data_len number of bytes in @a data (if applicable)
139 * @param[out] param_values SQL data to set
140 * @param[out] param_lengths SQL length data to set
141 * @param[out] param_formats SQL format data to set
142 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
143 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
144 * @param scratch_length number of entries left in @a scratch
145 * @return -1 on error, number of offsets used in @a scratch otherwise
146 */
147static int
148qconv_uint32 (void *cls,
149 const void *data,
150 size_t data_len,
151 void *param_values[],
152 int param_lengths[],
153 int param_formats[],
154 unsigned int param_length,
155 void *scratch[],
156 unsigned int scratch_length)
157{
158 const uint32_t *u_hbo = data;
159 uint32_t *u_nbo;
160
161 GNUNET_break (NULL == cls);
162 if (1 != param_length)
163 return -1;
164 u_nbo = GNUNET_new (uint32_t);
165 scratch[0] = u_nbo;
166 *u_nbo = htonl (*u_hbo);
167 param_values[0] = (void *) u_nbo;
168 param_lengths[0] = sizeof (uint32_t);
169 param_formats[0] = 1;
170 return 1;
171}
172
173
174/**
175 * Generate query parameter for an uint32_t in host byte order.
176 *
177 * @param x pointer to the query parameter to pass
178 */
179struct GNUNET_PQ_QueryParam
180GNUNET_PQ_query_param_uint32 (const uint32_t *x)
181{
182 struct GNUNET_PQ_QueryParam res =
183 { &qconv_uint32, NULL, x, sizeof (*x), 1 };
184 return res;
185}
186
187
188/**
189 * Function called to convert input argument into SQL parameters.
190 *
191 * @param cls closure
192 * @param data pointer to input argument
193 * @param data_len number of bytes in @a data (if applicable)
194 * @param[out] param_values SQL data to set
195 * @param[out] param_lengths SQL length data to set
196 * @param[out] param_formats SQL format data to set
197 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
198 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
199 * @param scratch_length number of entries left in @a scratch
200 * @return -1 on error, number of offsets used in @a scratch otherwise
201 */
202static int
203qconv_uint64 (void *cls,
204 const void *data,
205 size_t data_len,
206 void *param_values[],
207 int param_lengths[],
208 int param_formats[],
209 unsigned int param_length,
210 void *scratch[],
211 unsigned int scratch_length)
212{
213 const uint64_t *u_hbo = data;
214 uint64_t *u_nbo;
215
216 GNUNET_break (NULL == cls);
217 if (1 != param_length)
218 return -1;
219 u_nbo = GNUNET_new (uint64_t);
220 scratch[0] = u_nbo;
221 *u_nbo = GNUNET_htonll (*u_hbo);
222 param_values[0] = (void *) u_nbo;
223 param_lengths[0] = sizeof (uint64_t);
224 param_formats[0] = 1;
225 return 1;
226}
227
228
229/**
230 * Generate query parameter for an uint64_t in host byte order.
231 *
232 * @param x pointer to the query parameter to pass
233 */
234struct GNUNET_PQ_QueryParam
235GNUNET_PQ_query_param_uint64 (const uint64_t *x)
236{
237 struct GNUNET_PQ_QueryParam res =
238 { &qconv_uint64, NULL, x, sizeof (*x), 1 };
239 return res;
240}
241
242
243/**
244 * Function called to convert input argument into SQL parameters.
245 *
246 * @param cls closure
247 * @param data pointer to input argument
248 * @param data_len number of bytes in @a data (if applicable)
249 * @param[out] param_values SQL data to set
250 * @param[out] param_lengths SQL length data to set
251 * @param[out] param_formats SQL format data to set
252 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
253 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
254 * @param scratch_length number of entries left in @a scratch
255 * @return -1 on error, number of offsets used in @a scratch otherwise
256 */
257static int
258qconv_rsa_public_key (void *cls,
259 const void *data,
260 size_t data_len,
261 void *param_values[],
262 int param_lengths[],
263 int param_formats[],
264 unsigned int param_length,
265 void *scratch[],
266 unsigned int scratch_length)
267{
268 const struct GNUNET_CRYPTO_rsa_PublicKey *rsa = data;
269 char *buf;
270 size_t buf_size;
271
272 GNUNET_break (NULL == cls);
273 if (1 != param_length)
274 return -1;
275 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa,
276 &buf);
277 scratch[0] = buf;
278 param_values[0] = (void *) buf;
279 param_lengths[0] = buf_size - 1; /* DB doesn't like the trailing \0 */
280 param_formats[0] = 1;
281 return 1;
282}
283
284
285/**
286 * Generate query parameter for an RSA public key. The
287 * database must contain a BLOB type in the respective position.
288 *
289 * @param x the query parameter to pass
290 * @return array entry for the query parameters to use
291 */
292struct GNUNET_PQ_QueryParam
293GNUNET_PQ_query_param_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *x)
294{
295 struct GNUNET_PQ_QueryParam res =
296 { &qconv_rsa_public_key, NULL, (x), 0, 1 };
297 return res;
298}
299
300
301/**
302 * Function called to convert input argument into SQL parameters.
303 *
304 * @param cls closure
305 * @param data pointer to input argument
306 * @param data_len number of bytes in @a data (if applicable)
307 * @param[out] param_values SQL data to set
308 * @param[out] param_lengths SQL length data to set
309 * @param[out] param_formats SQL format data to set
310 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
311 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
312 * @param scratch_length number of entries left in @a scratch
313 * @return -1 on error, number of offsets used in @a scratch otherwise
314 */
315static int
316qconv_rsa_signature (void *cls,
317 const void *data,
318 size_t data_len,
319 void *param_values[],
320 int param_lengths[],
321 int param_formats[],
322 unsigned int param_length,
323 void *scratch[],
324 unsigned int scratch_length)
325{
326 const struct GNUNET_CRYPTO_rsa_Signature *sig = data;
327 char *buf;
328 size_t buf_size;
329
330 GNUNET_break (NULL == cls);
331 if (1 != param_length)
332 return -1;
333 buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig,
334 &buf);
335 scratch[0] = buf;
336 param_values[0] = (void *) buf;
337 param_lengths[0] = buf_size - 1; /* DB doesn't like the trailing \0 */
338 param_formats[0] = 1;
339 return 1;
340}
341
342
343/**
344 * Generate query parameter for an RSA signature. The
345 * database must contain a BLOB type in the respective position.
346 *
347 * @param x the query parameter to pass
348 * @return array entry for the query parameters to use
349 */
350struct GNUNET_PQ_QueryParam
351GNUNET_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *x)
352{
353 struct GNUNET_PQ_QueryParam res =
354 { &qconv_rsa_signature, NULL, (x), 0, 1 };
355 return res;
356}
357
358
359/**
360 * Generate query parameter for an absolute time value.
361 * The database must store a 64-bit integer.
362 *
363 * @param x pointer to the query parameter to pass
364 * @return array entry for the query parameters to use
365 */
366struct GNUNET_PQ_QueryParam
367GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
368{
369 return GNUNET_PQ_query_param_uint64 (&x->abs_value_us);
370}
371
372
373/**
374 * Generate query parameter for an absolute time value.
375 * The database must store a 64-bit integer.
376 *
377 * @param x pointer to the query parameter to pass
378 */
379struct GNUNET_PQ_QueryParam
380GNUNET_PQ_query_param_absolute_time_nbo(const struct GNUNET_TIME_AbsoluteNBO *x)
381{
382 return GNUNET_PQ_query_param_auto_from_type (&x->abs_value_us__);
383}
384
385
386/* end of pq_query_helper.c */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
new file mode 100644
index 000000000..dc5700730
--- /dev/null
+++ b/src/pq/pq_result_helper.c
@@ -0,0 +1,674 @@
1 /*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file pq/pq_result_helper.c
18 * @brief functions to extract result values
19 * @author Christian Grothoff
20 */
21#include "platform.h"
22#include <gnunet/gnunet_util_lib.h>
23#include "gnunet_pq_lib.h"
24
25
26/**
27 * Function called to clean up memory allocated
28 * by a #GNUNET_PQ_ResultConverter.
29 *
30 * @param cls closure
31 * @param rd result data to clean up
32 */
33static void
34clean_varsize_blob (void *cls,
35 void *rd)
36{
37 void **dst = rd;
38
39 if (NULL != *dst)
40 {
41 GNUNET_free (*dst);
42 *dst = NULL;
43 }
44}
45
46
47/**
48 * Extract data from a Postgres database @a result at row @a row.
49 *
50 * @param cls closure
51 * @param result where to extract data from
52 * @param int row to extract data from
53 * @param fname name (or prefix) of the fields to extract from
54 * @param[in,out] dst_size where to store size of result, may be NULL
55 * @param[out] dst where to store the result
56 * @return
57 * #GNUNET_YES if all results could be extracted
58 * #GNUNET_NO if at least one result was NULL
59 * #GNUNET_SYSERR if a result was invalid (non-existing field)
60 */
61static int
62extract_varsize_blob (void *cls,
63 PGresult *result,
64 int row,
65 const char *fname,
66 size_t *dst_size,
67 void *dst)
68{
69 size_t len;
70 const char *res;
71 void *idst;
72 int fnum;
73
74 fnum = PQfnumber (result,
75 fname);
76 if (fnum < 0)
77 {
78 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
79 "Field `%s' does not exist in result\n",
80 fname);
81 return GNUNET_SYSERR;
82 }
83 if (PQgetisnull (result,
84 row,
85 fnum))
86 return GNUNET_NO;
87
88 /* if a field is null, continue but
89 * remember that we now return a different result */
90 len = PQgetlength (result,
91 row,
92 fnum);
93 res = PQgetvalue (result,
94 row,
95 fnum);
96 GNUNET_assert (NULL != res);
97 *dst_size = len;
98 idst = GNUNET_malloc (len);
99 *((void **) dst) = idst;
100 memcpy (idst,
101 res,
102 len);
103 return GNUNET_OK;
104}
105
106
107/**
108 * Variable-size result expected.
109 *
110 * @param name name of the field in the table
111 * @param[out] dst where to store the result, allocated
112 * @param[out] sptr where to store the size of @a dst
113 * @return array entry for the result specification to use
114 */
115struct GNUNET_PQ_ResultSpec
116GNUNET_PQ_result_spec_variable_size (const char *name,
117 void **dst,
118 size_t *sptr)
119{
120 struct GNUNET_PQ_ResultSpec res =
121 { &extract_varsize_blob,
122 &clean_varsize_blob, NULL,
123 (void *) (dst), 0, name, sptr };
124 return res;
125}
126
127
128/**
129 * Extract data from a Postgres database @a result at row @a row.
130 *
131 * @param cls closure
132 * @param result where to extract data from
133 * @param int row to extract data from
134 * @param fname name (or prefix) of the fields to extract from
135 * @param[in] dst_size desired size, never NULL
136 * @param[out] dst where to store the result
137 * @return
138 * #GNUNET_YES if all results could be extracted
139 * #GNUNET_NO if at least one result was NULL
140 * #GNUNET_SYSERR if a result was invalid (non-existing field)
141 */
142static int
143extract_fixed_blob (void *cls,
144 PGresult *result,
145 int row,
146 const char *fname,
147 size_t *dst_size,
148 void *dst)
149{
150 size_t len;
151 const char *res;
152 int fnum;
153
154 fnum = PQfnumber (result,
155 fname);
156 if (fnum < 0)
157 {
158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
159 "Field `%s' does not exist in result\n",
160 fname);
161 return GNUNET_SYSERR;
162 }
163 if (PQgetisnull (result,
164 row,
165 fnum))
166 return GNUNET_NO;
167
168 /* if a field is null, continue but
169 * remember that we now return a different result */
170 len = PQgetlength (result,
171 row,
172 fnum);
173 if (*dst_size != len)
174 {
175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
176 "Field `%s' has wrong size (got %u, expected %u)\n",
177 fname,
178 (unsigned int) len,
179 (unsigned int) *dst_size);
180 return GNUNET_SYSERR;
181 }
182 res = PQgetvalue (result,
183 row,
184 fnum);
185 GNUNET_assert (NULL != res);
186 memcpy (dst,
187 res,
188 len);
189 return GNUNET_OK;
190}
191
192
193/**
194 * Fixed-size result expected.
195 *
196 * @param name name of the field in the table
197 * @param[out] dst where to store the result
198 * @param dst_size number of bytes in @a dst
199 * @return array entry for the result specification to use
200 */
201struct GNUNET_PQ_ResultSpec
202GNUNET_PQ_result_spec_fixed_size (const char *name,
203 void *dst,
204 size_t dst_size)
205{
206 struct GNUNET_PQ_ResultSpec res =
207 { &extract_fixed_blob,
208 NULL, NULL,
209 (dst), dst_size, name, NULL };
210 return res;
211}
212
213
214/**
215 * Extract data from a Postgres database @a result at row @a row.
216 *
217 * @param cls closure
218 * @param result where to extract data from
219 * @param int row to extract data from
220 * @param fname name (or prefix) of the fields to extract from
221 * @param[in,out] dst_size where to store size of result, may be NULL
222 * @param[out] dst where to store the result
223 * @return
224 * #GNUNET_YES if all results could be extracted
225 * #GNUNET_NO if at least one result was NULL
226 * #GNUNET_SYSERR if a result was invalid (non-existing field)
227 */
228static int
229extract_rsa_public_key (void *cls,
230 PGresult *result,
231 int row,
232 const char *fname,
233 size_t *dst_size,
234 void *dst)
235{
236 struct GNUNET_CRYPTO_rsa_PublicKey **pk = dst;
237 size_t len;
238 const char *res;
239 int fnum;
240
241 *pk = NULL;
242 fnum = PQfnumber (result,
243 fname);
244 if (fnum < 0)
245 {
246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
247 "Field `%s' does not exist in result\n",
248 fname);
249 return GNUNET_SYSERR;
250 }
251 if (PQgetisnull (result,
252 row,
253 fnum))
254 return GNUNET_NO;
255
256 /* if a field is null, continue but
257 * remember that we now return a different result */
258 len = PQgetlength (result,
259 row,
260 fnum);
261 res = PQgetvalue (result,
262 row,
263 fnum);
264 *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
265 len);
266 if (NULL == *pk)
267 {
268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
269 "Field `%s' contains bogus value (fails to decode)\n",
270 fname);
271 return GNUNET_SYSERR;
272 }
273 return GNUNET_OK;
274}
275
276
277/**
278 * Function called to clean up memory allocated
279 * by a #GNUNET_PQ_ResultConverter.
280 *
281 * @param cls closure
282 * @param rd result data to clean up
283 */
284static void
285clean_rsa_public_key (void *cls,
286 void *rd)
287{
288 struct GNUNET_CRYPTO_rsa_PublicKey **pk = rd;
289
290 if (NULL != *pk)
291 {
292 GNUNET_CRYPTO_rsa_public_key_free (*pk);
293 *pk = NULL;
294 }
295}
296
297
298/**
299 * RSA public key expected.
300 *
301 * @param name name of the field in the table
302 * @param[out] rsa where to store the result
303 * @return array entry for the result specification to use
304 */
305struct GNUNET_PQ_ResultSpec
306GNUNET_PQ_result_spec_rsa_public_key (const char *name,
307 struct GNUNET_CRYPTO_rsa_PublicKey **rsa)
308{
309 struct GNUNET_PQ_ResultSpec res =
310 { &extract_rsa_public_key,
311 &clean_rsa_public_key,
312 NULL,
313 (void *) rsa, 0, name, NULL };
314 return res;
315}
316
317
318/**
319 * Extract data from a Postgres database @a result at row @a row.
320 *
321 * @param cls closure
322 * @param result where to extract data from
323 * @param int row to extract data from
324 * @param fname name (or prefix) of the fields to extract from
325 * @param[in,out] dst_size where to store size of result, may be NULL
326 * @param[out] dst where to store the result
327 * @return
328 * #GNUNET_YES if all results could be extracted
329 * #GNUNET_NO if at least one result was NULL
330 * #GNUNET_SYSERR if a result was invalid (non-existing field)
331 */
332static int
333extract_rsa_signature (void *cls,
334 PGresult *result,
335 int row,
336 const char *fname,
337 size_t *dst_size,
338 void *dst)
339{
340 struct GNUNET_CRYPTO_rsa_Signature **sig = dst;
341 size_t len;
342 const char *res;
343 int fnum;
344
345 *sig = NULL;
346 fnum = PQfnumber (result,
347 fname);
348 if (fnum < 0)
349 {
350 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
351 "Field `%s' does not exist in result\n",
352 fname);
353 return GNUNET_SYSERR;
354 }
355 if (PQgetisnull (result,
356 row,
357 fnum))
358 return GNUNET_NO;
359
360 /* if a field is null, continue but
361 * remember that we now return a different result */
362 len = PQgetlength (result,
363 row,
364 fnum);
365 res = PQgetvalue (result,
366 row,
367 fnum);
368 *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
369 len);
370 if (NULL == *sig)
371 {
372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
373 "Field `%s' contains bogus value (fails to decode)\n",
374 fname);
375 return GNUNET_SYSERR;
376 }
377 return GNUNET_OK;
378}
379
380
381/**
382 * Function called to clean up memory allocated
383 * by a #GNUNET_PQ_ResultConverter.
384 *
385 * @param cls closure
386 * @param rd result data to clean up
387 */
388static void
389clean_rsa_signature (void *cls,
390 void *rd)
391{
392 struct GNUNET_CRYPTO_rsa_Signature **sig = rd;
393
394 if (NULL != *sig)
395 {
396 GNUNET_CRYPTO_rsa_signature_free (*sig);
397 *sig = NULL;
398 }
399}
400
401
402/**
403 * RSA signature expected.
404 *
405 * @param name name of the field in the table
406 * @param[out] sig where to store the result;
407 * @return array entry for the result specification to use
408 */
409struct GNUNET_PQ_ResultSpec
410GNUNET_PQ_result_spec_rsa_signature (const char *name,
411 struct GNUNET_CRYPTO_rsa_Signature **sig)
412{
413 struct GNUNET_PQ_ResultSpec res =
414 { &extract_rsa_signature,
415 &clean_rsa_signature,
416 NULL,
417 (void *) sig, 0, (name), NULL };
418 return res;
419}
420
421
422/**
423 * Absolute time expected.
424 *
425 * @param name name of the field in the table
426 * @param[out] at where to store the result
427 * @return array entry for the result specification to use
428 */
429struct GNUNET_PQ_ResultSpec
430GNUNET_PQ_result_spec_absolute_time (const char *name,
431 struct GNUNET_TIME_Absolute *at)
432{
433 return GNUNET_PQ_result_spec_uint64 (name,
434 &at->abs_value_us);
435}
436
437
438/**
439 * Absolute time in network byte order expected.
440 *
441 * @param name name of the field in the table
442 * @param[out] at where to store the result
443 * @return array entry for the result specification to use
444 */
445struct GNUNET_PQ_ResultSpec
446GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
447 struct GNUNET_TIME_AbsoluteNBO *at)
448{
449 struct GNUNET_PQ_ResultSpec res =
450 GNUNET_PQ_result_spec_auto_from_type(name, &at->abs_value_us__);
451 return res;
452}
453
454
455/**
456 * Extract data from a Postgres database @a result at row @a row.
457 *
458 * @param cls closure
459 * @param result where to extract data from
460 * @param int row to extract data from
461 * @param fname name (or prefix) of the fields to extract from
462 * @param[in,out] dst_size where to store size of result, may be NULL
463 * @param[out] dst where to store the result
464 * @return
465 * #GNUNET_YES if all results could be extracted
466 * #GNUNET_NO if at least one result was NULL
467 * #GNUNET_SYSERR if a result was invalid (non-existing field)
468 */
469static int
470extract_uint16 (void *cls,
471 PGresult *result,
472 int row,
473 const char *fname,
474 size_t *dst_size,
475 void *dst)
476{
477 uint16_t *udst = dst;
478 const uint16_t *res;
479 int fnum;
480
481 fnum = PQfnumber (result,
482 fname);
483 if (fnum < 0)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
486 "Field `%s' does not exist in result\n",
487 fname);
488 return GNUNET_SYSERR;
489 }
490 if (PQgetisnull (result,
491 row,
492 fnum))
493 return GNUNET_NO;
494 GNUNET_assert (NULL != dst);
495 if (sizeof (uint16_t) != *dst_size)
496 {
497 GNUNET_break (0);
498 return GNUNET_SYSERR;
499 }
500 res = (uint16_t *) PQgetvalue (result,
501 row,
502 fnum);
503 *udst = ntohs (*res);
504 return GNUNET_OK;
505}
506
507
508/**
509 * uint16_t expected.
510 *
511 * @param name name of the field in the table
512 * @param[out] u16 where to store the result
513 * @return array entry for the result specification to use
514 */
515struct GNUNET_PQ_ResultSpec
516GNUNET_PQ_result_spec_uint16 (const char *name,
517 uint16_t *u16)
518{
519 struct GNUNET_PQ_ResultSpec res =
520 { &extract_uint16,
521 NULL,
522 NULL,
523 (void *) u16, sizeof (*u16), (name), NULL };
524 return res;
525}
526
527
528/**
529 * Extract data from a Postgres database @a result at row @a row.
530 *
531 * @param cls closure
532 * @param result where to extract data from
533 * @param int row to extract data from
534 * @param fname name (or prefix) of the fields to extract from
535 * @param[in,out] dst_size where to store size of result, may be NULL
536 * @param[out] dst where to store the result
537 * @return
538 * #GNUNET_YES if all results could be extracted
539 * #GNUNET_NO if at least one result was NULL
540 * #GNUNET_SYSERR if a result was invalid (non-existing field)
541 */
542static int
543extract_uint32 (void *cls,
544 PGresult *result,
545 int row,
546 const char *fname,
547 size_t *dst_size,
548 void *dst)
549{
550 uint32_t *udst = dst;
551 const uint32_t *res;
552 int fnum;
553
554 fnum = PQfnumber (result,
555 fname);
556 if (fnum < 0)
557 {
558 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
559 "Field `%s' does not exist in result\n",
560 fname);
561 return GNUNET_SYSERR;
562 }
563 if (PQgetisnull (result,
564 row,
565 fnum))
566 return GNUNET_NO;
567 GNUNET_assert (NULL != dst);
568 if (sizeof (uint32_t) != *dst_size)
569 {
570 GNUNET_break (0);
571 return GNUNET_SYSERR;
572 }
573 res = (uint32_t *) PQgetvalue (result,
574 row,
575 fnum);
576 *udst = ntohl (*res);
577 return GNUNET_OK;
578}
579
580
581/**
582 * uint32_t expected.
583 *
584 * @param name name of the field in the table
585 * @param[out] u32 where to store the result
586 * @return array entry for the result specification to use
587 */
588struct GNUNET_PQ_ResultSpec
589GNUNET_PQ_result_spec_uint32 (const char *name,
590 uint32_t *u32)
591{
592 struct GNUNET_PQ_ResultSpec res =
593 { &extract_uint32,
594 NULL,
595 NULL,
596 (void *) u32, sizeof (*u32), (name), NULL };
597 return res;
598}
599
600
601/**
602 * Extract data from a Postgres database @a result at row @a row.
603 *
604 * @param cls closure
605 * @param result where to extract data from
606 * @param int row to extract data from
607 * @param fname name (or prefix) of the fields to extract from
608 * @param[in,out] dst_size where to store size of result, may be NULL
609 * @param[out] dst where to store the result
610 * @return
611 * #GNUNET_YES if all results could be extracted
612 * #GNUNET_NO if at least one result was NULL
613 * #GNUNET_SYSERR if a result was invalid (non-existing field)
614 */
615static int
616extract_uint64 (void *cls,
617 PGresult *result,
618 int row,
619 const char *fname,
620 size_t *dst_size,
621 void *dst)
622{
623 uint64_t *udst = dst;
624 const uint64_t *res;
625 int fnum;
626
627 fnum = PQfnumber (result,
628 fname);
629 if (fnum < 0)
630 {
631 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
632 "Field `%s' does not exist in result\n",
633 fname);
634 return GNUNET_SYSERR;
635 }
636 if (PQgetisnull (result,
637 row,
638 fnum))
639 return GNUNET_NO;
640 GNUNET_assert (NULL != dst);
641 if (sizeof (uint64_t) != *dst_size)
642 {
643 GNUNET_break (0);
644 return GNUNET_SYSERR;
645 }
646 res = (uint64_t *) PQgetvalue (result,
647 row,
648 fnum);
649 *udst = GNUNET_ntohll (*res);
650 return GNUNET_OK;
651}
652
653
654/**
655 * uint64_t expected.
656 *
657 * @param name name of the field in the table
658 * @param[out] u64 where to store the result
659 * @return array entry for the result specification to use
660 */
661struct GNUNET_PQ_ResultSpec
662GNUNET_PQ_result_spec_uint64 (const char *name,
663 uint64_t *u64)
664{
665 struct GNUNET_PQ_ResultSpec res =
666 { &extract_uint64,
667 NULL,
668 NULL,
669 (void *) u64, sizeof (*u64), (name), NULL };
670 return res;
671}
672
673
674/* end of pq_result_helper.c */
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
new file mode 100644
index 000000000..b9bf1be76
--- /dev/null
+++ b/src/pq/test_pq.c
@@ -0,0 +1,288 @@
1/*
2 This file is part of GNUnet
3 (C) 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file pq/test_pq.c
18 * @brief Tests for Postgres convenience API
19 * @author Christian Grothoff <christian@grothoff.org>
20 */
21#include "platform.h"
22#include "gnunet_util_lib.h"
23#include "gnunet_pq_lib.h"
24
25
26/**
27 * Setup prepared statements.
28 *
29 * @param db_conn connection handle to initialize
30 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
31 */
32static int
33postgres_prepare (PGconn *db_conn)
34{
35 PGresult *result;
36
37#define PREPARE(name, sql, ...) \
38 do { \
39 result = PQprepare (db_conn, name, sql, __VA_ARGS__); \
40 if (PGRES_COMMAND_OK != PQresultStatus (result)) \
41 { \
42 GNUNET_break (0); \
43 PQclear (result); result = NULL; \
44 return GNUNET_SYSERR; \
45 } \
46 PQclear (result); result = NULL; \
47 } while (0);
48
49 PREPARE ("test_insert",
50 "INSERT INTO test_pq ("
51 " pub"
52 ",sig"
53 ",abs_time"
54 ",forever"
55 ",hash"
56 ",vsize"
57 ",u16"
58 ",u32"
59 ",u64"
60 ") VALUES "
61 "($1, $2, $3, $4, $5, $6,"
62 "$7, $8, $9);",
63 9, NULL);
64 PREPARE ("test_select",
65 "SELECT"
66 " pub"
67 ",sig"
68 ",abs_time"
69 ",forever"
70 ",hash"
71 ",vsize"
72 ",u16"
73 ",u32"
74 ",u64"
75 " FROM test_pq"
76 " ORDER BY abs_time DESC "
77 " LIMIT 1;",
78 0, NULL);
79 return GNUNET_OK;
80#undef PREPARE
81}
82
83
84/**
85 * Run actual test queries.
86 *
87 * @return 0 on success
88 */
89static int
90run_queries (PGconn *conn)
91{
92 struct GNUNET_CRYPTO_rsa_PublicKey *pub;
93 struct GNUNET_CRYPTO_rsa_PublicKey *pub2 = NULL;
94 struct GNUNET_CRYPTO_rsa_Signature *sig;
95 struct GNUNET_CRYPTO_rsa_Signature *sig2 = NULL;
96 struct GNUNET_TIME_Absolute abs_time = GNUNET_TIME_absolute_get ();
97 struct GNUNET_TIME_Absolute abs_time2;
98 struct GNUNET_TIME_Absolute forever = GNUNET_TIME_UNIT_FOREVER_ABS;
99 struct GNUNET_TIME_Absolute forever2;
100 struct GNUNET_HashCode hc;
101 struct GNUNET_HashCode hc2;
102 PGresult *result;
103 int ret;
104 struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
105 char msg[] = "Hello";
106 void *msg2;
107 size_t msg2_len;
108 uint16_t u16;
109 uint16_t u162;
110 uint32_t u32;
111 uint32_t u322;
112 uint64_t u64;
113 uint64_t u642;
114
115 priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
116 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
117 sig = GNUNET_CRYPTO_rsa_sign (priv,
118 msg,
119 sizeof (msg));
120 u16 = 16;
121 u32 = 32;
122 u64 = 64;
123 /* FIXME: test GNUNET_PQ_result_spec_variable_size */
124 {
125 struct GNUNET_PQ_QueryParam params_insert[] = {
126 GNUNET_PQ_query_param_rsa_public_key (pub),
127 GNUNET_PQ_query_param_rsa_signature (sig),
128 GNUNET_PQ_query_param_absolute_time (&abs_time),
129 GNUNET_PQ_query_param_absolute_time (&forever),
130 GNUNET_PQ_query_param_auto_from_type (&hc),
131 GNUNET_PQ_query_param_fixed_size (msg, strlen (msg)),
132 GNUNET_PQ_query_param_uint16 (&u16),
133 GNUNET_PQ_query_param_uint32 (&u32),
134 GNUNET_PQ_query_param_uint64 (&u64),
135 GNUNET_PQ_query_param_end
136 };
137 struct GNUNET_PQ_QueryParam params_select[] = {
138 GNUNET_PQ_query_param_end
139 };
140 struct GNUNET_PQ_ResultSpec results_select[] = {
141 GNUNET_PQ_result_spec_rsa_public_key ("pub", &pub2),
142 GNUNET_PQ_result_spec_rsa_signature ("sig", &sig2),
143 GNUNET_PQ_result_spec_absolute_time ("abs_time", &abs_time2),
144 GNUNET_PQ_result_spec_absolute_time ("forever", &forever2),
145 GNUNET_PQ_result_spec_auto_from_type ("hash", &hc2),
146 GNUNET_PQ_result_spec_variable_size ("vsize", &msg2, &msg2_len),
147 GNUNET_PQ_result_spec_uint16 ("u16", &u162),
148 GNUNET_PQ_result_spec_uint32 ("u32", &u322),
149 GNUNET_PQ_result_spec_uint64 ("u64", &u642),
150 GNUNET_PQ_result_spec_end
151 };
152
153 result = GNUNET_PQ_exec_prepared (conn,
154 "test_insert",
155 params_insert);
156 if (PGRES_COMMAND_OK != PQresultStatus (result))
157 {
158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
159 "Database failure: %s\n",
160 PQresultErrorMessage (result));
161 PQclear (result);
162 GNUNET_CRYPTO_rsa_signature_free (sig);
163 GNUNET_CRYPTO_rsa_private_key_free (priv);
164 GNUNET_CRYPTO_rsa_public_key_free (pub);
165 return 1;
166 }
167
168 PQclear (result);
169 result = GNUNET_PQ_exec_prepared (conn,
170 "test_select",
171 params_select);
172 if (1 !=
173 PQntuples (result))
174 {
175 GNUNET_break (0);
176 PQclear (result);
177 GNUNET_CRYPTO_rsa_signature_free (sig);
178 GNUNET_CRYPTO_rsa_private_key_free (priv);
179 GNUNET_CRYPTO_rsa_public_key_free (pub);
180 return 1;
181 }
182 ret = GNUNET_PQ_extract_result (result,
183 results_select,
184 0);
185 GNUNET_break (GNUNET_YES == ret);
186 GNUNET_break (abs_time.abs_value_us == abs_time2.abs_value_us);
187 GNUNET_break (forever.abs_value_us == forever2.abs_value_us);
188 GNUNET_break (0 ==
189 memcmp (&hc,
190 &hc2,
191 sizeof (struct GNUNET_HashCode)));
192 GNUNET_break (0 ==
193 GNUNET_CRYPTO_rsa_signature_cmp (sig,
194 sig2));
195 GNUNET_break (0 ==
196 GNUNET_CRYPTO_rsa_public_key_cmp (pub,
197 pub2));
198 GNUNET_break (strlen (msg) == msg2_len);
199 GNUNET_break (0 ==
200 strncmp (msg,
201 msg2,
202 msg2_len));
203 GNUNET_break (16 == u162);
204 GNUNET_break (32 == u322);
205 GNUNET_break (64 == u642);
206 GNUNET_PQ_cleanup_result (results_select);
207 PQclear (result);
208 }
209 GNUNET_CRYPTO_rsa_signature_free (sig);
210 GNUNET_CRYPTO_rsa_private_key_free (priv);
211 GNUNET_CRYPTO_rsa_public_key_free (pub);
212 if (GNUNET_OK != ret)
213 return 1;
214
215 return 0;
216}
217
218
219int
220main(int argc,
221 const char *const argv[])
222{
223 PGconn *conn;
224 PGresult *result;
225 int ret;
226
227 GNUNET_log_setup ("test-pq",
228 "WARNING",
229 NULL);
230 conn = PQconnectdb ("postgres:///gnunetcheck");
231 if (CONNECTION_OK != PQstatus (conn))
232 {
233 fprintf (stderr,
234 "Cannot run test, database connection failed: %s\n",
235 PQerrorMessage (conn));
236 GNUNET_break (0);
237 PQfinish (conn);
238 return 0; /* We ignore this type of error... */
239 }
240
241 result = PQexec (conn,
242 "CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
243 " pub BYTEA NOT NULL"
244 ",sig BYTEA NOT NULL"
245 ",abs_time INT8 NOT NULL"
246 ",forever INT8 NOT NULL"
247 ",hash BYTEA NOT NULL CHECK(LENGTH(hash)=64)"
248 ",vsize VARCHAR NOT NULL"
249 ",u16 INT2 NOT NULL"
250 ",u32 INT4 NOT NULL"
251 ",u64 INT8 NOT NULL"
252 ")");
253 if (PGRES_COMMAND_OK != PQresultStatus (result))
254 {
255 fprintf (stderr,
256 "Failed to create table: %s\n",
257 PQerrorMessage (conn));
258 PQclear (result);
259 PQfinish (conn);
260 return 1;
261 }
262 PQclear (result);
263 if (GNUNET_OK !=
264 postgres_prepare (conn))
265 {
266 GNUNET_break (0);
267 PQfinish (conn);
268 return 1;
269 }
270 ret = run_queries (conn);
271 result = PQexec (conn,
272 "DROP TABLE test_pq");
273 if (PGRES_COMMAND_OK != PQresultStatus (result))
274 {
275 fprintf (stderr,
276 "Failed to create table: %s\n",
277 PQerrorMessage (conn));
278 PQclear (result);
279 PQfinish (conn);
280 return 1;
281 }
282 PQclear (result);
283 PQfinish (conn);
284 return ret;
285}
286
287
288/* end of test_pq.c */