aboutsummaryrefslogtreecommitdiff
path: root/src/sq/sq_result_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sq/sq_result_helper.c')
-rw-r--r--src/sq/sq_result_helper.c710
1 files changed, 710 insertions, 0 deletions
diff --git a/src/sq/sq_result_helper.c b/src/sq/sq_result_helper.c
new file mode 100644
index 000000000..eaf606aa4
--- /dev/null
+++ b/src/sq/sq_result_helper.c
@@ -0,0 +1,710 @@
1
2/*
3 This file is part of GNUnet
4 Copyright (C) 2017 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify it under the
7 terms of the GNU General Public License as published by the Free Software
8 Foundation; either version 3, or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along with
15 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
16*/
17/**
18 * @file sq/sq_result_helper.c
19 * @brief helper functions for queries
20 * @author Christian Grothoff
21 */
22#include "platform.h"
23#include "gnunet_sq_lib.h"
24
25
26/**
27 * Extract variable-sized binary data from a Postgres database @a result at row @a row.
28 *
29 * @param cls closure
30 * @param result where to extract data from
31 * @param column column to extract data from
32 * @param[in,out] dst_size where to store size of result, may be NULL
33 * @param[out] dst where to store the result (actually a `void **`)
34 * @return
35 * #GNUNET_YES if all results could be extracted
36 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
37 */
38static int
39extract_var_blob (void *cls,
40 sqlite3_stmt *result,
41 unsigned int column,
42 size_t *dst_size,
43 void *dst)
44{
45 int have;
46 const void *ret;
47 void **rdst = (void **) dst;
48
49 if (SQLITE_BLOB !=
50 sqlite3_column_type (result,
51 column))
52 {
53 GNUNET_break (0);
54 return GNUNET_SYSERR;
55 }
56 /* sqlite manual says to invoke 'sqlite3_column_blob()'
57 before calling sqlite3_column_bytes() */
58 ret = sqlite3_column_blob (result,
59 column);
60 have = sqlite3_column_bytes (result,
61 column);
62 if (have < 0)
63 {
64 GNUNET_break (0);
65 return GNUNET_SYSERR;
66 }
67 *dst_size = have;
68 if (0 == have)
69 {
70 *rdst = NULL;
71 return GNUNET_OK;
72 }
73 *rdst = GNUNET_malloc (have);
74 GNUNET_memcpy (*rdst,
75 ret,
76 have);
77 return GNUNET_OK;
78}
79
80
81/**
82 * Cleanup memory allocated by #extract_var_blob().
83 *
84 * @param cls pointer to pointer of allocation
85 */
86static void
87clean_var_blob (void *cls)
88{
89 void **dptr = (void **) cls;
90
91 if (NULL != *dptr)
92 {
93 GNUNET_free (*dptr);
94 *dptr = NULL;
95 }
96}
97
98
99/**
100 * Variable-size result expected.
101 *
102 * @param[out] dst where to store the result, allocated
103 * @param[out] sptr where to store the size of @a dst
104 * @return array entry for the result specification to use
105 */
106struct GNUNET_SQ_ResultSpec
107GNUNET_SQ_result_spec_variable_size (void **dst,
108 size_t *sptr)
109{
110 struct GNUNET_SQ_ResultSpec rs = {
111 .conv = &extract_var_blob,
112 .cleaner = &clean_var_blob,
113 .dst = dst,
114 .cls = dst,
115 .result_size = sptr,
116 .num_params = 1
117 };
118
119 return rs;
120}
121
122
123/**
124 * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
125 *
126 * @param cls closure
127 * @param result where to extract data from
128 * @param column column to extract data from
129 * @param[in,out] dst_size where to store size of result, may be NULL
130 * @param[out] dst where to store the result
131 * @return
132 * #GNUNET_YES if all results could be extracted
133 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
134 */
135static int
136extract_fixed_blob (void *cls,
137 sqlite3_stmt *result,
138 unsigned int column,
139 size_t *dst_size,
140 void *dst)
141{
142 int have;
143 const void *ret;
144
145 if (SQLITE_BLOB !=
146 sqlite3_column_type (result,
147 column))
148 {
149 GNUNET_break (0);
150 return GNUNET_SYSERR;
151 }
152 /* sqlite manual says to invoke 'sqlite3_column_blob()'
153 before calling sqlite3_column_bytes() */
154 ret = sqlite3_column_blob (result,
155 column);
156 have = sqlite3_column_bytes (result,
157 column);
158 if (*dst_size != have)
159 {
160 GNUNET_break (0);
161 return GNUNET_SYSERR;
162 }
163 GNUNET_memcpy (dst,
164 ret,
165 have);
166 return GNUNET_OK;
167}
168
169
170/**
171 * Fixed-size result expected.
172 *
173 * @param[out] dst where to store the result
174 * @param dst_size number of bytes in @a dst
175 * @return array entry for the result specification to use
176 */
177struct GNUNET_SQ_ResultSpec
178GNUNET_SQ_result_spec_fixed_size (void *dst,
179 size_t dst_size)
180{
181 struct GNUNET_SQ_ResultSpec rs = {
182 .conv = &extract_fixed_blob,
183 .dst = dst,
184 .dst_size = dst_size,
185 .num_params = 1
186 };
187
188 return rs;
189}
190
191
192/**
193 * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
194 *
195 * @param cls closure
196 * @param result where to extract data from
197 * @param column column to extract data from
198 * @param[in,out] dst_size where to store size of result, may be NULL
199 * @param[out] dst where to store the result
200 * @return
201 * #GNUNET_YES if all results could be extracted
202 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
203 */
204static int
205extract_utf8_string (void *cls,
206 sqlite3_stmt *result,
207 unsigned int column,
208 size_t *dst_size,
209 void *dst)
210{
211 const char *text;
212 char **rdst = dst;
213
214 if (SQLITE_TEXT !=
215 sqlite3_column_type (result,
216 column))
217 {
218 GNUNET_break (0);
219 return GNUNET_SYSERR;
220 }
221 /* sqlite manual guarantees that 'sqlite3_column_text()'
222 is 0-terminated */
223 text = (const char *) sqlite3_column_text (result,
224 column);
225 if (NULL == text)
226 {
227 GNUNET_break (0);
228 return GNUNET_SYSERR;
229 }
230 *dst_size = strlen (text) + 1;
231 *rdst = GNUNET_strdup (text);
232 return GNUNET_OK;
233}
234
235
236/**
237 * Cleanup memory allocated by #extract_var_blob().
238 *
239 * @param cls pointer to pointer of allocation
240 */
241static void
242clean_utf8_string (void *cls)
243{
244 char **dptr = (char **) cls;
245
246 if (NULL != *dptr)
247 {
248 GNUNET_free (*dptr);
249 *dptr = NULL;
250 }
251}
252
253
254/**
255 * 0-terminated string expected.
256 *
257 * @param[out] dst where to store the result, allocated
258 * @return array entry for the result specification to use
259 */
260struct GNUNET_SQ_ResultSpec
261GNUNET_SQ_result_spec_string (char **dst)
262{
263 struct GNUNET_SQ_ResultSpec rs = {
264 .conv = &extract_utf8_string,
265 .cleaner = &clean_utf8_string,
266 .cls = dst,
267 .dst = dst,
268 .num_params = 1
269 };
270
271 return rs;
272}
273
274
275/**
276 * Extract data from a Postgres database @a result at row @a row.
277 *
278 * @param cls closure
279 * @param result where to extract data from
280 * @param column column to extract data from
281 * @param[in,out] dst_size where to store size of result, may be NULL
282 * @param[out] dst where to store the result
283 * @return
284 * #GNUNET_YES if all results could be extracted
285 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
286 */
287static int
288extract_rsa_pub (void *cls,
289 sqlite3_stmt *result,
290 unsigned int column,
291 size_t *dst_size,
292 void *dst)
293{
294 struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
295 int have;
296 const void *ret;
297
298 if (SQLITE_BLOB !=
299 sqlite3_column_type (result,
300 column))
301 {
302 GNUNET_break (0);
303 return GNUNET_SYSERR;
304 }
305 /* sqlite manual says to invoke 'sqlite3_column_blob()'
306 before calling sqlite3_column_bytes() */
307 ret = sqlite3_column_blob (result,
308 column);
309 have = sqlite3_column_bytes (result,
310 column);
311 if (have < 0)
312 {
313 GNUNET_break (0);
314 return GNUNET_SYSERR;
315 }
316
317 *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret,
318 have);
319 if (NULL == *pk)
320 {
321 GNUNET_break (0);
322 return GNUNET_SYSERR;
323 }
324 return GNUNET_OK;
325}
326
327
328/**
329 * Function called to clean up memory allocated
330 * by a #GNUNET_PQ_ResultConverter.
331 *
332 * @param cls closure
333 */
334static void
335clean_rsa_pub (void *cls)
336{
337 struct GNUNET_CRYPTO_RsaPublicKey **pk = cls;
338
339 if (NULL != *pk)
340 {
341 GNUNET_CRYPTO_rsa_public_key_free (*pk);
342 *pk = NULL;
343 }
344}
345
346
347/**
348 * RSA public key expected.
349 *
350 * @param[out] rsa where to store the result
351 * @return array entry for the result specification to use
352 */
353struct GNUNET_SQ_ResultSpec
354GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
355{
356 struct GNUNET_SQ_ResultSpec rs = {
357 .conv = &extract_rsa_pub,
358 .cleaner = &clean_rsa_pub,
359 .dst = rsa,
360 .cls = rsa,
361 .num_params = 1
362 };
363
364 return rs;
365}
366
367
368/**
369 * Extract data from a Postgres database @a result at row @a row.
370 *
371 * @param cls closure
372 * @param result where to extract data from
373 * @param column column to extract data from
374 * @param[in,out] dst_size where to store size of result, may be NULL
375 * @param[out] dst where to store the result
376 * @return
377 * #GNUNET_YES if all results could be extracted
378 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
379 */
380static int
381extract_rsa_sig (void *cls,
382 sqlite3_stmt *result,
383 unsigned int column,
384 size_t *dst_size,
385 void *dst)
386{
387 struct GNUNET_CRYPTO_RsaSignature **sig = dst;
388 int have;
389 const void *ret;
390
391 if (SQLITE_BLOB !=
392 sqlite3_column_type (result,
393 column))
394 {
395 GNUNET_break (0);
396 return GNUNET_SYSERR;
397 }
398 /* sqlite manual says to invoke 'sqlite3_column_blob()'
399 before calling sqlite3_column_bytes() */
400 ret = sqlite3_column_blob (result,
401 column);
402 have = sqlite3_column_bytes (result,
403 column);
404 if (have < 0)
405 {
406 GNUNET_break (0);
407 return GNUNET_SYSERR;
408 }
409
410 *sig = GNUNET_CRYPTO_rsa_signature_decode (ret,
411 have);
412 if (NULL == *sig)
413 {
414 GNUNET_break (0);
415 return GNUNET_SYSERR;
416 }
417 return GNUNET_OK;
418}
419
420
421/**
422 * Function called to clean up memory allocated
423 * by a #GNUNET_PQ_ResultConverter.
424 *
425 * @param cls result data to clean up
426 */
427static void
428clean_rsa_sig (void *cls)
429{
430 struct GNUNET_CRYPTO_RsaSignature **sig = cls;
431
432 if (NULL != *sig)
433 {
434 GNUNET_CRYPTO_rsa_signature_free (*sig);
435 *sig = NULL;
436 }
437}
438
439
440/**
441 * RSA signature expected.
442 *
443 * @param[out] sig where to store the result;
444 * @return array entry for the result specification to use
445 */
446struct GNUNET_SQ_ResultSpec
447GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
448{
449 struct GNUNET_SQ_ResultSpec rs = {
450 .conv = &extract_rsa_sig,
451 .cleaner = &clean_rsa_sig,
452 .dst = sig,
453 .cls = sig,
454 .num_params = 1
455 };
456
457 return rs;
458}
459
460
461/**
462 * Absolute time expected.
463 *
464 * @param[out] at where to store the result
465 * @return array entry for the result specification to use
466 */
467struct GNUNET_SQ_ResultSpec
468GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
469{
470 return GNUNET_SQ_result_spec_uint64 (&at->abs_value_us);
471}
472
473
474/**
475 * Extract absolute time value in NBO from a Postgres database @a result at row @a row.
476 *
477 * @param cls closure
478 * @param result where to extract data from
479 * @param column column to extract data from
480 * @param[in,out] dst_size where to store size of result, may be NULL
481 * @param[out] dst where to store the result
482 * @return
483 * #GNUNET_YES if all results could be extracted
484 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
485 */
486static int
487extract_abs_time_nbo (void *cls,
488 sqlite3_stmt *result,
489 unsigned int column,
490 size_t *dst_size,
491 void *dst)
492{
493 struct GNUNET_TIME_AbsoluteNBO *u = dst;
494 struct GNUNET_TIME_Absolute t;
495
496 GNUNET_assert (sizeof (uint64_t) == *dst_size);
497 if (SQLITE_INTEGER !=
498 sqlite3_column_type (result,
499 column))
500 {
501 GNUNET_break (0);
502 return GNUNET_SYSERR;
503 }
504 t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
505 column);
506 *u = GNUNET_TIME_absolute_hton (t);
507 return GNUNET_OK;
508}
509
510
511/**
512 * Absolute time expected.
513 *
514 * @param[out] at where to store the result
515 * @return array entry for the result specification to use
516 */
517struct GNUNET_SQ_ResultSpec
518GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
519{
520 struct GNUNET_SQ_ResultSpec rs = {
521 .conv = &extract_abs_time_nbo,
522 .dst = at,
523 .dst_size = sizeof (struct GNUNET_TIME_AbsoluteNBO),
524 .num_params = 1
525 };
526
527 return rs;
528}
529
530
531/**
532 * Extract 16-bit integer from a Postgres database @a result at row @a row.
533 *
534 * @param cls closure
535 * @param result where to extract data from
536 * @param column column to extract data from
537 * @param[in,out] dst_size where to store size of result, may be NULL
538 * @param[out] dst where to store the result
539 * @return
540 * #GNUNET_YES if all results could be extracted
541 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
542 */
543static int
544extract_uint16 (void *cls,
545 sqlite3_stmt *result,
546 unsigned int column,
547 size_t *dst_size,
548 void *dst)
549{
550 uint64_t v;
551 uint32_t *u = dst;
552
553 GNUNET_assert (sizeof (uint16_t) == *dst_size);
554 if (SQLITE_INTEGER !=
555 sqlite3_column_type (result,
556 column))
557 {
558 GNUNET_break (0);
559 return GNUNET_SYSERR;
560 }
561 v = (uint64_t) sqlite3_column_int64 (result,
562 column);
563 if (v > UINT16_MAX)
564 {
565 GNUNET_break (0);
566 return GNUNET_SYSERR;
567 }
568 *u = (uint16_t) v;
569 return GNUNET_OK;
570}
571
572
573/**
574 * uint16_t expected.
575 *
576 * @param[out] u16 where to store the result
577 * @return array entry for the result specification to use
578 */
579struct GNUNET_SQ_ResultSpec
580GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
581{
582 struct GNUNET_SQ_ResultSpec rs = {
583 .conv = &extract_uint16,
584 .dst = u16,
585 .dst_size = sizeof (uint16_t),
586 .num_params = 1
587 };
588
589 return rs;
590}
591
592
593/**
594 * Extract 32-bit integer from a Postgres database @a result at row @a row.
595 *
596 * @param cls closure
597 * @param result where to extract data from
598 * @param column column to extract data from
599 * @param[in,out] dst_size where to store size of result, may be NULL
600 * @param[out] dst where to store the result
601 * @return
602 * #GNUNET_YES if all results could be extracted
603 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
604 */
605static int
606extract_uint32 (void *cls,
607 sqlite3_stmt *result,
608 unsigned int column,
609 size_t *dst_size,
610 void *dst)
611{
612 uint64_t v;
613 uint32_t *u = dst;
614
615 GNUNET_assert (sizeof (uint32_t) == *dst_size);
616 if (SQLITE_INTEGER !=
617 sqlite3_column_type (result,
618 column))
619 {
620 GNUNET_break (0);
621 return GNUNET_SYSERR;
622 }
623 v = (uint64_t) sqlite3_column_int64 (result,
624 column);
625 if (v > UINT32_MAX)
626 {
627 GNUNET_break (0);
628 return GNUNET_SYSERR;
629 }
630 *u = (uint32_t) v;
631 return GNUNET_OK;
632}
633
634
635/**
636 * uint32_t expected.
637 *
638 * @param[out] u32 where to store the result
639 * @return array entry for the result specification to use
640 */
641struct GNUNET_SQ_ResultSpec
642GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
643{
644 struct GNUNET_SQ_ResultSpec rs = {
645 .conv = &extract_uint32,
646 .dst = u32,
647 .dst_size = sizeof (uint32_t),
648 .num_params = 1
649 };
650
651 return rs;
652}
653
654
655/**
656 * Extract 64-bit integer from a Postgres database @a result at row @a row.
657 *
658 * @param cls closure
659 * @param result where to extract data from
660 * @param column column to extract data from
661 * @param[in,out] dst_size where to store size of result, may be NULL
662 * @param[out] dst where to store the result
663 * @return
664 * #GNUNET_YES if all results could be extracted
665 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
666 */
667static int
668extract_uint64 (void *cls,
669 sqlite3_stmt *result,
670 unsigned int column,
671 size_t *dst_size,
672 void *dst)
673{
674 uint64_t *u = dst;
675
676 GNUNET_assert (sizeof (uint64_t) == *dst_size);
677 if (SQLITE_INTEGER !=
678 sqlite3_column_type (result,
679 column))
680 {
681 GNUNET_break (0);
682 return GNUNET_SYSERR;
683 }
684 *u = (uint64_t) sqlite3_column_int64 (result,
685 column);
686 return GNUNET_OK;
687}
688
689
690/**
691 * uint64_t expected.
692 *
693 * @param[out] u64 where to store the result
694 * @return array entry for the result specification to use
695 */
696struct GNUNET_SQ_ResultSpec
697GNUNET_SQ_result_spec_uint64 (uint64_t *u64)
698{
699 struct GNUNET_SQ_ResultSpec rs = {
700 .conv = &extract_uint64,
701 .dst = u64,
702 .dst_size = sizeof (uint64_t),
703 .num_params = 1
704 };
705
706 return rs;
707}
708
709
710/* end of sq_result_helper.c */