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