gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] 19/277: backenddb implementation work


From: gnunet
Subject: [taler-merchant] 19/277: backenddb implementation work
Date: Sun, 05 Jul 2020 20:48:52 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

commit 64cc6eb8c6ed4b7867c76f57c7762414ab4d0685
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Apr 20 13:39:18 2020 +0200

    backenddb implementation work
---
 .../taler-merchant-httpd_private-get-products-ID.c |   4 +-
 .../taler-merchant-httpd_private-get-products.c    |   3 -
 ...aler-merchant-httpd_private-patch-products-ID.c |   6 +-
 .../taler-merchant-httpd_private-post-products.c   |   8 +-
 src/backenddb/plugin_merchantdb_postgres.c         | 346 ++++++++++++++++++++-
 src/include/taler_merchantdb_plugin.h              |   7 +-
 6 files changed, 348 insertions(+), 26 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_private-get-products-ID.c 
b/src/backend/taler-merchant-httpd_private-get-products-ID.c
index 85358ff..57b3182 100644
--- a/src/backend/taler-merchant-httpd_private-get-products-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-products-ID.c
@@ -79,8 +79,8 @@ TMH_private_get_products_ID (const struct TMH_RequestHandler 
*rh,
       (json_int_t) pd.total_lost,
       "description_i18n",
       pd.description_i18n,
-      "location",
-      pd.location,
+      "address",
+      pd.address,
       "image",
       pd.image);
     GNUNET_free (pd.description);
diff --git a/src/backend/taler-merchant-httpd_private-get-products.c 
b/src/backend/taler-merchant-httpd_private-get-products.c
index 8f70c9f..21729a5 100644
--- a/src/backend/taler-merchant-httpd_private-get-products.c
+++ b/src/backend/taler-merchant-httpd_private-get-products.c
@@ -26,21 +26,18 @@
  * Add product details to our JSON array.
  *
  * @param cls a `json_t *` JSON array to build
- * @param key unused
  * @param product_id ID of the product
  * @param in_stock how many are currently in stock (possibly locked), -1 for 
infinite
  * @param unit in which unit is the stock measured in
  */
 static void
 add_product (void *cls,
-             const struct GNUNET_HashCode *key,
              const char *product_id,
              long long in_stock,
              const char *unit)
 {
   json_t *pa = cls;
 
-  (void) key;
   GNUNET_assert (0 ==
                  json_array_append_new (
                    pa,
diff --git a/src/backend/taler-merchant-httpd_private-patch-products-ID.c 
b/src/backend/taler-merchant-httpd_private-patch-products-ID.c
index fd5a6c1..6821d3d 100644
--- a/src/backend/taler-merchant-httpd_private-patch-products-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-products-ID.c
@@ -101,7 +101,7 @@ determine_cause (struct MHD_Connection *connection,
     GNUNET_free (pdx.unit);
     json_decref (pdx.taxes);
     json_decref (pdx.image);
-    json_decref (pdx.location);
+    json_decref (pdx.address);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_CONFLICT,
                                        ec,
@@ -141,8 +141,8 @@ TMH_private_patch_products_ID (const struct 
TMH_RequestHandler *rh,
                            &pd.image),
     GNUNET_JSON_spec_json ("taxes",
                            &pd.taxes),
-    GNUNET_JSON_spec_json ("location",
-                           &pd.taxes),
+    GNUNET_JSON_spec_json ("address",
+                           &pd.address),
     GNUNET_JSON_spec_int64 ("total_stocked",
                             &total_stocked),
     GNUNET_JSON_spec_absolute_time ("next_restock",
diff --git a/src/backend/taler-merchant-httpd_private-post-products.c 
b/src/backend/taler-merchant-httpd_private-post-products.c
index 498e51c..c440284 100644
--- a/src/backend/taler-merchant-httpd_private-post-products.c
+++ b/src/backend/taler-merchant-httpd_private-post-products.c
@@ -61,8 +61,8 @@ products_equal (const struct TALER_MERCHANTDB_ProductDetails 
*p1,
            (p1->total_lost == p2->total_lost) &&
            (1 == json_equal (p1->image,
                              p2->image)) &&
-           (1 == json_equal (p1->location,
-                             p2->location)) &&
+           (1 == json_equal (p1->address,
+                             p2->address)) &&
            (p1->next_restock.abs_value_us ==
             p2->next_restock.abs_value_us) );
 }
@@ -101,8 +101,8 @@ TMH_private_post_products (const struct TMH_RequestHandler 
*rh,
                            &pd.image),
     GNUNET_JSON_spec_json ("taxes",
                            &pd.taxes),
-    GNUNET_JSON_spec_json ("location",
-                           &pd.taxes),
+    GNUNET_JSON_spec_json ("address",
+                           &pd.address),
     GNUNET_JSON_spec_int64 ("total_stocked",
                             &total_stocked),
     GNUNET_JSON_spec_absolute_time ("next_restock",
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 70a98d5..08f8093 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -666,8 +666,8 @@ postgres_purge_instance (void *cls,
  * @return database result code
  */
 static enum GNUNET_DB_QueryStatus
-postgres_patch_instance (void *cls,
-                         const struct TALER_MERCHANTDB_InstanceSettings *is)
+postgres_update_instance (void *cls,
+                          const struct TALER_MERCHANTDB_InstanceSettings *is)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -715,6 +715,327 @@ postgres_inactivate_account (void *cls,
 }
 
 
+/**
+ * Context used for postgres_lookup_products().
+ */
+struct LookupProductsContext
+{
+  /**
+   * Function to call with the results.
+   */
+  TALER_MERCHANTDB_ProductsCallback cb;
+
+  /**
+   * Closure for @a cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Internal result.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about products.
+ *
+ * @param[in,out] cls of type `struct LookupProductsContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+lookup_products_cb (void *cls,
+                    PGresult *result,
+                    unsigned int num_results)
+{
+  struct LookupProductsContext *plc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    char *product_id;
+    uint64_t in_stock;
+    char *unit;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("product_id",
+                                    &product_id),
+      GNUNET_PQ_result_spec_uint64 ("in_stock",
+                                    &in_stock),
+      GNUNET_PQ_result_spec_string ("unit",
+                                    &unit),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      plc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    plc->cb (plc->cb_cls,
+             product_id,
+             (UINT64_MAX == in_stock) ? -1LL : (long long) in_stock,
+             unit);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+/**
+ * Lookup all of the products the given instance has configured.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup products for
+ * @param cb function to call on all products found
+ * @param cb_cls closure for @a cb
+ * @return database result code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_products (void *cls,
+                          const char *instance_id,
+                          TALER_MERCHANTDB_ProductsCallback cb,
+                          void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct LookupProductsContext plc = {
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_products",
+                                             params,
+                                             &lookup_products_cb,
+                                             &plc);
+  if (0 != plc.qs)
+    return plc.qs;
+  return qs;
+}
+
+
+/**
+ * Lookup details about a particular product.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup products for
+ * @param product_id product to lookup
+ * @param[out] pd set to the product details on success, can be NULL
+ *             (in that case we only want to check if the product exists)
+ * @return database result code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_product (void *cls,
+                         const char *instance_id,
+                         const char *product_id,
+                         struct TALER_MERCHANTDB_ProductDetails *pd)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (product_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_string ("description",
+                                  &pd->description),
+    TALER_PQ_result_spec_json ("description_i18n",
+                               &pd->description_i18n),
+    GNUNET_PQ_result_spec_string ("unit",
+                                  &pd->unit),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("price",
+                                 &pd->price),
+    TALER_PQ_result_spec_json ("taxes",
+                               &pd->taxes),
+    GNUNET_PQ_result_spec_uint64 ("total_stocked",
+                                  &pd->total_stocked),
+    GNUNET_PQ_result_spec_uint64 ("total_sold",
+                                  &pd->total_sold),
+    GNUNET_PQ_result_spec_uint64 ("total_lost",
+                                  &pd->total_lost),
+    TALER_PQ_result_spec_json ("image",
+                               &pd->image),
+    TALER_PQ_result_spec_json ("address",
+                               &pd->address),
+    GNUNET_PQ_result_spec_absolute_time ("next_restock",
+                                         &pd->next_restock),
+    GNUNET_PQ_result_spec_end
+  };
+  struct GNUNET_PQ_ResultSpec rs_null[] = {
+    GNUNET_PQ_result_spec_end
+  };
+
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_product",
+                                                   params,
+                                                   (NULL == pd)
+                                                   ? rs_null
+                                                   : rs);
+}
+
+
+/**
+ * Delete information about a product.  Note that the transaction must
+ * enforce that no stocks are currently locked.
+ *
+ * @param cls closure
+ * @param instance_id instance to delete product of
+ * @param product_id product to delete
+ * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ *           if locks prevent deletion OR product unknown
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_delete_product (void *cls,
+                         const char *instance_id,
+                         const char *product_id)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (product_id),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "delete_product",
+                                             params);
+}
+
+
+/**
+ * Insert details about a particular product.
+ *
+ * @param cls closure
+ * @param instance_id instance to insert product for
+ * @param product_id product identifier of product to insert
+ * @param pd the product details to insert
+ * @return database result code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_insert_product (void *cls,
+                         const char *instance_id,
+                         const char *product_id,
+                         const struct TALER_MERCHANTDB_ProductDetails *pd)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (product_id),
+    GNUNET_PQ_query_param_string (pd->description),
+    TALER_PQ_query_param_json (pd->description_i18n),
+    GNUNET_PQ_query_param_string (pd->unit),
+    TALER_PQ_query_param_json (pd->image),
+    TALER_PQ_query_param_json (pd->taxes),
+    TALER_PQ_query_param_amount (&pd->price),
+    GNUNET_PQ_query_param_uint64 (&pd->total_stocked),
+    GNUNET_PQ_query_param_uint64 (&pd->total_sold),
+    GNUNET_PQ_query_param_uint64 (&pd->total_lost),
+    TALER_PQ_query_param_json (pd->address),
+    GNUNET_PQ_query_param_absolute_time (&pd->next_restock),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_product",
+                                             params);
+}
+
+
+/**
+ * Update details about a particular product. Note that the
+ * transaction must enforce that the sold/stocked/lost counters
+ * are not reduced (i.e. by expanding the WHERE clause on the existing
+ * values).
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup products for
+ * @param product_id product to lookup
+ * @param[out] pd set to the product details on success, can be NULL
+ *             (in that case we only want to check if the product exists)
+ * @return database result code, #GNUNET_DB_SUCCESS_NO_RESULTS if the
+ *         non-decreasing constraints are not met *or* if the product
+ *         does not yet exist.
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_update_product (void *cls,
+                         const char *instance_id,
+                         const char *product_id,
+                         struct TALER_MERCHANTDB_ProductDetails *pd)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (product_id),
+    GNUNET_PQ_query_param_string (pd->description),
+    TALER_PQ_query_param_json (pd->description_i18n),
+    GNUNET_PQ_query_param_string (pd->unit),
+    TALER_PQ_query_param_json (pd->image),
+    TALER_PQ_query_param_json (pd->taxes),
+    TALER_PQ_query_param_amount (&pd->price),
+    GNUNET_PQ_query_param_uint64 (&pd->total_stocked),
+    GNUNET_PQ_query_param_uint64 (&pd->total_sold),
+    GNUNET_PQ_query_param_uint64 (&pd->total_lost),
+    TALER_PQ_query_param_json (pd->address),
+    GNUNET_PQ_query_param_absolute_time (&pd->next_restock),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "update_product",
+                                             params);
+}
+
+
+/**
+ * Lock stocks of a particular product. Note that the transaction must
+ * enforce that the "stocked-sold-lost >= locked" constraint holds.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup products for
+ * @param product_id product to lookup
+ * @param uuid the UUID that holds the lock
+ * @param quantity how many units should be locked
+ * @param expiration_time when should the lock expire
+ * @return database result code, #GNUNET_DB_SUCCESS_NO_RESULTS if the
+ *         product is unknown OR if there insufficient stocks remaining
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lock_product (void *cls,
+                       const char *instance_id,
+                       const char *product_id,
+                       const struct GNUNET_Uuid *uuid,
+                       uint32_t quantity,
+                       struct GNUNET_TIME_Absolute expiration_time)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (product_id),
+    GNUNET_PQ_query_param_auto_from_type (uuid),
+    GNUNET_PQ_query_param_uint32 (&quantity),
+    GNUNET_PQ_query_param_absolute_time (&expiration_time),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "lock_product",
+                                             params);
+}
+
+
 /* ********************* OLD API ************************** */
 
 /**
@@ -727,12 +1048,11 @@ postgres_inactivate_account (void *cls,
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_find_contract_terms_from_hash (void *cls,
-                                        json_t **contract_terms,
-                                        const struct
-                                        GNUNET_HashCode *h_contract_terms,
-                                        const struct
-                                        TALER_MerchantPublicKeyP *merchant_pub)
+postgres_find_contract_terms_from_hash (
+  void *cls,
+  json_t **contract_terms,
+  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantPublicKeyP *merchant_pub)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -3677,7 +3997,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "DELETE FROM merchant_instances"
                             " WHERE merchant_instances.merchant_id = $1",
                             1),
-    /* for postgres_patch_instance() */
+    /* for postgres_update_instance() */
     GNUNET_PQ_make_prepare ("update_instance",
                             "UPDATE merchant_instances SET"
                             " merchant_name=$2"
@@ -4199,8 +4519,14 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->insert_account = &postgres_insert_account;
   plugin->delete_instance_private_key = &postgres_delete_instance_private_key;
   plugin->purge_instance = &postgres_purge_instance;
-  plugin->patch_instance = &postgres_patch_instance;
+  plugin->update_instance = &postgres_update_instance;
   plugin->inactivate_account = &postgres_inactivate_account;
+  plugin->lookup_products = &postgres_lookup_products;
+  plugin->lookup_product = &postgres_lookup_product;
+  plugin->delete_product = &postgres_delete_product;
+  plugin->insert_product = &postgres_insert_product;
+  plugin->update_product = &postgres_update_product;
+  plugin->lock_product = &postgres_lock_product;
 
   /* old API: */
   plugin->store_deposit = &postgres_store_deposit;
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 353997d..09bb137 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -144,14 +144,12 @@ typedef void
  * Typically called by `lookup_products`.
  *
  * @param cls a `json_t *` JSON array to build
- * @param key unused
  * @param product_id ID of the product
  * @param in_stock how many are currently in stock (possibly locked), -1 for 
infinite
  * @param unit in which unit is the stock measured in
  */
 typedef void
 (*TALER_MERCHANTDB_ProductsCallback)(void *cls,
-                                     const struct GNUNET_HashCode *key,
                                      const char *product_id,
                                      long long in_stock,
                                      const char *unit);
@@ -214,7 +212,7 @@ struct TALER_MERCHANTDB_ProductDetails
   /**
    * Identifies where the product is in stock, possibly an empty map.
    */
-  json_t *location;
+  json_t *address;
 
   /**
    * Identifies when the product will be restocked. 0 for unknown,
@@ -542,7 +540,8 @@ struct TALER_MERCHANTDB_Plugin
                     struct TALER_MERCHANTDB_ProductDetails *pd);
 
   /**
-   * Delete information about a product.
+   * Delete information about a product. Note that the transaction must
+   * enforce that no stocks are currently locked.
    *
    * @param cls closure
    * @param instance_id instance to delete product of

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