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