gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: [pq] added array support for tal


From: gnunet
Subject: [taler-exchange] branch master updated: [pq] added array support for taler_amount composite type
Date: Sat, 29 Jul 2023 21:28:25 +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 ecf6b275 [pq] added array support for taler_amount composite type
ecf6b275 is described below

commit ecf6b2750bb6ed9157aece72602dd042a50e36f3
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Sat Jul 29 21:26:58 2023 +0200

    [pq] added array support for taler_amount composite type
    
    API added:
    - TALER_PQ_query_param_array_amount
    - TALER_PQ_result_spec_array_amount
---
 src/include/taler_pq_lib.h | 32 ++++++++++++++++++
 src/pq/pq_common.h         |  2 +-
 src/pq/pq_query_helper.c   | 65 ++++++++++++++++++++++++++++++++----
 src/pq/pq_result_helper.c  | 82 ++++++++++++++++++++++++++++++++++++++++++++++
 src/pq/test_pq.c           | 57 +++++++++++++++++++++++++++++---
 5 files changed, 226 insertions(+), 12 deletions(-)

diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h
index 051962b2..fddfd2a2 100644
--- a/src/include/taler_pq_lib.h
+++ b/src/include/taler_pq_lib.h
@@ -193,6 +193,19 @@ TALER_PQ_query_param_array_blinded_coin_hash (
   const struct TALER_BlindedCoinHashP *coin_evs,
   const struct GNUNET_PQ_Context *db);
 
+/**
+ * Generate query parameter for an array of mounts
+ *
+ * @param num of elements in @e amounts
+ * @param amounts continuous array of amounts
+ * @param db context for db-connection, needed for OID-lookup
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_array_amount (
+  size_t num,
+  const struct TALER_Amount *amounts,
+  struct GNUNET_PQ_Context *db);
+
 /**
  * Currency amount expected.
  *
@@ -356,6 +369,25 @@ TALER_PQ_result_spec_array_denom_hash (
   size_t *num,
   struct TALER_DenominationHashP **denom_hs);
 
+/**
+ * Array of amounts
+ *
+ * @param db context of the database connection
+ * @param name name of the field in the table
+ * @param currency The currency
+ * @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 (
+  struct GNUNET_PQ_Context *db, /* not const because we need to query 
dynamically */
+  const char *name,
+  const char *currency,
+  size_t *num,
+  struct TALER_Amount **amounts);
+
+
 #endif  /* TALER_PQ_LIB_H_ */
 
 /* end of include/taler_pq_lib.h */
diff --git a/src/pq/pq_common.h b/src/pq/pq_common.h
index 79c9d83c..26137f42 100644
--- a/src/pq/pq_common.h
+++ b/src/pq/pq_common.h
@@ -43,7 +43,7 @@ enum TALER_PQ_ArrayType
   TALER_PQ_array_of_blinded_denom_sig,
   TALER_PQ_array_of_blinded_coin_hash,
   TALER_PQ_array_of_denom_hash,
-  /* TODO[oec]: Next up: TALER_PQ_array_of_amount, */
+  TALER_PQ_array_of_amount,
   TALER_PQ_array_of_MAX,       /* must be last */
 };
 
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index 6d8318b4..a21b0b1d 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -791,6 +791,11 @@ struct qconv_array_cls
    * Oid of the array elements
    */
   Oid oid;
+
+  /**
+   * db context, needed for OID-lookup of basis-types
+   */
+  const struct GNUNET_PQ_Context *db;
 };
 
 /**
@@ -964,6 +969,20 @@ qconv_array (
 
       switch (meta->typ)
       {
+      case TALER_PQ_array_of_amount:
+        {
+          const struct TALER_Amount *amounts = data;
+          struct TALER_PQ_Amount_P am = MAKE_TALER_PQ_AMOUNT_P (meta->db,
+                                                                &amounts[i]);
+
+          *(uint32_t *) out = htonl (2); /* number of elements in tuple */
+          out += sizeof(uint32_t);
+          sz -= sizeof(uint32_t);
+          GNUNET_memcpy (out,
+                         &am,
+                         sizeof(am));
+          break;
+        }
       case TALER_PQ_array_of_blinded_denom_sig:
         {
           const struct TALER_BlindedDenominationSignature *denom_sigs = data;
@@ -1066,7 +1085,8 @@ query_param_array_generic (
   const size_t *sizes,
   size_t same_size,
   enum TALER_PQ_ArrayType typ,
-  Oid oid)
+  Oid oid,
+  const struct GNUNET_PQ_Context *db)
 {
   struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls);
   meta->typ = typ;
@@ -1074,6 +1094,7 @@ query_param_array_generic (
   meta->sizes = sizes;
   meta->same_size = same_size;
   meta->continuous = continuous;
+  meta->db = db;
 
   struct GNUNET_PQ_QueryParam res = {
     .conv = qconv_array,
@@ -1101,8 +1122,10 @@ TALER_PQ_query_param_array_blinded_denom_sig (
                                     0,
                                     TALER_PQ_array_of_blinded_denom_sig,
                                     GNUNET_PQ_get_oid (db,
-                                                       
GNUNET_PQ_DATATYPE_BYTEA));
-};
+                                                       
GNUNET_PQ_DATATYPE_BYTEA),
+                                    NULL);
+}
+
 
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_array_blinded_coin_hash (
@@ -1117,8 +1140,10 @@ TALER_PQ_query_param_array_blinded_coin_hash (
                                     sizeof(struct TALER_BlindedCoinHashP),
                                     TALER_PQ_array_of_blinded_coin_hash,
                                     GNUNET_PQ_get_oid (db,
-                                                       
GNUNET_PQ_DATATYPE_BYTEA));
-};
+                                                       
GNUNET_PQ_DATATYPE_BYTEA),
+                                    NULL);
+}
+
 
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_array_denom_hash (
@@ -1133,6 +1158,32 @@ TALER_PQ_query_param_array_denom_hash (
                                     sizeof(struct TALER_DenominationHashP),
                                     TALER_PQ_array_of_denom_hash,
                                     GNUNET_PQ_get_oid (db,
-                                                       
GNUNET_PQ_DATATYPE_BYTEA));
-};
+                                                       
GNUNET_PQ_DATATYPE_BYTEA),
+                                    NULL);
+}
+
+
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_array_amount (
+  size_t num,
+  const struct TALER_Amount *amounts,
+  struct GNUNET_PQ_Context *db)
+{
+  if (TALER_PQ_CompositeOIDs[0] == 0)
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_PQ_load_oids_for_composite_types (db));
+
+  return query_param_array_generic (
+    num,
+    true,
+    amounts,
+    NULL,
+    sizeof(uint32_t) /* the # of elements in the tuple, here: 2 */
+    + sizeof(struct TALER_PQ_Amount_P),
+    TALER_PQ_array_of_amount,
+    TALER_PQ_CompositeOIDs[TALER_PQ_CompositeAmount],
+    db);
+}
+
+
 /* end of pq/pq_query_helper.c */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index ac1642ba..52e42562 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -1136,6 +1136,12 @@ struct ArrayResultCls
   /* Out-pointer. If @a typ is TALER_PQ_array_of_byte and @a same_size is 0,
    * allocate and put the array of @a num sizes here. NULL otherwise */
   size_t **sizes;
+
+  /* DB_connection, needed for OID-lookup for composite types */
+  const struct GNUNET_PQ_Context *db;
+
+  /* Currency information for amount composites */
+  char currency[TALER_CURRENCY_LEN];
 };
 
 /**
@@ -1216,6 +1222,43 @@ extract_array_generic (
 
     switch (info->typ)
     {
+    case TALER_PQ_array_of_amount:
+      {
+        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_Amount_P ap;
+          struct TALER_Amount *amount = &amounts[i];
+          size_t sz = ntohl (*(uint32_t *) in);
+          in += sizeof(uint32_t);
+
+          /* total size for this array-entry */
+          FAIL_IF ((sizeof(uint32_t)
+                    + sizeof(struct TALER_PQ_Amount_P))
+                   > sz);
+
+          /* number of elements in composite type*/
+          sz = ntohl (*(uint32_t *) in);
+          in += sizeof(uint32_t);
+          FAIL_IF (2 != sz);
+
+          ap = *(struct TALER_PQ_Amount_P *) in;
+          amount->value = GNUNET_ntohll (ap.v);
+          amount->fraction = ntohl (ap.f);
+          GNUNET_memcpy (amount->currency,
+                         info->currency,
+                         TALER_CURRENCY_LEN);
+
+          in += sizeof(struct TALER_PQ_Amount_P);
+        }
+        return GNUNET_OK;
+      }
     case TALER_PQ_array_of_denom_hash:
       if (NULL != dst_size)
         *dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim);
@@ -1415,5 +1458,44 @@ TALER_PQ_result_spec_array_denom_hash (
 
 };
 
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_array_amount (
+  struct GNUNET_PQ_Context *db,
+  const char *name,
+  const char *currency,
+  size_t *num,
+  struct TALER_Amount **amounts)
+{
+  if (TALER_PQ_CompositeOIDs[0] == 0)
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_PQ_load_oids_for_composite_types (db));
+
+  struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls);
+
+  info->num = num;
+  info->typ = TALER_PQ_array_of_amount;
+  info->oid = TALER_PQ_CompositeOIDs[TALER_PQ_CompositeAmount];
+  info->db = db;
+
+  {
+    size_t clen = GNUNET_MIN (TALER_CURRENCY_LEN - 1,
+                              strlen (currency));
+    GNUNET_memcpy (&info->currency,
+                   currency,
+                   clen);
+  }
+
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = extract_array_generic,
+    .cleaner = array_cleanup,
+    .dst = (void *) amounts,
+    .fname = name,
+    .cls = info,
+  };
+  return res;
+
+
+}
+
 
 /* end of pq_result_helper.c */
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
index 9f18e767..a09e500f 100644
--- a/src/pq/test_pq.c
+++ b/src/pq/test_pq.c
@@ -35,20 +35,24 @@ postgres_prepare (struct GNUNET_PQ_Context *db)
   struct GNUNET_PQ_PreparedStatement ps[] = {
     GNUNET_PQ_make_prepare ("test_insert",
                             "INSERT INTO test_pq ("
-                            " hamount_val"
+                            " tamount"
+                            ",hamount_val"
                             ",hamount_frac"
                             ",namount_val"
                             ",namount_frac"
                             ",json"
+                            ",aamount"
                             ") VALUES "
-                            "($1, $2, $3, $4, $5);"),
+                            "($1, $2, $3, $4, $5, $6, $7);"),
     GNUNET_PQ_make_prepare ("test_select",
                             "SELECT"
-                            " hamount_val"
+                            " tamount"
+                            ",hamount_val"
                             ",hamount_frac"
                             ",namount_val"
                             ",namount_frac"
                             ",json"
+                            ",aamount"
                             " FROM test_pq;"),
     GNUNET_PQ_PREPARED_STATEMENT_END
   };
@@ -66,15 +70,31 @@ postgres_prepare (struct GNUNET_PQ_Context *db)
 static int
 run_queries (struct GNUNET_PQ_Context *conn)
 {
+  struct TALER_Amount tamount;
   struct TALER_Amount hamount;
   struct TALER_Amount hamount2;
   struct TALER_AmountNBO namount;
   struct TALER_AmountNBO namount2;
+  struct TALER_Amount aamount[3];
+  struct TALER_Amount *pamount;
+  size_t npamount;
   PGresult *result;
   int ret;
   json_t *json;
   json_t *json2;
 
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:5.3",
+                                         &aamount[0]));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:6.4",
+                                         &aamount[1]));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:7.5",
+                                         &aamount[2]));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:7.7",
+                                         &tamount));
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount ("EUR:5.5",
                                          &hamount));
@@ -88,9 +108,13 @@ run_queries (struct GNUNET_PQ_Context *conn)
   GNUNET_assert (NULL != json);
   {
     struct GNUNET_PQ_QueryParam params_insert[] = {
+      TALER_PQ_query_param_amount_tuple (conn, &tamount),
       TALER_PQ_query_param_amount (&hamount),
       TALER_PQ_query_param_amount_nbo (&namount),
       TALER_PQ_query_param_json (json),
+      TALER_PQ_query_param_array_amount (3,
+                                         aamount,
+                                         conn),
       GNUNET_PQ_query_param_end
     };
 
@@ -129,6 +153,12 @@ run_queries (struct GNUNET_PQ_Context *conn)
       TALER_PQ_result_spec_amount ("hamount", "EUR", &hamount2),
       TALER_PQ_result_spec_amount_nbo ("namount", "EUR", &namount2),
       TALER_PQ_result_spec_json ("json", &json2),
+      TALER_PQ_result_spec_amount_tuple ("tamount", "EUR", &tamount),
+      TALER_PQ_result_spec_array_amount (conn,
+                                         "aamount",
+                                         "EUR",
+                                         &npamount,
+                                         &pamount),
       GNUNET_PQ_result_spec_end
     };
 
@@ -148,6 +178,15 @@ run_queries (struct GNUNET_PQ_Context *conn)
                                     &hamount2));
     GNUNET_break (42 ==
                   json_integer_value (json_object_get (json2, "foo")));
+
+    GNUNET_break (3 == npamount);
+    for (size_t i = 0; i < 3; i++)
+    {
+      GNUNET_break (0 ==
+                    TALER_amount_cmp (&aamount[i],
+                                      &pamount[i]));
+    }
+
     GNUNET_PQ_cleanup_result (results_select);
     PQclear (result);
   }
@@ -164,12 +203,22 @@ main (int argc,
       const char *const argv[])
 {
   struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("DO $$ "
+                            " BEGIN"
+                            " CREATE TYPE taler_amount AS"
+                            "   (val INT8, frac INT4);"
+                            " EXCEPTION"
+                            "   WHEN duplicate_object THEN null;"
+                            " END "
+                            "$$;"),
     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
-                            " hamount_val INT8 NOT NULL"
+                            " tamount taler_amount NOT NULL"
+                            ",hamount_val INT8 NOT NULL"
                             ",hamount_frac INT4 NOT NULL"
                             ",namount_val INT8 NOT NULL"
                             ",namount_frac INT4 NOT NULL"
                             ",json VARCHAR NOT NULL"
+                            ",aamount taler_amount[]"
                             ")"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
   };

-- 
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]