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