completing sq_result_helper
authorChristian Grothoff <christian@grothoff.org>
Tue, 28 Feb 2017 03:07:26 +0000 (04:07 +0100)
committerChristian Grothoff <christian@grothoff.org>
Tue, 28 Feb 2017 03:07:26 +0000 (04:07 +0100)
src/include/gnunet_sq_lib.h
src/pq/pq_result_helper.c
src/sq/sq.c
src/sq/sq_result_helper.c

index 4484c28515e03b04d0e1feb470e367ac9d77c803..c03f83e07b15a504f86509a420c949b84cc99731 100644 (file)
@@ -252,7 +252,9 @@ struct GNUNET_SQ_ResultSpec
   size_t dst_size;
 
   /**
-   * Where to store actual size of the result.
+   * Where to store actual size of the result.  If left at
+   * NULL, will be made to point to @e dst_size before
+   * @a conv is called.
    */
   size_t *result_size;
 
index 180c5fc187a28bd1891d91d12a81eec802b60c3b..c5c8e56b9d73af090ed106493c72cb9990ae983e 100644 (file)
@@ -77,9 +77,7 @@ extract_varsize_blob (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -156,9 +154,7 @@ extract_fixed_blob (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -173,11 +169,7 @@ extract_fixed_blob (void *cls,
                     fnum);
   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);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   res = PQgetvalue (result,
@@ -243,9 +235,7 @@ extract_rsa_public_key (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -265,9 +255,7 @@ extract_rsa_public_key (void *cls,
                                             len);
   if (NULL == *pk)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' contains bogus value (fails to decode)\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   return GNUNET_OK;
@@ -346,9 +334,7 @@ extract_rsa_signature (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -368,9 +354,7 @@ extract_rsa_signature (void *cls,
                                             len);
   if (NULL == *sig)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' contains bogus value (fails to decode)\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   return GNUNET_OK;
@@ -449,9 +433,7 @@ extract_string (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -471,9 +453,7 @@ extract_string (void *cls,
                          len);
   if (NULL == *str)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' contains bogus value (fails to decode)\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   return GNUNET_OK;
@@ -583,9 +563,7 @@ extract_uint16 (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -655,9 +633,7 @@ extract_uint32 (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
@@ -727,9 +703,7 @@ extract_uint64 (void *cls,
                    fname);
   if (fnum < 0)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Field `%s' does not exist in result\n",
-               fname);
+    GNUNET_break (0);
     return GNUNET_SYSERR;
   }
   if (PQgetisnull (result,
index 47fcaf24ea13e6217c9c1ecc6d28b513901e595c..dc4416761b9aed0506a12e69b3048f2ae8e7ffcf 100644 (file)
@@ -75,6 +75,8 @@ GNUNET_SQ_extract_result (sqlite3_stmt *result,
 
   for (unsigned int i=0;NULL != rs[i].conv; i++)
   {
+    if (NULL == rs[i].result_size)
+      rs[i].result_size = &rs[i].dst_size;
     if (GNUNET_OK !=
         rs[i].conv (rs[i].cls,
                     result,
index 36ce533174420a0269cea2fcb61eebf22e3156f4..9ac2e2533730f79eb141aa44bdaf44ced9f00edf 100644 (file)
 
 
 /**
- * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
+ * Extract variable-sized binary data from a Postgres database @a result at row @a row.
  *
  * @param cls closure
  * @param result where to extract data from
- * @param row row to extract data from
  * @param column column to extract data from
  * @param[in,out] dst_size where to store size of result, may be NULL
- * @param[out] dst where to store the result
+ * @param[out] dst where to store the result (actually a `void **`)
  * @return
  *   #GNUNET_YES 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,
-                    sqlite3_stmt *result,
-                    int row,
-                    unsigned int column,
-                    size_t *dst_size,
-                    void *dst)
+extract_var_blob (void *cls,
+                  sqlite3_stmt *result,
+                  unsigned int column,
+                  size_t *dst_size,
+                  void *dst)
 {
+  int have;
+  const void *ret;
+  void **rdst = (void **) dst;
+
+  if (SQLITE_BLOB !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  /* sqlite manual says to invoke 'sqlite3_column_blob()'
+     before calling sqlite3_column_bytes() */
+  ret = sqlite3_column_blob (result,
+                             column);
+  have = sqlite3_column_bytes (result,
+                               column);
+  if (have < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  *dst_size = have;
+  if (0 == have)
+  {
+    *rdst = NULL;
+    return GNUNET_OK;
+  }
+  *rdst = GNUNET_malloc (have);
+  GNUNET_memcpy (*rdst,
+                 ret,
+                 have);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup memory allocated by #extract_var_blob().
+ *
+ * @param cls pointer to pointer of allocation
+ */
+static void
+clean_var_blob (void *cls)
+{
+  void **dptr = (void **) cls;
+
+  if (NULL != *dptr)
+  {
+    GNUNET_free (*dptr);
+    *dptr = NULL;
+  }
 }
 
 
@@ -58,6 +107,62 @@ struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_variable_size (void **dst,
                                     size_t *sptr)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_var_blob,
+    .cleaner = &clean_var_blob,
+    .cls = dst,
+    .result_size = sptr,
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES 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,
+                    sqlite3_stmt *result,
+                    unsigned int column,
+                    size_t *dst_size,
+                    void *dst)
+{
+  int have;
+  const void *ret;
+
+  if (SQLITE_BLOB !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  /* sqlite manual says to invoke 'sqlite3_column_blob()'
+     before calling sqlite3_column_bytes() */
+  ret = sqlite3_column_blob (result,
+                             column);
+  have = sqlite3_column_bytes (result,
+                               column);
+  if (*dst_size != have)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_memcpy (dst,
+                 ret,
+                 have);
+  return GNUNET_OK;
 }
 
 
@@ -72,6 +177,76 @@ struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_fixed_size (void *dst,
                                  size_t dst_size)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_fixed_blob,
+    .dst = dst,
+    .dst_size = dst_size,
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+extract_utf8_string (void *cls,
+                     sqlite3_stmt *result,
+                     unsigned int column,
+                     size_t *dst_size,
+                     void *dst)
+{
+  const char *text;
+  char **rdst = dst;
+
+  if (SQLITE_TEXT !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  /* sqlite manual guarantees that 'sqlite3_column_text()'
+     is 0-terminated */
+  text = (const char *) sqlite3_column_text (result,
+                                             column);
+  if (NULL == text)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  *dst_size = strlen (text) + 1;
+  *rdst = GNUNET_strdup (text);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup memory allocated by #extract_var_blob().
+ *
+ * @param cls pointer to pointer of allocation
+ */
+static void
+clean_utf8_string (void *cls)
+{
+  char **dptr = (char **) cls;
+
+  if (NULL != *dptr)
+  {
+    GNUNET_free (*dptr);
+    *dptr = NULL;
+  }
 }
 
 
@@ -84,6 +259,87 @@ GNUNET_SQ_result_spec_fixed_size (void *dst,
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_string (char **dst)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_utf8_string,
+    .cleaner = &clean_utf8_string,
+    .cls = dst,
+    .dst = dst,
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+extract_rsa_pub (void *cls,
+                 sqlite3_stmt *result,
+                 unsigned int column,
+                 size_t *dst_size,
+                 void *dst)
+{
+  struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
+  int have;
+  const void *ret;
+
+  if (SQLITE_BLOB !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  /* sqlite manual says to invoke 'sqlite3_column_blob()'
+     before calling sqlite3_column_bytes() */
+  ret = sqlite3_column_blob (result,
+                             column);
+  have = sqlite3_column_bytes (result,
+                               column);
+  if (have < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret,
+                                            have);
+  if (NULL == *pk)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_PQ_ResultConverter.
+ *
+ * @param cls closure
+ */
+static void
+clean_rsa_pub (void *cls)
+{
+  struct GNUNET_CRYPTO_RsaPublicKey **pk = cls;
+
+  if (NULL != *pk)
+  {
+    GNUNET_CRYPTO_rsa_public_key_free (*pk);
+    *pk = NULL;
+  }
 }
 
 
@@ -96,6 +352,87 @@ GNUNET_SQ_result_spec_string (char **dst)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_rsa_pub,
+    .cleaner = &clean_rsa_pub,
+    .dst = rsa,
+    .cls = rsa,
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+extract_rsa_sig (void *cls,
+                 sqlite3_stmt *result,
+                 unsigned int column,
+                 size_t *dst_size,
+                 void *dst)
+{
+  struct GNUNET_CRYPTO_RsaSignature **sig = dst;
+  int have;
+  const void *ret;
+
+  if (SQLITE_BLOB !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  /* sqlite manual says to invoke 'sqlite3_column_blob()'
+     before calling sqlite3_column_bytes() */
+  ret = sqlite3_column_blob (result,
+                             column);
+  have = sqlite3_column_bytes (result,
+                               column);
+  if (have < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  *sig = GNUNET_CRYPTO_rsa_signature_decode (ret,
+                                            have);
+  if (NULL == *sig)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_PQ_ResultConverter.
+ *
+ * @param cls result data to clean up
+ */
+static void
+clean_rsa_sig (void *cls)
+{
+  struct GNUNET_CRYPTO_RsaSignature **sig = cls;
+
+  if (NULL != *sig)
+  {
+    GNUNET_CRYPTO_rsa_signature_free (*sig);
+    *sig = NULL;
+  }
 }
 
 
@@ -108,6 +445,15 @@ GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_rsa_sig,
+    .cleaner = &clean_rsa_sig,
+    .dst = sig,
+    .cls = sig,
+    .num_params = 1
+  };
+
+  return rs;
 }
 
 
@@ -120,6 +466,44 @@ GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
 {
+  return GNUNET_SQ_result_spec_uint64 (&at->abs_value_us);
+}
+
+
+/**
+ * Extract absolute time value in NBO from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+extract_abs_time_nbo (void *cls,
+                      sqlite3_stmt *result,
+                      unsigned int column,
+                      size_t *dst_size,
+                      void *dst)
+{
+  struct GNUNET_TIME_AbsoluteNBO *u = dst;
+  struct GNUNET_TIME_Absolute t;
+
+  GNUNET_assert (sizeof (uint64_t) == *dst_size);
+  if (SQLITE_INTEGER !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
+                                                    column);
+  *u = GNUNET_TIME_absolute_hton (t);
+  return GNUNET_OK;
 }
 
 
@@ -132,6 +516,56 @@ GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_abs_time_nbo,
+    .dst = at,
+    .dst_size = sizeof (struct GNUNET_TIME_AbsoluteNBO),
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract 16-bit integer from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_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,
+                sqlite3_stmt *result,
+                unsigned int column,
+                size_t *dst_size,
+                void *dst)
+{
+  uint64_t v;
+  uint32_t *u = dst;
+
+  GNUNET_assert (sizeof (uint16_t) == *dst_size);
+  if (SQLITE_INTEGER !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  v = (uint64_t) sqlite3_column_int64 (result,
+                                       column);
+  if (v > UINT16_MAX)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  *u = (uint16_t) v;
+  return GNUNET_OK;
 }
 
 
@@ -144,6 +578,56 @@ GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_uint16,
+    .dst = u16,
+    .dst_size = sizeof (uint16_t),
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract 32-bit integer from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+extract_uint32 (void *cls,
+                sqlite3_stmt *result,
+                unsigned int column,
+                size_t *dst_size,
+                void *dst)
+{
+  uint64_t v;
+  uint32_t *u = dst;
+
+  GNUNET_assert (sizeof (uint32_t) == *dst_size);
+  if (SQLITE_INTEGER !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  v = (uint64_t) sqlite3_column_int64 (result,
+                                       column);
+  if (v > UINT32_MAX)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  *u = (uint32_t) v;
+  return GNUNET_OK;
 }
 
 
@@ -156,6 +640,49 @@ GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_uint32,
+    .dst = u32,
+    .dst_size = sizeof (uint32_t),
+    .num_params = 1
+  };
+
+  return rs;
+}
+
+
+/**
+ * Extract 64-bit integer from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param column column to extract data 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_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static int
+extract_uint64 (void *cls,
+                sqlite3_stmt *result,
+                unsigned int column,
+                size_t *dst_size,
+                void *dst)
+{
+  uint64_t *u = dst;
+
+  GNUNET_assert (sizeof (uint64_t) == *dst_size);
+  if (SQLITE_INTEGER !=
+      sqlite3_column_type (result,
+                           column))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  *u = (uint64_t) sqlite3_column_int64 (result,
+                                        column);
+  return GNUNET_OK;
 }
 
 
@@ -168,6 +695,14 @@ GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
 struct GNUNET_SQ_ResultSpec
 GNUNET_SQ_result_spec_uint64 (uint64_t *u64)
 {
+  struct GNUNET_SQ_ResultSpec rs = {
+    .conv = &extract_uint64,
+    .dst = u64,
+    .dst_size = sizeof (uint64_t),
+    .num_params = 1
+  };
+
+  return rs;
 }