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