Merge branch 'master' of ssh://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 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_TEXT !=
232       sqlite3_column_type (result,
233                            column))
234   {
235     GNUNET_break (0);
236     return GNUNET_SYSERR;
237   }
238   /* sqlite manual guarantees that 'sqlite3_column_text()'
239      is 0-terminated */
240   text = (const char *) sqlite3_column_text (result,
241                                              column);
242   if (NULL == text)
243   {
244     GNUNET_break (0);
245     return GNUNET_SYSERR;
246   }
247   *dst_size = strlen (text) + 1;
248   *rdst = GNUNET_strdup (text);
249   return GNUNET_OK;
250 }
251
252
253 /**
254  * Cleanup memory allocated by #extract_var_blob().
255  *
256  * @param cls pointer to pointer of allocation
257  */
258 static void
259 clean_utf8_string (void *cls)
260 {
261   char **dptr = (char **) cls;
262
263   if (NULL != *dptr)
264   {
265     GNUNET_free (*dptr);
266     *dptr = NULL;
267   }
268 }
269
270
271 /**
272  * 0-terminated string expected.
273  *
274  * @param[out] dst where to store the result, allocated
275  * @return array entry for the result specification to use
276  */
277 struct GNUNET_SQ_ResultSpec
278 GNUNET_SQ_result_spec_string (char **dst)
279 {
280   struct GNUNET_SQ_ResultSpec rs = {
281     .conv = &extract_utf8_string,
282     .cleaner = &clean_utf8_string,
283     .cls = dst,
284     .dst = dst,
285     .num_params = 1
286   };
287
288   return rs;
289 }
290
291
292 /**
293  * Extract data from a Postgres database @a result at row @a row.
294  *
295  * @param cls closure
296  * @param result where to extract data from
297  * @param column column to extract data from
298  * @param[in,out] dst_size where to store size of result, may be NULL
299  * @param[out] dst where to store the result
300  * @return
301  *   #GNUNET_YES if all results could be extracted
302  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
303  */
304 static int
305 extract_rsa_pub (void *cls,
306                  sqlite3_stmt *result,
307                  unsigned int column,
308                  size_t *dst_size,
309                  void *dst)
310 {
311   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
312   int have;
313   const void *ret;
314
315   if (SQLITE_BLOB !=
316       sqlite3_column_type (result,
317                            column))
318   {
319     GNUNET_break (0);
320     return GNUNET_SYSERR;
321   }
322   /* sqlite manual says to invoke 'sqlite3_column_blob()'
323      before calling sqlite3_column_bytes() */
324   ret = sqlite3_column_blob (result,
325                              column);
326   have = sqlite3_column_bytes (result,
327                                column);
328   if (have < 0)
329   {
330     GNUNET_break (0);
331     return GNUNET_SYSERR;
332   }
333
334   *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret,
335                                              have);
336   if (NULL == *pk)
337   {
338     GNUNET_break (0);
339     return GNUNET_SYSERR;
340   }
341   return GNUNET_OK;
342 }
343
344
345 /**
346  * Function called to clean up memory allocated
347  * by a #GNUNET_PQ_ResultConverter.
348  *
349  * @param cls closure
350  */
351 static void
352 clean_rsa_pub (void *cls)
353 {
354   struct GNUNET_CRYPTO_RsaPublicKey **pk = cls;
355
356   if (NULL != *pk)
357   {
358     GNUNET_CRYPTO_rsa_public_key_free (*pk);
359     *pk = NULL;
360   }
361 }
362
363
364 /**
365  * RSA public key expected.
366  *
367  * @param[out] rsa where to store the result
368  * @return array entry for the result specification to use
369  */
370 struct GNUNET_SQ_ResultSpec
371 GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
372 {
373   struct GNUNET_SQ_ResultSpec rs = {
374     .conv = &extract_rsa_pub,
375     .cleaner = &clean_rsa_pub,
376     .dst = rsa,
377     .cls = rsa,
378     .num_params = 1
379   };
380
381   return rs;
382 }
383
384
385 /**
386  * Extract data from a Postgres database @a result at row @a row.
387  *
388  * @param cls closure
389  * @param result where to extract data from
390  * @param column column to extract data from
391  * @param[in,out] dst_size where to store size of result, may be NULL
392  * @param[out] dst where to store the result
393  * @return
394  *   #GNUNET_YES if all results could be extracted
395  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
396  */
397 static int
398 extract_rsa_sig (void *cls,
399                  sqlite3_stmt *result,
400                  unsigned int column,
401                  size_t *dst_size,
402                  void *dst)
403 {
404   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
405   int have;
406   const void *ret;
407
408   if (SQLITE_BLOB !=
409       sqlite3_column_type (result,
410                            column))
411   {
412     GNUNET_break (0);
413     return GNUNET_SYSERR;
414   }
415   /* sqlite manual says to invoke 'sqlite3_column_blob()'
416      before calling sqlite3_column_bytes() */
417   ret = sqlite3_column_blob (result,
418                              column);
419   have = sqlite3_column_bytes (result,
420                                column);
421   if (have < 0)
422   {
423     GNUNET_break (0);
424     return GNUNET_SYSERR;
425   }
426
427   *sig = GNUNET_CRYPTO_rsa_signature_decode (ret,
428                                              have);
429   if (NULL == *sig)
430   {
431     GNUNET_break (0);
432     return GNUNET_SYSERR;
433   }
434   return GNUNET_OK;
435 }
436
437
438 /**
439  * Function called to clean up memory allocated
440  * by a #GNUNET_PQ_ResultConverter.
441  *
442  * @param cls result data to clean up
443  */
444 static void
445 clean_rsa_sig (void *cls)
446 {
447   struct GNUNET_CRYPTO_RsaSignature **sig = cls;
448
449   if (NULL != *sig)
450   {
451     GNUNET_CRYPTO_rsa_signature_free (*sig);
452     *sig = NULL;
453   }
454 }
455
456
457 /**
458  * RSA signature expected.
459  *
460  * @param[out] sig where to store the result;
461  * @return array entry for the result specification to use
462  */
463 struct GNUNET_SQ_ResultSpec
464 GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
465 {
466   struct GNUNET_SQ_ResultSpec rs = {
467     .conv = &extract_rsa_sig,
468     .cleaner = &clean_rsa_sig,
469     .dst = sig,
470     .cls = sig,
471     .num_params = 1
472   };
473
474   return rs;
475 }
476
477
478 /**
479  * Extract absolute time value from a Postgres database @a result at row @a row.
480  *
481  * @param cls closure
482  * @param result where to extract data from
483  * @param column column to extract data from
484  * @param[in,out] dst_size where to store size of result, may be NULL
485  * @param[out] dst where to store the result
486  * @return
487  *   #GNUNET_YES if all results could be extracted
488  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
489  */
490 static int
491 extract_abs_time (void *cls,
492                   sqlite3_stmt *result,
493                   unsigned int column,
494                   size_t *dst_size,
495                   void *dst)
496 {
497   struct GNUNET_TIME_Absolute *u = dst;
498   struct GNUNET_TIME_Absolute t;
499
500   GNUNET_assert (sizeof (uint64_t) == *dst_size);
501   if (SQLITE_INTEGER !=
502       sqlite3_column_type (result,
503                            column))
504   {
505     GNUNET_break (0);
506     return GNUNET_SYSERR;
507   }
508   t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
509                                                     column);
510   if (INT64_MAX == t.abs_value_us)
511     t = GNUNET_TIME_UNIT_FOREVER_ABS;
512   *u = t;
513   return GNUNET_OK;
514 }
515
516
517 /**
518  * Absolute time expected.
519  *
520  * @param[out] at where to store the result
521  * @return array entry for the result specification to use
522  */
523 struct GNUNET_SQ_ResultSpec
524 GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
525 {
526   struct GNUNET_SQ_ResultSpec rs = {
527     .conv = &extract_abs_time,
528     .dst = at,
529     .dst_size = sizeof (struct GNUNET_TIME_Absolute),
530     .num_params = 1
531   };
532
533   return rs;
534 }
535
536
537 /**
538  * Extract absolute time value in NBO from a Postgres database @a result at row @a row.
539  *
540  * @param cls closure
541  * @param result where to extract data from
542  * @param column column to extract data from
543  * @param[in,out] dst_size where to store size of result, may be NULL
544  * @param[out] dst where to store the result
545  * @return
546  *   #GNUNET_YES if all results could be extracted
547  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
548  */
549 static int
550 extract_abs_time_nbo (void *cls,
551                       sqlite3_stmt *result,
552                       unsigned int column,
553                       size_t *dst_size,
554                       void *dst)
555 {
556   struct GNUNET_TIME_AbsoluteNBO *u = dst;
557   struct GNUNET_TIME_Absolute t;
558
559   GNUNET_assert (sizeof (uint64_t) == *dst_size);
560   if (SQLITE_INTEGER !=
561       sqlite3_column_type (result,
562                            column))
563   {
564     GNUNET_break (0);
565     return GNUNET_SYSERR;
566   }
567   t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
568                                                     column);
569   if (INT64_MAX == t.abs_value_us)
570     t = GNUNET_TIME_UNIT_FOREVER_ABS;
571   *u = GNUNET_TIME_absolute_hton (t);
572   return GNUNET_OK;
573 }
574
575
576 /**
577  * Absolute time expected.
578  *
579  * @param[out] at where to store the result
580  * @return array entry for the result specification to use
581  */
582 struct GNUNET_SQ_ResultSpec
583 GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
584 {
585   struct GNUNET_SQ_ResultSpec rs = {
586     .conv = &extract_abs_time_nbo,
587     .dst = at,
588     .dst_size = sizeof (struct GNUNET_TIME_AbsoluteNBO),
589     .num_params = 1
590   };
591
592   return rs;
593 }
594
595
596 /**
597  * Extract 16-bit integer from a Postgres database @a result at row @a row.
598  *
599  * @param cls closure
600  * @param result where to extract data from
601  * @param column column to extract data from
602  * @param[in,out] dst_size where to store size of result, may be NULL
603  * @param[out] dst where to store the result
604  * @return
605  *   #GNUNET_YES if all results could be extracted
606  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
607  */
608 static int
609 extract_uint16 (void *cls,
610                 sqlite3_stmt *result,
611                 unsigned int column,
612                 size_t *dst_size,
613                 void *dst)
614 {
615   uint64_t v;
616   uint32_t *u = dst;
617
618   GNUNET_assert (sizeof (uint16_t) == *dst_size);
619   if (SQLITE_INTEGER !=
620       sqlite3_column_type (result,
621                            column))
622   {
623     GNUNET_break (0);
624     return GNUNET_SYSERR;
625   }
626   v = (uint64_t) sqlite3_column_int64 (result,
627                                        column);
628   if (v > UINT16_MAX)
629   {
630     GNUNET_break (0);
631     return GNUNET_SYSERR;
632   }
633   *u = (uint16_t) v;
634   return GNUNET_OK;
635 }
636
637
638 /**
639  * uint16_t expected.
640  *
641  * @param[out] u16 where to store the result
642  * @return array entry for the result specification to use
643  */
644 struct GNUNET_SQ_ResultSpec
645 GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
646 {
647   struct GNUNET_SQ_ResultSpec rs = {
648     .conv = &extract_uint16,
649     .dst = u16,
650     .dst_size = sizeof (uint16_t),
651     .num_params = 1
652   };
653
654   return rs;
655 }
656
657
658 /**
659  * Extract 32-bit integer from a Postgres database @a result at row @a row.
660  *
661  * @param cls closure
662  * @param result where to extract data from
663  * @param column column to extract data from
664  * @param[in,out] dst_size where to store size of result, may be NULL
665  * @param[out] dst where to store the result
666  * @return
667  *   #GNUNET_YES if all results could be extracted
668  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
669  */
670 static int
671 extract_uint32 (void *cls,
672                 sqlite3_stmt *result,
673                 unsigned int column,
674                 size_t *dst_size,
675                 void *dst)
676 {
677   uint64_t v;
678   uint32_t *u = dst;
679
680   GNUNET_assert (sizeof (uint32_t) == *dst_size);
681   if (SQLITE_INTEGER !=
682       sqlite3_column_type (result,
683                            column))
684   {
685     GNUNET_break (0);
686     return GNUNET_SYSERR;
687   }
688   v = (uint64_t) sqlite3_column_int64 (result,
689                                        column);
690   if (v > UINT32_MAX)
691   {
692     GNUNET_break (0);
693     return GNUNET_SYSERR;
694   }
695   *u = (uint32_t) v;
696   return GNUNET_OK;
697 }
698
699
700 /**
701  * uint32_t expected.
702  *
703  * @param[out] u32 where to store the result
704  * @return array entry for the result specification to use
705  */
706 struct GNUNET_SQ_ResultSpec
707 GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
708 {
709   struct GNUNET_SQ_ResultSpec rs = {
710     .conv = &extract_uint32,
711     .dst = u32,
712     .dst_size = sizeof (uint32_t),
713     .num_params = 1
714   };
715
716   return rs;
717 }
718
719
720 /**
721  * Extract 64-bit integer from a Postgres database @a result at row @a row.
722  *
723  * @param cls closure
724  * @param result where to extract data from
725  * @param column column to extract data from
726  * @param[in,out] dst_size where to store size of result, may be NULL
727  * @param[out] dst where to store the result
728  * @return
729  *   #GNUNET_YES if all results could be extracted
730  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
731  */
732 static int
733 extract_uint64 (void *cls,
734                 sqlite3_stmt *result,
735                 unsigned int column,
736                 size_t *dst_size,
737                 void *dst)
738 {
739   uint64_t *u = dst;
740
741   GNUNET_assert (sizeof (uint64_t) == *dst_size);
742   if (SQLITE_INTEGER !=
743       sqlite3_column_type (result,
744                            column))
745   {
746     GNUNET_break (0);
747     return GNUNET_SYSERR;
748   }
749   *u = (uint64_t) sqlite3_column_int64 (result,
750                                         column);
751   return GNUNET_OK;
752 }
753
754
755 /**
756  * uint64_t expected.
757  *
758  * @param[out] u64 where to store the result
759  * @return array entry for the result specification to use
760  */
761 struct GNUNET_SQ_ResultSpec
762 GNUNET_SQ_result_spec_uint64 (uint64_t *u64)
763 {
764   struct GNUNET_SQ_ResultSpec rs = {
765     .conv = &extract_uint64,
766     .dst = u64,
767     .dst_size = sizeof (uint64_t),
768     .num_params = 1
769   };
770
771   return rs;
772 }
773
774
775 /* end of sq_result_helper.c */