SQL fixes

This commit is contained in:
Christian Grothoff 2021-10-30 13:52:03 +02:00
parent 22e7dabef1
commit 55ea7fcb9a
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC

View File

@ -395,20 +395,20 @@ prepare_statements (struct PostgresClosure *pg)
// FIXME: Note that this statement has not been debugged at all... // FIXME: Note that this statement has not been debugged at all...
// It just represents the _idea_. // It just represents the _idea_.
GNUNET_PQ_make_prepare ("inselect_wallet_kyc_status", GNUNET_PQ_make_prepare ("inselect_wallet_kyc_status",
"INSERT INTO wire_targets" "WITH cte AS ("
"(h_payto" " INSERT INTO wire_targets"
",payto_uri" " (h_payto"
") VALUES " " ,payto_uri"
"($1)" " ) VALUES "
" ON CONFLICT (wire_target_serial_id) DO " " ($1, $2)"
"(SELECT " " ON CONFLICT (wire_target_serial_id) DO NOTHING"
" kyc_ok" ") "
" ,wire_target_serial_id" "SELECT "
")" " kyc_ok"
" RETURNING " ",wire_target_serial_id"
" FALSE AS kyc_ok" " FROM wire_targets"
" wire_target_serial_id;", " WHERE h_payto=$1;",
1), 2),
/* Used in #reserves_get() */ /* Used in #reserves_get() */
GNUNET_PQ_make_prepare ("reserves_get", GNUNET_PQ_make_prepare ("reserves_get",
"SELECT" "SELECT"
@ -439,7 +439,7 @@ prepare_statements (struct PostgresClosure *pg)
"(reserve_uuid" "(reserve_uuid"
",execution_date" ",execution_date"
",wtid" ",wtid"
",receiver_account" ",wire_target_serial_id"
",amount_val" ",amount_val"
",amount_frac" ",amount_frac"
",closing_fee_val" ",closing_fee_val"
@ -466,7 +466,7 @@ prepare_statements (struct PostgresClosure *pg)
",credit_val" ",credit_val"
",credit_frac" ",credit_frac"
",exchange_account_section" ",exchange_account_section"
",sender_account_details" ",wire_source_serial_id"
",execution_date" ",execution_date"
") SELECT reserve_uuid, $2, $3, $4, $5, $6, $7" ") SELECT reserve_uuid, $2, $3, $4, $5, $6, $7"
" FROM reserves" " FROM reserves"
@ -481,7 +481,7 @@ prepare_statements (struct PostgresClosure *pg)
",credit_val" ",credit_val"
",credit_frac" ",credit_frac"
",exchange_account_section" ",exchange_account_section"
",sender_account_details" ",wire_source_serial_id"
",execution_date" ",execution_date"
") VALUES ($1, $2, $3, $4, $5, $6, $7)" ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
" ON CONFLICT DO NOTHING;", " ON CONFLICT DO NOTHING;",
@ -505,11 +505,13 @@ prepare_statements (struct PostgresClosure *pg)
",credit_val" ",credit_val"
",credit_frac" ",credit_frac"
",execution_date" ",execution_date"
",sender_account_details" ",payto_uri AS sender_account_details"
",reserve_in_serial_id" ",reserve_in_serial_id"
" FROM reserves_in" " FROM reserves_in"
" JOIN reserves" " JOIN reserves"
" USING (reserve_uuid)" " USING (reserve_uuid)"
" JOIN wire_targets"
" ON (wire_source_serial_id = wire_target_serial_id)"
" WHERE reserve_in_serial_id>=$1" " WHERE reserve_in_serial_id>=$1"
" ORDER BY reserve_in_serial_id;", " ORDER BY reserve_in_serial_id;",
1), 1),
@ -523,11 +525,13 @@ prepare_statements (struct PostgresClosure *pg)
",credit_val" ",credit_val"
",credit_frac" ",credit_frac"
",execution_date" ",execution_date"
",sender_account_details" ",payto_uri AS sender_account_details"
",reserve_in_serial_id" ",reserve_in_serial_id"
" FROM reserves_in" " FROM reserves_in"
" JOIN reserves " " JOIN reserves "
" USING (reserve_uuid)" " USING (reserve_uuid)"
" JOIN wire_targets"
" ON (wire_source_serial_id = wire_target_serial_id)"
" WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2" " WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2"
" ORDER BY reserve_in_serial_id;", " ORDER BY reserve_in_serial_id;",
2), 2),
@ -539,8 +543,10 @@ prepare_statements (struct PostgresClosure *pg)
",credit_val" ",credit_val"
",credit_frac" ",credit_frac"
",execution_date" ",execution_date"
",sender_account_details" ",payto_uri AS sender_account_details"
" FROM reserves_in" " FROM reserves_in"
" JOIN wire_targets"
" ON (wire_source_serial_id = wire_target_serial_id)"
" WHERE reserve_uuid=" " WHERE reserve_uuid="
" (SELECT reserve_uuid " " (SELECT reserve_uuid "
" FROM reserves" " FROM reserves"
@ -3678,50 +3684,20 @@ postgres_select_kyc_status (void *cls,
* inserts a new status record (hence INsertSELECT). * inserts a new status record (hence INsertSELECT).
* *
* @param cls the @e cls of this struct with the plugin-specific state * @param cls the @e cls of this struct with the plugin-specific state
* @param reserve_pub public key of the wallet * @param payto_uri the payto URI to check
* @param[out] kyc set to the KYC status of the wallet * @param[out] kyc set to the KYC status of the wallet
* @return transaction status * @return transaction status
*/ */
static enum GNUNET_DB_QueryStatus static enum GNUNET_DB_QueryStatus
postgres_inselect_wallet_kyc_status ( inselect_account_kyc_status (
void *cls, struct PostgresClosure *pg,
const struct TALER_ReservePublicKeyP *reserve_pub, const char *payto_uri,
struct TALER_EXCHANGEDB_KycStatus *kyc) struct TALER_EXCHANGEDB_KycStatus *kyc)
{ {
struct PostgresClosure *pg = cls;
char *payto_uri;
struct TALER_PaytoHash h_payto; struct TALER_PaytoHash h_payto;
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
{
char *rps;
unsigned int skip;
const char *extra = "";
int url_len;
rps = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
sizeof (*reserve_pub));
skip = 0;
if (0 == strncasecmp (pg->exchange_url,
"http://",
strlen ("http://")))
skip = strlen ("http://");
if (0 == strncasecmp (pg->exchange_url,
"https://",
strlen ("https://")))
skip = strlen ("https://");
url_len = strlen (pg->exchange_url);
if ('/' == pg->exchange_url[url_len - 1])
url_len--;
url_len -= skip;
GNUNET_asprintf (&payto_uri,
"taler%s://reserve/%.*s/%s",
extra,
url_len,
pg->exchange_url + skip,
rps);
GNUNET_free (rps);
}
TALER_payto_hash (payto_uri, TALER_payto_hash (payto_uri,
&h_payto); &h_payto);
{ {
@ -3745,12 +3721,67 @@ postgres_inselect_wallet_kyc_status (
rs); rs);
kyc->ok = (0 != ok8); kyc->ok = (0 != ok8);
} }
GNUNET_free (payto_uri);
kyc->type = TALER_EXCHANGEDB_KYC_BALANCE; kyc->type = TALER_EXCHANGEDB_KYC_BALANCE;
return qs; return qs;
} }
/**
* Get the KYC status for a wallet. If the status is unknown,
* inserts a new status record (hence INsertSELECT).
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param reserve_pub public key of the wallet
* @param[out] kyc set to the KYC status of the wallet
* @return transaction status
*/
static enum GNUNET_DB_QueryStatus
postgres_inselect_wallet_kyc_status (
void *cls,
const struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_EXCHANGEDB_KycStatus *kyc)
{
struct PostgresClosure *pg = cls;
char *payto_uri;
char *rps;
unsigned int skip;
const char *extra = "";
int url_len;
rps = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
sizeof (*reserve_pub));
skip = 0;
if (0 == strncasecmp (pg->exchange_url,
"http://",
strlen ("http://")))
skip = strlen ("http://");
if (0 == strncasecmp (pg->exchange_url,
"https://",
strlen ("https://")))
skip = strlen ("https://");
url_len = strlen (pg->exchange_url);
if ('/' == pg->exchange_url[url_len - 1])
url_len--;
url_len -= skip;
GNUNET_asprintf (&payto_uri,
"taler%s://reserve/%.*s/%s",
extra,
url_len,
pg->exchange_url + skip,
rps);
GNUNET_free (rps);
{
enum GNUNET_DB_QueryStatus qs;
qs = inselect_account_kyc_status (pg,
payto_uri,
kyc);
GNUNET_free (payto_uri);
return qs;
}
}
/** /**
* Get the summary of a reserve. * Get the summary of a reserve.
* *
@ -3919,7 +3950,18 @@ postgres_reserves_in_insert (void *cls,
is again used to guard against duplicates. */ is again used to guard against duplicates. */
{ {
enum GNUNET_DB_QueryStatus qs2; enum GNUNET_DB_QueryStatus qs2;
struct TALER_EXCHANGEDB_KycStatus kyc;
enum GNUNET_DB_QueryStatus qs3;
qs3 = inselect_account_kyc_status (pg,
sender_account_details,
&kyc);
if (qs3 <= 0)
{
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs3);
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs3);
return qs3;
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs1) if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs1)
{ {
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
@ -3927,7 +3969,7 @@ postgres_reserves_in_insert (void *cls,
GNUNET_PQ_query_param_uint64 (&wire_ref), GNUNET_PQ_query_param_uint64 (&wire_ref),
TALER_PQ_query_param_amount (balance), TALER_PQ_query_param_amount (balance),
GNUNET_PQ_query_param_string (exchange_account_section), GNUNET_PQ_query_param_string (exchange_account_section),
GNUNET_PQ_query_param_string (sender_account_details), GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
TALER_PQ_query_param_absolute_time (&execution_time), TALER_PQ_query_param_absolute_time (&execution_time),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
@ -3943,7 +3985,7 @@ postgres_reserves_in_insert (void *cls,
GNUNET_PQ_query_param_uint64 (&wire_ref), GNUNET_PQ_query_param_uint64 (&wire_ref),
TALER_PQ_query_param_amount (balance), TALER_PQ_query_param_amount (balance),
GNUNET_PQ_query_param_string (exchange_account_section), GNUNET_PQ_query_param_string (exchange_account_section),
GNUNET_PQ_query_param_string (sender_account_details), GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
TALER_PQ_query_param_absolute_time (&execution_time), TALER_PQ_query_param_absolute_time (&execution_time),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
@ -7274,21 +7316,33 @@ postgres_insert_reserve_closed (
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct TALER_EXCHANGEDB_Reserve reserve; struct TALER_EXCHANGEDB_Reserve reserve;
struct GNUNET_PQ_QueryParam params[] = { struct TALER_EXCHANGEDB_KycStatus kyc;
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
TALER_PQ_query_param_absolute_time (&execution_date),
GNUNET_PQ_query_param_auto_from_type (wtid),
GNUNET_PQ_query_param_string (receiver_account),
TALER_PQ_query_param_amount (amount_with_fee),
TALER_PQ_query_param_amount (closing_fee),
GNUNET_PQ_query_param_end
};
enum TALER_AmountArithmeticResult ret;
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, qs = inselect_account_kyc_status (pg,
"reserves_close_insert", receiver_account,
params); &kyc);
if (qs <= 0)
{
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
{
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
TALER_PQ_query_param_absolute_time (&execution_date),
GNUNET_PQ_query_param_auto_from_type (wtid),
GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
TALER_PQ_query_param_amount (amount_with_fee),
TALER_PQ_query_param_amount (closing_fee),
GNUNET_PQ_query_param_end
};
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
"reserves_close_insert",
params);
}
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
return qs; return qs;
@ -7304,20 +7358,24 @@ postgres_insert_reserve_closed (
qs = GNUNET_DB_STATUS_HARD_ERROR; qs = GNUNET_DB_STATUS_HARD_ERROR;
return qs; return qs;
} }
ret = TALER_amount_subtract (&reserve.balance,
&reserve.balance,
amount_with_fee);
if (ret < 0)
{ {
/* The reserve history was checked to make sure there is enough of a balance enum TALER_AmountArithmeticResult ret;
left before we tried this; however, concurrent operations may have changed
the situation by now. We should re-try the transaction. */ ret = TALER_amount_subtract (&reserve.balance,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, &reserve.balance,
"Closing of reserve `%s' refused due to balance mismatch. Retrying.\n", amount_with_fee);
TALER_B2S (reserve_pub)); if (ret < 0)
return GNUNET_DB_STATUS_HARD_ERROR; {
/* The reserve history was checked to make sure there is enough of a balance
left before we tried this; however, concurrent operations may have changed
the situation by now. We should re-try the transaction. */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Closing of reserve `%s' refused due to balance mismatch. Retrying.\n",
TALER_B2S (reserve_pub));
return GNUNET_DB_STATUS_HARD_ERROR;
}
GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
} }
GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
return reserves_update (cls, return reserves_update (cls,
&reserve); &reserve);
} }