summaryrefslogtreecommitdiff
path: root/src/backenddb/plugin_merchantdb_postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backenddb/plugin_merchantdb_postgres.c')
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c548
1 files changed, 422 insertions, 126 deletions
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 8e402d31..8c1646a7 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -3457,6 +3457,219 @@ postgres_lookup_transfer_details (
}
+/**
+ * Closure for #lookup_transfers_cb().
+ */
+struct LookupTransfersContext
+{
+ /**
+ * Function to call on results.
+ */
+ TALER_MERCHANTDB_TransferCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Postgres context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Transaction status (set).
+ */
+ enum GNUNET_DB_QueryStatus qs;
+
+ /**
+ * Filter to apply by verification status.
+ */
+ enum TALER_MERCHANTDB_YesNoAll verified;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls of type `struct LookupTransfersContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+lookup_transfers_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupTransfersContext *ltc = cls;
+ struct PostgresClosure *pg = ltc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount credit_amount;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ char *payto_uri;
+ char *exchange_url;
+ uint64_t transfer_serial_id;
+ struct GNUNET_TIME_Absolute execution_time;
+ enum TALER_MERCHANTDB_YesNoAll verified;
+ uint8_t verified8;
+ uint8_t confirmed8;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("credit_amount",
+ &credit_amount),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
+ &wtid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri),
+ GNUNET_PQ_result_spec_string ("exchange_url",
+ &exchange_url),
+ GNUNET_PQ_result_spec_uint64 ("credit_serial",
+ &transfer_serial_id),
+ GNUNET_PQ_result_spec_absolute_time ("execution_time",
+ &execution_time),
+ GNUNET_PQ_result_spec_auto_from_type ("verified",
+ &verified8),
+ GNUNET_PQ_result_spec_auto_from_type ("confirmed",
+ &confirmed8),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ltc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (0 == verified8)
+ verified = TALER_MERCHANTDB_YNA_NO;
+ else
+ verified = TALER_MERCHANTDB_YNA_YES;
+ if ( (ltc->verified == TALER_MERCHANTDB_YNA_ALL) ||
+ (ltc->verified == verified) )
+ {
+ ltc->qs = i + 1;
+ ltc->cb (ltc->cb_cls,
+ &credit_amount,
+ &wtid,
+ payto_uri,
+ exchange_url,
+ transfer_serial_id,
+ execution_time,
+ TALER_MERCHANTDB_YNA_YES == verified,
+ 0 != confirmed8);
+ }
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Lookup transfers. Note that filtering by @a verified status is done
+ * outside of SQL, as we already have 8 prepared statements and adding
+ * a filter on verified would further double the number of statements for
+ * a likely rather ineffective filter. So we apply that filter in
+ * #lookup_transfers_cb().
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup payments for
+ * @param payto_uri account that we are interested in transfers to
+ * @param before timestamp for the earliest transfer we care about
+ * @param after timestamp for the last transfer we care about
+ * @param limit number of entries to return, negative for descending in execution time,
+ * positive for ascending in execution time
+ * @param offset transfer_serial number of the transfer we want to offset from
+ * @param verified filter transfers by verification status
+ * @param cb function to call with detailed transfer data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_transfers (void *cls,
+ const char *instance_id,
+ const char *payto_uri,
+ struct GNUNET_TIME_Absolute before,
+ struct GNUNET_TIME_Absolute after,
+ int64_t limit,
+ uint64_t offset,
+ enum TALER_MERCHANTDB_YesNoAll verified,
+ TALER_MERCHANTDB_TransferCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params_payto_et[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_absolute_time (&before),
+ GNUNET_PQ_query_param_absolute_time (&after),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params_et[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_absolute_time (&before),
+ GNUNET_PQ_query_param_absolute_time (&after),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params_payto[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam params_none[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam *params;
+ struct LookupTransfersContext ltc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .verified = verified
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ char stmt[128];
+ bool by_time;
+
+ by_time = ( (before.abs_value_us !=
+ GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) ||
+ (after.abs_value_us != GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us) );
+
+ check_connection (pg);
+ GNUNET_snprintf (stmt,
+ sizeof (stmt),
+ "lookup_transfers%s%s%s",
+ (by_time) ? "_time" : "",
+ (NULL != payto_uri) ? "_payto" : "",
+ (limit > 0) ? "_asc" : "_desc");
+ params = (by_time)
+ ? ( (NULL != payto_uri) ? params_payto_et : params_et)
+ : ( (NULL != payto_uri) ? params_payto : params_none);
+
+ // FIXME: write SQL (_desc-variant!)
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &lookup_transfers_cb,
+ &ltc);
+ if (0 >= qs)
+ return qs;
+ return ltc.qs;
+}
+
+
/* ********************* OLD API ************************** */
/**
@@ -3672,131 +3885,6 @@ postgres_get_authorized_tip_amount (void *cls,
/**
- * Closure for #find_transfers_cb().
- */
-struct FindTransfersContext
-{
- /**
- * Function to call on results.
- */
- TALER_MERCHANTDB_TransferCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Hash of the contract we are looking under.
- */
- const struct GNUNET_HashCode *h_contract_terms;
-
- /**
- * Transaction status (set).
- */
- enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls of type `struct FindTransfersContext *`
- * @param result the postgres result
- * @param num_result the number of results in @a result
- */
-static void
-find_transfers_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct FindTransfersContext *ftc = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_WireTransferIdentifierRawP wtid;
- struct GNUNET_TIME_Absolute execution_time;
- json_t *proof;
-
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("wtid",
- &wtid),
- GNUNET_PQ_result_spec_absolute_time ("execution_time",
- &execution_time),
- TALER_PQ_result_spec_json ("proof",
- &proof),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ftc->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- ftc->qs = i + 1;
- ftc->cb (ftc->cb_cls,
- ftc->h_contract_terms,
- &coin_pub,
- &wtid,
- execution_time,
- proof);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Lookup information about a transfer by @a h_contract_terms. Note
- * that in theory there could be multiple wire transfers for a
- * single @a h_contract_terms, as the transaction may have involved
- * multiple coins and the coins may be spread over different wire
- * transfers.
- *
- * @param cls closure
- * @param h_contract_terms key for the search
- * @param cb function to call with transfer data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_find_transfers_by_hash (void *cls,
- const struct GNUNET_HashCode *h_contract_terms,
- TALER_MERCHANTDB_TransferCallback cb,
- void *cb_cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_end
- };
- struct FindTransfersContext ftc = {
- .h_contract_terms = h_contract_terms,
- .cb = cb,
- .cb_cls = cb_cls
- };
- enum GNUNET_DB_QueryStatus qs;
-
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "find_transfers_by_hash",
- params,
- &find_transfers_cb,
- &ftc);
- if (0 >= qs)
- return qs;
- return ftc.qs;
-}
-
-
-/**
* Store information about wire fees charged by an exchange,
* including signature (so we have proof).
*
@@ -6007,6 +6095,214 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" WHERE merchant_transfers.wtid=$2"
" AND merchant_transfers.exchange_url=$1",
2),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_payto_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial > $4"
+ " AND payto_uri = $6"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $5",
+ 6),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial > $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $5",
+ 5),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_payto_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial > $2"
+ " AND payto_uri = $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $3",
+ 4),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_asc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial > $2"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial ASC"
+ " LIMIT $3",
+ 3),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_payto_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial < $4"
+ " AND payto_uri = $6"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $5",
+ 6),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_time_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",merchant_transfer_signatures.execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE execution_time < $2"
+ " AND execution_time >= $3"
+ " AND credit_serial < $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $5",
+ 5),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_payto_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial < $2"
+ " AND payto_uri = $4"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $3",
+ 4),
+ /* for postgres_lookup_transfers() */
+ GNUNET_PQ_make_prepare ("lookup_transfers_desc",
+ "SELECT"
+ " credit_amount_val"
+ ",credit_amount_frac"
+ ",wtid"
+ ",merchant_accounts.payto_uri"
+ ",exchange_url"
+ ",credit_serial"
+ ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL"
+ " THEN 9223372036854775807" /* largest BIGINT possible */
+ " ELSE merchant_transfer_signatures.execution_time"
+ " END AS execution_time"
+ ",verified"
+ ",confirmed"
+ " FROM merchant_transfers"
+ " JOIN merchant_accounts USING (account_serial)"
+ " LEFT JOIN merchant_transfer_signatures USING (credit_serial)"
+ " WHERE credit_serial < $2"
+ " AND merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " ORDER BY credit_serial DESC"
+ " LIMIT $3",
+ 3),
/* OLD API: */
#if 0
@@ -6333,12 +6629,12 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
&postgres_set_transfer_status_to_verified;
plugin->lookup_transfer_summary = &postgres_lookup_transfer_summary;
plugin->lookup_transfer_details = &postgres_lookup_transfer_details;
+ plugin->lookup_transfers = &postgres_lookup_transfers;
/* OLD API: */
plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer;
plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof;
plugin->store_wire_fee_by_exchange = &postgres_store_wire_fee_by_exchange;
- plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash;
plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid;
plugin->get_authorized_tip_amount = &postgres_get_authorized_tip_amount;
plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR;