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