REST: nothing triggers rest
[oweals/gnunet.git] / src / my / my_result_helper.c
index f58c8e1507d106d48040e14c593416764a75cebd..75a3400144dd12ccb30a6a73f97215436c0534bb 100644 (file)
@@ -1,14 +1,21 @@
  /*
   This file is part of GNUnet
   Copyright (C) 2014, 2015, 2016 GNUnet e.V.
-  GNUnet is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-  GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License along with
-  GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
+
+  GNUnet is free software: you can redistribute it and/or modify it
+  under the terms of the GNU Affero General Public License as published
+  by the Free Software Foundation, either version 3 of the License,
+  or (at your option) any later version.
+
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Affero General Public License for more details.
+  You should have received a copy of the GNU Affero General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 /**
  * @file my/my_result_helper.c
 #include "gnunet_util_lib.h"
 #include "gnunet_my_lib.h"
 
+
 /**
-  * extract data from a Mysql database @a result at row @a row
-  *
-  * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in, out] dst_size where to store size of result, may be NULL
-  * @param[out] dst where to store the result
-  * @return
-  *   #GNUNET_OK if all results could be extracted
-  *   #GNUNET_SYSERR if a result was invalid
-  */
+ * extract data from a Mysql database @a result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] result mysql result
+ * @return
+ *   #GNUNET_OK if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid
+ */
 static int
-extract_varsize_blob (void *cls,
-                      MYSQL_RES * result,
-                      int row,
-                      const char *fname,
-                      size_t *dst_size,
-                      void *dst)
+pre_extract_varsize_blob (void *cls,
+                          struct GNUNET_MY_ResultSpec *rs,
+                          MYSQL_STMT *stmt,
+                          unsigned int column,
+                          MYSQL_BIND *results)
 {
-  const char *res;
-  void *idst;
-  size_t len;
-
-  MYSQL_ROW rows;
-  MYSQL_FIELD *field;
+  results[0].buffer = NULL;
+  results[0].buffer_length = 0;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  rows = mysql_fetch_row (result);
+  return GNUNET_OK;
+}
 
-  field = mysql_fetch_field (result);
 
-  //If it's the correct field
-  if (field->name != fname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
+/**
+ * extract data from a Mysql database @a result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *   #GNUNET_OK if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid
+ */
+static int
+post_extract_varsize_blob (void *cls,
+                           struct GNUNET_MY_ResultSpec *rs,
+                           MYSQL_STMT *stmt,
+                           unsigned int column,
+                           MYSQL_BIND *results)
+{
+  void *buf;
+  size_t size;
 
+  if (*results->is_null)
     return GNUNET_SYSERR;
-  }
+  size = (size_t) rs->mysql_bind_output_length;
+
+  if (rs->mysql_bind_output_length != size)
+    return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
 
+  buf = GNUNET_malloc (size);
 
-  if (rows[row] == NULL)
+  results[0].buffer = buf;
+  results[0].buffer_length = size;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+
+  if (0 !=
+      mysql_stmt_fetch_column (stmt,
+                               results,
+                               column,
+                               0))
   {
+    GNUNET_free (buf);
     return GNUNET_SYSERR;
   }
 
-  res = rows[row];
+  *(void **) rs->dst = buf;
+  *rs->result_size = size;
 
-  len = strlen(res);
+  return GNUNET_OK;
+}
 
-  GNUNET_assert (NULL != res);
-  
-  *dst_size = len;
-  idst = GNUNET_malloc (len);
-  *((void **) dst) = idst;
-  memcpy (idst,
-          res,
-          len);
 
-  return GNUNET_OK;
+/**
+ * extract data from a Mysql database @a result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ */
+static void
+cleanup_varsize_blob (void *cls,
+                      struct GNUNET_MY_ResultSpec *rs)
+{
+  void **ptr = (void **)rs->dst;
+
+  if (NULL != *ptr)
+  {
+    GNUNET_free (*ptr);
+    *ptr = NULL;
+  }
 }
 
+
 /**
 * Variable-size result expected
 *
 * @param[out] dst where to store the result, allocated
 * @param[out] sptr where to store the size of @a dst
 * @return array entru for the result specification to use
 */
+ * Variable-size result expected
+ *
+ * @param[out] dst where to store the result, allocated
* @param[out] ptr_size where to store the size of @a dst
+ * @return array entru for the result specification to use
+ */
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_variable_size (void **dst,
                                     size_t *ptr_size)
 {
-  struct GNUNET_MY_ResultSpec res = {
-    &extract_varsize_blob,
-    NULL,
-    (void *)(dst),
-    0,
-    ptr_size
+  struct GNUNET_MY_ResultSpec res =
+  {
+    .pre_conv = &pre_extract_varsize_blob,
+    .post_conv = &post_extract_varsize_blob,
+    .cleaner = &cleanup_varsize_blob,
+    .dst =  (void *)(dst),
+    .result_size = ptr_size,
+    .num_fields = 1
   };
 
   return res;
 }
 
+
 /**
-  * Extract data from a Mysql database @a result at row @a row
-  *
-  * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in] dst_size desired size, never NULL
-  * @param[out] dst where to store the result
-  * @return
-  *  #GNUNET_OK if all results could be extracted
-  *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
-  *
-  */
+ * Extract data from a Mysql database @a result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *  #GNUNET_OK if all results could be extracted
+ *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
+ */
 static int
-extract_fixed_blob (void *cls,
-                      MYSQL_RES * result,
-                      int row,
-                      const char * fname,
-                      size_t * dst_size,
-                      void *dst)
+pre_extract_fixed_blob (void *cls,
+                        struct GNUNET_MY_ResultSpec *rs,
+                        MYSQL_STMT *stmt,
+                        unsigned int column,
+                        MYSQL_BIND *results)
 {
-  size_t len;
-  const char *res;
+  results[0].buffer = rs->dst;
+  results[0].buffer_length = rs->dst_size;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
-
-  rows = mysql_fetch_row (result);
-
-  field = mysql_fetch_field (result);
+  return GNUNET_OK;
+}
 
-  //If it's the correct field
-  if (field->name != fname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
 
+/**
+ * Check size of extracted fixed size data from a Mysql database @a
+ * result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *  #GNUNET_OK if all results could be extracted
+ *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
+ */
+static int
+post_extract_fixed_blob (void *cls,
+                         struct GNUNET_MY_ResultSpec *rs,
+                         MYSQL_STMT *stmt,
+                         unsigned int column,
+                         MYSQL_BIND *results)
+{
+  if (*results->is_null)
     return GNUNET_SYSERR;
-  }
-
-
-  if (rows[row] == NULL)
-  {
+  if (rs->dst_size != rs->mysql_bind_output_length)
     return GNUNET_SYSERR;
-  }
-
-  res = rows[row];
-
-  len = strlen (res);
-  if (*dst_size != len)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Field '%s' has wrong size (got %u, expected %u)\n",
-                fname,
-                (unsigned int)len,
-                (unsigned int) *dst_size);
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_assert (NULL != res);
-  
-  memcpy (dst,
-          res,
-          len);
-
   return GNUNET_OK;
 }
+
+
 /**
  * Fixed-size result expected.
  *
  * @param name name of the field in the table
  * @param[out] dst where to store the result
- * @param dst_size number of bytes in @a dst
+ * @param ptr_size number of bytes in @a dst
  * @return array entry for the result specification to use
  */
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_fixed_size (void *ptr,
                                   size_t ptr_size)
 {
-  struct GNUNET_MY_ResultSpec res = { 
-    &extract_fixed_blob,
-    NULL,
-    (void *)(ptr),
-    ptr_size,
-    NULL 
+  struct GNUNET_MY_ResultSpec res =
+  {
+    .pre_conv = &pre_extract_fixed_blob,
+    .post_conv = &post_extract_fixed_blob,
+    .cleaner = NULL,
+    .dst = (void *)(ptr),
+    .dst_size = ptr_size,
+    .num_fields = 1
   };
-      
+
   return res;
 }
 
+
 /**
   * Extract data from a Mysql database @a result at row @a row
   *
   * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in, out] dst_size where to store size of result, may be NULL
-  * @param[out] dst where to store the result
+  * @param[in,out] rs
+  * @param stmt the mysql statement that is being run
+  * @param column the column that is being processed
+  * @param[out] results
   * @return
   *   #GNUNET_OK if all results could be extracted
   *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
   */
 static int
-extract_rsa_public_key (void *cls,
-                        MYSQL_RES *result,
-                        int row,
-                        const char *fname,
-                        size_t *dst_size,
-                        void *dst)
+pre_extract_rsa_public_key (void *cls,
+                            struct GNUNET_MY_ResultSpec *rs,
+                            MYSQL_STMT *stmt,
+                            unsigned int column,
+                            MYSQL_BIND *results)
 {
-  struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
-  size_t len;
-  const char *res;
+  results[0].buffer = NULL;
+  results[0].buffer_length = 0;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
+  return GNUNET_OK;
+}
 
-  *pk = NULL;
 
-  rows = mysql_fetch_row (result);
+/**
+  * Check size of extracted fixed size data from a Mysql database @a
+  * result at row @a row
+  *
+  * @param cls closure
+  * @param[in,out] rs
+  * @param stmt the mysql statement that is being run
+  * @param column the column that is being processed
+  * @param[out] results
+  * @return
+  *   #GNUNET_OK if all results could be extracted
+  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+  */
+static int
+post_extract_rsa_public_key  (void *cls,
+                              struct GNUNET_MY_ResultSpec *rs,
+                              MYSQL_STMT *stmt,
+                              unsigned int column,
+                              MYSQL_BIND *results)
 
-  field = mysql_fetch_field (result);
+{
+  struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
+  void *buf;
+  size_t size;
 
-  //If it's the correct field
-  if (field->name != fname)
+  if (*results->is_null)
+    return GNUNET_SYSERR;
+  size = (size_t) rs->mysql_bind_output_length;
+
+  if (rs->mysql_bind_output_length != size)
+    return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
+  buf = GNUNET_malloc (size);
+
+  results[0].buffer = buf;
+  results[0].buffer_length = size;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+  if (0 !=
+      mysql_stmt_fetch_column (stmt,
+                               results,
+                               column,
+                               0))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
+    GNUNET_free (buf);
     return GNUNET_SYSERR;
   }
 
-
-  if (rows[row] == NULL)
+  *pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
+                                             size);
+  GNUNET_free (buf);
+  if (NULL == *pk)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Results contains bogus public key value (fail to decode)\n");
     return GNUNET_SYSERR;
   }
 
-  res = rows[row];
+  return GNUNET_OK;
+}
+
 
-  len = strlen (res);
-  
-  *pk = GNUNET_CRYPTO_rsa_public_key_decode (res, 
-                                            len);
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_MY_ResultConverter.
+ *
+ * @param cls closure
+ * @param rs result data to clean up
+ */
+static void
+clean_rsa_public_key (void *cls,
+                      struct GNUNET_MY_ResultSpec *rs)
+{
+  struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
 
-  if (NULL == *pk)
+  if (NULL != *pk)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Field '%s' contains bogus value (fails to decode\n",
-                  fname);
-    return GNUNET_SYSERR;
+    GNUNET_CRYPTO_rsa_public_key_free (*pk);
+    *pk = NULL;
   }
-  return GNUNET_OK;
 }
 
+
 /**
   * RSA public key expected
   *
@@ -275,82 +360,126 @@ struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
 {
   struct GNUNET_MY_ResultSpec res = {
-    &extract_rsa_public_key,
-    NULL,
-    (void *) rsa,
-    0,
-    NULL    
+    .pre_conv = &pre_extract_rsa_public_key,
+    .post_conv = &post_extract_rsa_public_key,
+    .cleaner = &clean_rsa_public_key,
+    .dst = (void *) rsa,
+    .dst_size = 0,
+    .num_fields = 1
   };
 
   return res;
 }
 
+
 /**
   * Extract data from a Mysql database @a result at row @a row.
   *
   * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in,out] dst_size where to store size of result, may be NULL
-  * @param[out] dst where to store the result
+  * @param[in,out] rs
+  * @param stmt the mysql statement that is being run
+  * @param column the column that is being processed
+  * @param[out] results
   * @return
   *    #GNUNET_OK if all results could be extracted
   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
   */
 static int
-extract_rsa_signature (void *cls,
-                      MYSQL_RES * result,
-                      int row, const char *fname,
-                      size_t * dst_size,
-                      void *dst)
+pre_extract_rsa_signature (void *cls,
+                      struct GNUNET_MY_ResultSpec *rs,
+                      MYSQL_STMT *stmt,
+                      unsigned int column,
+                      MYSQL_BIND *results)
 {
-  struct GNUNET_CRYPTO_RsaSignature **sig = dst;
-  size_t len;
-  const char *res;
-
-  
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
+  results[0].buffer = 0;
+  results[0].buffer_length = 0;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  *sig = NULL;
+  return GNUNET_OK;
+}
 
-  rows = mysql_fetch_row (result);
 
-  field = mysql_fetch_field (result);
+/**
+  * Extract data from a Mysql database @a result at row @a row.
+  *
+  * @param cls closure
+  * @param[in,out] rs
+  * @param stmt the mysql statement that is being run
+  * @param column the column that is being processed
+  * @param[out] results
+  * @return
+  *    #GNUNET_OK if all results could be extracted
+  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+  */
+static int
+post_extract_rsa_signature (void *cls,
+                            struct GNUNET_MY_ResultSpec *rs,
+                            MYSQL_STMT *stmt,
+                            unsigned int column,
+                            MYSQL_BIND *results)
+{
+  struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
+  void *buf;
+  size_t size;
 
-  //If it's the correct field
-  if (field->name == fname)
+  if (*results->is_null)
+    return GNUNET_SYSERR;
+  size = (size_t) rs->mysql_bind_output_length;
+
+  if (rs->mysql_bind_output_length != size)
+    return GNUNET_SYSERR; /* 'unsigned long' does not fit in size_t!? */
+  buf = GNUNET_malloc (size);
+
+  results[0].buffer = buf;
+  results[0].buffer_length = size;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+  if (0 !=
+      mysql_stmt_fetch_column (stmt,
+                               results,
+                               column,
+                               0))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
+    GNUNET_free (buf);
     return GNUNET_SYSERR;
   }
 
-
-  if (rows[row] == NULL)
+  *sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
+                                             size);
+  GNUNET_free (buf);
+  if (NULL == *sig)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Resuls contains bogus signature value (fails to decode)\n");
     return GNUNET_SYSERR;
   }
+  return GNUNET_OK;
+}
 
-  res = rows[row];
-  len = strlen (res);
 
-  *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
-                                            len);
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_MY_ResultConverter.
+ *
+ * @param cls closure
+ * @param rd result data to clean up
+ */
+static void
+clean_rsa_signature (void *cls,
+                     struct GNUNET_MY_ResultSpec *rs)
+{
+  struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
 
-  if (NULL == *sig)
+  if (NULL != *sig)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Field '%s' contains bogus value (fails to decode)\n",
-                fname);
-    return GNUNET_SYSERR;
+    GNUNET_CRYPTO_rsa_signature_free (*sig);
+    *sig = NULL;
   }
-
-  return GNUNET_OK;
 }
 
+
 /**
   * RSA signature expected.
   *
@@ -360,106 +489,126 @@ extract_rsa_signature (void *cls,
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
 {
-  struct GNUNET_MY_ResultSpec res = 
+  struct GNUNET_MY_ResultSpec res =
   {
-    &extract_rsa_signature,
-    NULL,
-    (void *)sig,
-    0,
-    NULL
+    .pre_conv = &pre_extract_rsa_signature,
+    .post_conv = &post_extract_rsa_signature,
+    .cleaner = &clean_rsa_signature,
+    .dst = (void *)sig,
+    .dst_size = 0,
+    .num_fields = 1
   };
   return res;
 }
 
+
 /**
-  * Extract data from a Mysql database @a result at row @a row
-  *
-  * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in, out] dst_size where to store size of result, may be NULL
-  * @param[out] dst where to store the result
-  * @return
-  *    #GNUNET_OK if all results could be extracted
-  *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
-  */
+ * Extract data from a Mysql database @a result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *    #GNUNET_OK if all results could be extracted
+ *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
+ */
 static int
-extract_string (void * cls,
-                MYSQL_RES * result,
-                int row,
-                const char * fname,
-                size_t *dst_size,
-                void *dst)
+pre_extract_string (void * cls,
+                    struct GNUNET_MY_ResultSpec *rs,
+                    MYSQL_STMT *stmt,
+                    unsigned int column,
+                    MYSQL_BIND *results)
 {
-  char **str = dst;
-  size_t len;
-  const char *res;
+  results[0].buffer = NULL;
+  results[0].buffer_length = 0;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
-
-  *str = NULL;
+  return GNUNET_OK;
+}
 
-  rows = mysql_fetch_row (result);
 
-  field = mysql_fetch_field (result);
+/**
+ * Check size of extracted fixed size data from a Mysql database @a
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *    #GNUNET_OK if all results could be extracted
+ *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
+ */
+static int
+post_extract_string (void * cls,
+                     struct GNUNET_MY_ResultSpec *rs,
+                     MYSQL_STMT *stmt,
+                     unsigned int column,
+                     MYSQL_BIND *results)
+{
+  size_t size = (size_t) rs->mysql_bind_output_length;
+  char *buf;
 
-  //If it's the correct field
-  if (field == fname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
+  if (rs->mysql_bind_output_length != size)
     return GNUNET_SYSERR;
-  }
-
-
-  if (rows[row] == NULL)
+  if (*results->is_null)
   {
-    return GNUNET_SYSERR;
+    *(void **) rs->dst = NULL;
+    return GNUNET_OK;
   }
 
-  res = rows[row];
-  len = strlen (res);
-  *str = GNUNET_strndup (res,
-                        len);
+  buf = GNUNET_malloc (size);
+  results[0].buffer = buf;
+  results[0].buffer_length = size;
+  results[0].buffer_type = MYSQL_TYPE_BLOB;
 
-  if (NULL == *str)
+  if (0 !=
+      mysql_stmt_fetch_column (stmt,
+                               results,
+                               column,
+                               0))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Field '%s' contains bogus value (fails to decode) \n",
-                fname);
+    GNUNET_free (buf);
     return GNUNET_SYSERR;
   }
+  buf[size] = '\0';
+  *(void **) rs->dst = buf;
   return GNUNET_OK;
-}    
+}
+
+
 /**
 * 0- terminated string exprected.
 *
 * @param[out] dst where to store the result, allocated
 * @return array entry for the result specification to use
 */
+ * 0- terminated string exprected.
+ *
+ * @param[out] dst where to store the result, allocated
+ * @return array entry for the result specification to use
+ */
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_string (char **dst)
 {
   struct GNUNET_MY_ResultSpec res = {
-    &extract_string,
-    NULL,
-    (void *) dst,
-    0,
-    NULL
+    .pre_conv = &pre_extract_string,
+    .post_conv = &post_extract_string,
+    .cleaner = NULL,
+    .dst = (void *) dst,
+    .dst_size = 0,
+    .num_fields = 1
   };
   return res;
 }
 
+
 /**
 * Absolute time expected
 *
 * @param name name of the field in the table
 * @param[out] at where to store the result
 * @return array entry for the result specification to use
+ * Absolute time expected
+ *
+ * @param name name of the field in the table
+ * @param[out] at where to store the result
+ * @return array entry for the result specification to use
   */
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
@@ -467,6 +616,7 @@ GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
 }
 
+
 /**
   * Absolute time in network byte order expected
   *
@@ -476,151 +626,149 @@ GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
 {
-  struct GNUNET_MY_ResultSpec res = 
+  struct GNUNET_MY_ResultSpec res =
     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
-    return res;
+  return res;
 }
 
+
 /**
  * Extract data from a Postgres database @a result at row @a row.
  *
  * @param cls closure
- * @param result where to extract data from
- * @param int row to extract data from
- * @param fname name (or prefix) of the fields to extract from
- * @param[in,out] dst_size where to store size of result, may be NULL
- * @param[out] dst where to store the result
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
  * @return
  *   #GNUNET_YES if all results could be extracted
  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
  */
 static int
-extract_uint16 (void *cls,
-              MYSQL_RES * result,
-              int row,
-              const char *fname,
-              size_t *dst_size,
-              void *dst)
+pre_extract_uint16 (void *cls,
+                    struct GNUNET_MY_ResultSpec *rs,
+                    MYSQL_STMT *stmt,
+                    unsigned int column,
+                    MYSQL_BIND *results)
 {
-    //TO COMPLETE 
-  uint16_t *udst = dst;
-  const uint16_t *res;
-
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
+  results[0].buffer = rs->dst;
+  results[0].buffer_length = rs->dst_size;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_SHORT;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  rows = mysql_fetch_row (result);
-
-  field = mysql_fetch_field (result);
-
-  //If it's the correct field
-  if (field->name == fname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
-    return GNUNET_SYSERR;
-  }
+  return GNUNET_OK;
+}
 
 
-  if (rows[row] == NULL)
-  {
+/**
+ * Check size of extracted fixed size data from a Mysql datbase.
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *   #GNUNET_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+post_extract_uint16 (void *cls,
+                     struct GNUNET_MY_ResultSpec *rs,
+                     MYSQL_STMT *stmt,
+                     unsigned int column,
+                     MYSQL_BIND *results)
+{
+  if (rs->dst_size != rs->mysql_bind_output_length)
     return GNUNET_SYSERR;
-  }
-
-  GNUNET_assert (NULL != dst);
-
-  if (sizeof (uint16_t) != *dst_size)
-  {
-    GNUNET_break (0);
+  if (*results->is_null)
     return GNUNET_SYSERR;
-  }
-
-  res = (uint16_t) rows[row];
-  *udst = ntohs (*res);
-
   return GNUNET_OK;
 }
 
+
 /**
 * uint16_t expected
 *
 * @param[out] u16 where to store the result
 * @return array entry for the result specification to use
 */
+ * uint16_t expected
+ *
+ * @param[out] u16 where to store the result
+ * @return array entry for the result specification to use
+ */
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_uint16 (uint16_t *u16)
 {
   struct GNUNET_MY_ResultSpec res = {
-    &extract_uint16,
-    NULL,
-    (void *) u16,
-    sizeof (*u16),
-    NULL
+    .pre_conv = &pre_extract_uint16,
+    .post_conv = &post_extract_uint16,
+    .cleaner = NULL,
+    .dst = (void *) u16,
+    .dst_size = sizeof (*u16),
+    .num_fields = 1
   };
   return res;
 }
 
+
 /**
   * Extrac data from a  MYSQL database @a result at row @a row
   *
   * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in, out] dst_size where to store size of result, may be NULL
-  * @param[out] dst where to store the result
+  * @param cls closure
+  * @param[in,out] rs
+  * @param stmt the mysql statement that is being run
+  * @param column the column that is being processed
+  * @param[out] results
   * @return
   *      #GNUNET_OK if all results could be extracted
   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
   */
 static int
-extract_uint32 (void *cls,
-                MYSQL_RES * result,
-                int row,
-                const char *fname,
-                size_t *dst_size,
-                void *dst)
+pre_extract_uint32 (void *cls,
+                    struct GNUNET_MY_ResultSpec *rs,
+                    MYSQL_STMT *stmt,
+                    unsigned int column,
+                    MYSQL_BIND *results)
 {
-  uint32_t *udst = dst;
-  const uint32_t *res;
-
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
-
-  rows = mysql_fetch_row (result);
+  results[0].buffer = rs->dst;
+  results[0].buffer_length = rs->dst_size;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_LONG;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  field = mysql_fetch_field (result);
-
-  //If it's the correct field
-  if (field->name == fname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
-    return GNUNET_SYSERR;
-  }
+  return GNUNET_OK;
+}
 
 
-  if (rows[row] == NULL)
-  {
+/**
+  * Extrac data from a  MYSQL database @a result at row @a row
+  *
+  * @param cls closure
+  * @param cls closure
+  * @param[in,out] rs
+  * @param stmt the mysql statement that is being run
+  * @param column the column that is being processed
+  * @param[out] results
+  * @return
+  *      #GNUNET_OK if all results could be extracted
+  *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+  */
+static int
+post_extract_uint32 (void *cls,
+                     struct GNUNET_MY_ResultSpec *rs,
+                     MYSQL_STMT * stmt,
+                     unsigned int column,
+                     MYSQL_BIND *results)
+{
+  if (rs->dst_size != rs->mysql_bind_output_length)
     return GNUNET_SYSERR;
-  }
-
-  GNUNET_assert (NULL != dst);
-
-  if (sizeof (uint32_t) != *dst_size)
-  {
-    GNUNET_break (0);
+  if (*results->is_null)
     return GNUNET_SYSERR;
-  }
-
-  res = (uint32_t) rows[row];
-
-  *udst = ntohl (*res);
   return GNUNET_OK;
 }
 
+
 /**
   * uint32_t expected
   *
@@ -631,92 +779,95 @@ struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_uint32 (uint32_t *u32)
 {
   struct GNUNET_MY_ResultSpec res = {
-    &extract_uint32,
-    NULL,
-    (void *) u32,
-    sizeof (*u32),
-    NULL
+    .pre_conv = &pre_extract_uint32,
+    .post_conv = &post_extract_uint32,
+    .cleaner = NULL,
+    .dst = (void *) u32,
+    .dst_size = sizeof (*u32),
+    .num_fields = 1
   };
   return res;
 }
 
+
 /**
-  * Extract data from a MYSQL database @a result at row @a row
-  *
-  * @param cls closure
-  * @param result where to extract data from
-  * @param int row to extract data from
-  * @param fname name (or prefix) of the fields to extract from
-  * @param[in, out] dst_size where to store size of result, may be null
-  * @param[out] dst where to store the result
-  * @return
-  *    #GNUNET_OK if all results could be extracted
-  *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
-  */
+ * Extract data from a MYSQL database @a result at row @a row
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *    #GNUNET_OK if all results could be extracted
+ *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
 static int
-extract_uint64 (void *cls,
-                MYSQL_RES * result,
-                int row, 
-                const char *fname,
-                size_t *dst_size,
-                void *dst)
+pre_extract_uint64 (void *cls,
+                    struct GNUNET_MY_ResultSpec *rs,
+                    MYSQL_STMT *stmt,
+                    unsigned int column,
+                    MYSQL_BIND *results)
 {
-  uint64_t *udst = dst;
-  const uint64_t *res;
-
-  MYSQL_ROW rows;
-  MYSQL_FIELD * field;
+  if (sizeof (uint64_t) != rs->dst_size)
+    return GNUNET_SYSERR;
+  results[0].buffer = rs->dst;
+  results[0].buffer_length = rs->dst_size;
+  results[0].length = &rs->mysql_bind_output_length;
+  results[0].buffer_type = MYSQL_TYPE_LONGLONG;
+  results[0].is_null = &rs->is_null;
+  rs->is_null = 0;
 
-  rows = mysql_fetch_row (result);
+  return GNUNET_OK;
+}
 
-  field = mysql_fetch_field (result);
 
-  //If it's the correct field
-  if (field->name == fname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "Field '%s' does not exist in result",
-                fname);
+/**
+ * Check size of extracted fixe size data from a Mysql database
+ *
+ * @param cls closure
+ * @param[in,out] rs
+ * @param stmt the mysql statement that is being run
+ * @param column the column that is being processed
+ * @param[out] results
+ * @return
+ *    #GNUNET_OK if all results could be extracted
+ *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+post_extract_uint64 (void *cls,
+                     struct GNUNET_MY_ResultSpec *rs,
+                     MYSQL_STMT *stmt,
+                     unsigned int column,
+                     MYSQL_BIND *results)
+{
+  if (sizeof (uint64_t) != rs->dst_size)
     return GNUNET_SYSERR;
-  }
-
-
-  if (rows[row] == NULL)
-  {
+  if (*results->is_null)
     return GNUNET_SYSERR;
-  }
-
-  GNUNET_assert (NULL != dst);
-  if (sizeof (uint64_t) != *dst_size)
-  {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-  }
-
-  res = (uint64_t) rows[row];
-  *udst = GNUNET_ntohll (*res);
-
   return GNUNET_OK;
 }
 
 
 /**
 * uint64_t expected.
 *
 * @param[out] u64 where to store the result
 * @return array entry for the result specification to use
 */
+ * uint64_t expected.
+ *
+ * @param[out] u64 where to store the result
+ * @return array entry for the result specification to use
+ */
 struct GNUNET_MY_ResultSpec
 GNUNET_MY_result_spec_uint64 (uint64_t *u64)
 {
   struct GNUNET_MY_ResultSpec res = {
-    &extract_uint64,
-    NULL,
-    (void *) u64,
-    sizeof (*u64),
-    NULL
+    .pre_conv = &pre_extract_uint64,
+    .post_conv = &post_extract_uint64,
+    .cleaner = NULL,
+    .dst = (void *) u64,
+    .dst_size = sizeof (*u64),
+    .num_fields = 1
   };
   return res;
 }
 
-/* end of pq_result_helper.c */
\ No newline at end of file
+
+/* end of my_result_helper.c */