gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: [WiP] added TALER_AMOUNT type to


From: gnunet
Subject: [taler-exchange] branch master updated: [WiP] added TALER_AMOUNT type to Postgres - first in age_withdraw
Date: Fri, 28 Jul 2023 00:05:58 +0200

This is an automated email from the git hooks/post-receive script.

oec pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 571d43ce [WiP] added TALER_AMOUNT type to Postgres - first in 
age_withdraw
571d43ce is described below

commit 571d43cef3732ed6f491d91a9e767a80008edeb1
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Thu Jul 27 23:57:07 2023 +0200

    [WiP] added TALER_AMOUNT type to Postgres - first in age_withdraw
    
    - Added a type TALER_AMOUNT (val INT8, frac INT4) to Postgres.
    
    - Added PLSQL functions/procedures
            - amount_normalize(a)
            - amount_add(a, b)
            - amount_left_minus_right(l, r, diff, ok bool)
    
    - Added PQ-helper functions
            - TALER_PQ_query_param_amount_tuple()
            - TALER_PQ_result_spec_amount_tuple()
    
    - In table 'age_withdraw', changed fields 'amount_with_fee_val' and 
'..._frac'
      into single field 'amount_with_fee' be of type TALER_AMOUNT
    
    - Changed functions/stored procedures 'do_age_withdraw' and
      'get_age_withdraw' to use new APIs.
    
    => make check runs through without errors,
       age-withdraw and -reveal test passes.
---
 src/exchangedb/0003-age_withdraw.sql        |   3 +-
 src/exchangedb/exchange-0001.sql            |  91 +++++++++++++++++
 src/exchangedb/exchange_do_age_withdraw.sql |  60 +++++-------
 src/exchangedb/pg_do_age_withdraw.c         |   5 +-
 src/exchangedb/pg_get_age_withdraw.c        |   8 +-
 src/exchangedb/test_exchangedb.c            |   5 +
 src/include/taler_pq_lib.h                  |  25 +++++
 src/pq/pq_query_helper.c                    |  83 +++++++++++++++-
 src/pq/pq_result_helper.c                   | 145 +++++++++++++++++++++++++++-
 9 files changed, 377 insertions(+), 48 deletions(-)

diff --git a/src/exchangedb/0003-age_withdraw.sql 
b/src/exchangedb/0003-age_withdraw.sql
index 9816e466..c85eb60f 100644
--- a/src/exchangedb/0003-age_withdraw.sql
+++ b/src/exchangedb/0003-age_withdraw.sql
@@ -29,8 +29,7 @@ BEGIN
       '(age_withdraw_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
       ',h_commitment BYTEA NOT NULL CONSTRAINT h_commitment_length 
CHECK(LENGTH(h_commitment)=64)'
       ',max_age SMALLINT NOT NULL CONSTRAINT max_age_positive 
CHECK(max_age>=0)'
-      ',amount_with_fee_val INT8 NOT NULL'
-      ',amount_with_fee_frac INT4 NOT NULL'
+      ',amount_with_fee TALER_AMOUNT NOT NULL'
       ',reserve_pub BYTEA NOT NULL CONSTRAINT reserve_pub_length 
CHECK(LENGTH(reserve_pub)=32)'
       ',reserve_sig BYTEA NOT NULL CONSTRAINT reserve_sig_length 
CHECK(LENGTH(reserve_sig)=64)'
       ',noreveal_index SMALLINT NOT NULL CONSTRAINT noreveal_index_positive 
CHECK(noreveal_index>=0)'
diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql
index d08aab4e..79a0dec1 100644
--- a/src/exchangedb/exchange-0001.sql
+++ b/src/exchangedb/exchange-0001.sql
@@ -137,6 +137,97 @@ COMMENT ON FUNCTION comment_partitioned_column
   IS 'Generic function to create a comment on column of a table that is 
partitioned.';
 
 
+--------------------------------------------------------------
+-- Taler amounts and helper functiosn
+-------------------------------------------------------------
+
+DO $$
+BEGIN
+  CREATE TYPE TALER_AMOUNT
+    AS (val  INT8
+       ,frac INT4);
+
+  COMMENT ON TYPE TALER_AMOUNT
+    IS 'Type to store a TALER-amount as (val, frac) pair.';
+EXCEPTION
+  WHEN duplicate_object THEN null;
+END
+$$;
+
+CREATE PROCEDURE amount_normalize(
+    IN amount TALER_AMOUNT
+  ,OUT normalized TALER_AMOUNT
+)
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  normalized.val = amount.val + amount.frac / 100000000;
+  normalized.frac = amount.frac % 100000000;
+END $$;
+
+COMMENT ON PROCEDURE amount_normalize
+  IS 'Returns the normalized amount by adding to the .val the value of (.frac 
/ 100000000) and removing the modulus 100000000 from .frac.';
+
+CREATE PROCEDURE amount_add(
+   IN a TALER_AMOUNT
+  ,IN b TALER_AMOUNT
+  ,OUT sum TALER_AMOUNT
+)
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  sum = (a.val + b.val, a.frac + b.frac);
+  CALL amount_normalize(sum ,sum);
+
+  IF (sum.val > (1<<52))
+  THEN
+    RAISE EXCEPTION 'addition overflow';
+  END IF;
+END $$;
+
+COMMENT ON PROCEDURE amount_add
+  IS 'Returns the normalized sum of two amounts. It raises an exception when 
the resulting .val is larger than 2^52';
+
+CREATE FUNCTION amount_left_minus_right(
+  IN  l TALER_AMOUNT
+ ,IN  r TALER_AMOUNT
+ ,OUT diff TALER_AMOUNT
+ ,OUT ok BOOLEAN
+)
+LANGUAGE plpgsql
+AS $$
+BEGIN
+
+IF (l.val > r.val)
+THEN
+  ok = TRUE;
+  IF (l.frac >= r.frac)
+  THEN
+    diff.val  = l.val  - r.val;
+    diff.frac = l.frac - r.frac;
+  ELSE
+    diff.val  = l.val  - r.val - 1;
+    diff.frac = l.frac + 100000000 - r.frac;
+  END IF;
+ELSE
+  IF (l.val = r.val) AND (l.frac >= r.frac)
+  THEN
+    diff.val  = 0;
+    diff.frac = l.frac - r.frac;
+    ok = TRUE;
+  ELSE
+    diff = (-1, -1);
+    ok = FALSE;
+  END IF;
+END IF;
+
+RETURN;
+END $$;
+
+COMMENT ON FUNCTION amount_left_minus_right
+  IS 'Subtracts the right amount from the left and returns the difference and 
TRUE, if the left amount is larger than the right, or an invalid amount and 
FALSE otherwise.';
+
+
 ---------------------------------------------------------------------------
 --                   Main DB setup loop
 ---------------------------------------------------------------------------
diff --git a/src/exchangedb/exchange_do_age_withdraw.sql 
b/src/exchangedb/exchange_do_age_withdraw.sql
index 49a1433f..e76d4ba7 100644
--- a/src/exchangedb/exchange_do_age_withdraw.sql
+++ b/src/exchangedb/exchange_do_age_withdraw.sql
@@ -16,8 +16,7 @@
 -- @author Özgür Kesim
 
 CREATE OR REPLACE FUNCTION exchange_do_age_withdraw(
-  IN amount_val INT8,
-  IN amount_frac INT4,
+  IN amount_with_fee TALER_AMOUNT,
   IN rpub BYTEA,
   IN rsig BYTEA,
   IN now INT8,
@@ -38,8 +37,9 @@ LANGUAGE plpgsql
 AS $$
 DECLARE
   reserve_gc INT8;
-  reserve_val INT8;
-  reserve_frac INT4;
+  difference RECORD;
+  balance  TALER_AMOUNT;
+  new_balance TALER_AMOUNT;
   not_before date;
   earliest_date date;
 BEGIN
@@ -55,8 +55,8 @@ SELECT
   ,gc_date
   ,birthday
  INTO
-   reserve_val
-  ,reserve_frac
+   balance.val
+  ,balance.frac
   ,reserve_gc
   ,reserve_birthday
   FROM exchange.reserves
@@ -102,31 +102,23 @@ END IF;
 age_ok = TRUE;
 required_age=0;
 
-
-
 -- Check reserve balance is sufficient.
-IF (reserve_val > amount_val)
-THEN
-  IF (reserve_frac >= amount_frac)
-  THEN
-    reserve_val=reserve_val - amount_val;
-    reserve_frac=reserve_frac - amount_frac;
-  ELSE
-    reserve_val=reserve_val - amount_val - 1;
-    reserve_frac=reserve_frac + 100000000 - amount_frac;
-  END IF;
-ELSE
-  IF (reserve_val = amount_val) AND (reserve_frac >= amount_frac)
-  THEN
-    reserve_val=0;
-    reserve_frac=reserve_frac - amount_frac;
-  ELSE
-    balance_ok=FALSE;
-    RETURN;
-  END IF;
+SELECT *
+INTO 
+  difference
+FROM 
+  amount_left_minus_right(
+     balance
+    ,amount_with_fee);
+
+balance_ok = difference.ok;
+
+IF NOT balance_ok
+THEN 
+  RETURN;
 END IF;
 
-balance_ok=TRUE;
+new_balance = difference.diff;
 
 -- Calculate new expiration dates.
 min_reserve_gc=GREATEST(min_reserve_gc,reserve_gc);
@@ -134,8 +126,8 @@ min_reserve_gc=GREATEST(min_reserve_gc,reserve_gc);
 -- Update reserve balance.
 UPDATE reserves SET
   gc_date=min_reserve_gc
- ,current_balance_val=reserve_val
- ,current_balance_frac=reserve_frac
+ ,current_balance_val=new_balance.val
+ ,current_balance_frac=new_balance.frac
 WHERE
   reserves.reserve_pub=rpub;
 
@@ -143,8 +135,7 @@ WHERE
 INSERT INTO exchange.age_withdraw
   (h_commitment
   ,max_age
-  ,amount_with_fee_val
-  ,amount_with_fee_frac
+  ,amount_with_fee
   ,reserve_pub
   ,reserve_sig
   ,noreveal_index
@@ -154,8 +145,7 @@ INSERT INTO exchange.age_withdraw
 VALUES
   (h_commitment
   ,maximum_age_committed
-  ,amount_val
-  ,amount_frac
+  ,amount_with_fee
   ,rpub
   ,rsig
   ,noreveal_index
@@ -176,6 +166,6 @@ END IF;
 
 END $$;
 
-COMMENT ON FUNCTION exchange_do_age_withdraw(INT8, INT4, BYTEA, BYTEA, INT8, 
INT8, BYTEA, INT2, INT2, BYTEA[], INT8[], BYTEA[])
+COMMENT ON FUNCTION exchange_do_age_withdraw(TALER_AMOUNT, BYTEA, BYTEA, INT8, 
INT8, BYTEA, INT2, INT2, BYTEA[], INT8[], BYTEA[])
   IS 'Checks whether the reserve has sufficient balance for an age-withdraw 
operation (or the request is repeated and was previously approved) and that age 
requirements are met. If so updates the database with the result. Includes 
storing the blinded planchets and denomination signatures, or signaling 
conflict';
 
diff --git a/src/exchangedb/pg_do_age_withdraw.c 
b/src/exchangedb/pg_do_age_withdraw.c
index 4fb52d46..0c79f58c 100644
--- a/src/exchangedb/pg_do_age_withdraw.c
+++ b/src/exchangedb/pg_do_age_withdraw.c
@@ -44,7 +44,8 @@ TEH_PG_do_age_withdraw (
   struct PostgresClosure *pg = cls;
   struct GNUNET_TIME_Timestamp gc;
   struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (&commitment->amount_with_fee),
+    TALER_PQ_query_param_amount_tuple (pg->conn,
+                                       &commitment->amount_with_fee),
     GNUNET_PQ_query_param_auto_from_type (&commitment->reserve_pub),
     GNUNET_PQ_query_param_auto_from_type (&commitment->reserve_sig),
     GNUNET_PQ_query_param_timestamp (&now),
@@ -96,7 +97,7 @@ TEH_PG_do_age_withdraw (
            ",reserve_birthday"
            ",conflict"
            " FROM exchange_do_age_withdraw"
-           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);");
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                    "call_age_withdraw",
                                                    params,
diff --git a/src/exchangedb/pg_get_age_withdraw.c 
b/src/exchangedb/pg_get_age_withdraw.c
index a66051c7..62ccaa83 100644
--- a/src/exchangedb/pg_get_age_withdraw.c
+++ b/src/exchangedb/pg_get_age_withdraw.c
@@ -48,8 +48,9 @@ TEH_PG_get_age_withdraw (
                                           &aw->reserve_pub),
     GNUNET_PQ_result_spec_uint16 ("max_age",
                                   &aw->max_age),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 &aw->amount_with_fee),
+    TALER_PQ_result_spec_amount_tuple ("amount_with_fee",
+                                       pg->currency,
+                                       &aw->amount_with_fee),
     GNUNET_PQ_result_spec_uint16 ("noreveal_index",
                                   &aw->noreveal_index),
     TALER_PQ_result_spec_array_blinded_coin_hash (
@@ -83,8 +84,7 @@ TEH_PG_get_age_withdraw (
            ",reserve_sig"
            ",reserve_pub"
            ",max_age"
-           ",amount_with_fee_val"
-           ",amount_with_fee_frac"
+           ",amount_with_fee"
            ",noreveal_index"
            ",h_blind_evs"
            ",denom_sigs"
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index ac3735b2..36f51120 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1421,6 +1421,8 @@ run (void *cls)
     bool found;
     bool nonce_ok;
     bool balance_ok;
+    bool age_ok;
+    uint16_t maximum_age;
     uint64_t ruuid;
 
     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -1428,9 +1430,12 @@ run (void *cls)
                                  NULL,
                                  &cbc,
                                  now,
+                                 false,
                                  &found,
                                  &balance_ok,
                                  &nonce_ok,
+                                 &age_ok,
+                                 &maximum_age,
                                  &ruuid));
     GNUNET_assert (found);
     GNUNET_assert (nonce_ok);
diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h
index db77c53b..43561703 100644
--- a/src/include/taler_pq_lib.h
+++ b/src/include/taler_pq_lib.h
@@ -51,6 +51,19 @@ TALER_PQ_query_param_amount_nbo (const struct 
TALER_AmountNBO *x);
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_amount (const struct TALER_Amount *x);
 
+/**
+ * Generate query parameter (as record tuple) for an amount, consisting
+ * of the two components "value" and "fraction" in this order. The
+ * types must be a 64-bit integer and a 32-bit integer
+ * respectively. The currency is dropped.
+ *
+ * @param db The database context for OID lookup
+ * @param amount pointer to the query parameter to pass
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_amount_tuple (
+  const struct GNUNET_PQ_Context *db,
+  const struct TALER_Amount *amount);
 
 /**
  * Generate query parameter for a denomination public
@@ -180,6 +193,18 @@ TALER_PQ_result_spec_amount (const char *name,
                              const char *currency,
                              struct TALER_Amount *amount);
 
+/**
+ * Currency amount expected, from a record-field of (DB) taler_amount type
+ *
+ * @param name name of the field in the table
+ * @param currency currency to use for @a amount
+ * @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_tuple (const char *name,
+                                   const char *currency,
+                                   struct TALER_Amount *amount);
 
 /**
  * Denomination public key expected.
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index 9a02cdda..9ada2357 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -21,6 +21,7 @@
  * @author Christian Grothoff
  */
 #include "platform.h"
+#include <gnunet/gnunet_common.h>
 #include <gnunet/gnunet_util_lib.h>
 #include <gnunet/gnunet_pq_lib.h>
 #include "taler_pq_lib.h"
@@ -149,6 +150,84 @@ TALER_PQ_query_param_amount (const struct TALER_Amount *x)
 }
 
 
+/**
+ * Function called to convert input amount into SQL parameter as tuple.
+ *
+ * @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_tuple (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 GNUNET_PQ_Context *db = cls;
+  const struct TALER_Amount *amount = data;
+  size_t sz;
+
+  GNUNET_assert (NULL != db);
+  GNUNET_assert (NULL != amount);
+  GNUNET_assert (1 == param_length);
+  GNUNET_assert (1 <= scratch_length);
+  GNUNET_assert (sizeof (struct TALER_Amount) == data_len);
+  GNUNET_static_assert (sizeof(uint32_t) == sizeof(Oid));
+
+  {
+    char *out;
+    struct TALER_PQ_Amount_P d = MAKE_TALER_PQ_AMOUNT_P (db, amount);
+
+    sz = sizeof(uint32_t); /* number of elements in tuple */
+    sz += sizeof(d);
+
+    out = GNUNET_malloc (sz);
+    scratch[0] = out;
+
+    *(uint32_t *) out = htonl (2);
+    out += sizeof(uint32_t);
+
+    *(struct TALER_PQ_Amount_P*) out = d;
+
+  }
+
+  param_values[0] = scratch[0];
+  param_lengths[0] = sz;
+  param_formats[0] = 1;
+
+  return 1;
+}
+
+
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_amount_tuple (
+  const struct GNUNET_PQ_Context *db,
+  const struct TALER_Amount *amount)
+{
+  struct GNUNET_PQ_QueryParam res = {
+    .conv_cls = (void *) db,
+    .conv = &qconv_amount_tuple,
+    .data = amount,
+    .size = sizeof (*amount),
+    .num_params = 1,
+  };
+
+  return res;
+}
+
+
 /**
  * Function called to convert input argument into SQL parameters.
  *
@@ -793,7 +872,7 @@ qconv_array (
     RETURN_UNLESS ((0 == num) || (y / num == x));
 
     /* size of header */
-    total_size  = x = sizeof(struct TALER_PQ_ArrayHeader);
+    total_size  = x = sizeof(struct TALER_PQ_ArrayHeader_P);
     total_size += y;
     RETURN_UNLESS (total_size >= x);
 
@@ -862,7 +941,7 @@ qconv_array (
   /* Write data */
   {
     char *out = elements;
-    struct TALER_PQ_ArrayHeader h = {
+    struct TALER_PQ_ArrayHeader_P h = {
       .ndim = htonl (1),        /* We only support one-dimensional arrays */
       .has_null = htonl (0),    /* We do not support NULL entries in arrays */
       .lbound = htonl (1),      /* Default start index value */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index 0a734bbc..3ef2e71f 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -264,6 +264,145 @@ TALER_PQ_result_spec_amount (const char *name,
 }
 
 
+/**
+ * Extract an amount from a tuple from a Postgres database @a result at row @a 
row.
+ *
+ * @param cls closure, a `const char *` giving the currency
+ * @param result where to extract data from
+ * @param row 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 enum GNUNET_GenericReturnValue
+extract_amount_tuple (void *cls,
+                      PGresult *result,
+                      int row,
+                      const char *fname,
+                      size_t *dst_size,
+                      void *dst)
+{
+  struct TALER_Amount *r_amount = dst;
+  const char *currency = cls;
+  int col;
+  int len;
+
+  if (sizeof (struct TALER_Amount) != *dst_size)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  /* Set return value to invalid in case we don't finish */
+  memset (r_amount,
+          0,
+          sizeof (struct TALER_Amount));
+  col = PQfnumber (result,
+                   fname);
+  if (col < 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Field `%s' does not exist in result\n",
+                fname);
+    return GNUNET_SYSERR;
+  }
+  if (PQgetisnull (result,
+                   row,
+                   col))
+  {
+    return GNUNET_NO;
+  }
+
+  /* Parse the tuple */
+  {
+    char *in;
+    uint32_t num;
+    struct TALER_PQ_Amount_P ap;
+    int size;
+    const static int expected_size = sizeof(uint32_t) /* length */
+                                     + sizeof(struct TALER_PQ_Amount_P);
+
+    size = PQgetlength (result,
+                        row,
+                        col);
+
+    if (expected_size != size)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Incorrect size of binary field `%s' (got %d, expected 
%d)\n",
+                  fname,
+                  size,
+                  expected_size);
+      return GNUNET_SYSERR;
+    }
+
+    in = PQgetvalue (result,
+                     row,
+                     col);
+
+    num = ntohl (*(uint32_t *) in);
+    if (2 != num)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Incorrect number of elements in tuple-field `%s'\n",
+                  fname);
+      return GNUNET_SYSERR;
+    }
+    in += sizeof(uint32_t);
+    ap = *(struct TALER_PQ_Amount_P *) in;
+
+    /* TODO[oec]: OID-checks? */
+
+    r_amount->value = GNUNET_ntohll (ap.v);
+    r_amount->fraction = ntohl (ap.f);
+  }
+
+  if (r_amount->value >= TALER_AMOUNT_MAX_VALUE)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Value in field `%s' exceeds legal range\n",
+                fname);
+    return GNUNET_SYSERR;
+  }
+  if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Fraction in field `%s' exceeds legal range\n",
+                fname);
+    return GNUNET_SYSERR;
+  }
+
+  len = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
+                    strlen (currency));
+
+  GNUNET_memcpy (r_amount->currency,
+                 currency,
+                 len);
+  return GNUNET_OK;
+}
+
+
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_amount_tuple (const char *name,
+                                   const char *currency,
+                                   struct TALER_Amount *amount)
+{
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = &extract_amount_tuple,
+    .cls = (void *) currency,
+    .dst = (void *) amount,
+    .dst_size = sizeof (*amount),
+    .fname = name
+  };
+
+  return res;
+}
+
+
 /**
  * Extract data from a Postgres database @a result at row @a row.
  *
@@ -1027,7 +1166,7 @@ extract_array_generic (
   int data_sz;
   char *data;
   void *out = NULL;
-  struct TALER_PQ_ArrayHeader header;
+  struct TALER_PQ_ArrayHeader_P header;
   int col_num;
 
   GNUNET_assert (NULL != dst);
@@ -1053,8 +1192,8 @@ extract_array_generic (
   FAIL_IF (NULL == data);
 
   {
-    struct TALER_PQ_ArrayHeader *h =
-      (struct TALER_PQ_ArrayHeader *) data;
+    struct TALER_PQ_ArrayHeader_P *h =
+      (struct TALER_PQ_ArrayHeader_P *) data;
 
     header.ndim = ntohl (h->ndim);
     header.has_null = ntohl (h->has_null);

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]