aboutsummaryrefslogtreecommitdiff
path: root/src/pq
diff options
context:
space:
mode:
Diffstat (limited to 'src/pq')
-rw-r--r--src/pq/Makefile.am8
-rw-r--r--src/pq/db_pq.c883
-rw-r--r--src/pq/pq_helper.c370
-rw-r--r--src/pq/pq_query_helper.c208
-rw-r--r--src/pq/pq_result_helper.c358
-rw-r--r--src/pq/test_pq.c153
6 files changed, 595 insertions, 1385 deletions
diff --git a/src/pq/Makefile.am b/src/pq/Makefile.am
index 2187d494b..810aa47b3 100644
--- a/src/pq/Makefile.am
+++ b/src/pq/Makefile.am
@@ -12,8 +12,8 @@ lib_LTLIBRARIES = \
libtalerpq.la
libtalerpq_la_SOURCES = \
- db_pq.c \
- pq_helper.c
+ pq_query_helper.c \
+ pq_result_helper.c
libtalerpq_la_LIBADD = \
$(top_builddir)/src/util/libtalerutil.la \
@@ -36,5 +36,7 @@ test_pq_SOURCES = \
test_pq_LDADD = \
libtalerpq.la \
$(top_builddir)/src/util/libtalerutil.la \
- -lgnunetutil -ljansson \
+ -lgnunetpq \
+ -lgnunetutil \
+ -ljansson \
-lpq $(XLIB)
diff --git a/src/pq/db_pq.c b/src/pq/db_pq.c
deleted file mode 100644
index 59a1db022..000000000
--- a/src/pq/db_pq.c
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015 GNUnet e.V.
-
- TALER 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.
-
- TALER 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
- TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file pq/db_pq.c
- * @brief helper functions for libpq (PostGres) interactions
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Florian Dold
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_pq_lib.h"
-
-
-/**
- * Execute a prepared statement.
- *
- * @param db_conn database connection
- * @param name name of the prepared statement
- * @param params parameters to the statement
- * @return postgres result
- */
-PGresult *
-TALER_PQ_exec_prepared (PGconn *db_conn,
- const char *name,
- const struct TALER_PQ_QueryParam *params)
-{
- unsigned int len;
- unsigned int i;
-
- /* count the number of parameters */
- i = 0;
- len = 0;
- while (TALER_PQ_QF_END != params[i].format)
- {
- const struct TALER_PQ_QueryParam *x = &params[i];
-
- switch (x->format)
- {
- case TALER_PQ_QF_FIXED_BLOB:
- case TALER_PQ_QF_VARSIZE_BLOB:
- len++;
- break;
- case TALER_PQ_QF_AMOUNT_NBO:
- case TALER_PQ_QF_AMOUNT:
- len += 3;
- break;
- case TALER_PQ_QF_RSA_PUBLIC_KEY:
- case TALER_PQ_QF_RSA_SIGNATURE:
- case TALER_PQ_QF_TIME_ABSOLUTE:
- case TALER_PQ_QF_UINT16:
- case TALER_PQ_QF_UINT32:
- case TALER_PQ_QF_UINT64:
- case TALER_PQ_QF_JSON:
- len++;
- break;
- default:
- /* format not supported */
- GNUNET_assert (0);
- break;
- }
- i++;
- }
-
- /* new scope to allow stack allocation without alloca */
- {
- /* Scratch buffer for temporary storage */
- void *scratch[len];
- /* Parameter array we are building for the query */
- void *param_values[len];
- int param_lengths[len];
- int param_formats[len];
- unsigned int off;
- /* How many entries in the scratch buffer are in use? */
- unsigned int soff;
- PGresult *res;
-
- i = 0;
- off = 0;
- soff = 0;
- while (TALER_PQ_QF_END != params[i].format)
- {
- const struct TALER_PQ_QueryParam *x = &params[i];
-
- switch (x->format)
- {
- case TALER_PQ_QF_FIXED_BLOB:
- case TALER_PQ_QF_VARSIZE_BLOB:
- param_values[off] = (void *) x->data;
- param_lengths[off] = x->size;
- param_formats[off] = 1;
- off++;
- break;
- case TALER_PQ_QF_AMOUNT_NBO:
- {
- const struct TALER_Amount *amount = x->data;
-
- param_values[off] = (void *) &amount->value;
- param_lengths[off] = sizeof (amount->value);
- param_formats[off] = 1;
- off++;
- param_values[off] = (void *) &amount->fraction;
- param_lengths[off] = sizeof (amount->fraction);
- param_formats[off] = 1;
- off++;
- param_values[off] = (void *) amount->currency;
- param_lengths[off] = strlen (amount->currency);
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_AMOUNT:
- {
- const struct TALER_Amount *amount_hbo = x->data;
- struct TALER_AmountNBO *amount;
-
- amount = GNUNET_new (struct TALER_AmountNBO);
- scratch[soff++] = amount;
- TALER_amount_hton (amount,
- amount_hbo);
- param_values[off] = (void *) &amount->value;
- param_lengths[off] = sizeof (amount->value);
- param_formats[off] = 1;
- off++;
- param_values[off] = (void *) &amount->fraction;
- param_lengths[off] = sizeof (amount->fraction);
- param_formats[off] = 1;
- off++;
- param_values[off] = (void *) amount->currency;
- param_lengths[off] = strlen (amount->currency);
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_RSA_PUBLIC_KEY:
- {
- const struct GNUNET_CRYPTO_rsa_PublicKey *rsa = x->data;
- char *buf;
- size_t buf_size;
-
- buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa,
- &buf);
- scratch[soff++] = buf;
- param_values[off] = (void *) buf;
- param_lengths[off] = buf_size - 1; /* DB doesn't like the trailing \0 */
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_RSA_SIGNATURE:
- {
- const struct GNUNET_CRYPTO_rsa_Signature *sig = x->data;
- char *buf;
- size_t buf_size;
-
- buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig,
- &buf);
- scratch[soff++] = buf;
- param_values[off] = (void *) buf;
- param_lengths[off] = buf_size - 1; /* DB doesn't like the trailing \0 */
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_TIME_ABSOLUTE:
- {
- const struct GNUNET_TIME_Absolute *at_hbo = x->data;
- struct GNUNET_TIME_AbsoluteNBO *at_nbo;
-
- at_nbo = GNUNET_new (struct GNUNET_TIME_AbsoluteNBO);
- scratch[soff++] = at_nbo;
- *at_nbo = GNUNET_TIME_absolute_hton (*at_hbo);
- param_values[off] = (void *) at_nbo;
- param_lengths[off] = sizeof (struct GNUNET_TIME_AbsoluteNBO);
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_UINT16:
- {
- const uint16_t *u_hbo = x->data;
- uint16_t *u_nbo;
-
- u_nbo = GNUNET_new (uint16_t);
- scratch[soff++] = u_nbo;
- *u_nbo = htons (*u_hbo);
- param_values[off] = (void *) u_nbo;
- param_lengths[off] = sizeof (uint16_t);
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_UINT32:
- {
- const uint32_t *u_hbo = x->data;
- uint32_t *u_nbo;
-
- u_nbo = GNUNET_new (uint32_t);
- scratch[soff++] = u_nbo;
- *u_nbo = htonl (*u_hbo);
- param_values[off] = (void *) u_nbo;
- param_lengths[off] = sizeof (uint32_t);
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_UINT64:
- {
- const uint64_t *u_hbo = x->data;
- uint64_t *u_nbo;
-
- u_nbo = GNUNET_new (uint64_t);
- scratch[soff++] = u_nbo;
- *u_nbo = GNUNET_htonll (*u_hbo);
- param_values[off] = (void *) u_nbo;
- param_lengths[off] = sizeof (uint64_t);
- param_formats[off] = 1;
- off++;
- }
- break;
- case TALER_PQ_QF_JSON:
- {
- const json_t *json = x->data;
- char *str;
-
- str = json_dumps (json, JSON_COMPACT);
- GNUNET_assert (NULL != str);
- scratch[soff++] = str;
- param_values[off] = (void *) str;
- param_lengths[off] = strlen (str);
- param_formats[off] = 1;
- off++;
- }
- break;
- default:
- /* format not supported */
- GNUNET_assert (0);
- break;
- }
- i++;
- }
- GNUNET_assert (off == len);
- res = PQexecPrepared (db_conn,
- name,
- len,
- (const char **) param_values,
- param_lengths,
- param_formats,
- 1);
- for (off = 0; off < soff; off++)
- GNUNET_free (scratch[off]);
- return res;
- }
-}
-
-
-/**
- * Free all memory that was allocated in @a rs during
- * #TALER_PQ_extract_result().
- *
- * @param rs reult specification to clean up
- */
-void
-TALER_PQ_cleanup_result (struct TALER_PQ_ResultSpec *rs)
-{
- unsigned int i;
-
- for (i=0; TALER_PQ_RF_END != rs[i].format; i++)
- {
- switch (rs[i].format)
- {
- case TALER_PQ_RF_VARSIZE_BLOB:
- {
- void **dst = rs[i].dst;
- if (NULL != *dst)
- {
- GNUNET_free (*dst);
- *dst = NULL;
- *rs[i].result_size = 0;
- }
- break;
- }
- case TALER_PQ_RF_RSA_PUBLIC_KEY:
- {
- void **dst = rs[i].dst;
- if (NULL != *dst)
- {
- GNUNET_CRYPTO_rsa_public_key_free (*dst);
- *dst = NULL;
- }
- break;
- }
- case TALER_PQ_RF_RSA_SIGNATURE:
- {
- void **dst = rs[i].dst;
- if (NULL != *dst)
- {
- GNUNET_CRYPTO_rsa_signature_free (*dst);
- *dst = NULL;
- }
- }
- break;
- default:
- break;
- }
- }
-}
-
-
-/**
- * Extract results from a query result according to the given specification.
- * If colums are NULL, the destination is not modified, and #GNUNET_NO
- * is returned.
- *
- * @param result result to process
- * @param[in,out] rs result specification to extract for
- * @param row row from the result to extract
- * @return
- * #GNUNET_YES if all results could be extracted
- * #GNUNET_NO if at least one result was NULL
- * #GNUNET_SYSERR if a result was invalid (non-existing field)
- */
-int
-TALER_PQ_extract_result (PGresult *result,
- struct TALER_PQ_ResultSpec *rs,
- int row)
-{
- unsigned int i;
- int had_null = GNUNET_NO;
-
- for (i=0; TALER_PQ_RF_END != rs[i].format; i++)
- {
- struct TALER_PQ_ResultSpec *spec;
-
- spec = &rs[i];
- switch (spec->format)
- {
- case TALER_PQ_RF_FIXED_BLOB:
- case TALER_PQ_RF_VARSIZE_BLOB:
- {
- size_t len;
- const char *res;
- void *dst;
- int fnum;
-
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
-
- /* if a field is null, continue but
- * remember that we now return a different result */
- len = PQgetlength (result,
- row,
- fnum);
- if ( (0 != spec->dst_size) &&
- (spec->dst_size != len) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' has wrong size (got %u, expected %u)\n",
- spec->fname,
- (unsigned int) len,
- (unsigned int) spec->dst_size);
- TALER_PQ_cleanup_result (rs);
- return GNUNET_SYSERR;
- }
- res = PQgetvalue (result,
- row,
- fnum);
- GNUNET_assert (NULL != res);
- if (0 == spec->dst_size)
- {
- if (NULL != spec->result_size)
- *spec->result_size = len;
- spec->dst_size = len;
- dst = GNUNET_malloc (len);
- *((void **) spec->dst) = dst;
- }
- else
- dst = spec->dst;
- memcpy (dst,
- res,
- len);
- break;
- }
- case TALER_PQ_RF_AMOUNT_NBO:
- {
- char *val_name;
- char *frac_name;
- char *curr_name;
- const char *name = spec->fname;
- int ret;
-
- GNUNET_assert (NULL != spec->dst);
- GNUNET_assert (sizeof (struct TALER_AmountNBO) ==
- spec->dst_size);
- GNUNET_asprintf (&val_name,
- "%s_val",
- name);
- GNUNET_asprintf (&frac_name,
- "%s_frac",
- name);
- GNUNET_asprintf (&curr_name,
- "%s_curr",
- name);
- ret = TALER_PQ_extract_amount_nbo (result,
- row,
- val_name,
- frac_name,
- curr_name,
- spec->dst);
- GNUNET_free (val_name);
- GNUNET_free (frac_name);
- GNUNET_free (curr_name);
- if (GNUNET_SYSERR == ret)
- return GNUNET_SYSERR;
- if (GNUNET_OK != ret)
- had_null = GNUNET_YES;
- break;
- }
- case TALER_PQ_RF_AMOUNT:
- {
- char *val_name;
- char *frac_name;
- char *curr_name;
- const char *name = spec->fname;
- int ret;
-
- GNUNET_assert (NULL != spec->dst);
- GNUNET_assert (sizeof (struct TALER_Amount) ==
- spec->dst_size);
- GNUNET_asprintf (&val_name,
- "%s_val",
- name);
- GNUNET_asprintf (&frac_name,
- "%s_frac",
- name);
- GNUNET_asprintf (&curr_name,
- "%s_curr",
- name);
- ret = TALER_PQ_extract_amount (result,
- row,
- val_name,
- frac_name,
- curr_name,
- spec->dst);
- GNUNET_free (val_name);
- GNUNET_free (frac_name);
- GNUNET_free (curr_name);
- if (GNUNET_SYSERR == ret)
- return GNUNET_SYSERR;
- if (GNUNET_OK != ret)
- had_null = GNUNET_YES;
- break;
- }
- case TALER_PQ_RF_RSA_PUBLIC_KEY:
- {
- struct GNUNET_CRYPTO_rsa_PublicKey **pk = spec->dst;
- size_t len;
- const char *res;
- int fnum;
-
- *pk = NULL;
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
-
- /* if a field is null, continue but
- * remember that we now return a different result */
- len = PQgetlength (result,
- row,
- fnum);
- res = PQgetvalue (result,
- row,
- fnum);
- *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
- len);
- if (NULL == *pk)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' contains bogus value (fails to decode)\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- break;
- }
- case TALER_PQ_RF_RSA_SIGNATURE:
- {
- struct GNUNET_CRYPTO_rsa_Signature **sig = spec->dst;
- size_t len;
- const char *res;
- int fnum;
-
- *sig = NULL;
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
-
- /* if a field is null, continue but
- * remember that we now return a different result */
- len = PQgetlength (result,
- row,
- fnum);
- res = PQgetvalue (result,
- row,
- fnum);
- *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
- len);
- if (NULL == *sig)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' contains bogus value (fails to decode)\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- break;
- }
- case TALER_PQ_RF_TIME_ABSOLUTE:
- {
- struct GNUNET_TIME_Absolute *dst = spec->dst;
- const struct GNUNET_TIME_AbsoluteNBO *res;
- int fnum;
-
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
- GNUNET_assert (NULL != dst);
- GNUNET_assert (sizeof (struct GNUNET_TIME_AbsoluteNBO) ==
- spec->dst_size);
- res = (const struct GNUNET_TIME_AbsoluteNBO *)
- PQgetvalue (result,
- row,
- fnum);
- *dst = GNUNET_TIME_absolute_ntoh (*res);
- break;
- }
- case TALER_PQ_RF_UINT16:
- {
- uint16_t *dst = spec->dst;
- const uint16_t *res;
- int fnum;
-
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
- GNUNET_assert (NULL != dst);
- GNUNET_assert (sizeof (uint16_t) ==
- spec->dst_size);
- res = (uint16_t *) PQgetvalue (result,
- row,
- fnum);
- *dst = ntohs (*res);
- break;
- }
- case TALER_PQ_RF_UINT32:
- {
- uint32_t *dst = spec->dst;
- const uint32_t *res;
- int fnum;
-
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
- GNUNET_assert (NULL != dst);
- GNUNET_assert (sizeof (uint32_t) ==
- spec->dst_size);
- res = (uint32_t *) PQgetvalue (result,
- row,
- fnum);
- *dst = ntohl (*res);
- break;
- }
- case TALER_PQ_RF_UINT64:
- {
- uint64_t *dst = spec->dst;
- const uint64_t *res;
- int fnum;
-
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
- GNUNET_assert (NULL != dst);
- GNUNET_assert (sizeof (uint64_t) ==
- spec->dst_size);
- res = (uint64_t *) PQgetvalue (result,
- row,
- fnum);
- *dst = GNUNET_ntohll (*res);
- break;
- }
- case TALER_PQ_RF_JSON:
- {
- json_t **dst = spec->dst;
- char *res;
- int fnum;
- json_error_t json_error;
- size_t slen;
-
- fnum = PQfnumber (result,
- spec->fname);
- if (fnum < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Field `%s' does not exist in result\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- if (PQgetisnull (result,
- row,
- fnum))
- {
- had_null = GNUNET_YES;
- continue;
- }
- GNUNET_assert (NULL != dst);
- GNUNET_break (0 == spec->dst_size);
- slen = PQgetlength (result,
- row,
- fnum);
- res = (char *) PQgetvalue (result,
- row,
- fnum);
- *dst = json_loadb (res,
- slen,
- JSON_REJECT_DUPLICATES,
- &json_error);
- if (NULL == *dst)
- {
- TALER_json_warn (json_error);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse JSON result for field `%s'\n",
- spec->fname);
- return GNUNET_SYSERR;
- }
- break;
- }
- default:
- GNUNET_assert (0);
- break;
- }
- }
- if (GNUNET_YES == had_null)
- return GNUNET_NO;
- return GNUNET_YES;
-}
-
-
-/**
- * Extract a currency amount from a query result according to the
- * given specification.
- *
- * @param result the result to extract the amount from
- * @param row which row of the result to extract the amount from (needed as results can have multiple rows)
- * @param val_name name of the column with the amount's "value", must include the substring "_val".
- * @param frac_name name of the column with the amount's "fractional" value, must include the substring "_frac".
- * @param curr_name name of the column with the amount's currency name, must include the substring "_curr".
- * @param[out] r_amount_nbo where to store the amount, in network byte order
- * @return
- * #GNUNET_YES if all results could be extracted
- * #GNUNET_NO if at least one result was NULL
- * #GNUNET_SYSERR if a result was invalid (non-existing field)
- */
-int
-TALER_PQ_extract_amount_nbo (PGresult *result,
- int row,
- const char *val_name,
- const char *frac_name,
- const char *curr_name,
- struct TALER_AmountNBO *r_amount_nbo)
-{
- int val_num;
- int frac_num;
- int curr_num;
- int len;
-
- /* These checks are simply to check that clients obey by our naming
- conventions, and not for any functional reason */
- GNUNET_assert (NULL !=
- strstr (val_name,
- "_val"));
- GNUNET_assert (NULL !=
- strstr (frac_name,
- "_frac"));
- GNUNET_assert (NULL !=
- strstr (curr_name,
- "_curr"));
- /* Set return value to invalid in case we don't finish */
- memset (r_amount_nbo,
- 0,
- sizeof (struct TALER_AmountNBO));
- val_num = PQfnumber (result,
- val_name);
- frac_num = PQfnumber (result,
- frac_name);
- curr_num = PQfnumber (result,
- curr_name);
- if ( (val_num < 0) ||
- (frac_num < 0) ||
- (curr_num < 0) )
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if ( (PQgetisnull (result,
- row,
- val_num)) ||
- (PQgetisnull (result,
- row,
- frac_num)) ||
- (PQgetisnull (result,
- row,
- curr_num)) )
- {
- GNUNET_break (0);
- return GNUNET_NO;
- }
- /* Note that Postgres stores value in NBO internally,
- so no conversion needed in this case */
- r_amount_nbo->value = *(uint64_t *) PQgetvalue (result,
- row,
- val_num);
- r_amount_nbo->fraction = *(uint32_t *) PQgetvalue (result,
- row,
- frac_num);
- len = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
- PQgetlength (result,
- row,
- curr_num));
- memcpy (r_amount_nbo->currency,
- PQgetvalue (result,
- row,
- curr_num),
- len);
- return GNUNET_OK;
-}
-
-
-/**
- * Extract a currency amount from a query result according to the
- * given specification.
- *
- * @param result the result to extract the amount from
- * @param row which row of the result to extract the amount from (needed as
- * results can have multiple rows)
- * @param val_name name of the column with the amount's "value", must include
- * the substring "_val".
- * @param frac_name name of the column with the amount's "fractional" value,
- * must include the substring "_frac".
- * @param curr_name name of the column with the amount's currency name, must
- * include the substring "_curr".
- * @param[out] r_amount where to store the amount, in host byte order
- * @return
- * #GNUNET_YES if all results could be extracted
- * #GNUNET_NO if at least one result was NULL
- * #GNUNET_SYSERR if a result was invalid (non-existing field)
- */
-int
-TALER_PQ_extract_amount (PGresult *result,
- int row,
- const char *val_name,
- const char *frac_name,
- const char *curr_name,
- struct TALER_Amount *r_amount)
-{
- struct TALER_AmountNBO amount_nbo;
- int ret;
-
- ret = TALER_PQ_extract_amount_nbo (result,
- row,
- val_name,
- frac_name,
- curr_name,
- &amount_nbo);
- TALER_amount_ntoh (r_amount,
- &amount_nbo);
- return ret;
-}
-
-
-/* end of pq/db_pq.c */
diff --git a/src/pq/pq_helper.c b/src/pq/pq_helper.c
deleted file mode 100644
index d245ffdb8..000000000
--- a/src/pq/pq_helper.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015 GNUnet e.V.
-
- TALER 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.
-
- TALER 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
- TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file pq/pq_helper.c
- * @brief functions to initialize parameter arrays
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_pq_lib.h"
-
-
-/**
- * Generate query parameter for a currency, consisting of the three
- * components "value", "fraction" and "currency" in this order. The
- * types must be a 64-bit integer, 32-bit integer and a
- * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_AMOUNT_NBO, x, sizeof (*x) };
- return res;
-}
-
-
-/**
- * Generate query parameter for a currency, consisting of the three
- * components "value", "fraction" and "currency" in this order. The
- * types must be a 64-bit integer, 32-bit integer and a
- * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_amount (const struct TALER_Amount *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_AMOUNT, x, sizeof (*x) };
- return res;
-}
-
-
-/**
- * Generate query parameter for an RSA public key. The
- * database must contain a BLOB type in the respective position.
- *
- * @param x the query parameter to pass
- * @return array entry for the query parameters to use
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_RSA_PUBLIC_KEY, (x), 0 };
- return res;
-}
-
-
-/**
- * Generate query parameter for an RSA signature. The
- * database must contain a BLOB type in the respective position.
- *
- * @param x the query parameter to pass
- * @return array entry for the query parameters to use
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_RSA_SIGNATURE, (x), 0 };
- return res;
-}
-
-
-/**
- * Generate query parameter for an absolute time value.
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_TIME_ABSOLUTE, x, sizeof (*x) };
- return res;
-}
-
-
-/**
- * Generate query parameter for an absolute time value.
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_absolute_time_nbo(const struct GNUNET_TIME_AbsoluteNBO *x)
-{
- struct TALER_PQ_QueryParam res =
- TALER_PQ_query_param_auto_from_type (&x->abs_value_us__);
- return res;
-}
-
-
-/**
- * Generate query parameter for an uint16_t in host byte order.
- *
- * @param x pointer to the query parameter to pass
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_uint16 (const uint16_t *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_UINT16, x, sizeof (*x) };
- return res;
-}
-
-
-/**
- * Generate query parameter for an uint32_t in host byte order.
- *
- * @param x pointer to the query parameter to pass
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_uint32 (const uint32_t *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_UINT32, x, sizeof (*x) };
- return res;
-}
-
-
-/**
- * Generate query parameter for an uint16_t in host byte order.
- *
- * @param x pointer to the query parameter to pass
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_uint64 (const uint64_t *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_UINT64, x, sizeof (*x) };
- return res;
-}
-
-
-/**
- * Generate query parameter for a JSON object (stored as a string
- * in the DB).
- *
- * @param x pointer to the json object to pass
- */
-struct TALER_PQ_QueryParam
-TALER_PQ_query_param_json (const json_t *x)
-{
- struct TALER_PQ_QueryParam res =
- { TALER_PQ_QF_JSON, x, 0 };
- return res;
-}
-
-
-/**
- * Variable-size result expected.
- *
- * @param name name of the field in the table
- * @param[out] dst where to store the result, allocated
- * @param[out] sptr where to store the size of @a dst
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_variable_size (const char *name,
- void **dst,
- size_t *sptr)
-{
- struct TALER_PQ_ResultSpec res =
- { TALER_PQ_RF_VARSIZE_BLOB, (void *) (dst), 0, name, sptr };
- return res;
-}
-
-
-/**
- * Currency amount expected.
- *
- * @param name name of the field in the table
- * @param[out] amount where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_amount_nbo (const char *name,
- struct TALER_AmountNBO *amount)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_AMOUNT_NBO, (void *) amount, sizeof (*amount), name, NULL };
- return res;
-}
-
-
-/**
- * Currency amount expected.
- *
- * @param name name of the field in the table
- * @param[out] amount where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_amount (const char *name,
- struct TALER_Amount *amount)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_AMOUNT, (void *) amount, sizeof (*amount), name, NULL };
- return res;
-}
-
-
-/**
- * RSA public key expected.
- *
- * @param name name of the field in the table
- * @param[out] rsa where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_rsa_public_key (const char *name,
- struct GNUNET_CRYPTO_rsa_PublicKey **rsa)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_RSA_PUBLIC_KEY, (void *) rsa, 0, name, NULL };
- return res;
-}
-
-
-/**
- * RSA signature expected.
- *
- * @param name name of the field in the table
- * @param[out] sig where to store the result;
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_rsa_signature (const char *name,
- struct GNUNET_CRYPTO_rsa_Signature **sig)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_RSA_SIGNATURE, (void *) sig, 0, (name), NULL };
- 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
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_absolute_time (const char *name,
- struct GNUNET_TIME_Absolute *at)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_TIME_ABSOLUTE, (void *) at, sizeof (*at), (name), NULL };
- 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
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_absolute_time_nbo (const char *name,
- struct GNUNET_TIME_AbsoluteNBO *at)
-{
- struct TALER_PQ_ResultSpec res =
- TALER_PQ_result_spec_auto_from_type(name, &at->abs_value_us__);
- return res;
-}
-
-
-/**
- * uint16_t expected.
- *
- * @param name name of the field in the table
- * @param[out] u16 where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_uint16 (const char *name,
- uint16_t *u16)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_UINT16, (void *) u16, sizeof (*u16), (name), NULL };
- return res;
-}
-
-
-/**
- * uint32_t expected.
- *
- * @param name name of the field in the table
- * @param[out] u32 where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_uint32 (const char *name,
- uint32_t *u32)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_UINT32, (void *) u32, sizeof (*u32), (name), NULL };
- return res;
-}
-
-
-/**
- * uint64_t expected.
- *
- * @param name name of the field in the table
- * @param[out] u64 where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_uint64 (const char *name,
- uint64_t *u64)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_UINT64, (void *) u64, sizeof (*u64), (name), NULL };
- return res;
-}
-
-
-/**
- * json_t expected.
- *
- * @param name name of the field in the table
- * @param[out] jp where to store the result
- * @return array entry for the result specification to use
- */
-struct TALER_PQ_ResultSpec
-TALER_PQ_result_spec_json (const char *name,
- json_t **jp)
-{
- struct TALER_PQ_ResultSpec res =
- {TALER_PQ_RF_JSON, (void *) jp, 0, (name), NULL };
- return res;
-}
-
-/* end of pq_helper.c */
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
new file mode 100644
index 000000000..5d2e9ce06
--- /dev/null
+++ b/src/pq/pq_query_helper.c
@@ -0,0 +1,208 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ TALER 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.
+
+ TALER 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
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file pq/pq_query_helper.c
+ * @brief helper functions for Taler-specific libpq (PostGres) interactions
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_pq_lib.h>
+#include "taler_pq_lib.h"
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument, here a `struct TALER_AmountNBO`
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
+qconv_amount_nbo (void *cls,
+ const void *data,
+ size_t data_len,
+ void *param_values[],
+ int param_lengths[],
+ int param_formats[],
+ unsigned int param_length,
+ void *scratch[],
+ unsigned int scratch_length)
+{
+ const struct TALER_AmountNBO *amount = data;
+ unsigned int off = 0;
+
+ GNUNET_assert (3 == param_length);
+ param_values[off] = (void *) &amount->value;
+ param_lengths[off] = sizeof (amount->value);
+ param_formats[off] = 1;
+ off++;
+ param_values[off] = (void *) &amount->fraction;
+ param_lengths[off] = sizeof (amount->fraction);
+ param_formats[off] = 1;
+ off++;
+ param_values[off] = (void *) amount->currency;
+ param_lengths[off] = strlen (amount->currency);
+ param_formats[off] = 1;
+ return 0;
+}
+
+
+/**
+ * Generate query parameter for a currency, consisting of the three
+ * components "value", "fraction" and "currency" in this order. The
+ * types must be a 64-bit integer, 32-bit integer and a
+ * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
+ *
+ * @param x pointer to the query parameter to pass
+ * @return array entry for the query parameters to use
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x)
+{
+ struct GNUNET_PQ_QueryParam res =
+ { &qconv_amount_nbo, NULL, x, sizeof (*x), 3 };
+ return res;
+}
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument, here a `struct TALER_Amount`
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
+qconv_amount (void *cls,
+ const void *data,
+ size_t data_len,
+ void *param_values[],
+ int param_lengths[],
+ int param_formats[],
+ unsigned int param_length,
+ void *scratch[],
+ unsigned int scratch_length)
+{
+ const struct TALER_Amount *amount_hbo = data;
+ struct TALER_AmountNBO *amount;
+
+ amount = GNUNET_new (struct TALER_AmountNBO);
+ scratch[0] = amount;
+ TALER_amount_hton (amount,
+ amount_hbo);
+ qconv_amount_nbo (cls,
+ amount,
+ sizeof (struct TALER_AmountNBO),
+ param_values,
+ param_lengths,
+ param_formats,
+ param_length,
+ &scratch[1],
+ scratch_length - 1);
+ return 1;
+}
+
+
+/**
+ * Generate query parameter for a currency, consisting of the three
+ * components "value", "fraction" and "currency" in this order. The
+ * types must be a 64-bit integer, 32-bit integer and a
+ * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
+ *
+ * @param x pointer to the query parameter to pass
+ * @return array entry for the query parameters to use
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_amount (const struct TALER_Amount *x)
+{
+ struct GNUNET_PQ_QueryParam res =
+ { &qconv_amount, NULL, x, sizeof (*x), 3 };
+ return res;
+}
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument, here a `json_t *`
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
+qconv_json (void *cls,
+ const void *data,
+ size_t data_len,
+ void *param_values[],
+ int param_lengths[],
+ int param_formats[],
+ unsigned int param_length,
+ void *scratch[],
+ unsigned int scratch_length)
+{
+ const json_t *json = data;
+ char *str;
+
+ str = json_dumps (json, JSON_COMPACT);
+ if (NULL == str)
+ return -1;
+ scratch[0] = str;
+ param_values[0] = (void *) str;
+ param_lengths[0] = strlen (str);
+ param_formats[0] = 1;
+ return 1;
+}
+
+
+/**
+ * Generate query parameter for a JSON object (stored as a string
+ * in the DB).
+ *
+ * @param x pointer to the json object to pass
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_json (const json_t *x)
+{
+ struct GNUNET_PQ_QueryParam res =
+ { &qconv_json, NULL, x, 0, 1 };
+ return res;
+}
+
+
+/* end of pq/pq_query_helper.c */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
new file mode 100644
index 000000000..c8b3b01fc
--- /dev/null
+++ b/src/pq/pq_result_helper.c
@@ -0,0 +1,358 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ TALER 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.
+
+ TALER 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
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file pq/pq_result_helper.c
+ * @brief functions to initialize parameter arrays
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_pq_lib.h"
+
+
+/**
+ * Extract a currency amount from a query result according to the
+ * given specification.
+ *
+ * @param result the result to extract the amount from
+ * @param row which row of the result to extract the amount from (needed as results can have multiple rows)
+ * @param val_name name of the column with the amount's "value", must include the substring "_val".
+ * @param frac_name name of the column with the amount's "fractional" value, must include the substring "_frac".
+ * @param curr_name name of the column with the amount's currency name, must include the substring "_curr".
+ * @param[out] r_amount_nbo where to store the amount, in network byte order
+ * @return
+ * #GNUNET_YES if all results could be extracted
+ * #GNUNET_NO if at least one result was NULL
+ * #GNUNET_SYSERR if a result was invalid (non-existing field)
+ */
+static int
+extract_amount_nbo_helper (PGresult *result,
+ int row,
+ const char *val_name,
+ const char *frac_name,
+ const char *curr_name,
+ struct TALER_AmountNBO *r_amount_nbo)
+{
+ int val_num;
+ int frac_num;
+ int curr_num;
+ int len;
+
+ /* These checks are simply to check that clients obey by our naming
+ conventions, and not for any functional reason */
+ GNUNET_assert (NULL !=
+ strstr (val_name,
+ "_val"));
+ GNUNET_assert (NULL !=
+ strstr (frac_name,
+ "_frac"));
+ GNUNET_assert (NULL !=
+ strstr (curr_name,
+ "_curr"));
+ /* Set return value to invalid in case we don't finish */
+ memset (r_amount_nbo,
+ 0,
+ sizeof (struct TALER_AmountNBO));
+ val_num = PQfnumber (result,
+ val_name);
+ frac_num = PQfnumber (result,
+ frac_name);
+ curr_num = PQfnumber (result,
+ curr_name);
+ if ( (val_num < 0) ||
+ (frac_num < 0) ||
+ (curr_num < 0) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if ( (PQgetisnull (result,
+ row,
+ val_num)) ||
+ (PQgetisnull (result,
+ row,
+ frac_num)) ||
+ (PQgetisnull (result,
+ row,
+ curr_num)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_NO;
+ }
+ /* Note that Postgres stores value in NBO internally,
+ so no conversion needed in this case */
+ r_amount_nbo->value = *(uint64_t *) PQgetvalue (result,
+ row,
+ val_num);
+ r_amount_nbo->fraction = *(uint32_t *) PQgetvalue (result,
+ row,
+ frac_num);
+ len = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
+ PQgetlength (result,
+ row,
+ curr_num));
+ memcpy (r_amount_nbo->currency,
+ PQgetvalue (result,
+ row,
+ curr_num),
+ len);
+ return GNUNET_OK;
+}
+
+
+/**
+ * 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
+ * @return
+ * #GNUNET_YES if all results could be extracted
+ * #GNUNET_NO if at least one result was NULL
+ * #GNUNET_SYSERR if a result was invalid (non-existing field)
+ */
+static int
+extract_amount_nbo (void *cls,
+ PGresult *result,
+ int row,
+ const char *fname,
+ size_t *dst_size,
+ void *dst)
+{
+ char *val_name;
+ char *frac_name;
+ char *curr_name;
+ int ret;
+
+ GNUNET_asprintf (&val_name,
+ "%s_val",
+ fname);
+ GNUNET_asprintf (&frac_name,
+ "%s_frac",
+ fname);
+ GNUNET_asprintf (&curr_name,
+ "%s_curr",
+ fname);
+ ret = extract_amount_nbo_helper (result,
+ row,
+ val_name,
+ frac_name,
+ curr_name,
+ dst);
+ GNUNET_free (val_name);
+ GNUNET_free (frac_name);
+ GNUNET_free (curr_name);
+ return ret;
+}
+
+
+/**
+ * Currency amount expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] amount where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_amount_nbo (const char *name,
+ struct TALER_AmountNBO *amount)
+{
+ struct GNUNET_PQ_ResultSpec res =
+ { &extract_amount_nbo, NULL, NULL,
+ (void *) amount, sizeof (*amount),
+ name, NULL };
+ 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
+ * @return
+ * #GNUNET_YES if all results could be extracted
+ * #GNUNET_NO if at least one result was NULL
+ * #GNUNET_SYSERR if a result was invalid (non-existing field)
+ */
+static int
+extract_amount (void *cls,
+ PGresult *result,
+ int row,
+ const char *fname,
+ size_t *dst_size,
+ void *dst)
+{
+ struct TALER_Amount *r_amount = dst;
+ char *val_name;
+ char *frac_name;
+ char *curr_name;
+ struct TALER_AmountNBO amount_nbo;
+ int ret;
+
+ GNUNET_asprintf (&val_name,
+ "%s_val",
+ fname);
+ GNUNET_asprintf (&frac_name,
+ "%s_frac",
+ fname);
+ GNUNET_asprintf (&curr_name,
+ "%s_curr",
+ fname);
+ ret = extract_amount_nbo_helper (result,
+ row,
+ val_name,
+ frac_name,
+ curr_name,
+ &amount_nbo);
+ TALER_amount_ntoh (r_amount,
+ &amount_nbo);
+ GNUNET_free (val_name);
+ GNUNET_free (frac_name);
+ GNUNET_free (curr_name);
+ return ret;
+}
+
+
+/**
+ * Currency amount expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] amount where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_amount (const char *name,
+ struct TALER_Amount *amount)
+{
+ struct GNUNET_PQ_ResultSpec res =
+ { &extract_amount, NULL, NULL,
+ (void *) amount, sizeof (*amount),
+ name, NULL };
+ 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
+ * @return
+ * #GNUNET_YES if all results could be extracted
+ * #GNUNET_NO if at least one result was NULL
+ * #GNUNET_SYSERR if a result was invalid (non-existing field)
+ */
+static int
+extract_json (void *cls,
+ PGresult *result,
+ int row,
+ const char *fname,
+ size_t *dst_size,
+ void *dst)
+{
+ json_t **j_dst = dst;
+ const char *res;
+ int fnum;
+ json_error_t json_error;
+ size_t slen;
+
+ fnum = PQfnumber (result,
+ fname);
+ if (fnum < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Field `%s' does not exist in result\n",
+ fname);
+ return GNUNET_SYSERR;
+ }
+ if (PQgetisnull (result,
+ row,
+ fnum))
+ return GNUNET_NO;
+ slen = PQgetlength (result,
+ row,
+ fnum);
+ res = (const char *) PQgetvalue (result,
+ row,
+ fnum);
+ *j_dst = json_loadb (res,
+ slen,
+ JSON_REJECT_DUPLICATES,
+ &json_error);
+ if (NULL == *j_dst)
+ {
+ TALER_json_warn (json_error);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to parse JSON result for field `%s'\n",
+ fname);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_PQ_ResultConverter.
+ *
+ * @param cls closure
+ * @param rd result data to clean up
+ */
+static void
+clean_json (void *cls,
+ void *rd)
+{
+ json_t **dst = rd;
+
+ if (NULL != *dst)
+ {
+ json_decref (*dst);
+ *dst = NULL;
+ }
+}
+
+
+/**
+ * json_t expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] jp where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_json (const char *name,
+ json_t **jp)
+{
+ struct GNUNET_PQ_ResultSpec res =
+ { &extract_json, &clean_json, NULL,
+ (void *) jp, 0,
+ name, NULL };
+ return res;
+}
+
+/* end of pq_result_helper.c */
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
index f0413d1ff..95cfb715d 100644
--- a/src/pq/test_pq.c
+++ b/src/pq/test_pq.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2015 GNUnet e.V.
+ (C) 2015, 2016 GNUnet e.V.
TALER 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
@@ -48,47 +48,27 @@ postgres_prepare (PGconn *db_conn)
PREPARE ("test_insert",
"INSERT INTO test_pq ("
- " pub"
- ",sig"
- ",abs_time"
- ",forever"
- ",hash"
- ",hamount_val"
+ " hamount_val"
",hamount_frac"
",hamount_curr"
",namount_val"
",namount_frac"
",namount_curr"
- ",vsize"
- ",u16"
- ",u32"
- ",u64"
",json"
") VALUES "
"($1, $2, $3, $4, $5, $6,"
- "$7, $8, $9, $10, $11, $12, $13, $14, $15, $16);",
- 16, NULL);
+ "$7);",
+ 7, NULL);
PREPARE ("test_select",
"SELECT"
- " pub"
- ",sig"
- ",abs_time"
- ",forever"
- ",hash"
- ",hamount_val"
+ " hamount_val"
",hamount_frac"
",hamount_curr"
",namount_val"
",namount_frac"
",namount_curr"
- ",vsize"
- ",u16"
- ",u32"
- ",u64"
",json"
- " FROM test_pq"
- " ORDER BY abs_time DESC "
- " LIMIT 1;",
+ " FROM test_pq;",
0, NULL);
return GNUNET_OK;
#undef PREPARE
@@ -103,40 +83,15 @@ postgres_prepare (PGconn *db_conn)
static int
run_queries (PGconn *conn)
{
- struct GNUNET_CRYPTO_rsa_PublicKey *pub;
- struct GNUNET_CRYPTO_rsa_PublicKey *pub2 = NULL;
- struct GNUNET_CRYPTO_rsa_Signature *sig;
- struct GNUNET_CRYPTO_rsa_Signature *sig2 = NULL;
- struct GNUNET_TIME_Absolute abs_time = GNUNET_TIME_absolute_get ();
- struct GNUNET_TIME_Absolute abs_time2;
- struct GNUNET_TIME_Absolute forever = GNUNET_TIME_UNIT_FOREVER_ABS;
- struct GNUNET_TIME_Absolute forever2;
- struct GNUNET_HashCode hc;
- struct GNUNET_HashCode hc2;
struct TALER_Amount hamount;
struct TALER_Amount hamount2;
struct TALER_AmountNBO namount;
struct TALER_AmountNBO namount2;
PGresult *result;
int ret;
- struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
- char msg[] = "Hello";
- void *msg2;
- size_t msg2_len;
- uint16_t u16;
- uint16_t u162;
- uint32_t u32;
- uint32_t u322;
- uint64_t u64;
- uint64_t u642;
json_t *json;
json_t *json2;
- priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
- pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
- sig = GNUNET_CRYPTO_rsa_sign (priv,
- msg,
- sizeof (msg));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:5.5",
&hamount));
@@ -145,87 +100,53 @@ run_queries (PGconn *conn)
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:4.4",
&hamount));
- u16 = 16;
- u32 = 32;
- u64 = 64;
json = json_object ();
json_object_set (json, "foo", json_integer (42));
GNUNET_assert (NULL != json);
- /* FIXME: test TALER_PQ_result_spec_variable_size */
+ /* FIXME: test GNUNET_PQ_result_spec_variable_size */
{
- struct TALER_PQ_QueryParam params_insert[] = {
- TALER_PQ_query_param_rsa_public_key (pub),
- TALER_PQ_query_param_rsa_signature (sig),
- TALER_PQ_query_param_absolute_time (&abs_time),
- TALER_PQ_query_param_absolute_time (&forever),
- TALER_PQ_query_param_auto_from_type (&hc),
+ struct GNUNET_PQ_QueryParam params_insert[] = {
TALER_PQ_query_param_amount (&hamount),
TALER_PQ_query_param_amount_nbo (&namount),
- TALER_PQ_query_param_fixed_size (msg, strlen (msg)),
- TALER_PQ_query_param_uint16 (&u16),
- TALER_PQ_query_param_uint32 (&u32),
- TALER_PQ_query_param_uint64 (&u64),
TALER_PQ_query_param_json (json),
- TALER_PQ_query_param_end
+ GNUNET_PQ_query_param_end
};
- struct TALER_PQ_QueryParam params_select[] = {
- TALER_PQ_query_param_end
+ struct GNUNET_PQ_QueryParam params_select[] = {
+ GNUNET_PQ_query_param_end
};
- struct TALER_PQ_ResultSpec results_select[] = {
- TALER_PQ_result_spec_rsa_public_key ("pub", &pub2),
- TALER_PQ_result_spec_rsa_signature ("sig", &sig2),
- TALER_PQ_result_spec_absolute_time ("abs_time", &abs_time2),
- TALER_PQ_result_spec_absolute_time ("forever", &forever2),
- TALER_PQ_result_spec_auto_from_type ("hash", &hc2),
+ struct GNUNET_PQ_ResultSpec results_select[] = {
TALER_PQ_result_spec_amount ("hamount", &hamount2),
TALER_PQ_result_spec_amount_nbo ("namount", &namount2),
- TALER_PQ_result_spec_variable_size ("vsize", &msg2, &msg2_len),
- TALER_PQ_result_spec_uint16 ("u16", &u162),
- TALER_PQ_result_spec_uint32 ("u32", &u322),
- TALER_PQ_result_spec_uint64 ("u64", &u642),
TALER_PQ_result_spec_json ("json", &json2),
- TALER_PQ_result_spec_end
+ GNUNET_PQ_result_spec_end
};
- result = TALER_PQ_exec_prepared (conn,
- "test_insert",
- params_insert);
+ result = GNUNET_PQ_exec_prepared (conn,
+ "test_insert",
+ params_insert);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Database failure: %s\n",
PQresultErrorMessage (result));
PQclear (result);
- GNUNET_CRYPTO_rsa_signature_free (sig);
- GNUNET_CRYPTO_rsa_private_key_free (priv);
- GNUNET_CRYPTO_rsa_public_key_free (pub);
return 1;
}
PQclear (result);
- result = TALER_PQ_exec_prepared (conn,
- "test_select",
- params_select);
+ result = GNUNET_PQ_exec_prepared (conn,
+ "test_select",
+ params_select);
if (1 !=
PQntuples (result))
{
GNUNET_break (0);
PQclear (result);
- GNUNET_CRYPTO_rsa_signature_free (sig);
- GNUNET_CRYPTO_rsa_private_key_free (priv);
- GNUNET_CRYPTO_rsa_public_key_free (pub);
return 1;
}
- ret = TALER_PQ_extract_result (result,
- results_select,
- 0);
- GNUNET_break (GNUNET_YES == ret);
- GNUNET_break (abs_time.abs_value_us == abs_time2.abs_value_us);
- GNUNET_break (forever.abs_value_us == forever2.abs_value_us);
- GNUNET_break (0 ==
- memcmp (&hc,
- &hc2,
- sizeof (struct GNUNET_HashCode)));
+ ret = GNUNET_PQ_extract_result (result,
+ results_select,
+ 0);
GNUNET_break (0 ==
TALER_amount_cmp (&hamount,
&hamount2));
@@ -237,28 +158,11 @@ run_queries (PGconn *conn)
GNUNET_break (0 ==
TALER_amount_cmp (&hamount,
&hamount2));
- GNUNET_break (0 ==
- GNUNET_CRYPTO_rsa_signature_cmp (sig,
- sig2));
- GNUNET_break (0 ==
- GNUNET_CRYPTO_rsa_public_key_cmp (pub,
- pub2));
- GNUNET_break (strlen (msg) == msg2_len);
- GNUNET_break (0 ==
- strncmp (msg,
- msg2,
- msg2_len));
- GNUNET_break (16 == u162);
- GNUNET_break (32 == u322);
- GNUNET_break (64 == u642);
GNUNET_break (42 == json_integer_value (json_object_get (json2, "foo")));
json_decref (json2);
- TALER_PQ_cleanup_result (results_select);
+ GNUNET_PQ_cleanup_result (results_select);
PQclear (result);
}
- GNUNET_CRYPTO_rsa_signature_free (sig);
- GNUNET_CRYPTO_rsa_private_key_free (priv);
- GNUNET_CRYPTO_rsa_public_key_free (pub);
if (GNUNET_OK != ret)
return 1;
@@ -290,21 +194,12 @@ main(int argc,
result = PQexec (conn,
"CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
- " pub BYTEA NOT NULL"
- ",sig BYTEA NOT NULL"
- ",abs_time INT8 NOT NULL"
- ",forever INT8 NOT NULL"
- ",hash BYTEA NOT NULL CHECK(LENGTH(hash)=64)"
- ",hamount_val INT8 NOT NULL"
+ " hamount_val INT8 NOT NULL"
",hamount_frac INT4 NOT NULL"
",hamount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",namount_val INT8 NOT NULL"
",namount_frac INT4 NOT NULL"
",namount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
- ",vsize VARCHAR NOT NULL"
- ",u16 INT2 NOT NULL"
- ",u32 INT4 NOT NULL"
- ",u64 INT8 NOT NULL"
",json VARCHAR NOT NULL"
")");
if (PGRES_COMMAND_OK != PQresultStatus (result))