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