uncrustify as demanded.
[oweals/gnunet.git] / src / my / my_result_helper.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2014, 2015, 2016 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 my/my_result_helper.c
22  * @brief functions to extract result values
23  * @author Christophe Genevey
24  */
25
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_my_lib.h"
29
30
31 /**
32  * extract data from a Mysql database @a result at row @a row
33  *
34  * @param cls closure
35  * @param[in,out] rs
36  * @param stmt the mysql statement that is being run
37  * @param column the column that is being processed
38  * @param[out] result mysql result
39  * @return
40  *   #GNUNET_OK if all results could be extracted
41  *   #GNUNET_SYSERR if a result was invalid
42  */
43 static int
44 pre_extract_varsize_blob(void *cls,
45                          struct GNUNET_MY_ResultSpec *rs,
46                          MYSQL_STMT *stmt,
47                          unsigned int column,
48                          MYSQL_BIND *results)
49 {
50   results[0].buffer = NULL;
51   results[0].buffer_length = 0;
52   results[0].length = &rs->mysql_bind_output_length;
53   results[0].is_null = &rs->is_null;
54   rs->is_null = 0;
55
56   return GNUNET_OK;
57 }
58
59
60 /**
61  * extract data from a Mysql database @a result at row @a row
62  *
63  * @param cls closure
64  * @param[in,out] rs
65  * @param stmt the mysql statement that is being run
66  * @param column the column that is being processed
67  * @param[out] results
68  * @return
69  *   #GNUNET_OK if all results could be extracted
70  *   #GNUNET_SYSERR if a result was invalid
71  */
72 static int
73 post_extract_varsize_blob(void *cls,
74                           struct GNUNET_MY_ResultSpec *rs,
75                           MYSQL_STMT *stmt,
76                           unsigned int column,
77                           MYSQL_BIND *results)
78 {
79   void *buf;
80   size_t size;
81
82   if (*results->is_null)
83     return GNUNET_SYSERR;
84   size = (size_t)rs->mysql_bind_output_length;
85
86   if (rs->mysql_bind_output_length != size)
87     return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
88
89   buf = GNUNET_malloc(size);
90
91   results[0].buffer = buf;
92   results[0].buffer_length = size;
93   results[0].buffer_type = MYSQL_TYPE_BLOB;
94
95   if (0 !=
96       mysql_stmt_fetch_column(stmt,
97                               results,
98                               column,
99                               0))
100     {
101       GNUNET_free(buf);
102       return GNUNET_SYSERR;
103     }
104
105   *(void **)rs->dst = buf;
106   *rs->result_size = size;
107
108   return GNUNET_OK;
109 }
110
111
112 /**
113  * extract data from a Mysql database @a result at row @a row
114  *
115  * @param cls closure
116  * @param[in,out] rs
117  */
118 static void
119 cleanup_varsize_blob(void *cls,
120                      struct GNUNET_MY_ResultSpec *rs)
121 {
122   void **ptr = (void **)rs->dst;
123
124   if (NULL != *ptr)
125     {
126       GNUNET_free(*ptr);
127       *ptr = NULL;
128     }
129 }
130
131
132 /**
133  * Variable-size result expected
134  *
135  * @param[out] dst where to store the result, allocated
136  * @param[out] ptr_size where to store the size of @a dst
137  * @return array entru for the result specification to use
138  */
139 struct GNUNET_MY_ResultSpec
140 GNUNET_MY_result_spec_variable_size(void **dst,
141                                     size_t *ptr_size)
142 {
143   struct GNUNET_MY_ResultSpec res =
144   {
145     .pre_conv = &pre_extract_varsize_blob,
146     .post_conv = &post_extract_varsize_blob,
147     .cleaner = &cleanup_varsize_blob,
148     .dst = (void *)(dst),
149     .result_size = ptr_size,
150     .num_fields = 1
151   };
152
153   return res;
154 }
155
156
157 /**
158  * Extract data from a Mysql database @a result at row @a row
159  *
160  * @param cls closure
161  * @param[in,out] rs
162  * @param stmt the mysql statement that is being run
163  * @param column the column that is being processed
164  * @param[out] results
165  * @return
166  *  #GNUNET_OK if all results could be extracted
167  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
168  */
169 static int
170 pre_extract_fixed_blob(void *cls,
171                        struct GNUNET_MY_ResultSpec *rs,
172                        MYSQL_STMT *stmt,
173                        unsigned int column,
174                        MYSQL_BIND *results)
175 {
176   results[0].buffer = rs->dst;
177   results[0].buffer_length = rs->dst_size;
178   results[0].length = &rs->mysql_bind_output_length;
179   results[0].buffer_type = MYSQL_TYPE_BLOB;
180   results[0].is_null = &rs->is_null;
181   rs->is_null = 0;
182
183   return GNUNET_OK;
184 }
185
186
187 /**
188  * Check size of extracted fixed size data from a Mysql database @a
189  * result at row @a row
190  *
191  * @param cls closure
192  * @param[in,out] rs
193  * @param stmt the mysql statement that is being run
194  * @param column the column that is being processed
195  * @param[out] results
196  * @return
197  *  #GNUNET_OK if all results could be extracted
198  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
199  */
200 static int
201 post_extract_fixed_blob(void *cls,
202                         struct GNUNET_MY_ResultSpec *rs,
203                         MYSQL_STMT *stmt,
204                         unsigned int column,
205                         MYSQL_BIND *results)
206 {
207   if (*results->is_null)
208     return GNUNET_SYSERR;
209   if (rs->dst_size != rs->mysql_bind_output_length)
210     return GNUNET_SYSERR;
211   return GNUNET_OK;
212 }
213
214
215 /**
216  * Fixed-size result expected.
217  *
218  * @param name name of the field in the table
219  * @param[out] dst where to store the result
220  * @param ptr_size number of bytes in @a dst
221  * @return array entry for the result specification to use
222  */
223 struct GNUNET_MY_ResultSpec
224 GNUNET_MY_result_spec_fixed_size(void *ptr,
225                                  size_t ptr_size)
226 {
227   struct GNUNET_MY_ResultSpec res =
228   {
229     .pre_conv = &pre_extract_fixed_blob,
230     .post_conv = &post_extract_fixed_blob,
231     .cleaner = NULL,
232     .dst = (void *)(ptr),
233     .dst_size = ptr_size,
234     .num_fields = 1
235   };
236
237   return res;
238 }
239
240
241 /**
242  * Extract data from a Mysql database @a result at row @a row
243  *
244  * @param cls closure
245  * @param[in,out] rs
246  * @param stmt the mysql statement that is being run
247  * @param column the column that is being processed
248  * @param[out] results
249  * @return
250  *   #GNUNET_OK if all results could be extracted
251  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
252  */
253 static int
254 pre_extract_rsa_public_key(void *cls,
255                            struct GNUNET_MY_ResultSpec *rs,
256                            MYSQL_STMT *stmt,
257                            unsigned int column,
258                            MYSQL_BIND *results)
259 {
260   results[0].buffer = NULL;
261   results[0].buffer_length = 0;
262   results[0].length = &rs->mysql_bind_output_length;
263   results[0].buffer_type = MYSQL_TYPE_BLOB;
264   results[0].is_null = &rs->is_null;
265   rs->is_null = 0;
266
267   return GNUNET_OK;
268 }
269
270
271 /**
272  * Check size of extracted fixed size data from a Mysql database @a
273  * result at row @a row
274  *
275  * @param cls closure
276  * @param[in,out] rs
277  * @param stmt the mysql statement that is being run
278  * @param column the column that is being processed
279  * @param[out] results
280  * @return
281  *   #GNUNET_OK if all results could be extracted
282  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
283  */
284 static int
285 post_extract_rsa_public_key(void *cls,
286                             struct GNUNET_MY_ResultSpec *rs,
287                             MYSQL_STMT *stmt,
288                             unsigned int column,
289                             MYSQL_BIND *results)
290
291 {
292   struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
293   void *buf;
294   size_t size;
295
296   if (*results->is_null)
297     return GNUNET_SYSERR;
298   size = (size_t)rs->mysql_bind_output_length;
299
300   if (rs->mysql_bind_output_length != size)
301     return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
302   buf = GNUNET_malloc(size);
303
304   results[0].buffer = buf;
305   results[0].buffer_length = size;
306   results[0].buffer_type = MYSQL_TYPE_BLOB;
307   if (0 !=
308       mysql_stmt_fetch_column(stmt,
309                               results,
310                               column,
311                               0))
312     {
313       GNUNET_free(buf);
314       return GNUNET_SYSERR;
315     }
316
317   *pk = GNUNET_CRYPTO_rsa_public_key_decode(buf,
318                                             size);
319   GNUNET_free(buf);
320   if (NULL == *pk)
321     {
322       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
323                  "Results contains bogus public key value (fail to decode)\n");
324       return GNUNET_SYSERR;
325     }
326
327   return GNUNET_OK;
328 }
329
330
331 /**
332  * Function called to clean up memory allocated
333  * by a #GNUNET_MY_ResultConverter.
334  *
335  * @param cls closure
336  * @param rs result data to clean up
337  */
338 static void
339 clean_rsa_public_key(void *cls,
340                      struct GNUNET_MY_ResultSpec *rs)
341 {
342   struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
343
344   if (NULL != *pk)
345     {
346       GNUNET_CRYPTO_rsa_public_key_free(*pk);
347       *pk = NULL;
348     }
349 }
350
351
352 /**
353  * RSA public key expected
354  *
355  * @param name name of the field in the table
356  * @param[out] rsa where to store the result
357  * @return array entry for the result specification to use
358  */
359 struct GNUNET_MY_ResultSpec
360 GNUNET_MY_result_spec_rsa_public_key(struct GNUNET_CRYPTO_RsaPublicKey **rsa)
361 {
362   struct GNUNET_MY_ResultSpec res = {
363     .pre_conv = &pre_extract_rsa_public_key,
364     .post_conv = &post_extract_rsa_public_key,
365     .cleaner = &clean_rsa_public_key,
366     .dst = (void *)rsa,
367     .dst_size = 0,
368     .num_fields = 1
369   };
370
371   return res;
372 }
373
374
375 /**
376  * Extract data from a Mysql database @a result at row @a row.
377  *
378  * @param cls closure
379  * @param[in,out] rs
380  * @param stmt the mysql statement that is being run
381  * @param column the column that is being processed
382  * @param[out] results
383  * @return
384  *    #GNUNET_OK if all results could be extracted
385  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
386  */
387 static int
388 pre_extract_rsa_signature(void *cls,
389                           struct GNUNET_MY_ResultSpec *rs,
390                           MYSQL_STMT *stmt,
391                           unsigned int column,
392                           MYSQL_BIND *results)
393 {
394   results[0].buffer = 0;
395   results[0].buffer_length = 0;
396   results[0].length = &rs->mysql_bind_output_length;
397   results[0].buffer_type = MYSQL_TYPE_BLOB;
398   results[0].is_null = &rs->is_null;
399   rs->is_null = 0;
400
401   return GNUNET_OK;
402 }
403
404
405 /**
406  * Extract data from a Mysql database @a result at row @a row.
407  *
408  * @param cls closure
409  * @param[in,out] rs
410  * @param stmt the mysql statement that is being run
411  * @param column the column that is being processed
412  * @param[out] results
413  * @return
414  *    #GNUNET_OK if all results could be extracted
415  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
416  */
417 static int
418 post_extract_rsa_signature(void *cls,
419                            struct GNUNET_MY_ResultSpec *rs,
420                            MYSQL_STMT *stmt,
421                            unsigned int column,
422                            MYSQL_BIND *results)
423 {
424   struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
425   void *buf;
426   size_t size;
427
428   if (*results->is_null)
429     return GNUNET_SYSERR;
430   size = (size_t)rs->mysql_bind_output_length;
431
432   if (rs->mysql_bind_output_length != size)
433     return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
434   buf = GNUNET_malloc(size);
435
436   results[0].buffer = buf;
437   results[0].buffer_length = size;
438   results[0].buffer_type = MYSQL_TYPE_BLOB;
439   if (0 !=
440       mysql_stmt_fetch_column(stmt,
441                               results,
442                               column,
443                               0))
444     {
445       GNUNET_free(buf);
446       return GNUNET_SYSERR;
447     }
448
449   *sig = GNUNET_CRYPTO_rsa_signature_decode(buf,
450                                             size);
451   GNUNET_free(buf);
452   if (NULL == *sig)
453     {
454       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
455                  "Resuls contains bogus signature value (fails to decode)\n");
456       return GNUNET_SYSERR;
457     }
458   return GNUNET_OK;
459 }
460
461
462 /**
463  * Function called to clean up memory allocated
464  * by a #GNUNET_MY_ResultConverter.
465  *
466  * @param cls closure
467  * @param rd result data to clean up
468  */
469 static void
470 clean_rsa_signature(void *cls,
471                     struct GNUNET_MY_ResultSpec *rs)
472 {
473   struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
474
475   if (NULL != *sig)
476     {
477       GNUNET_CRYPTO_rsa_signature_free(*sig);
478       *sig = NULL;
479     }
480 }
481
482
483 /**
484  * RSA signature expected.
485  *
486  * @param[out] sig where to store the result;
487  * @return array entry for the result specification to use
488  */
489 struct GNUNET_MY_ResultSpec
490 GNUNET_MY_result_spec_rsa_signature(struct GNUNET_CRYPTO_RsaSignature **sig)
491 {
492   struct GNUNET_MY_ResultSpec res =
493   {
494     .pre_conv = &pre_extract_rsa_signature,
495     .post_conv = &post_extract_rsa_signature,
496     .cleaner = &clean_rsa_signature,
497     .dst = (void *)sig,
498     .dst_size = 0,
499     .num_fields = 1
500   };
501
502   return res;
503 }
504
505
506 /**
507  * Extract data from a Mysql database @a result at row @a row
508  *
509  * @param cls closure
510  * @param[in,out] rs
511  * @param stmt the mysql statement that is being run
512  * @param column the column that is being processed
513  * @param[out] results
514  * @return
515  *    #GNUNET_OK if all results could be extracted
516  *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
517  */
518 static int
519 pre_extract_string(void * cls,
520                    struct GNUNET_MY_ResultSpec *rs,
521                    MYSQL_STMT *stmt,
522                    unsigned int column,
523                    MYSQL_BIND *results)
524 {
525   results[0].buffer = NULL;
526   results[0].buffer_length = 0;
527   results[0].length = &rs->mysql_bind_output_length;
528   results[0].buffer_type = MYSQL_TYPE_BLOB;
529   results[0].is_null = &rs->is_null;
530   rs->is_null = 0;
531
532   return GNUNET_OK;
533 }
534
535
536 /**
537  * Check size of extracted fixed size data from a Mysql database @a
538  *
539  * @param cls closure
540  * @param[in,out] rs
541  * @param stmt the mysql statement that is being run
542  * @param column the column that is being processed
543  * @param[out] results
544  * @return
545  *    #GNUNET_OK if all results could be extracted
546  *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
547  */
548 static int
549 post_extract_string(void * cls,
550                     struct GNUNET_MY_ResultSpec *rs,
551                     MYSQL_STMT *stmt,
552                     unsigned int column,
553                     MYSQL_BIND *results)
554 {
555   size_t size = (size_t)rs->mysql_bind_output_length;
556   char *buf;
557
558   if (rs->mysql_bind_output_length != size)
559     return GNUNET_SYSERR;
560   if (*results->is_null)
561     {
562       *(void **)rs->dst = NULL;
563       return GNUNET_OK;
564     }
565
566   buf = GNUNET_malloc(size);
567   results[0].buffer = buf;
568   results[0].buffer_length = size;
569   results[0].buffer_type = MYSQL_TYPE_BLOB;
570
571   if (0 !=
572       mysql_stmt_fetch_column(stmt,
573                               results,
574                               column,
575                               0))
576     {
577       GNUNET_free(buf);
578       return GNUNET_SYSERR;
579     }
580   buf[size] = '\0';
581   *(void **)rs->dst = buf;
582   return GNUNET_OK;
583 }
584
585
586 /**
587  * 0- terminated string exprected.
588  *
589  * @param[out] dst where to store the result, allocated
590  * @return array entry for the result specification to use
591  */
592 struct GNUNET_MY_ResultSpec
593 GNUNET_MY_result_spec_string(char **dst)
594 {
595   struct GNUNET_MY_ResultSpec res = {
596     .pre_conv = &pre_extract_string,
597     .post_conv = &post_extract_string,
598     .cleaner = NULL,
599     .dst = (void *)dst,
600     .dst_size = 0,
601     .num_fields = 1
602   };
603
604   return res;
605 }
606
607
608 /**
609  * Absolute time expected
610  *
611  * @param name name of the field in the table
612  * @param[out] at where to store the result
613  * @return array entry for the result specification to use
614  */
615 struct GNUNET_MY_ResultSpec
616 GNUNET_MY_result_spec_absolute_time(struct GNUNET_TIME_Absolute *at)
617 {
618   return GNUNET_MY_result_spec_uint64(&at->abs_value_us);
619 }
620
621
622 /**
623  * Absolute time in network byte order expected
624  *
625  * @param[out] at where to store the result
626  * @return array entry for the result specification to use
627  */
628 struct GNUNET_MY_ResultSpec
629 GNUNET_MY_result_spec_absolute_time_nbo(struct GNUNET_TIME_AbsoluteNBO *at)
630 {
631   struct GNUNET_MY_ResultSpec res =
632     GNUNET_MY_result_spec_auto_from_type(&at->abs_value_us__);
633
634   return res;
635 }
636
637
638 /**
639  * Extract data from a Postgres database @a result at row @a row.
640  *
641  * @param cls closure
642  * @param[in,out] rs
643  * @param stmt the mysql statement that is being run
644  * @param column the column that is being processed
645  * @param[out] results
646  * @return
647  *   #GNUNET_YES if all results could be extracted
648  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
649  */
650 static int
651 pre_extract_uint16(void *cls,
652                    struct GNUNET_MY_ResultSpec *rs,
653                    MYSQL_STMT *stmt,
654                    unsigned int column,
655                    MYSQL_BIND *results)
656 {
657   results[0].buffer = rs->dst;
658   results[0].buffer_length = rs->dst_size;
659   results[0].length = &rs->mysql_bind_output_length;
660   results[0].buffer_type = MYSQL_TYPE_SHORT;
661   results[0].is_null = &rs->is_null;
662   rs->is_null = 0;
663
664   return GNUNET_OK;
665 }
666
667
668 /**
669  * Check size of extracted fixed size data from a Mysql datbase.
670  *
671  * @param cls closure
672  * @param[in,out] rs
673  * @param stmt the mysql statement that is being run
674  * @param column the column that is being processed
675  * @param[out] results
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 post_extract_uint16(void *cls,
682                     struct GNUNET_MY_ResultSpec *rs,
683                     MYSQL_STMT *stmt,
684                     unsigned int column,
685                     MYSQL_BIND *results)
686 {
687   if (rs->dst_size != rs->mysql_bind_output_length)
688     return GNUNET_SYSERR;
689   if (*results->is_null)
690     return GNUNET_SYSERR;
691   return GNUNET_OK;
692 }
693
694
695 /**
696  * uint16_t expected
697  *
698  * @param[out] u16 where to store the result
699  * @return array entry for the result specification to use
700  */
701 struct GNUNET_MY_ResultSpec
702 GNUNET_MY_result_spec_uint16(uint16_t *u16)
703 {
704   struct GNUNET_MY_ResultSpec res = {
705     .pre_conv = &pre_extract_uint16,
706     .post_conv = &post_extract_uint16,
707     .cleaner = NULL,
708     .dst = (void *)u16,
709     .dst_size = sizeof(*u16),
710     .num_fields = 1
711   };
712
713   return res;
714 }
715
716
717 /**
718  * Extrac data from a  MYSQL database @a result at row @a row
719  *
720  * @param cls closure
721  * @param cls closure
722  * @param[in,out] rs
723  * @param stmt the mysql statement that is being run
724  * @param column the column that is being processed
725  * @param[out] results
726  * @return
727  *      #GNUNET_OK if all results could be extracted
728  *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
729  */
730 static int
731 pre_extract_uint32(void *cls,
732                    struct GNUNET_MY_ResultSpec *rs,
733                    MYSQL_STMT *stmt,
734                    unsigned int column,
735                    MYSQL_BIND *results)
736 {
737   results[0].buffer = rs->dst;
738   results[0].buffer_length = rs->dst_size;
739   results[0].length = &rs->mysql_bind_output_length;
740   results[0].buffer_type = MYSQL_TYPE_LONG;
741   results[0].is_null = &rs->is_null;
742   rs->is_null = 0;
743
744   return GNUNET_OK;
745 }
746
747
748 /**
749  * Extrac data from a  MYSQL database @a result at row @a row
750  *
751  * @param cls closure
752  * @param cls closure
753  * @param[in,out] rs
754  * @param stmt the mysql statement that is being run
755  * @param column the column that is being processed
756  * @param[out] results
757  * @return
758  *      #GNUNET_OK if all results could be extracted
759  *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
760  */
761 static int
762 post_extract_uint32(void *cls,
763                     struct GNUNET_MY_ResultSpec *rs,
764                     MYSQL_STMT * stmt,
765                     unsigned int column,
766                     MYSQL_BIND *results)
767 {
768   if (rs->dst_size != rs->mysql_bind_output_length)
769     return GNUNET_SYSERR;
770   if (*results->is_null)
771     return GNUNET_SYSERR;
772   return GNUNET_OK;
773 }
774
775
776 /**
777  * uint32_t expected
778  *
779  * @param[out] u32 where to store the result
780  * @return array entry for the result specification to use
781  */
782 struct GNUNET_MY_ResultSpec
783 GNUNET_MY_result_spec_uint32(uint32_t *u32)
784 {
785   struct GNUNET_MY_ResultSpec res = {
786     .pre_conv = &pre_extract_uint32,
787     .post_conv = &post_extract_uint32,
788     .cleaner = NULL,
789     .dst = (void *)u32,
790     .dst_size = sizeof(*u32),
791     .num_fields = 1
792   };
793
794   return res;
795 }
796
797
798 /**
799  * Extract data from a MYSQL database @a result at row @a row
800  *
801  * @param cls closure
802  * @param[in,out] rs
803  * @param stmt the mysql statement that is being run
804  * @param column the column that is being processed
805  * @param[out] results
806  * @return
807  *    #GNUNET_OK if all results could be extracted
808  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
809  */
810 static int
811 pre_extract_uint64(void *cls,
812                    struct GNUNET_MY_ResultSpec *rs,
813                    MYSQL_STMT *stmt,
814                    unsigned int column,
815                    MYSQL_BIND *results)
816 {
817   if (sizeof(uint64_t) != rs->dst_size)
818     return GNUNET_SYSERR;
819   results[0].buffer = rs->dst;
820   results[0].buffer_length = rs->dst_size;
821   results[0].length = &rs->mysql_bind_output_length;
822   results[0].buffer_type = MYSQL_TYPE_LONGLONG;
823   results[0].is_null = &rs->is_null;
824   rs->is_null = 0;
825
826   return GNUNET_OK;
827 }
828
829
830 /**
831  * Check size of extracted fixe size data from a Mysql database
832  *
833  * @param cls closure
834  * @param[in,out] rs
835  * @param stmt the mysql statement that is being run
836  * @param column the column that is being processed
837  * @param[out] results
838  * @return
839  *    #GNUNET_OK if all results could be extracted
840  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
841  */
842 static int
843 post_extract_uint64(void *cls,
844                     struct GNUNET_MY_ResultSpec *rs,
845                     MYSQL_STMT *stmt,
846                     unsigned int column,
847                     MYSQL_BIND *results)
848 {
849   if (sizeof(uint64_t) != rs->dst_size)
850     return GNUNET_SYSERR;
851   if (*results->is_null)
852     return GNUNET_SYSERR;
853   return GNUNET_OK;
854 }
855
856
857 /**
858  * uint64_t expected.
859  *
860  * @param[out] u64 where to store the result
861  * @return array entry for the result specification to use
862  */
863 struct GNUNET_MY_ResultSpec
864 GNUNET_MY_result_spec_uint64(uint64_t *u64)
865 {
866   struct GNUNET_MY_ResultSpec res = {
867     .pre_conv = &pre_extract_uint64,
868     .post_conv = &post_extract_uint64,
869     .cleaner = NULL,
870     .dst = (void *)u64,
871     .dst_size = sizeof(*u64),
872     .num_fields = 1
873   };
874
875   return res;
876 }
877
878
879 /* end of my_result_helper.c */