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