commit baaaebc76618d9bbde84511afcddf015b7fd96da
parent c4c3844cd45e8011db7eb97f9310abaa84757c8c
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Tue, 11 Nov 2025 15:17:51 +0100
adding TALER_PQ_result_spec_array_amount_with_currency
Diffstat:
3 files changed, 130 insertions(+), 8 deletions(-)
diff --git a/src/include/taler/taler_pq_lib.h b/src/include/taler/taler_pq_lib.h
@@ -454,6 +454,23 @@ TALER_PQ_result_spec_array_amount (
/**
+ * Array of amounts including currency
+ *
+ * @param db context of the database connection
+ * @param name name of the field in the table
+ * @param[out] num number of elements in @e amounts
+ * @param[out] amounts where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_array_amount_with_currency (
+ struct GNUNET_PQ_Context *db,
+ const char *name,
+ size_t *num,
+ struct TALER_Amount **amounts);
+
+
+/**
* Array of public R-values for Clause-Schnorr
*
* @param db context of the database connection
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
@@ -1163,13 +1163,13 @@ extract_array_generic (
*((void **) dst) = NULL;
#define FAIL_IF(cond) \
- do { \
- if ((cond)) \
- { \
- GNUNET_break (! (cond)); \
- goto FAIL; \
- } \
- } while (0)
+ do { \
+ if ((cond)) \
+ { \
+ GNUNET_break (! (cond)); \
+ goto FAIL; \
+ } \
+ } while (0)
col_num = PQfnumber (result, fname);
FAIL_IF (0 > col_num);
@@ -1252,6 +1252,54 @@ extract_array_generic (
}
return GNUNET_OK;
}
+ case TALER_PQ_array_of_amount_currency:
+ {
+ struct TALER_Amount *amounts;
+ if (NULL != dst_size)
+ *dst_size = sizeof(struct TALER_Amount) * (header.dim);
+
+ amounts = GNUNET_new_array (header.dim,
+ struct TALER_Amount);
+ *((void **) dst) = amounts;
+
+ for (uint32_t i = 0; i < header.dim; i++)
+ {
+ struct TALER_PQ_AmountCurrencyP ap;
+ struct TALER_Amount *amount = &amounts[i];
+ uint32_t val;
+ size_t sz;
+
+ GNUNET_memcpy (&val,
+ in,
+ sizeof(val));
+ sz = ntohl (val);
+ in += sizeof(val);
+
+ FAIL_IF ( (sz >= sizeof(ap)) ||
+ (sz <= sizeof(ap) - TALER_CURRENCY_LEN) );
+
+ memset (&ap,
+ 0,
+ sizeof(ap));
+ GNUNET_memcpy (&ap,
+ in,
+ sz);
+ FAIL_IF (3 != ntohl (ap.cnt));
+
+ amount->value = GNUNET_ntohll (ap.v);
+ amount->fraction = ntohl (ap.f);
+ GNUNET_memcpy (amount->currency,
+ ap.c,
+ TALER_CURRENCY_LEN);
+
+ FAIL_IF ('\0' != amount->currency[TALER_CURRENCY_LEN - 1]);
+ FAIL_IF (amount->value >= TALER_AMOUNT_MAX_VALUE);
+ FAIL_IF (amount->fraction >= TALER_AMOUNT_FRAC_BASE);
+
+ in += sz;
+ }
+ return GNUNET_OK;
+ }
case TALER_PQ_array_of_denom_hash:
if (NULL != dst_size)
*dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim);
@@ -1587,6 +1635,37 @@ TALER_PQ_result_spec_array_amount (
struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_array_amount_with_currency (
+ struct GNUNET_PQ_Context *db,
+ const char *name,
+ size_t *num,
+ struct TALER_Amount **amounts)
+{
+ struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
+
+ info->num = num;
+ info->typ = TALER_PQ_array_of_amount_currency;
+ info->db = db;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_PQ_get_oid_by_name (db,
+ "taler_amount_currency",
+ &info->oid));
+
+ {
+ struct GNUNET_PQ_ResultSpec res = {
+ .conv = extract_array_generic,
+ .cleaner = &array_cleanup,
+ .dst = (void *) amounts,
+ .fname = name,
+ .cls = info,
+ };
+
+ return res;
+ }
+}
+
+
+struct GNUNET_PQ_ResultSpec
TALER_PQ_result_spec_array_hash_code (
struct GNUNET_PQ_Context *db,
const char *name,
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
@@ -39,17 +39,19 @@ postgres_prepare (struct GNUNET_PQ_Context *db)
" tamount"
",json"
",aamount"
+ ",aamountc"
",tamountc"
",hash"
",hashes"
",cs_r_pubs"
") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);"),
+ "($1, $2, $3, $4, $5, $6, $7, $8);"),
GNUNET_PQ_make_prepare ("test_select",
"SELECT"
" tamount"
",json"
",aamount"
+ ",aamountc"
",tamountc"
",hash"
",hashes"
@@ -73,6 +75,7 @@ run_queries (struct GNUNET_PQ_Context *conn)
{
struct TALER_Amount tamount;
struct TALER_Amount aamount[3];
+ struct TALER_Amount aamountc[2];
struct TALER_Amount tamountc;
struct GNUNET_HashCode hc =
{{0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
@@ -104,6 +107,12 @@ run_queries (struct GNUNET_PQ_Context *conn)
TALER_string_to_amount ("EUR:7.7",
&tamount));
GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("USD:3.2",
+ &aamountc[0]));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("CHF:4.5",
+ &aamountc[1]));
+ GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("FOO:8.7",
&tamountc));
json = json_object ();
@@ -123,6 +132,9 @@ run_queries (struct GNUNET_PQ_Context *conn)
TALER_PQ_query_param_array_amount (3,
aamount,
conn),
+ TALER_PQ_query_param_array_amount_with_currency (2,
+ aamountc,
+ conn),
TALER_PQ_query_param_amount_with_currency (conn,
&tamountc),
GNUNET_PQ_query_param_fixed_size (&hc,
@@ -164,10 +176,12 @@ run_queries (struct GNUNET_PQ_Context *conn)
struct TALER_Amount tamount2;
struct TALER_Amount tamountc2;
struct TALER_Amount *pamount;
+ struct TALER_Amount *pamountc;
struct GNUNET_HashCode hc2;
struct GNUNET_HashCode *hcs2;
struct GNUNET_CRYPTO_CSPublicRPairP *out_cs_r_pubs;
size_t npamount;
+ size_t npamountc;
size_t nhcs;
size_t n_rpubs;
json_t *json2;
@@ -185,6 +199,10 @@ run_queries (struct GNUNET_PQ_Context *conn)
"EUR",
&npamount,
&pamount),
+ TALER_PQ_result_spec_array_amount_with_currency (conn,
+ "aamountc",
+ &npamountc,
+ &pamountc),
TALER_PQ_result_spec_amount_with_currency ("tamountc",
&tamountc2),
GNUNET_PQ_result_spec_auto_from_type ("hash",
@@ -222,6 +240,13 @@ run_queries (struct GNUNET_PQ_Context *conn)
TALER_amount_cmp (&aamount[i],
&pamount[i]));
}
+ GNUNET_break (2 == npamountc);
+ for (size_t i = 0; i < npamountc; i++)
+ {
+ GNUNET_break (0 ==
+ TALER_amount_cmp (&aamountc[i],
+ &pamountc[i]));
+ }
GNUNET_break (0 ==
TALER_amount_cmp (&tamountc,
&tamountc2));
@@ -283,6 +308,7 @@ main (int argc,
" tamount taler_amount NOT NULL"
",json VARCHAR NOT NULL"
",aamount taler_amount[]"
+ ",aamountc taler_amount_currency[]"
",tamountc taler_amount_currency"
",hash gnunet_hashcode"
",hashes gnunet_hashcode[]"