-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[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 /**
19  * @file my/my_result_helper.c
20  * @brief functions to extract result values
21  * @author Christophe Genevey
22  */
23
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_my_lib.h"
27
28
29 /**
30  * extract data from a Mysql database @a result at row @a row
31  *
32  * @param cls closure
33  * @param[in,out] rs
34  * @param stmt the mysql statement that is being run
35  * @param column the column that is being processed
36  * @param[out] result mysql result
37  * @return
38  *   #GNUNET_OK if all results could be extracted
39  *   #GNUNET_SYSERR if a result was invalid
40  */
41 static int
42 pre_extract_varsize_blob (void *cls,
43                           struct GNUNET_MY_ResultSpec *rs,
44                           MYSQL_STMT *stmt,
45                           unsigned int column,
46                           MYSQL_BIND *results)
47 {
48   results[0].buffer = NULL;
49   results[0].buffer_length = 0;
50   results[0].length = &rs->mysql_bind_output_length;
51   results[0].is_null = &rs->is_null;
52   rs->is_null = 0;
53
54   return GNUNET_OK;
55 }
56
57
58 /**
59  * extract data from a Mysql database @a result at row @a row
60  *
61  * @param cls closure
62  * @param[in,out] rs
63  * @param stmt the mysql statement that is being run
64  * @param column the column that is being processed
65  * @param[out] results
66  * @return
67  *   #GNUNET_OK if all results could be extracted
68  *   #GNUNET_SYSERR if a result was invalid
69  */
70 static int
71 post_extract_varsize_blob (void *cls,
72                            struct GNUNET_MY_ResultSpec *rs,
73                            MYSQL_STMT *stmt,
74                            unsigned int column,
75                            MYSQL_BIND *results)
76 {
77   void *buf;
78   size_t size;
79
80   if (*results->is_null)
81     return GNUNET_SYSERR;
82   size = (size_t) rs->mysql_bind_output_length;
83
84   if (rs->mysql_bind_output_length != size)
85     return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
86
87   buf = GNUNET_malloc (size);
88
89   results[0].buffer = buf;
90   results[0].buffer_length = size;
91   results[0].buffer_type = MYSQL_TYPE_BLOB;
92
93   if (0 !=
94       mysql_stmt_fetch_column (stmt,
95                                results,
96                                column,
97                                0))
98   {
99     GNUNET_free (buf);
100     return GNUNET_SYSERR;
101   }
102
103   *(void **) rs->dst = buf;
104   *rs->result_size = size;
105
106   return GNUNET_OK;
107 }
108
109
110 /**
111  * extract data from a Mysql database @a result at row @a row
112  *
113  * @param cls closure
114  * @param[in,out] rs
115  */
116 static void
117 cleanup_varsize_blob (void *cls,
118                       struct GNUNET_MY_ResultSpec *rs)
119 {
120   void **ptr = (void **)rs->dst;
121
122   if (NULL != *ptr)
123   {
124     GNUNET_free (*ptr);
125     *ptr = NULL;
126   }
127 }
128
129
130 /**
131  * Variable-size result expected
132  *
133  * @param[out] dst where to store the result, allocated
134  * @param[out] ptr_size where to store the size of @a dst
135  * @return array entru for the result specification to use
136  */
137 struct GNUNET_MY_ResultSpec
138 GNUNET_MY_result_spec_variable_size (void **dst,
139                                     size_t *ptr_size)
140 {
141   struct GNUNET_MY_ResultSpec res =
142   {
143     .pre_conv = &pre_extract_varsize_blob,
144     .post_conv = &post_extract_varsize_blob,
145     .cleaner = &cleanup_varsize_blob,
146     .dst =  (void *)(dst),
147     .result_size = ptr_size,
148     .num_fields = 1
149   };
150
151   return res;
152 }
153
154
155 /**
156  * Extract data from a Mysql database @a result at row @a row
157  *
158  * @param cls closure
159  * @param[in,out] rs
160  * @param stmt the mysql statement that is being run
161  * @param column the column that is being processed
162  * @param[out] results
163  * @return
164  *  #GNUNET_OK if all results could be extracted
165  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
166  */
167 static int
168 pre_extract_fixed_blob (void *cls,
169                         struct GNUNET_MY_ResultSpec *rs,
170                         MYSQL_STMT *stmt,
171                         unsigned int column,
172                         MYSQL_BIND *results)
173 {
174   results[0].buffer = rs->dst;
175   results[0].buffer_length = rs->dst_size;
176   results[0].length = &rs->mysql_bind_output_length;
177   results[0].buffer_type = MYSQL_TYPE_BLOB;
178   results[0].is_null = &rs->is_null;
179   rs->is_null = 0;
180
181   return GNUNET_OK;
182 }
183
184
185 /**
186  * Check size of extracted fixed size data from a Mysql database @a
187  * result at row @a row
188  *
189  * @param cls closure
190  * @param[in,out] rs
191  * @param stmt the mysql statement that is being run
192  * @param column the column that is being processed
193  * @param[out] results
194  * @return
195  *  #GNUNET_OK if all results could be extracted
196  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
197  */
198 static int
199 post_extract_fixed_blob (void *cls,
200                          struct GNUNET_MY_ResultSpec *rs,
201                          MYSQL_STMT *stmt,
202                          unsigned int column,
203                          MYSQL_BIND *results)
204 {
205   if (*results->is_null)
206     return GNUNET_SYSERR;
207   if (rs->dst_size != rs->mysql_bind_output_length)
208     return GNUNET_SYSERR;
209   return GNUNET_OK;
210 }
211
212
213 /**
214  * Fixed-size result expected.
215  *
216  * @param name name of the field in the table
217  * @param[out] dst where to store the result
218  * @param ptr_size number of bytes in @a dst
219  * @return array entry for the result specification to use
220  */
221 struct GNUNET_MY_ResultSpec
222 GNUNET_MY_result_spec_fixed_size (void *ptr,
223                                   size_t ptr_size)
224 {
225   struct GNUNET_MY_ResultSpec res =
226   {
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   {
492     .pre_conv = &pre_extract_rsa_signature,
493     .post_conv = &post_extract_rsa_signature,
494     .cleaner = &clean_rsa_signature,
495     .dst = (void *)sig,
496     .dst_size = 0,
497     .num_fields = 1
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   return res;
601 }
602
603
604 /**
605  * Absolute time expected
606  *
607  * @param name name of the field in the table
608  * @param[out] at where to store the result
609  * @return array entry for the result specification to use
610   */
611 struct GNUNET_MY_ResultSpec
612 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
613 {
614   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
615 }
616
617
618 /**
619   * Absolute time in network byte order expected
620   *
621   * @param[out] at where to store the result
622   * @return array entry for the result specification to use
623   */
624 struct GNUNET_MY_ResultSpec
625 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
626 {
627   struct GNUNET_MY_ResultSpec res =
628     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
629   return res;
630 }
631
632
633 /**
634  * Extract data from a Postgres database @a result at row @a row.
635  *
636  * @param cls closure
637  * @param[in,out] rs
638  * @param stmt the mysql statement that is being run
639  * @param column the column that is being processed
640  * @param[out] results
641  * @return
642  *   #GNUNET_YES if all results could be extracted
643  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
644  */
645 static int
646 pre_extract_uint16 (void *cls,
647                     struct GNUNET_MY_ResultSpec *rs,
648                     MYSQL_STMT *stmt,
649                     unsigned int column,
650                     MYSQL_BIND *results)
651 {
652   results[0].buffer = rs->dst;
653   results[0].buffer_length = rs->dst_size;
654   results[0].length = &rs->mysql_bind_output_length;
655   results[0].buffer_type = MYSQL_TYPE_SHORT;
656   results[0].is_null = &rs->is_null;
657   rs->is_null = 0;
658
659   return GNUNET_OK;
660 }
661
662
663 /**
664  * Check size of extracted fixed size data from a Mysql datbase.
665  *
666  * @param cls closure
667  * @param[in,out] rs
668  * @param stmt the mysql statement that is being run
669  * @param column the column that is being processed
670  * @param[out] results
671  * @return
672  *   #GNUNET_YES if all results could be extracted
673  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
674  */
675 static int
676 post_extract_uint16 (void *cls,
677                      struct GNUNET_MY_ResultSpec *rs,
678                      MYSQL_STMT *stmt,
679                      unsigned int column,
680                      MYSQL_BIND *results)
681 {
682   if (rs->dst_size != rs->mysql_bind_output_length)
683     return GNUNET_SYSERR;
684   if (*results->is_null)
685     return GNUNET_SYSERR;
686   return GNUNET_OK;
687 }
688
689
690 /**
691  * uint16_t expected
692  *
693  * @param[out] u16 where to store the result
694  * @return array entry for the result specification to use
695  */
696 struct GNUNET_MY_ResultSpec
697 GNUNET_MY_result_spec_uint16 (uint16_t *u16)
698 {
699   struct GNUNET_MY_ResultSpec res = {
700     .pre_conv = &pre_extract_uint16,
701     .post_conv = &post_extract_uint16,
702     .cleaner = NULL,
703     .dst = (void *) u16,
704     .dst_size = sizeof (*u16),
705     .num_fields = 1
706   };
707   return res;
708 }
709
710
711 /**
712   * Extrac data from a  MYSQL database @a result at row @a row
713   *
714   * @param cls closure
715   * @param cls closure
716   * @param[in,out] rs
717   * @param stmt the mysql statement that is being run
718   * @param column the column that is being processed
719   * @param[out] results
720   * @return
721   *      #GNUNET_OK if all results could be extracted
722   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
723   */
724 static int
725 pre_extract_uint32 (void *cls,
726                     struct GNUNET_MY_ResultSpec *rs,
727                     MYSQL_STMT *stmt,
728                     unsigned int column,
729                     MYSQL_BIND *results)
730 {
731   results[0].buffer = rs->dst;
732   results[0].buffer_length = rs->dst_size;
733   results[0].length = &rs->mysql_bind_output_length;
734   results[0].buffer_type = MYSQL_TYPE_LONG;
735   results[0].is_null = &rs->is_null;
736   rs->is_null = 0;
737
738   return GNUNET_OK;
739 }
740
741
742 /**
743   * Extrac data from a  MYSQL database @a result at row @a row
744   *
745   * @param cls closure
746   * @param cls closure
747   * @param[in,out] rs
748   * @param stmt the mysql statement that is being run
749   * @param column the column that is being processed
750   * @param[out] results
751   * @return
752   *      #GNUNET_OK if all results could be extracted
753   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
754   */
755 static int
756 post_extract_uint32 (void *cls,
757                      struct GNUNET_MY_ResultSpec *rs,
758                      MYSQL_STMT * stmt,
759                      unsigned int column,
760                      MYSQL_BIND *results)
761 {
762   if (rs->dst_size != rs->mysql_bind_output_length)
763     return GNUNET_SYSERR;
764   if (*results->is_null)
765     return GNUNET_SYSERR;
766   return GNUNET_OK;
767 }
768
769
770 /**
771   * uint32_t expected
772   *
773   * @param[out] u32 where to store the result
774   * @return array entry for the result specification to use
775   */
776 struct GNUNET_MY_ResultSpec
777 GNUNET_MY_result_spec_uint32 (uint32_t *u32)
778 {
779   struct GNUNET_MY_ResultSpec res = {
780     .pre_conv = &pre_extract_uint32,
781     .post_conv = &post_extract_uint32,
782     .cleaner = NULL,
783     .dst = (void *) u32,
784     .dst_size = sizeof (*u32),
785     .num_fields = 1
786   };
787   return res;
788 }
789
790
791 /**
792  * Extract data from a MYSQL database @a result at row @a row
793  *
794  * @param cls closure
795  * @param[in,out] rs
796  * @param stmt the mysql statement that is being run
797  * @param column the column that is being processed
798  * @param[out] results
799  * @return
800  *    #GNUNET_OK if all results could be extracted
801  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
802  */
803 static int
804 pre_extract_uint64 (void *cls,
805                     struct GNUNET_MY_ResultSpec *rs,
806                     MYSQL_STMT *stmt,
807                     unsigned int column,
808                     MYSQL_BIND *results)
809 {
810   if (sizeof (uint64_t) != rs->dst_size)
811     return GNUNET_SYSERR;
812   results[0].buffer = rs->dst;
813   results[0].buffer_length = rs->dst_size;
814   results[0].length = &rs->mysql_bind_output_length;
815   results[0].buffer_type = MYSQL_TYPE_LONGLONG;
816   results[0].is_null = &rs->is_null;
817   rs->is_null = 0;
818
819   return GNUNET_OK;
820 }
821
822
823 /**
824  * Check size of extracted fixe size data from a Mysql database
825  *
826  * @param cls closure
827  * @param[in,out] rs
828  * @param stmt the mysql statement that is being run
829  * @param column the column that is being processed
830  * @param[out] results
831  * @return
832  *    #GNUNET_OK if all results could be extracted
833  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
834  */
835 static int
836 post_extract_uint64 (void *cls,
837                      struct GNUNET_MY_ResultSpec *rs,
838                      MYSQL_STMT *stmt,
839                      unsigned int column,
840                      MYSQL_BIND *results)
841 {
842   if (sizeof (uint64_t) != rs->dst_size)
843     return GNUNET_SYSERR;
844   if (*results->is_null)
845     return GNUNET_SYSERR;
846   return GNUNET_OK;
847 }
848
849
850 /**
851  * uint64_t expected.
852  *
853  * @param[out] u64 where to store the result
854  * @return array entry for the result specification to use
855  */
856 struct GNUNET_MY_ResultSpec
857 GNUNET_MY_result_spec_uint64 (uint64_t *u64)
858 {
859   struct GNUNET_MY_ResultSpec res = {
860     .pre_conv = &pre_extract_uint64,
861     .post_conv = &post_extract_uint64,
862     .cleaner = NULL,
863     .dst = (void *) u64,
864     .dst_size = sizeof (*u64),
865     .num_fields = 1
866   };
867   return res;
868 }
869
870
871 /* end of my_result_helper.c */