2 This file is part of GNUnet
3 Copyright (C) 2017 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file sq/sq_result_helper.c
22 * @brief helper functions for queries
23 * @author Christian Grothoff
26 #include "gnunet_sq_lib.h"
30 * Extract variable-sized binary data from a Postgres database @a result at row @a row.
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 **`)
38 * #GNUNET_YES if all results could be extracted
39 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
42 extract_var_blob (void *cls,
50 void **rdst = (void **) dst;
53 sqlite3_column_type (result,
62 sqlite3_column_type (result,
68 /* sqlite manual says to invoke 'sqlite3_column_blob()'
69 before calling sqlite3_column_bytes() */
70 ret = sqlite3_column_blob (result,
72 have = sqlite3_column_bytes (result,
85 *rdst = GNUNET_malloc (have);
94 * Cleanup memory allocated by #extract_var_blob().
96 * @param cls pointer to pointer of allocation
99 clean_var_blob (void *cls)
101 void **dptr = (void **) cls;
112 * Variable-size result expected.
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
118 struct GNUNET_SQ_ResultSpec
119 GNUNET_SQ_result_spec_variable_size (void **dst,
122 struct GNUNET_SQ_ResultSpec rs = {
123 .conv = &extract_var_blob,
124 .cleaner = &clean_var_blob,
136 * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
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
144 * #GNUNET_YES if all results could be extracted
145 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
148 extract_fixed_blob (void *cls,
149 sqlite3_stmt *result,
157 if ((0 == *dst_size) &&
159 sqlite3_column_type (result,
166 sqlite3_column_type (result,
170 return GNUNET_SYSERR;
172 /* sqlite manual says to invoke 'sqlite3_column_blob()'
173 before calling sqlite3_column_bytes() */
174 ret = sqlite3_column_blob (result,
176 have = sqlite3_column_bytes (result,
178 if (*dst_size != have)
181 return GNUNET_SYSERR;
191 * Fixed-size result expected.
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
197 struct GNUNET_SQ_ResultSpec
198 GNUNET_SQ_result_spec_fixed_size (void *dst,
201 struct GNUNET_SQ_ResultSpec rs = {
202 .conv = &extract_fixed_blob,
204 .dst_size = dst_size,
213 * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
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
221 * #GNUNET_YES if all results could be extracted
222 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
225 extract_utf8_string (void *cls,
226 sqlite3_stmt *result,
235 sqlite3_column_type (result,
242 sqlite3_column_type (result,
246 return GNUNET_SYSERR;
248 /* sqlite manual guarantees that 'sqlite3_column_text()'
250 text = (const char *) sqlite3_column_text (result,
255 return GNUNET_SYSERR;
257 *dst_size = strlen (text) + 1;
258 *rdst = GNUNET_strdup (text);
264 * Cleanup memory allocated by #extract_var_blob().
266 * @param cls pointer to pointer of allocation
269 clean_utf8_string (void *cls)
271 char **dptr = (char **) cls;
282 * 0-terminated string expected.
284 * @param[out] dst where to store the result, allocated
285 * @return array entry for the result specification to use
287 struct GNUNET_SQ_ResultSpec
288 GNUNET_SQ_result_spec_string (char **dst)
290 struct GNUNET_SQ_ResultSpec rs = {
291 .conv = &extract_utf8_string,
292 .cleaner = &clean_utf8_string,
303 * Extract data from a Postgres database @a result at row @a row.
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
311 * #GNUNET_YES if all results could be extracted
312 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
315 extract_rsa_pub (void *cls,
316 sqlite3_stmt *result,
321 struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
326 sqlite3_column_type (result,
330 return GNUNET_SYSERR;
332 /* sqlite manual says to invoke 'sqlite3_column_blob()'
333 before calling sqlite3_column_bytes() */
334 ret = sqlite3_column_blob (result,
336 have = sqlite3_column_bytes (result,
341 return GNUNET_SYSERR;
344 *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret,
349 return GNUNET_SYSERR;
356 * Function called to clean up memory allocated
357 * by a #GNUNET_PQ_ResultConverter.
362 clean_rsa_pub (void *cls)
364 struct GNUNET_CRYPTO_RsaPublicKey **pk = cls;
368 GNUNET_CRYPTO_rsa_public_key_free (*pk);
375 * RSA public key expected.
377 * @param[out] rsa where to store the result
378 * @return array entry for the result specification to use
380 struct GNUNET_SQ_ResultSpec
381 GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
383 struct GNUNET_SQ_ResultSpec rs = {
384 .conv = &extract_rsa_pub,
385 .cleaner = &clean_rsa_pub,
396 * Extract data from a Postgres database @a result at row @a row.
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
404 * #GNUNET_YES if all results could be extracted
405 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
408 extract_rsa_sig (void *cls,
409 sqlite3_stmt *result,
414 struct GNUNET_CRYPTO_RsaSignature **sig = dst;
419 sqlite3_column_type (result,
423 return GNUNET_SYSERR;
425 /* sqlite manual says to invoke 'sqlite3_column_blob()'
426 before calling sqlite3_column_bytes() */
427 ret = sqlite3_column_blob (result,
429 have = sqlite3_column_bytes (result,
434 return GNUNET_SYSERR;
437 *sig = GNUNET_CRYPTO_rsa_signature_decode (ret,
442 return GNUNET_SYSERR;
449 * Function called to clean up memory allocated
450 * by a #GNUNET_PQ_ResultConverter.
452 * @param cls result data to clean up
455 clean_rsa_sig (void *cls)
457 struct GNUNET_CRYPTO_RsaSignature **sig = cls;
461 GNUNET_CRYPTO_rsa_signature_free (*sig);
468 * RSA signature expected.
470 * @param[out] sig where to store the result;
471 * @return array entry for the result specification to use
473 struct GNUNET_SQ_ResultSpec
474 GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
476 struct GNUNET_SQ_ResultSpec rs = {
477 .conv = &extract_rsa_sig,
478 .cleaner = &clean_rsa_sig,
489 * Extract absolute time value from a Postgres database @a result at row @a row.
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
497 * #GNUNET_YES if all results could be extracted
498 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
501 extract_abs_time (void *cls,
502 sqlite3_stmt *result,
507 struct GNUNET_TIME_Absolute *u = dst;
508 struct GNUNET_TIME_Absolute t;
510 GNUNET_assert (sizeof(uint64_t) == *dst_size);
511 if (SQLITE_INTEGER !=
512 sqlite3_column_type (result,
516 return GNUNET_SYSERR;
518 t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
520 if (INT64_MAX == t.abs_value_us)
521 t = GNUNET_TIME_UNIT_FOREVER_ABS;
528 * Absolute time expected.
530 * @param[out] at where to store the result
531 * @return array entry for the result specification to use
533 struct GNUNET_SQ_ResultSpec
534 GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
536 struct GNUNET_SQ_ResultSpec rs = {
537 .conv = &extract_abs_time,
539 .dst_size = sizeof(struct GNUNET_TIME_Absolute),
548 * Extract absolute time value in NBO from a Postgres database @a result at row @a row.
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
556 * #GNUNET_YES if all results could be extracted
557 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
560 extract_abs_time_nbo (void *cls,
561 sqlite3_stmt *result,
566 struct GNUNET_TIME_AbsoluteNBO *u = dst;
567 struct GNUNET_TIME_Absolute t;
569 GNUNET_assert (sizeof(uint64_t) == *dst_size);
570 if (SQLITE_INTEGER !=
571 sqlite3_column_type (result,
575 return GNUNET_SYSERR;
577 t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
579 if (INT64_MAX == t.abs_value_us)
580 t = GNUNET_TIME_UNIT_FOREVER_ABS;
581 *u = GNUNET_TIME_absolute_hton (t);
587 * Absolute time expected.
589 * @param[out] at where to store the result
590 * @return array entry for the result specification to use
592 struct GNUNET_SQ_ResultSpec
593 GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
595 struct GNUNET_SQ_ResultSpec rs = {
596 .conv = &extract_abs_time_nbo,
598 .dst_size = sizeof(struct GNUNET_TIME_AbsoluteNBO),
607 * Extract 16-bit integer from a Postgres database @a result at row @a row.
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
615 * #GNUNET_YES if all results could be extracted
616 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
619 extract_uint16 (void *cls,
620 sqlite3_stmt *result,
628 GNUNET_assert (sizeof(uint16_t) == *dst_size);
629 if (SQLITE_INTEGER !=
630 sqlite3_column_type (result,
634 return GNUNET_SYSERR;
636 v = (uint64_t) sqlite3_column_int64 (result,
641 return GNUNET_SYSERR;
651 * @param[out] u16 where to store the result
652 * @return array entry for the result specification to use
654 struct GNUNET_SQ_ResultSpec
655 GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
657 struct GNUNET_SQ_ResultSpec rs = {
658 .conv = &extract_uint16,
660 .dst_size = sizeof(uint16_t),
669 * Extract 32-bit integer from a Postgres database @a result at row @a row.
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
677 * #GNUNET_YES if all results could be extracted
678 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
681 extract_uint32 (void *cls,
682 sqlite3_stmt *result,
690 GNUNET_assert (sizeof(uint32_t) == *dst_size);
691 if (SQLITE_INTEGER !=
692 sqlite3_column_type (result,
696 return GNUNET_SYSERR;
698 v = (uint64_t) sqlite3_column_int64 (result,
703 return GNUNET_SYSERR;
713 * @param[out] u32 where to store the result
714 * @return array entry for the result specification to use
716 struct GNUNET_SQ_ResultSpec
717 GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
719 struct GNUNET_SQ_ResultSpec rs = {
720 .conv = &extract_uint32,
722 .dst_size = sizeof(uint32_t),
731 * Extract 64-bit integer from a Postgres database @a result at row @a row.
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
739 * #GNUNET_YES if all results could be extracted
740 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
743 extract_uint64 (void *cls,
744 sqlite3_stmt *result,
751 GNUNET_assert (sizeof(uint64_t) == *dst_size);
752 if (SQLITE_INTEGER !=
753 sqlite3_column_type (result,
757 return GNUNET_SYSERR;
759 *u = (uint64_t) sqlite3_column_int64 (result,
768 * @param[out] u64 where to store the result
769 * @return array entry for the result specification to use
771 struct GNUNET_SQ_ResultSpec
772 GNUNET_SQ_result_spec_uint64 (uint64_t *u64)
774 struct GNUNET_SQ_ResultSpec rs = {
775 .conv = &extract_uint64,
777 .dst_size = sizeof(uint64_t),
785 /* end of sq_result_helper.c */