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