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