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