summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2023-05-08 22:25:45 -0600
committerIván Ávalos <avalos@disroot.org>2023-05-08 22:25:45 -0600
commit6cf8a87be1ec8cb846a361d35b68c5602e174fa5 (patch)
tree3787242609b7cd2dd1c16feb319210a83625ce50 /src
parent75c1fbfe39a625320bb8a0a219bdb599927cf552 (diff)
downloadmerchant-6cf8a87be1ec8cb846a361d35b68c5602e174fa5.tar.gz
merchant-6cf8a87be1ec8cb846a361d35b68c5602e174fa5.tar.bz2
merchant-6cf8a87be1ec8cb846a361d35b68c5602e174fa5.zip
Factor out {lookup,delete,insert,update,lock}_product(s) (shit job)
Diffstat (limited to 'src')
-rw-r--r--src/backenddb/Makefile.am6
-rw-r--r--src/backenddb/pg_delete_product.c57
-rw-r--r--src/backenddb/pg_delete_product.h43
-rw-r--r--src/backenddb/pg_insert_product.c76
-rw-r--r--src/backenddb/pg_insert_product.h43
-rw-r--r--src/backenddb/pg_lock_product.c76
-rw-r--r--src/backenddb/pg_lock_product.h49
-rw-r--r--src/backenddb/pg_lookup_product.c110
-rw-r--r--src/backenddb/pg_lookup_product.h44
-rw-r--r--src/backenddb/pg_lookup_products.c126
-rw-r--r--src/backenddb/pg_lookup_products.h43
-rw-r--r--src/backenddb/pg_update_product.c85
-rw-r--r--src/backenddb/pg_update_product.h53
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c477
14 files changed, 829 insertions, 459 deletions
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index 6227eba2..91b48223 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -75,6 +75,12 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \
pg_update_instance_auth.h pg_update_instance_auth.c \
pg_inactivate_account.h pg_inactivate_account.c \
pg_activate_account.h pg_activate_account.c \
+ pg_lookup_products.h pg_lookup_products.c \
+ pg_lookup_product.h pg_lookup_product.c \
+ pg_delete_product.h pg_delete_product.c \
+ pg_insert_product.h pg_insert_product.c \
+ pg_update_product.h pg_update_product.c \
+ pg_lock_product.h pg_lock_product.c \
plugin_merchantdb_postgres.c pg_helper.h
libtaler_plugin_merchantdb_postgres_la_LIBADD = \
$(LTLIBINTL)
diff --git a/src/backenddb/pg_delete_product.c b/src/backenddb/pg_delete_product.c
new file mode 100644
index 00000000..2d70c9b8
--- /dev/null
+++ b/src/backenddb/pg_delete_product.c
@@ -0,0 +1,57 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_delete_product.c
+ * @brief Implementation of the delete_product function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_delete_product.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_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);
+ PREPARE (pg,
+ "delete_product",
+ "DELETE"
+ " FROM merchant_inventory"
+ " WHERE merchant_inventory.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_inventory.product_id=$2"
+ " AND product_serial NOT IN "
+ " (SELECT product_serial FROM merchant_order_locks)"
+ " AND product_serial NOT IN "
+ " (SELECT product_serial FROM merchant_inventory_locks)");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "delete_product",
+ params);
+}
diff --git a/src/backenddb/pg_delete_product.h b/src/backenddb/pg_delete_product.h
new file mode 100644
index 00000000..c88e46f4
--- /dev/null
+++ b/src/backenddb/pg_delete_product.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_delete_product.h
+ * @brief implementation of the delete_product function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_DELETE_PRODUCT_H
+#define PG_DELETE_PRODUCT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * 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
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_delete_product (void *cls,
+ const char *instance_id,
+ const char *product_id);
+
+#endif
diff --git a/src/backenddb/pg_insert_product.c b/src/backenddb/pg_insert_product.c
new file mode 100644
index 00000000..8ee2b274
--- /dev/null
+++ b/src/backenddb/pg_insert_product.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_insert_product.c
+ * @brief Implementation of the insert_product function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_insert_product.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_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),
+ GNUNET_PQ_query_param_string (pd->image),
+ TALER_PQ_query_param_json (pd->taxes),
+ TALER_PQ_query_param_amount (&pd->price),
+ GNUNET_PQ_query_param_uint64 (&pd->total_stock),
+ TALER_PQ_query_param_json (pd->address),
+ GNUNET_PQ_query_param_timestamp (&pd->next_restock),
+ GNUNET_PQ_query_param_uint32 (&pd->minimum_age),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "insert_product",
+ "INSERT INTO merchant_inventory"
+ "(merchant_serial"
+ ",product_id"
+ ",description"
+ ",description_i18n"
+ ",unit"
+ ",image"
+ ",taxes"
+ ",price_val"
+ ",price_frac"
+ ",total_stock"
+ ",address"
+ ",next_restock"
+ ",minimum_age"
+ ")"
+ " SELECT merchant_serial,"
+ " $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_product",
+ params);
+}
diff --git a/src/backenddb/pg_insert_product.h b/src/backenddb/pg_insert_product.h
new file mode 100644
index 00000000..169bd150
--- /dev/null
+++ b/src/backenddb/pg_insert_product.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_insert_product.h
+ * @brief implementation of the insert_product function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_INSERT_PRODUCT_H
+#define PG_INSERT_PRODUCT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * 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
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_product (void *cls,
+ const char *instance_id,
+ const char *product_id,
+ const struct TALER_MERCHANTDB_ProductDetails *pd);
+
+#endif
diff --git a/src/backenddb/pg_lock_product.c b/src/backenddb/pg_lock_product.c
new file mode 100644
index 00000000..205f0b67
--- /dev/null
+++ b/src/backenddb/pg_lock_product.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lock_product.c
+ * @brief Implementation of the lock_product function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lock_product.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lock_product (void *cls,
+ const char *instance_id,
+ const char *product_id,
+ const struct GNUNET_Uuid *uuid,
+ uint64_t quantity,
+ struct GNUNET_TIME_Timestamp 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_uint64 (&quantity),
+ GNUNET_PQ_query_param_timestamp (&expiration_time),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "lock_product",
+ "WITH ps AS"
+ " (SELECT product_serial"
+ " FROM merchant_inventory"
+ " WHERE product_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))"
+ "INSERT INTO merchant_inventory_locks"
+ "(product_serial"
+ ",lock_uuid"
+ ",total_locked"
+ ",expiration)"
+ " SELECT product_serial, $3, $4, $5"
+ " FROM merchant_inventory"
+ " JOIN ps USING (product_serial)"
+ " WHERE "
+ " total_stock - total_sold - total_lost - $4 >= "
+ " (SELECT COALESCE(SUM(total_locked), 0)"
+ " FROM merchant_inventory_locks"
+ " WHERE product_serial=ps.product_serial) + "
+ " (SELECT COALESCE(SUM(total_locked), 0)"
+ " FROM merchant_order_locks"
+ " WHERE product_serial=ps.product_serial)");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "lock_product",
+ params);
+}
diff --git a/src/backenddb/pg_lock_product.h b/src/backenddb/pg_lock_product.h
new file mode 100644
index 00000000..d0e13d41
--- /dev/null
+++ b/src/backenddb/pg_lock_product.h
@@ -0,0 +1,49 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lock_product.h
+ * @brief implementation of the lock_product function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOCK_PRODUCT_H
+#define PG_LOCK_PRODUCT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * 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_STATUS_SUCCESS_NO_RESULTS if the
+ * product is unknown OR if there insufficient stocks remaining
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lock_product (void *cls,
+ const char *instance_id,
+ const char *product_id,
+ const struct GNUNET_Uuid *uuid,
+ uint64_t quantity,
+ struct GNUNET_TIME_Timestamp expiration_time);
+
+#endif
diff --git a/src/backenddb/pg_lookup_product.c b/src/backenddb/pg_lookup_product.c
new file mode 100644
index 00000000..d9eb0915
--- /dev/null
+++ b/src/backenddb/pg_lookup_product.c
@@ -0,0 +1,110 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_product.c
+ * @brief Implementation of the lookup_product function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_product.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_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
+ };
+
+ if (NULL == pd)
+ {
+ 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,
+ rs_null);
+ }
+ else
+ {
+ 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_stock",
+ &pd->total_stock),
+ GNUNET_PQ_result_spec_uint64 ("total_sold",
+ &pd->total_sold),
+ GNUNET_PQ_result_spec_uint64 ("total_lost",
+ &pd->total_lost),
+ GNUNET_PQ_result_spec_string ("image",
+ &pd->image),
+ TALER_PQ_result_spec_json ("address",
+ &pd->address),
+ GNUNET_PQ_result_spec_timestamp ("next_restock",
+ &pd->next_restock),
+ GNUNET_PQ_result_spec_uint32 ("minimum_age",
+ &pd->minimum_age),
+ GNUNET_PQ_result_spec_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_product",
+ "SELECT"
+ " description"
+ ",description_i18n"
+ ",unit"
+ ",price_val"
+ ",price_frac"
+ ",taxes"
+ ",total_stock"
+ ",total_sold"
+ ",total_lost"
+ ",image"
+ ",merchant_inventory.address"
+ ",next_restock"
+ ",minimum_age"
+ " FROM merchant_inventory"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_inventory.product_id=$2");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_product",
+ params,
+ rs);
+ }
+}
diff --git a/src/backenddb/pg_lookup_product.h b/src/backenddb/pg_lookup_product.h
new file mode 100644
index 00000000..a6add4cb
--- /dev/null
+++ b/src/backenddb/pg_lookup_product.h
@@ -0,0 +1,44 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_product.h
+ * @brief implementation of the lookup_product function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_PRODUCT_H
+#define PG_LOOKUP_PRODUCT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * 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
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_product (void *cls,
+ const char *instance_id,
+ const char *product_id,
+ struct TALER_MERCHANTDB_ProductDetails *pd);
+
+#endif
diff --git a/src/backenddb/pg_lookup_products.c b/src/backenddb/pg_lookup_products.c
new file mode 100644
index 00000000..c04ad5f2
--- /dev/null
+++ b/src/backenddb/pg_lookup_products.c
@@ -0,0 +1,126 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_products.c
+ * @brief Implementation of the lookup_products function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_products.h"
+#include "pg_helper.h"
+
+/**
+ * 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;
+
+ /**
+ * Did database result extraction fail?
+ */
+ bool extract_failed;
+};
+
+
+/**
+ * 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_results 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;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("product_id",
+ &product_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ plc->extract_failed = true;
+ return;
+ }
+ plc->cb (plc->cb_cls,
+ product_id);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_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,
+ /* Can be overwritten by the lookup_products_cb */
+ .extract_failed = false,
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_products",
+ "SELECT"
+ " product_id"
+ " FROM merchant_inventory"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_products",
+ params,
+ &lookup_products_cb,
+ &plc);
+ /* If there was an error inside lookup_products_cb, return a hard error. */
+ if (plc.extract_failed)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/backenddb/pg_lookup_products.h b/src/backenddb/pg_lookup_products.h
new file mode 100644
index 00000000..398b5eac
--- /dev/null
+++ b/src/backenddb/pg_lookup_products.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_products.h
+ * @brief implementation of the lookup_products function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_PRODUCTS_H
+#define PG_LOOKUP_PRODUCTS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * 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
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_products (void *cls,
+ const char *instance_id,
+ TALER_MERCHANTDB_ProductsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_update_product.c b/src/backenddb/pg_update_product.c
new file mode 100644
index 00000000..b571a8fe
--- /dev/null
+++ b/src/backenddb/pg_update_product.c
@@ -0,0 +1,85 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_update_product.c
+ * @brief Implementation of the update_product function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_update_product.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_update_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), /* $1 */
+ 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),
+ GNUNET_PQ_query_param_string (pd->image), /* $6 */
+ TALER_PQ_query_param_json (pd->taxes),
+ TALER_PQ_query_param_amount (&pd->price), /* $8+$9 */
+ GNUNET_PQ_query_param_uint64 (&pd->total_stock), /* $10 */
+ GNUNET_PQ_query_param_uint64 (&pd->total_lost),
+ TALER_PQ_query_param_json (pd->address),
+ GNUNET_PQ_query_param_timestamp (&pd->next_restock),
+ GNUNET_PQ_query_param_uint32 (&pd->minimum_age),
+ GNUNET_PQ_query_param_end
+ };
+
+ if ( (pd->total_stock < pd->total_lost + pd->total_sold) ||
+ (pd->total_lost < pd->total_lost
+ + pd->total_sold) /* integer overflow */)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ check_connection (pg);
+ PREPARE (pg,
+ "update_product",
+ "UPDATE merchant_inventory SET"
+ " description=$3"
+ ",description_i18n=$4"
+ ",unit=$5"
+ ",image=$6"
+ ",taxes=$7"
+ ",price_val=$8"
+ ",price_frac=$9"
+ ",total_stock=$10"
+ ",total_lost=$11"
+ ",address=$12"
+ ",next_restock=$13"
+ ",minimum_age=$14"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND product_id=$2"
+ " AND total_stock <= $10"
+ " AND total_lost <= $11");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "update_product",
+ params);
+}
diff --git a/src/backenddb/pg_update_product.h b/src/backenddb/pg_update_product.h
new file mode 100644
index 00000000..3ad280ef
--- /dev/null
+++ b/src/backenddb/pg_update_product.h
@@ -0,0 +1,53 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ 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, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_update_product.h
+ * @brief implementation of the update_product function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_UPDATE_PRODUCT_H
+#define PG_UPDATE_PRODUCT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * 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)
+ * total_sold in @a pd is ignored, total_lost must not
+ * exceed total_stock minus the existing total_sold;
+ * total_sold and total_stock must be larger or equal to
+ * the existing value;
+ * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the
+ * non-decreasing constraints are not met *or* if the product
+ * does not yet exist.
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_update_product (void *cls,
+ const char *instance_id,
+ const char *product_id,
+ const struct TALER_MERCHANTDB_ProductDetails *pd);
+
+#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 0e0e7abb..0e5f921f 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -53,6 +53,12 @@
#include "pg_update_instance_auth.h"
#include "pg_inactivate_account.h"
#include "pg_activate_account.h"
+#include "pg_lookup_products.h"
+#include "pg_lookup_product.h"
+#include "pg_delete_product.h"
+#include "pg_insert_product.h"
+#include "pg_update_product.h"
+#include "pg_lock_product.h"
#include "pg_set_transfer_status_to_confirmed.h"
@@ -331,346 +337,6 @@ postgres_commit (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;
-
- /**
- * Did database result extraction fail?
- */
- bool extract_failed;
-};
-
-
-/**
- * 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_results 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;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("product_id",
- &product_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- plc->extract_failed = true;
- return;
- }
- plc->cb (plc->cb_cls,
- product_id);
- 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,
- /* Can be overwritten by the lookup_products_cb */
- .extract_failed = false,
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_products",
- params,
- &lookup_products_cb,
- &plc);
- /* If there was an error inside lookup_products_cb, return a hard error. */
- if (plc.extract_failed)
- return GNUNET_DB_STATUS_HARD_ERROR;
- 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
- };
-
- if (NULL == pd)
- {
- 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,
- rs_null);
- }
- else
- {
- 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_stock",
- &pd->total_stock),
- GNUNET_PQ_result_spec_uint64 ("total_sold",
- &pd->total_sold),
- GNUNET_PQ_result_spec_uint64 ("total_lost",
- &pd->total_lost),
- GNUNET_PQ_result_spec_string ("image",
- &pd->image),
- TALER_PQ_result_spec_json ("address",
- &pd->address),
- GNUNET_PQ_result_spec_timestamp ("next_restock",
- &pd->next_restock),
- GNUNET_PQ_result_spec_uint32 ("minimum_age",
- &pd->minimum_age),
- GNUNET_PQ_result_spec_end
- };
-
- check_connection (pg);
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_product",
- params,
- 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),
- GNUNET_PQ_query_param_string (pd->image),
- TALER_PQ_query_param_json (pd->taxes),
- TALER_PQ_query_param_amount (&pd->price),
- GNUNET_PQ_query_param_uint64 (&pd->total_stock),
- TALER_PQ_query_param_json (pd->address),
- GNUNET_PQ_query_param_timestamp (&pd->next_restock),
- GNUNET_PQ_query_param_uint32 (&pd->minimum_age),
- 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)
- * total_sold in @a pd is ignored, total_lost must not
- * exceed total_stock minus the existing total_sold;
- * total_sold and total_stock must be larger or equal to
- * the existing value;
- * @return database result code, #GNUNET_DB_STATUS_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,
- const struct TALER_MERCHANTDB_ProductDetails *pd)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id), /* $1 */
- 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),
- GNUNET_PQ_query_param_string (pd->image), /* $6 */
- TALER_PQ_query_param_json (pd->taxes),
- TALER_PQ_query_param_amount (&pd->price), /* $8+$9 */
- GNUNET_PQ_query_param_uint64 (&pd->total_stock), /* $10 */
- GNUNET_PQ_query_param_uint64 (&pd->total_lost),
- TALER_PQ_query_param_json (pd->address),
- GNUNET_PQ_query_param_timestamp (&pd->next_restock),
- GNUNET_PQ_query_param_uint32 (&pd->minimum_age),
- GNUNET_PQ_query_param_end
- };
-
- if ( (pd->total_stock < pd->total_lost + pd->total_sold) ||
- (pd->total_lost < pd->total_lost
- + pd->total_sold) /* integer overflow */)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- 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_STATUS_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,
- uint64_t quantity,
- struct GNUNET_TIME_Timestamp 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_uint64 (&quantity),
- GNUNET_PQ_query_param_timestamp (&expiration_time),
- GNUNET_PQ_query_param_end
- };
-
- check_connection (pg);
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "lock_product",
- params);
-}
-
-
-/**
* Release all expired product locks, including
* those from expired offers -- across all
* instances.
@@ -6540,119 +6206,6 @@ postgres_connect (void *cls)
struct GNUNET_PQ_PreparedStatement ps[] = {
GNUNET_PQ_make_prepare ("end_transaction",
"COMMIT"),
- /* for postgres_lookup_products() */
- GNUNET_PQ_make_prepare ("lookup_products",
- "SELECT"
- " product_id"
- " FROM merchant_inventory"
- " JOIN merchant_instances"
- " USING (merchant_serial)"
- " WHERE merchant_instances.merchant_id=$1"),
- /* for postgres_lookup_product() */
- GNUNET_PQ_make_prepare ("lookup_product",
- "SELECT"
- " description"
- ",description_i18n"
- ",unit"
- ",price_val"
- ",price_frac"
- ",taxes"
- ",total_stock"
- ",total_sold"
- ",total_lost"
- ",image"
- ",merchant_inventory.address"
- ",next_restock"
- ",minimum_age"
- " FROM merchant_inventory"
- " JOIN merchant_instances"
- " USING (merchant_serial)"
- " WHERE merchant_instances.merchant_id=$1"
- " AND merchant_inventory.product_id=$2"),
- /* for postgres_delete_product() */
- GNUNET_PQ_make_prepare ("delete_product",
- "DELETE"
- " FROM merchant_inventory"
- " WHERE merchant_inventory.merchant_serial="
- " (SELECT merchant_serial "
- " FROM merchant_instances"
- " WHERE merchant_id=$1)"
- " AND merchant_inventory.product_id=$2"
- " AND product_serial NOT IN "
- " (SELECT product_serial FROM merchant_order_locks)"
- " AND product_serial NOT IN "
- " (SELECT product_serial FROM merchant_inventory_locks)"),
- /* for postgres_insert_product() */
- GNUNET_PQ_make_prepare ("insert_product",
- "INSERT INTO merchant_inventory"
- "(merchant_serial"
- ",product_id"
- ",description"
- ",description_i18n"
- ",unit"
- ",image"
- ",taxes"
- ",price_val"
- ",price_frac"
- ",total_stock"
- ",address"
- ",next_restock"
- ",minimum_age"
- ")"
- " SELECT merchant_serial,"
- " $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13"
- " FROM merchant_instances"
- " WHERE merchant_id=$1"),
- /* for postgres_update_product() */
- GNUNET_PQ_make_prepare ("update_product",
- "UPDATE merchant_inventory SET"
- " description=$3"
- ",description_i18n=$4"
- ",unit=$5"
- ",image=$6"
- ",taxes=$7"
- ",price_val=$8"
- ",price_frac=$9"
- ",total_stock=$10"
- ",total_lost=$11"
- ",address=$12"
- ",next_restock=$13"
- ",minimum_age=$14"
- " WHERE merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1)"
- " AND product_id=$2"
- " AND total_stock <= $10"
- " AND total_lost <= $11"),
-
- /* for postgres_lock_product() */
- GNUNET_PQ_make_prepare ("lock_product",
- "WITH ps AS"
- " (SELECT product_serial"
- " FROM merchant_inventory"
- " WHERE product_id=$2"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1))"
- "INSERT INTO merchant_inventory_locks"
- "(product_serial"
- ",lock_uuid"
- ",total_locked"
- ",expiration)"
- " SELECT product_serial, $3, $4, $5"
- " FROM merchant_inventory"
- " JOIN ps USING (product_serial)"
- " WHERE "
- " total_stock - total_sold - total_lost - $4 >= "
- " (SELECT COALESCE(SUM(total_locked), 0)"
- " FROM merchant_inventory_locks"
- " WHERE product_serial=ps.product_serial) + "
- " (SELECT COALESCE(SUM(total_locked), 0)"
- " FROM merchant_order_locks"
- " WHERE product_serial=ps.product_serial)"),
-
/* for postgres_expire_locks() */
GNUNET_PQ_make_prepare ("unlock_products",
"DELETE FROM merchant_inventory_locks"
@@ -8861,12 +8414,18 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
= &TMH_PG_inactivate_account;
plugin->update_transfer_status
= &TMH_PG_update_transfer_status;
- 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;
+ plugin->lookup_products
+ = &TMH_PG_lookup_products;
+ plugin->lookup_product
+ = &TMH_PG_lookup_product;
+ plugin->delete_product
+ = &TMH_PG_delete_product;
+ plugin->insert_product
+ = &TMH_PG_insert_product;
+ plugin->update_product
+ = &TMH_PG_update_product;
+ plugin->lock_product
+ = &TMH_PG_lock_product;
plugin->expire_locks = &postgres_expire_locks;
plugin->delete_order = &postgres_delete_order;
plugin->lookup_order = &postgres_lookup_order;