aboutsummaryrefslogtreecommitdiff
path: root/src/pq
diff options
context:
space:
mode:
Diffstat (limited to 'src/pq')
-rw-r--r--src/pq/db_pq.c48
-rw-r--r--src/pq/pq_helper.c214
-rw-r--r--src/pq/test_pq.c168
3 files changed, 364 insertions, 66 deletions
diff --git a/src/pq/db_pq.c b/src/pq/db_pq.c
index 72a9370ed..a718c805f 100644
--- a/src/pq/db_pq.c
+++ b/src/pq/db_pq.c
@@ -60,6 +60,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
break;
case TALER_PQ_QF_RSA_PUBLIC_KEY:
case TALER_PQ_QF_RSA_SIGNATURE:
+ case TALER_PQ_QF_TIME_ABSOLUTE:
len++;
break;
default:
@@ -67,6 +68,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
GNUNET_assert (0);
break;
}
+ i++;
}
/* new scope to allow stack allocation without alloca */
@@ -111,7 +113,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
param_formats[off] = 1;
off++;
param_values[off] = (void *) amount->currency;
- param_lengths[off] = strlen (amount->currency) + 1;
+ param_lengths[off] = strlen (amount->currency);
param_formats[off] = 1;
off++;
}
@@ -134,7 +136,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
param_formats[off] = 1;
off++;
param_values[off] = (void *) amount->currency;
- param_lengths[off] = strlen (amount->currency) + 1;
+ param_lengths[off] = strlen (amount->currency);
param_formats[off] = 1;
off++;
}
@@ -176,8 +178,6 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
at_nbo = GNUNET_new (struct GNUNET_TIME_AbsoluteNBO);
scratch[soff++] = at_nbo;
- /* FIXME: this does not work for 'forever' as PQ uses 63-bit integers;
- should check and handle! (Need testcase!) */
*at_nbo = GNUNET_TIME_absolute_hton (*at_hbo);
param_values[off] = (void *) at_nbo;
param_lengths[off] = sizeof (struct GNUNET_TIME_AbsoluteNBO);
@@ -190,6 +190,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
GNUNET_assert (0);
break;
}
+ i++;
}
GNUNET_assert (off == len);
res = PQexecPrepared (db_conn,
@@ -200,7 +201,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn,
param_formats,
1);
for (off = 0; off < soff; off++)
- GNUNET_free (scratch[soff]);
+ GNUNET_free (scratch[off]);
return res;
}
}
@@ -222,25 +223,34 @@ TALER_PQ_cleanup_result (struct TALER_PQ_ResultSpec *rs)
switch (rs[i].format)
{
case TALER_PQ_RF_VARSIZE_BLOB:
- if (NULL != rs[i].dst)
{
- GNUNET_free (rs[i].dst);
- rs[i].dst = NULL;
- *rs[i].result_size = 0;
+ void **dst = rs[i].dst;
+ if (NULL != *dst)
+ {
+ GNUNET_free (*dst);
+ *dst = NULL;
+ *rs[i].result_size = 0;
+ }
+ break;
}
- break;
case TALER_PQ_RF_RSA_PUBLIC_KEY:
- if (NULL != rs[i].dst)
{
- GNUNET_CRYPTO_rsa_public_key_free (rs[i].dst);
- rs[i].dst = NULL;
+ void **dst = rs[i].dst;
+ if (NULL != *dst)
+ {
+ GNUNET_CRYPTO_rsa_public_key_free (*dst);
+ *dst = NULL;
+ }
+ break;
}
- break;
case TALER_PQ_RF_RSA_SIGNATURE:
- if (NULL != rs[i].dst)
{
- GNUNET_CRYPTO_rsa_signature_free (rs[i].dst);
- rs[i].dst = NULL;
+ void **dst = rs[i].dst;
+ if (NULL != *dst)
+ {
+ GNUNET_CRYPTO_rsa_signature_free (*dst);
+ *dst = NULL;
+ }
}
break;
default:
@@ -256,7 +266,7 @@ TALER_PQ_cleanup_result (struct TALER_PQ_ResultSpec *rs)
* is returned.
*
* @param result result to process
- * @param[in|out] rs result specification to extract for
+ * @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
@@ -525,8 +535,6 @@ TALER_PQ_extract_result (PGresult *result,
PQgetvalue (result,
row,
fnum);
- /* FIXME: this does not work for 'forever' as PQ uses 63-bit integers;
- should check and handle! (Need testcase!) */
*dst = GNUNET_TIME_absolute_ntoh (*res);
break;
}
diff --git a/src/pq/pq_helper.c b/src/pq/pq_helper.c
new file mode 100644
index 000000000..5da1ced41
--- /dev/null
+++ b/src/pq/pq_helper.c
@@ -0,0 +1,214 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
+
+ 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;
+}
+
+
+/**
+ * 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;
+}
+
+
+/* end of pq_helper.c */
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
index 2d56e11e7..ff89e29f3 100644
--- a/src/pq/test_pq.c
+++ b/src/pq/test_pq.c
@@ -60,9 +60,10 @@ postgres_prepare (PGconn *db_conn)
",namount_val"
",namount_frac"
",namount_curr"
+ ",vsize"
") VALUES "
"($1, $2, $3, $4, $5, $6,"
- "$7, $8, $9, $10, $11);",
+ "$7, $8, $9, $10, $11, $12);",
11, NULL);
PREPARE ("test_select",
"SELECT"
@@ -77,9 +78,10 @@ postgres_prepare (PGconn *db_conn)
",namount_val"
",namount_frac"
",namount_curr"
- "FROM test_pq"
- "ORDER BY abs_time DESC "
- "LIMIT 1;",
+ ",vsize"
+ " FROM test_pq"
+ " ORDER BY abs_time DESC "
+ " LIMIT 1;",
0, NULL);
return GNUNET_OK;
#undef PREPARE
@@ -108,47 +110,119 @@ run_queries (PGconn *conn)
struct TALER_Amount hamount2;
struct TALER_AmountNBO namount;
struct TALER_AmountNBO namount2;
- 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_PTR (&hc),
- TALER_PQ_QUERY_PARAM_AMOUNT (hamount),
- TALER_PQ_QUERY_PARAM_AMOUNT_NBO (namount),
- TALER_PQ_QUERY_PARAM_END
- };
- struct TALER_PQ_QueryParam params_select[] = {
- TALER_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 ("hash", &hc2),
- TALER_PQ_RESULT_SPEC_AMOUNT ("hamount", hamount2),
- TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("namount", namount2),
- TALER_PQ_RESULT_SPEC_END
- };
PGresult *result;
int ret;
+ struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
+ char msg[] = "Hello";
+ void *msg2;
+ size_t msg2_len;
+
+ 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));
+ TALER_string_to_amount ("EUR:5.5",
+ &hamount);
+ TALER_amount_hton (&namount,
+ &hamount);
+ TALER_string_to_amount ("EUR:4.4",
+ &hamount);
+ /* FIXME: test TALER_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),
+ 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_end
+ };
+ struct TALER_PQ_QueryParam params_select[] = {
+ TALER_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),
+ 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_end
+ };
+
+ result = TALER_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);
+ 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)));
+ GNUNET_break (0 ==
+ TALER_amount_cmp (&hamount,
+ &hamount2));
+ TALER_string_to_amount ("EUR:5.5",
+ &hamount);
+ TALER_amount_ntoh (&hamount2,
+ &namount2);
+ 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));
- // FIXME: init pub, sig
- result = TALER_PQ_exec_prepared (conn,
- "test_insert",
- params_insert);
- PQclear (result);
- result = TALER_PQ_exec_prepared (conn,
- "test_select",
- params_select);
- ret = TALER_PQ_extract_result (result,
- results_select,
- 0);
- // FIXME: cmp results!
- TALER_PQ_cleanup_result (results_select);
- PQclear (result);
-
+ TALER_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;
@@ -164,8 +238,10 @@ main(int argc,
PGresult *result;
int ret;
- // FIXME: pass valid connect string for tests...
- conn = PQconnectdb ("");
+ GNUNET_log_setup ("test-pq",
+ "WARNING",
+ NULL);
+ conn = PQconnectdb ("postgres:///talercheck");
if (CONNECTION_OK != PQstatus (conn))
{
fprintf (stderr,
@@ -177,7 +253,7 @@ main(int argc,
}
result = PQexec (conn,
- "CREATE TABLE test_pq ("
+ "CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
" pub BYTEA NOT NULL"
",sig BYTEA NOT NULL"
",abs_time INT8 NOT NULL"
@@ -189,6 +265,7 @@ main(int argc,
",namount_val INT8 NOT NULL"
",namount_frac INT4 NOT NULL"
",namount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+ ",vsize VARCHAR NOT NULL"
")");
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
@@ -204,7 +281,6 @@ main(int argc,
postgres_prepare (conn))
{
GNUNET_break (0);
- PQclear (result);
PQfinish (conn);
return 1;
}