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