Merge branch 'license/spdx'
[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   return res;
502 }
503
504
505 /**
506  * Extract data from a Mysql database @a result at row @a row
507  *
508  * @param cls closure
509  * @param[in,out] rs
510  * @param stmt the mysql statement that is being run
511  * @param column the column that is being processed
512  * @param[out] results
513  * @return
514  *    #GNUNET_OK if all results could be extracted
515  *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
516  */
517 static int
518 pre_extract_string (void * cls,
519                     struct GNUNET_MY_ResultSpec *rs,
520                     MYSQL_STMT *stmt,
521                     unsigned int column,
522                     MYSQL_BIND *results)
523 {
524   results[0].buffer = NULL;
525   results[0].buffer_length = 0;
526   results[0].length = &rs->mysql_bind_output_length;
527   results[0].buffer_type = MYSQL_TYPE_BLOB;
528   results[0].is_null = &rs->is_null;
529   rs->is_null = 0;
530
531   return GNUNET_OK;
532 }
533
534
535 /**
536  * Check size of extracted fixed size data from a Mysql database @a
537  *
538  * @param cls closure
539  * @param[in,out] rs
540  * @param stmt the mysql statement that is being run
541  * @param column the column that is being processed
542  * @param[out] results
543  * @return
544  *    #GNUNET_OK if all results could be extracted
545  *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
546  */
547 static int
548 post_extract_string (void * cls,
549                      struct GNUNET_MY_ResultSpec *rs,
550                      MYSQL_STMT *stmt,
551                      unsigned int column,
552                      MYSQL_BIND *results)
553 {
554   size_t size = (size_t) rs->mysql_bind_output_length;
555   char *buf;
556
557   if (rs->mysql_bind_output_length != size)
558     return GNUNET_SYSERR;
559   if (*results->is_null)
560   {
561     *(void **) rs->dst = NULL;
562     return GNUNET_OK;
563   }
564
565   buf = GNUNET_malloc (size);
566   results[0].buffer = buf;
567   results[0].buffer_length = size;
568   results[0].buffer_type = MYSQL_TYPE_BLOB;
569
570   if (0 !=
571       mysql_stmt_fetch_column (stmt,
572                                results,
573                                column,
574                                0))
575   {
576     GNUNET_free (buf);
577     return GNUNET_SYSERR;
578   }
579   buf[size] = '\0';
580   *(void **) rs->dst = buf;
581   return GNUNET_OK;
582 }
583
584
585 /**
586  * 0- terminated string exprected.
587  *
588  * @param[out] dst where to store the result, allocated
589  * @return array entry for the result specification to use
590  */
591 struct GNUNET_MY_ResultSpec
592 GNUNET_MY_result_spec_string (char **dst)
593 {
594   struct GNUNET_MY_ResultSpec res = {
595     .pre_conv = &pre_extract_string,
596     .post_conv = &post_extract_string,
597     .cleaner = NULL,
598     .dst = (void *) dst,
599     .dst_size = 0,
600     .num_fields = 1
601   };
602   return res;
603 }
604
605
606 /**
607  * Absolute time expected
608  *
609  * @param name name of the field in the table
610  * @param[out] at where to store the result
611  * @return array entry for the result specification to use
612   */
613 struct GNUNET_MY_ResultSpec
614 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
615 {
616   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
617 }
618
619
620 /**
621   * Absolute time in network byte order expected
622   *
623   * @param[out] at where to store the result
624   * @return array entry for the result specification to use
625   */
626 struct GNUNET_MY_ResultSpec
627 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
628 {
629   struct GNUNET_MY_ResultSpec res =
630     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
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   return res;
710 }
711
712
713 /**
714   * Extrac data from a  MYSQL database @a result at row @a row
715   *
716   * @param cls closure
717   * @param cls closure
718   * @param[in,out] rs
719   * @param stmt the mysql statement that is being run
720   * @param column the column that is being processed
721   * @param[out] results
722   * @return
723   *      #GNUNET_OK if all results could be extracted
724   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
725   */
726 static int
727 pre_extract_uint32 (void *cls,
728                     struct GNUNET_MY_ResultSpec *rs,
729                     MYSQL_STMT *stmt,
730                     unsigned int column,
731                     MYSQL_BIND *results)
732 {
733   results[0].buffer = rs->dst;
734   results[0].buffer_length = rs->dst_size;
735   results[0].length = &rs->mysql_bind_output_length;
736   results[0].buffer_type = MYSQL_TYPE_LONG;
737   results[0].is_null = &rs->is_null;
738   rs->is_null = 0;
739
740   return GNUNET_OK;
741 }
742
743
744 /**
745   * Extrac data from a  MYSQL database @a result at row @a row
746   *
747   * @param cls closure
748   * @param cls closure
749   * @param[in,out] rs
750   * @param stmt the mysql statement that is being run
751   * @param column the column that is being processed
752   * @param[out] results
753   * @return
754   *      #GNUNET_OK if all results could be extracted
755   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
756   */
757 static int
758 post_extract_uint32 (void *cls,
759                      struct GNUNET_MY_ResultSpec *rs,
760                      MYSQL_STMT * stmt,
761                      unsigned int column,
762                      MYSQL_BIND *results)
763 {
764   if (rs->dst_size != rs->mysql_bind_output_length)
765     return GNUNET_SYSERR;
766   if (*results->is_null)
767     return GNUNET_SYSERR;
768   return GNUNET_OK;
769 }
770
771
772 /**
773   * uint32_t expected
774   *
775   * @param[out] u32 where to store the result
776   * @return array entry for the result specification to use
777   */
778 struct GNUNET_MY_ResultSpec
779 GNUNET_MY_result_spec_uint32 (uint32_t *u32)
780 {
781   struct GNUNET_MY_ResultSpec res = {
782     .pre_conv = &pre_extract_uint32,
783     .post_conv = &post_extract_uint32,
784     .cleaner = NULL,
785     .dst = (void *) u32,
786     .dst_size = sizeof (*u32),
787     .num_fields = 1
788   };
789   return res;
790 }
791
792
793 /**
794  * Extract data from a MYSQL database @a result at row @a row
795  *
796  * @param cls closure
797  * @param[in,out] rs
798  * @param stmt the mysql statement that is being run
799  * @param column the column that is being processed
800  * @param[out] results
801  * @return
802  *    #GNUNET_OK if all results could be extracted
803  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
804  */
805 static int
806 pre_extract_uint64 (void *cls,
807                     struct GNUNET_MY_ResultSpec *rs,
808                     MYSQL_STMT *stmt,
809                     unsigned int column,
810                     MYSQL_BIND *results)
811 {
812   if (sizeof (uint64_t) != rs->dst_size)
813     return GNUNET_SYSERR;
814   results[0].buffer = rs->dst;
815   results[0].buffer_length = rs->dst_size;
816   results[0].length = &rs->mysql_bind_output_length;
817   results[0].buffer_type = MYSQL_TYPE_LONGLONG;
818   results[0].is_null = &rs->is_null;
819   rs->is_null = 0;
820
821   return GNUNET_OK;
822 }
823
824
825 /**
826  * Check size of extracted fixe size data from a Mysql database
827  *
828  * @param cls closure
829  * @param[in,out] rs
830  * @param stmt the mysql statement that is being run
831  * @param column the column that is being processed
832  * @param[out] results
833  * @return
834  *    #GNUNET_OK if all results could be extracted
835  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
836  */
837 static int
838 post_extract_uint64 (void *cls,
839                      struct GNUNET_MY_ResultSpec *rs,
840                      MYSQL_STMT *stmt,
841                      unsigned int column,
842                      MYSQL_BIND *results)
843 {
844   if (sizeof (uint64_t) != rs->dst_size)
845     return GNUNET_SYSERR;
846   if (*results->is_null)
847     return GNUNET_SYSERR;
848   return GNUNET_OK;
849 }
850
851
852 /**
853  * uint64_t expected.
854  *
855  * @param[out] u64 where to store the result
856  * @return array entry for the result specification to use
857  */
858 struct GNUNET_MY_ResultSpec
859 GNUNET_MY_result_spec_uint64 (uint64_t *u64)
860 {
861   struct GNUNET_MY_ResultSpec res = {
862     .pre_conv = &pre_extract_uint64,
863     .post_conv = &post_extract_uint64,
864     .cleaner = NULL,
865     .dst = (void *) u64,
866     .dst_size = sizeof (*u64),
867     .num_fields = 1
868   };
869   return res;
870 }
871
872
873 /* end of my_result_helper.c */