commit 91a71aa9e789c7b23226f2178caa86ed6b06db42
parent e484532d9604491ddd5e8b37fb8cd1d7d6202945
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 9 May 2026 14:26:38 +0200
Revert "split DB by instance into schema"
This reverts commit e484532d9604491ddd5e8b37fb8cd1d7d6202945.
Diffstat:
193 files changed, 3639 insertions(+), 9494 deletions(-)
diff --git a/src/backenddb/account_kyc_get_outdated.c b/src/backenddb/account_kyc_get_outdated.c
@@ -76,11 +76,11 @@ kyc_status_cb (void *cls,
char *exchange_url;
char *instance_id;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("out_h_wire",
+ GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&h_wire),
- GNUNET_PQ_result_spec_string ("out_exchange_url",
+ GNUNET_PQ_result_spec_string ("exchange_url",
&exchange_url),
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("instance_id",
&instance_id),
GNUNET_PQ_result_spec_end
};
@@ -123,11 +123,17 @@ TALER_MERCHANTDB_account_kyc_get_outdated (struct TALER_MERCHANTDB_PostgresConte
check_connection (pg);
PREPARE (pg,
"account_kyc_get_outdated",
- "SELECT"
- " out_merchant_id"
- " ,out_h_wire"
- " ,out_exchange_url"
- " FROM merchant.account_kyc_get_outdated($1)");
+ "SELECT "
+ " mi.merchant_id"
+ " ,ma.h_wire"
+ " ,kyc.exchange_url"
+ " FROM merchant_kyc kyc"
+ " JOIN merchant_accounts ma"
+ " USING (account_serial)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE kyc.next_kyc_poll < $1"
+ " ORDER BY kyc.next_kyc_poll ASC;");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
"account_kyc_get_outdated",
diff --git a/src/backenddb/account_kyc_get_status.c b/src/backenddb/account_kyc_get_status.c
@@ -172,6 +172,7 @@ TALER_MERCHANTDB_account_kyc_get_status (
struct GNUNET_TIME_Absolute now
= GNUNET_TIME_absolute_get ();
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_absolute_time (&now),
NULL == exchange_url
? GNUNET_PQ_query_param_null ()
@@ -182,30 +183,25 @@ TALER_MERCHANTDB_account_kyc_get_status (
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (merchant_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "account_kyc_get_status",
- "SELECT "
- " out_h_wire AS h_wire"
- " ,out_payto_uri AS payto_uri"
- " ,out_exchange_url AS exchange_url"
- " ,out_kyc_timestamp AS kyc_timestamp"
- " ,out_kyc_ok AS kyc_ok"
- " ,out_access_token AS access_token"
- " ,out_exchange_http_status AS exchange_http_status"
- " ,out_exchange_ec_code AS exchange_ec_code"
- " ,out_aml_review AS aml_review"
- " ,out_jaccount_limits::TEXT AS jaccount_limits"
- " FROM merchant_do_account_kyc_get_status($1, $2, $3);");
+ PREPARE (pg,
+ "account_kyc_get_status",
+ "SELECT "
+ " out_h_wire AS h_wire"
+ " ,out_payto_uri AS payto_uri"
+ " ,out_exchange_url AS exchange_url"
+ " ,out_kyc_timestamp AS kyc_timestamp"
+ " ,out_kyc_ok AS kyc_ok"
+ " ,out_access_token AS access_token"
+ " ,out_exchange_http_status AS exchange_http_status"
+ " ,out_exchange_ec_code AS exchange_ec_code"
+ " ,out_aml_review AS aml_review"
+ " ,out_jaccount_limits::TEXT AS jaccount_limits"
+ " FROM merchant_do_account_kyc_get_status($1, $2, $3, $4);");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "account_kyc_get_status",
params,
&kyc_status_cb,
&ksc);
diff --git a/src/backenddb/account_kyc_set_failed.c b/src/backenddb/account_kyc_set_failed.c
@@ -50,6 +50,7 @@ TALER_MERCHANTDB_account_kyc_set_failed (struct TALER_MERCHANTDB_PostgresContext
= GNUNET_PQ_get_event_notify_channel (&hdr);
uint32_t http_status32 = (uint32_t) exchange_http_status;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_timestamp (×tamp),
@@ -59,29 +60,28 @@ TALER_MERCHANTDB_account_kyc_set_failed (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_string (notify2_s),
GNUNET_PQ_query_param_end
};
+ bool no_instance;
bool no_account;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ &no_instance),
GNUNET_PQ_result_spec_bool ("no_account",
&no_account),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (merchant_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "account_kyc_set_failed",
- "SELECT "
- " out_no_account AS no_account"
- " FROM merchant_do_account_kyc_set_failed"
- "($1, $2, $3, $4, $5, $6, $7);");
+ PREPARE (pg,
+ "account_kyc_set_failed",
+ "SELECT "
+ " out_no_instance AS no_instance"
+ " ,out_no_account AS no_account"
+ " FROM merchant_do_account_kyc_set_failed"
+ "($1, $2, $3, $4, $5, $6, $7, $8);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "account_kyc_set_failed",
params,
rs);
GNUNET_free (notify_s);
@@ -93,6 +93,7 @@ TALER_MERCHANTDB_account_kyc_set_failed (struct TALER_MERCHANTDB_PostgresContext
GNUNET_break (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs);
return qs;
}
+ GNUNET_break (! no_instance);
GNUNET_break (! no_account);
return qs;
}
diff --git a/src/backenddb/account_kyc_set_status.c b/src/backenddb/account_kyc_set_status.c
@@ -59,6 +59,7 @@ TALER_MERCHANTDB_account_kyc_set_status (struct TALER_MERCHANTDB_PostgresContext
uint32_t http_status32 = (uint32_t) exchange_http_status;
uint32_t ec_code32 = (uint32_t) exchange_ec_code;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_timestamp (×tamp),
@@ -79,30 +80,29 @@ TALER_MERCHANTDB_account_kyc_set_status (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_relative_time (&kyc_backoff),
GNUNET_PQ_query_param_end
};
+ bool no_instance;
bool no_account;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ &no_instance),
GNUNET_PQ_result_spec_bool ("no_account",
&no_account),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (merchant_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "account_kyc_set_status",
- "SELECT "
- " out_no_account AS no_account"
- " FROM merchant_do_account_kyc_set_status"
- "($1, $2, $3, $4, $5, $6, $7::TEXT::JSONB"
- ",$8, $9, $10, $11, $12, $13, $14);");
+ PREPARE (pg,
+ "account_kyc_set_status",
+ "SELECT "
+ " out_no_instance AS no_instance"
+ " ,out_no_account AS no_account"
+ " FROM merchant_do_account_kyc_set_status"
+ "($1, $2, $3, $4, $5, $6, $7, $8::TEXT::JSONB"
+ ",$9, $10, $11, $12, $13, $14, $15);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "account_kyc_set_status",
params,
rs);
GNUNET_free (notify_s);
@@ -114,6 +114,7 @@ TALER_MERCHANTDB_account_kyc_set_status (struct TALER_MERCHANTDB_PostgresContext
GNUNET_break (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs);
return qs;
}
+ GNUNET_break (! no_instance);
GNUNET_break (! no_account);
return qs;
}
diff --git a/src/backenddb/activate_account.c b/src/backenddb/activate_account.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_activate_account (struct TALER_MERCHANTDB_PostgresContext *pg,
bool *conflict)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (account_details->instance_id),
GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire),
GNUNET_PQ_query_param_auto_from_type (&account_details->salt),
GNUNET_PQ_query_param_string (account_details->payto_uri.full_payto),
@@ -61,25 +62,20 @@ TALER_MERCHANTDB_activate_account (struct TALER_MERCHANTDB_PostgresContext *pg,
salt),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
GNUNET_assert (account_details->active);
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (account_details->instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "activate_account",
- "SELECT "
- " out_h_wire AS h_wire"
- " ,out_salt AS salt"
- " ,out_conflict AS conflict"
- " ,out_not_found AS not_found"
- " FROM merchant_do_activate_account"
- " ($1,$2,$3,$4,$5,$6);");
+ PREPARE (pg,
+ "activate_account",
+ "SELECT "
+ " out_h_wire AS h_wire"
+ " ,out_salt AS salt"
+ " ,out_conflict AS conflict"
+ " ,out_not_found AS not_found"
+ " FROM merchant_do_activate_account"
+ " ($1,$2,$3,$4,$5,$6,$7);");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "activate_account",
params,
rs);
}
diff --git a/src/backenddb/check_donau_instance.c b/src/backenddb/check_donau_instance.c
@@ -36,25 +36,26 @@ TALER_MERCHANTDB_check_donau_instance (struct TALER_MERCHANTDB_PostgresContext *
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (donau_url),
GNUNET_PQ_query_param_uint64 (&charity_id),
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- (void) merchant_pub;
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "check_donau_instance",
- "SELECT 1"
- " FROM merchant_donau_instances"
- " WHERE donau_url=$1"
- " AND charity_id=$2");
+ PREPARE (pg,
+ "check_donau_instance",
+ "SELECT 1"
+ " FROM merchant_donau_instances"
+ " WHERE donau_url=$1"
+ " AND charity_id=$2 "
+ " AND merchant_instance_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances mi"
+ " WHERE mi.merchant_pub = $3)");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "check_donau_instance",
params,
rs);
diff --git a/src/backenddb/check_money_pots.c b/src/backenddb/check_money_pots.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_check_money_pots (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t *pot_missing)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_array_uint64 (pots_len,
pots,
pg->conn),
@@ -45,26 +46,24 @@ TALER_MERCHANTDB_check_money_pots (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "check_money_pots",
- "SELECT n AS out_missing"
- " FROM UNNEST($1::INT8[]) AS n"
- " WHERE NOT EXISTS ("
- " SELECT 1"
- " FROM merchant_money_pots mmp"
- " WHERE mmp.money_pot_serial=n"
- " )"
- " LIMIT 1;");
+ PREPARE (pg,
+ "check_money_pots",
+ "SELECT n AS out_missing"
+ " FROM UNNEST($2::INT8[]) AS n"
+ " WHERE NOT EXISTS ("
+ " SELECT 1"
+ " FROM merchant_money_pots mmp"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mmp.money_pot_serial=n"
+ " AND mi.merchant_id=$1"
+ " )"
+ " LIMIT 1;");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "check_money_pots",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/check_report.c b/src/backenddb/check_report.c
@@ -40,9 +40,9 @@ TALER_MERCHANTDB_check_report (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("merchant_id",
instance_id),
- GNUNET_PQ_result_spec_string ("out_data_source",
+ GNUNET_PQ_result_spec_string ("data_source",
data_source),
GNUNET_PQ_result_spec_end
};
@@ -51,9 +51,14 @@ TALER_MERCHANTDB_check_report (struct TALER_MERCHANTDB_PostgresContext *pg,
PREPARE (pg,
"check_report",
"SELECT"
- " out_merchant_id"
- " ,out_data_source"
- " FROM merchant.check_report($1, $2, $3)");
+ " mi.merchant_id"
+ " ,mr.data_source"
+ " FROM merchant_reports mr"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mr.report_serial=$1"
+ " AND mr.report_token=$2"
+ " AND mr.mime_type=$3;");
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
"check_report",
diff --git a/src/backenddb/check_transfer_exists.c b/src/backenddb/check_transfer_exists.c
@@ -31,28 +31,32 @@ TALER_MERCHANTDB_check_transfer_exists (struct TALER_MERCHANTDB_PostgresContext
uint64_t transfer_serial_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&transfer_serial_id),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "check_transfer_exists",
- "SELECT"
- " 1"
- " FROM merchant_transfers"
- " WHERE credit_serial=$1");
+ PREPARE (pg,
+ "check_transfer_exists",
+ "SELECT"
+ " 1"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts"
+ " USING (account_serial)"
+ " WHERE"
+ " credit_serial=$2"
+ " AND"
+ " merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "check_transfer_exists",
params,
rs);
}
diff --git a/src/backenddb/create_mfa_challenge.c b/src/backenddb/create_mfa_challenge.c
@@ -55,6 +55,7 @@ TALER_MERCHANTDB_create_mfa_challenge (
GNUNET_PQ_query_param_absolute_time (&retransmission_date),
GNUNET_PQ_query_param_string (channel_str),
GNUNET_PQ_query_param_string (required_address), /* $9 */
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@@ -62,30 +63,28 @@ TALER_MERCHANTDB_create_mfa_challenge (
challenge_id),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- PREPARE_INSTANCE (pg,
- stmt,
- "create_mfa_challenge",
- "INSERT INTO tan_challenges"
- " (h_body"
- " ,salt"
- " ,op"
- " ,code"
- " ,creation_date"
- " ,expiration_date"
- " ,retransmission_date"
- " ,retry_counter" /* always set to 3 */
- " ,tan_channel"
- " ,required_address)"
- " VALUES"
- " ($1, $2, $3, $4, $5, $6, $7, 3, $8, $9)"
- " RETURNING challenge_id;");
+ PREPARE (pg,
+ "create_mfa_challenge",
+ "INSERT INTO tan_challenges"
+ " (h_body"
+ " ,salt"
+ " ,op"
+ " ,code"
+ " ,creation_date"
+ " ,expiration_date"
+ " ,retransmission_date"
+ " ,retry_counter" /* always set to 3 */
+ " ,tan_channel"
+ " ,required_address"
+ " ,merchant_serial)"
+ " SELECT"
+ " $1, $2, $3, $4, $5, $6, $7, 3, $8, $9, merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$10"
+ " RETURNING challenge_id;");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "create_mfa_challenge",
params,
rs);
}
diff --git a/src/backenddb/delete_category.c b/src/backenddb/delete_category.c
@@ -32,22 +32,22 @@ TALER_MERCHANTDB_delete_category (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t category_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&category_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_category",
- "DELETE"
- " FROM merchant_categories"
- " WHERE category_serial=$1");
+ PREPARE (pg,
+ "delete_category",
+ "DELETE"
+ " FROM merchant_categories"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND category_serial=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_category",
params);
}
diff --git a/src/backenddb/delete_contract_terms.c b/src/backenddb/delete_contract_terms.c
@@ -33,26 +33,26 @@ TALER_MERCHANTDB_delete_contract_terms (struct TALER_MERCHANTDB_PostgresContext
{
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_relative_time (&legal_expiration),
GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_contract_terms",
- "DELETE FROM merchant_contract_terms"
- " WHERE order_id=$1"
- " AND ( ( (pay_deadline < $3) AND"
- " (NOT paid) ) OR"
- " (creation_time + $2 < $3) )");
+ PREPARE (pg,
+ "delete_contract_terms",
+ "DELETE FROM merchant_contract_terms"
+ " WHERE order_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND ( ( (pay_deadline < $4) AND"
+ " (NOT paid) ) OR"
+ " (creation_time + $3 < $4) )");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_contract_terms",
params);
}
diff --git a/src/backenddb/delete_donau_instance.c b/src/backenddb/delete_donau_instance.c
@@ -33,20 +33,19 @@ TALER_MERCHANTDB_delete_donau_instance (struct TALER_MERCHANTDB_PostgresContext
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&donau_serial_id),
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_donau_instance",
- "DELETE FROM merchant_donau_instances"
- " WHERE donau_instances_serial = $1;");
+ PREPARE (pg,
+ "delete_donau_instance",
+ "DELETE FROM merchant_donau_instances di"
+ " USING merchant_instances mi"
+ " WHERE di.merchant_instance_serial = mi.merchant_serial"
+ " AND di.donau_instances_serial = $1"
+ " AND mi.merchant_id = $2;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_donau_instance",
params);
}
\ No newline at end of file
diff --git a/src/backenddb/delete_instance_private_key.c b/src/backenddb/delete_instance_private_key.c
@@ -30,19 +30,19 @@ TALER_MERCHANTDB_delete_instance_private_key (struct TALER_MERCHANTDB_PostgresCo
const char *merchant_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (merchant_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_key",
- "DELETE FROM merchant_keys");
+ PREPARE (pg,
+ "delete_key",
+ "DELETE FROM merchant_keys"
+ " USING merchant_instances"
+ " WHERE merchant_keys.merchant_serial"
+ " = merchant_instances.merchant_serial"
+ " AND merchant_instances.merchant_id = $1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_key",
params);
}
diff --git a/src/backenddb/delete_login_token.c b/src/backenddb/delete_login_token.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2026 Taler Systems SA
+ Copyright (C) 2023 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
@@ -31,22 +31,22 @@ TALER_MERCHANTDB_delete_login_token_serial (struct TALER_MERCHANTDB_PostgresCont
uint64_t serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_uint64 (&serial),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_login_token_serial",
- "DELETE FROM merchant_login_tokens"
- " WHERE serial=$1");
+ PREPARE (pg,
+ "delete_login_token_serial",
+ "DELETE FROM merchant_login_tokens"
+ " WHERE serial=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_login_token_serial",
params);
}
@@ -57,21 +57,21 @@ TALER_MERCHANTDB_delete_login_token (struct TALER_MERCHANTDB_PostgresContext *pg
const struct TALER_MERCHANTDB_LoginTokenP *token)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_auto_from_type (token),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_login_token",
- "DELETE FROM merchant_login_tokens"
- " WHERE token=$1");
+ PREPARE (pg,
+ "delete_login_token",
+ "DELETE FROM merchant_login_tokens"
+ " WHERE token=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_login_token",
params);
}
diff --git a/src/backenddb/delete_money_pot.c b/src/backenddb/delete_money_pot.c
@@ -32,22 +32,22 @@ TALER_MERCHANTDB_delete_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t money_pot_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&money_pot_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_money_pot",
- "DELETE"
- " FROM merchant_money_pots"
- " WHERE money_pot_serial=$1");
+ PREPARE (pg,
+ "delete_money_pot",
+ "DELETE"
+ " FROM merchant_money_pots"
+ " WHERE merchant_money_pots.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_money_pots.money_pot_serial=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_money_pot",
params);
}
diff --git a/src/backenddb/delete_order.c b/src/backenddb/delete_order.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2022, 2026 Taler Systems SA
+ 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
@@ -33,51 +33,56 @@ TALER_MERCHANTDB_delete_order (struct TALER_MERCHANTDB_PostgresContext *pg,
{
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_bool (force),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam params2[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
enum GNUNET_DB_QueryStatus qs2;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- char stmt2[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_order",
- "WITH mc AS"
- "(SELECT paid"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1) "
- "DELETE"
- " FROM merchant_orders mo"
- " WHERE order_id=$1"
- " AND ( (pay_deadline < $2)"
- " OR (NOT EXISTS (SELECT paid FROM mc))"
- " OR ($3 AND (FALSE=(SELECT paid FROM mc))) );");
+ PREPARE (pg,
+ "delete_order",
+ "WITH ms AS"
+ "(SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ ", mc AS"
+ "(SELECT paid"
+ " FROM merchant_contract_terms"
+ " JOIN ms USING (merchant_serial)"
+ " WHERE order_id=$2) "
+ "DELETE"
+ " FROM merchant_orders mo"
+ " WHERE order_id=$2"
+ " AND merchant_serial=(SELECT merchant_serial FROM ms)"
+ " AND ( (pay_deadline < $3)"
+ " OR (NOT EXISTS (SELECT paid FROM mc))"
+ " OR ($4 AND (FALSE=(SELECT paid FROM mc))) );");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_order",
params);
if ( (qs < 0) || (! force) )
return qs;
- PREPARE_INSTANCE (pg,
- stmt2,
- "delete_contract",
- "DELETE"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1"
- " AND NOT paid;");
+ PREPARE (pg,
+ "delete_contract",
+ "DELETE"
+ " FROM merchant_contract_terms"
+ " WHERE order_id=$2 AND"
+ " merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND NOT paid;");
qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt2,
+ "delete_contract",
params2);
if (qs2 < 0)
return qs2;
diff --git a/src/backenddb/delete_otp.c b/src/backenddb/delete_otp.c
@@ -32,22 +32,22 @@ TALER_MERCHANTDB_delete_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
const char *otp_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (otp_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_otp",
- "DELETE"
- " FROM merchant_otp_devices"
- " WHERE otp_id=$1");
+ PREPARE (pg,
+ "delete_otp",
+ "DELETE"
+ " FROM merchant_otp_devices"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND otp_id=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_otp",
params);
}
diff --git a/src/backenddb/delete_pending_webhook.c b/src/backenddb/delete_pending_webhook.c
@@ -34,18 +34,14 @@ TALER_MERCHANTDB_delete_pending_webhook (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_pending_webhook",
- "DELETE"
- " FROM merchant_pending_webhooks"
- " WHERE webhook_pending_serial=$1");
+ PREPARE (pg,
+ "delete_pending_webhook",
+ "DELETE"
+ " FROM merchant_pending_webhooks"
+ " WHERE webhook_pending_serial=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_pending_webhook",
params);
}
diff --git a/src/backenddb/delete_product.c b/src/backenddb/delete_product.c
@@ -31,26 +31,26 @@ TALER_MERCHANTDB_delete_product (struct TALER_MERCHANTDB_PostgresContext *pg,
const char *product_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (product_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_product",
- "DELETE"
- " FROM merchant_inventory"
- " WHERE product_id=$1"
- " AND product_serial NOT IN "
- " (SELECT product_serial FROM merchant_order_locks)"
- " AND product_serial NOT IN "
- " (SELECT product_serial FROM merchant_inventory_locks)");
+ 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,
- stmt,
+ "delete_product",
params);
}
diff --git a/src/backenddb/delete_product_group.c b/src/backenddb/delete_product_group.c
@@ -31,22 +31,22 @@ TALER_MERCHANTDB_delete_product_group (struct TALER_MERCHANTDB_PostgresContext *
uint64_t product_group_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&product_group_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_product_group",
- "DELETE"
- " FROM merchant_product_groups"
- " WHERE product_group_serial=$1");
+ PREPARE (pg,
+ "delete_product_group",
+ "DELETE"
+ " FROM merchant_product_groups"
+ " WHERE merchant_product_groups.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_product_groups.product_group_serial=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_product_group",
params);
}
diff --git a/src/backenddb/delete_report.c b/src/backenddb/delete_report.c
@@ -32,22 +32,22 @@ TALER_MERCHANTDB_delete_report (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t report_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&report_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_report",
- "DELETE"
- " FROM merchant_reports"
- " WHERE report_serial=$1");
+ PREPARE (pg,
+ "delete_report",
+ "DELETE"
+ " FROM merchant_reports"
+ " WHERE merchant_reports.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_reports.report_serial=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_report",
params);
}
diff --git a/src/backenddb/delete_template.c b/src/backenddb/delete_template.c
@@ -32,22 +32,22 @@ TALER_MERCHANTDB_delete_template (struct TALER_MERCHANTDB_PostgresContext *pg,
const char *template_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (template_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_template",
- "DELETE"
- " FROM merchant_template"
- " WHERE template_id=$1");
+ PREPARE (pg,
+ "delete_template",
+ "DELETE"
+ " FROM merchant_template"
+ " WHERE merchant_template.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_template.template_id=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_template",
params);
}
diff --git a/src/backenddb/delete_token_family.c b/src/backenddb/delete_token_family.c
@@ -31,22 +31,22 @@ TALER_MERCHANTDB_delete_token_family (struct TALER_MERCHANTDB_PostgresContext *p
const char *token_family_slug)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (token_family_slug),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_token_family",
- "DELETE"
- " FROM merchant_token_families"
- " WHERE slug=$1");
+ PREPARE (pg,
+ "delete_token_family",
+ "DELETE"
+ " FROM merchant_token_families"
+ " WHERE merchant_token_families.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND slug=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_token_family",
params);
}
\ No newline at end of file
diff --git a/src/backenddb/delete_transfer.c b/src/backenddb/delete_transfer.c
@@ -32,22 +32,26 @@ TALER_MERCHANTDB_delete_transfer (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t transfer_serial_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&transfer_serial_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_transfer",
- "DELETE FROM merchant_transfers"
- " WHERE credit_serial=$1");
+ PREPARE (pg,
+ "delete_transfer",
+ "DELETE FROM merchant_transfers"
+ " WHERE"
+ " credit_serial=$2"
+ " AND account_serial IN "
+ " (SELECT account_serial "
+ " FROM merchant_accounts"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_transfer",
params);
}
diff --git a/src/backenddb/delete_unit.c b/src/backenddb/delete_unit.c
@@ -35,10 +35,13 @@ TALER_MERCHANTDB_delete_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
bool *builtin_conflict)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (unit_id),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_no_instance",
+ no_instance),
GNUNET_PQ_result_spec_bool ("out_no_unit",
no_unit),
GNUNET_PQ_result_spec_bool ("out_builtin_conflict",
@@ -46,22 +49,17 @@ TALER_MERCHANTDB_delete_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- *no_instance = false;
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_unit",
- "SELECT"
- " out_no_unit"
- " ,out_builtin_conflict"
- " FROM merchant_do_delete_unit($1);");
+ PREPARE (pg,
+ "delete_unit",
+ "SELECT"
+ " out_no_instance"
+ " ,out_no_unit"
+ " ,out_builtin_conflict"
+ " FROM merchant_do_delete_unit($1,$2);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "delete_unit",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/delete_webhook.c b/src/backenddb/delete_webhook.c
@@ -31,23 +31,23 @@ TALER_MERCHANTDB_delete_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
const char *webhook_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (webhook_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "delete_webhook",
- "DELETE"
- " FROM merchant_webhook"
- " WHERE webhook_id=$1");
+ PREPARE (pg,
+ "delete_webhook",
+ "DELETE"
+ " FROM merchant_webhook"
+ " WHERE merchant_webhook.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_webhook.webhook_id=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "delete_webhook",
params);
}
diff --git a/src/backenddb/expire_locks.c b/src/backenddb/expire_locks.c
@@ -34,29 +34,52 @@ TALER_MERCHANTDB_expire_locks (struct TALER_MERCHANTDB_PostgresContext *pg)
GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_end
};
- uint64_t total;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("expire_locks",
- &total),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
+ enum GNUNET_DB_QueryStatus qs1;
+ enum GNUNET_DB_QueryStatus qs2;
+ enum GNUNET_DB_QueryStatus qs3;
check_connection (pg);
PREPARE (pg,
- "expire_locks",
- "SELECT merchant.expire_locks($1) AS expire_locks");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "expire_locks",
- params,
- rs);
- if (qs < 0)
+ "unlock_products",
+ "DELETE FROM merchant_inventory_locks"
+ " WHERE expiration < $1");
+ qs1 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "unlock_products",
+ params);
+ if (qs1 < 0)
+ {
+ GNUNET_break (0);
+ return qs1;
+ }
+ PREPARE (pg,
+ "unlock_orders",
+ "DELETE FROM merchant_orders"
+ " WHERE pay_deadline < $1");
+ qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "unlock_orders",
+ params);
+ if (qs2 < 0)
+ {
+ GNUNET_break (0);
+ return qs2;
+ }
+ PREPARE (pg,
+ "unlock_contracts",
+ "DELETE FROM merchant_contract_terms"
+ " WHERE NOT paid"
+ " AND pay_deadline < $1");
+ qs3 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "unlock_contracts",
+ params);
+ if (qs3 < 0)
{
GNUNET_break (0);
- return qs;
+ return qs3;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Released %llu locks across all instances\n",
- (unsigned long long) total);
- return (enum GNUNET_DB_QueryStatus) total;
+ "Released %d+%d+%d locks\n",
+ qs1,
+ qs2,
+ qs3);
+ return qs1 + qs2 + qs3;
}
diff --git a/src/backenddb/finalize_transfer_status.c b/src/backenddb/finalize_transfer_status.c
@@ -49,34 +49,30 @@ TALER_MERCHANTDB_finalize_transfer_status (struct TALER_MERCHANTDB_PostgresConte
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "finalize_transfer_status",
- "WITH subquery AS ("
- " SELECT signkey_serial"
- " FROM merchant.merchant_exchange_signing_keys"
- " WHERE exchange_pub=$6"
- ")"
- "UPDATE merchant_expected_transfers SET"
- " last_http_status=200"
- ",last_ec=0"
- ",last_detail=NULL"
- ",retry_needed=FALSE"
- ",retry_time=0"
- ",expected_credit_amount=$3"
- ",wire_fee=$4"
- ",h_details=$5"
- ",signkey_serial=subquery.signkey_serial"
- ",exchange_sig=$7"
- " FROM subquery"
- " WHERE wtid=$1"
- " AND exchange_url=$2");
+ PREPARE (pg,
+ "finalize_transfer_status",
+ "WITH subquery AS ("
+ " SELECT signkey_serial"
+ " FROM merchant_exchange_signing_keys"
+ " WHERE exchange_pub=$6"
+ ")"
+ "UPDATE merchant_expected_transfers SET"
+ " last_http_status=200"
+ ",last_ec=0"
+ ",last_detail=NULL"
+ ",retry_needed=FALSE"
+ ",retry_time=0"
+ ",expected_credit_amount=$3"
+ ",wire_fee=$4"
+ ",h_details=$5"
+ ",signkey_serial=subquery.signkey_serial"
+ ",exchange_sig=$7"
+ " FROM subquery"
+ " WHERE wtid=$1"
+ " AND exchange_url=$2");
return GNUNET_PQ_eval_prepared_non_select (
pg->conn,
- stmt,
+ "finalize_transfer_status",
params);
}
diff --git a/src/backenddb/get_kyc_limits.c b/src/backenddb/get_kyc_limits.c
@@ -36,6 +36,7 @@ TALER_MERCHANTDB_get_kyc_limits (struct TALER_MERCHANTDB_PostgresContext *pg,
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (merchant_account_uri.full_payto),
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_end
};
@@ -50,28 +51,27 @@ TALER_MERCHANTDB_get_kyc_limits (struct TALER_MERCHANTDB_PostgresContext *pg,
NULL),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "get_kyc_limits",
- "SELECT"
- " mk.kyc_ok"
- ",mk.jaccount_limits::TEXT"
- ",mk.access_token IS NULL AS no_access_token"
- " FROM merchant_kyc mk"
- " WHERE mk.exchange_url=$2"
- " AND mk.account_serial="
- " (SELECT account_serial"
- " FROM merchant_accounts"
- " WHERE payto_uri=$1);");
+ PREPARE (pg,
+ "get_kyc_limits",
+ "SELECT"
+ " mk.kyc_ok"
+ ",mk.jaccount_limits::TEXT"
+ ",mk.access_token IS NULL AS no_access_token"
+ " FROM merchant_kyc mk"
+ " WHERE mk.exchange_url=$3"
+ " AND mk.account_serial="
+ " (SELECT account_serial"
+ " FROM merchant_accounts"
+ " WHERE payto_uri=$1"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$2));");
*jlimits = NULL;
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "get_kyc_limits",
params,
rs);
}
diff --git a/src/backenddb/get_kyc_status.c b/src/backenddb/get_kyc_status.c
@@ -45,6 +45,7 @@ TALER_MERCHANTDB_get_kyc_status (struct TALER_MERCHANTDB_PostgresContext *pg,
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (merchant_account_uri.full_payto),
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_end
};
@@ -79,35 +80,34 @@ TALER_MERCHANTDB_get_kyc_status (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "get_kyc_status",
- "SELECT"
- " mk.access_token"
- ",mk.exchange_http_status"
- ",mk.exchange_ec_code"
- ",mk.kyc_ok"
- ",mk.last_rule_gen"
- ",mk.kyc_timestamp"
- ",mk.next_kyc_poll"
- ",mk.kyc_backoff"
- ",mk.aml_review"
- ",mk.jaccount_limits::TEXT"
- " FROM merchant_kyc mk"
- " WHERE mk.exchange_url=$2"
- " AND mk.account_serial="
- " (SELECT account_serial"
- " FROM merchant_accounts"
- " WHERE payto_uri=$1);");
+ PREPARE (pg,
+ "get_kyc_status",
+ "SELECT"
+ " mk.access_token"
+ ",mk.exchange_http_status"
+ ",mk.exchange_ec_code"
+ ",mk.kyc_ok"
+ ",mk.last_rule_gen"
+ ",mk.kyc_timestamp"
+ ",mk.next_kyc_poll"
+ ",mk.kyc_backoff"
+ ",mk.aml_review"
+ ",mk.jaccount_limits::TEXT"
+ " FROM merchant_kyc mk"
+ " WHERE mk.exchange_url=$3"
+ " AND mk.account_serial="
+ " (SELECT account_serial"
+ " FROM merchant_accounts"
+ " WHERE payto_uri=$1"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$2));");
*jlimits = NULL;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "get_kyc_status",
params,
rs);
*last_ec = (enum TALER_ErrorCode) (int) e32;
diff --git a/src/backenddb/helper.h b/src/backenddb/helper.h
@@ -53,20 +53,6 @@ struct TALER_MERCHANTDB_PostgresContext
const char *transaction_name;
/**
- * Instance id ("merchant_id") that the search_path is currently
- * pointing at, or NULL if no per-instance schema is selected.
- * Owned by this struct; set by TALER_MERCHANTDB_set_instance().
- */
- char *current_merchant_id;
-
- /**
- * merchant_serial corresponding to @e current_merchant_id, or 0
- * if no per-instance schema is selected. Used as the suffix in
- * per-instance prepared-statement names.
- */
- uint64_t current_merchant_serial;
-
- /**
* How many times have we connected to the DB.
*/
uint64_t prep_gen;
@@ -107,94 +93,6 @@ struct TALER_MERCHANTDB_PostgresContext
/**
- * Maximum length (incl. NUL) of a per-instance prepared-statement name buffer.
- * Generous: longest base name in this library is well under 56 chars and a
- * 64-bit serial fits in 20 decimal digits + underscore + NUL.
- */
-#define PG_PREP_INSTANCE_NAME_MAX 96
-
-
-/**
- * Number of slots in each per-call-site (serial -> gen) cache used by
- * #PREPARE_INSTANCE. A typical merchant deployment has a handful of
- * instances; this is sized to comfortably cover that case. On a miss
- * (cache thrash with more instances active than slots), the macro
- * falls back to re-issuing PREPARE, which is correct as long as the
- * statement was deallocated by the connection drop that bumped
- * @e prep_gen. Increase if multi-tenant deployments thrash.
- */
-#define PG_PREP_INSTANCE_CACHE_SLOTS 8
-
-
-/**
- * Per-instance variant of #PREPARE. Prepares SQL statement @a sql
- * under the connection-scoped name "<base>_<merchant_serial>" once
- * per (call-site, merchant_serial, prep_gen). Writes the resolved
- * name into @a sname (a caller-provided char buffer of at least
- * #PG_PREP_INSTANCE_NAME_MAX bytes) so the caller can pass it to
- * GNUNET_PQ_eval_prepared_*.
- *
- * Per-instance call sites must run with @e current_merchant_serial
- * != 0 (i.e. after a successful TALER_MERCHANTDB_set_instance()).
- *
- * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure.
- *
- * @param pg a `struct TALER_MERCHANTDB_PostgresContext`
- * @param sname caller-owned char buffer receiving the resolved name
- * @param base base statement name (string literal)
- * @param sql actual SQL text
- */
-#define PREPARE_INSTANCE(pg,sname,base,sql) \
- do { \
- static struct { \
- uint64_t serial; \
- unsigned long long gen; \
- } _pi_cache[PG_PREP_INSTANCE_CACHE_SLOTS]; \
- static unsigned int _pi_next; \
- bool _pi_hit = false; \
- \
- GNUNET_assert (0 != (pg)->current_merchant_serial); \
- GNUNET_snprintf ((sname), \
- PG_PREP_INSTANCE_NAME_MAX, \
- "%s_%llu", \
- base, \
- (unsigned long long) (pg)-> \
- current_merchant_serial); \
- for (unsigned int _i = 0; \
- _i < PG_PREP_INSTANCE_CACHE_SLOTS; \
- _i++) \
- { \
- if ( (_pi_cache[_i].gen == (pg)->prep_gen) && \
- (_pi_cache[_i].serial == \
- (pg)->current_merchant_serial) ) \
- { \
- _pi_hit = true; \
- break; \
- } \
- } \
- if (! _pi_hit) \
- { \
- struct GNUNET_PQ_PreparedStatement _pi_ps[] = { \
- GNUNET_PQ_make_prepare ((sname), sql), \
- GNUNET_PQ_PREPARED_STATEMENT_END \
- }; \
- \
- if (GNUNET_OK != \
- GNUNET_PQ_prepare_statements ((pg)->conn, \
- _pi_ps)) \
- { \
- GNUNET_break (0); \
- return GNUNET_DB_STATUS_HARD_ERROR; \
- } \
- _pi_cache[_pi_next].gen = (pg)->prep_gen; \
- _pi_cache[_pi_next].serial = \
- (pg)->current_merchant_serial; \
- _pi_next = (_pi_next + 1) % PG_PREP_INSTANCE_CACHE_SLOTS; \
- } \
- } while (0)
-
-
-/**
* Check that the database connection is still up and automatically reconnects
* unless we are already inside of a transaction.
*
diff --git a/src/backenddb/inactivate_account.c b/src/backenddb/inactivate_account.c
@@ -31,6 +31,7 @@ TALER_MERCHANTDB_inactivate_account (struct TALER_MERCHANTDB_PostgresContext *pg
const struct TALER_MerchantWireHashP *h_wire)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_end
};
@@ -41,20 +42,15 @@ TALER_MERCHANTDB_inactivate_account (struct TALER_MERCHANTDB_PostgresContext *pg
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (merchant_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "inactivate_account",
- "SELECT out_found AS found"
- " FROM merchant_do_inactivate_account"
- " ($1);");
+ PREPARE (pg,
+ "inactivate_account",
+ "SELECT out_found AS found"
+ " FROM merchant_do_inactivate_account"
+ " ($1,$2);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "inactivate_account",
params,
rs);
if (qs < 0)
diff --git a/src/backenddb/increase_refund.c b/src/backenddb/increase_refund.c
@@ -66,11 +66,6 @@ struct FindRefundContext
struct TALER_MERCHANTDB_PostgresContext *pg;
/**
- * Resolved per-instance prepared-statement name for "find_refunds_by_coin".
- */
- const char *stmt_find_refunds;
-
- /**
* Updated to reflect total amount refunded so far.
*/
struct TALER_Amount refunded_amount;
@@ -138,16 +133,6 @@ struct InsertRefundContext
* due to legal limits?
*/
bool legal_capped;
-
- /**
- * Resolved per-instance prepared-statement name for "insert_refund".
- */
- const char *stmt_insert_refund;
-
- /**
- * Resolved per-instance prepared-statement name for "find_refunds_by_coin".
- */
- const char *stmt_find_refunds;
};
@@ -373,8 +358,7 @@ process_deposits_for_refund_cb (void *cls,
GNUNET_PQ_result_spec_end
};
struct FindRefundContext ictx = {
- .pg = pg,
- .stmt_find_refunds = ctx->stmt_find_refunds
+ .pg = pg
};
struct ExchangeLimit *el;
@@ -411,7 +395,7 @@ process_deposits_for_refund_cb (void *cls,
&ictx.refunded_amount));
ires = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- ictx.stmt_find_refunds,
+ "find_refunds_by_coin",
params,
&process_refund_cb,
&ictx);
@@ -576,7 +560,7 @@ process_deposits_for_refund_cb (void *cls,
check_connection (pg);
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- ctx->stmt_insert_refund,
+ "insert_refund",
params);
switch (qs)
{
@@ -635,69 +619,63 @@ TALER_MERCHANTDB_increase_refund (
{
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
- char stmt_insert_refund[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_find_refunds[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_find_deposits[PG_PREP_INSTANCE_NAME_MAX];
struct InsertRefundContext ctx = {
.pg = pg,
.refund = refund,
.olc = olc,
.olc_cls = olc_cls,
- .reason = reason,
- .stmt_insert_refund = stmt_insert_refund,
- .stmt_find_refunds = stmt_find_refunds
+ .reason = reason
};
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
// FIXME: return 'refund_serial' from this INSERT statement for #10577
- PREPARE_INSTANCE (pg,
- stmt_insert_refund,
- "insert_refund",
- "INSERT INTO merchant_refunds"
- "(order_serial"
- ",rtransaction_id"
- ",refund_timestamp"
- ",coin_pub"
- ",reason"
- ",refund_amount"
- ") VALUES"
- "($1, $2, $3, $4, $5, $6)");
- PREPARE_INSTANCE (pg,
- stmt_find_refunds,
- "find_refunds_by_coin",
- "SELECT"
- " refund_amount"
- ",rtransaction_id"
- " FROM merchant_refunds"
- " WHERE coin_pub=$1"
- " AND order_serial=$2");
- PREPARE_INSTANCE (pg,
- stmt_find_deposits,
- "find_deposits_for_refund",
- "SELECT"
- " dep.coin_pub"
- ",dco.order_serial"
- ",dep.amount_with_fee"
- ",dco.exchange_url"
- " FROM merchant_deposits dep"
- " JOIN merchant_deposit_confirmations dco"
- " USING (deposit_confirmation_serial)"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1"
- " AND paid)");
+ PREPARE (pg,
+ "insert_refund",
+ "INSERT INTO merchant_refunds"
+ "(order_serial"
+ ",rtransaction_id"
+ ",refund_timestamp"
+ ",coin_pub"
+ ",reason"
+ ",refund_amount"
+ ") VALUES"
+ "($1, $2, $3, $4, $5, $6)");
+ PREPARE (pg,
+ "find_refunds_by_coin",
+ "SELECT"
+ " refund_amount"
+ ",rtransaction_id"
+ " FROM merchant_refunds"
+ " WHERE coin_pub=$1"
+ " AND order_serial=$2");
+ PREPARE (pg,
+ "find_deposits_for_refund",
+ "SELECT"
+ " dep.coin_pub"
+ ",dco.order_serial"
+ ",dep.amount_with_fee"
+ ",dco.exchange_url"
+ " FROM merchant_deposits dep"
+ " JOIN merchant_deposit_confirmations dco"
+ " USING (deposit_confirmation_serial)"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE order_id=$2"
+ " AND paid"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Asked to refund %s on order %s\n",
TALER_amount2s (refund),
order_id);
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt_find_deposits,
+ "find_deposits_for_refund",
params,
&process_deposits_for_refund_cb,
&ctx);
diff --git a/src/backenddb/increment_money_pots.c b/src/backenddb/increment_money_pots.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_increment_money_pots (struct TALER_MERCHANTDB_PostgresContext *
const struct TALER_Amount *pot_increments)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_array_uint64 (money_pots_len,
money_pot_ids,
pg->conn),
@@ -49,21 +50,16 @@ TALER_MERCHANTDB_increment_money_pots (struct TALER_MERCHANTDB_PostgresContext *
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "increment_money_pots",
- "SELECT"
- " out_not_found AS not_found"
- " FROM merchant_do_increment_money_pots"
- "($1,$2);");
+ PREPARE (pg,
+ "increment_money_pots",
+ "SELECT"
+ " out_not_found AS not_found"
+ " FROM merchant_do_increment_money_pots"
+ "($1,$2,$3);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "increment_money_pots",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/insert_account.c b/src/backenddb/insert_account.c
@@ -31,6 +31,7 @@ TALER_MERCHANTDB_insert_account (struct TALER_MERCHANTDB_PostgresContext *pg,
const struct TALER_MERCHANTDB_AccountDetails *account_details)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (account_details->instance_id),
GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire),
GNUNET_PQ_query_param_auto_from_type (&account_details->salt),
GNUNET_PQ_query_param_string (account_details->payto_uri.full_payto),
@@ -47,32 +48,30 @@ TALER_MERCHANTDB_insert_account (struct TALER_MERCHANTDB_PostgresContext *pg,
account_details->extra_wire_subject_metadata),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (account_details->instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_account",
- "INSERT INTO merchant_accounts AS ma"
- "(h_wire"
- ",salt"
- ",payto_uri"
- ",credit_facade_url"
- ",credit_facade_credentials"
- ",active"
- ",extra_wire_subject_metadata)"
- " VALUES ($1, $2, $3, $4, $5::TEXT::JSONB, $6, $7)"
- " ON CONFLICT(payto_uri)"
- " DO UPDATE SET"
- " active = true"
- ",credit_facade_url = EXCLUDED.credit_facade_url"
- ",credit_facade_credentials = EXCLUDED.credit_facade_credentials"
- ",extra_wire_subject_metadata = EXCLUDED.extra_wire_subject_metadata"
- " WHERE NOT ma.active");
+ PREPARE (pg,
+ "insert_account",
+ "INSERT INTO merchant_accounts AS ma"
+ "(merchant_serial"
+ ",h_wire"
+ ",salt"
+ ",payto_uri"
+ ",credit_facade_url"
+ ",credit_facade_credentials"
+ ",active"
+ ",extra_wire_subject_metadata)"
+ " SELECT merchant_serial, $2, $3, $4, $5, $6::TEXT::JSONB, $7, $8"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1"
+ " ON CONFLICT(merchant_serial,payto_uri)"
+ " DO UPDATE SET"
+ " active = true"
+ ",credit_facade_url = EXCLUDED.credit_facade_url"
+ ",credit_facade_credentials = EXCLUDED.credit_facade_credentials"
+ ",extra_wire_subject_metadata = EXCLUDED.extra_wire_subject_metadata"
+ " WHERE NOT ma.active");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_account",
params);
}
diff --git a/src/backenddb/insert_category.c b/src/backenddb/insert_category.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2024, 2026 Taler Systems SA
+ Copyright (C) 2024 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
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_insert_category (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t *category_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (category_name),
TALER_PQ_query_param_json (category_name_i18n),
GNUNET_PQ_query_param_end
@@ -43,23 +44,22 @@ TALER_MERCHANTDB_insert_category (struct TALER_MERCHANTDB_PostgresContext *pg,
category_id),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_category",
- "INSERT INTO merchant_categories"
- "(category_name"
- ",category_name_i18n"
- ")"
- " VALUES ($1, $2::TEXT::JSONB)"
- " RETURNING category_serial");
+ PREPARE (pg,
+ "insert_category",
+ "INSERT INTO merchant_categories"
+ "(merchant_serial"
+ ",category_name"
+ ",category_name_i18n"
+ ")"
+ " SELECT merchant_serial,"
+ " $2, $3::TEXT::JSONB"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1"
+ " RETURNING category_serial");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_category",
params,
rs);
}
diff --git a/src/backenddb/insert_contract_terms.c b/src/backenddb/insert_contract_terms.c
@@ -71,12 +71,10 @@ TALER_MERCHANTDB_insert_contract_terms (struct TALER_MERCHANTDB_PostgresContext
fulfillment_url =
json_string_value (json_object_get (contract_terms,
"fulfillment_url"));
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
TALER_PQ_query_param_json (contract_terms),
GNUNET_PQ_query_param_auto_from_type (&h_contract_terms),
@@ -92,40 +90,43 @@ TALER_MERCHANTDB_insert_contract_terms (struct TALER_MERCHANTDB_PostgresContext
order_serial),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_contract_terms",
- "INSERT INTO merchant_contract_terms"
- "(order_serial"
- ",order_id"
- ",contract_terms"
- ",h_contract_terms"
- ",creation_time"
- ",pay_deadline"
- ",refund_deadline"
- ",fulfillment_url"
- ",claim_token"
- ",pos_key"
- ",pos_algorithm)"
- "SELECT"
- " mo.order_serial"
- ",mo.order_id"
- ",$2::TEXT::JSONB" /* contract_terms */
- ",$3" /* h_contract_terms */
- ",mo.creation_time"
- ",$4" /* pay_deadline */
- ",$5" /* refund_deadline */
- ",$6" /* fulfillment_url */
- ",mo.claim_token"
- ",mo.pos_key"
- ",mo.pos_algorithm"
- " FROM merchant_orders mo"
- " WHERE order_id=$1"
- " RETURNING order_serial");
+ PREPARE (pg,
+ "insert_contract_terms",
+ "INSERT INTO merchant_contract_terms"
+ "(order_serial"
+ ",merchant_serial"
+ ",order_id"
+ ",contract_terms"
+ ",h_contract_terms"
+ ",creation_time"
+ ",pay_deadline"
+ ",refund_deadline"
+ ",fulfillment_url"
+ ",claim_token"
+ ",pos_key"
+ ",pos_algorithm)"
+ "SELECT"
+ " mo.order_serial"
+ ",mo.merchant_serial"
+ ",mo.order_id"
+ ",$3::TEXT::JSONB" /* contract_terms */
+ ",$4" /* h_contract_terms */
+ ",mo.creation_time"
+ ",$5" /* pay_deadline */
+ ",$6" /* refund_deadline */
+ ",$7" /* fulfillment_url */
+ ",mo.claim_token"
+ ",mo.pos_key"
+ ",mo.pos_algorithm"
+ " FROM merchant_orders mo"
+ " WHERE order_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " RETURNING order_serial");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_contract_terms",
params,
rs);
}
diff --git a/src/backenddb/insert_deposit.c b/src/backenddb/insert_deposit.c
@@ -53,29 +53,26 @@ TALER_MERCHANTDB_insert_deposit (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
/* no preflight check here, run in transaction by caller! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing deposit for coin_pub: `%s', amount_with_fee: %s\n",
TALER_B2S (coin_pub),
TALER_amount2s (amount_with_fee));
- GNUNET_assert (NULL != pg->current_merchant_id);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_deposit",
- "INSERT INTO merchant_deposits"
- "(deposit_confirmation_serial"
- ",coin_offset"
- ",coin_pub"
- ",coin_sig"
- ",amount_with_fee"
- ",deposit_fee"
- ",refund_fee"
- ",settlement_retry_time"
- ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8)"
- " ON CONFLICT DO NOTHING;");
+ check_connection (pg);
+ PREPARE (pg,
+ "insert_deposit",
+ "INSERT INTO merchant_deposits"
+ "(deposit_confirmation_serial"
+ ",coin_offset"
+ ",coin_pub"
+ ",coin_sig"
+ ",amount_with_fee"
+ ",deposit_fee"
+ ",refund_fee"
+ ",settlement_retry_time"
+ ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8)"
+ " ON CONFLICT DO NOTHING;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_deposit",
params);
}
diff --git a/src/backenddb/insert_deposit_confirmation.c b/src/backenddb/insert_deposit_confirmation.c
@@ -47,6 +47,7 @@ TALER_MERCHANTDB_insert_deposit_confirmation (struct TALER_MERCHANTDB_PostgresCo
= GNUNET_STRINGS_data_to_string_alloc (&nbo,
sizeof (nbo));
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_timestamp (&deposit_timestamp),
GNUNET_PQ_query_param_string (exchange_url),
@@ -54,18 +55,21 @@ TALER_MERCHANTDB_insert_deposit_confirmation (struct TALER_MERCHANTDB_PostgresCo
total_without_fees),
TALER_PQ_query_param_amount_with_currency (pg->conn,
wire_fee),
- GNUNET_PQ_query_param_auto_from_type (h_wire), /* 6 */
+ GNUNET_PQ_query_param_auto_from_type (h_wire), /* 7 */
GNUNET_PQ_query_param_auto_from_type (exchange_sig),
GNUNET_PQ_query_param_auto_from_type (exchange_pub),
GNUNET_PQ_query_param_timestamp (&wire_transfer_deadline),
GNUNET_PQ_query_param_string (nbo_str),
GNUNET_PQ_query_param_end
};
+ bool no_instance;
bool no_order;
bool no_account;
bool no_signkey;
bool conflict;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ &no_instance),
GNUNET_PQ_result_spec_bool ("no_order",
&no_order),
GNUNET_PQ_result_spec_bool ("no_account",
@@ -79,11 +83,7 @@ TALER_MERCHANTDB_insert_deposit_confirmation (struct TALER_MERCHANTDB_PostgresCo
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
/* no preflight check here, run in transaction by caller! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing deposit confirmation for instance `%s' h_contract_terms `%s', total_without_fees: %s and wire transfer deadline in %s\n",
@@ -95,19 +95,19 @@ TALER_MERCHANTDB_insert_deposit_confirmation (struct TALER_MERCHANTDB_PostgresCo
wire_transfer_deadline.abs_time),
true));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_deposit_confirmation",
- "SELECT "
- " out_no_account AS no_account"
- " ,out_no_order AS no_order"
- " ,out_no_signkey AS no_signkey"
- " ,out_conflict AS conflict"
- " ,out_deposit_confirmation_serial AS deposit_confirmation_serial"
- " FROM merchant_do_insert_deposit_confirmation"
- " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
+ PREPARE (pg,
+ "insert_deposit_confirmation",
+ "SELECT "
+ " out_no_instance AS no_instance"
+ " ,out_no_account AS no_account"
+ " ,out_no_order AS no_order"
+ " ,out_no_signkey AS no_signkey"
+ " ,out_conflict AS conflict"
+ " ,out_deposit_confirmation_serial AS deposit_confirmation_serial"
+ " FROM merchant_do_insert_deposit_confirmation"
+ " ($1, $2 ,$3, $4, $5, $6, $7, $8, $9, $10, $11);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_deposit_confirmation",
params,
rs);
GNUNET_free (nbo_str);
@@ -116,6 +116,11 @@ TALER_MERCHANTDB_insert_deposit_confirmation (struct TALER_MERCHANTDB_PostgresCo
return qs;
// FIXME: in the future, return these codes to the client and
// return more specific error codes to the client from the API!
+ if (no_instance)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
if (no_order)
{
GNUNET_break (0);
diff --git a/src/backenddb/insert_deposit_to_transfer.c b/src/backenddb/insert_deposit_to_transfer.c
@@ -51,19 +51,16 @@ TALER_MERCHANTDB_insert_deposit_to_transfer (struct TALER_MERCHANTDB_PostgresCon
&dummy),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_deposit_to_transfer",
- "SELECT"
- " out_dummy"
- " FROM merchant_insert_deposit_to_transfer"
- " ($1,$2,$3,$4,$5,$6,$7,$8);");
+ PREPARE (pg,
+ "insert_deposit_to_transfer",
+ "SELECT"
+ " out_dummy"
+ " FROM merchant_insert_deposit_to_transfer"
+ " ($1,$2,$3,$4,$5,$6,$7,$8);");
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "insert_deposit_to_transfer",
params,
rs);
}
diff --git a/src/backenddb/insert_donau_instance.c b/src/backenddb/insert_donau_instance.c
@@ -37,6 +37,7 @@ TALER_MERCHANTDB_insert_donau_instance (struct TALER_MERCHANTDB_PostgresContext
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (donau_url),
GNUNET_PQ_query_param_string (charity->name),
+ GNUNET_PQ_query_param_auto_from_type (&charity->charity_pub),
GNUNET_PQ_query_param_uint64 (&charity_id),
TALER_PQ_query_param_amount_with_currency (pg->conn,
&charity->max_per_year),
@@ -45,24 +46,26 @@ TALER_MERCHANTDB_insert_donau_instance (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_uint64 (&charity->current_year),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_donau_instance",
- "INSERT INTO merchant_donau_instances"
- " (donau_url"
- " ,charity_name"
- " ,charity_id"
- " ,charity_max_per_year"
- " ,charity_receipts_to_date"
- " ,current_year)"
- "VALUES"
- " ($1, $2, $3, $4, $5, $6)"
- " ON CONFLICT DO NOTHING;");
+ PREPARE (pg,
+ "insert_donau_instance",
+ "INSERT INTO merchant_donau_instances"
+ " (donau_url"
+ " ,charity_name"
+ " ,merchant_instance_serial"
+ " ,charity_id"
+ " ,charity_max_per_year"
+ " ,charity_receipts_to_date"
+ " ,current_year)"
+ "VALUES"
+ " ($1, $2,"
+ " (SELECT merchant_serial"
+ " FROM merchant_instances mi"
+ " WHERE mi.merchant_pub = $3),"
+ " $4, $5, $6, $7)"
+ " ON CONFLICT DO NOTHING;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_donau_instance",
params);
}
diff --git a/src/backenddb/insert_instance.c b/src/backenddb/insert_instance.c
@@ -24,7 +24,6 @@
#include <taler/taler_dbevents.h>
#include <taler/taler_pq_lib.h>
#include "merchant-database/insert_instance.h"
-#include "merchant-database/set_instance.h"
#include "helper.h"
enum GNUNET_DB_QueryStatus
@@ -71,9 +70,9 @@ TALER_MERCHANTDB_insert_instance (
};
struct GNUNET_PQ_QueryParam params_priv[] = {
GNUNET_PQ_query_param_auto_from_type (merchant_priv),
+ GNUNET_PQ_query_param_string (is->id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
enum GNUNET_DB_QueryStatus qs;
check_connection (pg);
@@ -102,27 +101,20 @@ TALER_MERCHANTDB_insert_instance (
"VALUES"
"($1,$2,$3,LOWER($4),$5,$6::TEXT::JSONB,$7::TEXT::JSONB,$8,$9,$10,$11,"
"$12,$13,$14,$15,$16,$17,$18,$19::time_rounder_interval)");
+ PREPARE (pg,
+ "insert_keys",
+ "INSERT INTO merchant_keys"
+ "(merchant_priv"
+ ",merchant_serial)"
+ " SELECT $1, merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$2");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
"insert_instance",
params);
if (qs <= 0)
return qs;
- /* AFTER INSERT trigger has now created the merchant_instance_<N> schema.
- Route to it so the merchant_keys INSERT lands in the per-instance table. */
- qs = TALER_MERCHANTDB_set_instance (pg,
- is->id);
- if (qs <= 0)
- {
- GNUNET_break (0);
- return qs;
- }
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_keys",
- "INSERT INTO merchant_keys"
- "(merchant_priv)"
- " VALUES ($1)");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_keys",
params_priv);
}
diff --git a/src/backenddb/insert_issued_token.c b/src/backenddb/insert_issued_token.c
@@ -50,21 +50,18 @@ TALER_MERCHANTDB_insert_issued_token (struct TALER_MERCHANTDB_PostgresContext *p
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "issued_token_insert",
- "SELECT"
- " out_no_family"
- " ,out_existed"
- " FROM merchant_do_insert_issued_token"
- " ($1, $2, $3);");
+ PREPARE (pg,
+ "issued_token_insert",
+ "SELECT"
+ " out_no_family"
+ " ,out_existed"
+ " FROM merchant_do_insert_issued_token"
+ " ($1, $2, $3);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "issued_token_insert",
params,
rs);
if (qs < 0)
diff --git a/src/backenddb/insert_login_token.c b/src/backenddb/insert_login_token.c
@@ -36,6 +36,7 @@ TALER_MERCHANTDB_insert_login_token (struct TALER_MERCHANTDB_PostgresContext *pg
const char *description)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_auto_from_type (token),
GNUNET_PQ_query_param_timestamp (&creation_time),
GNUNET_PQ_query_param_timestamp (&expiration_time),
@@ -43,24 +44,22 @@ TALER_MERCHANTDB_insert_login_token (struct TALER_MERCHANTDB_PostgresContext *pg
GNUNET_PQ_query_param_string (description),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_login_token",
- "INSERT INTO merchant_login_tokens"
- "(token"
- ",creation_time"
- ",expiration_time"
- ",validity_scope"
- ",description"
- ")"
- " VALUES ($1, $2, $3, $4, $5)");
+ PREPARE (pg,
+ "insert_login_token",
+ "INSERT INTO merchant_login_tokens"
+ "(token"
+ ",creation_time"
+ ",expiration_time"
+ ",validity_scope"
+ ",description"
+ ",merchant_serial"
+ ")"
+ "SELECT $2, $3, $4, $5, $6, merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_login_token",
params);
}
diff --git a/src/backenddb/insert_money_pot.c b/src/backenddb/insert_money_pot.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_insert_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t *money_pot_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (name),
GNUNET_PQ_query_param_string (description),
GNUNET_PQ_query_param_end
@@ -43,23 +44,21 @@ TALER_MERCHANTDB_insert_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
money_pot_id),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_money_pot",
- "INSERT INTO merchant_money_pots"
- "(money_pot_name"
- ",money_pot_description)"
- " VALUES ($1, $2)"
- " ON CONFLICT DO NOTHING"
- " RETURNING money_pot_serial;");
+ PREPARE (pg,
+ "insert_money_pot",
+ "INSERT INTO merchant_money_pots"
+ "(merchant_serial"
+ ",money_pot_name"
+ ",money_pot_description)"
+ " SELECT merchant_serial, $2, $3"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1"
+ " ON CONFLICT DO NOTHING"
+ " RETURNING money_pot_serial;");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_money_pot",
params,
rs);
}
diff --git a/src/backenddb/insert_order.c b/src/backenddb/insert_order.c
@@ -44,6 +44,7 @@ TALER_MERCHANTDB_insert_order (struct TALER_MERCHANTDB_PostgresContext *pg,
= json_string_value (json_object_get (contract_terms,
"fulfillment_url"));
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_timestamp (&pay_deadline),
GNUNET_PQ_query_param_auto_from_type (claim_token),
@@ -62,34 +63,32 @@ TALER_MERCHANTDB_insert_order (struct TALER_MERCHANTDB_PostgresContext *pg,
: GNUNET_PQ_query_param_string (fulfillment_url),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
now = GNUNET_TIME_timestamp_get ();
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"inserting order: order_id: %s, instance_id: %s.\n",
order_id,
instance_id);
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_order",
- "INSERT INTO merchant_orders"
- "(order_id"
- ",pay_deadline"
- ",claim_token"
- ",h_post_data"
- ",creation_time"
- ",contract_terms"
- ",pos_key"
- ",pos_algorithm"
- ",session_id"
- ",fulfillment_url)"
- " VALUES"
- " ($1, $2, $3, $4, $5, $6::TEXT::JSONB, $7, $8, $9, $10)");
+ PREPARE (pg,
+ "insert_order",
+ "INSERT INTO merchant_orders"
+ "(merchant_serial"
+ ",order_id"
+ ",pay_deadline"
+ ",claim_token"
+ ",h_post_data"
+ ",creation_time"
+ ",contract_terms"
+ ",pos_key"
+ ",pos_algorithm"
+ ",session_id"
+ ",fulfillment_url)"
+ " SELECT merchant_serial,"
+ " $2, $3, $4, $5, $6, $7::TEXT::JSONB, $8, $9, $10, $11"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_order",
params);
}
diff --git a/src/backenddb/insert_order_blinded_sigs.c b/src/backenddb/insert_order_blinded_sigs.c
@@ -40,24 +40,20 @@ TALER_MERCHANTDB_insert_order_blinded_sigs (struct TALER_MERCHANTDB_PostgresCont
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_blinded_sigs",
- "INSERT INTO merchant_order_token_blinded_sigs"
- " (order_serial"
- " ,token_index"
- " ,token_hash"
- " ,token_blinded_signature"
- ")"
- " SELECT order_serial, $2, $3, $4"
- " FROM merchant_contract_terms"
- " WHERE order_id = $1");
+ PREPARE (pg,
+ "insert_blinded_sigs",
+ "INSERT INTO merchant_order_token_blinded_sigs"
+ " (order_serial"
+ " ,token_index"
+ " ,token_hash"
+ " ,token_blinded_signature"
+ ")"
+ " SELECT order_serial, $2, $3, $4"
+ " FROM merchant_contract_terms"
+ " WHERE order_id = $1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_blinded_sigs",
params);
}
diff --git a/src/backenddb/insert_order_lock.c b/src/backenddb/insert_order_lock.c
@@ -34,63 +34,64 @@ TALER_MERCHANTDB_insert_order_lock (struct TALER_MERCHANTDB_PostgresContext *pg,
uint32_t quantity_frac)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_string (product_id),
GNUNET_PQ_query_param_uint64 (&quantity),
GNUNET_PQ_query_param_uint32 (&quantity_frac),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_order_lock",
- "WITH tmp AS"
- " (SELECT "
- " product_serial"
- " ,total_stock"
- " ,total_stock_frac"
- " ,total_sold"
- " ,total_sold_frac"
- " ,total_lost"
- " ,total_lost_frac"
- " ,allow_fractional_quantity"
- " FROM merchant_inventory"
- " WHERE product_id=$2)"
- " INSERT INTO merchant_order_locks"
- " (product_serial"
- " ,total_locked"
- " ,total_locked_frac"
- " ,order_serial)"
- " SELECT tmp.product_serial, $3::INT8, $4::INT4, order_serial"
- " FROM merchant_orders"
- " CROSS JOIN tmp"
- " WHERE order_id=$1"
- " AND (tmp.allow_fractional_quantity OR $4 = 0)"
- " AND (tmp.total_stock = 9223372036854775807"
- " OR ("
- " (tmp.total_stock::NUMERIC * 1000000"
- " + tmp.total_stock_frac::NUMERIC)"
- " - (tmp.total_sold::NUMERIC * 1000000"
- " + tmp.total_sold_frac::NUMERIC)"
- " - (tmp.total_lost::NUMERIC * 1000000"
- " + tmp.total_lost_frac::NUMERIC)"
- " >= "
- " (($3::NUMERIC * 1000000) + $4::NUMERIC)"
- " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " FROM merchant_inventory_locks mil"
- " WHERE mil.product_serial = tmp.product_serial)"
- " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " FROM merchant_order_locks mol"
- " WHERE mol.product_serial = tmp.product_serial)"
- " ))");
+ PREPARE (pg,
+ "insert_order_lock",
+ "WITH tmp AS"
+ " (SELECT "
+ " product_serial"
+ " ,merchant_serial"
+ " ,total_stock"
+ " ,total_stock_frac"
+ " ,total_sold"
+ " ,total_sold_frac"
+ " ,total_lost"
+ " ,total_lost_frac"
+ " ,allow_fractional_quantity"
+ " FROM merchant_inventory"
+ " WHERE product_id=$3"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))"
+ " INSERT INTO merchant_order_locks"
+ " (product_serial"
+ " ,total_locked"
+ " ,total_locked_frac"
+ " ,order_serial)"
+ " SELECT tmp.product_serial, $4::INT8, $5::INT4, order_serial"
+ " FROM merchant_orders"
+ " JOIN tmp USING(merchant_serial)"
+ " WHERE order_id=$2"
+ " AND (tmp.allow_fractional_quantity OR $5 = 0)"
+ " AND (tmp.total_stock = 9223372036854775807"
+ " OR ("
+ " (tmp.total_stock::NUMERIC * 1000000"
+ " + tmp.total_stock_frac::NUMERIC)"
+ " - (tmp.total_sold::NUMERIC * 1000000"
+ " + tmp.total_sold_frac::NUMERIC)"
+ " - (tmp.total_lost::NUMERIC * 1000000"
+ " + tmp.total_lost_frac::NUMERIC)"
+ " >= "
+ " (($4::NUMERIC * 1000000) + $5::NUMERIC)"
+ " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " FROM merchant_inventory_locks mil"
+ " WHERE mil.product_serial = tmp.product_serial)"
+ " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " FROM merchant_order_locks mol"
+ " WHERE mol.product_serial = tmp.product_serial)"
+ " ))");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_order_lock",
params);
}
diff --git a/src/backenddb/insert_otp.c b/src/backenddb/insert_otp.c
@@ -43,6 +43,7 @@ TALER_MERCHANTDB_insert_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
{
uint32_t pos32 = (uint32_t) td->otp_algorithm;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (otp_id),
GNUNET_PQ_query_param_string (td->otp_description),
GNUNET_PQ_query_param_string (td->otp_key),
@@ -50,24 +51,23 @@ TALER_MERCHANTDB_insert_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_uint64 (&td->otp_ctr),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_otp",
- "INSERT INTO merchant_otp_devices"
- "(otp_id"
- ",otp_description"
- ",otp_key"
- ",otp_algorithm"
- ",otp_ctr"
- ")"
- " VALUES ($1, $2, $3, $4, $5)");
+ PREPARE (pg,
+ "insert_otp",
+ "INSERT INTO merchant_otp_devices"
+ "(merchant_serial"
+ ",otp_id"
+ ",otp_description"
+ ",otp_key"
+ ",otp_algorithm"
+ ",otp_ctr"
+ ")"
+ " SELECT merchant_serial,"
+ " $2, $3, $4, $5, $6"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_otp",
params);
}
diff --git a/src/backenddb/insert_pending_webhook.c b/src/backenddb/insert_pending_webhook.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_insert_pending_webhook (struct TALER_MERCHANTDB_PostgresContext
const char *body)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&webhook_serial),
GNUNET_PQ_query_param_string (url),
GNUNET_PQ_query_param_string (http_method),
@@ -46,25 +47,23 @@ TALER_MERCHANTDB_insert_pending_webhook (struct TALER_MERCHANTDB_PostgresContext
: GNUNET_PQ_query_param_string (body),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_pending_webhook",
- "INSERT INTO merchant_pending_webhooks"
- "(webhook_serial"
- ",url"
- ",http_method"
- ",header"
- ",body"
- ")"
- " VALUES ($1, $2, $3, $4, $5)");
+ PREPARE (pg,
+ "insert_pending_webhook",
+ "INSERT INTO merchant_pending_webhooks"
+ "(merchant_serial"
+ ",webhook_serial"
+ ",url"
+ ",http_method"
+ ",header"
+ ",body"
+ ")"
+ " SELECT mi.merchant_serial,"
+ " $2, $3, $4, $5, $6"
+ " FROM merchant_instances mi"
+ " WHERE mi.merchant_id=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_pending_webhook",
params);
}
diff --git a/src/backenddb/insert_product.c b/src/backenddb/insert_product.c
@@ -41,34 +41,35 @@ TALER_MERCHANTDB_insert_product (struct TALER_MERCHANTDB_PostgresContext *pg,
bool *no_pot)
{
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), /* $3 */
+ TALER_PQ_query_param_json (pd->description_i18n), /* $4 */
GNUNET_PQ_query_param_string (pd->unit),
GNUNET_PQ_query_param_string (pd->image),
- TALER_PQ_query_param_json (pd->taxes), /* $6 */
+ TALER_PQ_query_param_json (pd->taxes), /* $7 */
TALER_PQ_query_param_array_amount_with_currency (
pd->price_array_length,
pd->price_array,
- pg->conn), /* $7 */
- GNUNET_PQ_query_param_uint64 (&pd->total_stock), /* $8 */
- GNUNET_PQ_query_param_uint32 (&pd->total_stock_frac), /* $9 */
+ pg->conn), /* $8 */
+ GNUNET_PQ_query_param_uint64 (&pd->total_stock), /* $9 */
+ GNUNET_PQ_query_param_uint32 (&pd->total_stock_frac), /* $10 */
GNUNET_PQ_query_param_bool (pd->allow_fractional_quantity),
GNUNET_PQ_query_param_uint32 (&pd->fractional_precision_level),
- TALER_PQ_query_param_json (pd->address), /* $12 */
+ TALER_PQ_query_param_json (pd->address), /* $13 */
GNUNET_PQ_query_param_timestamp (&pd->next_restock),
GNUNET_PQ_query_param_uint32 (&pd->minimum_age),
GNUNET_PQ_query_param_array_uint64 (num_cats,
cats,
- pg->conn), /* $15 */
+ pg->conn), /* $16 */
GNUNET_PQ_query_param_string (pd->product_name),
(0 == pd->product_group_id)
? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&pd->product_group_id), /* $17 */
+ : GNUNET_PQ_query_param_uint64 (&pd->product_group_id), /* $18 */
(0 == pd->money_pot_id)
? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&pd->money_pot_id), /* $18 */
- GNUNET_PQ_query_param_bool (pd->price_is_net), /* $19 */
+ : GNUNET_PQ_query_param_uint64 (&pd->money_pot_id), /* $19 */
+ GNUNET_PQ_query_param_bool (pd->price_is_net), /* $20 */
GNUNET_PQ_query_param_end
};
uint64_t ncat;
@@ -76,6 +77,8 @@ TALER_MERCHANTDB_insert_product (struct TALER_MERCHANTDB_PostgresContext *pg,
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_bool ("conflict",
conflict),
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ no_instance),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_uint64 ("no_cat",
&ncat),
@@ -87,27 +90,22 @@ TALER_MERCHANTDB_insert_product (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- *no_instance = false;
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_product",
- "SELECT"
- " out_conflict AS conflict"
- ",out_no_cat AS no_cat"
- ",out_no_group AS no_group"
- ",out_no_pot AS no_pot"
- " FROM merchant_do_insert_product"
- "($1, $2, $3::TEXT::JSONB, $4, $5, $6::TEXT::JSONB, $7"
- ",$8, $9, $10, $11, $12::TEXT::JSONB, $13, $14, $15"
- ",$16, $17, $18, $19);");
+ PREPARE (pg,
+ "insert_product",
+ "SELECT"
+ " out_conflict AS conflict"
+ ",out_no_instance AS no_instance"
+ ",out_no_cat AS no_cat"
+ ",out_no_group AS no_group"
+ ",out_no_pot AS no_pot"
+ " FROM merchant_do_insert_product"
+ "($1, $2, $3, $4::TEXT::JSONB, $5, $6, $7::TEXT::JSONB, $8"
+ ",$9, $10, $11, $12, $13::TEXT::JSONB, $14, $15, $16"
+ ",$17, $18, $19, $20);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_product",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/insert_product_group.c b/src/backenddb/insert_product_group.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_insert_product_group (struct TALER_MERCHANTDB_PostgresContext *
uint64_t *product_group_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (name),
GNUNET_PQ_query_param_string (description),
GNUNET_PQ_query_param_end
@@ -43,24 +44,22 @@ TALER_MERCHANTDB_insert_product_group (struct TALER_MERCHANTDB_PostgresContext *
product_group_id),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_product_group",
- "INSERT INTO merchant_product_groups"
- "(product_group_name"
- ",product_group_description)"
- " VALUES ($1, $2)"
- " ON CONFLICT DO NOTHING"
- " RETURNING product_group_serial");
+ PREPARE (pg,
+ "insert_product_group",
+ "INSERT INTO merchant_product_groups"
+ "(merchant_serial"
+ ",product_group_name"
+ ",product_group_description)"
+ " SELECT merchant_serial, $2, $3"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1"
+ " ON CONFLICT DO NOTHING"
+ " RETURNING product_group_serial");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_product_group",
params,
rs);
}
diff --git a/src/backenddb/insert_refund_proof.c b/src/backenddb/insert_refund_proof.c
@@ -38,24 +38,20 @@ TALER_MERCHANTDB_insert_refund_proof (struct TALER_MERCHANTDB_PostgresContext *p
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_refund_proof",
- "INSERT INTO merchant_refund_proofs"
- "(refund_serial"
- ",exchange_sig"
- ",signkey_serial)"
- "SELECT $1, $2, signkey_serial"
- " FROM merchant.merchant_exchange_signing_keys"
- " WHERE exchange_pub=$3"
- " ORDER BY start_date DESC"
- " LIMIT 1");
+ PREPARE (pg,
+ "insert_refund_proof",
+ "INSERT INTO merchant_refund_proofs"
+ "(refund_serial"
+ ",exchange_sig"
+ ",signkey_serial)"
+ "SELECT $1, $2, signkey_serial"
+ " FROM merchant_exchange_signing_keys"
+ " WHERE exchange_pub=$3"
+ " ORDER BY start_date DESC"
+ " LIMIT 1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_refund_proof",
params);
}
diff --git a/src/backenddb/insert_report.c b/src/backenddb/insert_report.c
@@ -43,6 +43,7 @@ TALER_MERCHANTDB_insert_report (
struct TALER_MERCHANT_ReportToken report_token;
struct GNUNET_TIME_Timestamp start;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (report_program_section),
GNUNET_PQ_query_param_string (report_description),
GNUNET_PQ_query_param_string (mime_type),
@@ -59,11 +60,7 @@ TALER_MERCHANTDB_insert_report (
report_id),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&report_token,
sizeof (report_token));
@@ -76,25 +73,27 @@ TALER_MERCHANTDB_insert_report (
frequency_shift)));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_report",
- "INSERT INTO merchant_reports"
- "(report_program_section"
- ",report_description"
- ",mime_type"
- ",report_token"
- ",data_source"
- ",target_address"
- ",frequency"
- ",frequency_shift"
- ",next_transmission)"
- " VALUES ($1, $2, $3, $4,"
- " $5, $6, $7, $8, $9)"
- " ON CONFLICT DO NOTHING;");
+ PREPARE (pg,
+ "insert_report",
+ "INSERT INTO merchant_reports"
+ "(merchant_serial"
+ ",report_program_section"
+ ",report_description"
+ ",mime_type"
+ ",report_token"
+ ",data_source"
+ ",target_address"
+ ",frequency"
+ ",frequency_shift"
+ ",next_transmission)"
+ " SELECT merchant_serial, $2, $3, $4, $5,"
+ " $6, $7, $8, $9, $10"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1"
+ " ON CONFLICT DO NOTHING;");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_report",
params,
rs);
}
diff --git a/src/backenddb/insert_spent_token.c b/src/backenddb/insert_spent_token.c
@@ -52,24 +52,21 @@ TALER_MERCHANTDB_insert_spent_token (struct TALER_MERCHANTDB_PostgresContext *pg
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Storing token spent with key %s\n",
GNUNET_h2s (&h_issue_pub->hash));
- PREPARE_INSTANCE (pg,
- stmt,
- "spent_token_insert",
- "SELECT"
- " out_no_family"
- " ,out_conflict"
- " FROM merchant_do_insert_spent_token"
- "($1, $2, $3, $4, $5);");
+ PREPARE (pg,
+ "spent_token_insert",
+ "SELECT"
+ " out_no_family"
+ " ,out_conflict"
+ " FROM merchant_do_insert_spent_token"
+ "($1, $2, $3, $4, $5);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "spent_token_insert",
params,
rs);
if (qs < 0)
diff --git a/src/backenddb/insert_template.c b/src/backenddb/insert_template.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_insert_template (struct TALER_MERCHANTDB_PostgresContext *pg,
const struct TALER_MERCHANTDB_TemplateDetails *td)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (template_id),
GNUNET_PQ_query_param_string (td->template_description),
(0 == otp_serial_id)
@@ -46,26 +47,24 @@ TALER_MERCHANTDB_insert_template (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_template",
- "INSERT INTO merchant_template"
- "(template_id"
- ",template_description"
- ",otp_device_id"
- ",template_contract"
- ",editable_defaults"
- ")"
- " VALUES"
- " ($1, $2, $3, $4::TEXT::JSONB, $5::TEXT::JSONB)");
+ PREPARE (pg,
+ "insert_template",
+ "INSERT INTO merchant_template"
+ "(merchant_serial"
+ ",template_id"
+ ",template_description"
+ ",otp_device_id"
+ ",template_contract"
+ ",editable_defaults"
+ ")"
+ " SELECT merchant_serial,"
+ " $2, $3, $4, $5::TEXT::JSONB, $6::TEXT::JSONB"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_template",
params);
GNUNET_PQ_cleanup_query_params_closures (params);
return qs;
diff --git a/src/backenddb/insert_token_family.c b/src/backenddb/insert_token_family.c
@@ -46,52 +46,48 @@ TALER_MERCHANTDB_insert_token_family (struct TALER_MERCHANTDB_PostgresContext *p
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
+ PREPARE (pg,
+ "insert_token_family",
+ "INSERT INTO merchant_token_families"
+ "(merchant_serial"
+ ",slug"
+ ",name"
+ ",description"
+ ",description_i18n"
+ ",extra_data"
+ ",valid_after"
+ ",valid_before"
+ ",duration"
+ ",validity_granularity"
+ ",start_offset"
+ ",kind)"
+ " SELECT merchant_serial, $2, $3, $4, $5::TEXT::JSONB,"
+ " $6::TEXT::JSONB, $7, $8, $9, $10, $11, $12"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1"
+ " ON CONFLICT DO NOTHING;");
{
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_string (token_family_slug),
+ GNUNET_PQ_query_param_string (details->name),
+ GNUNET_PQ_query_param_string (details->description),
+ TALER_PQ_query_param_json (details->description_i18n),
+ NULL == details->extra_data
+ ? GNUNET_PQ_query_param_null ()
+ : TALER_PQ_query_param_json (details->extra_data),
+ GNUNET_PQ_query_param_timestamp (&details->valid_after),
+ GNUNET_PQ_query_param_timestamp (&details->valid_before),
+ GNUNET_PQ_query_param_relative_time (&details->duration),
+ GNUNET_PQ_query_param_relative_time (&details->validity_granularity),
+ GNUNET_PQ_query_param_relative_time (&details->start_offset),
+ GNUNET_PQ_query_param_string (kind),
+ GNUNET_PQ_query_param_end
+ };
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_token_family",
- "INSERT INTO merchant_token_families"
- "(slug"
- ",name"
- ",description"
- ",description_i18n"
- ",extra_data"
- ",valid_after"
- ",valid_before"
- ",duration"
- ",validity_granularity"
- ",start_offset"
- ",kind)"
- " VALUES ($1, $2, $3, $4::TEXT::JSONB,"
- " $5::TEXT::JSONB, $6, $7, $8, $9, $10, $11)"
- " ON CONFLICT DO NOTHING;");
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (token_family_slug),
- GNUNET_PQ_query_param_string (details->name),
- GNUNET_PQ_query_param_string (details->description),
- TALER_PQ_query_param_json (details->description_i18n),
- NULL == details->extra_data
- ? GNUNET_PQ_query_param_null ()
- : TALER_PQ_query_param_json (details->extra_data),
- GNUNET_PQ_query_param_timestamp (&details->valid_after),
- GNUNET_PQ_query_param_timestamp (&details->valid_before),
- GNUNET_PQ_query_param_relative_time (&details->duration),
- GNUNET_PQ_query_param_relative_time (&details->validity_granularity),
- GNUNET_PQ_query_param_relative_time (&details->start_offset),
- GNUNET_PQ_query_param_string (kind),
- GNUNET_PQ_query_param_end
- };
-
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
- params);
- }
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_token_family",
+ params);
}
}
diff --git a/src/backenddb/insert_token_family_key.c b/src/backenddb/insert_token_family_key.c
@@ -89,53 +89,50 @@ TALER_MERCHANTDB_insert_token_family_key (struct TALER_MERCHANTDB_PostgresContex
valid_after.abs_time));
GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
valid_before.abs_time));
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (merchant_id,
- pg->current_merchant_id));
+ PREPARE (pg,
+ "token_family_key_insert",
+ "INSERT INTO merchant_token_family_keys "
+ "(token_family_serial"
+ ",pub"
+ ",h_pub"
+ ",priv"
+ ",private_key_created_at"
+ ",private_key_deleted_at"
+ ",signature_validity_start"
+ ",signature_validity_end"
+ ",cipher)"
+ " SELECT token_family_serial, $2, $3, $4, $5, $6, $7, $8, $9"
+ " FROM merchant_token_families"
+ " WHERE (slug = $1)"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$10)");
{
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (token_family_slug),
+ GNUNET_PQ_query_param_blind_sign_pub (pub->public_key),
+ GNUNET_PQ_query_param_auto_from_type (&pub->public_key->pub_key_hash),
+ GNUNET_PQ_query_param_blind_sign_priv (priv->private_key),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_timestamp (&key_expires),
+ GNUNET_PQ_query_param_timestamp (&valid_after),
+ GNUNET_PQ_query_param_timestamp (&valid_before),
+ GNUNET_PQ_query_param_string (cipher),
+ GNUNET_PQ_query_param_string (merchant_id),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
- PREPARE_INSTANCE (pg,
- stmt,
- "token_family_key_insert",
- "INSERT INTO merchant_token_family_keys "
- "(token_family_serial"
- ",pub"
- ",h_pub"
- ",priv"
- ",private_key_created_at"
- ",private_key_deleted_at"
- ",signature_validity_start"
- ",signature_validity_end"
- ",cipher)"
- " SELECT token_family_serial, $2, $3, $4, $5, $6, $7, $8, $9"
- " FROM merchant_token_families"
- " WHERE (slug = $1)");
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (token_family_slug),
- GNUNET_PQ_query_param_blind_sign_pub (pub->public_key),
- GNUNET_PQ_query_param_auto_from_type (&pub->public_key->pub_key_hash),
- GNUNET_PQ_query_param_blind_sign_priv (priv->private_key),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_timestamp (&key_expires),
- GNUNET_PQ_query_param_timestamp (&valid_after),
- GNUNET_PQ_query_param_timestamp (&valid_before),
- GNUNET_PQ_query_param_string (cipher),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
- params);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Insert into MTFK %s with valid [%llu,%llu] got %d\n",
- token_family_slug,
- (unsigned long long) valid_after.abs_time.abs_value_us,
- (unsigned long long) valid_before.abs_time.abs_value_us,
- (int) qs);
- return qs;
- }
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "token_family_key_insert",
+ params);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Insert into MTFK %s with valid [%llu,%llu] got %d\n",
+ token_family_slug,
+ (unsigned long long) valid_after.abs_time.abs_value_us,
+ (unsigned long long) valid_before.abs_time.abs_value_us,
+ (int) qs);
+ return qs;
}
}
diff --git a/src/backenddb/insert_transfer.c b/src/backenddb/insert_transfer.c
@@ -40,6 +40,7 @@ TALER_MERCHANTDB_insert_transfer (struct TALER_MERCHANTDB_PostgresContext *pg,
{
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_auto_from_type (wtid),
TALER_PQ_query_param_amount_with_currency (pg->conn,
@@ -52,29 +53,26 @@ TALER_MERCHANTDB_insert_transfer (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ no_instance),
GNUNET_PQ_result_spec_bool ("no_account",
no_account),
GNUNET_PQ_result_spec_bool ("conflict",
conflict),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- *no_instance = false;
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_transfer",
- "SELECT "
- " out_no_account AS no_account"
- " ,out_conflict AS conflict"
- " FROM merchant_do_insert_transfer"
- " ($1, $2, $3, $4, $5, $6);");
+ PREPARE (pg,
+ "insert_transfer",
+ "SELECT "
+ " out_no_instance AS no_instance"
+ " ,out_no_account AS no_account"
+ " ,out_conflict AS conflict"
+ " FROM merchant_do_insert_transfer"
+ " ($1, $2, $3, $4, $5, $6, $7);");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_transfer",
params,
rs);
}
diff --git a/src/backenddb/insert_transfer_details.c b/src/backenddb/insert_transfer_details.c
@@ -48,11 +48,6 @@ TALER_MERCHANTDB_insert_transfer_details (struct TALER_MERCHANTDB_PostgresContex
const struct TALER_PrivateContractHashP *contract_terms[GNUNET_NZL (len)];
enum GNUNET_DB_QueryStatus qs;
bool duplicate;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
for (unsigned int i = 0; i<len; i++)
{
@@ -65,18 +60,18 @@ TALER_MERCHANTDB_insert_transfer_details (struct TALER_MERCHANTDB_PostgresContex
}
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_transfer_details",
- "SELECT"
- " out_no_account"
- ",out_no_exchange"
- ",out_duplicate"
- ",out_conflict"
- ",out_order_id"
- ",out_merchant_pub"
- " FROM merchant_do_insert_transfer_details"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
+ PREPARE (pg,
+ "insert_transfer_details",
+ "SELECT"
+ " out_no_instance"
+ ",out_no_account"
+ ",out_no_exchange"
+ ",out_duplicate"
+ ",out_conflict"
+ ",out_order_id"
+ ",out_merchant_pub"
+ " FROM merchant_do_insert_transfer_details"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);");
for (unsigned int retries = 0;
retries < MAX_RETRIES;
@@ -92,6 +87,7 @@ TALER_MERCHANTDB_insert_transfer_details (struct TALER_MERCHANTDB_PostgresContex
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_string (payto_uri.full_payto),
GNUNET_PQ_query_param_auto_from_type (wtid),
@@ -120,12 +116,15 @@ TALER_MERCHANTDB_insert_transfer_details (struct TALER_MERCHANTDB_PostgresContex
pg->conn),
GNUNET_PQ_query_param_end
};
+ bool no_instance;
bool no_account;
bool no_exchange;
bool conflict;
char *order_id = NULL;
struct TALER_MerchantPublicKeyP merchant_pub;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_no_instance",
+ &no_instance),
GNUNET_PQ_result_spec_bool ("out_no_account",
&no_account),
GNUNET_PQ_result_spec_bool ("out_no_exchange",
@@ -146,7 +145,7 @@ TALER_MERCHANTDB_insert_transfer_details (struct TALER_MERCHANTDB_PostgresContex
};
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_transfer_details",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
@@ -182,7 +181,8 @@ TALER_MERCHANTDB_insert_transfer_details (struct TALER_MERCHANTDB_PostgresContex
GNUNET_free (order_id);
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Transfer details inserted: %s%s%s%s\n",
+ "Transfer details inserted: %s%s%s%s%s\n",
+ no_instance ? "no instance " : "",
no_account ? "no account " : "",
no_exchange ? "no exchange ": "",
duplicate ? "duplicate ": "",
diff --git a/src/backenddb/insert_unclaim_signature.c b/src/backenddb/insert_unclaim_signature.c
@@ -61,6 +61,7 @@ TALER_MERCHANTDB_insert_unclaim_signature (
char *notify_str = get_notify_str (order_id,
merchant_pub);
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_string (nonce_str),
GNUNET_PQ_query_param_string (notify_str),
@@ -75,22 +76,17 @@ TALER_MERCHANTDB_insert_unclaim_signature (
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_unclaim_signature",
- "SELECT"
- " out_found"
- " FROM merchant_do_insert_unclaim_signature"
- "($1, $2, $3, $4, $5);");
+ PREPARE (pg,
+ "insert_unclaim_signature",
+ "SELECT"
+ " out_found"
+ " FROM merchant_do_insert_unclaim_signature"
+ "($1, $2, $3, $4, $5, $6);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "insert_unclaim_signature",
params,
rs);
GNUNET_free (nonce_str);
diff --git a/src/backenddb/insert_unit.c b/src/backenddb/insert_unit.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2025, 2026 Taler Systems SA
+ Copyright (C) 2025 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
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_insert_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t *unit_serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (ud->unit),
GNUNET_PQ_query_param_string (ud->unit_name_long),
GNUNET_PQ_query_param_string (ud->unit_name_short),
@@ -47,6 +48,8 @@ TALER_MERCHANTDB_insert_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
};
bool unit_serial_present = true;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ no_instance),
GNUNET_PQ_result_spec_bool ("conflict",
conflict),
GNUNET_PQ_result_spec_allow_null (
@@ -56,25 +59,21 @@ TALER_MERCHANTDB_insert_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
*no_instance = false;
*conflict = false;
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_unit",
- "SELECT"
- " out_conflict AS conflict"
- " ,out_unit_serial AS unit_serial"
- " FROM merchant_do_insert_unit"
- " ($1,$2,$3,$4,$5,$6,$7,$8);");
+ PREPARE (pg,
+ "insert_unit",
+ "SELECT"
+ " out_no_instance AS no_instance"
+ " ,out_conflict AS conflict"
+ " ,out_unit_serial AS unit_serial"
+ " FROM merchant_do_insert_unit"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "insert_unit",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/insert_webhook.c b/src/backenddb/insert_webhook.c
@@ -32,6 +32,7 @@ TALER_MERCHANTDB_insert_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
const struct TALER_MERCHANTDB_WebhookDetails *wb)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (webhook_id),
GNUNET_PQ_query_param_string (wb->event_type),
GNUNET_PQ_query_param_string (wb->url),
@@ -44,26 +45,25 @@ TALER_MERCHANTDB_insert_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
: GNUNET_PQ_query_param_string (wb->body_template),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "insert_webhook",
- "INSERT INTO merchant_webhook"
- "(webhook_id"
- ",event_type"
- ",url"
- ",http_method"
- ",header_template"
- ",body_template"
- ")"
- " VALUES ($1, $2, $3, $4, $5, $6)");
+ PREPARE (pg,
+ "insert_webhook",
+ "INSERT INTO merchant_webhook"
+ "(merchant_serial"
+ ",webhook_id"
+ ",event_type"
+ ",url"
+ ",http_method"
+ ",header_template"
+ ",body_template"
+ ")"
+ " SELECT merchant_serial,"
+ " $2, $3, $4, $5, $6, $7"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "insert_webhook",
params);
}
diff --git a/src/backenddb/lock_product.c b/src/backenddb/lock_product.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_lock_product (struct TALER_MERCHANTDB_PostgresContext *pg,
struct GNUNET_TIME_Timestamp expiration_time)
{
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),
@@ -42,56 +43,59 @@ TALER_MERCHANTDB_lock_product (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_timestamp (&expiration_time),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lock_product",
- "WITH tmp AS"
- " (SELECT"
- " mi.product_serial"
- " ,mi.total_stock"
- " ,mi.total_stock_frac"
- " ,mi.total_sold"
- " ,mi.total_sold_frac"
- " ,mi.total_lost"
- " ,mi.total_lost_frac"
- " ,mi.allow_fractional_quantity"
- " FROM merchant_inventory mi"
- " WHERE mi.product_id=$1)"
- "INSERT INTO merchant_inventory_locks"
- "(product_serial"
- ",lock_uuid"
- ",total_locked"
- ",total_locked_frac"
- ",expiration)"
- " SELECT tmp.product_serial, $2, $3::INT8, $4::INT4, $5"
- " FROM tmp"
- " WHERE (tmp.allow_fractional_quantity OR $4 = 0)"
- " AND (tmp.total_stock = 9223372036854775807"
- " OR ("
- " (tmp.total_stock::NUMERIC * 1000000"
- " + tmp.total_stock_frac::NUMERIC)"
- " - (tmp.total_sold::NUMERIC * 1000000"
- " + tmp.total_sold_frac::NUMERIC)"
- " - (tmp.total_lost::NUMERIC * 1000000"
- " + tmp.total_lost_frac::NUMERIC)"
- " >= "
- " (($3::NUMERIC * 1000000) + $4::NUMERIC)"
- " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " FROM merchant_inventory_locks mil"
- " WHERE mil.product_serial = tmp.product_serial)"
- " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " FROM merchant_order_locks mol"
- " WHERE mol.product_serial = tmp.product_serial)"
- " ))");
+ 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))"
+ ",tmp AS"
+ " (SELECT"
+ " mi.product_serial"
+ " ,mi.total_stock"
+ " ,mi.total_stock_frac"
+ " ,mi.total_sold"
+ " ,mi.total_sold_frac"
+ " ,mi.total_lost"
+ " ,mi.total_lost_frac"
+ " ,mi.allow_fractional_quantity"
+ " FROM merchant_inventory mi"
+ " JOIN ps USING (product_serial))"
+ "INSERT INTO merchant_inventory_locks"
+ "(product_serial"
+ ",lock_uuid"
+ ",total_locked"
+ ",total_locked_frac"
+ ",expiration)"
+ " SELECT tmp.product_serial, $3, $4::INT8, $5::INT4, $6"
+ " FROM tmp"
+ " WHERE (tmp.allow_fractional_quantity OR $5 = 0)"
+ " AND (tmp.total_stock = 9223372036854775807"
+ " OR ("
+ " (tmp.total_stock::NUMERIC * 1000000"
+ " + tmp.total_stock_frac::NUMERIC)"
+ " - (tmp.total_sold::NUMERIC * 1000000"
+ " + tmp.total_sold_frac::NUMERIC)"
+ " - (tmp.total_lost::NUMERIC * 1000000"
+ " + tmp.total_lost_frac::NUMERIC)"
+ " >= "
+ " (($4::NUMERIC * 1000000) + $5::NUMERIC)"
+ " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " FROM merchant_inventory_locks mil"
+ " WHERE mil.product_serial = tmp.product_serial)"
+ " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " FROM merchant_order_locks mol"
+ " WHERE mol.product_serial = tmp.product_serial)"
+ " ))");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "lock_product",
params);
}
diff --git a/src/backenddb/lookup_account.c b/src/backenddb/lookup_account.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2026 Taler Systems SA
+ Copyright (C) 2023 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
@@ -32,6 +32,7 @@ TALER_MERCHANTDB_lookup_account (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t *account_serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (payto_uri.full_payto),
GNUNET_PQ_query_param_end
};
@@ -40,22 +41,21 @@ TALER_MERCHANTDB_lookup_account (struct TALER_MERCHANTDB_PostgresContext *pg,
account_serial),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_account",
- "SELECT"
- " account_serial"
- " FROM merchant_accounts"
- " WHERE REGEXP_REPLACE(payto_uri,'\\?.*','')"
- " =REGEXP_REPLACE($1,'\\?.*','')");
+ PREPARE (pg,
+ "lookup_account",
+ "SELECT"
+ " account_serial"
+ " FROM merchant_accounts"
+ " WHERE REGEXP_REPLACE(payto_uri,'\\?.*','')"
+ " =REGEXP_REPLACE($2,'\\?.*','')"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_account",
params,
rs);
}
diff --git a/src/backenddb/lookup_all_products.c b/src/backenddb/lookup_all_products.c
@@ -173,54 +173,53 @@ TALER_MERCHANTDB_lookup_all_products (
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_all_products",
- "SELECT"
- " description"
- ",description_i18n::TEXT"
- ",product_name"
- ",unit"
- ",price_array"
- ",taxes::TEXT"
- ",total_stock"
- ",total_stock_frac"
- ",allow_fractional_quantity"
- ",fractional_precision_level"
- ",total_sold"
- ",total_sold_frac"
- ",total_lost"
- ",total_lost_frac"
- ",image"
- ",minv.address::TEXT"
- ",next_restock"
- ",minimum_age"
- ",product_id"
- ",product_serial"
- ",t.category_array AS categories"
- ",product_group_serial"
- ",money_pot_serial"
- ",price_is_net"
- " FROM merchant_inventory minv"
- ",LATERAL ("
- " SELECT ARRAY ("
- " SELECT mpc.category_serial"
- " FROM merchant_product_categories mpc"
- " WHERE mpc.product_serial = minv.product_serial"
- " ) AS category_array"
- " ) t");
+ PREPARE (pg,
+ "lookup_all_products",
+ "SELECT"
+ " description"
+ ",description_i18n::TEXT"
+ ",product_name"
+ ",unit"
+ ",price_array"
+ ",taxes::TEXT"
+ ",total_stock"
+ ",total_stock_frac"
+ ",allow_fractional_quantity"
+ ",fractional_precision_level"
+ ",total_sold"
+ ",total_sold_frac"
+ ",total_lost"
+ ",total_lost_frac"
+ ",image"
+ ",minv.address::TEXT"
+ ",next_restock"
+ ",minimum_age"
+ ",product_id"
+ ",product_serial"
+ ",t.category_array AS categories"
+ ",product_group_serial"
+ ",money_pot_serial"
+ ",price_is_net"
+ " FROM merchant_inventory minv"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ ",LATERAL ("
+ " SELECT ARRAY ("
+ " SELECT mpc.category_serial"
+ " FROM merchant_product_categories mpc"
+ " WHERE mpc.product_serial = minv.product_serial"
+ " ) AS category_array"
+ " ) t"
+ " WHERE inst.merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_all_products",
params,
&lookup_products_cb,
&plc);
diff --git a/src/backenddb/lookup_categories.c b/src/backenddb/lookup_categories.c
@@ -113,31 +113,30 @@ TALER_MERCHANTDB_lookup_categories (struct TALER_MERCHANTDB_PostgresContext *pg,
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_categories",
- "SELECT"
- " mc.category_serial"
- ",mc.category_name"
- ",mc.category_name_i18n::TEXT"
- ",COALESCE(COUNT(mpc.product_serial),0)"
- " AS product_count"
- " FROM merchant_categories mc"
- " LEFT JOIN merchant_product_categories mpc"
- " USING (category_serial)"
- " GROUP BY mc.category_serial"
- " ORDER BY mc.category_serial;");
+ PREPARE (pg,
+ "lookup_categories",
+ "SELECT"
+ " mc.category_serial"
+ ",mc.category_name"
+ ",mc.category_name_i18n::TEXT"
+ ",COALESCE(COUNT(mpc.product_serial),0)"
+ " AS product_count"
+ " FROM merchant_categories mc"
+ " LEFT JOIN merchant_product_categories mpc"
+ " USING (category_serial)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " GROUP BY mc.category_serial"
+ " ORDER BY mc.category_serial;");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_categories",
params,
&lookup_categories_cb,
&tlc);
diff --git a/src/backenddb/lookup_categories_by_ids.c b/src/backenddb/lookup_categories_by_ids.c
@@ -107,35 +107,34 @@ TALER_MERCHANTDB_lookup_categories_by_ids (struct TALER_MERCHANTDB_PostgresConte
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_array_uint64 (num_category_ids,
category_ids,
pg->conn),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_categories_by_ids",
- "SELECT"
- " mc.category_serial"
- ",mc.category_name"
- ",mc.category_name_i18n::TEXT"
- ",COALESCE(COUNT(mpc.product_serial),0)"
- " AS product_count"
- " FROM merchant_categories mc"
- " LEFT JOIN merchant_product_categories mpc"
- " USING (category_serial)"
- " WHERE mc.category_serial = ANY ($1)"
- " GROUP BY mc.category_serial"
- " ORDER BY mc.category_serial;");
+ PREPARE (pg,
+ "lookup_categories_by_ids",
+ "SELECT"
+ " mc.category_serial"
+ ",mc.category_name"
+ ",mc.category_name_i18n::TEXT"
+ ",COALESCE(COUNT(mpc.product_serial),0)"
+ " AS product_count"
+ " FROM merchant_categories mc"
+ " LEFT JOIN merchant_product_categories mpc"
+ " USING (category_serial)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " AND mc.category_serial = ANY ($2)"
+ " GROUP BY mc.category_serial"
+ " ORDER BY mc.category_serial;");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_categories_by_ids",
params,
&lookup_categories_cb,
&tlc);
diff --git a/src/backenddb/lookup_contract_terms.c b/src/backenddb/lookup_contract_terms.c
@@ -38,6 +38,7 @@ TALER_MERCHANTDB_lookup_contract_terms (struct TALER_MERCHANTDB_PostgresContext
enum GNUNET_DB_QueryStatus qs;
struct TALER_ClaimTokenP ct;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
@@ -51,23 +52,22 @@ TALER_MERCHANTDB_lookup_contract_terms (struct TALER_MERCHANTDB_PostgresContext
&ct),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_contract_terms",
- "SELECT"
- " contract_terms::TEXT"
- ",order_serial"
- ",claim_token"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1");
+ PREPARE (pg,
+ "lookup_contract_terms",
+ "SELECT"
+ " contract_terms::TEXT"
+ ",order_serial"
+ ",claim_token"
+ " FROM merchant_contract_terms"
+ " WHERE order_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_contract_terms",
params,
(NULL != contract_terms)
? rs
diff --git a/src/backenddb/lookup_contract_terms2.c b/src/backenddb/lookup_contract_terms2.c
@@ -39,6 +39,7 @@ TALER_MERCHANTDB_lookup_contract_terms2 (struct TALER_MERCHANTDB_PostgresContext
enum GNUNET_DB_QueryStatus qs;
struct TALER_ClaimTokenP ct;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
@@ -63,26 +64,25 @@ TALER_MERCHANTDB_lookup_contract_terms2 (struct TALER_MERCHANTDB_PostgresContext
NULL),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_contract_terms2",
- "SELECT"
- " contract_terms::TEXT"
- ",order_serial"
- ",claim_token"
- ",paid"
- ",pos_key"
- ",pos_algorithm"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1");
+ PREPARE (pg,
+ "lookup_contract_terms2",
+ "SELECT"
+ " contract_terms::TEXT"
+ ",order_serial"
+ ",claim_token"
+ ",paid"
+ ",pos_key"
+ ",pos_algorithm"
+ " FROM merchant_contract_terms"
+ " WHERE order_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_contract_terms2",
params,
(NULL != contract_terms)
? rs
diff --git a/src/backenddb/lookup_contract_terms3.c b/src/backenddb/lookup_contract_terms3.c
@@ -46,6 +46,7 @@ TALER_MERCHANTDB_lookup_contract_terms3 (struct TALER_MERCHANTDB_PostgresContext
uint16_t ci = 0;
bool choice_index_null = false;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
NULL == session_id
? GNUNET_PQ_query_param_null ()
@@ -74,28 +75,27 @@ TALER_MERCHANTDB_lookup_contract_terms3 (struct TALER_MERCHANTDB_PostgresContext
&choice_index_null),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
*session_matches = false;
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_contract_terms3",
- "SELECT"
- " contract_terms::TEXT"
- ",order_serial"
- ",claim_token"
- ",paid"
- ",wired"
- ",(session_id=$2) AS session_matches"
- ",choice_index"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1");
+ PREPARE (pg,
+ "lookup_contract_terms3",
+ "SELECT"
+ " contract_terms::TEXT"
+ ",order_serial"
+ ",claim_token"
+ ",paid"
+ ",wired"
+ ",(session_id=$3) AS session_matches"
+ ",choice_index"
+ " FROM merchant_contract_terms"
+ " WHERE order_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_contract_terms3",
params,
(NULL != contract_terms)
? rs
diff --git a/src/backenddb/lookup_custom_units_by_names.c b/src/backenddb/lookup_custom_units_by_names.c
@@ -102,36 +102,36 @@ TALER_MERCHANTDB_lookup_custom_units_by_names (struct TALER_MERCHANTDB_PostgresC
.extract_failed = false
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_array_ptrs_string (num_units,
(const char **) units,
pg->conn),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_custom_units_by_names",
- "SELECT cu.unit_serial"
- " ,cu.unit"
- " ,cu.unit_name_long"
- " ,cu.unit_name_short"
- " ,cu.unit_name_long_i18n"
- " ,cu.unit_name_short_i18n"
- " ,cu.unit_allow_fraction"
- " ,cu.unit_precision_level"
- " ,cu.unit_active"
- " ,FALSE AS unit_builtin"
- " FROM merchant_custom_units cu"
- " WHERE cu.unit = ANY ($1)"
- " ORDER BY cu.unit");
+ PREPARE (pg,
+ "lookup_custom_units_by_names",
+ "WITH mi AS ("
+ " SELECT merchant_serial FROM merchant_instances WHERE merchant_id=$1"
+ ")"
+ "SELECT cu.unit_serial"
+ " ,cu.unit"
+ " ,cu.unit_name_long"
+ " ,cu.unit_name_short"
+ " ,cu.unit_name_long_i18n"
+ " ,cu.unit_name_short_i18n"
+ " ,cu.unit_allow_fraction"
+ " ,cu.unit_precision_level"
+ " ,cu.unit_active"
+ " ,FALSE AS unit_builtin"
+ " FROM merchant_custom_units cu"
+ " JOIN mi ON cu.merchant_serial = mi.merchant_serial"
+ " WHERE cu.unit = ANY ($2)"
+ " ORDER BY cu.unit");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_custom_units_by_names",
params,
&lookup_units_cb,
&luc);
diff --git a/src/backenddb/lookup_deposits.c b/src/backenddb/lookup_deposits.c
@@ -118,6 +118,7 @@ TALER_MERCHANTDB_lookup_deposits (
void *cb_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_end
};
@@ -127,34 +128,33 @@ TALER_MERCHANTDB_lookup_deposits (
.pg = pg
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
/* no preflight check here, run in its own transaction by the caller! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Finding deposits for h_contract_terms '%s'\n",
GNUNET_h2s (&h_contract_terms->hash));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_deposits",
- "SELECT"
- " dcom.exchange_url"
- ",dep.coin_pub"
- ",dep.amount_with_fee"
- ",dep.deposit_fee"
- ",dep.refund_fee"
- " FROM merchant_deposits dep"
- " JOIN merchant_deposit_confirmations dcom"
- " USING (deposit_confirmation_serial)"
- " WHERE dcom.order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)");
+ PREPARE (pg,
+ "lookup_deposits",
+ "SELECT"
+ " dcom.exchange_url"
+ ",dep.coin_pub"
+ ",dep.amount_with_fee"
+ ",dep.deposit_fee"
+ ",dep.refund_fee"
+ " FROM merchant_deposits dep"
+ " JOIN merchant_deposit_confirmations dcom"
+ " USING (deposit_confirmation_serial)"
+ " WHERE dcom.order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_deposits",
params,
&lookup_deposits_cb,
&ldc);
diff --git a/src/backenddb/lookup_deposits_by_contract_and_coin.c b/src/backenddb/lookup_deposits_by_contract_and_coin.c
@@ -245,6 +245,7 @@ TALER_MERCHANTDB_lookup_deposits_by_contract_and_coin (
void *cb_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_auto_from_type (coin_pub),
GNUNET_PQ_query_param_end
@@ -255,70 +256,71 @@ TALER_MERCHANTDB_lookup_deposits_by_contract_and_coin (
.pg = pg
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_refunds[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_deposits[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
/* no preflight check here, run in transaction by caller! */
TALER_LOG_DEBUG ("Looking for refund of h_contract_terms %s at `%s'\n",
GNUNET_h2s (&h_contract_terms->hash),
instance_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_refunds,
- "lookup_refunds_by_coin_and_contract",
- "SELECT"
- " refund_amount"
- " FROM merchant_refunds"
- /* Join to filter by refunds that actually
- did work, not only those we approved */
- " JOIN merchant_refund_proofs"
- " USING (refund_serial)"
- " WHERE coin_pub=$2"
- " AND order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)");
+ PREPARE (pg,
+ "lookup_refunds_by_coin_and_contract",
+ "SELECT"
+ " refund_amount"
+ " FROM merchant_refunds"
+ /* Join to filter by refunds that actually
+ did work, not only those we approved */
+ " JOIN merchant_refund_proofs"
+ " USING (refund_serial)"
+ " WHERE coin_pub=$3"
+ " AND order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt_refunds,
+ "lookup_refunds_by_coin_and_contract",
params,
&lookup_refunds_cb,
&ldcc);
if (0 > qs)
return qs;
- PREPARE_INSTANCE (pg,
- stmt_deposits,
- "lookup_deposits_by_contract_and_coin",
- "SELECT"
- " mcon.exchange_url"
- ",dep.amount_with_fee"
- ",dep.deposit_fee"
- ",dep.refund_fee"
- ",mcon.wire_fee"
- ",acc.h_wire"
- ",mcon.deposit_timestamp"
- ",mct.refund_deadline"
- ",mcon.exchange_sig"
- ",msig.exchange_pub"
- " FROM merchant_contract_terms mct"
- " JOIN merchant_deposit_confirmations mcon"
- " USING (order_serial)"
- " JOIN merchant_deposits dep"
- " USING (deposit_confirmation_serial)"
- " JOIN merchant_exchange_signing_keys msig"
- " ON (mcon.signkey_serial=msig.signkey_serial)"
- " JOIN merchant_accounts acc"
- " USING (account_serial)"
- " WHERE h_contract_terms=$1"
- " AND dep.coin_pub=$2");
+ PREPARE (pg,
+ "lookup_deposits_by_contract_and_coin",
+ "SELECT"
+ " mcon.exchange_url"
+ ",dep.amount_with_fee"
+ ",dep.deposit_fee"
+ ",dep.refund_fee"
+ ",mcon.wire_fee"
+ ",acc.h_wire"
+ ",mcon.deposit_timestamp"
+ ",mct.refund_deadline"
+ ",mcon.exchange_sig"
+ ",msig.exchange_pub"
+ " FROM merchant_contract_terms mct"
+ " JOIN merchant_deposit_confirmations mcon"
+ " USING (order_serial)"
+ " JOIN merchant_deposits dep"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_exchange_signing_keys msig"
+ " ON (mcon.signkey_serial=msig.signkey_serial)"
+ " JOIN merchant_accounts acc"
+ " USING (account_serial)"
+ " WHERE h_contract_terms=$2"
+ " AND dep.coin_pub=$3"
+ " AND mct.merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt_deposits,
+ "lookup_deposits_by_contract_and_coin",
params,
&lookup_deposits_by_contract_and_coin_cb,
&ldcc);
diff --git a/src/backenddb/lookup_deposits_by_order.c b/src/backenddb/lookup_deposits_by_order.c
@@ -135,30 +135,26 @@ TALER_MERCHANTDB_lookup_deposits_by_order (struct TALER_MERCHANTDB_PostgresConte
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_deposits_by_order",
- "SELECT"
- " dep.deposit_serial"
- ",mcon.exchange_url"
- ",acc.h_wire"
- ",mcon.deposit_timestamp"
- ",dep.amount_with_fee"
- ",dep.deposit_fee"
- ",dep.coin_pub"
- " FROM merchant_deposits dep"
- " JOIN merchant_deposit_confirmations mcon"
- " USING(deposit_confirmation_serial)"
- " JOIN merchant_accounts acc"
- " USING (account_serial)"
- " WHERE mcon.order_serial=$1");
+ PREPARE (pg,
+ "lookup_deposits_by_order",
+ "SELECT"
+ " dep.deposit_serial"
+ ",mcon.exchange_url"
+ ",acc.h_wire"
+ ",mcon.deposit_timestamp"
+ ",dep.amount_with_fee"
+ ",dep.deposit_fee"
+ ",dep.coin_pub"
+ " FROM merchant_deposits dep"
+ " JOIN merchant_deposit_confirmations mcon"
+ " USING(deposit_confirmation_serial)"
+ " JOIN merchant_accounts acc"
+ " USING (account_serial)"
+ " WHERE mcon.order_serial=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_deposits_by_order",
params,
&lookup_deposits_by_order_cb,
&ldoc);
diff --git a/src/backenddb/lookup_expected_transfer.c b/src/backenddb/lookup_expected_transfer.c
@@ -40,6 +40,7 @@ TALER_MERCHANTDB_lookup_expected_transfer (struct TALER_MERCHANTDB_PostgresConte
struct TALER_MasterPublicKeyP *master_pub)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&expected_incoming_serial),
GNUNET_PQ_query_param_end
};
@@ -66,38 +67,36 @@ TALER_MERCHANTDB_lookup_expected_transfer (struct TALER_MERCHANTDB_PostgresConte
master_pub),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
*execution_time = GNUNET_TIME_UNIT_ZERO_TS;
memset (expected_credit_amount,
0,
sizeof (*expected_credit_amount));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_expected_transfer",
- "SELECT"
- " met.expected_time"
- " ,met.confirmed"
- " ,met.expected_credit_amount"
- " ,met.exchange_url"
- " ,met.wtid"
- " ,ma.payto_uri"
- " ,mts.execution_time"
- " ,esk.master_pub"
- " FROM merchant_expected_transfers met"
- " JOIN merchant_exchange_signing_keys esk"
- " USING (signkey_serial)"
- " JOIN merchant_accounts ma"
- " USING (account_serial)"
- " LEFT JOIN merchant_transfer_signatures mts"
- " USING (expected_credit_serial)"
- " WHERE met.expected_credit_serial=$1");
+ PREPARE (pg,
+ "lookup_expected_transfer",
+ "SELECT"
+ " met.expected_time"
+ " ,met.confirmed"
+ " ,met.expected_credit_amount"
+ " ,met.exchange_url"
+ " ,met.wtid"
+ " ,ma.payto_uri"
+ " ,mts.execution_time"
+ " ,esk.master_pub"
+ " FROM merchant_expected_transfers met"
+ " JOIN merchant_exchange_signing_keys esk"
+ " USING (signkey_serial)"
+ " JOIN merchant_accounts ma"
+ " USING (account_serial)"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ " LEFT JOIN merchant_transfer_signatures mts"
+ " USING (expected_credit_serial)"
+ " WHERE inst.merchant_id=$1"
+ " AND met.expected_credit_serial=$2");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_expected_transfer",
params,
rs);
}
diff --git a/src/backenddb/lookup_expected_transfers.c b/src/backenddb/lookup_expected_transfers.c
@@ -171,6 +171,7 @@ TALER_MERCHANTDB_lookup_expected_transfers (struct TALER_MERCHANTDB_PostgresCont
.pg = pg
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_timestamp (&before),
GNUNET_PQ_query_param_timestamp (&after),
GNUNET_PQ_query_param_uint64 (&offset),
@@ -178,7 +179,7 @@ TALER_MERCHANTDB_lookup_expected_transfers (struct TALER_MERCHANTDB_PostgresCont
NULL == payto_uri.full_payto
? GNUNET_PQ_query_param_null () /* NULL: do not filter by payto URI */
: GNUNET_PQ_query_param_string (payto_uri.full_payto),
- GNUNET_PQ_query_param_bool (! by_time), /* $6: filter by time? */
+ GNUNET_PQ_query_param_bool (! by_time), /* $7: filter by time? */
GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_ALL == confirmed), /* filter by confirmed? */
GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_YES == confirmed),
GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_ALL == verified), /* filter by verified? */
@@ -187,84 +188,87 @@ TALER_MERCHANTDB_lookup_expected_transfers (struct TALER_MERCHANTDB_PostgresCont
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "lookup_expected_transfers_asc",
- "SELECT"
- " met.expected_credit_amount"
- ",met.wtid"
- ",mac.payto_uri"
- ",met.exchange_url"
- ",met.expected_credit_serial"
- ",mts.execution_time"
- ",met.confirmed"
- ",met.last_http_status"
- ",met.last_ec"
- ",met.last_detail"
- " FROM merchant_expected_transfers met"
- " JOIN merchant_accounts mac"
- " USING (account_serial)"
- " LEFT JOIN merchant_transfer_signatures mts"
- " USING (expected_credit_serial)"
- " WHERE ( $6 OR "
- " (mts.execution_time IS NOT NULL AND"
- " mts.execution_time < $1 AND"
- " mts.execution_time >= $2) )"
- " AND ( (CAST($5 AS TEXT) IS NULL) OR "
- " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
- " =REGEXP_REPLACE($5,'\\?.*','')) )"
- " AND ( $7 OR "
- " (met.confirmed = $8) )"
- " AND ( $9 OR "
- " ($10 = (200=met.last_http_status) AND"
- " (0=met.last_ec) ) )"
- " AND (met.expected_credit_serial > $3)"
- " ORDER BY met.expected_credit_serial ASC"
- " LIMIT $4");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_expected_transfers_desc",
- "SELECT"
- " met.expected_credit_amount"
- ",met.wtid"
- ",mac.payto_uri"
- ",met.exchange_url"
- ",met.expected_credit_serial"
- ",mts.execution_time"
- ",met.confirmed"
- ",met.last_http_status"
- ",met.last_ec"
- ",met.last_detail"
- " FROM merchant_expected_transfers met"
- " JOIN merchant_accounts mac"
- " USING (account_serial)"
- " LEFT JOIN merchant_transfer_signatures mts"
- " USING (expected_credit_serial)"
- " WHERE ( $6 OR "
- " (mts.execution_time IS NOT NULL AND"
- " mts.execution_time < $1 AND"
- " mts.execution_time >= $2) )"
- " AND ( (CAST($5 AS TEXT) IS NULL) OR "
- " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
- " =REGEXP_REPLACE($5,'\\?.*','')) )"
- " AND ( $7 OR "
- " (met.confirmed = $8) )"
- " AND ( $9 OR "
- " ($10 = (200=met.last_http_status) AND"
- " (0=met.last_ec) ) )"
- " AND (met.expected_credit_serial < $3)"
- " ORDER BY met.expected_credit_serial DESC"
- " LIMIT $4");
+ PREPARE (pg,
+ "lookup_expected_transfers_asc",
+ "SELECT"
+ " met.expected_credit_amount"
+ ",met.wtid"
+ ",mac.payto_uri"
+ ",met.exchange_url"
+ ",met.expected_credit_serial"
+ ",mts.execution_time"
+ ",met.confirmed"
+ ",met.last_http_status"
+ ",met.last_ec"
+ ",met.last_detail"
+ " FROM merchant_expected_transfers met"
+ " JOIN merchant_accounts mac"
+ " USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures mts"
+ " USING (expected_credit_serial)"
+ " WHERE ( $7 OR "
+ " (mts.execution_time IS NOT NULL AND"
+ " mts.execution_time < $2 AND"
+ " mts.execution_time >= $3) )"
+ " AND ( (CAST($6 AS TEXT) IS NULL) OR "
+ " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
+ " =REGEXP_REPLACE($6,'\\?.*','')) )"
+ " AND ( $8 OR "
+ " (met.confirmed = $9) )"
+ " AND ( $10 OR "
+ " ($11 = (200=met.last_http_status) AND"
+ " (0=met.last_ec) ) )"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND (met.expected_credit_serial > $4)"
+ " ORDER BY met.expected_credit_serial ASC"
+ " LIMIT $5");
+ PREPARE (pg,
+ "lookup_expected_transfers_desc",
+ "SELECT"
+ " met.expected_credit_amount"
+ ",met.wtid"
+ ",mac.payto_uri"
+ ",met.exchange_url"
+ ",met.expected_credit_serial"
+ ",mts.execution_time"
+ ",met.confirmed"
+ ",met.last_http_status"
+ ",met.last_ec"
+ ",met.last_detail"
+ " FROM merchant_expected_transfers met"
+ " JOIN merchant_accounts mac"
+ " USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures mts"
+ " USING (expected_credit_serial)"
+ " WHERE ( $7 OR "
+ " (mts.execution_time IS NOT NULL AND"
+ " mts.execution_time < $2 AND"
+ " mts.execution_time >= $3) )"
+ " AND ( (CAST($6 AS TEXT) IS NULL) OR "
+ " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
+ " =REGEXP_REPLACE($6,'\\?.*','')) )"
+ " AND ( $8 OR "
+ " (met.confirmed = $9) )"
+ " AND ( $10 OR "
+ " ($11 = (200=met.last_http_status) AND"
+ " (0=met.last_ec) ) )"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND (met.expected_credit_serial < $4)"
+ " ORDER BY met.expected_credit_serial DESC"
+ " LIMIT $5");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- (limit > 0) ? stmt_asc : stmt_desc,
+ (limit > 0)
+ ? "lookup_expected_transfers_asc"
+ : "lookup_expected_transfers_desc",
params,
&lookup_expected_transfers_cb,
<c);
diff --git a/src/backenddb/lookup_instances.c b/src/backenddb/lookup_instances.c
@@ -80,61 +80,61 @@ lookup_instances_cb (void *cls,
bool no_priv;
char *dwtri;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("out_merchant_serial",
+ GNUNET_PQ_result_spec_uint64 ("merchant_serial",
&instance_serial),
- GNUNET_PQ_result_spec_auto_from_type ("out_merchant_pub",
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
&merchant_pub),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("out_auth_hash",
+ GNUNET_PQ_result_spec_auto_from_type ("auth_hash",
&ias.auth_hash),
&no_auth),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("out_auth_salt",
+ GNUNET_PQ_result_spec_auto_from_type ("auth_salt",
&ias.auth_salt),
&no_salt),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("out_merchant_priv",
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
&merchant_priv),
&no_priv),
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("merchant_id",
&is.id),
- GNUNET_PQ_result_spec_string ("out_merchant_name",
+ GNUNET_PQ_result_spec_string ("merchant_name",
&is.name),
- TALER_PQ_result_spec_json ("out_address",
+ TALER_PQ_result_spec_json ("address",
&is.address),
- TALER_PQ_result_spec_json ("out_jurisdiction",
+ TALER_PQ_result_spec_json ("jurisdiction",
&is.jurisdiction),
- GNUNET_PQ_result_spec_bool ("out_use_stefan",
+ GNUNET_PQ_result_spec_bool ("use_stefan",
&is.use_stefan),
- GNUNET_PQ_result_spec_bool ("out_phone_validated",
+ GNUNET_PQ_result_spec_bool ("phone_validated",
&is.phone_validated),
- GNUNET_PQ_result_spec_bool ("out_email_validated",
+ GNUNET_PQ_result_spec_bool ("email_validated",
&is.email_validated),
GNUNET_PQ_result_spec_relative_time (
- "out_default_wire_transfer_delay",
+ "default_wire_transfer_delay",
&is.default_wire_transfer_delay),
- GNUNET_PQ_result_spec_relative_time ("out_default_pay_delay",
+ GNUNET_PQ_result_spec_relative_time ("default_pay_delay",
&is.default_pay_delay),
- GNUNET_PQ_result_spec_relative_time ("out_default_refund_delay",
+ GNUNET_PQ_result_spec_relative_time ("default_refund_delay",
&is.default_refund_delay),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_website",
+ GNUNET_PQ_result_spec_string ("website",
&is.website),
NULL),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_email",
+ GNUNET_PQ_result_spec_string ("email",
&is.email),
NULL),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_phone_number",
+ GNUNET_PQ_result_spec_string ("phone_number",
&is.phone),
NULL),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_logo",
+ GNUNET_PQ_result_spec_string ("logo",
&is.logo),
NULL),
GNUNET_PQ_result_spec_string (
- "out_default_wire_transfer_rounding_interval",
+ "default_wire_transfer_rounding_interval",
&dwtri),
GNUNET_PQ_result_spec_end
};
@@ -186,8 +186,6 @@ TALER_MERCHANTDB_lookup_instances (
.pg = pg
};
struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_bool (active_only),
- GNUNET_PQ_query_param_null (),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
@@ -196,30 +194,60 @@ TALER_MERCHANTDB_lookup_instances (
PREPARE (pg,
"lookup_instances",
"SELECT"
- " out_merchant_serial"
- " ,out_merchant_pub"
- " ,out_auth_hash"
- " ,out_auth_salt"
- " ,out_merchant_priv"
- " ,out_merchant_id"
- " ,out_merchant_name"
- " ,out_address::TEXT"
- " ,out_jurisdiction::TEXT"
- " ,out_use_stefan"
- " ,out_phone_validated"
- " ,out_email_validated"
- " ,out_default_wire_transfer_delay"
- " ,out_default_pay_delay"
- " ,out_default_refund_delay"
- " ,out_website"
- " ,out_email"
- " ,out_phone_number"
- " ,out_logo"
- " ,out_default_wire_transfer_rounding_interval::TEXT"
- " FROM merchant.lookup_instances($1, $2)");
+ " mi.merchant_serial"
+ ",mi.merchant_pub"
+ ",mi.auth_hash"
+ ",mi.auth_salt"
+ ",mi.merchant_id"
+ ",mi.merchant_name"
+ ",mi.address::TEXT"
+ ",mi.jurisdiction::TEXT"
+ ",mi.use_stefan"
+ ",mi.default_wire_transfer_delay"
+ ",mi.default_pay_delay"
+ ",mi.default_refund_delay"
+ ",mi.website"
+ ",mi.email"
+ ",mi.phone_number"
+ ",mi.phone_validated"
+ ",mi.email_validated"
+ ",mi.logo"
+ ",mi.default_wire_transfer_rounding_interval::TEXT"
+ ",mk.merchant_priv"
+ " FROM merchant_instances mi"
+ " LEFT JOIN merchant_keys mk"
+ " USING (merchant_serial)");
+ PREPARE (pg,
+ "lookup_active_instances",
+ "SELECT "
+ " mi.merchant_serial"
+ ",mi.merchant_pub"
+ ",mi.auth_hash"
+ ",mi.auth_salt"
+ ",mi.merchant_id"
+ ",mi.merchant_name"
+ ",mi.address::TEXT"
+ ",mi.jurisdiction::TEXT"
+ ",mi.use_stefan"
+ ",mi.default_wire_transfer_delay"
+ ",mi.default_pay_delay"
+ ",mi.default_refund_delay"
+ ",mi.website"
+ ",mi.email"
+ ",mi.phone_number"
+ ",mi.phone_validated"
+ ",mi.email_validated"
+ ",mi.logo"
+ ",mi.default_wire_transfer_rounding_interval::TEXT"
+ ",mk.merchant_priv"
+ " FROM merchant_instances mi"
+ " JOIN merchant_keys mk"
+ " USING (merchant_serial)");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- "lookup_instances",
+ active_only
+ ? "lookup_active_instances"
+ : "lookup_instances",
params,
&lookup_instances_cb,
&lic);
@@ -242,7 +270,6 @@ TALER_MERCHANTDB_lookup_instance (struct TALER_MERCHANTDB_PostgresContext *pg,
.pg = pg
};
struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_bool (active_only),
GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_end
};
@@ -252,30 +279,62 @@ TALER_MERCHANTDB_lookup_instance (struct TALER_MERCHANTDB_PostgresContext *pg,
PREPARE (pg,
"lookup_instance",
"SELECT"
- " out_merchant_serial"
- " ,out_merchant_pub"
- " ,out_auth_hash"
- " ,out_auth_salt"
- " ,out_merchant_priv"
- " ,out_merchant_id"
- " ,out_merchant_name"
- " ,out_address::TEXT"
- " ,out_jurisdiction::TEXT"
- " ,out_use_stefan"
- " ,out_phone_validated"
- " ,out_email_validated"
- " ,out_default_wire_transfer_delay"
- " ,out_default_pay_delay"
- " ,out_default_refund_delay"
- " ,out_website"
- " ,out_email"
- " ,out_phone_number"
- " ,out_logo"
- " ,out_default_wire_transfer_rounding_interval::TEXT"
- " FROM merchant.lookup_instances($1, $2)");
+ " mi.merchant_serial"
+ ",mi.merchant_pub"
+ ",mi.auth_hash"
+ ",mi.auth_salt"
+ ",mi.merchant_id"
+ ",mi.merchant_name"
+ ",mi.address::TEXT"
+ ",mi.jurisdiction::TEXT"
+ ",mi.use_stefan"
+ ",mi.default_wire_transfer_delay"
+ ",mi.default_pay_delay"
+ ",mi.default_refund_delay"
+ ",mi.website"
+ ",mi.email"
+ ",mi.phone_number"
+ ",mi.phone_validated"
+ ",mi.email_validated"
+ ",mi.logo"
+ ",mi.default_wire_transfer_rounding_interval::TEXT"
+ ",mk.merchant_priv"
+ " FROM merchant_instances mi"
+ " LEFT JOIN merchant_keys mk"
+ " USING (merchant_serial)"
+ " WHERE merchant_id=$1");
+ PREPARE (pg,
+ "lookup_active_instance",
+ "SELECT"
+ " mi.merchant_serial"
+ ",mi.merchant_pub"
+ ",mi.auth_hash"
+ ",mi.auth_salt"
+ ",mi.merchant_id"
+ ",mi.merchant_name"
+ ",mi.address::TEXT"
+ ",mi.jurisdiction::TEXT"
+ ",mi.use_stefan"
+ ",mi.default_wire_transfer_delay"
+ ",mi.default_pay_delay"
+ ",mi.default_refund_delay"
+ ",mi.website"
+ ",mi.email"
+ ",mi.phone_number"
+ ",mi.phone_validated"
+ ",mi.email_validated"
+ ",mi.logo"
+ ",mi.default_wire_transfer_rounding_interval::TEXT"
+ ",mk.merchant_priv"
+ " FROM merchant_instances mi"
+ " JOIN merchant_keys mk"
+ " USING (merchant_serial)"
+ " WHERE merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- "lookup_instance",
+ active_only
+ ? "lookup_active_instance"
+ : "lookup_instance",
params,
&lookup_instances_cb,
&lic);
diff --git a/src/backenddb/lookup_inventory_products.c b/src/backenddb/lookup_inventory_products.c
@@ -145,75 +145,74 @@ TALER_MERCHANTDB_lookup_inventory_products (
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_inventory_products",
- "SELECT"
- " description"
- ",description_i18n::TEXT"
- ",product_name"
- ",unit"
- ",price_array"
- ",CASE WHEN minv.total_stock = 9223372036854775807"
- " THEN minv.total_stock"
- " ELSE (GREATEST(0, rt.remaining_total) / 1000000)::INT8"
- " END AS remaining_stock"
- ",CASE WHEN minv.total_stock = 9223372036854775807"
- " THEN 2147483647"
- " ELSE mod(GREATEST(0, rt.remaining_total), 1000000)::INT4"
- " END AS remaining_stock_frac"
- ",taxes::TEXT"
- ",image_hash"
- ",allow_fractional_quantity"
- ",fractional_precision_level"
- ",product_id"
- ",t.category_array AS categories"
- " FROM merchant_inventory minv"
- ",LATERAL ("
- " SELECT ARRAY ("
- " SELECT mpc.category_serial"
- " FROM merchant_product_categories mpc"
- " WHERE mpc.product_serial = minv.product_serial"
- " ) AS category_array"
- " ) t"
- ",LATERAL ("
- " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " AS total_locked"
- " FROM merchant_inventory_locks mil"
- " WHERE mil.product_serial = minv.product_serial"
- " ) il"
- ",LATERAL ("
- " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " AS total_locked"
- " FROM merchant_order_locks mol"
- " WHERE mol.product_serial = minv.product_serial"
- " ) ol"
- ",LATERAL ("
- " SELECT"
- " (minv.total_stock::NUMERIC * 1000000"
- " + minv.total_stock_frac::NUMERIC)"
- " - (minv.total_sold::NUMERIC * 1000000"
- " + minv.total_sold_frac::NUMERIC)"
- " - (minv.total_lost::NUMERIC * 1000000"
- " + minv.total_lost_frac::NUMERIC)"
- " - il.total_locked"
- " - ol.total_locked"
- " AS remaining_total"
- " ) rt");
+ PREPARE (pg,
+ "lookup_inventory_products",
+ "SELECT"
+ " description"
+ ",description_i18n::TEXT"
+ ",product_name"
+ ",unit"
+ ",price_array"
+ ",CASE WHEN minv.total_stock = 9223372036854775807"
+ " THEN minv.total_stock"
+ " ELSE (GREATEST(0, rt.remaining_total) / 1000000)::INT8"
+ " END AS remaining_stock"
+ ",CASE WHEN minv.total_stock = 9223372036854775807"
+ " THEN 2147483647"
+ " ELSE mod(GREATEST(0, rt.remaining_total), 1000000)::INT4"
+ " END AS remaining_stock_frac"
+ ",taxes::TEXT"
+ ",image_hash"
+ ",allow_fractional_quantity"
+ ",fractional_precision_level"
+ ",product_id"
+ ",t.category_array AS categories"
+ " FROM merchant_inventory minv"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ ",LATERAL ("
+ " SELECT ARRAY ("
+ " SELECT mpc.category_serial"
+ " FROM merchant_product_categories mpc"
+ " WHERE mpc.product_serial = minv.product_serial"
+ " ) AS category_array"
+ " ) t"
+ ",LATERAL ("
+ " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " AS total_locked"
+ " FROM merchant_inventory_locks mil"
+ " WHERE mil.product_serial = minv.product_serial"
+ " ) il"
+ ",LATERAL ("
+ " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " AS total_locked"
+ " FROM merchant_order_locks mol"
+ " WHERE mol.product_serial = minv.product_serial"
+ " ) ol"
+ ",LATERAL ("
+ " SELECT"
+ " (minv.total_stock::NUMERIC * 1000000"
+ " + minv.total_stock_frac::NUMERIC)"
+ " - (minv.total_sold::NUMERIC * 1000000"
+ " + minv.total_sold_frac::NUMERIC)"
+ " - (minv.total_lost::NUMERIC * 1000000"
+ " + minv.total_lost_frac::NUMERIC)"
+ " - il.total_locked"
+ " - ol.total_locked"
+ " AS remaining_total"
+ " ) rt"
+ " WHERE inst.merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_inventory_products",
params,
&lookup_inventory_products_cb,
&plc);
diff --git a/src/backenddb/lookup_inventory_products_filtered.c b/src/backenddb/lookup_inventory_products_filtered.c
@@ -142,6 +142,7 @@ TALER_MERCHANTDB_lookup_inventory_products_filtered (
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
(0 == num_product_ids)
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_array_ptrs_string (
@@ -156,84 +157,82 @@ TALER_MERCHANTDB_lookup_inventory_products_filtered (
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_inventory_products_filtered",
- "SELECT"
- " description"
- ",description_i18n::TEXT"
- ",product_name"
- ",unit"
- ",price_array"
- ",CASE WHEN minv.total_stock = 9223372036854775807"
- " THEN minv.total_stock"
- " ELSE (GREATEST(0, rt.remaining_total) / 1000000)::INT8"
- " END AS remaining_stock"
- ",CASE WHEN minv.total_stock = 9223372036854775807"
- " THEN 2147483647"
- " ELSE mod(GREATEST(0, rt.remaining_total), 1000000)::INT4"
- " END AS remaining_stock_frac"
- ",taxes::TEXT"
- ",image_hash"
- ",allow_fractional_quantity"
- ",fractional_precision_level"
- ",product_id"
- ",t.category_array AS categories"
- " FROM merchant_inventory minv"
- ",LATERAL ("
- " SELECT ARRAY ("
- " SELECT mpc.category_serial"
- " FROM merchant_product_categories mpc"
- " WHERE mpc.product_serial = minv.product_serial"
- " ) AS category_array"
- " ) t"
- ",LATERAL ("
- " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " AS total_locked"
- " FROM merchant_inventory_locks mil"
- " WHERE mil.product_serial = minv.product_serial"
- " ) il"
- ",LATERAL ("
- " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
- " + total_locked_frac::NUMERIC), 0)"
- " AS total_locked"
- " FROM merchant_order_locks mol"
- " WHERE mol.product_serial = minv.product_serial"
- " ) ol"
- ",LATERAL ("
- " SELECT"
- " (minv.total_stock::NUMERIC * 1000000"
- " + minv.total_stock_frac::NUMERIC)"
- " - (minv.total_sold::NUMERIC * 1000000"
- " + minv.total_sold_frac::NUMERIC)"
- " - (minv.total_lost::NUMERIC * 1000000"
- " + minv.total_lost_frac::NUMERIC)"
- " - il.total_locked"
- " - ol.total_locked"
- " AS remaining_total"
- " ) rt"
- " WHERE ("
- " (COALESCE (array_length ($1::TEXT[], 1), 0) > 0"
- " AND minv.product_id = ANY ($1::TEXT[]))"
- " OR"
- " (COALESCE (array_length ($2::BIGINT[], 1), 0) > 0"
- " AND EXISTS ("
- " SELECT 1"
- " FROM merchant_product_categories mpc"
- " WHERE mpc.product_serial = minv.product_serial"
- " AND mpc.category_serial = ANY ($2::BIGINT[])"
- " ))"
- " )");
+ PREPARE (pg,
+ "lookup_inventory_products_filtered",
+ "SELECT"
+ " description"
+ ",description_i18n::TEXT"
+ ",product_name"
+ ",unit"
+ ",price_array"
+ ",CASE WHEN minv.total_stock = 9223372036854775807"
+ " THEN minv.total_stock"
+ " ELSE (GREATEST(0, rt.remaining_total) / 1000000)::INT8"
+ " END AS remaining_stock"
+ ",CASE WHEN minv.total_stock = 9223372036854775807"
+ " THEN 2147483647"
+ " ELSE mod(GREATEST(0, rt.remaining_total), 1000000)::INT4"
+ " END AS remaining_stock_frac"
+ ",taxes::TEXT"
+ ",image_hash"
+ ",allow_fractional_quantity"
+ ",fractional_precision_level"
+ ",product_id"
+ ",t.category_array AS categories"
+ " FROM merchant_inventory minv"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ ",LATERAL ("
+ " SELECT ARRAY ("
+ " SELECT mpc.category_serial"
+ " FROM merchant_product_categories mpc"
+ " WHERE mpc.product_serial = minv.product_serial"
+ " ) AS category_array"
+ " ) t"
+ ",LATERAL ("
+ " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " AS total_locked"
+ " FROM merchant_inventory_locks mil"
+ " WHERE mil.product_serial = minv.product_serial"
+ " ) il"
+ ",LATERAL ("
+ " SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000"
+ " + total_locked_frac::NUMERIC), 0)"
+ " AS total_locked"
+ " FROM merchant_order_locks mol"
+ " WHERE mol.product_serial = minv.product_serial"
+ " ) ol"
+ ",LATERAL ("
+ " SELECT"
+ " (minv.total_stock::NUMERIC * 1000000"
+ " + minv.total_stock_frac::NUMERIC)"
+ " - (minv.total_sold::NUMERIC * 1000000"
+ " + minv.total_sold_frac::NUMERIC)"
+ " - (minv.total_lost::NUMERIC * 1000000"
+ " + minv.total_lost_frac::NUMERIC)"
+ " - il.total_locked"
+ " - ol.total_locked"
+ " AS remaining_total"
+ " ) rt"
+ " WHERE inst.merchant_id=$1"
+ " AND ("
+ " (COALESCE (array_length ($2::TEXT[], 1), 0) > 0"
+ " AND minv.product_id = ANY ($2::TEXT[]))"
+ " OR"
+ " (COALESCE (array_length ($3::BIGINT[], 1), 0) > 0"
+ " AND EXISTS ("
+ " SELECT 1"
+ " FROM merchant_product_categories mpc"
+ " WHERE mpc.product_serial = minv.product_serial"
+ " AND mpc.category_serial = ANY ($3::BIGINT[])"
+ " ))"
+ " )");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_inventory_products_filtered",
params,
&lookup_inventory_products_cb,
&plc);
diff --git a/src/backenddb/lookup_login_tokens.c b/src/backenddb/lookup_login_tokens.c
@@ -123,52 +123,54 @@ TALER_MERCHANTDB_lookup_login_tokens (struct TALER_MERCHANTDB_PostgresContext *p
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_timestamp (&now),
GNUNET_PQ_query_param_uint64 (&offset),
GNUNET_PQ_query_param_uint64 (&plimit),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "lookup_login_tokens_asc",
- "SELECT"
- " token"
- ",serial"
- ",creation_time"
- ",expiration_time"
- ",validity_scope"
- ",description"
- " FROM merchant_login_tokens"
- " WHERE expiration_time > $1"
- " AND serial > $2"
- " ORDER BY serial ASC"
- " LIMIT $3");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_login_tokens_desc",
- "SELECT"
- " token"
- ",serial"
- ",creation_time"
- ",expiration_time"
- ",validity_scope"
- ",description"
- " FROM merchant_login_tokens"
- " WHERE expiration_time > $1"
- " AND serial < $2"
- " ORDER BY serial DESC"
- " LIMIT $3");
+ PREPARE (pg,
+ "lookup_login_tokens_asc",
+ "SELECT"
+ " token"
+ ",serial"
+ ",creation_time"
+ ",expiration_time"
+ ",validity_scope"
+ ",description"
+ " FROM merchant_login_tokens"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND expiration_time > $2"
+ " AND serial > $3"
+ " ORDER BY serial ASC"
+ " LIMIT $4");
+ PREPARE (pg,
+ "lookup_login_tokens_desc",
+ "SELECT"
+ " token"
+ ",serial"
+ ",creation_time"
+ ",expiration_time"
+ ",validity_scope"
+ ",description"
+ " FROM merchant_login_tokens"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND expiration_time > $2"
+ " AND serial < $3"
+ " ORDER BY serial DESC"
+ " LIMIT $4");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- (limit > 0) ? stmt_asc : stmt_desc,
+ (limit > 0)
+ ? "lookup_login_tokens_asc"
+ : "lookup_login_tokens_desc",
params,
&lookup_login_tokens_cb,
&plc);
diff --git a/src/backenddb/lookup_mfa_challenge.c b/src/backenddb/lookup_mfa_challenge.c
@@ -69,38 +69,39 @@ TALER_MERCHANTDB_lookup_mfa_challenge (
&chan_str),
GNUNET_PQ_result_spec_string ("required_address",
required_address),
+ GNUNET_PQ_result_spec_string ("merchant_id",
+ instance_name),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_mfa_challenge",
- "SELECT "
- " op::TEXT"
- " ,salt"
- " ,confirmation_date"
- " ,retransmission_date"
- " ,retry_counter"
- " ,required_address"
- " ,tan_channel::TEXT"
- " FROM tan_challenges"
- " WHERE (challenge_id = $1)"
- " AND (h_body = $2)"
- " AND (expiration_date > $3)");
+ PREPARE (pg,
+ "lookup_mfa_challenge",
+ "SELECT "
+ " tc.op::TEXT"
+ " ,tc.salt"
+ " ,tc.confirmation_date"
+ " ,tc.retransmission_date"
+ " ,tc.retry_counter"
+ " ,tc.required_address"
+ " ,tc.tan_channel::TEXT"
+ " ,mi.merchant_id"
+ " FROM tan_challenges tc"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE (challenge_id = $1)"
+ " AND (h_body = $2)"
+ " AND (expiration_date > $3)");
/* Initialize to conservative values in case qs ends up <= 0 */
*tan_channel = TALER_MERCHANT_MFA_CHANNEL_NONE;
*op = TALER_MERCHANT_MFA_CO_NONE;
*retry_counter = 0;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_mfa_challenge",
params,
rs);
if (qs <= 0)
return qs;
- *instance_name = GNUNET_strdup (pg->current_merchant_id);
if (no_conf)
*confirmation_date = GNUNET_TIME_UNIT_FOREVER_ABS;
*tan_channel = TALER_MERCHANT_MFA_channel_from_string (chan_str);
diff --git a/src/backenddb/lookup_order.c b/src/backenddb/lookup_order.c
@@ -39,6 +39,7 @@ TALER_MERCHANTDB_lookup_order (
struct TALER_ClaimTokenP ct;
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
@@ -51,27 +52,26 @@ TALER_MERCHANTDB_lookup_order (
h_post_data),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Finding contract term, order_id: '%s', instance_id: '%s'.\n",
order_id,
instance_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_order",
- "SELECT"
- " contract_terms::TEXT"
- ",claim_token"
- ",h_post_data"
- " FROM merchant_orders"
- " WHERE order_id=$1");
+ PREPARE (pg,
+ "lookup_order",
+ "SELECT"
+ " contract_terms::TEXT"
+ ",claim_token"
+ ",h_post_data"
+ " FROM merchant_orders"
+ " WHERE merchant_orders.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_orders.order_id=$2");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_order",
params,
rs);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
diff --git a/src/backenddb/lookup_order_by_fulfillment.c b/src/backenddb/lookup_order_by_fulfillment.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_lookup_order_by_fulfillment (struct TALER_MERCHANTDB_PostgresCo
char **order_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (fulfillment_url),
GNUNET_PQ_query_param_string (session_id),
GNUNET_PQ_query_param_bool (allow_refunded_for_repurchase),
@@ -45,34 +46,33 @@ TALER_MERCHANTDB_lookup_order_by_fulfillment (struct TALER_MERCHANTDB_PostgresCo
order_id),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_order_by_fulfillment",
- "SELECT"
- " mct.order_id"
- " FROM merchant_contract_terms mct"
- " LEFT JOIN merchant_refunds mref"
- " USING (order_serial)"
- " WHERE fulfillment_url=$1"
- " AND session_id=$2"
- " AND ((CAST($3 AS BOOL)) OR"
- " mref.refund_serial IS NULL)"
- /* Theoretically, multiple paid orders
- for the same fulfillment URL could
- exist for this session_id -- if a
- wallet was broken and did multiple
- payments without repurchase detection.
- So we need to limit to 1 when returning! */
- " ORDER BY order_id DESC"
- " LIMIT 1;");
+ PREPARE (pg,
+ "lookup_order_by_fulfillment",
+ "SELECT"
+ " mct.order_id"
+ " FROM merchant_contract_terms mct"
+ " LEFT JOIN merchant_refunds mref"
+ " USING (order_serial)"
+ " WHERE fulfillment_url=$2"
+ " AND session_id=$3"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND ((CAST($4 AS BOOL)) OR"
+ " mref.refund_serial IS NULL)"
+ /* Theoretically, multiple paid orders
+ for the same fulfillment URL could
+ exist for this session_id -- if a
+ wallet was broken and did multiple
+ payments without repurchase detection.
+ So we need to limit to 1 when returning! */
+ " ORDER BY order_id DESC"
+ " LIMIT 1;");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_order_by_fulfillment",
params,
rs);
}
diff --git a/src/backenddb/lookup_order_charity.c b/src/backenddb/lookup_order_charity.c
@@ -47,6 +47,7 @@ TALER_MERCHANTDB_lookup_order_charity (
uint64_t *donau_instance_serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (donau_url),
GNUNET_PQ_query_param_end
};
@@ -66,30 +67,29 @@ TALER_MERCHANTDB_lookup_order_charity (
donau_instance_serial),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_donau_charity",
- "SELECT"
- " di.donau_instances_serial"
- " ,di.charity_id"
- " ,k.merchant_priv"
- " ,dk.keys_json::TEXT"
- " ,di.charity_max_per_year"
- " ,di.charity_receipts_to_date"
- " FROM merchant_donau_instances di"
- " JOIN merchant_donau_keys dk"
- " ON dk.donau_url = di.donau_url"
- " CROSS JOIN merchant_keys k"
- " WHERE di.donau_url = $1;");
+ PREPARE (pg,
+ "lookup_donau_charity",
+ "SELECT"
+ " di.donau_instances_serial"
+ " ,di.charity_id"
+ " ,k.merchant_priv"
+ " ,dk.keys_json::TEXT"
+ " ,di.charity_max_per_year"
+ " ,di.charity_receipts_to_date"
+ " FROM merchant_donau_instances di"
+ " JOIN merchant_donau_keys dk"
+ " ON dk.donau_url = di.donau_url"
+ " JOIN merchant_instances mi"
+ " ON mi.merchant_serial = di.merchant_instance_serial"
+ " JOIN merchant_keys k"
+ " ON k.merchant_serial = mi.merchant_serial"
+ " WHERE mi.merchant_id = $1"
+ " AND di.donau_url = $2;");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_donau_charity",
params,
rs);
}
diff --git a/src/backenddb/lookup_order_status.c b/src/backenddb/lookup_order_status.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_lookup_order_status (struct TALER_MERCHANTDB_PostgresContext *p
uint8_t paid8;
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
@@ -45,22 +46,21 @@ TALER_MERCHANTDB_lookup_order_status (struct TALER_MERCHANTDB_PostgresContext *p
&paid8),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_order_status",
- "SELECT"
- " h_contract_terms"
- ",paid"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1");
+ PREPARE (pg,
+ "lookup_order_status",
+ "SELECT"
+ " h_contract_terms"
+ ",paid"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND order_id=$2");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_order_status",
params,
rs);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
diff --git a/src/backenddb/lookup_order_status_by_serial.c b/src/backenddb/lookup_order_status_by_serial.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_lookup_order_status_by_serial (struct TALER_MERCHANTDB_Postgres
bool *paid)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&order_serial),
GNUNET_PQ_query_param_end
};
@@ -46,24 +47,23 @@ TALER_MERCHANTDB_lookup_order_status_by_serial (struct TALER_MERCHANTDB_Postgres
paid),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
*paid = false; /* just to be safe(r) */
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_order_status_by_serial",
- "SELECT"
- " h_contract_terms"
- ",order_id"
- ",paid"
- " FROM merchant_contract_terms"
- " WHERE order_serial=$1");
+ PREPARE (pg,
+ "lookup_order_status_by_serial",
+ "SELECT"
+ " h_contract_terms"
+ ",order_id"
+ ",paid"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND order_serial=$2");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_order_status_by_serial",
params,
rs);
}
diff --git a/src/backenddb/lookup_order_summary.c b/src/backenddb/lookup_order_summary.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_lookup_order_summary (struct TALER_MERCHANTDB_PostgresContext *
uint64_t *order_serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
GNUNET_PQ_query_param_end
};
@@ -43,28 +44,31 @@ TALER_MERCHANTDB_lookup_order_summary (struct TALER_MERCHANTDB_PostgresContext *
timestamp),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_order_summary",
- "(SELECT"
- " creation_time"
- ",order_serial"
- " FROM merchant_contract_terms"
- " WHERE order_id=$1)"
- "UNION"
- "(SELECT"
- " creation_time"
- ",order_serial"
- " FROM merchant_orders"
- " WHERE order_id=$1)");
+ PREPARE (pg,
+ "lookup_order_summary",
+ "(SELECT"
+ " creation_time"
+ ",order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_contract_terms.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_contract_terms.order_id=$2)"
+ "UNION"
+ "(SELECT"
+ " creation_time"
+ ",order_serial"
+ " FROM merchant_orders"
+ " WHERE merchant_orders.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND merchant_orders.order_id=$2)");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_order_summary",
params,
rs);
}
diff --git a/src/backenddb/lookup_orders.c b/src/backenddb/lookup_orders.c
@@ -111,17 +111,18 @@ TALER_MERCHANTDB_lookup_orders (
uint64_t limit = (of->delta > 0) ? of->delta : -of->delta;
struct GNUNET_PQ_QueryParam params[] = {
/* $1 */
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&limit),
GNUNET_PQ_query_param_uint64 (&of->start_row),
GNUNET_PQ_query_param_timestamp (&of->date),
GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == of->paid)),
- /* $5 */
+ /* $6 */
GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == of->paid)),
GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == of->refunded)),
GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == of->refunded)),
GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == of->wired)),
GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == of->wired)),
- /* $10 */
+ /* $11 */
GNUNET_PQ_query_param_bool (NULL == of->session_id),
NULL == of->session_id
? GNUNET_PQ_query_param_null ()
@@ -136,135 +137,151 @@ TALER_MERCHANTDB_lookup_orders (
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_inc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_dec[PG_PREP_INSTANCE_NAME_MAX];
+ char stmt[128];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Looking up orders, using filter paid: %d, refunded: %d, wired: %d\n",
of->paid,
of->refunded,
of->wired);
- PREPARE_INSTANCE (pg,
- stmt_dec,
- "lookup_orders_dec",
- "(SELECT"
- " order_id"
- ",order_serial"
- ",creation_time"
- " FROM merchant_orders"
- " WHERE order_serial < $2"
- " AND"
- " creation_time < $3"
- " AND ($4 OR "
- " NOT CAST($5 AS BOOL))" /* unclaimed orders are never paid */
- " AND ($6 OR "
- " NOT CAST($7 AS BOOL))"/* unclaimed orders are never refunded */
- " AND ($8 OR "
- " NOT CAST($9 AS BOOL))" /* unclaimed orders are never wired */
- " AND"
- " order_serial NOT IN"
- " (SELECT order_serial"
- " FROM merchant_contract_terms)" /* only select unclaimed orders */
- " AND ($10 OR "
- " ($11 = session_id))"
- " AND ($12 OR "
- " ($13 = fulfillment_url))"
- " AND ( ($14::TEXT IS NULL) OR "
- " (LOWER(contract_terms ->> 'summary') LIKE LOWER($14)) )"
- " ORDER BY order_serial DESC"
- " LIMIT $1)"
- "UNION " /* union ensures elements are distinct! */
- "(SELECT"
- " order_id"
- ",order_serial"
- ",creation_time"
- " FROM merchant_contract_terms"
- " WHERE order_serial < $2"
- " AND"
- " creation_time < $3"
- " AND ($4 OR "
- " (CAST($5 AS BOOL) = paid))"
- " AND ($6 OR "
- " (CAST($7 AS BOOL) = (order_serial IN"
- " (SELECT order_serial "
- " FROM merchant_refunds))))"
- " AND ($8 OR"
- " (CAST($9 AS BOOL) = wired))"
- " AND ($10 OR "
- " ($11 = session_id))"
- " AND ($12 OR "
- " ($13 = fulfillment_url))"
- " AND ( ($14::TEXT IS NULL) OR "
- " (LOWER(contract_terms ->> 'summary') LIKE LOWER($14)) )"
- " ORDER BY order_serial DESC"
- " LIMIT $1)"
- " ORDER BY order_serial DESC"
- " LIMIT $1");
+ GNUNET_snprintf (stmt,
+ sizeof (stmt),
+ "lookup_orders_%s",
+ (of->delta > 0) ? "inc" : "dec");
+ PREPARE (pg,
+ "lookup_orders_dec",
+ "(SELECT"
+ " order_id"
+ ",order_serial"
+ ",creation_time"
+ " FROM merchant_orders"
+ " WHERE merchant_orders.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " order_serial < $3"
+ " AND"
+ " creation_time < $4"
+ " AND ($5 OR "
+ " NOT CAST($6 AS BOOL))" /* unclaimed orders are never paid */
+ " AND ($7 OR "
+ " NOT CAST($8 AS BOOL))"/* unclaimed orders are never refunded */
+ " AND ($9 OR "
+ " NOT CAST($10 AS BOOL))" /* unclaimed orders are never wired */
+ " AND"
+ " order_serial NOT IN"
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms)" /* only select unclaimed orders */
+ " AND ($11 OR "
+ " ($12 = session_id))"
+ " AND ($13 OR "
+ " ($14 = fulfillment_url))"
+ " AND ( ($15::TEXT IS NULL) OR "
+ " (LOWER(contract_terms ->> 'summary') LIKE LOWER($15)) )"
+ " ORDER BY order_serial DESC"
+ " LIMIT $2)"
+ "UNION " /* union ensures elements are distinct! */
+ "(SELECT"
+ " order_id"
+ ",order_serial"
+ ",creation_time"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_contract_terms.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " order_serial < $3"
+ " AND"
+ " creation_time < $4"
+ " AND ($5 OR "
+ " (CAST($6 AS BOOL) = paid))"
+ " AND ($7 OR "
+ " (CAST($8 AS BOOL) = (order_serial IN"
+ " (SELECT order_serial "
+ " FROM merchant_refunds))))"
+ " AND ($9 OR"
+ " (CAST($10 AS BOOL) = wired))"
+ " AND ($11 OR "
+ " ($12 = session_id))"
+ " AND ($13 OR "
+ " ($14 = fulfillment_url))"
+ " AND ( ($15::TEXT IS NULL) OR "
+ " (LOWER(contract_terms ->> 'summary') LIKE LOWER($15)) )"
+ " ORDER BY order_serial DESC"
+ " LIMIT $2)"
+ " ORDER BY order_serial DESC"
+ " LIMIT $2");
- PREPARE_INSTANCE (pg,
- stmt_inc,
- "lookup_orders_inc",
- "(SELECT"
- " order_id"
- ",order_serial"
- ",creation_time"
- " FROM merchant_orders"
- " WHERE order_serial > $2"
- " AND"
- " creation_time > $3"
- " AND ($4 OR "
- " NOT CAST($5 AS BOOL))" /* unclaimed orders are never paid */
- " AND ($6 OR "
- " NOT CAST($7 AS BOOL))"/* unclaimed orders are never refunded */
- " AND ($8 OR "
- " NOT CAST($9 AS BOOL))" /* unclaimed orders are never wired */
- " AND"
- " (order_serial NOT IN"
- " (SELECT order_serial"
- " FROM merchant_contract_terms))" /* only select unclaimed orders */
- " AND ($10 OR "
- " ($11 = session_id))"
- " AND ($12 OR "
- " ($13 = fulfillment_url))"
- " AND ( ($14::TEXT IS NULL) OR "
- " (LOWER(contract_terms ->> 'summary') LIKE LOWER($14)) )"
- " ORDER BY order_serial ASC"
- " LIMIT $1)"
- "UNION " /* union ensures elements are distinct! */
- "(SELECT"
- " order_id"
- ",order_serial"
- ",creation_time"
- " FROM merchant_contract_terms"
- " WHERE order_serial > $2"
- " AND"
- " creation_time > $3"
- " AND ($4 OR "
- " (CAST($5 AS BOOL) = paid))"
- " AND ($6 OR "
- " (CAST($7 AS BOOL) = (order_serial IN"
- " (SELECT order_serial "
- " FROM merchant_refunds))))"
- " AND ($8 OR"
- " (CAST($9 AS BOOL) = wired))"
- " AND ($10 OR "
- " ($11 = session_id))"
- " AND ($12 OR "
- " ($13 = fulfillment_url))"
- " AND ( ($14::TEXT IS NULL) OR "
- " (LOWER(contract_terms ->> 'summary') LIKE LOWER($14)) )"
- " ORDER BY order_serial ASC"
- " LIMIT $1)"
- " ORDER BY order_serial ASC"
- " LIMIT $1");
+ PREPARE (pg,
+ "lookup_orders_inc",
+ "(SELECT"
+ " order_id"
+ ",order_serial"
+ ",creation_time"
+ " FROM merchant_orders"
+ " WHERE merchant_orders.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " order_serial > $3"
+ " AND"
+ " creation_time > $4"
+ " AND ($5 OR "
+ " NOT CAST($6 AS BOOL))" /* unclaimed orders are never paid */
+ " AND ($7 OR "
+ " NOT CAST($8 AS BOOL))"/* unclaimed orders are never refunded */
+ " AND ($9 OR "
+ " NOT CAST($10 AS BOOL))" /* unclaimed orders are never wired */
+ " AND"
+ " (order_serial NOT IN"
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms))" /* only select unclaimed orders */
+ " AND ($11 OR "
+ " ($12 = session_id))"
+ " AND ($13 OR "
+ " ($14 = fulfillment_url))"
+ " AND ( ($15::TEXT IS NULL) OR "
+ " (LOWER(contract_terms ->> 'summary') LIKE LOWER($15)) )"
+ " ORDER BY order_serial ASC"
+ " LIMIT $2)"
+ "UNION " /* union ensures elements are distinct! */
+ "(SELECT"
+ " order_id"
+ ",order_serial"
+ ",creation_time"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_contract_terms.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " order_serial > $3"
+ " AND"
+ " creation_time > $4"
+ " AND ($5 OR "
+ " (CAST($6 AS BOOL) = paid))"
+ " AND ($7 OR "
+ " (CAST($8 AS BOOL) = (order_serial IN"
+ " (SELECT order_serial "
+ " FROM merchant_refunds))))"
+ " AND ($9 OR"
+ " (CAST($10 AS BOOL) = wired))"
+ " AND ($11 OR "
+ " ($12 = session_id))"
+ " AND ($13 OR "
+ " ($14 = fulfillment_url))"
+ " AND ( ($15::TEXT IS NULL) OR "
+ " (LOWER(contract_terms ->> 'summary') LIKE LOWER($15)) )"
+ " ORDER BY order_serial ASC"
+ " LIMIT $2)"
+ " ORDER BY order_serial ASC"
+ " LIMIT $2");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- (of->delta > 0)
- ? stmt_inc
- : stmt_dec,
+ stmt,
params,
&lookup_orders_cb,
&plc);
diff --git a/src/backenddb/lookup_otp_devices.c b/src/backenddb/lookup_otp_devices.c
@@ -106,24 +106,23 @@ TALER_MERCHANTDB_lookup_otp_devices (
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_otp_devices",
- "SELECT"
- " otp_id"
- ",otp_description"
- " FROM merchant_otp_devices");
+ PREPARE (pg,
+ "lookup_otp_devices",
+ "SELECT"
+ " otp_id"
+ ",otp_description"
+ " FROM merchant_otp_devices"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_otp_devices",
params,
&lookup_otp_devices_cb,
&tlc);
diff --git a/src/backenddb/lookup_pending_deposits.c b/src/backenddb/lookup_pending_deposits.c
@@ -82,25 +82,25 @@ lookup_deposits_cb (void *cls,
struct TALER_Amount deposit_fee;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("out_deposit_serial",
+ GNUNET_PQ_result_spec_uint64 ("deposit_serial",
&deposit_serial),
- GNUNET_PQ_result_spec_auto_from_type ("out_h_contract_terms",
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
&h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("out_merchant_priv",
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
&merchant_priv),
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("merchant_id",
&instance_id),
- GNUNET_PQ_result_spec_absolute_time ("out_wire_transfer_deadline",
+ GNUNET_PQ_result_spec_absolute_time ("wire_transfer_deadline",
&wire_deadline),
- GNUNET_PQ_result_spec_absolute_time ("out_retry_time",
+ GNUNET_PQ_result_spec_absolute_time ("retry_time",
&retry_time),
- GNUNET_PQ_result_spec_auto_from_type ("out_h_wire",
+ GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&h_wire),
- TALER_PQ_result_spec_amount_with_currency ("out_amount_with_fee",
+ TALER_PQ_result_spec_amount_with_currency ("amount_with_fee",
&amount_with_fee),
- TALER_PQ_result_spec_amount_with_currency ("out_deposit_fee",
+ TALER_PQ_result_spec_amount_with_currency ("deposit_fee",
&deposit_fee),
- GNUNET_PQ_result_spec_auto_from_type ("out_coin_pub",
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
&coin_pub),
GNUNET_PQ_result_spec_end
};
@@ -159,17 +159,35 @@ TALER_MERCHANTDB_lookup_pending_deposits (
PREPARE (pg,
"lookup_pending_deposits",
"SELECT"
- " out_deposit_serial"
- " ,out_h_contract_terms"
- " ,out_merchant_priv"
- " ,out_merchant_id"
- " ,out_wire_transfer_deadline"
- " ,out_retry_time"
- " ,out_h_wire"
- " ,out_amount_with_fee"
- " ,out_deposit_fee"
- " ,out_coin_pub"
- " FROM merchant.lookup_pending_deposits($1, $2, $3, $4)");
+ " md.deposit_serial"
+ ",mct.h_contract_terms"
+ ",mk.merchant_priv"
+ ",mi.merchant_id"
+ ",mdc.wire_transfer_deadline"
+ ",md.settlement_retry_time AS retry_time"
+ ",ma.h_wire"
+ ",md.amount_with_fee"
+ ",md.deposit_fee"
+ ",md.coin_pub"
+ " FROM merchant_deposits md"
+ " JOIN merchant_deposit_confirmations mdc"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_contract_terms mct"
+ " ON (mct.order_serial=mdc.order_serial)"
+ " JOIN merchant_accounts ma"
+ " ON (mdc.account_serial=ma.account_serial)"
+ " LEFT JOIN merchant_kyc kyc"
+ " ON (mdc.account_serial=kyc.account_serial)"
+ " JOIN merchant_instances mi"
+ " ON (mct.merchant_serial=mi.merchant_serial)"
+ " JOIN merchant_keys mk"
+ " ON (mi.merchant_serial=mk.merchant_serial)"
+ " WHERE (mdc.exchange_url=$1)"
+ " AND md.settlement_retry_needed"
+ " AND ($4 OR (md.settlement_retry_time < $2))"
+ " AND ( (kyc.kyc_ok IS NULL) OR kyc.kyc_ok)"
+ " ORDER BY md.settlement_retry_time ASC"
+ " LIMIT $3");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"lookup_pending_deposits",
params,
diff --git a/src/backenddb/lookup_pending_webhooks.c b/src/backenddb/lookup_pending_webhooks.c
@@ -72,22 +72,22 @@ lookup_pending_webhooks_cb (void *cls,
char *header = NULL;
char *body = NULL;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("out_webhook_pending_serial",
+ GNUNET_PQ_result_spec_uint64 ("webhook_pending_serial",
&webhook_pending_serial),
- GNUNET_PQ_result_spec_absolute_time ("out_next_attempt",
+ GNUNET_PQ_result_spec_absolute_time ("next_attempt",
&next_attempt),
- GNUNET_PQ_result_spec_uint32 ("out_retries",
+ GNUNET_PQ_result_spec_uint32 ("retries",
&retries),
- GNUNET_PQ_result_spec_string ("out_url",
+ GNUNET_PQ_result_spec_string ("url",
&url),
- GNUNET_PQ_result_spec_string ("out_http_method",
+ GNUNET_PQ_result_spec_string ("http_method",
&http_method),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_header",
+ GNUNET_PQ_result_spec_string ("header",
&header),
NULL),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_body",
+ GNUNET_PQ_result_spec_string ("body",
&body),
NULL),
GNUNET_PQ_result_spec_end
@@ -138,14 +138,17 @@ TALER_MERCHANTDB_lookup_pending_webhooks (
PREPARE (pg,
"lookup_pending_webhooks",
"SELECT"
- " out_webhook_pending_serial"
- " ,out_next_attempt"
- " ,out_retries"
- " ,out_url"
- " ,out_http_method"
- " ,out_header"
- " ,out_body"
- " FROM merchant.lookup_pending_webhooks($1)");
+ " webhook_pending_serial"
+ ",next_attempt"
+ ",retries"
+ ",url"
+ ",http_method"
+ ",header"
+ ",body"
+ " FROM merchant_pending_webhooks"
+ " WHERE next_attempt <= $1"
+ " ORDER BY next_attempt ASC"
+ );
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"lookup_pending_webhooks",
@@ -179,14 +182,16 @@ TALER_MERCHANTDB_lookup_future_webhook (struct TALER_MERCHANTDB_PostgresContext
PREPARE (pg,
"lookup_future_webhook",
"SELECT"
- " out_webhook_pending_serial"
- " ,out_next_attempt"
- " ,out_retries"
- " ,out_url"
- " ,out_http_method"
- " ,out_header"
- " ,out_body"
- " FROM merchant.lookup_future_webhook()");
+ " webhook_pending_serial"
+ ",next_attempt"
+ ",retries"
+ ",url"
+ ",http_method"
+ ",header"
+ ",body"
+ " FROM merchant_pending_webhooks"
+ " ORDER BY next_attempt ASC LIMIT 1"
+ );
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"lookup_future_webhook",
@@ -215,35 +220,35 @@ TALER_MERCHANTDB_lookup_all_webhooks (struct TALER_MERCHANTDB_PostgresContext *p
};
uint64_t max_results64 = max_results;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&min_row),
GNUNET_PQ_query_param_uint64 (&max_results64),
GNUNET_PQ_query_param_end
};
+
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_all_webhooks",
- " SELECT"
- " webhook_pending_serial AS out_webhook_pending_serial"
- " ,next_attempt AS out_next_attempt"
- " ,retries AS out_retries"
- " ,url AS out_url"
- " ,http_method AS out_http_method"
- " ,header AS out_header"
- " ,body AS out_body"
- " FROM merchant_pending_webhooks"
- " WHERE webhook_pending_serial > $1"
- " ORDER BY webhook_pending_serial"
- " ASC LIMIT $2");
+ PREPARE (pg,
+ "lookup_all_webhooks",
+ " SELECT"
+ " webhook_pending_serial"
+ ",next_attempt"
+ ",retries"
+ ",url"
+ ",http_method"
+ ",header"
+ ",body"
+ " FROM merchant_pending_webhooks"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND webhook_pending_serial > $2"
+ " ORDER BY webhook_pending_serial"
+ " ASC LIMIT $3");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_all_webhooks",
params,
&lookup_pending_webhooks_cb,
&pwlc);
diff --git a/src/backenddb/lookup_product.c b/src/backenddb/lookup_product.c
@@ -35,50 +35,49 @@ TALER_MERCHANTDB_lookup_product (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t **categories)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (product_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_product",
- "SELECT"
- " mi.description"
- ",mi.description_i18n::TEXT"
- ",mi.product_name"
- ",mi.unit"
- ",mi.price_array"
- ",mi.taxes::TEXT"
- ",mi.total_stock"
- ",mi.total_stock_frac"
- ",mi.allow_fractional_quantity"
- ",mi.fractional_precision_level"
- ",mi.total_sold"
- ",mi.total_sold_frac"
- ",mi.total_lost"
- ",mi.total_lost_frac"
- ",mi.image"
- ",mi.address::TEXT"
- ",mi.next_restock"
- ",mi.minimum_age"
- ",mi.product_group_serial"
- ",mi.money_pot_serial"
- ",mi.price_is_net"
- ",t.category_array AS categories"
- " FROM merchant_inventory mi"
- ",LATERAL ("
- " SELECT ARRAY ("
- " SELECT mpc.category_serial"
- " FROM merchant_product_categories mpc"
- " WHERE mpc.product_serial = mi.product_serial"
- " ) AS category_array"
- " ) t"
- " WHERE mi.product_id=$1"
- );
+ PREPARE (pg,
+ "lookup_product",
+ "SELECT"
+ " mi.description"
+ ",mi.description_i18n::TEXT"
+ ",mi.product_name"
+ ",mi.unit"
+ ",mi.price_array"
+ ",mi.taxes::TEXT"
+ ",mi.total_stock"
+ ",mi.total_stock_frac"
+ ",mi.allow_fractional_quantity"
+ ",mi.fractional_precision_level"
+ ",mi.total_sold"
+ ",mi.total_sold_frac"
+ ",mi.total_lost"
+ ",mi.total_lost_frac"
+ ",mi.image"
+ ",mi.address::TEXT"
+ ",mi.next_restock"
+ ",mi.minimum_age"
+ ",mi.product_group_serial"
+ ",mi.money_pot_serial"
+ ",mi.price_is_net"
+ ",t.category_array AS categories"
+ " FROM merchant_inventory mi"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ ",LATERAL ("
+ " SELECT ARRAY ("
+ " SELECT mpc.category_serial"
+ " FROM merchant_product_categories mpc"
+ " WHERE mpc.product_serial = mi.product_serial"
+ " ) AS category_array"
+ " ) t"
+ " WHERE inst.merchant_id=$1"
+ " AND mi.product_id=$2"
+ );
if (NULL == pd)
{
struct GNUNET_PQ_ResultSpec rs_null[] = {
@@ -87,7 +86,7 @@ TALER_MERCHANTDB_lookup_product (struct TALER_MERCHANTDB_PostgresContext *pg,
check_connection (pg);
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_product",
params,
rs_null);
}
@@ -164,7 +163,7 @@ TALER_MERCHANTDB_lookup_product (struct TALER_MERCHANTDB_PostgresContext *pg,
pd->product_group_id = 0;
pd->money_pot_id = 0;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_product",
params,
rs);
pd->product_name = my_name;
diff --git a/src/backenddb/lookup_product_image.c b/src/backenddb/lookup_product_image.c
@@ -33,23 +33,22 @@ TALER_MERCHANTDB_lookup_product_image_by_hash (
char **image)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (image_hash),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (
+ PREPARE (
pg,
- stmt,
"lookup_product_image_by_hash",
"SELECT"
" mi.image"
" FROM merchant_inventory mi"
- " WHERE mi.image_hash=$1");
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ " WHERE inst.merchant_id=$1"
+ " AND mi.image_hash=$2");
*image = NULL;
{
@@ -61,7 +60,7 @@ TALER_MERCHANTDB_lookup_product_image_by_hash (
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "lookup_product_image_by_hash",
params,
rs);
}
diff --git a/src/backenddb/lookup_products.c b/src/backenddb/lookup_products.c
@@ -112,6 +112,7 @@ TALER_MERCHANTDB_lookup_products (
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&offset),
NULL == category_filter
? GNUNET_PQ_query_param_null ()
@@ -127,64 +128,65 @@ TALER_MERCHANTDB_lookup_products (
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "lookup_products_asc",
- "SELECT"
- " product_id"
- " ,product_serial"
- " FROM merchant_inventory"
- " WHERE product_serial > $1"
- " AND ( ($2::TEXT IS NULL) OR"
- " (product_serial IN"
- " (SELECT product_serial"
- " FROM merchant_product_categories"
- " WHERE category_serial IN"
- " (SELECT category_serial"
- " FROM merchant_categories"
- " WHERE category_name LIKE LOWER($2)))) )"
- " AND ( (0 = $6::INT8) OR"
- " (product_group_serial = $6) )"
- " AND ( ($3::TEXT IS NULL) OR"
- " (product_name LIKE LOWER($3)) )"
- " AND ( ($4::TEXT IS NULL) OR"
- " (description LIKE LOWER($4)) )"
- " ORDER BY product_serial ASC"
- " LIMIT $5");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_products_desc",
- "SELECT"
- " product_id"
- " ,product_serial"
- " FROM merchant_inventory"
- " WHERE product_serial < $1"
- " AND ( ($2::TEXT IS NULL) OR"
- " (product_serial IN"
- " (SELECT product_serial"
- " FROM merchant_product_categories"
- " WHERE category_serial IN"
- " (SELECT category_serial"
- " FROM merchant_categories"
- " WHERE category_name LIKE LOWER($2)))) )"
- " AND ( (0 = $6::INT8) OR"
- " (product_group_serial = $6) )"
- " AND ( ($3::TEXT IS NULL) OR"
- " (product_name LIKE LOWER($3)) )"
- " AND ( ($4::TEXT IS NULL) OR"
- " (description LIKE LOWER($4)) )"
- " ORDER BY product_serial DESC"
- " LIMIT $5");
+ PREPARE (pg,
+ "lookup_products_asc",
+ "SELECT"
+ " product_id"
+ " ,product_serial"
+ " FROM merchant_inventory"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND product_serial > $2"
+ " AND ( ($3::TEXT IS NULL) OR"
+ " (product_serial IN"
+ " (SELECT product_serial"
+ " FROM merchant_product_categories"
+ " WHERE category_serial IN"
+ " (SELECT category_serial"
+ " FROM merchant_categories"
+ " WHERE category_name LIKE LOWER($3)))) )"
+ " AND ( (0 = $7::INT8) OR"
+ " (product_group_serial = $7) )"
+ " AND ( ($4::TEXT IS NULL) OR"
+ " (product_name LIKE LOWER($4)) )"
+ " AND ( ($5::TEXT IS NULL) OR"
+ " (description LIKE LOWER($5)) )"
+ " ORDER BY product_serial ASC"
+ " LIMIT $6");
+ PREPARE (pg,
+ "lookup_products_desc",
+ "SELECT"
+ " product_id"
+ " ,product_serial"
+ " FROM merchant_inventory"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND product_serial < $2"
+ " AND ( ($3::TEXT IS NULL) OR"
+ " (product_serial IN"
+ " (SELECT product_serial"
+ " FROM merchant_product_categories"
+ " WHERE category_serial IN"
+ " (SELECT category_serial"
+ " FROM merchant_categories"
+ " WHERE category_name LIKE LOWER($3)))) )"
+ " AND ( (0 = $7::INT8) OR"
+ " (product_group_serial = $7) )"
+ " AND ( ($4::TEXT IS NULL) OR"
+ " (product_name LIKE LOWER($4)) )"
+ " AND ( ($5::TEXT IS NULL) OR"
+ " (description LIKE LOWER($5)) )"
+ " ORDER BY product_serial DESC"
+ " LIMIT $6");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- (limit > 0) ? stmt_asc : stmt_desc,
+ (limit > 0)
+ ? "lookup_products_asc"
+ : "lookup_products_desc",
params,
&lookup_products_cb,
&plc);
diff --git a/src/backenddb/lookup_reconciliation_details.c b/src/backenddb/lookup_reconciliation_details.c
@@ -139,37 +139,36 @@ TALER_MERCHANTDB_lookup_reconciliation_details (
.pg = pg
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&expected_incoming_serial),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_reconciliation_details",
- "SELECT"
- " mct.order_id"
- ",SUM((etc.exchange_deposit_value).val)::INT8 AS deposit_value_sum"
- ",SUM((etc.exchange_deposit_value).frac)::INT8 AS deposit_frac_sum"
- ",SUM((etc.exchange_deposit_fee).val)::INT8 AS fee_value_sum"
- ",SUM((etc.exchange_deposit_fee).frac)::INT8 AS fee_frac_sum"
- ",(etc.exchange_deposit_value).curr AS currency"
- " FROM merchant_expected_transfer_to_coin etc"
- " JOIN merchant_deposits md"
- " USING (deposit_serial)"
- " JOIN merchant_deposit_confirmations mdc"
- " USING (deposit_confirmation_serial)"
- " JOIN merchant_contract_terms mct"
- " USING (order_serial)"
- " WHERE expected_credit_serial=$1"
- " GROUP BY mct.order_id, (etc.exchange_deposit_value).curr;");
+ PREPARE (pg,
+ "lookup_reconciliation_details",
+ "SELECT"
+ " mct.order_id"
+ ",SUM((etc.exchange_deposit_value).val)::INT8 AS deposit_value_sum"
+ ",SUM((etc.exchange_deposit_value).frac)::INT8 AS deposit_frac_sum"
+ ",SUM((etc.exchange_deposit_fee).val)::INT8 AS fee_value_sum"
+ ",SUM((etc.exchange_deposit_fee).frac)::INT8 AS fee_frac_sum"
+ ",(etc.exchange_deposit_value).curr AS currency"
+ " FROM merchant_expected_transfer_to_coin etc"
+ " JOIN merchant_deposits md"
+ " USING (deposit_serial)"
+ " JOIN merchant_deposit_confirmations mdc"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_contract_terms mct"
+ " USING (order_serial)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE expected_credit_serial=$2"
+ " AND mi.merchant_id=$1"
+ " GROUP BY mct.order_id, (etc.exchange_deposit_value).curr;");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_reconciliation_details",
params,
&reconciliation_cb,
&lic);
diff --git a/src/backenddb/lookup_refund_proof.c b/src/backenddb/lookup_refund_proof.c
@@ -43,24 +43,20 @@ TALER_MERCHANTDB_lookup_refund_proof (struct TALER_MERCHANTDB_PostgresContext *p
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_refund_proof",
- "SELECT"
- " merchant.merchant_exchange_signing_keys.exchange_pub"
- ",exchange_sig"
- " FROM merchant_refund_proofs"
- " JOIN merchant.merchant_exchange_signing_keys"
- " USING (signkey_serial)"
- " WHERE"
- " refund_serial=$1");
+ PREPARE (pg,
+ "lookup_refund_proof",
+ "SELECT"
+ " merchant_exchange_signing_keys.exchange_pub"
+ ",exchange_sig"
+ " FROM merchant_refund_proofs"
+ " JOIN merchant_exchange_signing_keys"
+ " USING (signkey_serial)"
+ " WHERE"
+ " refund_serial=$1");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_refund_proof",
params,
rs);
}
diff --git a/src/backenddb/lookup_refunds.c b/src/backenddb/lookup_refunds.c
@@ -105,6 +105,7 @@ TALER_MERCHANTDB_lookup_refunds (struct TALER_MERCHANTDB_PostgresContext *pg,
void *rc_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_end
};
@@ -114,29 +115,28 @@ TALER_MERCHANTDB_lookup_refunds (struct TALER_MERCHANTDB_PostgresContext *pg,
.pg = pg
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
/* no preflight check here, run in transaction by caller! */
TALER_LOG_DEBUG ("Looking for refund of h_contract_terms %s at `%s'\n",
GNUNET_h2s (&h_contract_terms->hash),
instance_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_refunds",
- "SELECT"
- " coin_pub"
- ",refund_amount"
- " FROM merchant_refunds"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)");
+ PREPARE (pg,
+ "lookup_refunds",
+ "SELECT"
+ " coin_pub"
+ ",refund_amount"
+ " FROM merchant_refunds"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_refunds",
params,
&lookup_refunds_cb,
&lrc);
diff --git a/src/backenddb/lookup_refunds_detailed.c b/src/backenddb/lookup_refunds_detailed.c
@@ -131,6 +131,7 @@ TALER_MERCHANTDB_lookup_refunds_detailed (
void *rc_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_end
};
@@ -140,43 +141,42 @@ TALER_MERCHANTDB_lookup_refunds_detailed (
.pg = pg
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
/* no preflight check here, run in transaction by caller! */
TALER_LOG_DEBUG ("Looking for refund %s + %s\n",
GNUNET_h2s (&h_contract_terms->hash),
instance_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_refunds_detailed",
- "SELECT"
- " ref.refund_serial"
- ",ref.refund_timestamp"
- ",dep.coin_pub"
- ",mcon.exchange_url"
- ",ref.rtransaction_id"
- ",ref.reason"
- ",ref.refund_amount"
- ",merchant_refund_proofs.exchange_sig IS NULL AS pending"
- " FROM merchant_deposit_confirmations mcon"
- " JOIN merchant_deposits dep"
- " USING (deposit_confirmation_serial)"
- " JOIN merchant_refunds ref"
- " USING (order_serial, coin_pub)"
- " LEFT JOIN merchant_refund_proofs"
- " USING (refund_serial)"
- " WHERE mcon.order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)");
+ PREPARE (pg,
+ "lookup_refunds_detailed",
+ "SELECT"
+ " ref.refund_serial"
+ ",ref.refund_timestamp"
+ ",dep.coin_pub"
+ ",mcon.exchange_url"
+ ",ref.rtransaction_id"
+ ",ref.reason"
+ ",ref.refund_amount"
+ ",merchant_refund_proofs.exchange_sig IS NULL AS pending"
+ " FROM merchant_deposit_confirmations mcon"
+ " JOIN merchant_deposits dep"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_refunds ref"
+ " USING (order_serial, coin_pub)"
+ " LEFT JOIN merchant_refund_proofs"
+ " USING (refund_serial)"
+ " WHERE mcon.order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_refunds_detailed",
params,
&lookup_refunds_detailed_cb,
&lrdc);
diff --git a/src/backenddb/lookup_reports_pending.c b/src/backenddb/lookup_reports_pending.c
@@ -77,27 +77,27 @@ select_pending_reports_cb (void *cls,
struct GNUNET_TIME_Absolute next_transmission;
bool one_shot;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("merchant_id",
&instance_id),
- GNUNET_PQ_result_spec_uint64 ("out_report_serial",
+ GNUNET_PQ_result_spec_uint64 ("report_serial",
&report_serial),
- GNUNET_PQ_result_spec_string ("out_report_program_section",
+ GNUNET_PQ_result_spec_string ("report_program_section",
&report_program_section),
- GNUNET_PQ_result_spec_string ("out_report_description",
+ GNUNET_PQ_result_spec_string ("report_description",
&report_description),
- GNUNET_PQ_result_spec_string ("out_mime_type",
+ GNUNET_PQ_result_spec_string ("mime_type",
&mime_type),
- GNUNET_PQ_result_spec_auto_from_type ("out_report_token",
+ GNUNET_PQ_result_spec_auto_from_type ("report_token",
&report_token),
- GNUNET_PQ_result_spec_string ("out_target_address",
+ GNUNET_PQ_result_spec_string ("target_address",
&target_address),
- GNUNET_PQ_result_spec_relative_time ("out_frequency",
+ GNUNET_PQ_result_spec_relative_time ("frequency",
&frequency),
- GNUNET_PQ_result_spec_relative_time ("out_frequency_shift",
+ GNUNET_PQ_result_spec_relative_time ("frequency_shift",
&frequency_shift),
- GNUNET_PQ_result_spec_absolute_time ("out_next_transmission",
+ GNUNET_PQ_result_spec_absolute_time ("next_transmission",
&next_transmission),
- GNUNET_PQ_result_spec_bool ("out_one_shot_hidden",
+ GNUNET_PQ_result_spec_bool ("one_shot_hidden",
&one_shot),
GNUNET_PQ_result_spec_end
};
@@ -149,18 +149,22 @@ TALER_MERCHANTDB_lookup_reports_pending (
PREPARE (pg,
"lookup_reports_pending",
"SELECT"
- " out_merchant_id"
- " ,out_report_serial"
- " ,out_report_program_section"
- " ,out_report_description"
- " ,out_mime_type"
- " ,out_report_token"
- " ,out_target_address"
- " ,out_frequency"
- " ,out_frequency_shift"
- " ,out_next_transmission"
- " ,out_one_shot_hidden"
- " FROM merchant.lookup_reports_pending()");
+ " mi.merchant_id"
+ " ,mr.report_serial"
+ " ,mr.report_program_section"
+ " ,mr.report_description"
+ " ,mr.mime_type"
+ " ,mr.report_token"
+ " ,mr.target_address"
+ " ,mr.frequency"
+ " ,mr.frequency_shift"
+ " ,mr.next_transmission"
+ " ,mr.one_shot_hidden"
+ " FROM merchant_reports mr"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " ORDER BY next_transmission ASC"
+ " LIMIT 1;");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
"lookup_reports_pending",
diff --git a/src/backenddb/lookup_spent_tokens_by_order.c b/src/backenddb/lookup_spent_tokens_by_order.c
@@ -133,29 +133,25 @@ TALER_MERCHANTDB_lookup_spent_tokens_by_order (
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_spent_tokens_by_order",
- "SELECT"
- " spent_token_serial"
- ",h_contract_terms"
- ",h_pub"
- ",token_pub"
- ",token_sig"
- ",blind_sig"
- " FROM merchant_used_tokens"
- " JOIN merchant_contract_terms"
- " USING (h_contract_terms)"
- " JOIN merchant_token_family_keys"
- " USING (token_family_key_serial)"
- " WHERE order_serial=$1");
+ PREPARE (pg,
+ "lookup_spent_tokens_by_order",
+ "SELECT"
+ " spent_token_serial"
+ ",h_contract_terms"
+ ",h_pub"
+ ",token_pub"
+ ",token_sig"
+ ",blind_sig"
+ " FROM merchant_used_tokens"
+ " JOIN merchant_contract_terms"
+ " USING (h_contract_terms)"
+ " JOIN merchant_token_family_keys"
+ " USING (token_family_key_serial)"
+ " WHERE order_serial=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_spent_tokens_by_order",
params,
&lookup_spent_tokens_by_order_cb,
&ctx);
diff --git a/src/backenddb/lookup_statistics_amount_by_bucket.c b/src/backenddb/lookup_statistics_amount_by_bucket.c
@@ -186,34 +186,33 @@ TALER_MERCHANTDB_lookup_statistics_amount_by_bucket (
.pg = pg,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (slug),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_statistics_amount_by_bucket",
- "SELECT"
- " bmeta_serial_id"
- ",description"
- ",bucket_start"
- ",bucket_range::TEXT"
- ",merchant_statistics_bucket_end(bucket_start, bucket_range) AS bucket_end"
- ",(cumulative_value,cumulative_frac,curr)::taler_amount_currency AS cumulative_amount"
- " FROM merchant_statistic_bucket_amount"
- " JOIN merchant_statistic_bucket_meta"
- " USING (bmeta_serial_id)"
- " WHERE merchant_statistic_bucket_meta.slug=$1"
- " AND merchant_statistic_bucket_meta.stype='amount'");
+ PREPARE (pg,
+ "lookup_statistics_amount_by_bucket",
+ "SELECT"
+ " bmeta_serial_id"
+ ",description"
+ ",bucket_start"
+ ",bucket_range::TEXT"
+ ",merchant_statistics_bucket_end(bucket_start, bucket_range) AS bucket_end"
+ ",(cumulative_value,cumulative_frac,curr)::taler_amount_currency AS cumulative_amount"
+ " FROM merchant_statistic_bucket_amount"
+ " JOIN merchant_statistic_bucket_meta"
+ " USING (bmeta_serial_id)"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_statistic_bucket_meta.slug=$2"
+ " AND merchant_statistic_bucket_meta.stype='amount'");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_statistics_amount_by_bucket",
params,
&lookup_statistics_amount_by_bucket_cb,
&context);
diff --git a/src/backenddb/lookup_statistics_amount_by_bucket2.c b/src/backenddb/lookup_statistics_amount_by_bucket2.c
@@ -123,38 +123,37 @@ TALER_MERCHANTDB_lookup_statistics_amount_by_bucket2 (
.pg = pg,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (slug),
GNUNET_PQ_query_param_string (granularity),
GNUNET_PQ_query_param_uint64 (&counter),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_statistics_amount_by_bucket2",
- "SELECT"
- " msba.bucket_start"
- ",ARRAY_AGG ("
- " ROW(msba.cumulative_value::INT8, msba.cumulative_frac::INT4, msba.curr)::taler_amount_currency"
- " ) AS cumulative_amounts"
- " FROM merchant_statistic_bucket_meta msbm"
- " JOIN merchant_statistic_bucket_amount msba"
- " USING (bmeta_serial_id)"
- " WHERE msbm.slug=$1"
- " AND msba.bucket_range=$2::TEXT::statistic_range"
- " AND msbm.stype='amount'"
- " GROUP BY msba.bucket_start"
- " ORDER BY msba.bucket_start DESC"
- " LIMIT $3;");
+ PREPARE (pg,
+ "lookup_statistics_amount_by_bucket2",
+ "SELECT"
+ " msba.bucket_start"
+ ",ARRAY_AGG ("
+ " ROW(msba.cumulative_value::INT8, msba.cumulative_frac::INT4, msba.curr)::taler_amount_currency"
+ " ) AS cumulative_amounts"
+ " FROM merchant_statistic_bucket_meta msbm"
+ " JOIN merchant_statistic_bucket_amount msba"
+ " USING (bmeta_serial_id)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " AND msbm.slug=$2"
+ " AND msba.bucket_range=$3::TEXT::statistic_range"
+ " AND msbm.stype='amount'"
+ " GROUP BY msba.bucket_start"
+ " ORDER BY msba.bucket_start DESC"
+ " LIMIT $4;");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_statistics_amount_by_bucket2",
params,
&lookup_statistics_amount_by_bucket_cb2,
&context);
diff --git a/src/backenddb/lookup_statistics_amount_by_interval.c b/src/backenddb/lookup_statistics_amount_by_interval.c
@@ -198,26 +198,21 @@ TALER_MERCHANTDB_lookup_statistics_amount_by_interval (
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (slug),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_statistics_amount_by_interval_description",
- "SELECT description"
- " FROM merchant_statistic_interval_meta"
- " WHERE slug=$1 LIMIT 1");
+ PREPARE (pg,
+ "lookup_statistics_amount_by_interval_description",
+ "SELECT description"
+ " FROM merchant_statistic_interval_meta"
+ " WHERE slug=$1 LIMIT 1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt_desc,
+ "lookup_statistics_amount_by_interval_description",
descParams,
&lookup_statistics_amount_by_interval_desc_cb,
&context);
@@ -227,14 +222,13 @@ TALER_MERCHANTDB_lookup_statistics_amount_by_interval (
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_statistics_amount_by_interval",
- "SELECT *"
- " FROM merchant_statistic_interval_amount_get($1)");
+ PREPARE (pg,
+ "lookup_statistics_amount_by_interval",
+ "SELECT *"
+ " FROM merchant_statistic_interval_amount_get($2,$1)");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_statistics_amount_by_interval",
params,
&lookup_statistics_amount_by_interval_cb,
&context);
diff --git a/src/backenddb/lookup_statistics_counter_by_bucket.c b/src/backenddb/lookup_statistics_counter_by_bucket.c
@@ -125,33 +125,32 @@ TALER_MERCHANTDB_lookup_statistics_counter_by_bucket (
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (slug),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_statistics_counter_by_bucket",
- "SELECT"
- " description"
- ",bucket_start"
- ",bucket_range::TEXT"
- ",merchant_statistics_bucket_end(bucket_start, bucket_range) AS bucket_end"
- ",cumulative_number"
- " FROM merchant_statistic_bucket_counter"
- " JOIN merchant_statistic_bucket_meta"
- " USING (bmeta_serial_id)"
- " WHERE merchant_statistic_bucket_meta.slug=$1"
- " AND merchant_statistic_bucket_meta.stype = 'number'");
+ PREPARE (pg,
+ "lookup_statistics_counter_by_bucket",
+ "SELECT"
+ " description"
+ ",bucket_start"
+ ",bucket_range::TEXT"
+ ",merchant_statistics_bucket_end(bucket_start, bucket_range) AS bucket_end"
+ ",cumulative_number"
+ " FROM merchant_statistic_bucket_counter"
+ " JOIN merchant_statistic_bucket_meta"
+ " USING (bmeta_serial_id)"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_statistic_bucket_meta.slug=$2"
+ " AND merchant_statistic_bucket_meta.stype = 'number'");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_statistics_counter_by_bucket",
params,
&lookup_statistics_counter_by_bucket_cb,
&context);
diff --git a/src/backenddb/lookup_statistics_counter_by_bucket2.c b/src/backenddb/lookup_statistics_counter_by_bucket2.c
@@ -147,37 +147,36 @@ TALER_MERCHANTDB_lookup_statistics_counter_by_bucket2 (
.pg = pg
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (prefix),
GNUNET_PQ_query_param_string (granularity),
GNUNET_PQ_query_param_uint64 (&counter),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_statistics_counter_by_bucket2",
- "SELECT"
- " msbc.bucket_start"
- ",ARRAY_AGG(msbm.slug) AS slugs"
- ",ARRAY_AGG(msbc.cumulative_number) AS counters"
- " FROM merchant_statistic_bucket_counter msbc"
- " JOIN merchant_statistic_bucket_meta msbm"
- " USING (bmeta_serial_id)"
- " WHERE msbm.slug LIKE $1"
- " AND msbc.bucket_range=$2::TEXT::statistic_range"
- " AND msbm.stype = 'number'"
- " GROUP BY msbc.bucket_start"
- " ORDER BY msbc.bucket_start DESC"
- " LIMIT $3");
+ PREPARE (pg,
+ "lookup_statistics_counter_by_bucket2",
+ "SELECT"
+ " msbc.bucket_start"
+ ",ARRAY_AGG(msbm.slug) AS slugs"
+ ",ARRAY_AGG(msbc.cumulative_number) AS counters"
+ " FROM merchant_statistic_bucket_counter msbc"
+ " JOIN merchant_statistic_bucket_meta msbm"
+ " USING (bmeta_serial_id)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " AND msbm.slug LIKE $2"
+ " AND msbc.bucket_range=$3::TEXT::statistic_range"
+ " AND msbm.stype = 'number'"
+ " GROUP BY msbc.bucket_start"
+ " ORDER BY msbc.bucket_start DESC"
+ " LIMIT $4");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_statistics_counter_by_bucket2",
params,
&lookup_statistics_counter_by_bucket_cb2,
&context);
diff --git a/src/backenddb/lookup_statistics_counter_by_interval.c b/src/backenddb/lookup_statistics_counter_by_interval.c
@@ -164,26 +164,21 @@ TALER_MERCHANTDB_lookup_statistics_counter_by_interval (
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (slug),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_statistics_counter_by_interval_description",
- "SELECT description"
- " FROM merchant_statistic_interval_meta"
- " WHERE slug=$1 LIMIT 1");
+ PREPARE (pg,
+ "lookup_statistics_counter_by_interval_description",
+ "SELECT description"
+ " FROM merchant_statistic_interval_meta"
+ " WHERE slug=$1 LIMIT 1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt_desc,
+ "lookup_statistics_counter_by_interval_description",
descParams,
&lookup_statistics_counter_by_interval_desc_cb,
&context);
@@ -193,14 +188,13 @@ TALER_MERCHANTDB_lookup_statistics_counter_by_interval (
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_statistics_counter_by_interval",
- "SELECT *"
- " FROM merchant_statistic_interval_number_get($1)");
+ PREPARE (pg,
+ "lookup_statistics_counter_by_interval",
+ "SELECT *"
+ " FROM merchant_statistic_interval_number_get($2,$1)");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_statistics_counter_by_interval",
params,
&lookup_statistics_counter_by_interval_cb,
&context);
diff --git a/src/backenddb/lookup_template.c b/src/backenddb/lookup_template.c
@@ -43,28 +43,27 @@ TALER_MERCHANTDB_lookup_template (struct TALER_MERCHANTDB_PostgresContext *pg,
struct TALER_MERCHANTDB_TemplateDetails *td)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (template_id),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_template",
- "SELECT"
- " mt.template_description"
- ",mod.otp_id"
- ",mt.template_contract::TEXT"
- ",mt.editable_defaults::TEXT"
- " FROM merchant_template mt"
- " LEFT JOIN merchant_otp_devices mod"
- " ON (mod.otp_serial = mt.otp_device_id)"
- " WHERE mt.template_id=$1");
+ PREPARE (pg,
+ "lookup_template",
+ "SELECT"
+ " mt.template_description"
+ ",mod.otp_id"
+ ",mt.template_contract::TEXT"
+ ",mt.editable_defaults::TEXT"
+ " FROM merchant_template mt"
+ " JOIN merchant_instances mi"
+ " ON (mi.merchant_serial = mt.merchant_serial)"
+ " LEFT JOIN merchant_otp_devices mod"
+ " ON (mod.otp_serial = mt.otp_device_id)"
+ " WHERE mi.merchant_id=$1"
+ " AND mt.template_id=$2");
if (NULL == td)
{
struct GNUNET_PQ_ResultSpec rs_null[] = {
@@ -72,7 +71,7 @@ TALER_MERCHANTDB_lookup_template (struct TALER_MERCHANTDB_PostgresContext *pg,
};
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_template",
params,
rs_null);
GNUNET_PQ_cleanup_query_params_closures (params);
@@ -100,7 +99,7 @@ TALER_MERCHANTDB_lookup_template (struct TALER_MERCHANTDB_PostgresContext *pg,
0,
sizeof (*td));
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_template",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/lookup_templates.c b/src/backenddb/lookup_templates.c
@@ -105,24 +105,23 @@ TALER_MERCHANTDB_lookup_templates (struct TALER_MERCHANTDB_PostgresContext *pg,
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_templates",
- "SELECT"
- " template_id"
- ",template_description"
- " FROM merchant_template");
+ PREPARE (pg,
+ "lookup_templates",
+ "SELECT"
+ " template_id"
+ ",template_description"
+ " FROM merchant_template"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_templates",
params,
&lookup_templates_cb,
&tlc);
diff --git a/src/backenddb/lookup_token_families.c b/src/backenddb/lookup_token_families.c
@@ -130,29 +130,28 @@ TALER_MERCHANTDB_lookup_token_families (
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_token_families",
- "SELECT"
- " slug"
- ",name"
- ",description"
- ",description_i18n::TEXT"
- ",valid_after"
- ",valid_before"
- ",kind"
- " FROM merchant_token_families");
+ PREPARE (pg,
+ "lookup_token_families",
+ "SELECT"
+ " slug"
+ ",name"
+ ",description"
+ ",description_i18n::TEXT"
+ ",valid_after"
+ ",valid_before"
+ ",kind"
+ " FROM merchant_token_families"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_token_families",
params,
&lookup_token_families_cb,
&context);
diff --git a/src/backenddb/lookup_token_family.c b/src/backenddb/lookup_token_family.c
@@ -33,43 +33,20 @@ TALER_MERCHANTDB_lookup_token_family (struct TALER_MERCHANTDB_PostgresContext *p
struct TALER_MERCHANTDB_TokenFamilyDetails *details)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (token_family_slug),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_token_family",
- "SELECT"
- " slug"
- ",name"
- ",cipher_choice"
- ",description"
- ",description_i18n::TEXT"
- ",extra_data::TEXT"
- ",valid_after"
- ",valid_before"
- ",duration"
- ",validity_granularity"
- ",start_offset"
- ",kind"
- ",issued"
- ",used"
- " FROM merchant_token_families"
- " WHERE slug=$1");
if (NULL == details)
{
struct GNUNET_PQ_ResultSpec rs_null[] = {
GNUNET_PQ_result_spec_end
};
+ check_connection (pg);
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_token_family",
params,
rs_null);
}
@@ -111,11 +88,34 @@ TALER_MERCHANTDB_lookup_token_family (struct TALER_MERCHANTDB_PostgresContext *p
};
enum GNUNET_DB_QueryStatus qs;
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_token_family",
+ "SELECT"
+ " slug"
+ ",name"
+ ",cipher_choice"
+ ",description"
+ ",description_i18n::TEXT"
+ ",extra_data::TEXT"
+ ",valid_after"
+ ",valid_before"
+ ",duration"
+ ",validity_granularity"
+ ",start_offset"
+ ",kind"
+ ",issued"
+ ",used"
+ " FROM merchant_token_families"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_token_families.slug=$2");
memset (details,
0,
sizeof (*details));
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_token_family",
params,
rs);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
diff --git a/src/backenddb/lookup_token_family_key.c b/src/backenddb/lookup_token_family_key.c
@@ -39,49 +39,48 @@ TALER_MERCHANTDB_lookup_token_family_key (
struct TALER_MERCHANTDB_TokenFamilyKeyDetails *details)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (token_family_slug),
GNUNET_PQ_query_param_timestamp (&valid_at),
GNUNET_PQ_query_param_timestamp (&sign_until),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_token_family_key",
- "SELECT"
- " h_pub"
- ",pub"
- ",priv"
- ",cipher_choice"
- ",mtfk.signature_validity_start"
- ",mtfk.signature_validity_end"
- ",mtfk.private_key_deleted_at"
- ",slug"
- ",name"
- ",description"
- ",description_i18n::TEXT"
- ",mtf.valid_after"
- ",mtf.valid_before"
- ",duration"
- ",validity_granularity"
- ",start_offset"
- ",kind"
- ",issued"
- ",used"
- " FROM merchant_token_families mtf"
- " LEFT JOIN merchant_token_family_keys mtfk"
- " USING (token_family_serial)"
- " WHERE slug=$1"
- " AND COALESCE ($2 >= mtfk.signature_validity_start, TRUE)"
- " AND COALESCE ($2 <= mtfk.signature_validity_end, TRUE)"
- " AND COALESCE ($3 <= mtfk.private_key_deleted_at, TRUE)"
- " ORDER BY mtfk.signature_validity_start ASC"
- " LIMIT 1");
+ PREPARE (pg,
+ "lookup_token_family_key",
+ "SELECT"
+ " h_pub"
+ ",pub"
+ ",priv"
+ ",cipher_choice"
+ ",mtfk.signature_validity_start"
+ ",mtfk.signature_validity_end"
+ ",mtfk.private_key_deleted_at"
+ ",slug"
+ ",name"
+ ",description"
+ ",description_i18n::TEXT"
+ ",mtf.valid_after"
+ ",mtf.valid_before"
+ ",duration"
+ ",validity_granularity"
+ ",start_offset"
+ ",kind"
+ ",issued"
+ ",used"
+ " FROM merchant_token_families mtf"
+ " LEFT JOIN merchant_token_family_keys mtfk"
+ " USING (token_family_serial)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " AND slug=$2"
+ " AND COALESCE ($3 >= mtfk.signature_validity_start, TRUE)"
+ " AND COALESCE ($3 <= mtfk.signature_validity_end, TRUE)"
+ " AND COALESCE ($4 <= mtfk.private_key_deleted_at, TRUE)"
+ " ORDER BY mtfk.signature_validity_start ASC"
+ " LIMIT 1");
if (NULL == details)
{
@@ -90,7 +89,7 @@ TALER_MERCHANTDB_lookup_token_family_key (
};
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_token_family_key",
params,
rs_null);
}
@@ -153,7 +152,7 @@ TALER_MERCHANTDB_lookup_token_family_key (
0,
sizeof (*details));
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_token_family_key",
params,
rs);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
diff --git a/src/backenddb/lookup_token_family_keys.c b/src/backenddb/lookup_token_family_keys.c
@@ -166,6 +166,7 @@ TALER_MERCHANTDB_lookup_token_family_keys (
void *cb_cls)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (token_family_slug),
GNUNET_PQ_query_param_timestamp (&start_time),
GNUNET_PQ_query_param_timestamp (&end_time),
@@ -177,44 +178,42 @@ TALER_MERCHANTDB_lookup_token_family_keys (
.cb_cls = cb_cls
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_token_family_keys",
- "SELECT"
- " h_pub"
- ",mtfk.pub"
- ",mtfk.priv"
- ",cipher_choice"
- ",mtfk.signature_validity_start"
- ",mtfk.signature_validity_end"
- ",mtfk.private_key_deleted_at"
- ",slug"
- ",name"
- ",description"
- ",description_i18n::TEXT"
- ",mtf.valid_after"
- ",mtf.valid_before"
- ",duration"
- ",validity_granularity"
- ",start_offset"
- ",kind"
- ",issued"
- ",used"
- " FROM merchant_token_families mtf"
- " LEFT JOIN merchant_token_family_keys mtfk"
- " USING (token_family_serial)"
- " WHERE slug=$1"
- " AND COALESCE ($2 <= mtfk.signature_validity_end, TRUE)"
- " AND COALESCE ($3 >= mtfk.signature_validity_start, TRUE);");
+ PREPARE (pg,
+ "lookup_token_family_keys",
+ "SELECT"
+ " h_pub"
+ ",mtfk.pub"
+ ",mtfk.priv"
+ ",cipher_choice"
+ ",mtfk.signature_validity_start"
+ ",mtfk.signature_validity_end"
+ ",mtfk.private_key_deleted_at"
+ ",slug"
+ ",name"
+ ",description"
+ ",description_i18n::TEXT"
+ ",mtf.valid_after"
+ ",mtf.valid_before"
+ ",duration"
+ ",validity_granularity"
+ ",start_offset"
+ ",kind"
+ ",issued"
+ ",used"
+ " FROM merchant_token_families mtf"
+ " LEFT JOIN merchant_token_family_keys mtfk"
+ " USING (token_family_serial)"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " AND slug=$2"
+ " AND COALESCE ($3 <= mtfk.signature_validity_end, TRUE)"
+ " AND COALESCE ($4 >= mtfk.signature_validity_start, TRUE);");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_token_family_keys",
params,
&lookup_token_keys_cb,
&ctx);
diff --git a/src/backenddb/lookup_transfer_details.c b/src/backenddb/lookup_transfer_details.c
@@ -123,34 +123,30 @@ TALER_MERCHANTDB_lookup_transfer_details (
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_transfer_details",
- "SELECT"
- " mterm.h_contract_terms"
- ",mtcoin.offset_in_exchange_list"
- ",dep.coin_pub"
- ",mtcoin.exchange_deposit_value"
- ",mtcoin.exchange_deposit_fee"
- " FROM merchant_expected_transfer_to_coin mtcoin"
- " JOIN merchant_deposits dep"
- " USING (deposit_serial)"
- " JOIN merchant_deposit_confirmations mcon"
- " USING (deposit_confirmation_serial)"
- " JOIN merchant_contract_terms mterm"
- " USING (order_serial)"
- " JOIN merchant_expected_transfers met"
- " USING (expected_credit_serial)"
- " WHERE met.wtid=$2"
- " AND met.exchange_url=$1");
+ PREPARE (pg,
+ "lookup_transfer_details",
+ "SELECT"
+ " mterm.h_contract_terms"
+ ",mtcoin.offset_in_exchange_list"
+ ",dep.coin_pub"
+ ",mtcoin.exchange_deposit_value"
+ ",mtcoin.exchange_deposit_fee"
+ " FROM merchant_expected_transfer_to_coin mtcoin"
+ " JOIN merchant_deposits dep"
+ " USING (deposit_serial)"
+ " JOIN merchant_deposit_confirmations mcon"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_contract_terms mterm"
+ " USING (order_serial)"
+ " JOIN merchant_expected_transfers met"
+ " USING (expected_credit_serial)"
+ " WHERE met.wtid=$2"
+ " AND met.exchange_url=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_transfer_details",
params,
&lookup_transfer_details_cb,
<dc);
diff --git a/src/backenddb/lookup_transfer_details_by_order.c b/src/backenddb/lookup_transfer_details_by_order.c
@@ -201,39 +201,36 @@ TALER_MERCHANTDB_lookup_transfer_details_by_order (
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_transfer_details_by_order",
- "SELECT"
- " md.deposit_serial"
- ",mcon.exchange_url"
- ",met.wtid"
- ",mtc.exchange_deposit_value"
- ",mtc.exchange_deposit_fee"
- ",mcon.deposit_timestamp"
- ",met.confirmed"
- ",met.expected_credit_serial"
- " FROM merchant_expected_transfer_to_coin mtc"
- " JOIN merchant_deposits md"
- " USING (deposit_serial)"
- " JOIN merchant_deposit_confirmations mcon"
- " USING (deposit_confirmation_serial)"
- " JOIN merchant_expected_transfers met"
- " USING (expected_credit_serial)"
- " JOIN merchant_accounts acc"
- " ON (acc.account_serial = met.account_serial)"
- " JOIN merchant_contract_terms contracts"
- " USING (order_serial)"
- " WHERE mcon.order_serial=$1"
- " ORDER BY met.wtid");
+ PREPARE (pg,
+ "lookup_transfer_details_by_order",
+ "SELECT"
+ " md.deposit_serial"
+ ",mcon.exchange_url"
+ ",met.wtid"
+ ",mtc.exchange_deposit_value"
+ ",mtc.exchange_deposit_fee"
+ ",mcon.deposit_timestamp"
+ ",met.confirmed"
+ ",met.expected_credit_serial"
+ " FROM merchant_expected_transfer_to_coin mtc"
+ " JOIN merchant_deposits md"
+ " USING (deposit_serial)"
+ " JOIN merchant_deposit_confirmations mcon"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_expected_transfers met"
+ " USING (expected_credit_serial)"
+ " JOIN merchant_accounts acc"
+ " ON (acc.account_serial = met.account_serial)"
+ /* Check that all this is for the same instance */
+ " JOIN merchant_contract_terms contracts"
+ " USING (merchant_serial, order_serial)"
+ " WHERE mcon.order_serial=$1"
+ " ORDER BY met.wtid");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_transfer_details_by_order",
params,
&lookup_transfer_details_by_order_cb,
<do);
diff --git a/src/backenddb/lookup_transfer_summary.c b/src/backenddb/lookup_transfer_summary.c
@@ -121,32 +121,28 @@ TALER_MERCHANTDB_lookup_transfer_summary (
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_transfer_summary",
- "SELECT"
- " mct.order_id"
- ",mtc.exchange_deposit_value"
- ",mtc.exchange_deposit_fee"
- " FROM merchant_expected_transfers met"
- " JOIN merchant_expected_transfer_to_coin mtc"
- " USING (expected_credit_serial)"
- " JOIN merchant_deposits dep"
- " USING (deposit_serial)"
- " JOIN merchant_deposit_confirmations mcon"
- " USING (deposit_confirmation_serial)"
- " JOIN merchant_contract_terms mct"
- " USING (order_serial)"
- " WHERE met.wtid=$2"
- " AND met.exchange_url=$1");
+ PREPARE (pg,
+ "lookup_transfer_summary",
+ "SELECT"
+ " mct.order_id"
+ ",mtc.exchange_deposit_value"
+ ",mtc.exchange_deposit_fee"
+ " FROM merchant_expected_transfers met"
+ " JOIN merchant_expected_transfer_to_coin mtc"
+ " USING (expected_credit_serial)"
+ " JOIN merchant_deposits dep"
+ " USING (deposit_serial)"
+ " JOIN merchant_deposit_confirmations mcon"
+ " USING (deposit_confirmation_serial)"
+ " JOIN merchant_contract_terms mct"
+ " USING (order_serial)"
+ " WHERE met.wtid=$2"
+ " AND met.exchange_url=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "lookup_transfer_summary",
params,
&lookup_transfer_summary_cb,
<dc);
diff --git a/src/backenddb/lookup_transfers.c b/src/backenddb/lookup_transfers.c
@@ -147,6 +147,7 @@ TALER_MERCHANTDB_lookup_transfers (
.pg = pg
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_timestamp (&before),
GNUNET_PQ_query_param_timestamp (&after),
GNUNET_PQ_query_param_uint64 (&offset),
@@ -154,85 +155,88 @@ TALER_MERCHANTDB_lookup_transfers (
NULL == payto_uri.full_payto
? GNUNET_PQ_query_param_null () /* NULL: do not filter by payto URI */
: GNUNET_PQ_query_param_string (payto_uri.full_payto),
- GNUNET_PQ_query_param_bool (! by_time), /* $6: filter by time? */
+ GNUNET_PQ_query_param_bool (! by_time), /* $7: filter by time? */
GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_ALL == expected), /* filter by expected? */
GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_YES == expected),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "lookup_transfers_asc",
- "SELECT"
- " mt.credit_amount"
- ",mt.wtid"
- ",mac.payto_uri"
- ",mt.exchange_url"
- ",mt.credit_serial"
- ",mt.execution_time"
- ",mt.expected"
- ",met.expected_credit_serial"
- " FROM merchant_transfers mt"
- " JOIN merchant_accounts mac"
- " USING (account_serial)"
- " LEFT JOIN merchant_expected_transfers met"
- " ON mt.wtid = met.wtid"
- " AND mt.account_serial = met.account_serial"
- " AND mt.exchange_url = met.exchange_url"
- " AND mt.expected"
- " WHERE ( $6 OR "
- " (mt.execution_time < $1 AND"
- " mt.execution_time >= $2) )"
- " AND ( (CAST($5 AS TEXT) IS NULL) OR "
- " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
- " =REGEXP_REPLACE($5,'\\?.*','')) )"
- " AND ( $7 OR "
- " (mt.expected = $8) )"
- " AND (mt.credit_serial > $3)"
- " ORDER BY mt.credit_serial ASC"
- " LIMIT $4");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_transfers_desc",
- "SELECT"
- " mt.credit_amount"
- ",mt.wtid"
- ",mac.payto_uri"
- ",mt.exchange_url"
- ",mt.credit_serial"
- ",mt.execution_time"
- ",mt.expected"
- ",met.expected_credit_serial"
- " FROM merchant_transfers mt"
- " JOIN merchant_accounts mac"
- " USING (account_serial)"
- " LEFT JOIN merchant_expected_transfers met"
- " ON mt.wtid = met.wtid"
- " AND mt.account_serial = met.account_serial"
- " AND mt.exchange_url = met.exchange_url"
- " AND mt.expected"
- " WHERE ( $6 OR "
- " (mt.execution_time < $1 AND"
- " mt.execution_time >= $2) )"
- " AND ( (CAST($5 AS TEXT) IS NULL) OR "
- " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
- " =REGEXP_REPLACE($5,'\\?.*','')) )"
- " AND ( $7 OR "
- " (mt.expected = $8) )"
- " AND (mt.credit_serial < $3)"
- " ORDER BY mt.credit_serial DESC"
- " LIMIT $4");
+ PREPARE (pg,
+ "lookup_transfers_asc",
+ "SELECT"
+ " mt.credit_amount"
+ ",mt.wtid"
+ ",mac.payto_uri"
+ ",mt.exchange_url"
+ ",mt.credit_serial"
+ ",mt.execution_time"
+ ",mt.expected"
+ ",met.expected_credit_serial"
+ " FROM merchant_transfers mt"
+ " JOIN merchant_accounts mac"
+ " USING (account_serial)"
+ " LEFT JOIN merchant_expected_transfers met"
+ " ON mt.wtid = met.wtid"
+ " AND mt.account_serial = met.account_serial"
+ " AND mt.exchange_url = met.exchange_url"
+ " AND mt.expected"
+ " WHERE ( $7 OR "
+ " (mt.execution_time < $2 AND"
+ " mt.execution_time >= $3) )"
+ " AND ( (CAST($6 AS TEXT) IS NULL) OR "
+ " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
+ " =REGEXP_REPLACE($6,'\\?.*','')) )"
+ " AND ( $8 OR "
+ " (mt.expected = $9) )"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND (mt.credit_serial > $4)"
+ " ORDER BY mt.credit_serial ASC"
+ " LIMIT $5");
+ PREPARE (pg,
+ "lookup_transfers_desc",
+ "SELECT"
+ " mt.credit_amount"
+ ",mt.wtid"
+ ",mac.payto_uri"
+ ",mt.exchange_url"
+ ",mt.credit_serial"
+ ",mt.execution_time"
+ ",mt.expected"
+ ",met.expected_credit_serial"
+ " FROM merchant_transfers mt"
+ " JOIN merchant_accounts mac"
+ " USING (account_serial)"
+ " LEFT JOIN merchant_expected_transfers met"
+ " ON mt.wtid = met.wtid"
+ " AND mt.account_serial = met.account_serial"
+ " AND mt.exchange_url = met.exchange_url"
+ " AND mt.expected"
+ " WHERE ( $7 OR "
+ " (mt.execution_time < $2 AND"
+ " mt.execution_time >= $3) )"
+ " AND ( (CAST($6 AS TEXT) IS NULL) OR "
+ " (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
+ " =REGEXP_REPLACE($6,'\\?.*','')) )"
+ " AND ( $8 OR "
+ " (mt.expected = $9) )"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND (mt.credit_serial < $4)"
+ " ORDER BY mt.credit_serial DESC"
+ " LIMIT $5");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- (limit > 0) ? stmt_asc : stmt_desc,
+ (limit > 0)
+ ? "lookup_transfers_asc"
+ : "lookup_transfers_desc",
params,
&lookup_transfers_cb,
<c);
diff --git a/src/backenddb/lookup_units.c b/src/backenddb/lookup_units.c
@@ -100,46 +100,48 @@ TALER_MERCHANTDB_lookup_units (struct TALER_MERCHANTDB_PostgresContext *pg,
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_units",
- "SELECT cu.unit_serial"
- " ,cu.unit"
- " ,cu.unit_name_long"
- " ,cu.unit_name_short"
- " ,cu.unit_name_long_i18n"
- " ,cu.unit_name_short_i18n"
- " ,cu.unit_allow_fraction"
- " ,cu.unit_precision_level"
- " ,cu.unit_active"
- " ,FALSE AS unit_builtin"
- " FROM merchant_custom_units cu"
- " UNION ALL "
- "SELECT bu.unit_serial"
- " ,bu.unit"
- " ,bu.unit_name_long"
- " ,bu.unit_name_short"
- " ,bu.unit_name_long_i18n"
- " ,bu.unit_name_short_i18n"
- " ,COALESCE(bo.override_allow_fraction, bu.unit_allow_fraction)"
- " ,COALESCE(bo.override_precision_level, bu.unit_precision_level)"
- " ,COALESCE(bo.override_active, bu.unit_active)"
- " ,TRUE AS unit_builtin"
- " FROM merchant.merchant_builtin_units bu"
- " LEFT JOIN merchant_builtin_unit_overrides bo"
- " ON bo.builtin_unit_serial = bu.unit_serial"
- " ORDER BY unit");
+ PREPARE (pg,
+ "lookup_units",
+ "WITH mi AS ("
+ " SELECT merchant_serial FROM merchant_instances WHERE merchant_id=$1"
+ ")"
+ "SELECT cu.unit_serial"
+ " ,cu.unit"
+ " ,cu.unit_name_long"
+ " ,cu.unit_name_short"
+ " ,cu.unit_name_long_i18n"
+ " ,cu.unit_name_short_i18n"
+ " ,cu.unit_allow_fraction"
+ " ,cu.unit_precision_level"
+ " ,cu.unit_active"
+ " ,FALSE AS unit_builtin"
+ " FROM merchant_custom_units cu"
+ " JOIN mi ON cu.merchant_serial = mi.merchant_serial"
+ " UNION ALL "
+ "SELECT bu.unit_serial"
+ " ,bu.unit"
+ " ,bu.unit_name_long"
+ " ,bu.unit_name_short"
+ " ,bu.unit_name_long_i18n"
+ " ,bu.unit_name_short_i18n"
+ " ,COALESCE(bo.override_allow_fraction, bu.unit_allow_fraction)"
+ " ,COALESCE(bo.override_precision_level, bu.unit_precision_level)"
+ " ,COALESCE(bo.override_active, bu.unit_active)"
+ " ,TRUE AS unit_builtin"
+ " FROM merchant_builtin_units bu"
+ " JOIN mi ON TRUE"
+ " LEFT JOIN merchant_builtin_unit_overrides bo"
+ " ON bo.builtin_unit_serial = bu.unit_serial"
+ " AND bo.merchant_serial = mi.merchant_serial"
+ " ORDER BY unit");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_units",
params,
&lookup_units_cb,
&luc);
diff --git a/src/backenddb/lookup_webhook.c b/src/backenddb/lookup_webhook.c
@@ -32,26 +32,25 @@ TALER_MERCHANTDB_lookup_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
struct TALER_MERCHANTDB_WebhookDetails *wb)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (webhook_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_webhook",
- "SELECT"
- " event_type"
- ",url"
- ",http_method"
- ",header_template"
- ",body_template"
- " FROM merchant_webhook"
- " WHERE webhook_id=$1");
+ PREPARE (pg,
+ "lookup_webhook",
+ "SELECT"
+ " event_type"
+ ",url"
+ ",http_method"
+ ",header_template"
+ ",body_template"
+ " FROM merchant_webhook"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_webhook.webhook_id=$2");
if (NULL == wb)
{
@@ -60,7 +59,7 @@ TALER_MERCHANTDB_lookup_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
};
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_webhook",
params,
rs_null);
}
@@ -85,7 +84,7 @@ TALER_MERCHANTDB_lookup_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
};
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "lookup_webhook",
params,
rs);
}
diff --git a/src/backenddb/lookup_webhook_by_event.c b/src/backenddb/lookup_webhook_by_event.c
@@ -124,31 +124,30 @@ TALER_MERCHANTDB_lookup_webhook_by_event (struct TALER_MERCHANTDB_PostgresContex
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (event_type),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_webhook_by_event",
- "SELECT"
- " webhook_serial"
- ",event_type"
- ",url"
- ",http_method"
- ",header_template"
- ",body_template"
- " FROM merchant_webhook"
- " WHERE event_type=$1");
+ PREPARE (pg,
+ "lookup_webhook_by_event",
+ "SELECT"
+ " webhook_serial"
+ ",event_type"
+ ",url"
+ ",http_method"
+ ",header_template"
+ ",body_template"
+ " FROM merchant_webhook"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND event_type=$2");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_webhook_by_event",
params,
&lookup_webhook_by_event_cb,
&wlc);
diff --git a/src/backenddb/lookup_webhooks.c b/src/backenddb/lookup_webhooks.c
@@ -104,25 +104,24 @@ TALER_MERCHANTDB_lookup_webhooks (struct TALER_MERCHANTDB_PostgresContext *pg,
.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;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "lookup_webhooks",
- "SELECT"
- " webhook_id"
- ",event_type"
- " FROM merchant_webhook");
+ PREPARE (pg,
+ "lookup_webhooks",
+ "SELECT"
+ " webhook_id"
+ ",event_type"
+ " FROM merchant_webhook"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "lookup_webhooks",
params,
&lookup_webhooks_cb,
&wlc);
diff --git a/src/backenddb/mark_contract_paid.c b/src/backenddb/mark_contract_paid.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_mark_contract_paid (struct TALER_MERCHANTDB_PostgresContext *pg
int16_t choice_index)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_string (session_id),
(choice_index >= 0)
@@ -41,19 +42,14 @@ TALER_MERCHANTDB_mark_contract_paid (struct TALER_MERCHANTDB_PostgresContext *pg
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam uparams[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_paid[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_sold[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_del[PG_PREP_INSTANCE_NAME_MAX];
/* Session ID must always be given by the caller. */
GNUNET_assert (NULL != session_id);
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
/* no preflight check here, run in transaction by caller! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -61,55 +57,65 @@ TALER_MERCHANTDB_mark_contract_paid (struct TALER_MERCHANTDB_PostgresContext *pg
GNUNET_h2s (&h_contract_terms->hash),
instance_id,
session_id);
- PREPARE_INSTANCE (pg,
- stmt_paid,
- "mark_contract_paid",
- "UPDATE merchant_contract_terms SET"
- " paid=TRUE"
- ",session_id=$2"
- ",choice_index=$3"
- " WHERE h_contract_terms=$1");
+ PREPARE (pg,
+ "mark_contract_paid",
+ "UPDATE merchant_contract_terms SET"
+ " paid=TRUE"
+ ",session_id=$3"
+ ",choice_index=$4"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt_paid,
+ "mark_contract_paid",
params);
if (qs <= 0)
return qs;
- PREPARE_INSTANCE (pg,
- stmt_sold,
- "mark_inventory_sold",
- "UPDATE merchant_inventory SET"
- " total_sold = total_sold"
- " + order_locks.total_locked"
- " + ((merchant_inventory.total_sold_frac::BIGINT"
- " + order_locks.total_locked_frac::BIGINT) / 1000000)"
- " ,total_sold_frac ="
- " ((merchant_inventory.total_sold_frac::BIGINT"
- " + order_locks.total_locked_frac::BIGINT) % 1000000)::INT4"
- " FROM (SELECT total_locked,total_locked_frac,product_serial"
- " FROM merchant_order_locks"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)"
- " ) AS order_locks"
- " WHERE merchant_inventory.product_serial"
- " =order_locks.product_serial");
+ PREPARE (pg,
+ "mark_inventory_sold",
+ "UPDATE merchant_inventory SET"
+ " total_sold = total_sold"
+ " + order_locks.total_locked"
+ " + ((merchant_inventory.total_sold_frac::BIGINT"
+ " + order_locks.total_locked_frac::BIGINT) / 1000000)"
+ " ,total_sold_frac ="
+ " ((merchant_inventory.total_sold_frac::BIGINT"
+ " + order_locks.total_locked_frac::BIGINT) % 1000000)::INT4"
+ " FROM (SELECT total_locked,total_locked_frac,product_serial"
+ " FROM merchant_order_locks"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))"
+ " ) AS order_locks"
+ " WHERE merchant_inventory.product_serial"
+ " =order_locks.product_serial");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt_sold,
+ "mark_inventory_sold",
uparams);
if (qs < 0)
return qs; /* 0: no inventory management, that's OK! */
/* ON DELETE CASCADE deletes from merchant_order_locks */
- PREPARE_INSTANCE (pg,
- stmt_del,
- "delete_completed_order",
- "DELETE"
- " FROM merchant_orders"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)");
+ PREPARE (pg,
+ "delete_completed_order",
+ "WITH md AS"
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1) "
+ "DELETE"
+ " FROM merchant_orders"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " JOIN md USING (merchant_serial)"
+ " WHERE h_contract_terms=$2)");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt_del,
+ "delete_completed_order",
uparams);
}
diff --git a/src/backenddb/mark_order_wired.c b/src/backenddb/mark_order_wired.c
@@ -34,18 +34,14 @@ TALER_MERCHANTDB_mark_order_wired (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "mark_order_wired",
- "UPDATE merchant_contract_terms SET"
- " wired=TRUE"
- " WHERE order_serial=$1");
+ PREPARE (pg,
+ "mark_order_wired",
+ "UPDATE merchant_contract_terms SET"
+ " wired=TRUE"
+ " WHERE order_serial=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "mark_order_wired",
params);
}
diff --git a/src/backenddb/meson.build b/src/backenddb/meson.build
@@ -14,7 +14,6 @@ libtalermerchantdb = library(
'event_listen.c',
'event_notify.c',
'preflight.c',
- 'set_instance.c',
'account_kyc_get_outdated.c',
'account_kyc_get_status.c',
'account_kyc_set_failed.c',
diff --git a/src/backenddb/pg.c b/src/backenddb/pg.c
@@ -85,7 +85,6 @@ void
TALER_MERCHANTDB_disconnect (struct TALER_MERCHANTDB_PostgresContext *pg)
{
GNUNET_PQ_disconnect (pg->conn);
- GNUNET_free (pg->current_merchant_id);
GNUNET_free (pg);
}
diff --git a/src/backenddb/pg_account_kyc_get_outdated.sql b/src/backenddb/pg_account_kyc_get_outdated.sql
@@ -1,57 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.account_kyc_get_outdated(INT8);
-CREATE FUNCTION merchant.account_kyc_get_outdated(IN p_now INT8)
-RETURNS TABLE(
- out_merchant_id TEXT,
- out_h_wire BYTEA,
- out_exchange_url TEXT)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_id FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- FOR inner_rec IN
- EXECUTE format('SELECT ma.h_wire AS h_wire, kyc.exchange_url AS exchange_url'
- ' FROM %I.merchant_kyc kyc'
- ' JOIN %I.merchant_accounts ma USING (account_serial)'
- ' WHERE kyc.next_kyc_poll < $1'
- ' ORDER BY kyc.next_kyc_poll ASC', s, s)
- USING p_now
- LOOP
- out_merchant_id := rec.merchant_id;
- out_h_wire := inner_rec.h_wire;
- out_exchange_url := inner_rec.exchange_url;
- RETURN NEXT;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.account_kyc_get_outdated(INT8)
- IS 'Returns one row per outdated KYC entry across all instance schemas.'
- ' An entry is outdated if its next_kyc_poll value is less than p_now.';
diff --git a/src/backenddb/pg_create_instance_schema.sql b/src/backenddb/pg_create_instance_schema.sql
@@ -1,39 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.create_instance_schema(BIGINT);
-CREATE FUNCTION merchant.create_instance_schema(in_merchant_serial BIGINT)
- RETURNS void
- LANGUAGE plpgsql
- AS $FN$
-DECLARE
- s TEXT := 'merchant_instance_' || in_merchant_serial::TEXT;
-BEGIN
- -- Resolve bare type references (statistic_range, taler_amount_currency, ...)
- -- and bare table references in trigger / procedure bodies against the new
- -- per-instance schema first, then fall through to merchant.
- EXECUTE format('SET LOCAL search_path TO %I, merchant', s);
-#include "pg_create_instance_schema_tables.sql.fragment"
-#include "pg_create_instance_schema_triggers.sql.fragment"
-#include "pg_create_instance_schema_procedures.sql.fragment"
-END;
-$FN$;
-COMMENT ON FUNCTION merchant.create_instance_schema(BIGINT)
- IS 'Constructs the per-instance schema merchant_instance_<merchant_serial>'
- ' with all per-instance tables, indexes, foreign keys, trigger functions,'
- ' triggers and stored procedures. Called from'
- ' merchant_instances_after_insert_trigger() whenever a new instance row'
- ' is inserted into merchant.merchant_instances.';
diff --git a/src/backenddb/pg_create_instance_schema_procedures.sql.fragment b/src/backenddb/pg_create_instance_schema_procedures.sql.fragment
@@ -1,2214 +0,0 @@
--- =====================================================================
--- Per-instance schema constructor: stored procedures and functions.
---
--- Embedded inside merchant.create_instance_schema(BIGINT); local var
--- `s TEXT` holds the per-instance schema name. All DDL is via
--- EXECUTE format(...) with %I quoting.
---
--- The merchant_serial column has been dropped from every per-instance
--- table; the in_instance_id / in_instance_name / in_merchant_serial /
--- out_no_instance parameters and the merchant_serial-resolution
--- prologue are removed from each procedure. Helper functions
--- (replace_placeholder, interval_to_start, ...) and global tables
--- (merchant_instances, merchant_exchange_*, merchant_builtin_units,
--- merchant_donau_keys) keep their `merchant.` qualifier.
--- =====================================================================
-
- -- -------------------------------------------------------------------
- -- Statistic bump procedures (6 procedures)
- -- -------------------------------------------------------------------
-
- -- merchant_do_bump_amount_bucket_stat
- EXECUTE format($OUTER$
- CREATE PROCEDURE %I.merchant_do_bump_amount_bucket_stat(IN in_slug text, IN in_timestamp timestamp without time zone, IN in_delta merchant.taler_amount_currency)
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_meta INT8;
- my_range statistic_range;
- my_bucket_start INT8;
- my_curs CURSOR (arg_slug TEXT)
- FOR SELECT UNNEST(ranges)
- FROM merchant_statistic_bucket_meta
- WHERE slug=arg_slug;
- BEGIN
- SELECT bmeta_serial_id
- INTO my_meta
- FROM merchant_statistic_bucket_meta
- WHERE slug=in_slug
- AND stype='amount';
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- OPEN my_curs (arg_slug:=in_slug);
- LOOP
- FETCH NEXT
- FROM my_curs
- INTO my_range;
- EXIT WHEN NOT FOUND;
- SELECT *
- INTO my_bucket_start
- FROM merchant.interval_to_start (in_timestamp, my_range);
- UPDATE merchant_statistic_bucket_amount
- SET
- cumulative_value = cumulative_value + (in_delta).val
- + CASE
- WHEN (in_delta).frac + cumulative_frac >= 100000000
- THEN 1
- ELSE 0
- END,
- cumulative_frac = cumulative_frac + (in_delta).frac
- - CASE
- WHEN (in_delta).frac + cumulative_frac >= 100000000
- THEN 100000000
- ELSE 0
- END
- WHERE bmeta_serial_id=my_meta
- AND curr=(in_delta).curr
- AND bucket_start=my_bucket_start
- AND bucket_range=my_range;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_statistic_bucket_amount
- (bmeta_serial_id
- ,bucket_start
- ,bucket_range
- ,curr
- ,cumulative_value
- ,cumulative_frac
- ) VALUES (
- my_meta
- ,my_bucket_start
- ,my_range
- ,(in_delta).curr
- ,(in_delta).val
- ,(in_delta).frac);
- END IF;
- END LOOP;
- CLOSE my_curs;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_bump_amount_interval_stat
- EXECUTE format($OUTER$
- CREATE PROCEDURE %I.merchant_do_bump_amount_interval_stat(IN in_slug text, IN in_timestamp timestamp without time zone, IN in_delta merchant.taler_amount_currency)
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_now INT8;
- my_record RECORD;
- my_meta INT8;
- my_ranges INT8[];
- my_precisions INT8[];
- my_x INT;
- my_rangex INT8;
- my_precisionx INT8;
- my_start INT8;
- my_event INT8;
- BEGIN
- my_now = ROUND(EXTRACT(epoch FROM CURRENT_TIMESTAMP(0)::TIMESTAMP) * 1000000)::INT8 / 1000 / 1000;
- SELECT imeta_serial_id
- ,ranges
- ,precisions
- INTO my_record
- FROM merchant_statistic_interval_meta
- WHERE slug=in_slug
- AND stype='amount';
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- my_start = ROUND(EXTRACT(epoch FROM in_timestamp) * 1000000)::INT8 / 1000 / 1000;
- my_precisions = my_record.precisions;
- my_ranges = my_record.ranges;
- my_rangex = NULL;
- FOR my_x IN 1..COALESCE(array_length(my_ranges,1),0)
- LOOP
- IF my_now - my_ranges[my_x] < my_start
- THEN
- my_rangex = my_ranges[my_x];
- my_precisionx = my_precisions[my_x];
- EXIT;
- END IF;
- END LOOP;
- IF my_rangex IS NULL
- THEN
- RETURN;
- END IF;
- my_start = my_start - my_start %% my_precisionx;
- my_meta = my_record.imeta_serial_id;
- INSERT INTO merchant_statistic_amount_event AS msae
- (imeta_serial_id
- ,slot
- ,delta_curr
- ,delta_value
- ,delta_frac
- ) VALUES (
- my_meta
- ,my_start
- ,(in_delta).curr
- ,(in_delta).val
- ,(in_delta).frac
- )
- ON CONFLICT (imeta_serial_id, slot, delta_curr)
- DO UPDATE SET
- delta_value = msae.delta_value + (in_delta).val
- + CASE
- WHEN (in_delta).frac + msae.delta_frac >= 100000000
- THEN 1
- ELSE 0
- END,
- delta_frac = msae.delta_frac + (in_delta).frac
- - CASE
- WHEN (in_delta).frac + msae.delta_frac >= 100000000
- THEN 100000000
- ELSE 0
- END
- RETURNING aevent_serial_id
- INTO my_event;
- UPDATE merchant_statistic_interval_amount
- SET
- cumulative_value = cumulative_value + (in_delta).val
- + CASE
- WHEN (in_delta).frac + cumulative_frac >= 100000000
- THEN 1
- ELSE 0
- END,
- cumulative_frac = cumulative_frac + (in_delta).frac
- - CASE
- WHEN (in_delta).frac + cumulative_frac >= 100000000
- THEN 100000000
- ELSE 0
- END
- WHERE imeta_serial_id=my_meta
- AND range=my_rangex
- AND curr=(in_delta).curr;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_statistic_interval_amount
- (imeta_serial_id
- ,range
- ,event_delimiter
- ,curr
- ,cumulative_value
- ,cumulative_frac
- ) VALUES (
- my_meta
- ,my_rangex
- ,my_event
- ,(in_delta).curr
- ,(in_delta).val
- ,(in_delta).frac);
- END IF;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_bump_amount_stat
- EXECUTE format($OUTER$
- CREATE PROCEDURE %I.merchant_do_bump_amount_stat(IN in_slug text, IN in_timestamp timestamp without time zone, IN in_delta merchant.taler_amount_currency)
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_amount_bucket_stat (in_slug, in_timestamp, in_delta);
- CALL merchant_do_bump_amount_interval_stat (in_slug, in_timestamp, in_delta);
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_bump_number_bucket_stat
- EXECUTE format($OUTER$
- CREATE PROCEDURE %I.merchant_do_bump_number_bucket_stat(IN in_slug text, IN in_timestamp timestamp without time zone, IN in_delta bigint)
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_meta INT8;
- my_range statistic_range;
- my_bucket_start INT8;
- my_curs CURSOR (arg_slug TEXT)
- FOR SELECT UNNEST(ranges)
- FROM merchant_statistic_bucket_meta
- WHERE slug=arg_slug;
- BEGIN
- SELECT bmeta_serial_id
- INTO my_meta
- FROM merchant_statistic_bucket_meta
- WHERE slug=in_slug
- AND stype='number';
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- OPEN my_curs (arg_slug:=in_slug);
- LOOP
- FETCH NEXT
- FROM my_curs
- INTO my_range;
- EXIT WHEN NOT FOUND;
- SELECT *
- INTO my_bucket_start
- FROM merchant.interval_to_start (in_timestamp, my_range);
- UPDATE merchant_statistic_bucket_counter
- SET cumulative_number = cumulative_number + in_delta
- WHERE bmeta_serial_id=my_meta
- AND bucket_start=my_bucket_start
- AND bucket_range=my_range;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_statistic_bucket_counter
- (bmeta_serial_id
- ,bucket_start
- ,bucket_range
- ,cumulative_number
- ) VALUES (
- my_meta
- ,my_bucket_start
- ,my_range
- ,in_delta);
- END IF;
- END LOOP;
- CLOSE my_curs;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_bump_number_interval_stat
- EXECUTE format($OUTER$
- CREATE PROCEDURE %I.merchant_do_bump_number_interval_stat(IN in_slug text, IN in_timestamp timestamp without time zone, IN in_delta bigint)
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_now INT8;
- my_record RECORD;
- my_meta INT8;
- my_ranges INT8[];
- my_precisions INT8[];
- my_rangex INT8;
- my_precisionx INT8;
- my_start INT8;
- my_event INT8;
- BEGIN
- my_now = ROUND(EXTRACT(epoch FROM CURRENT_TIMESTAMP(0)::TIMESTAMP) * 1000000)::INT8 / 1000 / 1000;
- SELECT imeta_serial_id
- ,ranges AS ranges
- ,precisions AS precisions
- INTO my_record
- FROM merchant_statistic_interval_meta
- WHERE slug=in_slug
- AND stype='number';
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- my_start = ROUND(EXTRACT(epoch FROM in_timestamp) * 1000000)::INT8 / 1000 / 1000;
- my_precisions = my_record.precisions;
- my_ranges = my_record.ranges;
- my_rangex = NULL;
- FOR my_x IN 1..COALESCE(array_length(my_ranges,1),0)
- LOOP
- IF my_now - my_ranges[my_x] < my_start
- THEN
- my_rangex = my_ranges[my_x];
- my_precisionx = my_precisions[my_x];
- EXIT;
- END IF;
- END LOOP;
- IF my_rangex IS NULL
- THEN
- RETURN;
- END IF;
- my_meta = my_record.imeta_serial_id;
- my_start = my_start - my_start %% my_precisionx;
- INSERT INTO merchant_statistic_counter_event AS msce
- (imeta_serial_id
- ,slot
- ,delta)
- VALUES
- (my_meta
- ,my_start
- ,in_delta)
- ON CONFLICT (imeta_serial_id, slot)
- DO UPDATE SET
- delta = msce.delta + in_delta
- RETURNING nevent_serial_id
- INTO my_event;
- UPDATE merchant_statistic_interval_counter
- SET cumulative_number = cumulative_number + in_delta
- WHERE imeta_serial_id = my_meta
- AND range=my_rangex;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_statistic_interval_counter
- (imeta_serial_id
- ,range
- ,event_delimiter
- ,cumulative_number
- ) VALUES (
- my_meta
- ,my_rangex
- ,my_event
- ,in_delta);
- END IF;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_bump_number_stat
- EXECUTE format($OUTER$
- CREATE PROCEDURE %I.merchant_do_bump_number_stat(IN in_slug text, IN in_timestamp timestamp without time zone, IN in_delta bigint)
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_number_bucket_stat (in_slug, in_timestamp, in_delta);
- CALL merchant_do_bump_number_interval_stat (in_slug, in_timestamp, in_delta);
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Account / KYC functions
- -- -------------------------------------------------------------------
-
- -- merchant_do_account_kyc_get_status
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_account_kyc_get_status(in_now bigint, in_exchange_url text, in_h_wire bytea) RETURNS TABLE(out_h_wire bytea, out_payto_uri text, out_exchange_url text, out_kyc_timestamp bigint, out_kyc_ok boolean, out_access_token bytea, out_exchange_http_status integer, out_exchange_ec_code integer, out_aml_review boolean, out_jaccount_limits text)
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_account_serial INT8;
- my_h_wire BYTEA;
- my_payto_uri TEXT;
- my_kyc_record RECORD;
- BEGIN
- FOR my_account_serial, my_h_wire, my_payto_uri
- IN SELECT account_serial, h_wire, payto_uri
- FROM merchant_accounts
- WHERE active
- AND (in_h_wire IS NULL OR h_wire = in_h_wire)
- ORDER BY account_serial ASC
- LOOP
- FOR my_kyc_record IN
- SELECT
- mk.kyc_serial_id
- ,mk.exchange_url
- ,mk.kyc_timestamp
- ,mk.kyc_ok
- ,mk.access_token
- ,mk.exchange_http_status
- ,mk.exchange_ec_code
- ,mk.aml_review
- ,mk.jaccount_limits::TEXT
- FROM merchant_kyc mk
- WHERE mk.account_serial = my_account_serial
- AND (in_exchange_url IS NULL OR mk.exchange_url = in_exchange_url)
- ORDER BY mk.kyc_serial_id ASC
- LOOP
- UPDATE merchant_kyc
- SET next_kyc_poll=in_now
- WHERE kyc_serial_id = my_kyc_record.kyc_serial_id;
- NOTIFY XDQM4Z4N0D3GX0H9JEXH70EBC2T3KY7HC0TJB0Z60D2H781RXR6AG;
- RETURN QUERY
- SELECT
- my_h_wire,
- my_payto_uri,
- my_kyc_record.exchange_url,
- my_kyc_record.kyc_timestamp,
- my_kyc_record.kyc_ok,
- my_kyc_record.access_token,
- my_kyc_record.exchange_http_status,
- my_kyc_record.exchange_ec_code,
- my_kyc_record.aml_review,
- my_kyc_record.jaccount_limits::TEXT;
- END LOOP;
- IF NOT FOUND
- THEN
- RETURN QUERY
- SELECT
- my_h_wire,
- my_payto_uri,
- NULL::TEXT,
- NULL::INT8,
- NULL::BOOLEAN,
- NULL::BYTEA,
- NULL::INT4,
- NULL::INT4,
- NULL::BOOLEAN,
- NULL::TEXT;
- END IF;
- END LOOP;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_account_kyc_set_failed
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_account_kyc_set_failed(in_h_wire bytea, in_exchange_url text, in_timestamp bigint, in_exchange_http_status integer, in_kyc_ok boolean, in_notify_str text, in_notify2_str text, OUT out_no_account boolean) RETURNS boolean
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_account_serial INT8;
- BEGIN
- out_no_account=FALSE;
- SELECT account_serial
- INTO my_account_serial
- FROM merchant_accounts
- WHERE h_wire=in_h_wire;
- IF NOT FOUND
- THEN
- out_no_account=TRUE;
- RETURN;
- END IF;
- UPDATE merchant_kyc
- SET kyc_timestamp=in_timestamp
- ,kyc_ok=in_kyc_ok
- ,exchange_http_status=in_exchange_http_status
- ,exchange_ec_code=0
- WHERE account_serial=my_account_serial
- AND exchange_url=in_exchange_url;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_kyc
- (kyc_timestamp
- ,kyc_ok
- ,account_serial
- ,exchange_url
- ,exchange_http_status)
- VALUES
- (in_timestamp
- ,in_kyc_ok
- ,my_account_serial
- ,in_exchange_url
- ,in_exchange_http_status);
- END IF;
- EXECUTE FORMAT (
- 'NOTIFY %%s'
- ,in_notify_str);
- EXECUTE FORMAT (
- 'NOTIFY %%s'
- ,in_notify2_str);
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_account_kyc_set_status
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_account_kyc_set_status(in_h_wire bytea, in_exchange_url text, in_timestamp bigint, in_exchange_http_status integer, in_exchange_ec_code integer, in_access_token bytea, in_jlimits jsonb, in_aml_active boolean, in_kyc_ok boolean, in_notify_str text, in_notify2_str text, in_rule_gen bigint, in_next_time bigint, in_kyc_backoff bigint, OUT out_no_account boolean) RETURNS boolean
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_account_serial INT8;
- BEGIN
- out_no_account=FALSE;
- SELECT account_serial
- INTO my_account_serial
- FROM merchant_accounts
- WHERE h_wire=in_h_wire;
- IF NOT FOUND
- THEN
- out_no_account=TRUE;
- RETURN;
- END IF;
- UPDATE merchant_kyc
- SET kyc_timestamp=in_timestamp
- ,kyc_ok=in_kyc_ok
- ,jaccount_limits=in_jlimits
- ,aml_review=in_aml_active
- ,exchange_http_status=in_exchange_http_status
- ,exchange_ec_code=in_exchange_ec_code
- ,access_token=in_access_token
- ,last_rule_gen=in_rule_gen
- ,next_kyc_poll=in_next_time
- ,kyc_backoff=in_kyc_backoff
- WHERE account_serial=my_account_serial
- AND exchange_url=in_exchange_url;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_kyc
- (kyc_timestamp
- ,kyc_ok
- ,account_serial
- ,exchange_url
- ,jaccount_limits
- ,aml_review
- ,exchange_http_status
- ,exchange_ec_code
- ,access_token
- ,last_rule_gen
- ,next_kyc_poll
- ,kyc_backoff)
- VALUES
- (in_timestamp
- ,in_kyc_ok
- ,my_account_serial
- ,in_exchange_url
- ,in_jlimits
- ,in_aml_active
- ,in_exchange_http_status
- ,in_exchange_ec_code
- ,in_access_token
- ,in_rule_gen
- ,in_next_time
- ,in_kyc_backoff);
- END IF;
- EXECUTE FORMAT (
- 'NOTIFY %%s'
- ,in_notify_str);
- EXECUTE FORMAT (
- 'NOTIFY %%s'
- ,in_notify2_str);
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_activate_account
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_activate_account(in_h_wire bytea, in_salt bytea, in_full_payto text, in_credit_facade_url text, in_credit_facade_credentials text, in_extra_wire_subject_metadata text, OUT out_h_wire bytea, OUT out_salt bytea, OUT out_not_found boolean, OUT out_conflict boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE my_active BOOL;
- DECLARE my_cfu TEXT;
- DECLARE my_cfc TEXT;
- DECLARE my_ewsm TEXT;
- DECLARE my_h_wire BYTEA;
- DECLARE my_salt BYTEA;
- BEGIN
- out_not_found = FALSE;
- out_conflict = FALSE;
- out_h_wire = in_h_wire;
- out_salt = in_salt;
- INSERT INTO merchant_accounts
- AS ma
- (h_wire
- ,salt
- ,payto_uri
- ,credit_facade_url
- ,credit_facade_credentials
- ,active
- ,extra_wire_subject_metadata
- ) VALUES (
- in_h_wire
- ,in_salt
- ,in_full_payto
- ,in_credit_facade_url
- ,in_credit_facade_credentials::JSONB
- ,TRUE
- ,in_extra_wire_subject_metadata
- ) ON CONFLICT DO NOTHING;
- IF FOUND
- THEN
- NOTIFY XDQM4Z4N0D3GX0H9JEXH70EBC2T3KY7HC0TJB0Z60D2H781RXR6AG;
- RETURN;
- END IF;
- SELECT h_wire
- ,salt
- ,active
- ,credit_facade_url
- ,credit_facade_credentials::TEXT
- ,extra_wire_subject_metadata
- INTO my_h_wire
- ,my_salt
- ,my_active
- ,my_cfu
- ,my_cfc
- ,my_ewsm
- FROM merchant_accounts
- WHERE payto_uri=in_full_payto;
- IF NOT FOUND
- THEN
- out_not_found = TRUE;
- RETURN;
- END IF;
- IF (my_active AND
- (ROW (my_cfu
- ,my_cfc
- ,my_ewsm)
- IS DISTINCT FROM
- ROW (in_credit_facade_url
- ,in_credit_facade_credentials
- ,in_extra_wire_subject_metadata)))
- THEN
- out_conflict = TRUE;
- RETURN;
- END IF;
- out_salt = my_salt;
- out_h_wire = my_h_wire;
- IF my_active
- THEN
- RETURN;
- END IF;
- UPDATE merchant_accounts
- SET active=TRUE
- ,credit_facade_url=in_credit_facade_url
- ,credit_facade_credentials=in_credit_facade_credentials::JSONB
- ,extra_wire_subject_metadata=in_extra_wire_subject_metadata
- WHERE h_wire=out_h_wire;
- NOTIFY XDQM4Z4N0D3GX0H9JEXH70EBC2T3KY7HC0TJB0Z60D2H781RXR6AG;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_inactivate_account
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_inactivate_account(in_h_wire bytea, OUT out_found boolean) RETURNS boolean
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- UPDATE merchant_accounts
- SET active=FALSE
- WHERE h_wire=in_h_wire;
- out_found = FOUND;
- IF out_found
- THEN
- NOTIFY XDQM4Z4N0D3GX0H9JEXH70EBC2T3KY7HC0TJB0Z60D2H781RXR6AG;
- END IF;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Unit functions
- -- -------------------------------------------------------------------
-
- -- merchant_do_delete_unit
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_delete_unit(in_unit_id text, OUT out_no_unit boolean, OUT out_builtin_conflict boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_unit merchant_custom_units%%ROWTYPE;
- BEGIN
- out_no_unit := FALSE;
- out_builtin_conflict := FALSE;
-
- SELECT *
- INTO my_unit
- FROM merchant_custom_units
- WHERE unit = in_unit_id
- FOR UPDATE;
-
- IF NOT FOUND THEN
- IF EXISTS (SELECT 1 FROM merchant.merchant_builtin_units bu WHERE bu.unit = in_unit_id) THEN
- out_builtin_conflict := TRUE;
- ELSE
- out_no_unit := TRUE;
- END IF;
- RETURN;
- END IF;
-
- DELETE FROM merchant_custom_units
- WHERE unit_serial = my_unit.unit_serial;
-
- RETURN;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_insert_unit
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_unit(in_unit text, in_unit_name_long text, in_unit_name_short text, in_unit_name_long_i18n bytea, in_unit_name_short_i18n bytea, in_unit_allow_fraction boolean, in_unit_precision_level integer, in_unit_active boolean, OUT out_conflict boolean, OUT out_unit_serial bigint) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- -- Reject attempts to shadow builtin identifiers.
- IF EXISTS (
- SELECT 1 FROM merchant.merchant_builtin_units bu WHERE bu.unit = in_unit
- ) THEN
- out_conflict := TRUE;
- out_unit_serial := NULL;
- RETURN;
- END IF;
-
- INSERT INTO merchant_custom_units (
- unit,
- unit_name_long,
- unit_name_short,
- unit_name_long_i18n,
- unit_name_short_i18n,
- unit_allow_fraction,
- unit_precision_level,
- unit_active)
- VALUES (
- in_unit,
- in_unit_name_long,
- in_unit_name_short,
- in_unit_name_long_i18n,
- in_unit_name_short_i18n,
- in_unit_allow_fraction,
- in_unit_precision_level,
- in_unit_active)
- ON CONFLICT (unit) DO NOTHING
- RETURNING unit_serial
- INTO out_unit_serial;
-
- IF FOUND THEN
- out_conflict := FALSE;
- RETURN;
- END IF;
-
- -- Conflict: custom unit already exists.
- SELECT unit_serial
- INTO out_unit_serial
- FROM merchant_custom_units
- WHERE unit = in_unit;
-
- out_conflict := TRUE;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_update_unit
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_update_unit(in_unit_id text, in_unit_name_long text, in_unit_name_long_i18n bytea, in_unit_name_short text, in_unit_name_short_i18n bytea, in_unit_allow_fraction boolean, in_unit_precision_level integer, in_unit_active boolean, OUT out_no_unit boolean, OUT out_builtin_conflict boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_custom merchant_custom_units%%ROWTYPE;
- my_builtin merchant.merchant_builtin_units%%ROWTYPE;
- my_override merchant_builtin_unit_overrides%%ROWTYPE;
- new_unit_name_long TEXT;
- new_unit_name_short TEXT;
- new_unit_name_long_i18n BYTEA;
- new_unit_name_short_i18n BYTEA;
- new_unit_allow_fraction BOOL;
- new_unit_precision_level INT4;
- new_unit_active BOOL;
- old_unit_allow_fraction BOOL;
- old_unit_precision_level INT4;
- old_unit_active BOOL;
- BEGIN
- out_no_unit := FALSE;
- out_builtin_conflict := FALSE;
-
- SELECT *
- INTO my_custom
- FROM merchant_custom_units
- WHERE unit = in_unit_id
- FOR UPDATE;
-
- IF FOUND THEN
- old_unit_allow_fraction := my_custom.unit_allow_fraction;
- old_unit_precision_level := my_custom.unit_precision_level;
- old_unit_active := my_custom.unit_active;
-
- new_unit_name_long := COALESCE (in_unit_name_long, my_custom.unit_name_long);
- new_unit_name_short := COALESCE (in_unit_name_short, my_custom.unit_name_short);
- new_unit_name_long_i18n := COALESCE (in_unit_name_long_i18n,
- my_custom.unit_name_long_i18n);
- new_unit_name_short_i18n := COALESCE (in_unit_name_short_i18n,
- my_custom.unit_name_short_i18n);
- new_unit_allow_fraction := COALESCE (in_unit_allow_fraction,
- my_custom.unit_allow_fraction);
- new_unit_precision_level := COALESCE (in_unit_precision_level,
- my_custom.unit_precision_level);
- IF NOT new_unit_allow_fraction THEN
- new_unit_precision_level := 0;
- END IF;
-
- new_unit_active := COALESCE (in_unit_active, my_custom.unit_active);
-
- UPDATE merchant_custom_units SET
- unit_name_long = new_unit_name_long
- ,unit_name_long_i18n = new_unit_name_long_i18n
- ,unit_name_short = new_unit_name_short
- ,unit_name_short_i18n = new_unit_name_short_i18n
- ,unit_allow_fraction = new_unit_allow_fraction
- ,unit_precision_level = new_unit_precision_level
- ,unit_active = new_unit_active
- WHERE unit_serial = my_custom.unit_serial;
-
- ASSERT FOUND,'SELECTED it earlier, should UPDATE it now';
-
- IF old_unit_allow_fraction IS DISTINCT FROM new_unit_allow_fraction
- OR old_unit_precision_level IS DISTINCT FROM new_unit_precision_level
- THEN
- UPDATE merchant_inventory SET
- allow_fractional_quantity = new_unit_allow_fraction
- , fractional_precision_level = new_unit_precision_level
- WHERE unit = in_unit_id
- AND allow_fractional_quantity = old_unit_allow_fraction
- AND fractional_precision_level = old_unit_precision_level;
- END IF;
- RETURN;
- END IF;
-
- -- Try builtin with overrides.
- SELECT *
- INTO my_builtin
- FROM merchant.merchant_builtin_units
- WHERE unit = in_unit_id;
-
- IF NOT FOUND THEN
- out_no_unit := TRUE;
- RETURN;
- END IF;
-
- SELECT *
- INTO my_override
- FROM merchant_builtin_unit_overrides
- WHERE builtin_unit_serial = my_builtin.unit_serial
- FOR UPDATE;
-
- old_unit_allow_fraction := COALESCE (my_override.override_allow_fraction,
- my_builtin.unit_allow_fraction);
- old_unit_precision_level := COALESCE (my_override.override_precision_level,
- my_builtin.unit_precision_level);
- old_unit_active := COALESCE (my_override.override_active,
- my_builtin.unit_active);
-
- -- Only policy flags can change for builtin units.
- IF in_unit_name_long IS NOT NULL
- OR in_unit_name_short IS NOT NULL
- OR in_unit_name_long_i18n IS NOT NULL
- OR in_unit_name_short_i18n IS NOT NULL THEN
- out_builtin_conflict := TRUE;
- RETURN;
- END IF;
-
- new_unit_allow_fraction := COALESCE (in_unit_allow_fraction,
- old_unit_allow_fraction);
- new_unit_precision_level := COALESCE (in_unit_precision_level,
- old_unit_precision_level);
- IF NOT new_unit_allow_fraction THEN
- new_unit_precision_level := 0;
- END IF;
- new_unit_active := COALESCE (in_unit_active, old_unit_active);
-
- INSERT INTO merchant_builtin_unit_overrides (
- builtin_unit_serial,
- override_allow_fraction,
- override_precision_level,
- override_active)
- VALUES (my_builtin.unit_serial,
- new_unit_allow_fraction,
- new_unit_precision_level,
- new_unit_active)
- ON CONFLICT (builtin_unit_serial)
- DO UPDATE SET override_allow_fraction = EXCLUDED.override_allow_fraction
- , override_precision_level = EXCLUDED.override_precision_level
- , override_active = EXCLUDED.override_active;
-
- IF old_unit_allow_fraction IS DISTINCT FROM new_unit_allow_fraction
- OR old_unit_precision_level IS DISTINCT FROM new_unit_precision_level
- THEN
- UPDATE merchant_inventory SET
- allow_fractional_quantity = new_unit_allow_fraction
- , fractional_precision_level = new_unit_precision_level
- WHERE unit = in_unit_id
- AND allow_fractional_quantity = old_unit_allow_fraction
- AND fractional_precision_level = old_unit_precision_level;
- END IF;
-
- RETURN;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Money pots
- -- -------------------------------------------------------------------
-
- -- merchant_do_increment_money_pots
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_increment_money_pots(ina_money_pots_ids bigint[], ina_increments merchant.taler_amount_currency[], OUT out_not_found boolean) RETURNS boolean
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- i INT;
- ini_current_pot_id INT8;
- ini_current_increment taler_amount_currency;
- my_totals taler_amount_currency[];
- currency_found BOOL;
- j INT;
- BEGIN
- out_not_found = FALSE;
- IF ( COALESCE(array_length(ina_money_pots_ids, 1), 0) !=
- COALESCE(array_length(ina_increments, 1), 0) )
- THEN
- RAISE EXCEPTION 'Array lengths must match';
- END IF;
- FOR i IN 1..COALESCE(array_length(ina_money_pots_ids, 1),0)
- LOOP
- ini_current_pot_id = ina_money_pots_ids[i];
- ini_current_increment = ina_increments[i];
- SELECT pot_totals
- INTO my_totals
- FROM merchant_money_pots
- WHERE money_pot_serial = ini_current_pot_id;
- IF NOT FOUND
- THEN
- out_not_found = TRUE;
- ELSE
- currency_found = FALSE;
- FOR j IN 1..COALESCE(array_length(my_totals, 1), 0)
- LOOP
- IF (my_totals[j]).currency = (ini_current_increment).currency
- THEN
- my_totals[j].frac
- = my_totals[j].frac + ini_current_increment.frac;
- my_totals[j].val
- = my_totals[j].val + ini_current_increment.val;
- IF my_totals[j].frac >= 100000000
- THEN
- my_totals[j].frac = my_totals[j].frac - 100000000;
- my_totals[j].val = my_totals[j].val + 1;
- END IF;
- currency_found = TRUE;
- EXIT;
- END IF;
- END LOOP;
- IF NOT currency_found
- THEN
- my_totals = array_append(my_totals, ini_current_increment);
- END IF;
- UPDATE merchant_money_pots
- SET pot_totals = my_totals
- WHERE money_pot_serial = ini_current_pot_id;
- END IF;
- END LOOP;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_update_money_pot
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_update_money_pot(in_money_pot_serial bigint, in_name text, in_description text, in_old_totals merchant.taler_amount_currency[], in_new_totals merchant.taler_amount_currency[], OUT out_conflict_total boolean, OUT out_conflict_name boolean, OUT out_not_found boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- BEGIN
- UPDATE merchant_money_pots SET
- money_pot_name=in_name
- ,money_pot_description=in_description
- ,pot_totals=COALESCE(in_new_totals, pot_totals)
- WHERE money_pot_serial=in_money_pot_serial
- AND ( (in_old_totals IS NULL) OR (pot_totals=in_old_totals) );
- IF NOT FOUND
- THEN
- PERFORM FROM merchant_money_pots
- WHERE money_pot_serial=in_money_pot_serial;
- out_conflict_total = FOUND;
- out_not_found = NOT FOUND;
- out_conflict_name = FALSE;
- ELSE
- out_conflict_total = FALSE;
- out_not_found = FALSE;
- out_conflict_name = FALSE;
- END IF;
- RETURN;
- EXCEPTION
- WHEN unique_violation
- THEN
- out_conflict_name = TRUE;
- out_conflict_total = FALSE;
- out_not_found = FALSE;
- RETURN;
- END;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Deposit confirmations and transfers
- -- -------------------------------------------------------------------
-
- -- merchant_do_insert_deposit_confirmation
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_deposit_confirmation(in_h_contract_terms bytea, in_deposit_timestamp bigint, in_exchange_url text, in_total_without_fee merchant.taler_amount_currency, in_wire_fee merchant.taler_amount_currency, in_h_wire bytea, in_exchange_sig bytea, in_exchange_pub bytea, in_wire_transfer_deadline bigint, in_notify_arg_str text, OUT out_no_order boolean, OUT out_no_account boolean, OUT out_no_signkey boolean, OUT out_conflict boolean, OUT out_deposit_confirmation_serial bigint) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_order_serial INT8;
- my_account_serial INT8;
- my_signkey_serial INT8;
- my_record RECORD;
- my_bank_serial_id INT8;
- my_credit_amount taler_amount_currency;
- BEGIN
- out_no_order=TRUE;
- out_no_account=TRUE;
- out_no_signkey=TRUE;
- out_conflict=FALSE;
- out_deposit_confirmation_serial=0;
- SELECT account_serial
- INTO my_account_serial
- FROM merchant_accounts
- WHERE h_wire=in_h_wire;
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- out_no_account=FALSE;
- SELECT signkey_serial
- INTO my_signkey_serial
- FROM merchant.merchant_exchange_signing_keys
- WHERE exchange_pub=in_exchange_pub
- ORDER BY start_date DESC
- LIMIT 1;
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- out_no_signkey=FALSE;
- SELECT order_serial
- INTO my_order_serial
- FROM merchant_contract_terms
- WHERE h_contract_terms=in_h_contract_terms;
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- out_no_order=FALSE;
- SELECT deposit_confirmation_serial
- ,deposit_timestamp
- ,exchange_url
- ,total_without_fee
- ,wire_fee
- ,wire_transfer_deadline
- ,account_serial
- INTO my_record
- FROM merchant_deposit_confirmations
- WHERE order_serial=my_order_serial
- AND exchange_url=in_exchange_url;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_deposit_confirmations
- (order_serial
- ,deposit_timestamp
- ,exchange_url
- ,total_without_fee
- ,wire_fee
- ,exchange_sig
- ,wire_transfer_deadline
- ,signkey_serial
- ,account_serial
- ) VALUES (
- my_order_serial
- ,in_deposit_timestamp
- ,in_exchange_url
- ,in_total_without_fee
- ,in_wire_fee
- ,in_exchange_sig
- ,in_wire_transfer_deadline
- ,my_signkey_serial
- ,my_account_serial
- ) RETURNING deposit_confirmation_serial
- INTO out_deposit_confirmation_serial;
- ELSE
- IF (in_deposit_timestamp,
- in_wire_transfer_deadline,
- in_wire_fee,
- my_account_serial)
- IS DISTINCT FROM
- (my_record.deposit_timestamp,
- my_record.wire_transfer_deadline,
- my_record.wire_fee,
- my_record.account_serial)
- THEN
- out_conflict = TRUE;
- out_deposit_confirmation_serial = my_record.deposit_confirmation_serial;
- RETURN;
- END IF;
- IF ( ((in_total_without_fee).val < (my_record.total_without_fee).val) OR
- ( ((in_total_without_fee).val = (my_record.total_without_fee).val) AND
- ((in_total_without_fee).frac <= (my_record.total_without_fee).frac) ) )
- THEN
- out_deposit_confirmation_serial = my_record.deposit_confirmation_serial;
- RETURN;
- END IF;
- UPDATE merchant_deposit_confirmations
- SET total_without_fee = in_total_without_fee
- ,exchange_sig = in_exchange_sig
- ,signkey_serial = my_signkey_serial;
- out_deposit_confirmation_serial = my_record.deposit_confirmation_serial;
- END IF;
- PERFORM pg_notify ('XBZ19D98AK2REYNX93F736A56MT14SCY2EEX7XNXQMNCQ01B121R0',
- in_notify_arg_str);
- END $BODY$
- $OUTER$, s);
-
- -- merchant_insert_deposit_to_transfer
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_insert_deposit_to_transfer(in_deposit_serial bigint, in_coin_contribution merchant.taler_amount_currency, in_execution_time bigint, in_exchange_url text, in_h_wire bytea, in_exchange_sig bytea, in_exchange_pub bytea, in_wtid bytea, OUT out_dummy boolean) RETURNS boolean
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_signkey_serial INT8;
- my_account_serial INT8;
- my_decose INT8;
- my_expected_credit_serial INT8;
- my_wire_pending_cleared BOOL;
- BEGIN
- out_dummy=FALSE;
- SELECT signkey_serial
- INTO my_signkey_serial
- FROM merchant.merchant_exchange_signing_keys
- WHERE exchange_pub=in_exchange_pub
- ORDER BY start_date DESC
- LIMIT 1;
- IF NOT FOUND
- THEN
- UPDATE merchant_deposits
- SET settlement_last_ec=2029
- ,settlement_last_http_status=200
- ,settlement_last_detail=ENCODE(in_exchange_pub, 'hex')
- ,settlement_wtid=in_wtid
- ,settlement_retry_needed=TRUE
- ,settlement_retry_time=(EXTRACT(epoch FROM (CURRENT_TIME + interval '8 hours')) * 1000000)::INT8
- WHERE deposit_serial=in_deposit_serial;
- RETURN;
- END IF;
- SELECT deposit_confirmation_serial
- INTO my_decose
- FROM merchant_deposits
- WHERE deposit_serial=in_deposit_serial;
- SELECT account_serial
- INTO my_account_serial
- FROM merchant_deposit_confirmations mdc
- JOIN merchant_accounts ma
- USING (account_serial)
- WHERE mdc.deposit_confirmation_serial=my_decose
- AND ma.h_wire=in_h_wire;
- IF NOT FOUND
- THEN
- UPDATE merchant_deposits
- SET settlement_last_ec=2558
- ,settlement_last_http_status=200
- ,settlement_last_detail=ENCODE(in_h_wire, 'hex')
- ,settlement_wtid=in_wtid
- ,settlement_retry_needed=FALSE
- ,settlement_coin_contribution=in_coin_contribution
- ,signkey_serial=my_signkey_serial
- ,settlement_exchange_sig=in_exchange_sig
- WHERE deposit_serial=in_deposit_serial;
- RETURN;
- END IF;
- SELECT expected_credit_serial
- INTO my_expected_credit_serial
- FROM merchant_expected_transfers
- WHERE wtid=in_wtid
- AND exchange_url=in_exchange_url
- AND account_serial=my_account_serial;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_expected_transfers
- (exchange_url
- ,wtid
- ,account_serial
- ,expected_time)
- VALUES
- (in_exchange_url
- ,in_wtid
- ,my_account_serial
- ,in_execution_time)
- RETURNING expected_credit_serial
- INTO my_expected_credit_serial;
- END IF;
- UPDATE merchant_deposits
- SET settlement_last_ec=0
- ,settlement_last_http_status=200
- ,settlement_last_detail=NULL
- ,settlement_wtid=in_wtid
- ,settlement_retry_needed=FALSE
- ,settlement_coin_contribution=in_coin_contribution
- ,settlement_expected_credit_serial=my_expected_credit_serial
- ,signkey_serial=my_signkey_serial
- ,settlement_exchange_sig=in_exchange_sig
- WHERE deposit_serial=in_deposit_serial;
- NOTIFY XR6849FMRD2AJFY1E2YY0GWA8GN0YT407Z66WHJB0SAKJWF8G2Q60;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Tokens
- -- -------------------------------------------------------------------
-
- -- merchant_do_insert_issued_token
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_issued_token(in_h_issue_pub bytea, in_h_contract_terms bytea, in_blind_sig bytea, OUT out_no_family boolean, OUT out_existed boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_rec RECORD;
- my_tfk_serial INT8;
- my_tf_serial INT8;
- BEGIN
- SELECT token_family_key_serial
- ,token_family_serial
- INTO my_rec
- FROM merchant_token_family_keys
- WHERE h_pub = in_h_issue_pub;
- IF NOT FOUND
- THEN
- out_no_family = TRUE;
- out_existed = FALSE;
- return;
- END IF;
- my_tfk_serial = my_rec.token_family_key_serial;
- my_tf_serial = my_rec.token_family_serial;
- out_no_family = FALSE;
- INSERT INTO merchant_issued_tokens
- (token_family_key_serial
- ,h_contract_terms
- ,blind_sig
- ) VALUES
- (my_tfk_serial
- ,in_h_contract_terms
- ,in_blind_sig)
- ON CONFLICT DO NOTHING;
- IF NOT FOUND
- THEN
- out_existed = TRUE;
- return;
- END IF;
- out_existed = FALSE;
- UPDATE merchant_token_families
- SET issued=issued+1
- WHERE token_family_serial=my_tf_serial;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_insert_spent_token
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_spent_token(in_h_contract_terms bytea, in_h_issue_pub bytea, in_use_pub bytea, in_use_sig bytea, in_issue_sig bytea, OUT out_no_family boolean, OUT out_conflict boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_rec RECORD;
- my_tfk_serial INT8;
- my_tf_serial INT8;
- BEGIN
- SELECT token_family_key_serial
- ,token_family_serial
- INTO my_rec
- FROM merchant_token_family_keys
- WHERE h_pub = in_h_issue_pub;
- IF NOT FOUND
- THEN
- out_no_family = TRUE;
- out_conflict = FALSE;
- return;
- END IF;
- out_no_family = FALSE;
- my_tfk_serial = my_rec.token_family_key_serial;
- my_tf_serial = my_rec.token_family_serial;
- INSERT INTO merchant_used_tokens
- (token_family_key_serial
- ,h_contract_terms
- ,token_pub
- ,token_sig
- ,blind_sig
- ) VALUES
- (my_tfk_serial
- ,in_h_contract_terms
- ,in_use_pub
- ,in_use_sig
- ,in_issue_sig)
- ON CONFLICT DO NOTHING;
- IF NOT FOUND
- THEN
- PERFORM FROM merchant_used_tokens
- WHERE token_family_key_serial=my_tfk_serial
- AND h_contract_terms=in_h_contract_terms
- AND token_pub=in_use_pub
- AND token_sig=in_use_sig
- AND blind_sig=in_issue_sig;
- out_conflict = NOT FOUND;
- return;
- END IF;
- out_conflict = FALSE;
- UPDATE merchant_token_families
- SET used=used+1
- WHERE token_family_serial=my_tf_serial;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Products and product groups
- -- -------------------------------------------------------------------
-
- -- merchant_do_insert_product
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_product(in_product_id text, in_description text, in_description_i18n jsonb, in_unit text, in_image text, in_taxes jsonb, ina_price_list merchant.taler_amount_currency[], in_total_stock bigint, in_total_stock_frac integer, in_allow_fractional_quantity boolean, in_fractional_precision_level integer, in_address jsonb, in_next_restock bigint, in_minimum_age integer, ina_categories bigint[], in_product_name text, in_product_group_id bigint, in_money_pot_id bigint, in_price_is_net boolean, OUT out_conflict boolean, OUT out_no_cat bigint, OUT out_no_group boolean, OUT out_no_pot boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_product_serial INT8;
- i INT8;
- ini_cat INT8;
- BEGIN
- out_no_group = FALSE;
- out_no_pot = FALSE;
- IF in_product_group_id IS NOT NULL
- THEN
- PERFORM FROM merchant_product_groups
- WHERE product_group_serial=in_product_group_id;
- IF NOT FOUND
- THEN
- out_no_group=TRUE;
- out_conflict=FALSE;
- out_no_cat=NULL;
- RETURN;
- END IF;
- END IF;
- IF in_money_pot_id IS NOT NULL
- THEN
- PERFORM FROM merchant_money_pots
- WHERE money_pot_serial=in_money_pot_id;
- IF NOT FOUND
- THEN
- out_no_pot=TRUE;
- out_conflict=FALSE;
- out_no_cat=NULL;
- RETURN;
- END IF;
- END IF;
- INSERT INTO merchant_inventory
- (product_id
- ,product_name
- ,description
- ,description_i18n
- ,unit
- ,image
- ,image_hash
- ,taxes
- ,price_array
- ,total_stock
- ,total_stock_frac
- ,allow_fractional_quantity
- ,fractional_precision_level
- ,address
- ,next_restock
- ,minimum_age
- ,product_group_serial
- ,money_pot_serial
- ,price_is_net
- ) VALUES (
- in_product_id
- ,in_product_name
- ,in_description
- ,in_description_i18n
- ,in_unit
- ,in_image
- ,CASE
- WHEN (in_image IS NULL) OR (in_image = '')
- THEN NULL
- ELSE encode(public.digest(convert_to(in_image, 'UTF8'),
- 'sha256'),
- 'hex')
- END
- ,in_taxes
- ,ina_price_list
- ,in_total_stock
- ,in_total_stock_frac
- ,in_allow_fractional_quantity
- ,in_fractional_precision_level
- ,in_address
- ,in_next_restock
- ,in_minimum_age
- ,in_product_group_id
- ,in_money_pot_id
- ,in_price_is_net
- )
- ON CONFLICT (product_id) DO NOTHING
- RETURNING product_serial
- INTO my_product_serial;
- IF NOT FOUND
- THEN
- SELECT product_serial
- INTO my_product_serial
- FROM merchant_inventory
- WHERE product_id=in_product_id
- AND product_name=in_product_name
- AND description=in_description
- AND description_i18n=in_description_i18n
- AND unit=in_unit
- AND image=in_image
- AND taxes=in_taxes
- AND to_jsonb(COALESCE(price_array, ARRAY[]::taler_amount_currency[]))
- = to_jsonb(COALESCE(ina_price_list, ARRAY[]::taler_amount_currency[]))
- AND total_stock=in_total_stock
- AND total_stock_frac=in_total_stock_frac
- AND allow_fractional_quantity=in_allow_fractional_quantity
- AND fractional_precision_level=in_fractional_precision_level
- AND address=in_address
- AND next_restock=in_next_restock
- AND minimum_age=in_minimum_age
- AND product_group_serial IS NOT DISTINCT FROM in_product_group_id
- AND money_pot_serial IS NOT DISTINCT FROM in_money_pot_id
- AND price_is_net=in_price_is_net;
- IF NOT FOUND
- THEN
- out_conflict=TRUE;
- out_no_cat=NULL;
- RETURN;
- END IF;
- FOR i IN 1..COALESCE(array_length(ina_categories,1),0)
- LOOP
- ini_cat=ina_categories[i];
- PERFORM
- FROM merchant_product_categories
- WHERE product_serial=my_product_serial
- AND category_serial=ini_cat;
- IF NOT FOUND
- THEN
- out_conflict=TRUE;
- out_no_cat=NULL;
- RETURN;
- END IF;
- END LOOP;
- SELECT COUNT(*)
- INTO i
- FROM merchant_product_categories
- WHERE product_serial=my_product_serial;
- IF i != COALESCE(array_length(ina_categories,1),0)
- THEN
- out_conflict=TRUE;
- out_no_cat=NULL;
- RETURN;
- END IF;
- out_conflict=FALSE;
- out_no_cat=NULL;
- RETURN;
- END IF;
- out_conflict=FALSE;
- FOR i IN 1..COALESCE(array_length(ina_categories,1),0)
- LOOP
- ini_cat=ina_categories[i];
- INSERT INTO merchant_product_categories
- (product_serial
- ,category_serial)
- VALUES
- (my_product_serial
- ,ini_cat)
- ON CONFLICT DO NOTHING;
- IF NOT FOUND
- THEN
- out_no_cat=i;
- RETURN;
- END IF;
- END LOOP;
- out_no_cat=NULL;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_update_product
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_update_product(in_product_id text, in_description text, in_description_i18n jsonb, in_unit text, in_image text, in_taxes jsonb, ina_price_list merchant.taler_amount_currency[], in_total_stock bigint, in_total_stock_frac integer, in_allow_fractional_quantity boolean, in_fractional_precision_level integer, in_total_lost bigint, in_address jsonb, in_next_restock bigint, in_minimum_age integer, ina_categories bigint[], in_product_name text, in_product_group_id bigint, in_money_pot_id bigint, in_price_is_net boolean, OUT out_no_product boolean, OUT out_lost_reduced boolean, OUT out_sold_reduced boolean, OUT out_stocked_reduced boolean, OUT out_no_cat bigint, OUT out_no_group boolean, OUT out_no_pot boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_product_serial INT8;
- i INT8;
- ini_cat INT8;
- rec RECORD;
- BEGIN
- out_no_group = FALSE;
- out_no_pot = FALSE;
- out_no_product=FALSE;
- out_lost_reduced=FALSE;
- out_sold_reduced=FALSE;
- out_stocked_reduced=FALSE;
- out_no_cat=NULL;
- IF in_product_group_id IS NOT NULL
- THEN
- PERFORM FROM merchant_product_groups
- WHERE product_group_serial=in_product_group_id;
- IF NOT FOUND
- THEN
- out_no_group=TRUE;
- RETURN;
- END IF;
- END IF;
- IF in_money_pot_id IS NOT NULL
- THEN
- PERFORM FROM merchant_money_pots
- WHERE money_pot_serial=in_money_pot_id;
- IF NOT FOUND
- THEN
- out_no_pot=TRUE;
- RETURN;
- END IF;
- END IF;
- SELECT total_stock
- ,total_stock_frac
- ,total_lost
- ,allow_fractional_quantity
- ,product_serial
- INTO rec
- FROM merchant_inventory
- WHERE product_id=in_product_id;
- IF NOT FOUND
- THEN
- out_no_product=TRUE;
- RETURN;
- END IF;
- my_product_serial = rec.product_serial;
- IF rec.total_stock > in_total_stock
- THEN
- out_stocked_reduced=TRUE;
- RETURN;
- END IF;
- IF rec.total_lost > in_total_lost
- THEN
- out_lost_reduced=TRUE;
- RETURN;
- END IF;
- IF rec.allow_fractional_quantity
- AND (NOT in_allow_fractional_quantity)
- THEN
- DELETE
- FROM merchant_inventory_locks
- WHERE product_serial = my_product_serial
- AND total_locked_frac <> 0;
- END IF;
- DELETE FROM merchant_product_categories
- WHERE product_serial=my_product_serial;
- FOR i IN 1..COALESCE(array_length(ina_categories,1),0)
- LOOP
- ini_cat=ina_categories[i];
- INSERT INTO merchant_product_categories
- (product_serial
- ,category_serial)
- VALUES
- (my_product_serial
- ,ini_cat)
- ON CONFLICT DO NOTHING;
- IF NOT FOUND
- THEN
- out_no_cat=i;
- RETURN;
- END IF;
- END LOOP;
- UPDATE merchant_inventory SET
- description=in_description
- ,description_i18n=in_description_i18n
- ,product_name=in_product_name
- ,unit=in_unit
- ,image=in_image
- ,image_hash=CASE
- WHEN (in_image IS NULL) OR (in_image = '')
- THEN NULL
- ELSE encode(public.digest(convert_to(in_image, 'UTF8'),
- 'sha256'),
- 'hex')
- END
- ,taxes=in_taxes
- ,price_array=ina_price_list
- ,total_stock=in_total_stock
- ,total_stock_frac=in_total_stock_frac
- ,allow_fractional_quantity=in_allow_fractional_quantity
- ,fractional_precision_level=in_fractional_precision_level
- ,total_lost=in_total_lost
- ,address=in_address
- ,next_restock=in_next_restock
- ,minimum_age=in_minimum_age
- ,product_group_serial=in_product_group_id
- ,money_pot_serial=in_money_pot_id
- ,price_is_net=in_price_is_net
- WHERE product_serial=my_product_serial;
- ASSERT FOUND,'SELECTED it earlier, should UPDATE it now';
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_update_product_group
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_update_product_group(in_product_group_serial text, in_name text, in_description text, OUT out_conflict boolean, OUT out_not_found boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- BEGIN
- UPDATE merchant_product_groups SET
- product_group_name=in_name
- ,product_group_description=in_description
- WHERE product_group_serial=in_product_group_serial;
- out_not_found = NOT FOUND;
- out_conflict = FALSE;
- RETURN;
- EXCEPTION
- WHEN unique_violation
- THEN
- out_conflict = TRUE;
- RETURN;
- END;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Transfers
- -- -------------------------------------------------------------------
-
- -- merchant_do_insert_transfer
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_transfer(in_exchange_url text, in_wtid bytea, in_credit_amount merchant.taler_amount_currency, in_credited_account_payto text, in_bank_serial_id bigint, in_execution_time bigint, OUT out_no_account boolean, OUT out_conflict boolean) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_account_serial INT8;
- my_record RECORD;
- my_bank_serial_id INT8;
- my_credit_amount taler_amount_currency;
- BEGIN
- out_conflict=FALSE;
- SELECT account_serial
- INTO my_account_serial
- FROM merchant_accounts
- WHERE REGEXP_REPLACE(payto_uri,
- '\\?.*','')
- =REGEXP_REPLACE(in_credited_account_payto,
- '\\?.*','');
- IF NOT FOUND
- THEN
- out_no_account=TRUE;
- RETURN;
- END IF;
- out_no_account=FALSE;
- SELECT bank_serial_id
- ,credit_amount
- INTO my_record
- FROM merchant_transfers
- WHERE wtid=in_wtid
- AND account_serial=my_account_serial
- AND exchange_url=in_exchange_url;
- IF NOT FOUND
- THEN
- INSERT INTO merchant_transfers
- (exchange_url
- ,wtid
- ,credit_amount
- ,account_serial
- ,bank_serial_id
- ,execution_time
- ) VALUES
- (in_exchange_url
- ,in_wtid
- ,in_credit_amount
- ,my_account_serial
- ,in_bank_serial_id
- ,in_execution_time);
- NOTIFY XJ5N652FA4TBS2WXGY3S1FMPMQYTD8KAZA9B7HW9JWJ4PZ2DB852G;
- RETURN;
- END IF;
- my_bank_serial_id = my_record.bank_serial_id;
- my_credit_amount = my_record.credit_amount;
- IF ( (in_credit_amount.val != my_credit_amount.val) OR
- (in_credit_amount.frac != my_credit_amount.frac) OR
- (in_credit_amount.curr != my_credit_amount.curr) )
- THEN
- out_conflict = TRUE;
- RETURN;
- END IF;
- IF ( (my_bank_serial_id IS NULL) AND
- (in_bank_serial_id IS NOT NULL) )
- THEN
- UPDATE merchant_transfers
- SET bank_serial_id=in_bank_serial_id
- WHERE wtid=in_wtid
- AND account_serial=my_account_serial
- AND exchange_url=in_exchange_url;
- RETURN;
- END IF;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_do_insert_transfer_details
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_insert_transfer_details(in_exchange_url text, in_payto_uri text, in_wtid bytea, in_execution_time bigint, in_exchange_pub bytea, in_exchange_sig bytea, in_total_amount merchant.taler_amount_currency, in_wire_fee merchant.taler_amount_currency, ina_coin_values merchant.taler_amount_currency[], ina_deposit_fees merchant.taler_amount_currency[], ina_coin_pubs bytea[], ina_contract_terms bytea[], OUT out_no_account boolean, OUT out_no_exchange boolean, OUT out_duplicate boolean, OUT out_conflict boolean, OUT out_order_id text) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_signkey_serial INT8;
- my_expected_credit_serial INT8;
- my_affected_orders RECORD;
- my_decose INT8;
- my_order_id TEXT;
- i INT8;
- curs CURSOR (arg_coin_pub BYTEA) FOR
- SELECT mcon.deposit_confirmation_serial,
- mcon.order_serial
- FROM merchant_deposits dep
- JOIN merchant_deposit_confirmations mcon
- USING (deposit_confirmation_serial)
- WHERE dep.coin_pub=arg_coin_pub;
- ini_coin_pub BYTEA;
- ini_contract_term BYTEA;
- ini_coin_value taler_amount_currency;
- ini_deposit_fee taler_amount_currency;
- BEGIN
- SELECT expected_credit_serial
- INTO my_expected_credit_serial
- FROM merchant_expected_transfers
- WHERE exchange_url=in_exchange_url
- AND wtid=in_wtid
- AND account_serial=
- (SELECT account_serial
- FROM merchant_accounts
- WHERE payto_uri=in_payto_uri
- AND exchange_url=in_exchange_url);
- IF NOT FOUND
- THEN
- out_no_account=TRUE;
- out_no_exchange=FALSE;
- out_duplicate=FALSE;
- out_conflict=FALSE;
- RETURN;
- END IF;
- out_no_account=FALSE;
- SELECT signkey_serial
- INTO my_signkey_serial
- FROM merchant.merchant_exchange_signing_keys
- WHERE exchange_pub=in_exchange_pub
- ORDER BY start_date DESC
- LIMIT 1;
- IF NOT FOUND
- THEN
- out_no_exchange=TRUE;
- out_conflict=FALSE;
- out_duplicate=FALSE;
- RETURN;
- END IF;
- out_no_exchange=FALSE;
- INSERT INTO merchant_transfer_signatures
- (expected_credit_serial
- ,signkey_serial
- ,credit_amount
- ,wire_fee
- ,execution_time
- ,exchange_sig)
- VALUES
- (my_expected_credit_serial
- ,my_signkey_serial
- ,in_total_amount
- ,in_wire_fee
- ,in_execution_time
- ,in_exchange_sig)
- ON CONFLICT DO NOTHING;
- IF NOT FOUND
- THEN
- PERFORM 1
- FROM merchant_transfer_signatures
- WHERE expected_credit_serial=my_expected_credit_serial
- AND signkey_serial=my_signkey_serial
- AND credit_amount=in_total_amount
- AND wire_fee=in_wire_fee
- AND execution_time=in_execution_time
- AND exchange_sig=in_exchange_sig;
- IF FOUND
- THEN
- out_duplicate=TRUE;
- out_conflict=FALSE;
- RETURN;
- END IF;
- out_duplicate=FALSE;
- out_conflict=TRUE;
- RETURN;
- END IF;
- out_duplicate=FALSE;
- out_conflict=FALSE;
- FOR i IN 1..array_length(ina_coin_pubs,1)
- LOOP
- ini_coin_value=ina_coin_values[i];
- ini_deposit_fee=ina_deposit_fees[i];
- ini_coin_pub=ina_coin_pubs[i];
- ini_contract_term=ina_contract_terms[i];
- INSERT INTO merchant_expected_transfer_to_coin
- (deposit_serial
- ,expected_credit_serial
- ,offset_in_exchange_list
- ,exchange_deposit_value
- ,exchange_deposit_fee)
- SELECT
- dep.deposit_serial
- ,my_expected_credit_serial
- ,i
- ,ini_coin_value
- ,ini_deposit_fee
- FROM merchant_deposits dep
- JOIN merchant_deposit_confirmations dcon
- USING (deposit_confirmation_serial)
- JOIN merchant_contract_terms cterm
- USING (order_serial)
- WHERE dep.coin_pub=ini_coin_pub
- AND cterm.h_contract_terms=ini_contract_term;
- RAISE NOTICE 'iterating over affected orders';
- OPEN curs (arg_coin_pub:=ini_coin_pub);
- LOOP
- FETCH NEXT FROM curs INTO my_affected_orders;
- EXIT WHEN NOT FOUND;
- RAISE NOTICE 'checking affected order for completion';
- my_decose=my_affected_orders.deposit_confirmation_serial;
- PERFORM FROM merchant_deposits md
- WHERE md.deposit_confirmation_serial=my_decose
- AND settlement_retry_needed
- OR settlement_wtid IS NULL;
- IF NOT FOUND
- THEN
- UPDATE merchant_deposit_confirmations
- SET wire_pending=FALSE
- WHERE (deposit_confirmation_serial=my_decose);
- IF FOUND
- THEN
- RAISE NOTICE 'checking affected contract for completion';
- PERFORM FROM merchant_deposit_confirmations mdc
- WHERE mdc.wire_pending
- AND mdc.order_serial=my_affected_orders.order_serial;
- IF NOT FOUND
- THEN
- UPDATE merchant_contract_terms
- SET wired=TRUE
- WHERE (order_serial=my_affected_orders.order_serial);
- SELECT order_id
- INTO my_order_id
- FROM merchant_contract_terms
- WHERE order_serial=my_affected_orders.order_serial;
- out_order_id = my_order_id;
- INSERT INTO merchant_pending_webhooks
- (webhook_serial
- ,url
- ,http_method
- ,header
- ,body)
- SELECT mw.webhook_serial
- ,mw.url
- ,mw.http_method
- ,merchant.replace_placeholder(
- merchant.replace_placeholder(mw.header_template, 'order_id', my_order_id),
- 'wtid', encode(in_wtid, 'hex')
- )::TEXT
- ,merchant.replace_placeholder(
- merchant.replace_placeholder(mw.body_template, 'order_id', my_order_id),
- 'wtid', encode(in_wtid, 'hex')
- )::TEXT
- FROM merchant_webhook mw
- WHERE mw.event_type = 'order_settled';
- IF FOUND
- THEN
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- END IF;
- END IF;
- END IF;
- END LOOP;
- CLOSE curs;
- END LOOP;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- TAN / MFA challenges
- -- -------------------------------------------------------------------
-
- -- merchant_do_solve_mfa_challenge
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_do_solve_mfa_challenge(in_challenge_id bigint, in_h_body bytea, in_solution text, in_now bigint, OUT out_solved boolean, OUT out_retry_counter integer) RETURNS record
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_confirmation_date INT8;
- DECLARE
- my_rec RECORD;
- BEGIN
- SELECT
- tc.confirmation_date
- ,tc.retry_counter
- ,(tc.code = in_solution) AS solved
- INTO
- my_rec
- FROM tan_challenges tc
- WHERE tc.challenge_id = in_challenge_id
- AND tc.h_body = in_h_body
- AND tc.expiration_date > in_now;
- IF NOT FOUND
- THEN
- out_solved = FALSE;
- RETURN;
- END IF;
- my_confirmation_date = my_rec.confirmation_date;
- out_retry_counter = my_rec.retry_counter;
- out_solved = my_rec.solved;
- IF my_confirmation_date IS NOT NULL
- THEN
- out_solved = TRUE;
- RETURN;
- END IF;
- IF (0 = out_retry_counter)
- THEN
- out_solved = FALSE;
- RETURN;
- END IF;
- IF out_solved
- THEN
- my_confirmation_date = in_now;
- UPDATE tan_challenges
- SET confirmation_date = my_confirmation_date
- WHERE challenge_id = in_challenge_id;
- ELSE
- out_retry_counter = out_retry_counter - 1;
- UPDATE tan_challenges
- SET retry_counter = out_retry_counter
- WHERE challenge_id = in_challenge_id;
- END IF;
- END;
- $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- Statistic interval getters
- -- -------------------------------------------------------------------
-
- -- merchant_statistic_interval_amount_get
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_statistic_interval_amount_get(in_slug text) RETURNS SETOF merchant.merchant_statistic_interval_amount_get_return_value
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_time INT8 DEFAULT ROUND(EXTRACT(epoch FROM CURRENT_TIMESTAMP(0)::TIMESTAMP) * 1000000)::INT8 / 1000 / 1000;
- my_ranges INT8[];
- my_range INT8;
- my_delta_value INT8;
- my_delta_frac INT8;
- my_meta INT8;
- my_next_max_serial INT8;
- my_currency TEXT;
- my_rec RECORD;
- my_irec RECORD;
- my_jrec RECORD;
- my_i INT;
- my_min_serial INT8 DEFAULT NULL;
- my_rval merchant.merchant_statistic_interval_amount_get_return_value;
- BEGIN
- SELECT imeta_serial_id
- ,ranges
- ,precisions
- INTO my_rec
- FROM merchant_statistic_interval_meta
- WHERE slug=in_slug;
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- my_meta = my_rec.imeta_serial_id;
- my_ranges = my_rec.ranges;
- FOR my_currency IN
- SELECT DISTINCT delta_curr
- FROM merchant_statistic_amount_event
- WHERE imeta_serial_id = my_meta
- LOOP
- my_rval.rvalue.val = 0;
- my_rval.rvalue.frac = 0;
- my_rval.rvalue.curr = my_currency;
- FOR my_i IN 1..COALESCE(array_length(my_ranges,1),0)
- LOOP
- my_range = my_ranges[my_i];
- SELECT event_delimiter
- ,cumulative_value
- ,cumulative_frac
- INTO my_irec
- FROM merchant_statistic_interval_amount
- WHERE imeta_serial_id = my_meta
- AND curr = my_currency
- AND range = my_range;
- IF FOUND
- THEN
- my_min_serial = my_irec.event_delimiter;
- my_rval.rvalue.val = (my_rval.rvalue).val + my_irec.cumulative_value + my_irec.cumulative_frac / 100000000;
- my_rval.rvalue.frac = (my_rval.rvalue).frac + my_irec.cumulative_frac %% 100000000;
- IF (my_rval.rvalue).frac > 100000000
- THEN
- my_rval.rvalue.frac = (my_rval.rvalue).frac - 100000000;
- my_rval.rvalue.val = (my_rval.rvalue).val + 1;
- END IF;
- SELECT SUM(delta_value) AS value_sum
- ,SUM(delta_frac) AS frac_sum
- INTO my_jrec
- FROM merchant_statistic_amount_event
- WHERE imeta_serial_id = my_meta
- AND delta_curr = my_currency
- AND slot < my_time - my_range
- AND aevent_serial_id >= my_min_serial;
- IF FOUND AND my_jrec.value_sum IS NOT NULL
- THEN
- my_delta_value = my_jrec.value_sum + my_jrec.frac_sum / 100000000;
- my_delta_frac = my_jrec.frac_sum %% 100000000;
- my_rval.rvalue.val = (my_rval.rvalue).val - my_delta_value;
- IF ((my_rval.rvalue).frac >= my_delta_frac)
- THEN
- my_rval.rvalue.frac = (my_rval.rvalue).frac - my_delta_frac;
- ELSE
- my_rval.rvalue.frac = 100000000 + (my_rval.rvalue).frac - my_delta_frac;
- my_rval.rvalue.val = (my_rval.rvalue).val - 1;
- END IF;
- SELECT aevent_serial_id
- INTO my_next_max_serial
- FROM merchant_statistic_amount_event
- WHERE imeta_serial_id = my_meta
- AND delta_curr = my_currency
- AND slot >= my_time - my_range
- AND aevent_serial_id >= my_min_serial
- ORDER BY slot ASC
- LIMIT 1;
- IF FOUND
- THEN
- UPDATE merchant_statistic_interval_amount SET
- cumulative_value = cumulative_value - my_delta_value
- - CASE
- WHEN cumulative_frac < my_delta_frac
- THEN 1
- ELSE 0
- END,
- cumulative_frac = cumulative_frac - my_delta_frac
- + CASE
- WHEN cumulative_frac < my_delta_frac
- THEN 100000000
- ELSE 0
- END,
- event_delimiter = my_next_max_serial
- WHERE imeta_serial_id = my_meta
- AND curr = my_currency
- AND range = my_range;
- ELSE
- DELETE FROM merchant_statistic_interval_amount
- WHERE imeta_serial_id = my_meta
- AND curr = my_currency
- AND range = my_range;
- END IF;
- IF (my_i < COALESCE(array_length(my_ranges,1),0))
- THEN
- UPDATE merchant_statistic_interval_amount AS msia SET
- cumulative_value = cumulative_value + my_delta_value
- + CASE
- WHEN cumulative_frac + my_delta_frac > 100000000
- THEN 1
- ELSE 0
- END,
- cumulative_frac = cumulative_frac + my_delta_frac
- - CASE
- WHEN cumulative_frac + my_delta_frac > 100000000
- THEN 100000000
- ELSE 0
- END,
- event_delimiter = LEAST (msia.event_delimiter,my_min_serial)
- WHERE imeta_serial_id = my_meta
- AND range=my_ranges[my_i+1];
- IF NOT FOUND
- THEN
- INSERT INTO merchant_statistic_interval_amount
- (imeta_serial_id
- ,event_delimiter
- ,range
- ,curr
- ,cumulative_value
- ,cumulative_frac
- ) VALUES (
- my_meta
- ,my_min_serial
- ,my_ranges[my_i+1]
- ,my_currency
- ,my_delta_value
- ,my_delta_frac);
- END IF;
- ELSE
- DELETE FROM merchant_statistic_amount_event
- WHERE imeta_serial_id = my_meta
- AND slot < my_time - my_range;
- END IF;
- END IF;
- my_rval.range = my_range;
- RETURN NEXT my_rval;
- END IF;
- END LOOP;
- END LOOP;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_statistic_interval_number_get
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_statistic_interval_number_get(in_slug text) RETURNS SETOF merchant.merchant_statistic_interval_number_get_return_value
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_time INT8 DEFAULT ROUND(EXTRACT(epoch FROM CURRENT_TIMESTAMP(0)::TIMESTAMP) * 1000000)::INT8 / 1000 / 1000;
- my_ranges INT8[];
- my_range INT8;
- my_delta INT8;
- my_meta INT8;
- my_next_max_serial INT8;
- my_rec RECORD;
- my_irec RECORD;
- my_i INT;
- my_min_serial INT8 DEFAULT NULL;
- my_rval merchant.merchant_statistic_interval_number_get_return_value;
- BEGIN
- SELECT imeta_serial_id
- ,ranges
- ,precisions
- INTO my_rec
- FROM merchant_statistic_interval_meta
- WHERE slug=in_slug;
- IF NOT FOUND
- THEN
- RETURN;
- END IF;
- my_rval.rvalue = 0;
- my_ranges = my_rec.ranges;
- my_meta = my_rec.imeta_serial_id;
- FOR my_i IN 1..COALESCE(array_length(my_ranges,1),0)
- LOOP
- my_range = my_ranges[my_i];
- SELECT event_delimiter
- ,cumulative_number
- INTO my_irec
- FROM merchant_statistic_interval_counter
- WHERE imeta_serial_id = my_meta
- AND range = my_range;
- IF FOUND
- THEN
- my_min_serial = my_irec.event_delimiter;
- my_rval.rvalue = my_rval.rvalue + my_irec.cumulative_number;
- SELECT SUM(delta) AS delta_sum
- INTO my_irec
- FROM merchant_statistic_counter_event
- WHERE imeta_serial_id = my_meta
- AND slot < my_time - my_range
- AND nevent_serial_id >= my_min_serial;
- IF FOUND AND my_irec.delta_sum IS NOT NULL
- THEN
- my_delta = my_irec.delta_sum;
- my_rval.rvalue = my_rval.rvalue - my_delta;
- SELECT nevent_serial_id
- INTO my_next_max_serial
- FROM merchant_statistic_counter_event
- WHERE imeta_serial_id = my_meta
- AND slot >= my_time - my_range
- AND nevent_serial_id >= my_min_serial
- ORDER BY slot ASC
- LIMIT 1;
- IF FOUND
- THEN
- UPDATE merchant_statistic_interval_counter
- SET cumulative_number = cumulative_number - my_delta,
- event_delimiter = my_next_max_serial
- WHERE imeta_serial_id = my_meta
- AND range = my_range;
- ELSE
- DELETE FROM merchant_statistic_interval_counter
- WHERE imeta_serial_id = my_meta
- AND range = my_range;
- END IF;
- IF (my_i < COALESCE(array_length(my_ranges,1),0))
- THEN
- UPDATE merchant_statistic_interval_counter AS usic SET
- cumulative_number = cumulative_number + my_delta,
- event_delimiter = LEAST(usic.event_delimiter,my_min_serial)
- WHERE imeta_serial_id = my_meta
- AND range=my_ranges[my_i+1];
- IF NOT FOUND
- THEN
- INSERT INTO merchant_statistic_interval_counter
- (imeta_serial_id
- ,range
- ,event_delimiter
- ,cumulative_number
- ) VALUES (
- my_meta
- ,my_ranges[my_i+1]
- ,my_min_serial
- ,my_delta);
- END IF;
- ELSE
- DELETE FROM merchant_statistic_counter_event
- WHERE imeta_serial_id = my_meta
- AND slot < my_time - my_range;
- END IF;
- END IF;
- my_rval.range = my_range;
- RETURN NEXT my_rval;
- END IF;
- END LOOP;
- END $BODY$
- $OUTER$, s);
diff --git a/src/backenddb/pg_create_instance_schema_tables.sql.fragment b/src/backenddb/pg_create_instance_schema_tables.sql.fragment
@@ -1,961 +0,0 @@
--- =====================================================================
--- Per-instance schema constructor: tables, indexes, FKs.
---
--- This fragment is embedded inside a PL/pgSQL function whose local
--- variable `s TEXT` already holds the schema name string
--- 'merchant_instance_<merchant_serial>'. Every DDL is issued via
--- EXECUTE format(...) with %I quoting on the schema name(s).
---
--- Triggers, sequence resets, stored procedures and the merchant.* FK
--- back-references to merchant_instances are intentionally omitted.
--- =====================================================================
-
- -- -------------------------------------------------------------------
- -- 1. Create the per-instance schema.
- -- -------------------------------------------------------------------
- EXECUTE format('CREATE SCHEMA %I', s);
-
- -- -------------------------------------------------------------------
- -- 2. CREATE TABLE statements for all per-instance tables.
- -- The merchant_serial column has been dropped everywhere; PK,
- -- UNIQUE and CHECK constraints have been adjusted accordingly.
- -- -------------------------------------------------------------------
-
- -- merchant_accounts
- EXECUTE format('CREATE TABLE %I.merchant_accounts ('
- || ' account_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' h_wire bytea NOT NULL UNIQUE,'
- || ' salt bytea NOT NULL,'
- || ' credit_facade_url text,'
- || ' credit_facade_credentials jsonb,'
- || ' last_bank_serial bigint DEFAULT 0 NOT NULL,'
- || ' payto_uri text NOT NULL UNIQUE,'
- || ' active boolean NOT NULL,'
- || ' extra_wire_subject_metadata text,'
- || ' CONSTRAINT merchant_accounts_h_wire_check CHECK ((length(h_wire) = 64)),'
- || ' CONSTRAINT merchant_accounts_salt_check CHECK ((length(salt) = 16))'
- || ')', s);
-
- -- merchant_builtin_unit_overrides
- EXECUTE format('CREATE TABLE %I.merchant_builtin_unit_overrides ('
- || ' builtin_unit_serial bigint NOT NULL PRIMARY KEY,'
- || ' override_allow_fraction boolean,'
- || ' override_precision_level integer,'
- || ' override_active boolean,'
- || ' CONSTRAINT merchant_builtin_unit_overrides_override_precision_level_check'
- || ' CHECK (((override_precision_level >= 0) AND (override_precision_level <= 6)))'
- || ')', s);
-
- -- merchant_categories
- EXECUTE format('CREATE TABLE %I.merchant_categories ('
- || ' category_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' category_name text NOT NULL UNIQUE,'
- || ' category_name_i18n jsonb NOT NULL'
- || ')', s);
-
- -- merchant_contract_terms
- EXECUTE format('CREATE TABLE %I.merchant_contract_terms ('
- || ' order_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' order_id text NOT NULL UNIQUE,'
- || ' contract_terms jsonb NOT NULL,'
- || ' wallet_data text,'
- || ' h_contract_terms bytea NOT NULL UNIQUE,'
- || ' creation_time bigint NOT NULL,'
- || ' pay_deadline bigint NOT NULL,'
- || ' refund_deadline bigint NOT NULL,'
- || ' paid boolean DEFAULT false NOT NULL,'
- || ' wired boolean DEFAULT false NOT NULL,'
- || ' fulfillment_url text,'
- || $DDL$ session_id text DEFAULT ''::text NOT NULL,$DDL$
- || ' pos_key text,'
- || ' pos_algorithm integer DEFAULT 0 NOT NULL,'
- || ' claim_token bytea NOT NULL,'
- || ' choice_index smallint,'
- || ' CONSTRAINT merchant_contract_terms_claim_token_check CHECK ((length(claim_token) = 16)),'
- || ' CONSTRAINT merchant_contract_terms_h_contract_terms_check CHECK ((length(h_contract_terms) = 64))'
- || ')', s);
-
- -- merchant_custom_units
- EXECUTE format($DDL$CREATE TABLE %I.merchant_custom_units (
- unit_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- unit text NOT NULL UNIQUE,
- unit_name_long text NOT NULL,
- unit_name_short text NOT NULL,
- unit_name_long_i18n bytea DEFAULT convert_to('{}'::text, 'UTF8'::name) NOT NULL,
- unit_name_short_i18n bytea DEFAULT convert_to('{}'::text, 'UTF8'::name) NOT NULL,
- unit_allow_fraction boolean DEFAULT false NOT NULL,
- unit_precision_level integer DEFAULT 0 NOT NULL,
- unit_active boolean DEFAULT true NOT NULL,
- CONSTRAINT merchant_custom_units_unit_precision_level_check
- CHECK (((unit_precision_level >= 0) AND (unit_precision_level <= 6)))
- )$DDL$, s);
-
- -- merchant_deposit_confirmations
- EXECUTE format('CREATE TABLE %I.merchant_deposit_confirmations ('
- || ' deposit_confirmation_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' order_serial bigint,'
- || ' deposit_timestamp bigint NOT NULL,'
- || ' exchange_url text NOT NULL,'
- || ' total_without_fee merchant.taler_amount_currency NOT NULL,'
- || ' wire_fee merchant.taler_amount_currency NOT NULL,'
- || ' signkey_serial bigint NOT NULL,'
- || ' exchange_sig bytea NOT NULL,'
- || ' account_serial bigint NOT NULL,'
- || ' wire_transfer_deadline bigint DEFAULT 0 NOT NULL,'
- || ' wire_pending boolean DEFAULT true NOT NULL,'
- || ' exchange_failure text,'
- || ' retry_backoff bigint DEFAULT 0 NOT NULL,'
- || ' CONSTRAINT merchant_deposit_confirmations_exchange_sig_check CHECK ((length(exchange_sig) = 64)),'
- || ' UNIQUE (order_serial, exchange_sig)'
- || ')', s);
-
- -- merchant_deposits
- EXECUTE format('CREATE TABLE %I.merchant_deposits ('
- || ' deposit_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' coin_offset integer NOT NULL,'
- || ' deposit_confirmation_serial bigint NOT NULL,'
- || ' coin_pub bytea NOT NULL,'
- || ' coin_sig bytea NOT NULL,'
- || ' amount_with_fee merchant.taler_amount_currency NOT NULL,'
- || ' deposit_fee merchant.taler_amount_currency NOT NULL,'
- || ' refund_fee merchant.taler_amount_currency NOT NULL,'
- || ' settlement_retry_needed boolean DEFAULT true,'
- || ' settlement_retry_time bigint DEFAULT 0,'
- || ' settlement_last_http_status integer,'
- || ' settlement_last_ec integer,'
- || ' settlement_last_detail text,'
- || ' settlement_wtid bytea,'
- || ' settlement_coin_contribution merchant.taler_amount_currency,'
- || ' settlement_expected_credit_serial bigint,'
- || ' signkey_serial bigint,'
- || ' settlement_exchange_sig bytea,'
- || ' CONSTRAINT merchant_deposits_coin_pub_check CHECK ((length(coin_pub) = 32)),'
- || ' CONSTRAINT merchant_deposits_coin_sig_check CHECK ((length(coin_sig) = 64)),'
- || ' CONSTRAINT merchant_deposits_settlement_exchange_sig_check CHECK ((length(settlement_exchange_sig) = 64)),'
- || ' CONSTRAINT merchant_deposits_settlement_wtid_check CHECK ((length(settlement_wtid) = 32)),'
- || ' UNIQUE (deposit_confirmation_serial, coin_pub)'
- || ')', s);
-
- -- merchant_donau_instances
- EXECUTE format('CREATE TABLE %I.merchant_donau_instances ('
- || ' donau_instances_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' donau_url text NOT NULL,'
- || ' charity_name text NOT NULL,'
- || ' charity_id bigint NOT NULL,'
- || ' charity_max_per_year merchant.taler_amount_currency NOT NULL,'
- || ' charity_receipts_to_date merchant.taler_amount_currency NOT NULL,'
- || ' current_year bigint NOT NULL,'
- || ' UNIQUE (donau_url, charity_id)'
- || ')', s);
-
- -- merchant_expected_transfer_to_coin
- EXECUTE format('CREATE TABLE %I.merchant_expected_transfer_to_coin ('
- || ' deposit_serial bigint NOT NULL UNIQUE,'
- || ' expected_credit_serial bigint NOT NULL,'
- || ' offset_in_exchange_list bigint NOT NULL,'
- || ' exchange_deposit_value merchant.taler_amount_currency NOT NULL,'
- || ' exchange_deposit_fee merchant.taler_amount_currency NOT NULL'
- || ')', s);
-
- -- merchant_expected_transfers
- EXECUTE format('CREATE TABLE %I.merchant_expected_transfers ('
- || ' expected_credit_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' exchange_url text NOT NULL,'
- || ' wtid bytea NOT NULL,'
- || ' expected_credit_amount merchant.taler_amount_currency,'
- || ' wire_fee merchant.taler_amount_currency,'
- || ' account_serial bigint NOT NULL,'
- || ' expected_time bigint NOT NULL,'
- || ' retry_time bigint DEFAULT 0 NOT NULL,'
- || ' last_http_status integer,'
- || ' last_ec integer,'
- || ' last_detail text,'
- || ' retry_needed boolean DEFAULT true NOT NULL,'
- || ' signkey_serial bigint,'
- || ' exchange_sig bytea,'
- || ' h_details bytea,'
- || ' confirmed boolean DEFAULT false NOT NULL,'
- || ' CONSTRAINT merchant_expected_transfers_exchange_sig_check CHECK ((length(exchange_sig) = 64)),'
- || ' CONSTRAINT merchant_expected_transfers_h_details_check CHECK ((length(h_details) = 64)),'
- || ' CONSTRAINT merchant_expected_transfers_wtid_check CHECK ((length(wtid) = 32)),'
- || ' UNIQUE (wtid, exchange_url, account_serial)'
- || ')', s);
-
- -- merchant_inventory
- EXECUTE format($DDL$CREATE TABLE %I.merchant_inventory (
- product_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- product_id text NOT NULL UNIQUE,
- description text NOT NULL,
- description_i18n jsonb NOT NULL,
- unit text NOT NULL,
- image text NOT NULL,
- taxes jsonb NOT NULL,
- total_stock bigint NOT NULL,
- total_sold bigint DEFAULT 0 NOT NULL,
- total_lost bigint DEFAULT 0 NOT NULL,
- address jsonb NOT NULL,
- next_restock bigint NOT NULL,
- minimum_age integer DEFAULT 0 NOT NULL,
- product_name text NOT NULL,
- image_hash text,
- price_array merchant.taler_amount_currency[]
- DEFAULT ARRAY[]::merchant.taler_amount_currency[] NOT NULL,
- total_stock_frac integer DEFAULT 0 NOT NULL,
- total_sold_frac integer DEFAULT 0 NOT NULL,
- total_lost_frac integer DEFAULT 0 NOT NULL,
- allow_fractional_quantity boolean DEFAULT false NOT NULL,
- fractional_precision_level integer DEFAULT 0 NOT NULL,
- product_group_serial bigint,
- money_pot_serial bigint,
- price_is_net boolean DEFAULT false
- )$DDL$, s);
-
- -- merchant_inventory_locks
- EXECUTE format('CREATE TABLE %I.merchant_inventory_locks ('
- || ' product_serial bigint NOT NULL,'
- || ' lock_uuid bytea NOT NULL,'
- || ' total_locked bigint NOT NULL,'
- || ' expiration bigint NOT NULL,'
- || ' total_locked_frac integer DEFAULT 0 NOT NULL,'
- || ' CONSTRAINT merchant_inventory_locks_lock_uuid_check CHECK ((length(lock_uuid) = 16))'
- || ')', s);
-
- -- merchant_issued_tokens
- EXECUTE format('CREATE TABLE %I.merchant_issued_tokens ('
- || ' issued_token_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' h_contract_terms bytea NOT NULL,'
- || ' token_family_key_serial bigint,'
- || ' blind_sig bytea NOT NULL,'
- || ' CONSTRAINT merchant_issued_tokens_h_contract_terms_check CHECK ((length(h_contract_terms) = 64))'
- || ')', s);
-
- -- merchant_keys (single-row per schema; merchant_priv becomes the PK)
- EXECUTE format('CREATE TABLE %I.merchant_keys ('
- || ' merchant_priv bytea NOT NULL PRIMARY KEY,'
- || ' CONSTRAINT merchant_keys_merchant_priv_check CHECK ((length(merchant_priv) = 32))'
- || ')', s);
-
- -- merchant_kyc (PK survives unchanged: (account_serial, exchange_url))
- EXECUTE format('CREATE TABLE %I.merchant_kyc ('
- || ' kyc_serial_id bigint GENERATED BY DEFAULT AS IDENTITY UNIQUE,'
- || ' kyc_timestamp bigint NOT NULL,'
- || ' kyc_ok boolean DEFAULT false NOT NULL,'
- || ' account_serial bigint NOT NULL,'
- || ' exchange_url text NOT NULL,'
- || ' access_token bytea,'
- || ' exchange_http_status integer DEFAULT 0,'
- || ' exchange_ec_code integer DEFAULT 0,'
- || ' aml_review boolean DEFAULT false,'
- || ' jaccount_limits jsonb,'
- || ' last_rule_gen bigint DEFAULT 0 NOT NULL,'
- || ' next_kyc_poll bigint DEFAULT 0 NOT NULL,'
- || ' kyc_backoff bigint DEFAULT 0 NOT NULL,'
- || ' CONSTRAINT access_token_length_check CHECK ((length(access_token) = 32)),'
- || ' PRIMARY KEY (account_serial, exchange_url)'
- || ')', s);
-
- -- merchant_login_tokens (note: serial is GENERATED ALWAYS)
- EXECUTE format('CREATE TABLE %I.merchant_login_tokens ('
- || ' token bytea NOT NULL UNIQUE,'
- || ' creation_time bigint NOT NULL,'
- || ' expiration_time bigint NOT NULL,'
- || ' validity_scope integer NOT NULL,'
- || ' description text NOT NULL,'
- || ' serial bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,'
- || ' CONSTRAINT merchant_login_tokens_token_check CHECK ((length(token) = 32))'
- || ')', s);
-
- -- merchant_money_pots
- EXECUTE format('CREATE TABLE %I.merchant_money_pots ('
- || ' money_pot_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' money_pot_name text NOT NULL UNIQUE,'
- || ' money_pot_description text NOT NULL,'
- || ' pot_totals merchant.taler_amount_currency[]'
- || ' DEFAULT ARRAY[]::merchant.taler_amount_currency[] NOT NULL'
- || ')', s);
-
- -- merchant_order_locks
- EXECUTE format('CREATE TABLE %I.merchant_order_locks ('
- || ' product_serial bigint NOT NULL,'
- || ' total_locked bigint NOT NULL,'
- || ' order_serial bigint NOT NULL,'
- || ' total_locked_frac integer DEFAULT 0 NOT NULL'
- || ')', s);
-
- -- merchant_order_token_blinded_sigs
- EXECUTE format('CREATE TABLE %I.merchant_order_token_blinded_sigs ('
- || ' order_token_bs_serial bigint GENERATED BY DEFAULT AS IDENTITY,'
- || ' order_serial bigint NOT NULL,'
- || ' token_index integer NOT NULL,'
- || ' token_blinded_signature bytea NOT NULL,'
- || ' token_hash bytea NOT NULL,'
- || ' CONSTRAINT merchant_order_token_blinded_sigs_token_hash_check CHECK ((length(token_hash) = 64)),'
- || ' PRIMARY KEY (order_serial, token_index)'
- || ')', s);
-
- -- merchant_orders
- EXECUTE format($DDL$CREATE TABLE %I.merchant_orders (
- order_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- order_id text NOT NULL UNIQUE,
- claim_token bytea NOT NULL,
- h_post_data bytea NOT NULL,
- pay_deadline bigint NOT NULL,
- creation_time bigint NOT NULL,
- contract_terms jsonb NOT NULL,
- pos_key text,
- pos_algorithm integer DEFAULT 0 NOT NULL,
- fulfillment_url text,
- session_id text DEFAULT ''::text NOT NULL,
- CONSTRAINT merchant_orders_claim_token_check CHECK ((length(claim_token) = 16)),
- CONSTRAINT merchant_orders_h_post_data_check CHECK ((length(h_post_data) = 64))
- )$DDL$, s);
-
- -- merchant_otp_devices
- EXECUTE format('CREATE TABLE %I.merchant_otp_devices ('
- || ' otp_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' otp_id text NOT NULL UNIQUE,'
- || ' otp_description text NOT NULL,'
- || ' otp_key text,'
- || ' otp_algorithm integer DEFAULT 0 NOT NULL,'
- || ' otp_ctr bigint DEFAULT 0 NOT NULL'
- || ')', s);
-
- -- merchant_pending_webhooks
- -- The original (merchant_serial, webhook_pending_serial) UNIQUE
- -- collapses to just (webhook_pending_serial), which is already the
- -- PK, so no extra UNIQUE constraint is needed.
- EXECUTE format('CREATE TABLE %I.merchant_pending_webhooks ('
- || ' webhook_pending_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' webhook_serial bigint NOT NULL,'
- || ' next_attempt bigint DEFAULT 0 NOT NULL,'
- || ' retries integer DEFAULT 0 NOT NULL,'
- || ' url text NOT NULL,'
- || ' http_method text NOT NULL,'
- || ' header text,'
- || ' body text'
- || ')', s);
-
- -- merchant_product_categories
- EXECUTE format('CREATE TABLE %I.merchant_product_categories ('
- || ' category_serial bigint NOT NULL,'
- || ' product_serial bigint NOT NULL'
- || ')', s);
-
- -- merchant_product_groups
- EXECUTE format('CREATE TABLE %I.merchant_product_groups ('
- || ' product_group_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' product_group_name text NOT NULL UNIQUE,'
- || ' product_group_description text NOT NULL'
- || ')', s);
-
- -- merchant_refund_proofs
- EXECUTE format('CREATE TABLE %I.merchant_refund_proofs ('
- || ' refund_serial bigint NOT NULL PRIMARY KEY,'
- || ' exchange_sig bytea NOT NULL,'
- || ' signkey_serial bigint NOT NULL,'
- || ' CONSTRAINT merchant_refund_proofs_exchange_sig_check CHECK ((length(exchange_sig) = 64))'
- || ')', s);
-
- -- merchant_refunds
- EXECUTE format('CREATE TABLE %I.merchant_refunds ('
- || ' refund_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' order_serial bigint NOT NULL,'
- || ' rtransaction_id bigint NOT NULL,'
- || ' refund_timestamp bigint NOT NULL,'
- || ' coin_pub bytea NOT NULL,'
- || ' reason text NOT NULL,'
- || ' refund_amount merchant.taler_amount_currency NOT NULL,'
- || ' UNIQUE (order_serial, coin_pub, rtransaction_id)'
- || ')', s);
-
- -- merchant_reports
- EXECUTE format('CREATE TABLE %I.merchant_reports ('
- || ' report_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' report_program_section text NOT NULL,'
- || ' report_description text NOT NULL,'
- || ' mime_type text NOT NULL,'
- || ' report_token bytea NOT NULL,'
- || ' data_source text NOT NULL,'
- || ' target_address text NOT NULL,'
- || ' frequency bigint NOT NULL,'
- || ' frequency_shift bigint NOT NULL,'
- || ' next_transmission bigint NOT NULL,'
- || ' last_error_code integer,'
- || ' last_error_detail text,'
- || ' one_shot_hidden boolean DEFAULT false,'
- || ' CONSTRAINT merchant_reports_report_token_check CHECK ((length(report_token) = 32))'
- || ')', s);
-
- -- merchant_used_tokens
- EXECUTE format('CREATE TABLE %I.merchant_used_tokens ('
- || ' spent_token_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' h_contract_terms bytea NOT NULL,'
- || ' token_family_key_serial bigint,'
- || ' token_pub bytea NOT NULL UNIQUE,'
- || ' token_sig bytea NOT NULL,'
- || ' blind_sig bytea NOT NULL,'
- || ' CONSTRAINT merchant_spent_tokens_h_contract_terms_check CHECK ((length(h_contract_terms) = 64)),'
- || ' CONSTRAINT merchant_spent_tokens_token_pub_check CHECK ((length(token_pub) = 32)),'
- || ' CONSTRAINT merchant_spent_tokens_token_sig_check CHECK ((length(token_sig) = 64))'
- || ')', s);
-
- -- merchant_statistic_amount_event
- EXECUTE format('CREATE TABLE %I.merchant_statistic_amount_event ('
- || ' aevent_serial_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' imeta_serial_id bigint,'
- || ' slot bigint NOT NULL,'
- || ' delta_curr character varying(12) NOT NULL,'
- || ' delta_value bigint NOT NULL,'
- || ' delta_frac integer NOT NULL,'
- || ' CONSTRAINT event_key UNIQUE (imeta_serial_id, delta_curr, slot)'
- || ')', s);
-
- -- merchant_statistic_bucket_amount
- EXECUTE format('CREATE TABLE %I.merchant_statistic_bucket_amount ('
- || ' bmeta_serial_id bigint NOT NULL,'
- || ' bucket_start bigint NOT NULL,'
- || ' bucket_range merchant.statistic_range NOT NULL,'
- || ' curr character varying(12) NOT NULL,'
- || ' cumulative_value bigint NOT NULL,'
- || ' cumulative_frac integer NOT NULL,'
- || ' PRIMARY KEY (bmeta_serial_id, curr, bucket_start, bucket_range)'
- || ')', s);
-
- -- merchant_statistic_bucket_counter
- EXECUTE format('CREATE TABLE %I.merchant_statistic_bucket_counter ('
- || ' bmeta_serial_id bigint NOT NULL,'
- || ' bucket_start bigint NOT NULL,'
- || ' bucket_range merchant.statistic_range NOT NULL,'
- || ' cumulative_number bigint NOT NULL,'
- || ' PRIMARY KEY (bmeta_serial_id, bucket_start, bucket_range)'
- || ')', s);
-
- -- merchant_statistic_bucket_meta
- EXECUTE format('CREATE TABLE %I.merchant_statistic_bucket_meta ('
- || ' bmeta_serial_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' slug text NOT NULL,'
- || ' description text NOT NULL,'
- || ' stype merchant.statistic_type NOT NULL,'
- || ' ranges merchant.statistic_range[] NOT NULL,'
- || ' ages integer[] NOT NULL,'
- || ' CONSTRAINT equal_array_length CHECK ((array_length(ranges, 1) = array_length(ages, 1))),'
- || ' UNIQUE (slug, stype)'
- || ')', s);
-
- -- merchant_statistic_counter_event
- EXECUTE format('CREATE TABLE %I.merchant_statistic_counter_event ('
- || ' nevent_serial_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' imeta_serial_id bigint,'
- || ' slot bigint NOT NULL,'
- || ' delta bigint NOT NULL,'
- || ' UNIQUE (imeta_serial_id, slot)'
- || ')', s);
-
- -- merchant_statistic_interval_amount
- EXECUTE format('CREATE TABLE %I.merchant_statistic_interval_amount ('
- || ' imeta_serial_id bigint NOT NULL,'
- || ' event_delimiter bigint NOT NULL,'
- || ' range bigint NOT NULL,'
- || ' curr character varying(12) NOT NULL,'
- || ' cumulative_value bigint NOT NULL,'
- || ' cumulative_frac integer NOT NULL,'
- || ' PRIMARY KEY (imeta_serial_id, curr, range)'
- || ')', s);
-
- -- merchant_statistic_interval_counter
- EXECUTE format('CREATE TABLE %I.merchant_statistic_interval_counter ('
- || ' imeta_serial_id bigint NOT NULL,'
- || ' range bigint NOT NULL,'
- || ' event_delimiter bigint NOT NULL,'
- || ' cumulative_number bigint NOT NULL,'
- || ' PRIMARY KEY (imeta_serial_id, range)'
- || ')', s);
-
- -- merchant_statistic_interval_meta
- EXECUTE format('CREATE TABLE %I.merchant_statistic_interval_meta ('
- || ' imeta_serial_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' slug text NOT NULL,'
- || ' description text NOT NULL,'
- || ' stype merchant.statistic_type NOT NULL,'
- || ' ranges bigint[] NOT NULL,'
- || ' precisions bigint[] NOT NULL,'
- || ' CONSTRAINT equal_array_length CHECK ((array_length(ranges, 1) = array_length(precisions, 1))),'
- || ' CONSTRAINT merchant_statistic_interval_meta_precisions_check CHECK ((array_length(precisions, 1) > 0)),'
- || ' CONSTRAINT merchant_statistic_interval_meta_ranges_check CHECK ((array_length(ranges, 1) > 0)),'
- || ' UNIQUE (slug, stype)'
- || ')', s);
-
- -- merchant_template
- EXECUTE format('CREATE TABLE %I.merchant_template ('
- || ' template_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' template_id text NOT NULL UNIQUE,'
- || ' template_description text NOT NULL,'
- || ' otp_device_id bigint,'
- || ' template_contract jsonb NOT NULL,'
- || ' editable_defaults jsonb'
- || ')', s);
-
- -- merchant_token_families
- EXECUTE format($DDL$CREATE TABLE %I.merchant_token_families (
- token_family_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
- slug text NOT NULL UNIQUE,
- name text NOT NULL,
- description text,
- description_i18n jsonb NOT NULL,
- valid_after bigint NOT NULL,
- valid_before bigint NOT NULL,
- duration bigint NOT NULL,
- kind text NOT NULL,
- issued bigint DEFAULT 0,
- used bigint DEFAULT 0,
- validity_granularity bigint DEFAULT '2592000000000'::bigint NOT NULL,
- start_offset bigint DEFAULT 0 NOT NULL,
- cipher_choice text DEFAULT 'rsa(2048)'::text NOT NULL,
- extra_data jsonb,
- CONSTRAINT merchant_token_families_kind_check
- CHECK ((kind = ANY (ARRAY['subscription'::text, 'discount'::text]))),
- CONSTRAINT merchant_token_families_validity_granularity_check
- CHECK ((validity_granularity = ANY (ARRAY[(60000000)::bigint,
- '3600000000'::bigint, '86400000000'::bigint, '604800000000'::bigint,
- '2592000000000'::bigint, '7776000000000'::bigint,
- '31536000000000'::bigint])))
- )$DDL$, s);
-
- -- merchant_token_family_keys
- EXECUTE format('CREATE TABLE %I.merchant_token_family_keys ('
- || ' token_family_key_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' token_family_serial bigint,'
- || ' pub bytea NOT NULL,'
- || ' h_pub bytea NOT NULL UNIQUE,'
- || ' priv bytea,'
- || ' cipher text NOT NULL,'
- || ' signature_validity_start bigint DEFAULT 0 NOT NULL,'
- || ' signature_validity_end bigint DEFAULT 0 NOT NULL,'
- || ' private_key_deleted_at bigint DEFAULT 0 NOT NULL,'
- || ' private_key_created_at bigint DEFAULT 0 NOT NULL,'
- || ' CONSTRAINT h_pub_length_check CHECK ((length(h_pub) = 64)),'
- || $DDL$ CONSTRAINT merchant_token_family_keys_cipher_check CHECK ((cipher = ANY (ARRAY['rsa'::text, 'cs'::text])))$DDL$
- || ')', s);
-
- -- merchant_transfer_signatures
- EXECUTE format('CREATE TABLE %I.merchant_transfer_signatures ('
- || ' expected_credit_serial bigint NOT NULL PRIMARY KEY,'
- || ' signkey_serial bigint NOT NULL,'
- || ' wire_fee merchant.taler_amount_currency NOT NULL,'
- || ' credit_amount merchant.taler_amount_currency NOT NULL,'
- || ' execution_time bigint NOT NULL,'
- || ' exchange_sig bytea NOT NULL,'
- || ' CONSTRAINT merchant_transfer_signatures_exchange_sig_check CHECK ((length(exchange_sig) = 64))'
- || ')', s);
-
- -- merchant_transfers
- EXECUTE format('CREATE TABLE %I.merchant_transfers ('
- || ' credit_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' exchange_url text NOT NULL,'
- || ' wtid bytea,'
- || ' credit_amount merchant.taler_amount_currency NOT NULL,'
- || ' account_serial bigint NOT NULL,'
- || ' bank_serial_id bigint,'
- || ' expected boolean DEFAULT false,'
- || ' execution_time bigint DEFAULT 0,'
- || ' CONSTRAINT merchant_transfers_wtid_check CHECK ((length(wtid) = 32)),'
- || ' CONSTRAINT merchant_transfers_unique UNIQUE (wtid, exchange_url, account_serial, bank_serial_id)'
- || ')', s);
-
- -- merchant_unclaim_signatures
- EXECUTE format('CREATE TABLE %I.merchant_unclaim_signatures ('
- || ' unclaim_serial bigint GENERATED BY DEFAULT AS IDENTITY UNIQUE,'
- || ' h_contract_terms bytea NOT NULL,'
- || ' unclaim_sig bytea NOT NULL PRIMARY KEY,'
- || ' expiration_time bigint NOT NULL,'
- || ' CONSTRAINT merchant_unclaim_signatures_h_contract_terms_check CHECK ((length(h_contract_terms) = 64)),'
- || ' CONSTRAINT merchant_unclaim_signatures_unclaim_sig_check CHECK ((length(unclaim_sig) = 64))'
- || ')', s);
-
- -- merchant_webhook
- EXECUTE format('CREATE TABLE %I.merchant_webhook ('
- || ' webhook_serial bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' webhook_id text NOT NULL UNIQUE,'
- || ' event_type text NOT NULL,'
- || ' url text NOT NULL,'
- || ' http_method text NOT NULL,'
- || ' header_template text,'
- || ' body_template text'
- || ')', s);
-
- -- tan_challenges
- EXECUTE format('CREATE TABLE %I.tan_challenges ('
- || ' challenge_id bigint GENERATED BY DEFAULT AS IDENTITY UNIQUE,'
- || ' h_body bytea NOT NULL,'
- || ' salt bytea NOT NULL,'
- || ' op merchant.op_enum NOT NULL,'
- || ' code text NOT NULL,'
- || ' creation_date bigint NOT NULL,'
- || ' expiration_date bigint NOT NULL,'
- || ' retransmission_date bigint DEFAULT 0 NOT NULL,'
- || ' confirmation_date bigint,'
- || ' retry_counter integer NOT NULL,'
- || ' tan_channel merchant.tan_enum NOT NULL,'
- || ' required_address text NOT NULL,'
- || ' CONSTRAINT tan_challenges_h_body_check CHECK ((length(h_body) = 32)),'
- || ' CONSTRAINT tan_challenges_salt_check CHECK ((length(salt) = 16))'
- || ')', s);
-
- -- -------------------------------------------------------------------
- -- 3. CREATE INDEX statements (per-instance only).
- -- Index names are bare; PostgreSQL scopes them by schema, so the
- -- same logical name in each instance schema is fine.
- -- merchant_serial leading columns are dropped from the column list.
- -- -------------------------------------------------------------------
-
- -- merchant_product_categories
- EXECUTE format('CREATE INDEX merchant_categories_by_category'
- || ' ON %I.merchant_product_categories USING btree (category_serial)', s);
- EXECUTE format('CREATE INDEX merchant_categories_by_product'
- || ' ON %I.merchant_product_categories USING btree (product_serial)', s);
-
- -- merchant_contract_terms
- EXECUTE format('CREATE INDEX merchant_contract_terms_by_expiration'
- || ' ON %I.merchant_contract_terms USING btree (paid, pay_deadline)', s);
- EXECUTE format('CREATE INDEX merchant_contract_terms_by_merchant_and_expiration'
- || ' ON %I.merchant_contract_terms USING btree (pay_deadline)', s);
- EXECUTE format('CREATE INDEX merchant_contract_terms_by_merchant_and_payment'
- || ' ON %I.merchant_contract_terms USING btree (paid)', s);
- EXECUTE format('CREATE INDEX merchant_contract_terms_by_merchant_and_session'
- || ' ON %I.merchant_contract_terms USING btree (session_id)', s);
- EXECUTE format('CREATE INDEX merchant_contract_terms_by_merchant_session_and_fulfillment'
- || ' ON %I.merchant_contract_terms USING btree (fulfillment_url, session_id)', s);
-
- -- merchant_deposit_confirmations
- EXECUTE format('CREATE INDEX merchant_deposit_confirmations_by_pending_wire'
- || ' ON %I.merchant_deposit_confirmations USING btree (exchange_url, wire_transfer_deadline)'
- || ' WHERE wire_pending', s);
-
- -- merchant_deposits
- EXECUTE format('CREATE INDEX merchant_deposits_by_deposit_confirmation'
- || ' ON %I.merchant_deposits USING btree (deposit_confirmation_serial)', s);
- EXECUTE format('CREATE INDEX merchant_deposits_by_deposit_confirmation_serial'
- || ' ON %I.merchant_deposits USING btree (deposit_confirmation_serial)', s);
- EXECUTE format('CREATE INDEX merchant_deposits_by_settlement_open'
- || ' ON %I.merchant_deposits USING btree (settlement_retry_time)'
- || ' WHERE settlement_retry_needed', s);
-
- -- merchant_expected_transfers
- EXECUTE format('CREATE INDEX merchant_expected_transfers_by_open'
- || ' ON %I.merchant_expected_transfers USING btree (retry_time)'
- || ' WHERE ((NOT confirmed) OR retry_needed)', s);
-
- -- merchant_inventory
- EXECUTE format('CREATE INDEX merchant_inventory_by_image_hash'
- || ' ON %I.merchant_inventory USING btree (image_hash)', s);
-
- -- merchant_inventory_locks
- EXECUTE format('CREATE INDEX merchant_inventory_locks_by_expiration'
- || ' ON %I.merchant_inventory_locks USING btree (expiration)', s);
- EXECUTE format('CREATE INDEX merchant_inventory_locks_by_uuid'
- || ' ON %I.merchant_inventory_locks USING btree (lock_uuid)', s);
-
- -- merchant_kyc
- EXECUTE format('CREATE INDEX merchant_kyc_by_next_kyc_poll'
- || ' ON %I.merchant_kyc USING btree (next_kyc_poll)', s);
-
- -- merchant_login_tokens
- EXECUTE format('CREATE INDEX merchant_login_tokens_by_expiration'
- || ' ON %I.merchant_login_tokens USING btree (expiration_time)', s);
-
- -- merchant_orders
- EXECUTE format('CREATE INDEX merchant_orders_by_creation_time'
- || ' ON %I.merchant_orders USING btree (creation_time)', s);
- EXECUTE format('CREATE INDEX merchant_orders_by_expiration'
- || ' ON %I.merchant_orders USING btree (pay_deadline)', s);
- EXECUTE format('CREATE INDEX merchant_orders_by_merchant_and_fullfilment_and_session'
- || ' ON %I.merchant_orders USING btree (fulfillment_url, session_id)', s);
- EXECUTE format('CREATE INDEX merchant_orders_by_merchant_and_session'
- || ' ON %I.merchant_orders USING btree (session_id)', s);
-
- -- merchant_order_locks
- EXECUTE format('CREATE INDEX merchant_orders_locks_by_order_and_product'
- || ' ON %I.merchant_order_locks USING btree (order_serial, product_serial)', s);
-
- -- merchant_refunds
- EXECUTE format('CREATE INDEX merchant_refunds_by_coin_and_order'
- || ' ON %I.merchant_refunds USING btree (coin_pub, order_serial)', s);
-
- -- merchant_expected_transfer_to_coin
- EXECUTE format('CREATE INDEX merchant_transfers_by_credit'
- || ' ON %I.merchant_expected_transfer_to_coin USING btree (expected_credit_serial)', s);
-
- -- merchant_unclaim_signatures
- EXECUTE format('CREATE INDEX merchant_unclaim_signatures_by_expiration'
- || ' ON %I.merchant_unclaim_signatures USING btree (expiration_time)', s);
-
- -- tan_challenges
- EXECUTE format('CREATE INDEX tan_challenges_expiration_index'
- || ' ON %I.tan_challenges USING btree (expiration_date)', s);
-
- -- trigram indexes
- EXECUTE format('CREATE INDEX trgm_idx_categories_by_name'
- || ' ON %I.merchant_categories USING gin (lower(category_name) public.gin_trgm_ops)', s);
- EXECUTE format($DDL$CREATE INDEX trgm_idx_contract_summaries
- ON %I.merchant_contract_terms USING gin (lower((contract_terms ->> 'summary'::text)) public.gin_trgm_ops)$DDL$, s);
- EXECUTE format($DDL$CREATE INDEX trgm_idx_order_summaries
- ON %I.merchant_orders USING gin (lower((contract_terms ->> 'summary'::text)) public.gin_trgm_ops)$DDL$, s);
- EXECUTE format('CREATE INDEX trgm_idx_products_by_description'
- || ' ON %I.merchant_inventory USING gin (lower(description) public.gin_trgm_ops)', s);
- EXECUTE format('CREATE INDEX trgm_idx_products_by_name'
- || ' ON %I.merchant_inventory USING gin (lower(product_name) public.gin_trgm_ops)', s);
-
- -- -------------------------------------------------------------------
- -- 4. ALTER TABLE for FKs *between per-instance tables* (intra-schema).
- -- Both sides live in `s`; use format(..., s, s).
- -- -------------------------------------------------------------------
-
- -- merchant_deposit_confirmations -> merchant_accounts
- EXECUTE format('ALTER TABLE %I.merchant_deposit_confirmations'
- || ' ADD CONSTRAINT merchant_deposit_confirmations_account_serial_fkey'
- || ' FOREIGN KEY (account_serial)'
- || ' REFERENCES %I.merchant_accounts(account_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_deposit_confirmations -> merchant_contract_terms
- EXECUTE format('ALTER TABLE %I.merchant_deposit_confirmations'
- || ' ADD CONSTRAINT merchant_deposit_confirmations_order_serial_fkey'
- || ' FOREIGN KEY (order_serial)'
- || ' REFERENCES %I.merchant_contract_terms(order_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_deposits -> merchant_deposit_confirmations
- EXECUTE format('ALTER TABLE %I.merchant_deposits'
- || ' ADD CONSTRAINT merchant_deposits_deposit_confirmation_serial_fkey'
- || ' FOREIGN KEY (deposit_confirmation_serial)'
- || ' REFERENCES %I.merchant_deposit_confirmations(deposit_confirmation_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_deposits -> merchant_expected_transfers (no ON DELETE clause originally)
- EXECUTE format('ALTER TABLE %I.merchant_deposits'
- || ' ADD CONSTRAINT merchant_deposits_settlement_expected_credit_serial_fkey'
- || ' FOREIGN KEY (settlement_expected_credit_serial)'
- || ' REFERENCES %I.merchant_expected_transfers(expected_credit_serial)', s, s);
-
- -- merchant_expected_transfer_to_coin -> merchant_deposits
- EXECUTE format('ALTER TABLE %I.merchant_expected_transfer_to_coin'
- || ' ADD CONSTRAINT merchant_expected_transfer_to_coin_deposit_serial_fkey'
- || ' FOREIGN KEY (deposit_serial)'
- || ' REFERENCES %I.merchant_deposits(deposit_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_expected_transfer_to_coin -> merchant_expected_transfers
- EXECUTE format('ALTER TABLE %I.merchant_expected_transfer_to_coin'
- || ' ADD CONSTRAINT merchant_expected_transfer_to_coin_expected_credit_serial_fkey'
- || ' FOREIGN KEY (expected_credit_serial)'
- || ' REFERENCES %I.merchant_expected_transfers(expected_credit_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_expected_transfers -> merchant_accounts
- EXECUTE format('ALTER TABLE %I.merchant_expected_transfers'
- || ' ADD CONSTRAINT merchant_expected_transfers_account_serial_fkey'
- || ' FOREIGN KEY (account_serial)'
- || ' REFERENCES %I.merchant_accounts(account_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_inventory -> merchant_money_pots
- EXECUTE format('ALTER TABLE %I.merchant_inventory'
- || ' ADD CONSTRAINT merchant_inventory_money_pot_serial_fkey'
- || ' FOREIGN KEY (money_pot_serial)'
- || ' REFERENCES %I.merchant_money_pots(money_pot_serial) ON DELETE SET NULL', s, s);
-
- -- merchant_inventory -> merchant_product_groups
- EXECUTE format('ALTER TABLE %I.merchant_inventory'
- || ' ADD CONSTRAINT merchant_inventory_product_group_serial_fkey'
- || ' FOREIGN KEY (product_group_serial)'
- || ' REFERENCES %I.merchant_product_groups(product_group_serial) ON DELETE SET NULL', s, s);
-
- -- merchant_inventory_locks -> merchant_inventory
- EXECUTE format('ALTER TABLE %I.merchant_inventory_locks'
- || ' ADD CONSTRAINT merchant_inventory_locks_product_serial_fkey'
- || ' FOREIGN KEY (product_serial)'
- || ' REFERENCES %I.merchant_inventory(product_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_issued_tokens -> merchant_token_family_keys
- EXECUTE format('ALTER TABLE %I.merchant_issued_tokens'
- || ' ADD CONSTRAINT merchant_issued_tokens_token_family_key_serial_fkey'
- || ' FOREIGN KEY (token_family_key_serial)'
- || ' REFERENCES %I.merchant_token_family_keys(token_family_key_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_kyc -> merchant_accounts
- EXECUTE format('ALTER TABLE %I.merchant_kyc'
- || ' ADD CONSTRAINT merchant_kyc_account_serial_fkey'
- || ' FOREIGN KEY (account_serial)'
- || ' REFERENCES %I.merchant_accounts(account_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_order_locks -> merchant_orders
- EXECUTE format('ALTER TABLE %I.merchant_order_locks'
- || ' ADD CONSTRAINT merchant_order_locks_order_serial_fkey'
- || ' FOREIGN KEY (order_serial)'
- || ' REFERENCES %I.merchant_orders(order_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_order_locks -> merchant_inventory (no ON DELETE clause originally)
- EXECUTE format('ALTER TABLE %I.merchant_order_locks'
- || ' ADD CONSTRAINT merchant_order_locks_product_serial_fkey'
- || ' FOREIGN KEY (product_serial)'
- || ' REFERENCES %I.merchant_inventory(product_serial)', s, s);
-
- -- merchant_order_token_blinded_sigs -> merchant_contract_terms
- EXECUTE format('ALTER TABLE %I.merchant_order_token_blinded_sigs'
- || ' ADD CONSTRAINT merchant_order_token_blinded_sigs_order_serial_fkey'
- || ' FOREIGN KEY (order_serial)'
- || ' REFERENCES %I.merchant_contract_terms(order_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_pending_webhooks -> merchant_webhook
- EXECUTE format('ALTER TABLE %I.merchant_pending_webhooks'
- || ' ADD CONSTRAINT merchant_pending_webhooks_webhook_serial_fkey'
- || ' FOREIGN KEY (webhook_serial)'
- || ' REFERENCES %I.merchant_webhook(webhook_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_product_categories -> merchant_categories
- EXECUTE format('ALTER TABLE %I.merchant_product_categories'
- || ' ADD CONSTRAINT merchant_product_categories_category_serial_fkey'
- || ' FOREIGN KEY (category_serial)'
- || ' REFERENCES %I.merchant_categories(category_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_product_categories -> merchant_inventory
- EXECUTE format('ALTER TABLE %I.merchant_product_categories'
- || ' ADD CONSTRAINT merchant_product_categories_product_serial_fkey'
- || ' FOREIGN KEY (product_serial)'
- || ' REFERENCES %I.merchant_inventory(product_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_refund_proofs -> merchant_refunds
- EXECUTE format('ALTER TABLE %I.merchant_refund_proofs'
- || ' ADD CONSTRAINT merchant_refund_proofs_refund_serial_fkey'
- || ' FOREIGN KEY (refund_serial)'
- || ' REFERENCES %I.merchant_refunds(refund_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_refunds -> merchant_contract_terms
- EXECUTE format('ALTER TABLE %I.merchant_refunds'
- || ' ADD CONSTRAINT merchant_refunds_order_serial_fkey'
- || ' FOREIGN KEY (order_serial)'
- || ' REFERENCES %I.merchant_contract_terms(order_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_used_tokens -> merchant_token_family_keys
- EXECUTE format('ALTER TABLE %I.merchant_used_tokens'
- || ' ADD CONSTRAINT merchant_spent_tokens_token_family_key_serial_fkey'
- || ' FOREIGN KEY (token_family_key_serial)'
- || ' REFERENCES %I.merchant_token_family_keys(token_family_key_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_statistic_amount_event -> merchant_statistic_interval_meta
- EXECUTE format('ALTER TABLE %I.merchant_statistic_amount_event'
- || ' ADD CONSTRAINT merchant_statistic_amount_event_imeta_serial_id_fkey'
- || ' FOREIGN KEY (imeta_serial_id)'
- || ' REFERENCES %I.merchant_statistic_interval_meta(imeta_serial_id) ON DELETE CASCADE', s, s);
-
- -- merchant_statistic_bucket_amount -> merchant_statistic_bucket_meta
- EXECUTE format('ALTER TABLE %I.merchant_statistic_bucket_amount'
- || ' ADD CONSTRAINT merchant_statistic_bucket_amount_bmeta_serial_id_fkey'
- || ' FOREIGN KEY (bmeta_serial_id)'
- || ' REFERENCES %I.merchant_statistic_bucket_meta(bmeta_serial_id) ON DELETE CASCADE', s, s);
-
- -- merchant_statistic_bucket_counter -> merchant_statistic_bucket_meta
- EXECUTE format('ALTER TABLE %I.merchant_statistic_bucket_counter'
- || ' ADD CONSTRAINT merchant_statistic_bucket_counter_bmeta_serial_id_fkey'
- || ' FOREIGN KEY (bmeta_serial_id)'
- || ' REFERENCES %I.merchant_statistic_bucket_meta(bmeta_serial_id) ON DELETE CASCADE', s, s);
-
- -- merchant_statistic_counter_event -> merchant_statistic_interval_meta
- EXECUTE format('ALTER TABLE %I.merchant_statistic_counter_event'
- || ' ADD CONSTRAINT merchant_statistic_counter_event_imeta_serial_id_fkey'
- || ' FOREIGN KEY (imeta_serial_id)'
- || ' REFERENCES %I.merchant_statistic_interval_meta(imeta_serial_id) ON DELETE CASCADE', s, s);
-
- -- merchant_statistic_interval_amount -> merchant_statistic_amount_event
- EXECUTE format('ALTER TABLE %I.merchant_statistic_interval_amount'
- || ' ADD CONSTRAINT merchant_statistic_interval_amount_event_delimiter_fkey'
- || ' FOREIGN KEY (event_delimiter)'
- || ' REFERENCES %I.merchant_statistic_amount_event(aevent_serial_id) ON DELETE RESTRICT', s, s);
-
- -- merchant_statistic_interval_amount -> merchant_statistic_interval_meta
- EXECUTE format('ALTER TABLE %I.merchant_statistic_interval_amount'
- || ' ADD CONSTRAINT merchant_statistic_interval_amount_imeta_serial_id_fkey'
- || ' FOREIGN KEY (imeta_serial_id)'
- || ' REFERENCES %I.merchant_statistic_interval_meta(imeta_serial_id) ON DELETE CASCADE', s, s);
-
- -- merchant_statistic_interval_counter -> merchant_statistic_counter_event
- EXECUTE format('ALTER TABLE %I.merchant_statistic_interval_counter'
- || ' ADD CONSTRAINT merchant_statistic_interval_counter_event_delimiter_fkey'
- || ' FOREIGN KEY (event_delimiter)'
- || ' REFERENCES %I.merchant_statistic_counter_event(nevent_serial_id) ON DELETE RESTRICT', s, s);
-
- -- merchant_statistic_interval_counter -> merchant_statistic_interval_meta
- EXECUTE format('ALTER TABLE %I.merchant_statistic_interval_counter'
- || ' ADD CONSTRAINT merchant_statistic_interval_counter_imeta_serial_id_fkey'
- || ' FOREIGN KEY (imeta_serial_id)'
- || ' REFERENCES %I.merchant_statistic_interval_meta(imeta_serial_id) ON DELETE CASCADE', s, s);
-
- -- merchant_template -> merchant_otp_devices
- EXECUTE format('ALTER TABLE %I.merchant_template'
- || ' ADD CONSTRAINT merchant_template_otp_device_id_fkey'
- || ' FOREIGN KEY (otp_device_id)'
- || ' REFERENCES %I.merchant_otp_devices(otp_serial) ON DELETE SET NULL', s, s);
-
- -- merchant_token_family_keys -> merchant_token_families
- EXECUTE format('ALTER TABLE %I.merchant_token_family_keys'
- || ' ADD CONSTRAINT merchant_token_family_keys_token_family_serial_fkey'
- || ' FOREIGN KEY (token_family_serial)'
- || ' REFERENCES %I.merchant_token_families(token_family_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_transfer_signatures -> merchant_expected_transfers
- EXECUTE format('ALTER TABLE %I.merchant_transfer_signatures'
- || ' ADD CONSTRAINT merchant_transfer_signatures_expected_credit_serial_fkey'
- || ' FOREIGN KEY (expected_credit_serial)'
- || ' REFERENCES %I.merchant_expected_transfers(expected_credit_serial) ON DELETE CASCADE', s, s);
-
- -- merchant_transfers -> merchant_accounts
- EXECUTE format('ALTER TABLE %I.merchant_transfers'
- || ' ADD CONSTRAINT merchant_transfers_account_serial_fkey'
- || ' FOREIGN KEY (account_serial)'
- || ' REFERENCES %I.merchant_accounts(account_serial) ON DELETE CASCADE', s, s);
-
- -- -------------------------------------------------------------------
- -- 5. ALTER TABLE for FKs to *global* merchant.* tables.
- -- Right-hand side keeps `merchant.` qualification.
- -- -------------------------------------------------------------------
-
- -- merchant_builtin_unit_overrides -> merchant.merchant_builtin_units
- EXECUTE format('ALTER TABLE %I.merchant_builtin_unit_overrides'
- || ' ADD CONSTRAINT merchant_builtin_unit_overrides_builtin_unit_serial_fkey'
- || ' FOREIGN KEY (builtin_unit_serial)'
- || ' REFERENCES merchant.merchant_builtin_units(unit_serial) ON DELETE CASCADE', s);
-
- -- merchant_deposit_confirmations -> merchant.merchant_exchange_signing_keys
- EXECUTE format('ALTER TABLE %I.merchant_deposit_confirmations'
- || ' ADD CONSTRAINT merchant_deposit_confirmations_signkey_serial_fkey'
- || ' FOREIGN KEY (signkey_serial)'
- || ' REFERENCES merchant.merchant_exchange_signing_keys(signkey_serial) ON DELETE CASCADE', s);
-
- -- merchant_deposits -> merchant.merchant_exchange_signing_keys
- EXECUTE format('ALTER TABLE %I.merchant_deposits'
- || ' ADD CONSTRAINT merchant_deposits_signkey_serial_fkey'
- || ' FOREIGN KEY (signkey_serial)'
- || ' REFERENCES merchant.merchant_exchange_signing_keys(signkey_serial) ON DELETE CASCADE', s);
-
- -- merchant_donau_instances -> merchant.merchant_donau_keys (FK on donau_url)
- EXECUTE format('ALTER TABLE %I.merchant_donau_instances'
- || ' ADD CONSTRAINT merchant_donau_instances_donau_url_fkey'
- || ' FOREIGN KEY (donau_url)'
- || ' REFERENCES merchant.merchant_donau_keys(donau_url) ON DELETE CASCADE', s);
-
- -- merchant_expected_transfers -> merchant.merchant_exchange_signing_keys
- EXECUTE format('ALTER TABLE %I.merchant_expected_transfers'
- || ' ADD CONSTRAINT merchant_expected_transfers_signkey_serial_fkey'
- || ' FOREIGN KEY (signkey_serial)'
- || ' REFERENCES merchant.merchant_exchange_signing_keys(signkey_serial) ON DELETE CASCADE', s);
-
- -- merchant_refund_proofs -> merchant.merchant_exchange_signing_keys
- EXECUTE format('ALTER TABLE %I.merchant_refund_proofs'
- || ' ADD CONSTRAINT merchant_refund_proofs_signkey_serial_fkey'
- || ' FOREIGN KEY (signkey_serial)'
- || ' REFERENCES merchant.merchant_exchange_signing_keys(signkey_serial) ON DELETE CASCADE', s);
-
- -- merchant_transfer_signatures -> merchant.merchant_exchange_signing_keys
- EXECUTE format('ALTER TABLE %I.merchant_transfer_signatures'
- || ' ADD CONSTRAINT merchant_transfer_signatures_signkey_serial_fkey'
- || ' FOREIGN KEY (signkey_serial)'
- || ' REFERENCES merchant.merchant_exchange_signing_keys(signkey_serial) ON DELETE CASCADE', s);
-
- -- =====================================================================
- -- (FKs back to merchant.merchant_instances are intentionally dropped:
- -- the existence of the per-instance schema implies that relationship.)
- -- =====================================================================
diff --git a/src/backenddb/pg_create_instance_schema_triggers.sql.fragment b/src/backenddb/pg_create_instance_schema_triggers.sql.fragment
@@ -1,736 +0,0 @@
--- =====================================================================
--- Per-instance schema constructor: triggers and trigger functions.
---
--- Embedded inside merchant.create_instance_schema(BIGINT); local var
--- `s TEXT` holds the per-instance schema name. All DDL is via
--- EXECUTE format(...) with %I quoting.
---
--- The merchant_serial column has been dropped from every per-instance
--- table; references to it inside the original trigger bodies are
--- removed here. Helper functions (replace_placeholder, ...) and
--- bump_*_stat procedures live in `merchant.` and stay qualified.
--- =====================================================================
-
- -- -------------------------------------------------------------------
- -- 1. CREATE FUNCTION for each per-instance trigger (17 functions).
- -- -------------------------------------------------------------------
-
- -- handle_category_changes
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.handle_category_changes() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- resolved_body TEXT;
- webhook RECORD;
- BEGIN
- IF TG_OP = 'INSERT' THEN
- FOR webhook IN
- SELECT webhook_serial,
- url,
- http_method,
- body_template
- FROM merchant_webhook
- WHERE event_type = 'category_added'
- LOOP
- resolved_body := webhook.body_template;
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'webhook_type',
- 'category_added');
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_serial',
- NEW.category_serial::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_name',
- NEW.category_name);
- INSERT INTO merchant_pending_webhooks
- (webhook_serial, url, http_method, body)
- VALUES
- (webhook.webhook_serial,
- webhook.url,
- webhook.http_method,
- resolved_body);
- END LOOP;
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- IF TG_OP = 'UPDATE' THEN
- FOR webhook IN
- SELECT webhook_serial,
- url,
- http_method,
- body_template
- FROM merchant_webhook
- WHERE event_type = 'category_updated'
- LOOP
- resolved_body := webhook.body_template;
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'webhook_type',
- 'category_updated');
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_serial',
- NEW.category_serial::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_category_name',
- OLD.category_name);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_name',
- NEW.category_name);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_name_i18n',
- NEW.category_name_i18n::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_category_name_i18n',
- OLD.category_name_i18n::TEXT);
- INSERT INTO merchant_pending_webhooks
- (webhook_serial, url, http_method, body)
- VALUES
- (webhook.webhook_serial,
- webhook.url,
- webhook.http_method,
- resolved_body);
- END LOOP;
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- IF TG_OP = 'DELETE' THEN
- FOR webhook IN
- SELECT webhook_serial,
- url,
- http_method,
- body_template
- FROM merchant_webhook
- WHERE event_type = 'category_deleted'
- LOOP
- resolved_body := webhook.body_template;
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'webhook_type',
- 'category_deleted');
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_serial',
- OLD.category_serial::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'category_name',
- OLD.category_name);
- INSERT INTO merchant_pending_webhooks
- (webhook_serial, url, http_method, body)
- VALUES
- (webhook.webhook_serial,
- webhook.url,
- webhook.http_method,
- resolved_body);
- END LOOP;
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- RETURN NULL;
- END;
- $BODY$
- $OUTER$, s);
-
- -- handle_inventory_changes
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.handle_inventory_changes() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- resolved_body TEXT;
- webhook RECORD;
- BEGIN
- IF TG_OP = 'INSERT' THEN
- FOR webhook IN
- SELECT webhook_serial,
- url,
- http_method,
- body_template
- FROM merchant_webhook
- WHERE event_type = 'inventory_added'
- LOOP
- resolved_body := webhook.body_template;
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'webhook_type',
- 'inventory_added');
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'product_serial',
- NEW.product_serial::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'product_id',
- NEW.product_id);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'description',
- NEW.description);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'description_i18n',
- NEW.description_i18n::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'unit',
- NEW.unit);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'image',
- NEW.image);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'taxes',
- NEW.taxes::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'price',
- NEW.price_array[1]::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'unit_price',
- NEW.price_array::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_stock',
- NEW.total_stock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_sold',
- NEW.total_sold::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_lost',
- NEW.total_lost::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'address',
- NEW.address::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'next_restock',
- NEW.next_restock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'minimum_age',
- NEW.minimum_age::TEXT);
- INSERT INTO merchant_pending_webhooks
- (webhook_serial, url, http_method, body)
- VALUES
- (webhook.webhook_serial,
- webhook.url,
- webhook.http_method,
- resolved_body);
- END LOOP;
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- IF TG_OP = 'UPDATE' THEN
- FOR webhook IN
- SELECT webhook_serial,
- url,
- http_method,
- body_template
- FROM merchant_webhook
- WHERE event_type = 'inventory_updated'
- LOOP
- resolved_body := webhook.body_template;
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'webhook_type',
- 'inventory_updated');
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'product_serial',
- NEW.product_serial::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'product_id',
- NEW.product_id);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_description',
- OLD.description);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'description',
- NEW.description);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_description_i18n',
- OLD.description_i18n::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'description_i18n',
- NEW.description_i18n::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_unit',
- OLD.unit);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'unit',
- NEW.unit);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_image',
- OLD.image);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'image',
- NEW.image);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_taxes',
- OLD.taxes::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'taxes',
- NEW.taxes::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_price',
- OLD.price_array[1]::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_unit_price',
- OLD.price_array::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'price',
- NEW.price_array[1]::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'unit_price',
- NEW.price_array::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_total_stock',
- OLD.total_stock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_stock',
- NEW.total_stock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_total_sold',
- OLD.total_sold::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_sold',
- NEW.total_sold::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_total_lost',
- OLD.total_lost::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_lost',
- NEW.total_lost::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_address',
- OLD.address::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'address',
- NEW.address::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_next_restock',
- OLD.next_restock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'next_restock',
- NEW.next_restock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'old_minimum_age',
- OLD.minimum_age::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'minimum_age',
- NEW.minimum_age::TEXT);
- INSERT INTO merchant_pending_webhooks
- (webhook_serial, url, http_method, body)
- VALUES
- (webhook.webhook_serial,
- webhook.url,
- webhook.http_method,
- resolved_body);
- END LOOP;
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- IF TG_OP = 'DELETE' THEN
- FOR webhook IN
- SELECT webhook_serial,
- url,
- http_method,
- body_template
- FROM merchant_webhook
- WHERE event_type = 'inventory_deleted'
- LOOP
- resolved_body := webhook.body_template;
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'webhook_type',
- 'inventory_deleted');
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'product_serial',
- OLD.product_serial::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'product_id',
- OLD.product_id);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'description',
- OLD.description);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'description_i18n',
- OLD.description_i18n::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'unit',
- OLD.unit);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'image',
- OLD.image);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'taxes',
- OLD.taxes::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'price',
- OLD.price_array[1]::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'unit_price',
- OLD.price_array::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_stock',
- OLD.total_stock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_sold',
- OLD.total_sold::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'total_lost',
- OLD.total_lost::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'address',
- OLD.address::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'next_restock',
- OLD.next_restock::TEXT);
- resolved_body := merchant.replace_placeholder(resolved_body,
- 'minimum_age',
- OLD.minimum_age::TEXT);
- INSERT INTO merchant_pending_webhooks
- (webhook_serial, url, http_method, body)
- VALUES
- (webhook.webhook_serial,
- webhook.url,
- webhook.http_method,
- resolved_body);
- END LOOP;
- NOTIFY XXJWF6C1DCS1255RJH7GQ1EK16J8DMRSQ6K9EDKNKCP7HRVWAJPKG;
- END IF;
- RETURN NULL;
- END;
- $BODY$
- $OUTER$, s);
-
- -- merchant_contract_terms_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_contract_terms_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_number_stat
- ('orders-claimed'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,1);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_contract_terms_update_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_contract_terms_update_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- DECLARE
- my_rec RECORD;
- BEGIN
- IF (NEW.wired AND NOT OLD.wired)
- THEN
- CALL merchant_do_bump_number_stat
- ('orders-settled'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,1);
- END IF;
- IF (NEW.paid AND NOT OLD.paid)
- THEN
- CALL merchant_do_bump_number_stat
- ('orders-paid'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,1);
- FOR my_rec IN
- SELECT total_without_fee
- FROM merchant_deposit_confirmations
- WHERE order_serial = NEW.order_serial
- LOOP
- CALL merchant_do_bump_amount_stat
- ('payments-received-after-deposit-fee'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,my_rec.total_without_fee);
- END LOOP;
- FOR my_rec IN
- SELECT deposit_fee
- FROM merchant_deposits
- WHERE deposit_confirmation_serial IN
- (SELECT deposit_confirmation_serial
- FROM merchant_deposit_confirmations
- WHERE order_serial = NEW.order_serial)
- LOOP
- CALL merchant_do_bump_amount_stat
- ('total-deposit-fees-paid'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,my_rec.deposit_fee);
- END LOOP;
- END IF;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_deposits_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_deposits_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_amount_stat
- ('deposits-received'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,NEW.amount_with_fee);
- CALL merchant_do_bump_amount_stat
- ('deposits-fees-paid'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,NEW.deposit_fee);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_expected_transfers_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_expected_transfers_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- IF NEW.wire_fee IS NOT NULL
- THEN
- CALL merchant_do_bump_amount_stat
- ('wire-fees-paid'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,NEW.wire_fee);
- END IF;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_expected_transfers_insert_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_expected_transfers_insert_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- UPDATE merchant_transfers
- SET expected = TRUE
- WHERE wtid = NEW.wtid
- AND exchange_url = NEW.exchange_url
- AND credit_amount = NEW.expected_credit_amount;
- NEW.confirmed = FOUND;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_expected_transfers_update_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_expected_transfers_update_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- IF NEW.wire_fee IS NOT NULL AND OLD.wire_fee IS NULL
- THEN
- CALL merchant_do_bump_amount_stat
- ('wire-fees-paid'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,NEW.wire_fee);
- END IF;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_expected_transfers_update_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_expected_transfers_update_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- UPDATE merchant_transfers
- SET expected = TRUE
- WHERE wtid = NEW.wtid
- AND exchange_url = NEW.exchange_url
- AND credit_amount = NEW.expected_credit_amount
- AND NOT expected;
- NEW.confirmed = NEW.confirmed OR FOUND;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_issued_tokens_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_issued_tokens_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_number_stat
- ('tokens-issued'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,1);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_kyc_insert_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_kyc_insert_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant.merchant_send_kyc_notification(NEW.account_serial,
- NEW.exchange_url);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_kyc_update_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_kyc_update_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- IF (OLD.kyc_ok
- ,OLD.last_rule_gen
- ,OLD.aml_review
- ,OLD.jaccount_limits)
- IS DISTINCT FROM
- (NEW.kyc_ok
- ,NEW.last_rule_gen
- ,NEW.aml_review
- ,NEW.jaccount_limits)
- THEN
- CALL merchant.merchant_send_kyc_notification(NEW.account_serial,
- NEW.exchange_url);
- END IF;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_orders_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_orders_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_number_stat
- ('orders-created'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,1);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_refunds_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_refunds_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_amount_stat
- ('refunds-granted'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,NEW.refund_amount);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_transfer_signatures_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_transfer_signatures_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_amount_stat
- ('wire-fees-paid'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,NEW.wire_fee);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_transfers_insert_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_transfers_insert_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- UPDATE merchant_expected_transfers
- SET confirmed = TRUE
- WHERE wtid = NEW.wtid
- AND exchange_url = NEW.exchange_url
- AND expected_credit_amount = NEW.credit_amount;
- NEW.expected = FOUND;
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- merchant_used_tokens_insert_statistics_trigger
- EXECUTE format($OUTER$
- CREATE FUNCTION %I.merchant_used_tokens_insert_statistics_trigger() RETURNS trigger
- LANGUAGE plpgsql
- AS $BODY$
- BEGIN
- CALL merchant_do_bump_number_stat
- ('tokens-used'
- ,CURRENT_TIMESTAMP(0)::TIMESTAMP
- ,1);
- RETURN NEW;
- END $BODY$
- $OUTER$, s);
-
- -- -------------------------------------------------------------------
- -- 2. CREATE TRIGGER attachments (16 triggers).
- -- -------------------------------------------------------------------
-
- EXECUTE format('CREATE TRIGGER merchant_contract_terms_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_contract_terms'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_contract_terms_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_contract_terms_on_update_statistic'
- || ' AFTER UPDATE ON %I.merchant_contract_terms'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_contract_terms_update_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_deposits_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_deposits'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_deposits_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_insert'
- || ' BEFORE INSERT ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_insert_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_update'
- || ' BEFORE UPDATE ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_update_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_update_statistic'
- || ' AFTER INSERT ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_update_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_issued_tokens_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_issued_tokens'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_issued_tokens_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_kyc_on_insert'
- || ' AFTER INSERT ON %I.merchant_kyc'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_kyc_insert_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_kyc_on_update'
- || ' AFTER UPDATE ON %I.merchant_kyc'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_kyc_update_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_orders_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_orders'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_orders_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_refunds_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_refunds'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_refunds_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_transfers_on_insert'
- || ' BEFORE INSERT ON %I.merchant_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_transfers_insert_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER merchant_used_tokens_on_insert_statistic'
- || ' AFTER INSERT ON %I.merchant_used_tokens'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_used_tokens_insert_statistics_trigger()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER trigger_category_changes'
- || ' AFTER INSERT OR DELETE OR UPDATE ON %I.merchant_categories'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.handle_category_changes()',
- s, s);
-
- EXECUTE format('CREATE TRIGGER trigger_inventory_changes'
- || ' AFTER INSERT OR DELETE OR UPDATE ON %I.merchant_inventory'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.handle_inventory_changes()',
- s, s);
diff --git a/src/backenddb/pg_create_instance_trigger.sql b/src/backenddb/pg_create_instance_trigger.sql
@@ -1,57 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.merchant_instances_after_insert_trigger() CASCADE;
-CREATE FUNCTION merchant.merchant_instances_after_insert_trigger()
- RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
- PERFORM merchant.create_instance_schema(NEW.merchant_serial);
- RETURN NULL;
-END $$;
-COMMENT ON FUNCTION merchant.merchant_instances_after_insert_trigger()
- IS 'Builds the per-instance schema merchant_instance_<merchant_serial>'
- ' for the newly inserted row.';
-
-DROP TRIGGER IF EXISTS merchant_instances_on_insert
- ON merchant.merchant_instances;
-CREATE TRIGGER merchant_instances_on_insert
- AFTER INSERT ON merchant.merchant_instances
- FOR EACH ROW
- EXECUTE FUNCTION merchant.merchant_instances_after_insert_trigger();
-
-
-DROP FUNCTION IF EXISTS merchant.merchant_instances_after_delete_trigger() CASCADE;
-CREATE FUNCTION merchant.merchant_instances_after_delete_trigger()
- RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
- EXECUTE format('DROP SCHEMA IF EXISTS %I CASCADE',
- 'merchant_instance_' || OLD.merchant_serial::TEXT);
- RETURN NULL;
-END $$;
-COMMENT ON FUNCTION merchant.merchant_instances_after_delete_trigger()
- IS 'Drops the per-instance schema merchant_instance_<merchant_serial>'
- ' when its row in merchant.merchant_instances is removed.';
-
-DROP TRIGGER IF EXISTS merchant_instances_on_delete
- ON merchant.merchant_instances;
-CREATE TRIGGER merchant_instances_on_delete
- AFTER DELETE ON merchant.merchant_instances
- FOR EACH ROW
- EXECUTE FUNCTION merchant.merchant_instances_after_delete_trigger();
diff --git a/src/backenddb/pg_expire_locks.sql b/src/backenddb/pg_expire_locks.sql
@@ -1,54 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.expire_locks(INT8);
-CREATE FUNCTION merchant.expire_locks(IN p_now INT8)
-RETURNS INT8
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- total INT8 := 0;
- affected INT8;
-BEGIN
- FOR rec IN
- SELECT merchant_serial FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- EXECUTE format('DELETE FROM %I.merchant_inventory_locks'
- ' WHERE expiration < $1', s) USING p_now;
- GET DIAGNOSTICS affected = ROW_COUNT;
- total := total + affected;
-
- EXECUTE format('DELETE FROM %I.merchant_orders'
- ' WHERE pay_deadline < $1', s) USING p_now;
- GET DIAGNOSTICS affected = ROW_COUNT;
- total := total + affected;
-
- EXECUTE format('DELETE FROM %I.merchant_contract_terms'
- ' WHERE NOT paid'
- ' AND pay_deadline < $1', s) USING p_now;
- GET DIAGNOSTICS affected = ROW_COUNT;
- total := total + affected;
- END LOOP;
- RETURN total;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.expire_locks(INT8)
- IS 'Loops over all instance schemas and DELETEs expired inventory locks,'
- ' unpaid orders past their pay_deadline, and unpaid contracts past their'
- ' pay_deadline. Returns the total number of rows deleted.';
diff --git a/src/backenddb/pg_lookup_instances.sql b/src/backenddb/pg_lookup_instances.sql
@@ -1,95 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.lookup_instances(BOOLEAN, TEXT);
-CREATE FUNCTION merchant.lookup_instances(
- IN p_active_only BOOLEAN,
- IN p_merchant_id TEXT)
-RETURNS TABLE(
- out_merchant_serial BIGINT,
- out_merchant_pub BYTEA,
- out_auth_hash BYTEA,
- out_auth_salt BYTEA,
- out_merchant_priv BYTEA,
- out_merchant_id TEXT,
- out_merchant_name TEXT,
- out_address JSONB,
- out_jurisdiction JSONB,
- out_use_stefan BOOLEAN,
- out_phone_validated BOOLEAN,
- out_email_validated BOOLEAN,
- out_default_wire_transfer_delay INT8,
- out_default_pay_delay INT8,
- out_default_refund_delay INT8,
- out_website TEXT,
- out_email TEXT,
- out_phone_number TEXT,
- out_logo BYTEA,
- out_default_wire_transfer_rounding_interval time_rounder_interval)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- pkey BYTEA;
-BEGIN
- FOR rec IN
- SELECT mi.*
- FROM merchant.merchant_instances mi
- WHERE p_merchant_id IS NULL
- OR mi.merchant_id = p_merchant_id
- LOOP
- pkey := NULL;
- BEGIN
- EXECUTE format('SELECT merchant_priv FROM %I.merchant_keys',
- 'merchant_instance_' || rec.merchant_serial::TEXT)
- INTO pkey;
- EXCEPTION
- WHEN undefined_table THEN
- pkey := NULL;
- END;
- IF p_active_only AND pkey IS NULL THEN
- CONTINUE;
- END IF;
- out_merchant_serial := rec.merchant_serial;
- out_merchant_pub := rec.merchant_pub;
- out_auth_hash := rec.auth_hash;
- out_auth_salt := rec.auth_salt;
- out_merchant_priv := pkey;
- out_merchant_id := rec.merchant_id;
- out_merchant_name := rec.merchant_name;
- out_address := rec.address;
- out_jurisdiction := rec.jurisdiction;
- out_use_stefan := rec.use_stefan;
- out_phone_validated := rec.phone_validated;
- out_email_validated := rec.email_validated;
- out_default_wire_transfer_delay := rec.default_wire_transfer_delay;
- out_default_pay_delay := rec.default_pay_delay;
- out_default_refund_delay := rec.default_refund_delay;
- out_website := rec.website;
- out_email := rec.email;
- out_phone_number := rec.phone_number;
- out_logo := rec.logo;
- out_default_wire_transfer_rounding_interval :=
- rec.default_wire_transfer_rounding_interval;
- RETURN NEXT;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.lookup_instances(BOOLEAN, TEXT)
- IS 'Returns one row per matching instance, joining merchant.merchant_instances'
- ' with the per-instance merchant_keys table (merchant_priv NULL if absent).'
- ' If p_active_only is true, instances without a private key are skipped.'
- ' If p_merchant_id is non-NULL, only the matching instance is returned.';
diff --git a/src/backenddb/pg_lookup_pending_deposits.sql b/src/backenddb/pg_lookup_pending_deposits.sql
@@ -1,230 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.lookup_pending_deposits(TEXT, INT8, INT8, BOOLEAN);
-CREATE FUNCTION merchant.lookup_pending_deposits(
- IN p_exchange_url TEXT,
- IN p_now INT8,
- IN p_limit INT8,
- IN p_allow_future BOOLEAN)
-RETURNS TABLE(
- out_deposit_serial INT8,
- out_h_contract_terms BYTEA,
- out_merchant_priv BYTEA,
- out_merchant_id TEXT,
- out_wire_transfer_deadline INT8,
- out_retry_time INT8,
- out_h_wire BYTEA,
- out_amount_with_fee taler_amount_currency,
- out_deposit_fee taler_amount_currency,
- out_coin_pub BYTEA)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- pkey BYTEA;
- inner_rec RECORD;
- remaining INT8 := p_limit;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_id FROM merchant.merchant_instances
- LOOP
- EXIT WHEN remaining <= 0;
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- pkey := NULL;
- BEGIN
- EXECUTE format('SELECT merchant_priv FROM %I.merchant_keys', s)
- INTO pkey;
- EXCEPTION
- WHEN undefined_table THEN
- pkey := NULL;
- END;
- BEGIN
- FOR inner_rec IN
- EXECUTE format(
- 'SELECT'
- ' md.deposit_serial AS deposit_serial'
- ' ,mct.h_contract_terms AS h_contract_terms'
- ' ,mdc.wire_transfer_deadline AS wire_transfer_deadline'
- ' ,md.settlement_retry_time AS retry_time'
- ' ,ma.h_wire AS h_wire'
- ' ,md.amount_with_fee AS amount_with_fee'
- ' ,md.deposit_fee AS deposit_fee'
- ' ,md.coin_pub AS coin_pub'
- ' FROM %I.merchant_deposits md'
- ' JOIN %I.merchant_deposit_confirmations mdc'
- ' USING (deposit_confirmation_serial)'
- ' JOIN %I.merchant_contract_terms mct'
- ' ON (mct.order_serial=mdc.order_serial)'
- ' JOIN %I.merchant_accounts ma'
- ' ON (mdc.account_serial=ma.account_serial)'
- ' LEFT JOIN %I.merchant_kyc kyc'
- ' ON (mdc.account_serial=kyc.account_serial)'
- ' WHERE (mdc.exchange_url=$1)'
- ' AND md.settlement_retry_needed'
- ' AND ($4 OR (md.settlement_retry_time < $2))'
- ' AND ( (kyc.kyc_ok IS NULL) OR kyc.kyc_ok)'
- ' ORDER BY md.settlement_retry_time ASC'
- ' LIMIT $3',
- s, s, s, s, s)
- USING p_exchange_url, p_now, remaining, p_allow_future
- LOOP
- out_deposit_serial := inner_rec.deposit_serial;
- out_h_contract_terms := inner_rec.h_contract_terms;
- out_merchant_priv := pkey;
- out_merchant_id := rec.merchant_id;
- out_wire_transfer_deadline := inner_rec.wire_transfer_deadline;
- out_retry_time := inner_rec.retry_time;
- out_h_wire := inner_rec.h_wire;
- out_amount_with_fee := inner_rec.amount_with_fee;
- out_deposit_fee := inner_rec.deposit_fee;
- out_coin_pub := inner_rec.coin_pub;
- remaining := remaining - 1;
- RETURN NEXT;
- EXIT WHEN remaining <= 0;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.lookup_pending_deposits(TEXT, INT8, INT8, BOOLEAN)
- IS 'Returns up to p_limit pending-settlement deposit rows for the given exchange'
- ' across all instance schemas, joined with the per-instance merchant_keys.';
-
-
-DROP FUNCTION IF EXISTS merchant.lookup_reports_pending();
-CREATE FUNCTION merchant.lookup_reports_pending()
-RETURNS TABLE(
- out_merchant_id TEXT,
- out_report_serial INT8,
- out_report_program_section TEXT,
- out_report_description TEXT,
- out_mime_type TEXT,
- out_report_token BYTEA,
- out_target_address TEXT,
- out_frequency INT8,
- out_frequency_shift INT8,
- out_next_transmission INT8,
- out_one_shot_hidden BOOLEAN)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
- found BOOLEAN := FALSE;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_id FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- EXECUTE format(
- 'SELECT'
- ' report_serial AS rs'
- ' ,report_program_section AS rps'
- ' ,report_description AS rd'
- ' ,mime_type AS mt'
- ' ,report_token AS rt'
- ' ,target_address AS ta'
- ' ,frequency AS f'
- ' ,frequency_shift AS fs'
- ' ,next_transmission AS nt'
- ' ,one_shot_hidden AS osh'
- ' FROM %I.merchant_reports'
- ' ORDER BY next_transmission ASC LIMIT 1', s)
- INTO inner_rec;
- IF inner_rec IS NULL THEN
- CONTINUE;
- END IF;
- IF (NOT found) OR (inner_rec.nt < out_next_transmission) THEN
- out_merchant_id := rec.merchant_id;
- out_report_serial := inner_rec.rs;
- out_report_program_section := inner_rec.rps;
- out_report_description := inner_rec.rd;
- out_mime_type := inner_rec.mt;
- out_report_token := inner_rec.rt;
- out_target_address := inner_rec.ta;
- out_frequency := inner_rec.f;
- out_frequency_shift := inner_rec.fs;
- out_next_transmission := inner_rec.nt;
- out_one_shot_hidden := inner_rec.osh;
- found := TRUE;
- END IF;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
- IF found THEN
- RETURN NEXT;
- END IF;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.lookup_reports_pending()
- IS 'Returns the single next-due report (smallest next_transmission)'
- ' across all instance schemas, or no row if no reports exist.';
-
-
-DROP FUNCTION IF EXISTS merchant.check_report(INT8, BYTEA, TEXT);
-CREATE FUNCTION merchant.check_report(
- IN p_report_id INT8,
- IN p_report_token BYTEA,
- IN p_mime_type TEXT)
-RETURNS TABLE(
- out_merchant_id TEXT,
- out_data_source TEXT)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_id FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- EXECUTE format(
- 'SELECT data_source AS ds'
- ' FROM %I.merchant_reports'
- ' WHERE report_serial=$1'
- ' AND report_token=$2'
- ' AND mime_type=$3', s)
- USING p_report_id, p_report_token, p_mime_type
- INTO inner_rec;
- IF inner_rec IS NOT NULL THEN
- out_merchant_id := rec.merchant_id;
- out_data_source := inner_rec.ds;
- RETURN NEXT;
- RETURN;
- END IF;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.check_report(INT8, BYTEA, TEXT)
- IS 'Searches all instance schemas for a report matching the given'
- ' (report_serial, report_token, mime_type). Returns at most one row'
- ' (the first matching instance encountered).';
diff --git a/src/backenddb/pg_lookup_pending_webhooks.sql b/src/backenddb/pg_lookup_pending_webhooks.sql
@@ -1,133 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.lookup_pending_webhooks(INT8);
-CREATE FUNCTION merchant.lookup_pending_webhooks(IN p_now INT8)
-RETURNS TABLE(
- out_webhook_pending_serial INT8,
- out_next_attempt INT8,
- out_retries INT4,
- out_url TEXT,
- out_http_method TEXT,
- out_header TEXT,
- out_body TEXT)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
-BEGIN
- FOR rec IN
- SELECT merchant_serial FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- FOR inner_rec IN
- EXECUTE format('SELECT'
- ' webhook_pending_serial AS wps'
- ',next_attempt AS na'
- ',retries AS r'
- ',url AS u'
- ',http_method AS hm'
- ',header AS h'
- ',body AS b'
- ' FROM %I.merchant_pending_webhooks'
- ' WHERE next_attempt <= $1'
- ' ORDER BY next_attempt ASC', s)
- USING p_now
- LOOP
- out_webhook_pending_serial := inner_rec.wps;
- out_next_attempt := inner_rec.na;
- out_retries := inner_rec.r;
- out_url := inner_rec.u;
- out_http_method := inner_rec.hm;
- out_header := inner_rec.h;
- out_body := inner_rec.b;
- RETURN NEXT;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.lookup_pending_webhooks(INT8)
- IS 'Returns one row per pending webhook (next_attempt <= p_now) across all'
- ' instance schemas, ordered per-instance by next_attempt ASC.';
-
-
-DROP FUNCTION IF EXISTS merchant.lookup_future_webhook();
-CREATE FUNCTION merchant.lookup_future_webhook()
-RETURNS TABLE(
- out_webhook_pending_serial INT8,
- out_next_attempt INT8,
- out_retries INT4,
- out_url TEXT,
- out_http_method TEXT,
- out_header TEXT,
- out_body TEXT)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- best RECORD;
- found BOOLEAN := FALSE;
-BEGIN
- best := NULL;
- FOR rec IN
- SELECT merchant_serial FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- EXECUTE format('SELECT'
- ' webhook_pending_serial AS wps'
- ',next_attempt AS na'
- ',retries AS r'
- ',url AS u'
- ',http_method AS hm'
- ',header AS h'
- ',body AS b'
- ' FROM %I.merchant_pending_webhooks'
- ' ORDER BY next_attempt ASC LIMIT 1', s)
- INTO best;
- IF best IS NOT NULL
- AND ((NOT found)
- OR (best.na < out_next_attempt)) THEN
- out_webhook_pending_serial := best.wps;
- out_next_attempt := best.na;
- out_retries := best.r;
- out_url := best.u;
- out_http_method := best.hm;
- out_header := best.h;
- out_body := best.b;
- found := TRUE;
- END IF;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
- IF found THEN
- RETURN NEXT;
- END IF;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.lookup_future_webhook()
- IS 'Returns the single soonest-due pending webhook across all instances,'
- ' or no row if no instance has any pending webhook.';
diff --git a/src/backenddb/pg_select_accounts.sql b/src/backenddb/pg_select_accounts.sql
@@ -1,84 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.select_accounts(TEXT);
-CREATE FUNCTION merchant.select_accounts(
- IN p_merchant_id TEXT)
-RETURNS TABLE(
- out_merchant_id TEXT,
- out_merchant_priv BYTEA,
- out_h_wire BYTEA,
- out_salt BYTEA,
- out_payto_uri TEXT,
- out_credit_facade_url TEXT,
- out_credit_facade_credentials JSONB,
- out_extra_wire_subject_metadata TEXT,
- out_active BOOLEAN)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- pkey BYTEA;
-BEGIN
- FOR rec IN
- SELECT mi.merchant_serial, mi.merchant_id
- FROM merchant.merchant_instances mi
- WHERE p_merchant_id IS NULL
- OR mi.merchant_id = p_merchant_id
- LOOP
- pkey := NULL;
- BEGIN
- EXECUTE format('SELECT merchant_priv FROM %I.merchant_keys',
- 'merchant_instance_' || rec.merchant_serial::TEXT)
- INTO pkey;
- EXCEPTION
- WHEN undefined_table THEN
- pkey := NULL;
- END;
- BEGIN
- FOR out_h_wire,
- out_salt,
- out_payto_uri,
- out_credit_facade_url,
- out_credit_facade_credentials,
- out_extra_wire_subject_metadata,
- out_active
- IN EXECUTE format('SELECT'
- ' h_wire'
- ',salt'
- ',payto_uri'
- ',credit_facade_url'
- ',credit_facade_credentials'
- ',extra_wire_subject_metadata'
- ',active'
- ' FROM %I.merchant_accounts',
- 'merchant_instance_' || rec.merchant_serial::TEXT)
- LOOP
- out_merchant_id := rec.merchant_id;
- out_merchant_priv := pkey;
- RETURN NEXT;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.select_accounts(TEXT)
- IS 'Returns one row per merchant_account across all (or one) instance schemas,'
- ' joined with the per-instance merchant_keys.merchant_priv (NULL if absent).'
- ' If p_merchant_id is non-NULL, only that instance is scanned.';
diff --git a/src/backenddb/pg_select_all_donau_instances.sql b/src/backenddb/pg_select_all_donau_instances.sql
@@ -1,116 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.select_all_donau_instances();
-CREATE FUNCTION merchant.select_all_donau_instances()
-RETURNS TABLE(
- out_donau_instances_serial INT8,
- out_donau_url TEXT,
- out_charity_name TEXT,
- out_charity_pub_key BYTEA,
- out_charity_id INT8,
- out_charity_max_per_year taler_amount_currency,
- out_charity_receipts_to_date taler_amount_currency,
- out_current_year INT8,
- out_keys_json JSONB)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_pub FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- FOR inner_rec IN
- EXECUTE format(
- 'SELECT'
- ' di.donau_instances_serial AS dis'
- ' ,di.donau_url AS du'
- ' ,di.charity_name AS cn'
- ' ,di.charity_id AS ci'
- ' ,di.charity_max_per_year AS cmp'
- ' ,di.charity_receipts_to_date AS crt'
- ' ,di.current_year AS cy'
- ' ,dk.keys_json AS kj'
- ' FROM %I.merchant_donau_instances di'
- ' LEFT JOIN merchant.merchant_donau_keys dk'
- ' ON di.donau_url = dk.donau_url', s)
- LOOP
- out_donau_instances_serial := inner_rec.dis;
- out_donau_url := inner_rec.du;
- out_charity_name := inner_rec.cn;
- out_charity_pub_key := rec.merchant_pub;
- out_charity_id := inner_rec.ci;
- out_charity_max_per_year := inner_rec.cmp;
- out_charity_receipts_to_date := inner_rec.crt;
- out_current_year := inner_rec.cy;
- out_keys_json := inner_rec.kj;
- RETURN NEXT;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.select_all_donau_instances()
- IS 'Returns all donau-instance configurations across every per-instance'
- ' schema, joined with merchant.merchant_donau_keys for the keys json'
- ' and with merchant.merchant_instances for the charity public key.';
-
-
-DROP FUNCTION IF EXISTS merchant.select_donau_instances_filtered(TEXT);
-CREATE FUNCTION merchant.select_donau_instances_filtered(IN p_currency TEXT)
-RETURNS TABLE(
- out_donau_url TEXT)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
-BEGIN
- FOR rec IN
- SELECT merchant_serial FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- FOR inner_rec IN
- EXECUTE format(
- 'SELECT donau_url AS du'
- ' FROM %I.merchant_donau_instances'
- ' WHERE (charity_max_per_year).curr = $1', s)
- USING p_currency
- LOOP
- out_donau_url := inner_rec.du;
- RETURN NEXT;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.select_donau_instances_filtered(TEXT)
- IS 'Returns the donau_url of every donau-instance configuration whose'
- ' charity_max_per_year currency matches p_currency, scanning across'
- ' all per-instance schemas.';
diff --git a/src/backenddb/pg_select_open_transfers.sql b/src/backenddb/pg_select_open_transfers.sql
@@ -1,124 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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/>
---
-
-DROP FUNCTION IF EXISTS merchant.select_open_transfers(INT8);
-CREATE FUNCTION merchant.select_open_transfers(IN p_limit INT8)
-RETURNS TABLE(
- out_expected_credit_serial INT8,
- out_instance_id TEXT,
- out_exchange_url TEXT,
- out_payto_uri TEXT,
- out_wtid BYTEA,
- out_retry_time INT8)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
- remaining INT8 := p_limit;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_id FROM merchant.merchant_instances
- LOOP
- EXIT WHEN remaining <= 0;
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- FOR inner_rec IN
- EXECUTE format(
- 'SELECT'
- ' met.expected_credit_serial AS ecs'
- ' ,met.exchange_url AS exu'
- ' ,ma.payto_uri AS pu'
- ' ,met.wtid AS wt'
- ' ,met.retry_time AS rt'
- ' FROM %I.merchant_expected_transfers met'
- ' JOIN %I.merchant_accounts ma USING (account_serial)'
- ' WHERE retry_needed'
- ' ORDER BY retry_time ASC'
- ' LIMIT $1', s, s)
- USING remaining
- LOOP
- out_expected_credit_serial := inner_rec.ecs;
- out_instance_id := rec.merchant_id;
- out_exchange_url := inner_rec.exu;
- out_payto_uri := inner_rec.pu;
- out_wtid := inner_rec.wt;
- out_retry_time := inner_rec.rt;
- remaining := remaining - 1;
- RETURN NEXT;
- EXIT WHEN remaining <= 0;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.select_open_transfers(INT8)
- IS 'Returns up to p_limit retry-needed expected_transfer rows across all'
- ' instance schemas, joined with the per-instance merchant_accounts.';
-
-
-DROP FUNCTION IF EXISTS merchant.select_wirewatch_accounts();
-CREATE FUNCTION merchant.select_wirewatch_accounts()
-RETURNS TABLE(
- out_merchant_id TEXT,
- out_payto_uri TEXT,
- out_credit_facade_url TEXT,
- out_credit_facade_credentials JSONB,
- out_last_bank_serial INT8)
-LANGUAGE plpgsql
-AS $FN$
-DECLARE
- rec RECORD;
- s TEXT;
- inner_rec RECORD;
-BEGIN
- FOR rec IN
- SELECT merchant_serial, merchant_id FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- FOR inner_rec IN
- EXECUTE format(
- 'SELECT'
- ' payto_uri AS pu'
- ' ,credit_facade_url AS cfu'
- ' ,credit_facade_credentials AS cfc'
- ' ,last_bank_serial AS lbs'
- ' FROM %I.merchant_accounts'
- ' WHERE active'
- ' AND credit_facade_url IS NOT NULL', s)
- LOOP
- out_merchant_id := rec.merchant_id;
- out_payto_uri := inner_rec.pu;
- out_credit_facade_url := inner_rec.cfu;
- out_credit_facade_credentials := inner_rec.cfc;
- out_last_bank_serial := inner_rec.lbs;
- RETURN NEXT;
- END LOOP;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- END;
- END LOOP;
-END
-$FN$;
-COMMENT ON FUNCTION merchant.select_wirewatch_accounts()
- IS 'Returns one row per active credit-facade-enabled merchant_account'
- ' across all instance schemas.';
diff --git a/src/backenddb/purge_instance.c b/src/backenddb/purge_instance.c
@@ -41,25 +41,8 @@ TALER_MERCHANTDB_purge_instance (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_end
};
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("SET search_path TO merchant"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
check_connection (pg);
- /* The AFTER DELETE trigger will DROP the per-instance schema. Reset
- search_path off it first so subsequent queries on this connection
- don't reference the about-to-be-dropped schema. */
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_free (pg->current_merchant_id);
- pg->current_merchant_id = NULL;
- pg->current_merchant_serial = 0;
PREPARE (pg,
"purge_instance",
"DELETE FROM merchant_instances"
diff --git a/src/backenddb/refund_coin.c b/src/backenddb/refund_coin.c
@@ -34,44 +34,43 @@ TALER_MERCHANTDB_refund_coin (struct TALER_MERCHANTDB_PostgresContext *pg,
const char *reason)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_timestamp (&refund_timestamp),
GNUNET_PQ_query_param_auto_from_type (coin_pub),
GNUNET_PQ_query_param_string (reason),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- PREPARE_INSTANCE (pg,
- stmt,
- "refund_coin",
- "INSERT INTO merchant_refunds"
- "(order_serial"
- ",rtransaction_id"
- ",refund_timestamp"
- ",coin_pub"
- ",reason"
- ",refund_amount"
- ") "
- "SELECT "
- " dcon.order_serial"
- ",0" /* rtransaction_id always 0 for /abort */
- ",$2"
- ",dep.coin_pub"
- ",$4"
- ",dep.amount_with_fee"
- " FROM merchant_deposits dep"
- " JOIN merchant_deposit_confirmations dcon"
- " USING (deposit_confirmation_serial)"
- " WHERE dep.coin_pub=$3"
- " AND dcon.order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$1)");
+ PREPARE (pg,
+ "refund_coin",
+ "INSERT INTO merchant_refunds"
+ "(order_serial"
+ ",rtransaction_id"
+ ",refund_timestamp"
+ ",coin_pub"
+ ",reason"
+ ",refund_amount"
+ ") "
+ "SELECT "
+ " dcon.order_serial"
+ ",0" /* rtransaction_id always 0 for /abort */
+ ",$3"
+ ",dep.coin_pub"
+ ",$5"
+ ",dep.amount_with_fee"
+ " FROM merchant_deposits dep"
+ " JOIN merchant_deposit_confirmations dcon"
+ " USING (deposit_confirmation_serial)"
+ " WHERE dep.coin_pub=$4"
+ " AND dcon.order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "refund_coin",
params);
}
diff --git a/src/backenddb/select_account.c b/src/backenddb/select_account.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_select_account (struct TALER_MERCHANTDB_PostgresContext *pg,
struct TALER_MERCHANTDB_AccountDetails *ad)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_end
};
@@ -57,28 +58,27 @@ TALER_MERCHANTDB_select_account (struct TALER_MERCHANTDB_PostgresContext *pg,
NULL),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
ad->h_wire = *h_wire;
ad->instance_id = id;
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_account",
- "SELECT"
- " salt"
- ",payto_uri"
- ",credit_facade_url"
- ",credit_facade_credentials::TEXT"
- ",active"
- ",extra_wire_subject_metadata"
- " FROM merchant_accounts"
- " WHERE h_wire=$1;");
+ PREPARE (pg,
+ "select_account",
+ "SELECT"
+ " salt"
+ ",payto_uri"
+ ",credit_facade_url"
+ ",credit_facade_credentials::TEXT"
+ ",active"
+ ",extra_wire_subject_metadata"
+ " FROM merchant_accounts"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1) "
+ " AND (h_wire=$2);");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "select_account",
params,
rs);
}
diff --git a/src/backenddb/select_account_by_uri.c b/src/backenddb/select_account_by_uri.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_select_account_by_uri (struct TALER_MERCHANTDB_PostgresContext
struct TALER_MERCHANTDB_AccountDetails *ad)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_string (payto_uri.full_payto),
GNUNET_PQ_query_param_end
};
@@ -53,30 +54,29 @@ TALER_MERCHANTDB_select_account_by_uri (struct TALER_MERCHANTDB_PostgresContext
&ad->active),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
ad->credit_facade_url = NULL;
ad->credit_facade_credentials = NULL;
ad->payto_uri.full_payto
= GNUNET_strdup (payto_uri.full_payto);
ad->instance_id = id;
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_account_by_uri",
- "SELECT"
- " salt"
- ",h_wire"
- ",credit_facade_url"
- ",credit_facade_credentials::TEXT"
- ",active"
- " FROM merchant_accounts"
- " WHERE payto_uri = $1");
+ PREPARE (pg,
+ "select_account_by_uri",
+ "SELECT"
+ " salt"
+ ",h_wire"
+ ",credit_facade_url"
+ ",credit_facade_credentials::TEXT"
+ ",active"
+ " FROM merchant_accounts"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND payto_uri = $2");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "select_account_by_uri",
params,
rs);
}
diff --git a/src/backenddb/select_accounts.c b/src/backenddb/select_accounts.c
@@ -80,30 +80,30 @@ select_account_cb (void *cls,
struct TALER_MerchantPrivateKeyP merchant_priv;
bool no_priv;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("out_h_wire",
+ GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&acc.h_wire),
- GNUNET_PQ_result_spec_auto_from_type ("out_salt",
+ GNUNET_PQ_result_spec_auto_from_type ("salt",
&acc.salt),
- GNUNET_PQ_result_spec_string ("out_payto_uri",
+ GNUNET_PQ_result_spec_string ("payto_uri",
&payto.full_payto),
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("merchant_id",
&instance_id),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_credit_facade_url",
+ GNUNET_PQ_result_spec_string ("credit_facade_url",
&facade_url),
NULL),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("out_extra_wire_subject_metadata",
+ GNUNET_PQ_result_spec_string ("extra_wire_subject_metadata",
&extra_wire_subject_metadata),
NULL),
GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("out_credit_facade_credentials",
+ TALER_PQ_result_spec_json ("credit_facade_credentials",
&credential),
NULL),
- GNUNET_PQ_result_spec_bool ("out_active",
+ GNUNET_PQ_result_spec_bool ("active",
&acc.active),
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("out_merchant_priv",
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
&merchant_priv),
&no_priv),
GNUNET_PQ_result_spec_end
@@ -156,16 +156,26 @@ TALER_MERCHANTDB_select_accounts (
PREPARE (pg,
"select_accounts",
"SELECT"
- " out_merchant_id"
- " ,out_merchant_priv"
- " ,out_h_wire"
- " ,out_salt"
- " ,out_payto_uri"
- " ,out_credit_facade_url"
- " ,out_credit_facade_credentials::TEXT"
- " ,out_extra_wire_subject_metadata"
- " ,out_active"
- " FROM merchant.select_accounts($1)");
+ " ma.h_wire"
+ ",ma.salt"
+ ",ma.payto_uri"
+ ",ma.credit_facade_url"
+ ",ma.credit_facade_credentials::TEXT"
+ ",ma.extra_wire_subject_metadata"
+ ",ma.active"
+ ",mk.merchant_priv"
+ ",mi.merchant_id"
+ " FROM merchant_accounts ma"
+ " JOIN merchant_instances mi"
+ " ON (mi.merchant_serial=ma.merchant_serial)"
+ " LEFT JOIN merchant_keys mk"
+ " ON (mk.merchant_serial=ma.merchant_serial)"
+ " WHERE"
+ " ($1::TEXT IS NULL) OR"
+ " (ma.merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1));");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"select_accounts",
params,
diff --git a/src/backenddb/select_all_donau_instances.c b/src/backenddb/select_all_donau_instances.c
@@ -76,24 +76,24 @@ select_donau_instance_cb (void *cls,
int64_t current_year;
json_t *donau_keys_json = NULL;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("out_donau_instances_serial",
+ GNUNET_PQ_result_spec_uint64 ("donau_instances_serial",
&donau_instance_serial),
- GNUNET_PQ_result_spec_string ("out_donau_url",
+ GNUNET_PQ_result_spec_string ("donau_url",
&donau_url),
- GNUNET_PQ_result_spec_string ("out_charity_name",
+ GNUNET_PQ_result_spec_string ("charity_name",
&charity_name),
- GNUNET_PQ_result_spec_auto_from_type ("out_charity_pub_key",
+ GNUNET_PQ_result_spec_auto_from_type ("charity_pub_key",
&charity_pub_key),
- GNUNET_PQ_result_spec_uint64 ("out_charity_id",
+ GNUNET_PQ_result_spec_uint64 ("charity_id",
&charity_id),
- TALER_PQ_result_spec_amount_with_currency ("out_charity_max_per_year",
+ TALER_PQ_result_spec_amount_with_currency ("charity_max_per_year",
&charity_max_per_year),
- TALER_PQ_result_spec_amount_with_currency ("out_charity_receipts_to_date",
+ TALER_PQ_result_spec_amount_with_currency ("charity_receipts_to_date",
&charity_receipts_to_date),
- GNUNET_PQ_result_spec_int64 ("out_current_year",
+ GNUNET_PQ_result_spec_int64 ("current_year",
¤t_year),
GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("out_keys_json",
+ TALER_PQ_result_spec_json ("keys_json",
&donau_keys_json),
NULL),
GNUNET_PQ_result_spec_end
@@ -144,16 +144,20 @@ TALER_MERCHANTDB_select_all_donau_instances (
PREPARE (pg,
"select_all_donau_instances",
"SELECT"
- " out_donau_instances_serial"
- " ,out_donau_url"
- " ,out_charity_name"
- " ,out_charity_pub_key"
- " ,out_charity_id"
- " ,out_charity_max_per_year"
- " ,out_charity_receipts_to_date"
- " ,out_current_year"
- " ,out_keys_json::TEXT"
- " FROM merchant.select_all_donau_instances()");
+ " di.donau_instances_serial"
+ ",di.donau_url"
+ ",di.charity_name"
+ ",mi.merchant_pub AS charity_pub_key"
+ ",di.charity_id"
+ ",di.charity_max_per_year"
+ ",di.charity_receipts_to_date"
+ ",di.current_year"
+ ",dk.keys_json::TEXT"
+ " FROM merchant_donau_instances di"
+ " LEFT JOIN merchant_donau_keys dk"
+ " ON di.donau_url = dk.donau_url"
+ " JOIN merchant_instances mi"
+ " ON di.merchant_instance_serial = mi.merchant_serial");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"select_all_donau_instances",
params,
diff --git a/src/backenddb/select_category.c b/src/backenddb/select_category.c
@@ -35,43 +35,21 @@ TALER_MERCHANTDB_select_category (struct TALER_MERCHANTDB_PostgresContext *pg,
char **products)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&category_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_category",
- "SELECT"
- " category_name"
- ",category_name_i18n::TEXT"
- ",t.product_array AS products"
- " FROM merchant_categories mc"
- ",LATERAL ("
- " SELECT ARRAY ("
- " SELECT "
- " mi.product_id AS product_id"
- " FROM merchant_product_categories mpc"
- " JOIN merchant_inventory mi"
- " USING (product_serial)"
- " WHERE mpc.category_serial = mc.category_serial"
- " ) AS product_array"
- " ) t"
- " WHERE mc.category_serial=$1");
if (NULL == cd)
{
struct GNUNET_PQ_ResultSpec rs_null[] = {
GNUNET_PQ_result_spec_end
};
+ check_connection (pg);
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "select_category",
params,
rs_null);
}
@@ -89,9 +67,31 @@ TALER_MERCHANTDB_select_category (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
+ PREPARE (pg,
+ "select_category",
+ "SELECT"
+ " category_name"
+ ",category_name_i18n::TEXT"
+ ",t.product_array AS products"
+ " FROM merchant_categories mc"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ ",LATERAL ("
+ " SELECT ARRAY ("
+ " SELECT "
+ " mi.product_id AS product_id"
+ " FROM merchant_product_categories mpc"
+ " JOIN merchant_inventory mi"
+ " USING (product_serial)"
+ " WHERE mpc.category_serial = mc.category_serial"
+ " ) AS product_array"
+ " ) t"
+ " WHERE inst.merchant_id=$1"
+ " AND mc.category_serial=$2");
+ check_connection (pg);
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "select_category",
params,
rs);
}
diff --git a/src/backenddb/select_category_by_name.c b/src/backenddb/select_category_by_name.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_select_category_by_name (struct TALER_MERCHANTDB_PostgresContex
uint64_t *category_id)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (category_name),
GNUNET_PQ_query_param_end
};
@@ -44,23 +45,21 @@ TALER_MERCHANTDB_select_category_by_name (struct TALER_MERCHANTDB_PostgresContex
name_i18n),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_category_by_name",
- "SELECT"
- " category_serial"
- ",category_name_i18n::TEXT"
- " FROM merchant_categories"
- " WHERE category_name=$1");
+ PREPARE (pg,
+ "select_category_by_name",
+ "SELECT"
+ " category_serial"
+ ",category_name_i18n::TEXT"
+ " FROM merchant_categories mc"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE mi.merchant_id=$1"
+ " AND mc.category_name=$2");
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "select_category_by_name",
params,
rs);
}
diff --git a/src/backenddb/select_donau_instance_by_serial.c b/src/backenddb/select_donau_instance_by_serial.c
@@ -45,21 +45,17 @@ TALER_MERCHANTDB_select_donau_instance_by_serial (struct TALER_MERCHANTDB_Postgr
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_donau_instance_by_serial",
- "SELECT donau_url"
- " ,charity_id"
- " FROM merchant_donau_instances"
- " WHERE donau_instances_serial = $1");
+ PREPARE (pg,
+ "select_donau_instance_by_serial",
+ "SELECT donau_url"
+ " ,charity_id"
+ " FROM merchant_donau_instances"
+ " WHERE donau_instances_serial = $1");
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "select_donau_instance_by_serial",
params,
rs);
}
diff --git a/src/backenddb/select_donau_instances.c b/src/backenddb/select_donau_instances.c
@@ -137,36 +137,32 @@ TALER_MERCHANTDB_select_donau_instances (
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&pg->current_merchant_serial),
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_donau_instances",
- "SELECT"
- " di.donau_instances_serial"
- ",di.donau_url"
- ",di.charity_name"
- ",mi.merchant_pub AS charity_pub_key"
- ",di.charity_id"
- ",di.charity_max_per_year"
- ",di.charity_receipts_to_date"
- ",di.current_year"
- ",dk.keys_json::TEXT"
- " FROM merchant_donau_instances di"
- " LEFT JOIN merchant_donau_keys dk"
- " ON di.donau_url = dk.donau_url"
- " JOIN merchant.merchant_instances mi"
- " ON mi.merchant_serial = $1");
+ PREPARE (pg,
+ "select_donau_instances",
+ "SELECT"
+ " di.donau_instances_serial"
+ ",di.donau_url"
+ ",di.charity_name"
+ ",mi.merchant_pub AS charity_pub_key"
+ ",di.charity_id"
+ ",di.charity_max_per_year"
+ ",di.charity_receipts_to_date"
+ ",di.current_year"
+ ",dk.keys_json::TEXT"
+ " FROM merchant_donau_instances di"
+ " LEFT JOIN merchant_donau_keys dk"
+ " ON di.donau_url = dk.donau_url"
+ " JOIN merchant_instances mi"
+ " ON di.merchant_instance_serial = mi.merchant_serial"
+ " WHERE mi.merchant_id = $1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
+ "select_donau_instances",
params,
&select_donau_instance_cb,
&sdc);
diff --git a/src/backenddb/select_donau_instances_filtered.c b/src/backenddb/select_donau_instances_filtered.c
@@ -67,7 +67,7 @@ select_donau_instance_cb (void *cls,
{
char *donau_url;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("out_donau_url",
+ GNUNET_PQ_result_spec_string ("donau_url",
&donau_url),
GNUNET_PQ_result_spec_end
};
@@ -112,8 +112,9 @@ TALER_MERCHANTDB_select_donau_instances_filtered (
PREPARE (pg,
"select_donau_instances_filtered",
"SELECT"
- " out_donau_url"
- " FROM merchant.select_donau_instances_filtered($1)");
+ " donau_url"
+ " FROM merchant_donau_instances"
+ " WHERE (charity_max_per_year).curr = $1");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"select_donau_instances_filtered",
diff --git a/src/backenddb/select_login_token.c b/src/backenddb/select_login_token.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_select_login_token (struct TALER_MERCHANTDB_PostgresContext *pg
uint32_t *validity_scope)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_auto_from_type (token),
GNUNET_PQ_query_param_end
};
@@ -44,22 +45,21 @@ TALER_MERCHANTDB_select_login_token (struct TALER_MERCHANTDB_PostgresContext *pg
validity_scope),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_login_token",
- "SELECT"
- " expiration_time"
- ",validity_scope"
- " FROM merchant_login_tokens"
- " WHERE token=$1");
+ PREPARE (pg,
+ "select_login_token",
+ "SELECT"
+ " expiration_time"
+ ",validity_scope"
+ " FROM merchant_login_tokens"
+ " WHERE token=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "select_login_token",
params,
rs);
}
diff --git a/src/backenddb/select_money_pot.c b/src/backenddb/select_money_pot.c
@@ -36,6 +36,7 @@ TALER_MERCHANTDB_select_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
struct TALER_Amount **pot_totals)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&money_pot_id),
GNUNET_PQ_query_param_end
};
@@ -50,24 +51,22 @@ TALER_MERCHANTDB_select_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
pot_totals),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_money_pot",
- "SELECT"
- " money_pot_name"
- " ,money_pot_description"
- " ,pot_totals"
- " FROM merchant_money_pots"
- " WHERE money_pot_serial=$1;");
+ PREPARE (pg,
+ "select_money_pot",
+ "SELECT"
+ " mp.money_pot_name"
+ " ,mp.money_pot_description"
+ " ,mp.pot_totals"
+ " FROM merchant_money_pots mp"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE merchant_id=$1"
+ " AND money_pot_serial=$2;");
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "select_money_pot",
params,
rs);
}
diff --git a/src/backenddb/select_money_pots.c b/src/backenddb/select_money_pots.c
@@ -122,45 +122,45 @@ TALER_MERCHANTDB_select_money_pots (struct TALER_MERCHANTDB_PostgresContext *pg,
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&offset),
GNUNET_PQ_query_param_uint64 (&plimit),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "lookup_money_pots_asc",
- "SELECT"
- " money_pot_serial"
- " ,money_pot_name"
- " ,pot_totals"
- " FROM merchant_money_pots"
- " WHERE money_pot_serial > $1"
- " ORDER BY money_pot_serial ASC"
- " LIMIT $2");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_money_pots_desc",
- "SELECT"
- " money_pot_serial"
- " ,money_pot_name"
- " ,pot_totals"
- " FROM merchant_money_pots"
- " WHERE money_pot_serial < $1"
- " ORDER BY money_pot_serial DESC"
- " LIMIT $2");
+ PREPARE (pg,
+ "lookup_money_pots_asc",
+ "SELECT"
+ " money_pot_serial"
+ " ,money_pot_name"
+ " ,pot_totals"
+ " FROM merchant_money_pots"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND money_pot_serial > $2"
+ " ORDER BY money_pot_serial ASC"
+ " LIMIT $3");
+ PREPARE (pg,
+ "lookup_money_pots_desc",
+ "SELECT"
+ " money_pot_serial"
+ " ,money_pot_name"
+ " ,pot_totals"
+ " FROM merchant_money_pots"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND money_pot_serial < $2"
+ " ORDER BY money_pot_serial DESC"
+ " LIMIT $3");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
(limit > 0)
- ? stmt_asc
- : stmt_desc,
+ ? "lookup_money_pots_asc"
+ : "lookup_money_pots_desc",
params,
&lookup_money_pots_cb,
&plc);
diff --git a/src/backenddb/select_open_transfers.c b/src/backenddb/select_open_transfers.c
@@ -77,17 +77,17 @@ open_transfers_cb (void *cls,
struct TALER_WireTransferIdentifierRawP wtid;
struct GNUNET_TIME_Absolute retry_time;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("out_expected_credit_serial",
+ GNUNET_PQ_result_spec_uint64 ("expected_credit_serial",
&rowid),
- GNUNET_PQ_result_spec_string ("out_instance_id",
+ GNUNET_PQ_result_spec_string ("instance_id",
&instance_id),
- GNUNET_PQ_result_spec_string ("out_exchange_url",
+ GNUNET_PQ_result_spec_string ("exchange_url",
&exchange_url),
- GNUNET_PQ_result_spec_string ("out_payto_uri",
+ GNUNET_PQ_result_spec_string ("payto_uri",
&payto_uri.full_payto),
- GNUNET_PQ_result_spec_auto_from_type ("out_wtid",
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
&wtid),
- GNUNET_PQ_result_spec_absolute_time ("out_retry_time",
+ GNUNET_PQ_result_spec_absolute_time ("retry_time",
&retry_time),
GNUNET_PQ_result_spec_end
};
@@ -134,13 +134,20 @@ TALER_MERCHANTDB_select_open_transfers (
PREPARE (pg,
"select_open_transfers",
"SELECT"
- " out_expected_credit_serial"
- " ,out_instance_id"
- " ,out_exchange_url"
- " ,out_payto_uri"
- " ,out_wtid"
- " ,out_retry_time"
- " FROM merchant.select_open_transfers($1)");
+ " met.expected_credit_serial"
+ ",mi.merchant_id AS instance_id"
+ ",met.exchange_url"
+ ",ma.payto_uri"
+ ",met.wtid"
+ ",met.retry_time"
+ " FROM merchant_expected_transfers met"
+ " JOIN merchant_accounts ma"
+ " USING (account_serial)"
+ " JOIN merchant_instances mi"
+ " ON (ma.merchant_serial=mi.merchant_serial)"
+ " WHERE retry_needed"
+ " ORDER BY retry_time ASC"
+ " LIMIT $1;");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
"select_open_transfers",
diff --git a/src/backenddb/select_order_blinded_sigs.c b/src/backenddb/select_order_blinded_sigs.c
@@ -106,23 +106,19 @@ TALER_MERCHANTDB_select_order_blinded_sigs (struct TALER_MERCHANTDB_PostgresCont
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_blinded_sigs",
- "SELECT"
- " motbs.token_blinded_signature"
- " ,motbs.token_hash"
- " FROM merchant_order_token_blinded_sigs AS motbs"
- " JOIN merchant_contract_terms AS mct USING (order_serial)"
- " WHERE mct.order_id = $1"
- " ORDER BY motbs.token_index ASC");
+ PREPARE (pg,
+ "select_blinded_sigs",
+ "SELECT"
+ " motbs.token_blinded_signature"
+ " ,motbs.token_hash"
+ " FROM merchant_order_token_blinded_sigs AS motbs"
+ " JOIN merchant_contract_terms AS mct USING (order_serial)"
+ " WHERE mct.order_id = $1"
+ " ORDER BY motbs.token_index ASC");
return GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
- stmt,
+ "select_blinded_sigs",
params,
&restore_sig_cb,
&ctx);
diff --git a/src/backenddb/select_otp.c b/src/backenddb/select_otp.c
@@ -33,33 +33,32 @@ TALER_MERCHANTDB_select_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
struct TALER_MERCHANTDB_OtpDeviceDetails *td)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (otp_id),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_otp",
- "SELECT"
- " otp_description"
- ",otp_ctr"
- ",otp_key"
- ",otp_algorithm"
- " FROM merchant_otp_devices"
- " WHERE otp_id=$1");
+ PREPARE (pg,
+ "select_otp",
+ "SELECT"
+ " otp_description"
+ ",otp_ctr"
+ ",otp_key"
+ ",otp_algorithm"
+ " FROM merchant_otp_devices"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_otp_devices.otp_id=$2");
if (NULL == td)
{
struct GNUNET_PQ_ResultSpec rs_null[] = {
GNUNET_PQ_result_spec_end
};
+ check_connection (pg);
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "select_otp",
params,
rs_null);
}
@@ -79,8 +78,9 @@ TALER_MERCHANTDB_select_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
};
enum GNUNET_DB_QueryStatus qs;
+ check_connection (pg);
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "select_otp",
params,
rs);
td->otp_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos32;
diff --git a/src/backenddb/select_otp_serial.c b/src/backenddb/select_otp_serial.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_select_otp_serial (struct TALER_MERCHANTDB_PostgresContext *pg,
uint64_t *serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (otp_id),
GNUNET_PQ_query_param_end
};
@@ -41,21 +42,19 @@ TALER_MERCHANTDB_select_otp_serial (struct TALER_MERCHANTDB_PostgresContext *pg,
serial),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_otp_serial",
- "SELECT"
- " otp_serial"
- " FROM merchant_otp_devices"
- " WHERE otp_id=$1");
+ PREPARE (pg,
+ "select_otp_serial",
+ "SELECT"
+ " otp_serial"
+ " FROM merchant_otp_devices"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND merchant_otp_devices.otp_id=$2");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "select_otp_serial",
params,
rs);
}
diff --git a/src/backenddb/select_product_groups.c b/src/backenddb/select_product_groups.c
@@ -112,45 +112,45 @@ TALER_MERCHANTDB_select_product_groups (struct TALER_MERCHANTDB_PostgresContext
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&offset),
GNUNET_PQ_query_param_uint64 (&plimit),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "lookup_product_groups_asc",
- "SELECT"
- " product_group_serial"
- " ,product_group_name"
- " ,product_group_description"
- " FROM merchant_product_groups"
- " WHERE product_group_serial > $1"
- " ORDER BY product_group_serial ASC"
- " LIMIT $2");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "lookup_product_groups_desc",
- "SELECT"
- " product_group_serial"
- " ,product_group_name"
- " ,product_group_description"
- " FROM merchant_product_groups"
- " WHERE product_group_serial < $1"
- " ORDER BY product_group_serial DESC"
- " LIMIT $2");
+ PREPARE (pg,
+ "lookup_product_groups_asc",
+ "SELECT"
+ " product_group_serial"
+ " ,product_group_name"
+ " ,product_group_description"
+ " FROM merchant_product_groups"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND product_group_serial > $2"
+ " ORDER BY product_group_serial ASC"
+ " LIMIT $3");
+ PREPARE (pg,
+ "lookup_product_groups_desc",
+ "SELECT"
+ " product_group_serial"
+ " ,product_group_name"
+ " ,product_group_description"
+ " FROM merchant_product_groups"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND product_group_serial < $2"
+ " ORDER BY product_group_serial DESC"
+ " LIMIT $3");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
(limit > 0)
- ? stmt_asc
- : stmt_desc,
+ ? "lookup_product_groups_asc"
+ : "lookup_product_groups_desc",
params,
&lookup_product_groups_cb,
&plc);
diff --git a/src/backenddb/select_report.c b/src/backenddb/select_report.c
@@ -41,6 +41,7 @@ TALER_MERCHANTDB_select_report (struct TALER_MERCHANTDB_PostgresContext *pg,
char **last_error_detail)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&report_id),
GNUNET_PQ_query_param_end
};
@@ -73,33 +74,31 @@ TALER_MERCHANTDB_select_report (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
*last_error_detail = NULL;
code = TALER_EC_NONE;
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "select_report",
- "SELECT"
- " report_program_section"
- " ,report_description"
- " ,mime_type"
- " ,data_source"
- " ,target_address"
- " ,frequency"
- " ,frequency_shift"
- " ,next_transmission"
- " ,last_error_code"
- " ,last_error_detail"
- " FROM merchant_reports"
- " WHERE report_serial=$1;");
+ PREPARE (pg,
+ "select_report",
+ "SELECT"
+ " mr.report_program_section"
+ " ,mr.report_description"
+ " ,mr.mime_type"
+ " ,mr.data_source"
+ " ,mr.target_address"
+ " ,mr.frequency"
+ " ,mr.frequency_shift"
+ " ,mr.next_transmission"
+ " ,mr.last_error_code"
+ " ,mr.last_error_detail"
+ " FROM merchant_reports mr"
+ " JOIN merchant_instances mi"
+ " USING (merchant_serial)"
+ " WHERE merchant_id=$1"
+ " AND report_serial=$2;");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
- stmt,
+ "select_report",
params,
rs);
*last_error_code = (enum TALER_ErrorCode) code;
diff --git a/src/backenddb/select_reports.c b/src/backenddb/select_reports.c
@@ -113,47 +113,47 @@ TALER_MERCHANTDB_select_reports (
.extract_failed = false,
};
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&offset),
GNUNET_PQ_query_param_uint64 (&plimit),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt_asc[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_desc[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_asc,
- "select_reports_asc",
- "SELECT"
- " report_serial"
- " ,report_description"
- " ,frequency"
- " FROM merchant_reports"
- " WHERE report_serial > $1"
- " AND NOT one_shot_hidden"
- " ORDER BY report_serial ASC"
- " LIMIT $2");
- PREPARE_INSTANCE (pg,
- stmt_desc,
- "select_reports_desc",
- "SELECT"
- " report_serial"
- " ,report_description"
- " ,frequency"
- " FROM merchant_reports"
- " WHERE report_serial < $1"
- " AND NOT one_shot_hidden"
- " ORDER BY report_serial DESC"
- " LIMIT $2");
+ PREPARE (pg,
+ "select_reports_asc",
+ "SELECT"
+ " report_serial"
+ " ,report_description"
+ " ,frequency"
+ " FROM merchant_reports"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND report_serial > $2"
+ " AND NOT one_shot_hidden"
+ " ORDER BY report_serial ASC"
+ " LIMIT $3");
+ PREPARE (pg,
+ "select_reports_desc",
+ "SELECT"
+ " report_serial"
+ " ,report_description"
+ " ,frequency"
+ " FROM merchant_reports"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND report_serial < $2"
+ " AND NOT one_shot_hidden"
+ " ORDER BY report_serial DESC"
+ " LIMIT $3");
qs = GNUNET_PQ_eval_prepared_multi_select (
pg->conn,
(limit > 0)
- ? stmt_asc
- : stmt_desc,
+ ? "select_reports_asc"
+ : "select_reports_desc",
params,
&select_reports_cb,
&plc);
diff --git a/src/backenddb/select_unit.c b/src/backenddb/select_unit.c
@@ -34,66 +34,23 @@ TALER_MERCHANTDB_select_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
{
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (unit_id),
GNUNET_PQ_query_param_end
};
- char stmt_custom[PG_PREP_INSTANCE_NAME_MAX];
- char stmt_builtin[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
- check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt_custom,
- "select_unit_custom",
- "SELECT"
- " cu.unit_serial"
- " ,cu.unit"
- " ,cu.unit_name_long"
- " ,cu.unit_name_short"
- " ,cu.unit_name_long_i18n"
- " ,cu.unit_name_short_i18n"
- " ,cu.unit_allow_fraction"
- " ,cu.unit_precision_level"
- " ,cu.unit_active"
- " ,FALSE AS unit_builtin"
- " FROM merchant_custom_units cu"
- " WHERE cu.unit=$1");
- PREPARE_INSTANCE (pg,
- stmt_builtin,
- "select_unit_builtin",
- "SELECT"
- " bu.unit_serial"
- " ,bu.unit"
- " ,bu.unit_name_long"
- " ,bu.unit_name_short"
- " ,bu.unit_name_long_i18n"
- " ,bu.unit_name_short_i18n"
- " ,COALESCE(bo.override_allow_fraction, bu.unit_allow_fraction)"
- " ,COALESCE(bo.override_precision_level, bu.unit_precision_level)"
- " ,COALESCE(bo.override_active, bu.unit_active)"
- " ,TRUE AS unit_builtin"
- " FROM merchant_builtin_units bu"
- " LEFT JOIN merchant_builtin_unit_overrides bo"
- " ON bo.builtin_unit_serial = bu.unit_serial"
- " WHERE bu.unit=$1");
if (NULL == ud)
{
struct GNUNET_PQ_ResultSpec rs_null[] = {
GNUNET_PQ_result_spec_end
};
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt_custom,
- params,
- rs_null);
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
- return qs;
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt_builtin,
- params,
- rs_null);
+ check_connection (pg);
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "select_unit",
+ params,
+ rs_null);
}
else
{
@@ -121,14 +78,56 @@ TALER_MERCHANTDB_select_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
+ check_connection (pg);
+
+ PREPARE (pg,
+ "select_unit_custom",
+ "SELECT"
+ " cu.unit_serial"
+ " ,cu.unit"
+ " ,cu.unit_name_long"
+ " ,cu.unit_name_short"
+ " ,cu.unit_name_long_i18n"
+ " ,cu.unit_name_short_i18n"
+ " ,cu.unit_allow_fraction"
+ " ,cu.unit_precision_level"
+ " ,cu.unit_active"
+ " ,FALSE AS unit_builtin"
+ " FROM merchant_custom_units cu"
+ " JOIN merchant_instances inst"
+ " USING (merchant_serial)"
+ " WHERE inst.merchant_id=$1"
+ " AND cu.unit=$2");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt_custom,
+ "select_unit_custom",
params,
rs);
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
return qs;
+
+ PREPARE (pg,
+ "select_unit_builtin",
+ "SELECT"
+ " bu.unit_serial"
+ " ,bu.unit"
+ " ,bu.unit_name_long"
+ " ,bu.unit_name_short"
+ " ,bu.unit_name_long_i18n"
+ " ,bu.unit_name_short_i18n"
+ " ,COALESCE(bo.override_allow_fraction, bu.unit_allow_fraction)"
+ " ,COALESCE(bo.override_precision_level, bu.unit_precision_level)"
+ " ,COALESCE(bo.override_active, bu.unit_active)"
+ " ,TRUE AS unit_builtin"
+ " FROM merchant_builtin_units bu"
+ " JOIN merchant_instances inst"
+ " ON TRUE"
+ " LEFT JOIN merchant_builtin_unit_overrides bo"
+ " ON bo.builtin_unit_serial = bu.unit_serial"
+ " AND bo.merchant_serial = inst.merchant_serial"
+ " WHERE inst.merchant_id=$1"
+ " AND bu.unit=$2");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt_builtin,
+ "select_unit_builtin",
params,
rs);
}
diff --git a/src/backenddb/select_wirewatch_accounts.c b/src/backenddb/select_wirewatch_accounts.c
@@ -71,17 +71,17 @@ handle_results (void *cls,
json_t *credential;
uint64_t last_serial;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("out_merchant_id",
+ GNUNET_PQ_result_spec_string ("merchant_id",
&instance),
- GNUNET_PQ_result_spec_string ("out_payto_uri",
+ GNUNET_PQ_result_spec_string ("payto_uri",
&payto_uri.full_payto),
- GNUNET_PQ_result_spec_string ("out_credit_facade_url",
+ GNUNET_PQ_result_spec_string ("credit_facade_url",
&facade_url),
GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("out_credit_facade_credentials",
+ TALER_PQ_result_spec_json ("credit_facade_credentials",
&credential),
NULL),
- GNUNET_PQ_result_spec_uint64 ("out_last_bank_serial",
+ GNUNET_PQ_result_spec_uint64 ("last_bank_serial",
&last_serial),
GNUNET_PQ_result_spec_end
};
@@ -124,12 +124,16 @@ TALER_MERCHANTDB_select_wirewatch_accounts (
PREPARE (pg,
"select_wirewatch_progress",
"SELECT"
- " out_last_bank_serial"
- " ,out_merchant_id"
- " ,out_payto_uri"
- " ,out_credit_facade_url"
- " ,out_credit_facade_credentials::TEXT"
- " FROM merchant.select_wirewatch_accounts()");
+ " last_bank_serial"
+ ",merchant_id"
+ ",payto_uri"
+ ",credit_facade_url"
+ ",credit_facade_credentials::TEXT"
+ " FROM merchant_accounts"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE active"
+ " AND credit_facade_url IS NOT NULL");
check_connection (pg);
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"select_wirewatch_progress",
diff --git a/src/backenddb/set_instance.c b/src/backenddb/set_instance.c
@@ -1,82 +0,0 @@
-/*
- This file is part of TALER
- (C) 2026 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser 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 src/backenddb/set_instance.c
- * @brief Implementation of TALER_MERCHANTDB_set_instance
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_pq_lib.h>
-#include <taler/taler_pq_lib.h>
-#include "merchant-database/set_instance.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_MERCHANTDB_set_instance (
- struct TALER_MERCHANTDB_PostgresContext *pg,
- const char *instance_id)
-{
- uint64_t serial;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("merchant_serial",
- &serial),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
- char sp_sql[128];
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute (sp_sql),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- if ( (NULL != pg->current_merchant_id) &&
- (0 == strcmp (pg->current_merchant_id,
- instance_id)) )
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- check_connection (pg);
- PREPARE (pg,
- "set_instance_lookup_serial",
- "SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "set_instance_lookup_serial",
- params,
- rs);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- return qs;
- GNUNET_snprintf (sp_sql,
- sizeof (sp_sql),
- "SET search_path TO merchant_instance_%llu, merchant",
- (unsigned long long) serial);
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_free (pg->current_merchant_id);
- pg->current_merchant_id = GNUNET_strdup (instance_id);
- pg->current_merchant_serial = serial;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-}
diff --git a/src/backenddb/solve_mfa_challenge.c b/src/backenddb/solve_mfa_challenge.c
@@ -55,23 +55,20 @@ TALER_MERCHANTDB_solve_mfa_challenge (
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
/* conservatively set security-relevant return values to
safe values, even though these should not be used with qs <= 0 */
*solved = false;
*retry_counter = 0;
- PREPARE_INSTANCE (pg,
- stmt,
- "solve_mfa_challenge",
- "SELECT"
- " out_solved"
- " ,out_retry_counter"
- " FROM merchant_do_solve_mfa_challenge"
- " ($1, $2, $3, $4);");
+ PREPARE (pg,
+ "solve_mfa_challenge",
+ "SELECT"
+ " out_solved"
+ " ,out_retry_counter"
+ " FROM merchant_do_solve_mfa_challenge"
+ " ($1, $2, $3, $4);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "solve_mfa_challenge",
params,
rs);
if (qs <= 0)
diff --git a/src/backenddb/sql-schema/gen-procedures.sh b/src/backenddb/sql-schema/gen-procedures.sh
@@ -46,7 +46,6 @@ SET search_path TO merchant;
EOF
-
# Output procedures, stripping comments
for x in $@; do
@@ -63,48 +62,21 @@ DROP PROCEDURE IF EXISTS merchant_do_gc;
CREATE PROCEDURE merchant_do_gc(in_now INT8)
LANGUAGE plpgsql
AS $$
-DECLARE
- rec RECORD;
- s TEXT;
BEGIN
- -- Drop validation-pending instances that never confirmed in time. The
- -- AFTER DELETE trigger on merchant.merchant_instances will DROP the
- -- per-instance schema for each removed row.
- DELETE FROM merchant.merchant_instances
+ DELETE FROM merchant_instances
WHERE validation_needed
AND validation_expiration < in_now;
-
- -- Per-instance GC: loop over all surviving instances and run the
- -- per-instance GC helpers + targeted DELETEs in each schema.
- FOR rec IN SELECT merchant_serial FROM merchant.merchant_instances
- LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
- BEGIN
- EXECUTE format('SET LOCAL search_path TO %I, merchant', s);
- CALL merchant_statistic_amount_gc ();
- CALL merchant_statistic_bucket_gc ();
- CALL merchant_statistic_counter_gc ();
- EXECUTE format('DELETE FROM %I.tan_challenges'
- ' WHERE expiration_date < $1', s) USING in_now;
- EXECUTE format('DELETE FROM %I.merchant_unclaim_signatures'
- ' WHERE expiration_time < $1', s) USING in_now;
- EXCEPTION
- WHEN undefined_table THEN
- NULL;
- WHEN undefined_function THEN
- NULL;
- END;
- END LOOP;
- -- Restore the global search_path so subsequent statements on this
- -- session don't leak into the last visited instance schema.
- SET LOCAL search_path TO merchant;
+ CALL merchant_statistic_amount_gc ();
+ CALL merchant_statistic_bucket_gc ();
+ CALL merchant_statistic_counter_gc ();
+
+ DELETE FROM tan_challenges
+ WHERE expiration_date < in_now;
+ DELETE FROM merchant_unclaim_signatures
+ WHERE expiration_time < in_now;
END $$;
COMMENT ON PROCEDURE merchant_do_gc
- IS 'Calls per-instance garbage collection subroutines across every instance.'
- ' Removes expired pending-validation instances first (whose ON DELETE'
- ' trigger drops the entire per-instance schema), then for each surviving'
- ' instance runs merchant_statistic_*_gc and DELETEs expired tan_challenges'
- ' / merchant_unclaim_signatures.';
+ IS 'calls all other garbage collection subroutines';
COMMIT;
EOF
diff --git a/src/backenddb/sql-schema/merchant-0036-copy.sql.fragment b/src/backenddb/sql-schema/merchant-0036-copy.sql.fragment
@@ -1,504 +0,0 @@
- -- =================================================================
- -- Copy per-instance row data from merchant.* into the new schema.
- -- Tables are listed in FK-dependency order so plain INSERT works
- -- (no DEFERRABLE games, no WITH ORDINALITY). $1 is bound to
- -- rec.merchant_serial via USING. The merchant_serial column is
- -- dropped from every column list — the schema name is the
- -- discriminator. All target tables use GENERATED BY DEFAULT AS
- -- IDENTITY (so we can keep the source serial values), except
- -- merchant_login_tokens whose `serial` is GENERATED ALWAYS — that
- -- one needs OVERRIDING SYSTEM VALUE.
- --
- -- Two stat-meta tables (merchant_statistic_bucket_meta,
- -- merchant_statistic_interval_meta) have no merchant_serial in the
- -- source schema — they are global slug catalogs and are copied
- -- verbatim into every per-instance schema.
- -- =================================================================
-
- -- ---------------- direct merchant_serial (no JOIN) --------------
-
- EXECUTE format('INSERT INTO %I.merchant_accounts'
- || ' (account_serial, h_wire, salt, credit_facade_url,'
- || ' credit_facade_credentials, last_bank_serial, payto_uri,'
- || ' active, extra_wire_subject_metadata)'
- || ' SELECT account_serial, h_wire, salt, credit_facade_url,'
- || ' credit_facade_credentials, last_bank_serial, payto_uri,'
- || ' active, extra_wire_subject_metadata'
- || ' FROM merchant.merchant_accounts'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_categories'
- || ' (category_serial, category_name, category_name_i18n)'
- || ' SELECT category_serial, category_name, category_name_i18n'
- || ' FROM merchant.merchant_categories'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_contract_terms'
- || ' (order_serial, order_id, contract_terms, wallet_data,'
- || ' h_contract_terms, creation_time, pay_deadline, refund_deadline,'
- || ' paid, wired, fulfillment_url, session_id, pos_key, pos_algorithm,'
- || ' claim_token, choice_index)'
- || ' SELECT order_serial, order_id, contract_terms, wallet_data,'
- || ' h_contract_terms, creation_time, pay_deadline, refund_deadline,'
- || ' paid, wired, fulfillment_url, session_id, pos_key, pos_algorithm,'
- || ' claim_token, choice_index'
- || ' FROM merchant.merchant_contract_terms'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_custom_units'
- || ' (unit_serial, unit, unit_name_long, unit_name_short,'
- || ' unit_name_long_i18n, unit_name_short_i18n,'
- || ' unit_allow_fraction, unit_precision_level, unit_active)'
- || ' SELECT unit_serial, unit, unit_name_long, unit_name_short,'
- || ' unit_name_long_i18n, unit_name_short_i18n,'
- || ' unit_allow_fraction, unit_precision_level, unit_active'
- || ' FROM merchant.merchant_custom_units'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- merchant_donau_instances: source filter column is named
- -- merchant_instance_serial (not merchant_serial).
- EXECUTE format('INSERT INTO %I.merchant_donau_instances'
- || ' (donau_instances_serial, donau_url, charity_name, charity_id,'
- || ' charity_max_per_year, charity_receipts_to_date, current_year)'
- || ' SELECT donau_instances_serial, donau_url, charity_name, charity_id,'
- || ' charity_max_per_year, charity_receipts_to_date, current_year'
- || ' FROM merchant.merchant_donau_instances'
- || ' WHERE merchant_instance_serial = $1', s)
- USING rec.merchant_serial;
-
- -- merchant_login_tokens: target `serial` column is GENERATED ALWAYS
- -- → must use OVERRIDING SYSTEM VALUE to preserve serial values.
- EXECUTE format('INSERT INTO %I.merchant_login_tokens'
- || ' (token, creation_time, expiration_time, validity_scope,'
- || ' description, serial)'
- || ' OVERRIDING SYSTEM VALUE'
- || ' SELECT token, creation_time, expiration_time, validity_scope,'
- || ' description, serial'
- || ' FROM merchant.merchant_login_tokens'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_money_pots'
- || ' (money_pot_serial, money_pot_name, money_pot_description, pot_totals)'
- || ' SELECT money_pot_serial, money_pot_name, money_pot_description, pot_totals'
- || ' FROM merchant.merchant_money_pots'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_otp_devices'
- || ' (otp_serial, otp_id, otp_description, otp_key, otp_algorithm, otp_ctr)'
- || ' SELECT otp_serial, otp_id, otp_description, otp_key, otp_algorithm, otp_ctr'
- || ' FROM merchant.merchant_otp_devices'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_orders'
- || ' (order_serial, order_id, claim_token, h_post_data, pay_deadline,'
- || ' creation_time, contract_terms, pos_key, pos_algorithm,'
- || ' fulfillment_url, session_id)'
- || ' SELECT order_serial, order_id, claim_token, h_post_data, pay_deadline,'
- || ' creation_time, contract_terms, pos_key, pos_algorithm,'
- || ' fulfillment_url, session_id'
- || ' FROM merchant.merchant_orders'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_product_groups'
- || ' (product_group_serial, product_group_name, product_group_description)'
- || ' SELECT product_group_serial, product_group_name, product_group_description'
- || ' FROM merchant.merchant_product_groups'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- merchant_inventory references merchant_product_groups and merchant_money_pots
- -- (already copied above).
- EXECUTE format('INSERT INTO %I.merchant_inventory'
- || ' (product_serial, product_id, description, description_i18n,'
- || ' unit, image, taxes, total_stock, total_sold, total_lost,'
- || ' address, next_restock, minimum_age, product_name, image_hash,'
- || ' price_array, total_stock_frac, total_sold_frac, total_lost_frac,'
- || ' allow_fractional_quantity, fractional_precision_level,'
- || ' product_group_serial, money_pot_serial, price_is_net)'
- || ' SELECT product_serial, product_id, description, description_i18n,'
- || ' unit, image, taxes, total_stock, total_sold, total_lost,'
- || ' address, next_restock, minimum_age, product_name, image_hash,'
- || ' price_array, total_stock_frac, total_sold_frac, total_lost_frac,'
- || ' allow_fractional_quantity, fractional_precision_level,'
- || ' product_group_serial, money_pot_serial, price_is_net'
- || ' FROM merchant.merchant_inventory'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_reports'
- || ' (report_serial, report_program_section, report_description,'
- || ' mime_type, report_token, data_source, target_address,'
- || ' frequency, frequency_shift, next_transmission,'
- || ' last_error_code, last_error_detail, one_shot_hidden)'
- || ' SELECT report_serial, report_program_section, report_description,'
- || ' mime_type, report_token, data_source, target_address,'
- || ' frequency, frequency_shift, next_transmission,'
- || ' last_error_code, last_error_detail, one_shot_hidden'
- || ' FROM merchant.merchant_reports'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- merchant_template references merchant_otp_devices (already copied).
- EXECUTE format('INSERT INTO %I.merchant_template'
- || ' (template_serial, template_id, template_description,'
- || ' otp_device_id, template_contract, editable_defaults)'
- || ' SELECT template_serial, template_id, template_description,'
- || ' otp_device_id, template_contract, editable_defaults'
- || ' FROM merchant.merchant_template'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_token_families'
- || ' (token_family_serial, slug, name, description, description_i18n,'
- || ' valid_after, valid_before, duration, kind, issued, used,'
- || ' validity_granularity, start_offset, cipher_choice, extra_data)'
- || ' SELECT token_family_serial, slug, name, description, description_i18n,'
- || ' valid_after, valid_before, duration, kind, issued, used,'
- || ' validity_granularity, start_offset, cipher_choice, extra_data'
- || ' FROM merchant.merchant_token_families'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_webhook'
- || ' (webhook_serial, webhook_id, event_type, url, http_method,'
- || ' header_template, body_template)'
- || ' SELECT webhook_serial, webhook_id, event_type, url, http_method,'
- || ' header_template, body_template'
- || ' FROM merchant.merchant_webhook'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- merchant_pending_webhooks references merchant_webhook (above) via webhook_serial.
- EXECUTE format('INSERT INTO %I.merchant_pending_webhooks'
- || ' (webhook_pending_serial, webhook_serial, next_attempt, retries,'
- || ' url, http_method, header, body)'
- || ' SELECT webhook_pending_serial, webhook_serial, next_attempt, retries,'
- || ' url, http_method, header, body'
- || ' FROM merchant.merchant_pending_webhooks'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.tan_challenges'
- || ' (challenge_id, h_body, salt, op, code, creation_date,'
- || ' expiration_date, retransmission_date, confirmation_date,'
- || ' retry_counter, tan_channel, required_address)'
- || ' SELECT challenge_id, h_body, salt, op, code, creation_date,'
- || ' expiration_date, retransmission_date, confirmation_date,'
- || ' retry_counter, tan_channel, required_address'
- || ' FROM merchant.tan_challenges'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_keys'
- || ' (merchant_priv)'
- || ' SELECT merchant_priv'
- || ' FROM merchant.merchant_keys'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_builtin_unit_overrides'
- || ' (builtin_unit_serial, override_allow_fraction,'
- || ' override_precision_level, override_active)'
- || ' SELECT builtin_unit_serial, override_allow_fraction,'
- || ' override_precision_level, override_active'
- || ' FROM merchant.merchant_builtin_unit_overrides'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- ---------------- statistics: meta tables are GLOBAL ------------
- -- Copied unfiltered (every instance gets a full slug catalog).
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_bucket_meta'
- || ' (bmeta_serial_id, slug, description, stype, ranges, ages)'
- || ' SELECT bmeta_serial_id, slug, description, stype, ranges, ages'
- || ' FROM merchant.merchant_statistic_bucket_meta', s);
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_interval_meta'
- || ' (imeta_serial_id, slug, description, stype, ranges, precisions)'
- || ' SELECT imeta_serial_id, slug, description, stype, ranges, precisions'
- || ' FROM merchant.merchant_statistic_interval_meta', s);
-
- -- ---------------- statistics: per-instance event/bucket tables --
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_amount_event'
- || ' (aevent_serial_id, imeta_serial_id, slot,'
- || ' delta_curr, delta_value, delta_frac)'
- || ' SELECT aevent_serial_id, imeta_serial_id, slot,'
- || ' delta_curr, delta_value, delta_frac'
- || ' FROM merchant.merchant_statistic_amount_event'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_counter_event'
- || ' (nevent_serial_id, imeta_serial_id, slot, delta)'
- || ' SELECT nevent_serial_id, imeta_serial_id, slot, delta'
- || ' FROM merchant.merchant_statistic_counter_event'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_bucket_amount'
- || ' (bmeta_serial_id, bucket_start, bucket_range, curr,'
- || ' cumulative_value, cumulative_frac)'
- || ' SELECT bmeta_serial_id, bucket_start, bucket_range, curr,'
- || ' cumulative_value, cumulative_frac'
- || ' FROM merchant.merchant_statistic_bucket_amount'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_bucket_counter'
- || ' (bmeta_serial_id, bucket_start, bucket_range, cumulative_number)'
- || ' SELECT bmeta_serial_id, bucket_start, bucket_range, cumulative_number'
- || ' FROM merchant.merchant_statistic_bucket_counter'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_interval_amount'
- || ' (imeta_serial_id, event_delimiter, range, curr,'
- || ' cumulative_value, cumulative_frac)'
- || ' SELECT imeta_serial_id, event_delimiter, range, curr,'
- || ' cumulative_value, cumulative_frac'
- || ' FROM merchant.merchant_statistic_interval_amount'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_statistic_interval_counter'
- || ' (imeta_serial_id, range, event_delimiter, cumulative_number)'
- || ' SELECT imeta_serial_id, range, event_delimiter, cumulative_number'
- || ' FROM merchant.merchant_statistic_interval_counter'
- || ' WHERE merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- ---------------- account-linked (JOIN via account_serial) ------
-
- EXECUTE format('INSERT INTO %I.merchant_kyc'
- || ' (kyc_serial_id, kyc_timestamp, kyc_ok, account_serial,'
- || ' exchange_url, access_token, exchange_http_status,'
- || ' exchange_ec_code, aml_review, jaccount_limits,'
- || ' last_rule_gen, next_kyc_poll, kyc_backoff)'
- || ' SELECT k.kyc_serial_id, k.kyc_timestamp, k.kyc_ok, k.account_serial,'
- || ' k.exchange_url, k.access_token, k.exchange_http_status,'
- || ' k.exchange_ec_code, k.aml_review, k.jaccount_limits,'
- || ' k.last_rule_gen, k.next_kyc_poll, k.kyc_backoff'
- || ' FROM merchant.merchant_kyc k'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON k.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_deposit_confirmations'
- || ' (deposit_confirmation_serial, order_serial, deposit_timestamp,'
- || ' exchange_url, total_without_fee, wire_fee, signkey_serial,'
- || ' exchange_sig, account_serial, wire_transfer_deadline,'
- || ' wire_pending, exchange_failure, retry_backoff)'
- || ' SELECT dc.deposit_confirmation_serial, dc.order_serial, dc.deposit_timestamp,'
- || ' dc.exchange_url, dc.total_without_fee, dc.wire_fee, dc.signkey_serial,'
- || ' dc.exchange_sig, dc.account_serial, dc.wire_transfer_deadline,'
- || ' dc.wire_pending, dc.exchange_failure, dc.retry_backoff'
- || ' FROM merchant.merchant_deposit_confirmations dc'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON dc.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_expected_transfers'
- || ' (expected_credit_serial, exchange_url, wtid, expected_credit_amount,'
- || ' wire_fee, account_serial, expected_time, retry_time, last_http_status,'
- || ' last_ec, last_detail, retry_needed, signkey_serial, exchange_sig,'
- || ' h_details, confirmed)'
- || ' SELECT et.expected_credit_serial, et.exchange_url, et.wtid, et.expected_credit_amount,'
- || ' et.wire_fee, et.account_serial, et.expected_time, et.retry_time, et.last_http_status,'
- || ' et.last_ec, et.last_detail, et.retry_needed, et.signkey_serial, et.exchange_sig,'
- || ' et.h_details, et.confirmed'
- || ' FROM merchant.merchant_expected_transfers et'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON et.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_transfers'
- || ' (credit_serial, exchange_url, wtid, credit_amount, account_serial,'
- || ' bank_serial_id, expected, execution_time)'
- || ' SELECT t.credit_serial, t.exchange_url, t.wtid, t.credit_amount, t.account_serial,'
- || ' t.bank_serial_id, t.expected, t.execution_time'
- || ' FROM merchant.merchant_transfers t'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON t.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- ---------------- deposits: deeper join (dc → accounts) ---------
-
- EXECUTE format('INSERT INTO %I.merchant_deposits'
- || ' (deposit_serial, coin_offset, deposit_confirmation_serial,'
- || ' coin_pub, coin_sig, amount_with_fee, deposit_fee, refund_fee,'
- || ' settlement_retry_needed, settlement_retry_time,'
- || ' settlement_last_http_status, settlement_last_ec,'
- || ' settlement_last_detail, settlement_wtid,'
- || ' settlement_coin_contribution, settlement_expected_credit_serial,'
- || ' signkey_serial, settlement_exchange_sig)'
- || ' SELECT d.deposit_serial, d.coin_offset, d.deposit_confirmation_serial,'
- || ' d.coin_pub, d.coin_sig, d.amount_with_fee, d.deposit_fee, d.refund_fee,'
- || ' d.settlement_retry_needed, d.settlement_retry_time,'
- || ' d.settlement_last_http_status, d.settlement_last_ec,'
- || ' d.settlement_last_detail, d.settlement_wtid,'
- || ' d.settlement_coin_contribution, d.settlement_expected_credit_serial,'
- || ' d.signkey_serial, d.settlement_exchange_sig'
- || ' FROM merchant.merchant_deposits d'
- || ' JOIN merchant.merchant_deposit_confirmations dc'
- || ' ON d.deposit_confirmation_serial = dc.deposit_confirmation_serial'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON dc.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- expected_transfer_to_coin: deposit_serial → deposits → dc → accounts.
- EXECUTE format('INSERT INTO %I.merchant_expected_transfer_to_coin'
- || ' (deposit_serial, expected_credit_serial, offset_in_exchange_list,'
- || ' exchange_deposit_value, exchange_deposit_fee)'
- || ' SELECT ettc.deposit_serial, ettc.expected_credit_serial, ettc.offset_in_exchange_list,'
- || ' ettc.exchange_deposit_value, ettc.exchange_deposit_fee'
- || ' FROM merchant.merchant_expected_transfer_to_coin ettc'
- || ' JOIN merchant.merchant_deposits d'
- || ' ON ettc.deposit_serial = d.deposit_serial'
- || ' JOIN merchant.merchant_deposit_confirmations dc'
- || ' ON d.deposit_confirmation_serial = dc.deposit_confirmation_serial'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON dc.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- transfer_signatures: expected_credit_serial → expected_transfers → accounts.
- EXECUTE format('INSERT INTO %I.merchant_transfer_signatures'
- || ' (expected_credit_serial, signkey_serial, wire_fee, credit_amount,'
- || ' execution_time, exchange_sig)'
- || ' SELECT ts.expected_credit_serial, ts.signkey_serial, ts.wire_fee, ts.credit_amount,'
- || ' ts.execution_time, ts.exchange_sig'
- || ' FROM merchant.merchant_transfer_signatures ts'
- || ' JOIN merchant.merchant_expected_transfers et'
- || ' ON ts.expected_credit_serial = et.expected_credit_serial'
- || ' JOIN merchant.merchant_accounts a'
- || ' ON et.account_serial = a.account_serial'
- || ' WHERE a.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- ---------------- order/contract-linked (JOIN via order_serial) ---
-
- EXECUTE format('INSERT INTO %I.merchant_refunds'
- || ' (refund_serial, order_serial, rtransaction_id, refund_timestamp,'
- || ' coin_pub, reason, refund_amount)'
- || ' SELECT r.refund_serial, r.order_serial, r.rtransaction_id, r.refund_timestamp,'
- || ' r.coin_pub, r.reason, r.refund_amount'
- || ' FROM merchant.merchant_refunds r'
- || ' JOIN merchant.merchant_contract_terms ct'
- || ' ON r.order_serial = ct.order_serial'
- || ' WHERE ct.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_refund_proofs'
- || ' (refund_serial, exchange_sig, signkey_serial)'
- || ' SELECT rp.refund_serial, rp.exchange_sig, rp.signkey_serial'
- || ' FROM merchant.merchant_refund_proofs rp'
- || ' JOIN merchant.merchant_refunds r'
- || ' ON rp.refund_serial = r.refund_serial'
- || ' JOIN merchant.merchant_contract_terms ct'
- || ' ON r.order_serial = ct.order_serial'
- || ' WHERE ct.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_order_token_blinded_sigs'
- || ' (order_token_bs_serial, order_serial, token_index,'
- || ' token_blinded_signature, token_hash)'
- || ' SELECT otbs.order_token_bs_serial, otbs.order_serial, otbs.token_index,'
- || ' otbs.token_blinded_signature, otbs.token_hash'
- || ' FROM merchant.merchant_order_token_blinded_sigs otbs'
- || ' JOIN merchant.merchant_contract_terms ct'
- || ' ON otbs.order_serial = ct.order_serial'
- || ' WHERE ct.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- unclaim_signatures: linked via h_contract_terms.
- EXECUTE format('INSERT INTO %I.merchant_unclaim_signatures'
- || ' (unclaim_serial, h_contract_terms, unclaim_sig, expiration_time)'
- || ' SELECT us.unclaim_serial, us.h_contract_terms, us.unclaim_sig, us.expiration_time'
- || ' FROM merchant.merchant_unclaim_signatures us'
- || ' JOIN merchant.merchant_contract_terms ct'
- || ' ON us.h_contract_terms = ct.h_contract_terms'
- || ' WHERE ct.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- order_locks: order_serial → contract_terms.
- EXECUTE format('INSERT INTO %I.merchant_order_locks'
- || ' (product_serial, total_locked, order_serial, total_locked_frac)'
- || ' SELECT ol.product_serial, ol.total_locked, ol.order_serial, ol.total_locked_frac'
- || ' FROM merchant.merchant_order_locks ol'
- || ' JOIN merchant.merchant_contract_terms ct'
- || ' ON ol.order_serial = ct.order_serial'
- || ' WHERE ct.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- inventory_locks: product_serial → inventory.
- EXECUTE format('INSERT INTO %I.merchant_inventory_locks'
- || ' (product_serial, lock_uuid, total_locked, expiration, total_locked_frac)'
- || ' SELECT il.product_serial, il.lock_uuid, il.total_locked, il.expiration, il.total_locked_frac'
- || ' FROM merchant.merchant_inventory_locks il'
- || ' JOIN merchant.merchant_inventory i'
- || ' ON il.product_serial = i.product_serial'
- || ' WHERE i.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- product_categories: junction; pivot on product_serial → inventory.
- EXECUTE format('INSERT INTO %I.merchant_product_categories'
- || ' (category_serial, product_serial)'
- || ' SELECT pc.category_serial, pc.product_serial'
- || ' FROM merchant.merchant_product_categories pc'
- || ' JOIN merchant.merchant_inventory i'
- || ' ON pc.product_serial = i.product_serial'
- || ' WHERE i.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- -- ---------------- token chain (token_families → keys → tokens) --
-
- EXECUTE format('INSERT INTO %I.merchant_token_family_keys'
- || ' (token_family_key_serial, token_family_serial, pub, h_pub,'
- || ' priv, cipher, signature_validity_start, signature_validity_end,'
- || ' private_key_deleted_at, private_key_created_at)'
- || ' SELECT tfk.token_family_key_serial, tfk.token_family_serial, tfk.pub, tfk.h_pub,'
- || ' tfk.priv, tfk.cipher, tfk.signature_validity_start, tfk.signature_validity_end,'
- || ' tfk.private_key_deleted_at, tfk.private_key_created_at'
- || ' FROM merchant.merchant_token_family_keys tfk'
- || ' JOIN merchant.merchant_token_families tf'
- || ' ON tfk.token_family_serial = tf.token_family_serial'
- || ' WHERE tf.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_issued_tokens'
- || ' (issued_token_serial, h_contract_terms, token_family_key_serial, blind_sig)'
- || ' SELECT it.issued_token_serial, it.h_contract_terms, it.token_family_key_serial, it.blind_sig'
- || ' FROM merchant.merchant_issued_tokens it'
- || ' JOIN merchant.merchant_token_family_keys tfk'
- || ' ON it.token_family_key_serial = tfk.token_family_key_serial'
- || ' JOIN merchant.merchant_token_families tf'
- || ' ON tfk.token_family_serial = tf.token_family_serial'
- || ' WHERE tf.merchant_serial = $1', s)
- USING rec.merchant_serial;
-
- EXECUTE format('INSERT INTO %I.merchant_used_tokens'
- || ' (spent_token_serial, h_contract_terms, token_family_key_serial,'
- || ' token_pub, token_sig, blind_sig)'
- || ' SELECT ut.spent_token_serial, ut.h_contract_terms, ut.token_family_key_serial,'
- || ' ut.token_pub, ut.token_sig, ut.blind_sig'
- || ' FROM merchant.merchant_used_tokens ut'
- || ' JOIN merchant.merchant_token_family_keys tfk'
- || ' ON ut.token_family_key_serial = tfk.token_family_key_serial'
- || ' JOIN merchant.merchant_token_families tf'
- || ' ON tfk.token_family_serial = tf.token_family_serial'
- || ' WHERE tf.merchant_serial = $1', s)
- USING rec.merchant_serial;
diff --git a/src/backenddb/sql-schema/merchant-0036-drop.sql.fragment b/src/backenddb/sql-schema/merchant-0036-drop.sql.fragment
@@ -1,50 +0,0 @@
--- Drop the now-empty per-instance tables from the merchant schema.
--- CASCADE removes the (now obsolete) trigger attachments along with them.
--- The per-instance trigger functions in merchant.* (handle_category_changes,
--- merchant_*_statistics_trigger, ...) are kept around — they will be replaced
--- by the procedures.sql reload after the patch finishes.
-
-DROP TABLE merchant.merchant_unclaim_signatures CASCADE;
-DROP TABLE merchant.merchant_used_tokens CASCADE;
-DROP TABLE merchant.merchant_issued_tokens CASCADE;
-DROP TABLE merchant.merchant_token_family_keys CASCADE;
-DROP TABLE merchant.merchant_token_families CASCADE;
-DROP TABLE merchant.merchant_pending_webhooks CASCADE;
-DROP TABLE merchant.merchant_webhook CASCADE;
-DROP TABLE merchant.merchant_transfer_signatures CASCADE;
-DROP TABLE merchant.merchant_expected_transfer_to_coin CASCADE;
-DROP TABLE merchant.merchant_transfers CASCADE;
-DROP TABLE merchant.merchant_expected_transfers CASCADE;
-DROP TABLE merchant.merchant_kyc CASCADE;
-DROP TABLE merchant.merchant_deposits CASCADE;
-DROP TABLE merchant.merchant_deposit_confirmations CASCADE;
-DROP TABLE merchant.merchant_refund_proofs CASCADE;
-DROP TABLE merchant.merchant_refunds CASCADE;
-DROP TABLE merchant.merchant_order_token_blinded_sigs CASCADE;
-DROP TABLE merchant.merchant_order_locks CASCADE;
-DROP TABLE merchant.merchant_inventory_locks CASCADE;
-DROP TABLE merchant.merchant_product_categories CASCADE;
-DROP TABLE merchant.merchant_template CASCADE;
-DROP TABLE merchant.merchant_otp_devices CASCADE;
-DROP TABLE merchant.merchant_inventory CASCADE;
-DROP TABLE merchant.merchant_product_groups CASCADE;
-DROP TABLE merchant.merchant_money_pots CASCADE;
-DROP TABLE merchant.merchant_categories CASCADE;
-DROP TABLE merchant.merchant_contract_terms CASCADE;
-DROP TABLE merchant.merchant_orders CASCADE;
-DROP TABLE merchant.merchant_custom_units CASCADE;
-DROP TABLE merchant.merchant_builtin_unit_overrides CASCADE;
-DROP TABLE merchant.merchant_login_tokens CASCADE;
-DROP TABLE merchant.merchant_donau_instances CASCADE;
-DROP TABLE merchant.merchant_reports CASCADE;
-DROP TABLE merchant.merchant_keys CASCADE;
-DROP TABLE merchant.merchant_accounts CASCADE;
-DROP TABLE merchant.tan_challenges CASCADE;
-DROP TABLE merchant.merchant_statistic_amount_event CASCADE;
-DROP TABLE merchant.merchant_statistic_counter_event CASCADE;
-DROP TABLE merchant.merchant_statistic_interval_amount CASCADE;
-DROP TABLE merchant.merchant_statistic_interval_counter CASCADE;
-DROP TABLE merchant.merchant_statistic_interval_meta CASCADE;
-DROP TABLE merchant.merchant_statistic_bucket_amount CASCADE;
-DROP TABLE merchant.merchant_statistic_bucket_counter CASCADE;
-DROP TABLE merchant.merchant_statistic_bucket_meta CASCADE;
diff --git a/src/backenddb/sql-schema/merchant-0036-setval.sql.fragment b/src/backenddb/sql-schema/merchant-0036-setval.sql.fragment
@@ -1,35 +0,0 @@
- -- Advance every IDENTITY sequence in the new instance schema past the
- -- maximum value just copied so future inserts do not collide.
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_accounts', 'account_serial'), COALESCE((SELECT MAX(account_serial) FROM merchant.merchant_accounts WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_categories', 'category_serial'), COALESCE((SELECT MAX(category_serial) FROM merchant.merchant_categories WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_contract_terms', 'order_serial'), COALESCE((SELECT MAX(order_serial) FROM merchant.merchant_contract_terms WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_custom_units', 'unit_serial'), COALESCE((SELECT MAX(unit_serial) FROM merchant.merchant_custom_units WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_donau_instances', 'donau_instances_serial'), COALESCE((SELECT MAX(donau_instances_serial) FROM merchant.merchant_donau_instances WHERE merchant_instance_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_inventory', 'product_serial'), COALESCE((SELECT MAX(product_serial) FROM merchant.merchant_inventory WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_login_tokens', 'serial'), COALESCE((SELECT MAX(serial) FROM merchant.merchant_login_tokens WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_money_pots', 'money_pot_serial'), COALESCE((SELECT MAX(money_pot_serial) FROM merchant.merchant_money_pots WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_orders', 'order_serial'), COALESCE((SELECT MAX(order_serial) FROM merchant.merchant_orders WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_otp_devices', 'otp_serial'), COALESCE((SELECT MAX(otp_serial) FROM merchant.merchant_otp_devices WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_pending_webhooks', 'webhook_pending_serial'), COALESCE((SELECT MAX(webhook_pending_serial) FROM merchant.merchant_pending_webhooks WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_product_groups', 'product_group_serial'), COALESCE((SELECT MAX(product_group_serial) FROM merchant.merchant_product_groups WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_reports', 'report_serial'), COALESCE((SELECT MAX(report_serial) FROM merchant.merchant_reports WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_statistic_amount_event', 'aevent_serial_id'), COALESCE((SELECT MAX(aevent_serial_id) FROM merchant.merchant_statistic_amount_event WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_statistic_bucket_meta', 'bmeta_serial_id'), COALESCE((SELECT MAX(bmeta_serial_id) FROM merchant.merchant_statistic_bucket_meta), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_statistic_counter_event', 'nevent_serial_id'), COALESCE((SELECT MAX(nevent_serial_id) FROM merchant.merchant_statistic_counter_event WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_statistic_interval_meta', 'imeta_serial_id'), COALESCE((SELECT MAX(imeta_serial_id) FROM merchant.merchant_statistic_interval_meta), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_template', 'template_serial'), COALESCE((SELECT MAX(template_serial) FROM merchant.merchant_template WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_token_families', 'token_family_serial'), COALESCE((SELECT MAX(token_family_serial) FROM merchant.merchant_token_families WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_webhook', 'webhook_serial'), COALESCE((SELECT MAX(webhook_serial) FROM merchant.merchant_webhook WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.tan_challenges', 'challenge_id'), COALESCE((SELECT MAX(challenge_id) FROM merchant.tan_challenges WHERE merchant_serial = rec.merchant_serial), 0) + 1, false);
- -- Indirect-FK tables (owning instance via JOIN)
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_kyc', 'kyc_serial_id'), COALESCE((SELECT MAX(k.kyc_serial_id) FROM merchant.merchant_kyc k JOIN merchant.merchant_accounts a ON k.account_serial = a.account_serial WHERE a.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_deposit_confirmations', 'deposit_confirmation_serial'), COALESCE((SELECT MAX(dc.deposit_confirmation_serial) FROM merchant.merchant_deposit_confirmations dc JOIN merchant.merchant_accounts a ON dc.account_serial = a.account_serial WHERE a.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_expected_transfers', 'expected_credit_serial'), COALESCE((SELECT MAX(et.expected_credit_serial) FROM merchant.merchant_expected_transfers et JOIN merchant.merchant_accounts a ON et.account_serial = a.account_serial WHERE a.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_transfers', 'credit_serial'), COALESCE((SELECT MAX(t.credit_serial) FROM merchant.merchant_transfers t JOIN merchant.merchant_accounts a ON t.account_serial = a.account_serial WHERE a.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_deposits', 'deposit_serial'), COALESCE((SELECT MAX(d.deposit_serial) FROM merchant.merchant_deposits d JOIN merchant.merchant_deposit_confirmations dc ON d.deposit_confirmation_serial = dc.deposit_confirmation_serial JOIN merchant.merchant_accounts a ON dc.account_serial = a.account_serial WHERE a.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_refunds', 'refund_serial'), COALESCE((SELECT MAX(r.refund_serial) FROM merchant.merchant_refunds r JOIN merchant.merchant_contract_terms ct ON r.order_serial = ct.order_serial WHERE ct.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_token_family_keys', 'token_family_key_serial'), COALESCE((SELECT MAX(tfk.token_family_key_serial) FROM merchant.merchant_token_family_keys tfk JOIN merchant.merchant_token_families tf ON tfk.token_family_serial = tf.token_family_serial WHERE tf.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_issued_tokens', 'issued_token_serial'), COALESCE((SELECT MAX(it.issued_token_serial) FROM merchant.merchant_issued_tokens it JOIN merchant.merchant_token_family_keys tfk ON it.token_family_key_serial = tfk.token_family_key_serial JOIN merchant.merchant_token_families tf ON tfk.token_family_serial = tf.token_family_serial WHERE tf.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_used_tokens', 'spent_token_serial'), COALESCE((SELECT MAX(ut.spent_token_serial) FROM merchant.merchant_used_tokens ut JOIN merchant.merchant_token_family_keys tfk ON ut.token_family_key_serial = tfk.token_family_key_serial JOIN merchant.merchant_token_families tf ON tfk.token_family_serial = tf.token_family_serial WHERE tf.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_unclaim_signatures', 'unclaim_serial'), COALESCE((SELECT MAX(us.unclaim_serial) FROM merchant.merchant_unclaim_signatures us JOIN merchant.merchant_contract_terms ct ON us.h_contract_terms = ct.h_contract_terms WHERE ct.merchant_serial = rec.merchant_serial), 0) + 1, false);
- PERFORM setval(pg_get_serial_sequence(s || '.merchant_order_token_blinded_sigs','order_token_bs_serial'), COALESCE((SELECT MAX(otbs.order_token_bs_serial) FROM merchant.merchant_order_token_blinded_sigs otbs JOIN merchant.merchant_contract_terms ct ON otbs.order_serial = ct.order_serial WHERE ct.merchant_serial = rec.merchant_serial), 0) + 1, false);
diff --git a/src/backenddb/sql-schema/merchant-0036.sql.in b/src/backenddb/sql-schema/merchant-0036.sql.in
@@ -1,88 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2026 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 merchant-0036.sql
--- @brief Move per-instance tables into per-instance schemas
--- merchant_instance_<merchant_serial>. Each existing row of
--- merchant_instances is converted by calling
--- merchant.create_instance_schema(serial), copying the rows of every
--- per-instance table into the new schema (dropping the merchant_serial
--- column), and finally dropping the now-empty merchant.<table>.
--- @author Christian Grothoff
-
-BEGIN;
-
-SELECT _v.register_patch('merchant-0036', NULL, NULL);
-
-SET search_path TO merchant;
-
--- ---------------------------------------------------------------------
--- Step 1: Install the schema constructor.
--- procedures.sql will re-install the same definition (DROP IF EXISTS),
--- so installing it here is harmless and lets the migration call it.
--- ---------------------------------------------------------------------
-#include "../pg_create_instance_schema.sql"
-
--- ---------------------------------------------------------------------
--- Step 2: Build a per-instance schema for every existing instance.
--- ---------------------------------------------------------------------
-DO $MIG$
-DECLARE
- rec RECORD;
-BEGIN
- FOR rec IN SELECT merchant_serial FROM merchant.merchant_instances LOOP
- PERFORM merchant.create_instance_schema(rec.merchant_serial);
- END LOOP;
-END $MIG$;
-
--- ---------------------------------------------------------------------
--- Step 3: Migrate row data per instance.
--- Tables are copied in FK-dependency order. Every copy drops the
--- merchant_serial column. After each table is copied, its IDENTITY
--- sequence (if any) is advanced past MAX(serial).
--- Indirect-FK tables (merchant_kyc, merchant_deposits, ...) are copied
--- by JOINing back to the table that owns the merchant_serial.
--- ---------------------------------------------------------------------
--- Suppress USER triggers during the bulk copy: per-instance triggers
--- (e.g. merchant_kyc_insert_trigger) would otherwise fire on every
--- inserted row and CALL into per-instance procedures that may rely on
--- runtime invariants we do not have during migration. This setting is
--- transaction-local and does not affect normal callers.
-SET session_replication_role = replica;
-
-DO $MIG$
-DECLARE
- rec RECORD;
- s TEXT;
-BEGIN
- FOR rec IN SELECT merchant_serial FROM merchant.merchant_instances LOOP
- s := 'merchant_instance_' || rec.merchant_serial::TEXT;
-
-#include "merchant-0036-copy.sql.fragment"
-
-#include "merchant-0036-setval.sql.fragment"
-
- END LOOP;
-END $MIG$;
-
-SET session_replication_role = origin;
-
--- ---------------------------------------------------------------------
--- Step 4: Drop old per-instance tables from the merchant schema, in
--- reverse FK-dependency order so CASCADE is not needed.
--- ---------------------------------------------------------------------
-#include "merchant-0036-drop.sql.fragment"
-
-COMMIT;
diff --git a/src/backenddb/sql-schema/meson.build b/src/backenddb/sql-schema/meson.build
@@ -66,7 +66,6 @@ sqlfiles = [
'merchant-0033.sql',
'merchant-0034.sql',
'merchant-0035.sql',
- 'merchant-0036.sql',
'versioning.sql',
]
diff --git a/src/backenddb/unlock_inventory.c b/src/backenddb/unlock_inventory.c
@@ -34,17 +34,13 @@ TALER_MERCHANTDB_unlock_inventory (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "unlock_inventory",
- "DELETE"
- " FROM merchant_inventory_locks"
- " WHERE lock_uuid=$1");
+ PREPARE (pg,
+ "unlock_inventory",
+ "DELETE"
+ " FROM merchant_inventory_locks"
+ " WHERE lock_uuid=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "unlock_inventory",
params);
}
diff --git a/src/backenddb/update_account.c b/src/backenddb/update_account.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_update_account (struct TALER_MERCHANTDB_PostgresContext *pg,
const json_t *credit_facade_credentials)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
NULL == credit_facade_url
? GNUNET_PQ_query_param_null ()
@@ -47,22 +48,21 @@ TALER_MERCHANTDB_update_account (struct TALER_MERCHANTDB_PostgresContext *pg,
: GNUNET_PQ_query_param_string (extra_wire_subject_metadata),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_account",
- "UPDATE merchant_accounts SET"
- " credit_facade_url=$2"
- ",credit_facade_credentials="
- " COALESCE($3::TEXT::JSONB, credit_facade_credentials)"
- ",extra_wire_subject_metadata=$4"
- " WHERE h_wire=$1;");
+ PREPARE (pg,
+ "update_account",
+ "UPDATE merchant_accounts SET"
+ " credit_facade_url=$3"
+ ",credit_facade_credentials="
+ " COALESCE($4::TEXT::JSONB, credit_facade_credentials)"
+ ",extra_wire_subject_metadata=$5"
+ " WHERE h_wire=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1);");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_account",
params);
}
diff --git a/src/backenddb/update_category.c b/src/backenddb/update_category.c
@@ -34,25 +34,25 @@ TALER_MERCHANTDB_update_category (struct TALER_MERCHANTDB_PostgresContext *pg,
const json_t *category_name_i18n)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&category_id),
GNUNET_PQ_query_param_string (category_name),
TALER_PQ_query_param_json (category_name_i18n),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_category",
- "UPDATE merchant_categories SET"
- " category_name=$2"
- ",category_name_i18n=$3::TEXT::JSONB"
- " WHERE category_serial=$1");
+ PREPARE (pg,
+ "update_category",
+ "UPDATE merchant_categories SET"
+ " category_name=$3"
+ ",category_name_i18n=$4::TEXT::JSONB"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND category_serial=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_category",
params);
}
diff --git a/src/backenddb/update_contract_session.c b/src/backenddb/update_contract_session.c
@@ -35,6 +35,7 @@ TALER_MERCHANTDB_update_contract_session (struct TALER_MERCHANTDB_PostgresContex
bool *refunded)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
GNUNET_PQ_query_param_string (session_id),
GNUNET_PQ_query_param_end
@@ -48,13 +49,9 @@ TALER_MERCHANTDB_update_contract_session (struct TALER_MERCHANTDB_PostgresContex
refunded),
GNUNET_PQ_result_spec_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
/* Session ID must always be given by the caller. */
GNUNET_assert (NULL != session_id);
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
/* no preflight check here, run in transaction by caller! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -62,21 +59,24 @@ TALER_MERCHANTDB_update_contract_session (struct TALER_MERCHANTDB_PostgresContex
GNUNET_h2s (&h_contract_terms->hash),
instance_id,
session_id);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_contract_session",
- "UPDATE merchant_contract_terms mct SET"
- " session_id=$2"
- " WHERE h_contract_terms=$1"
- " RETURNING"
- " contract_terms->>'fulfillment_url' AS fulfillment_url"
- " ,EXISTS (SELECT 1"
- " FROM merchant_refunds mr"
- " WHERE order_serial=mct.order_serial"
- " ) AS refunded");
+ PREPARE (pg,
+ "update_contract_session",
+ "UPDATE merchant_contract_terms mct SET"
+ " session_id=$3"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " RETURNING"
+ " contract_terms->>'fulfillment_url' AS fulfillment_url"
+ " ,EXISTS (SELECT 1"
+ " FROM merchant_refunds mr"
+ " WHERE order_serial=mct.order_serial"
+ " ) AS refunded");
*fulfillment_url = NULL;
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "update_contract_session",
params,
rs);
}
diff --git a/src/backenddb/update_contract_terms.c b/src/backenddb/update_contract_terms.c
@@ -71,12 +71,10 @@ TALER_MERCHANTDB_update_contract_terms (struct TALER_MERCHANTDB_PostgresContext
}
}
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (order_id),
TALER_PQ_query_param_json (contract_terms),
GNUNET_PQ_query_param_auto_from_type (&h_contract_terms),
@@ -87,20 +85,21 @@ TALER_MERCHANTDB_update_contract_terms (struct TALER_MERCHANTDB_PostgresContext
: GNUNET_PQ_query_param_string (fulfillment_url),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- PREPARE_INSTANCE (pg,
- stmt,
- "update_contract_terms",
- "UPDATE merchant_contract_terms SET"
- " contract_terms=$2::TEXT::JSONB"
- ",h_contract_terms=$3"
- ",pay_deadline=$4"
- ",refund_deadline=$5"
- ",fulfillment_url=$6"
- " WHERE order_id=$1");
+ PREPARE (pg,
+ "update_contract_terms",
+ "UPDATE merchant_contract_terms SET"
+ " contract_terms=$3::TEXT::JSONB"
+ ",h_contract_terms=$4"
+ ",pay_deadline=$5"
+ ",refund_deadline=$6"
+ ",fulfillment_url=$7"
+ " WHERE order_id=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_contract_terms",
params);
}
}
diff --git a/src/backenddb/update_deposit_confirmation_status.c b/src/backenddb/update_deposit_confirmation_status.c
@@ -48,22 +48,18 @@ TALER_MERCHANTDB_update_deposit_confirmation_status (struct TALER_MERCHANTDB_Pos
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_deposit_confirmation_status",
- "UPDATE merchant_deposits SET"
- " settlement_retry_needed=$2"
- ",settlement_retry_time=$3"
- ",settlement_last_http_status=$4"
- ",settlement_last_ec=$5"
- ",settlement_last_detail=$6"
- " WHERE deposit_serial=$1;");
+ PREPARE (pg,
+ "update_deposit_confirmation_status",
+ "UPDATE merchant_deposits SET"
+ " settlement_retry_needed=$2"
+ ",settlement_retry_time=$3"
+ ",settlement_last_http_status=$4"
+ ",settlement_last_ec=$5"
+ ",settlement_last_detail=$6"
+ " WHERE deposit_serial=$1;");
return GNUNET_PQ_eval_prepared_non_select (
pg->conn,
- stmt,
+ "update_deposit_confirmation_status",
params);
}
diff --git a/src/backenddb/update_donau_instance.c b/src/backenddb/update_donau_instance.c
@@ -37,6 +37,7 @@ TALER_MERCHANTDB_update_donau_instance (struct TALER_MERCHANTDB_PostgresContext
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (donau_url),
GNUNET_PQ_query_param_string (charity->name),
+ GNUNET_PQ_query_param_auto_from_type (&charity->charity_pub),
GNUNET_PQ_query_param_uint64 (&charity_id),
TALER_PQ_query_param_amount_with_currency (pg->conn,
&charity->max_per_year),
@@ -45,23 +46,24 @@ TALER_MERCHANTDB_update_donau_instance (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_uint64 (&charity->current_year),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_existing_donau_instance",
- "UPDATE merchant_donau_instances SET"
- " charity_name = $2,"
- " charity_max_per_year = $4,"
- " charity_receipts_to_date = $5,"
- " current_year = $6"
- " WHERE charity_id = $3"
- " AND donau_url = $1;");
+ PREPARE (pg,
+ "update_existing_donau_instance",
+ "UPDATE merchant_donau_instances SET"
+ " charity_name = $2,"
+ " charity_max_per_year = $5,"
+ " charity_receipts_to_date = $6,"
+ " current_year = $7"
+ " WHERE charity_id = $4"
+ " AND merchant_instance_serial "
+ " = (SELECT merchant_serial"
+ " FROM merchant_instances mi"
+ " WHERE mi.merchant_pub = $3)"
+ " AND donau_url = $1;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_existing_donau_instance",
params);
}
diff --git a/src/backenddb/update_donau_instance_receipts_amount.c b/src/backenddb/update_donau_instance_receipts_amount.c
@@ -40,19 +40,15 @@ TALER_MERCHANTDB_update_donau_instance_receipts_amount (struct TALER_MERCHANTDB_
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_donau_instance_receipts",
- "UPDATE merchant_donau_instances "
- "SET charity_receipts_to_date = $2 "
- "WHERE donau_instances_serial = $1;");
+ PREPARE (pg,
+ "update_donau_instance_receipts",
+ "UPDATE merchant_donau_instances "
+ "SET charity_receipts_to_date = $2 "
+ "WHERE donau_instances_serial = $1;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_donau_instance_receipts",
params);
}
diff --git a/src/backenddb/update_mfa_challenge.c b/src/backenddb/update_mfa_challenge.c
@@ -42,20 +42,17 @@ TALER_MERCHANTDB_update_mfa_challenge (struct TALER_MERCHANTDB_PostgresContext *
GNUNET_PQ_query_param_absolute_time (&retransmission_date),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_mfa_challenge",
- "UPDATE tan_challenges"
- " SET"
- " code=$2"
- " ,retry_counter=$3"
- " ,expiration_date=$4"
- " ,retransmission_date=$5"
- " WHERE challenge_id = $1;");
+ PREPARE (pg,
+ "update_mfa_challenge",
+ "UPDATE tan_challenges"
+ " SET"
+ " code=$2"
+ " ,retry_counter=$3"
+ " ,expiration_date=$4"
+ " ,retransmission_date=$5"
+ " WHERE challenge_id = $1;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_mfa_challenge",
params);
}
diff --git a/src/backenddb/update_money_pot.c b/src/backenddb/update_money_pot.c
@@ -40,6 +40,7 @@ TALER_MERCHANTDB_update_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
bool *conflict_name)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&money_pot_id),
GNUNET_PQ_query_param_string (name),
GNUNET_PQ_query_param_string (description),
@@ -66,23 +67,18 @@ TALER_MERCHANTDB_update_money_pot (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_money_pot",
- "SELECT"
- " out_conflict_name AS conflict_name"
- ",out_conflict_total AS conflict_total"
- ",out_not_found AS not_found"
- " FROM merchant_do_update_money_pot"
- "($1,$2,$3,$4,$5);");
+ PREPARE (pg,
+ "update_money_pot",
+ "SELECT"
+ " out_conflict_name AS conflict_name"
+ ",out_conflict_total AS conflict_total"
+ ",out_not_found AS not_found"
+ " FROM merchant_do_update_money_pot"
+ "($1,$2,$3,$4,$5,$6);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "update_money_pot",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/update_otp.c b/src/backenddb/update_otp.c
@@ -34,6 +34,7 @@ TALER_MERCHANTDB_update_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
{
uint32_t pos32 = (uint32_t) td->otp_algorithm;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (otp_id),
GNUNET_PQ_query_param_string (td->otp_description),
GNUNET_PQ_query_param_uint32 (&pos32),
@@ -43,22 +44,21 @@ TALER_MERCHANTDB_update_otp (struct TALER_MERCHANTDB_PostgresContext *pg,
: GNUNET_PQ_query_param_string (td->otp_key),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_otp",
- "UPDATE merchant_otp_devices SET"
- " otp_description=$2"
- ",otp_algorithm=$3"
- ",otp_ctr=$4"
- ",otp_key=COALESCE($5,otp_key)"
- " WHERE otp_id=$1");
+ PREPARE (pg,
+ "update_otp",
+ "UPDATE merchant_otp_devices SET"
+ " otp_description=$3"
+ ",otp_algorithm=$4"
+ ",otp_ctr=$5"
+ ",otp_key=COALESCE($6,otp_key)"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND otp_id=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_otp",
params);
}
diff --git a/src/backenddb/update_pending_webhook.c b/src/backenddb/update_pending_webhook.c
@@ -36,19 +36,15 @@ TALER_MERCHANTDB_update_pending_webhook (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_pending_webhook",
- "UPDATE merchant_pending_webhooks SET"
- " retries=retries+1"
- ",next_attempt=$2"
- " WHERE webhook_pending_serial=$1");
+ PREPARE (pg,
+ "update_pending_webhook",
+ "UPDATE merchant_pending_webhooks SET"
+ " retries=retries+1"
+ ",next_attempt=$2"
+ " WHERE webhook_pending_serial=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_pending_webhook",
params);
}
diff --git a/src/backenddb/update_product.c b/src/backenddb/update_product.c
@@ -44,40 +44,43 @@ TALER_MERCHANTDB_update_product (struct TALER_MERCHANTDB_PostgresContext *pg,
bool *no_pot)
{
struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (product_id), /* $1 */
+ 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), /* $3 */
+ TALER_PQ_query_param_json (pd->description_i18n), /* $4 */
GNUNET_PQ_query_param_string (pd->unit),
- GNUNET_PQ_query_param_string (pd->image), /* $5 */
- TALER_PQ_query_param_json (pd->taxes), /* $6 */
+ GNUNET_PQ_query_param_string (pd->image), /* $6 */
+ TALER_PQ_query_param_json (pd->taxes), /* $7 */
TALER_PQ_query_param_array_amount_with_currency (
pd->price_array_length,
pd->price_array,
- pg->conn), /* $7 */
- GNUNET_PQ_query_param_uint64 (&pd->total_stock), /* $8 */
- GNUNET_PQ_query_param_uint32 (&pd->total_stock_frac), /* $9 */
- GNUNET_PQ_query_param_bool (pd->allow_fractional_quantity), /* $10 */
+ pg->conn), /* $8 */
+ GNUNET_PQ_query_param_uint64 (&pd->total_stock), /* $9 */
+ GNUNET_PQ_query_param_uint32 (&pd->total_stock_frac), /* $10 */
+ GNUNET_PQ_query_param_bool (pd->allow_fractional_quantity), /* $11 */
GNUNET_PQ_query_param_uint32 (&pd->fractional_precision_level),
GNUNET_PQ_query_param_uint64 (&pd->total_lost),
- TALER_PQ_query_param_json (pd->address), /* $13 */
+ TALER_PQ_query_param_json (pd->address), /* $14 */
GNUNET_PQ_query_param_timestamp (&pd->next_restock),
GNUNET_PQ_query_param_uint32 (&pd->minimum_age),
GNUNET_PQ_query_param_array_uint64 (num_cats,
cats,
- pg->conn), /* $16 */
- GNUNET_PQ_query_param_string (pd->product_name), /* $17 */
+ pg->conn), /* $17 */
+ GNUNET_PQ_query_param_string (pd->product_name), /* $18 */
(0 == pd->product_group_id)
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_uint64 (&pd->product_group_id),
(0 == pd->money_pot_id)
? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&pd->money_pot_id), /* $19 */
+ : GNUNET_PQ_query_param_uint64 (&pd->money_pot_id), /* $20 */
GNUNET_PQ_query_param_bool (pd->price_is_net),
GNUNET_PQ_query_param_end
};
uint64_t ncat;
bool cats_found = true;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_instance",
+ no_instance),
GNUNET_PQ_result_spec_bool ("no_product",
no_product),
GNUNET_PQ_result_spec_bool ("lost_reduced",
@@ -97,9 +100,7 @@ TALER_MERCHANTDB_update_product (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- *no_instance = false;
if ( (pd->total_stock < pd->total_lost + pd->total_sold) ||
(pd->total_lost < pd->total_lost
+ pd->total_sold) /* integer overflow */)
@@ -107,27 +108,24 @@ TALER_MERCHANTDB_update_product (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_product",
- "SELECT"
- " out_lost_reduced AS lost_reduced"
- ",out_sold_reduced AS sold_reduced"
- ",out_stocked_reduced AS stocked_reduced"
- ",out_no_product AS no_product"
- ",out_no_cat AS no_cat"
- ",out_no_group AS no_group"
- ",out_no_pot AS no_pot"
- " FROM merchant_do_update_product"
- "($1,$2,$3::TEXT::JSONB,$4,$5,$6::TEXT::JSONB,$7,$8"
- ",$9,$10,$11,$12,$13::TEXT::JSONB,$14,$15,$16,$17"
- ",$18,$19,$20);");
+ PREPARE (pg,
+ "update_product",
+ "SELECT"
+ " out_lost_reduced AS lost_reduced"
+ ",out_sold_reduced AS sold_reduced"
+ ",out_stocked_reduced AS stocked_reduced"
+ ",out_no_product AS no_product"
+ ",out_no_cat AS no_cat"
+ ",out_no_instance AS no_instance"
+ ",out_no_group AS no_group"
+ ",out_no_pot AS no_pot"
+ " FROM merchant_do_update_product"
+ "($1,$2,$3,$4::TEXT::JSONB,$5,$6,$7::TEXT::JSONB,$8,$9"
+ ",$10,$11,$12,$13,$14::TEXT::JSONB,$15,$16,$17,$18"
+ ",$19,$20,$21);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "update_product",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/update_product_group.c b/src/backenddb/update_product_group.c
@@ -36,6 +36,7 @@ TALER_MERCHANTDB_update_product_group (
bool *conflict)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&product_group_id),
GNUNET_PQ_query_param_string (name),
GNUNET_PQ_query_param_string (description),
@@ -50,23 +51,18 @@ TALER_MERCHANTDB_update_product_group (
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_product_group",
- "SELECT"
- " out_conflict AS conflict"
- ",out_not_found AS not_found"
- " FROM merchant_do_update_product_group"
- "($1,$2,$3);");
+ PREPARE (pg,
+ "update_product_group",
+ "SELECT"
+ " out_conflict AS conflict"
+ ",out_not_found AS not_found"
+ " FROM merchant_do_update_product_group"
+ "($1,$2,$3,$4);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "update_product_group",
params,
rs);
if (qs <= 0)
diff --git a/src/backenddb/update_report.c b/src/backenddb/update_report.c
@@ -40,6 +40,7 @@ TALER_MERCHANTDB_update_report (struct TALER_MERCHANTDB_PostgresContext *pg,
{
struct GNUNET_TIME_Timestamp start;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&report_id),
GNUNET_PQ_query_param_string (report_program_section),
GNUNET_PQ_query_param_string (report_description),
@@ -51,11 +52,7 @@ TALER_MERCHANTDB_update_report (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_timestamp (&start),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
start =
GNUNET_TIME_absolute_to_timestamp (
GNUNET_TIME_absolute_add (
@@ -65,20 +62,23 @@ TALER_MERCHANTDB_update_report (struct TALER_MERCHANTDB_PostgresContext *pg,
frequency_shift)));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_report",
- "UPDATE merchant_reports SET"
- " report_program_section=$2"
- " ,report_description=$3"
- " ,mime_type=$4"
- " ,data_source=$5"
- " ,target_address=$6"
- " ,frequency=$7"
- " ,frequency_shift=$8"
- " ,next_transmission=$9"
- " WHERE report_serial=$1;");
+ PREPARE (pg,
+ "update_report",
+ "UPDATE merchant_reports SET"
+ " report_program_section=$3"
+ " ,report_description=$4"
+ " ,mime_type=$5"
+ " ,data_source=$6"
+ " ,target_address=$7"
+ " ,frequency=$8"
+ " ,frequency_shift=$9"
+ " ,next_transmission=$10"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND report_serial=$2;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_report",
params);
}
diff --git a/src/backenddb/update_report_status.c b/src/backenddb/update_report_status.c
@@ -36,6 +36,7 @@ TALER_MERCHANTDB_update_report_status (struct TALER_MERCHANTDB_PostgresContext *
{
uint32_t ec = (uint32_t) last_error_code;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_uint64 (&report_id),
GNUNET_PQ_query_param_timestamp (&next_transmission),
TALER_EC_NONE == ec
@@ -46,21 +47,20 @@ TALER_MERCHANTDB_update_report_status (struct TALER_MERCHANTDB_PostgresContext *
: GNUNET_PQ_query_param_string (last_error_detail),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_report_status",
- "UPDATE merchant_reports SET"
- " next_transmission=$2"
- ",last_error_code=$3"
- ",last_error_detail=$4"
- " WHERE report_serial=$1;");
+ PREPARE (pg,
+ "update_report_status",
+ "UPDATE merchant_reports SET"
+ " next_transmission=$3"
+ ",last_error_code=$4"
+ ",last_error_detail=$5"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND report_serial=$2;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_report_status",
params);
}
diff --git a/src/backenddb/update_template.c b/src/backenddb/update_template.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_update_template (struct TALER_MERCHANTDB_PostgresContext *pg,
const struct TALER_MERCHANTDB_TemplateDetails *td)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (template_id),
GNUNET_PQ_query_param_string (td->template_description),
(NULL == td->otp_id)
@@ -45,29 +46,32 @@ TALER_MERCHANTDB_update_template (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_template",
- "WITH otp AS ("
- " SELECT otp_serial"
- " FROM merchant_otp_devices"
- " WHERE otp_id=$3)"
- "UPDATE merchant_template SET"
- " template_description=$2"
- ",otp_device_id="
- " COALESCE((SELECT otp_serial"
- " FROM otp), NULL)"
- ",template_contract=$4::TEXT::JSONB"
- ",editable_defaults=$5::TEXT::JSONB"
- " WHERE template_id=$1");
+ PREPARE (pg,
+ "update_template",
+ "WITH mid AS ("
+ " SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ ",otp AS ("
+ " SELECT otp_serial"
+ " FROM merchant_otp_devices"
+ " JOIN mid USING (merchant_serial)"
+ " WHERE otp_id=$4)"
+ "UPDATE merchant_template SET"
+ " template_description=$3"
+ ",otp_device_id="
+ " COALESCE((SELECT otp_serial"
+ " FROM otp), NULL)"
+ ",template_contract=$5::TEXT::JSONB"
+ ",editable_defaults=$6::TEXT::JSONB"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM mid)"
+ " AND template_id=$2");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_template",
params);
GNUNET_PQ_cleanup_query_params_closures (params);
return qs;
diff --git a/src/backenddb/update_token_family.c b/src/backenddb/update_token_family.c
@@ -33,6 +33,7 @@ TALER_MERCHANTDB_update_token_family (struct TALER_MERCHANTDB_PostgresContext *p
const struct TALER_MERCHANTDB_TokenFamilyDetails *details)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (token_family_slug),
GNUNET_PQ_query_param_string (details->name),
GNUNET_PQ_query_param_string (details->description),
@@ -44,24 +45,23 @@ TALER_MERCHANTDB_update_token_family (struct TALER_MERCHANTDB_PostgresContext *p
GNUNET_PQ_query_param_timestamp (&details->valid_before),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_token_family",
- "UPDATE merchant_token_families SET"
- " name=$2"
- ",description=$3"
- ",description_i18n=$4::TEXT::JSONB"
- ",extra_data=$5::TEXT::JSONB"
- ",valid_after=$6"
- ",valid_before=$7"
- " WHERE slug=$1");
+ PREPARE (pg,
+ "update_token_family",
+ "UPDATE merchant_token_families SET"
+ " name=$3"
+ ",description=$4"
+ ",description_i18n=$5::TEXT::JSONB"
+ ",extra_data=$6::TEXT::JSONB"
+ ",valid_after=$7"
+ ",valid_before=$8"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND slug=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_token_family",
params);
}
diff --git a/src/backenddb/update_transfer_status.c b/src/backenddb/update_transfer_status.c
@@ -51,23 +51,19 @@ TALER_MERCHANTDB_update_transfer_status (struct TALER_MERCHANTDB_PostgresContext
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
-
- GNUNET_assert (NULL != pg->current_merchant_id);
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_transfer_status",
- "UPDATE merchant_expected_transfers SET"
- " last_http_status=$3"
- ",last_ec=$4"
- ",last_detail=$5"
- ",retry_needed=$6"
- ",retry_time=$7"
- " WHERE wtid=$1"
- " AND exchange_url=$2");
+ PREPARE (pg,
+ "update_transfer_status",
+ "UPDATE merchant_expected_transfers SET"
+ " last_http_status=$3"
+ ",last_ec=$4"
+ ",last_detail=$5"
+ ",retry_needed=$6"
+ ",retry_time=$7"
+ " WHERE wtid=$1"
+ " AND exchange_url=$2");
return GNUNET_PQ_eval_prepared_non_select (
pg->conn,
- stmt,
+ "update_transfer_status",
params);
}
diff --git a/src/backenddb/update_unit.c b/src/backenddb/update_unit.c
@@ -42,6 +42,7 @@ TALER_MERCHANTDB_update_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
bool *builtin_conflict)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (unit_id),
(NULL == unit_name_long)
? GNUNET_PQ_query_param_null ()
@@ -67,6 +68,8 @@ TALER_MERCHANTDB_update_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_no_instance",
+ no_instance),
GNUNET_PQ_result_spec_bool ("out_no_unit",
no_unit),
GNUNET_PQ_result_spec_bool ("out_builtin_conflict",
@@ -74,23 +77,18 @@ TALER_MERCHANTDB_update_unit (struct TALER_MERCHANTDB_PostgresContext *pg,
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- *no_instance = false;
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_unit",
- "SELECT"
- " out_no_unit"
- " ,out_builtin_conflict"
- " FROM merchant_do_update_unit"
- "($1,$2,$3,$4,$5,$6,$7,$8);");
+ PREPARE (pg,
+ "update_unit",
+ "SELECT"
+ " out_no_instance"
+ " ,out_no_unit"
+ " ,out_builtin_conflict"
+ " FROM merchant_do_update_unit"
+ "($1,$2,$3,$4,$5,$6,$7,$8,$9);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- stmt,
+ "update_unit",
params,
rs);
GNUNET_PQ_cleanup_query_params_closures (params);
diff --git a/src/backenddb/update_webhook.c b/src/backenddb/update_webhook.c
@@ -32,6 +32,7 @@ TALER_MERCHANTDB_update_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
const struct TALER_MERCHANTDB_WebhookDetails *wb)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_string (webhook_id),
GNUNET_PQ_query_param_string (wb->event_type),
GNUNET_PQ_query_param_string (wb->url),
@@ -44,24 +45,23 @@ TALER_MERCHANTDB_update_webhook (struct TALER_MERCHANTDB_PostgresContext *pg,
: GNUNET_PQ_query_param_string (wb->body_template),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance_id,
- pg->current_merchant_id));
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_webhook",
- "UPDATE merchant_webhook SET"
- " event_type=$2"
- ",url=$3"
- ",http_method=$4"
- ",header_template=$5"
- ",body_template=$6"
- " WHERE webhook_id=$1");
+ PREPARE (pg,
+ "update_webhook",
+ "UPDATE merchant_webhook SET"
+ " event_type=$3"
+ ",url=$4"
+ ",http_method=$5"
+ ",header_template=$6"
+ ",body_template=$7"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND webhook_id=$2");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_webhook",
params);
}
diff --git a/src/backenddb/update_wirewatch_progress.c b/src/backenddb/update_wirewatch_progress.c
@@ -33,24 +33,24 @@ TALER_MERCHANTDB_update_wirewatch_progress (struct TALER_MERCHANTDB_PostgresCont
uint64_t last_serial)
{
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance),
GNUNET_PQ_query_param_string (payto_uri.full_payto),
GNUNET_PQ_query_param_uint64 (&last_serial),
GNUNET_PQ_query_param_end
};
- char stmt[PG_PREP_INSTANCE_NAME_MAX];
- GNUNET_assert (NULL != pg->current_merchant_id);
- GNUNET_assert (0 == strcmp (instance,
- pg->current_merchant_id));
+ PREPARE (pg,
+ "update_wirewatch_progress",
+ "UPDATE merchant_accounts"
+ " SET last_bank_serial=$3"
+ " WHERE REGEXP_REPLACE(payto_uri,'\\?.*','')"
+ " =REGEXP_REPLACE(CAST ($2 AS TEXT),'\\?.*','')"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
check_connection (pg);
- PREPARE_INSTANCE (pg,
- stmt,
- "update_wirewatch_progress",
- "UPDATE merchant_accounts"
- " SET last_bank_serial=$2"
- " WHERE REGEXP_REPLACE(payto_uri,'\\?.*','')"
- " =REGEXP_REPLACE(CAST ($1 AS TEXT),'\\?.*','')");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- stmt,
+ "update_wirewatch_progress",
params);
}
diff --git a/src/include/merchant-database/set_instance.h b/src/include/merchant-database/set_instance.h
@@ -1,51 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2026 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 src/include/merchant-database/set_instance.h
- * @brief Select the per-instance schema active on the connection
- * @author Christian Grothoff
- */
-#ifndef MERCHANT_DATABASE_SET_INSTANCE_H
-#define MERCHANT_DATABASE_SET_INSTANCE_H
-
-#include <taler/taler_util.h>
-#include "merchantdb_lib.h"
-
-
-/**
- * Resolve @a instance_id to its merchant_serial and route subsequent
- * per-instance queries on @a pg to the corresponding
- * `merchant_instance_<serial>` schema. Updates the connection's
- * search_path to "merchant_instance_<serial>, merchant" and stores
- * @a instance_id / serial in the context for use by per-instance
- * call sites and the #PREPARE_INSTANCE macro.
- *
- * Idempotent: a call with an already-active @a instance_id is a no-op.
- *
- * @param pg database connection
- * @param instance_id instance to activate (must be NUL-terminated)
- * @return #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the instance was found
- * and the search_path was updated;
- * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no such instance exists;
- * a hard or soft error code otherwise
- */
-enum GNUNET_DB_QueryStatus
-TALER_MERCHANTDB_set_instance (
- struct TALER_MERCHANTDB_PostgresContext *pg,
- const char *instance_id);
-
-
-#endif