gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated (0599b3b -> 560051e)


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated (0599b3b -> 560051e)
Date: Sat, 24 Jun 2017 23:27:38 +0200

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

grothoff pushed a change to branch master
in repository exchange.

    from 0599b3b  need extra font to build on my system
     new 2d662e3  fix #5010 for taler-exchange-aggregator
     new c42d544  convert rest of exchangedb plugin API to fix #5010-issues
     new 560051e  migrating auditordb to new API to address #5010

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/auditor/taler-auditor.c                 |    2 -
 src/auditordb/plugin_auditordb_postgres.c   | 2670 +++++++++++----------------
 src/auditordb/test_auditordb.c              |  117 +-
 src/exchange/taler-exchange-aggregator.c    |  411 +++--
 src/exchangedb/plugin_exchangedb_postgres.c | 2001 ++++++++++----------
 src/exchangedb/test_exchangedb.c            |   70 +-
 src/include/taler_auditordb_plugin.h        |  133 +-
 src/include/taler_exchangedb_plugin.h       |   92 +-
 8 files changed, 2528 insertions(+), 2968 deletions(-)

diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 21c9579..f0608d6 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -2405,8 +2405,6 @@ struct CoinContext
   /**
    * Current financial risk of the exchange operator with respect
    * to key compromise.
-   *
-   * TODO: not yet properly used!
    */
   struct TALER_Amount risk;
 
diff --git a/src/auditordb/plugin_auditordb_postgres.c 
b/src/auditordb/plugin_auditordb_postgres.c
index 57f9e89..e02e69a 100644
--- a/src/auditordb/plugin_auditordb_postgres.c
+++ b/src/auditordb/plugin_auditordb_postgres.c
@@ -203,42 +203,35 @@ static int
 postgres_drop_tables (void *cls)
 {
   struct PostgresClosure *pc = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS predicted_result;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS historic_ledger;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS historic_losses;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS 
historic_denomination_revenue;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS balance_summary;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS denomination_pending;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_reserve_balance;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_wire_fee_balance;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_reserves;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_progress;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
   PGconn *conn;
+  int ret;
 
   conn = connect_to_postgres (pc);
   if (NULL == conn)
     return GNUNET_SYSERR;
   LOG (GNUNET_ERROR_TYPE_INFO,
        "Dropping ALL tables\n");
+  ret = GNUNET_PQ_exec_statements (conn,
+                                   es);
   /* TODO: we probably need a bit more fine-grained control
      over drops for the '-r' option of taler-auditor; also,
      for the testcase, we currently fail to drop the
      auditor_denominations table... */
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS predicted_result;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS historic_ledger;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS historic_losses;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS historic_denomination_revenue;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS balance_summary;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS denomination_pending;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS auditor_reserve_balance;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS auditor_wire_fee_balance;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS auditor_reserves;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS auditor_progress;");
-  PQfinish (conn);
-  return GNUNET_OK;
- SQLEXEC_fail:
   PQfinish (conn);
-  return GNUNET_SYSERR;
+  return ret;
 }
 
 
@@ -252,245 +245,222 @@ static int
 postgres_create_tables (void *cls)
 {
   struct PostgresClosure *pc = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    /* Table with all of the denomination keys that the auditor
+       is aware of. */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_denominations"
+                           "(denom_pub_hash BYTEA PRIMARY KEY CHECK 
(LENGTH(denom_pub_hash)=64)"
+                           ",master_pub BYTEA NOT NULL CHECK 
(LENGTH(master_pub)=32)"
+                           ",valid_from INT8 NOT NULL"
+                           ",expire_withdraw INT8 NOT NULL"
+                           ",expire_deposit INT8 NOT NULL"
+                           ",expire_legal INT8 NOT NULL"
+                           ",coin_val INT8 NOT NULL" /* value of this denom */
+                           ",coin_frac INT4 NOT NULL" /* fractional value of 
this denom */
+                           ",coin_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL" /* assuming same currency for fees */
+                           ",fee_withdraw_val INT8 NOT NULL"
+                           ",fee_withdraw_frac INT4 NOT NULL"
+                           ",fee_withdraw_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",fee_deposit_val INT8 NOT NULL"
+                           ",fee_deposit_frac INT4 NOT NULL"
+                           ",fee_deposit_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",fee_refresh_val INT8 NOT NULL"
+                           ",fee_refresh_frac INT4 NOT NULL"
+                           ",fee_refresh_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",fee_refund_val INT8 NOT NULL"
+                           ",fee_refund_frac INT4 NOT NULL"
+                           ",fee_refund_curr VARCHAR("TALER_CURRENCY_LEN_STR") 
NOT NULL"
+                           ")"),
+    /* Table indicating up to which transactions the auditor has
+       processed the exchange database.  Used for SELECTing the
+       statements to process.  We basically trace the exchange's
+       operations by the 6 primary tables: reserves_in,
+       reserves_out, deposits, refresh_sessions, refunds and prewire. The
+       other tables of the exchange DB just provide supporting
+       evidence which is checked alongside the audit of these
+       five tables.  The 6 indices below include the last serial
+       ID from the respective tables that we have processed. Thus,
+       we need to select those table entries that are strictly
+       larger (and process in monotonically increasing order). */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_progress"
+                           "(master_pub BYTEA PRIMARY KEY CHECK 
(LENGTH(master_pub)=32)"
+                           ",last_reserve_in_serial_id INT8 NOT NULL"
+                           ",last_reserve_out_serial_id INT8 NOT NULL"
+                           ",last_reserve_payback_serial_id INT8 NOT NULL"
+                           ",last_reserve_close_serial_id INT8 NOT NULL"
+                           ",last_withdraw_serial_id INT8 NOT NULL"
+                           ",last_deposit_serial_id INT8 NOT NULL"
+                           ",last_melt_serial_id INT8 NOT NULL"
+                           ",last_refund_serial_id INT8 NOT NULL"
+                           ",last_wire_out_serial_id INT8 NOT NULL"
+                           ")"),
+    /* Table with all of the customer reserves and their respective
+       balances that the auditor is aware of.
+       "last_reserve_out_serial_id" marks the last withdrawal from
+       "reserves_out" about this reserve that the auditor is aware of,
+       and "last_reserve_in_serial_id" is the last "reserve_in"
+       operation about this reserve that the auditor is aware of. */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_reserves"
+                           "(reserve_pub BYTEA NOT NULL 
CHECK(LENGTH(reserve_pub)=32)"
+                           ",master_pub BYTEA NOT NULL CHECK 
(LENGTH(master_pub)=32)"
+                           ",reserve_balance_val INT8 NOT NULL"
+                           ",reserve_balance_frac INT4 NOT NULL"
+                           ",reserve_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",withdraw_fee_balance_val INT8 NOT NULL"
+                           ",withdraw_fee_balance_frac INT4 NOT NULL"
+                           ",withdraw_fee_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",expiration_date INT8 NOT NULL"
+                           ",auditor_reserves_rowid BIGSERIAL"
+                           ")"),
+    GNUNET_PQ_make_try_execute ("CREATE INDEX auditor_reserves_by_reserve_pub "
+                               "ON auditor_reserves(reserve_pub)"),
+    /* Table with the sum of the balances of all customer reserves
+       (by exchange's master public key) */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS 
auditor_reserve_balance"
+                           "(master_pub BYTEA PRIMARY KEY CHECK 
(LENGTH(master_pub)=32)"
+                           ",reserve_balance_val INT8 NOT NULL"
+                           ",reserve_balance_frac INT4 NOT NULL"
+                           ",reserve_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",withdraw_fee_balance_val INT8 NOT NULL"
+                           ",withdraw_fee_balance_frac INT4 NOT NULL"
+                           ",withdraw_fee_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ")"),    
+    /* Table with the sum of the balances of all wire fees
+       (by exchange's master public key) */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS 
auditor_wire_fee_balance"
+                           "(master_pub BYTEA PRIMARY KEY CHECK 
(LENGTH(master_pub)=32)"
+                           ",wire_fee_balance_val INT8 NOT NULL"
+                           ",wire_fee_balance_frac INT4 NOT NULL"
+                           ",wire_fee_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ")"),
+    /* Table with all of the outstanding denomination coins that the
+       exchange is aware of.  "last_deposit_serial_id" marks the
+       deposit_serial_id from "deposits" about this denomination key
+       that the auditor is aware of; "last_melt_serial_id" marks the
+       last melt from "refresh_sessions" that the auditor is aware
+       of; "refund_serial_id" tells us the last entry in "refunds"
+       for this denom_pub that the auditor is aware of. */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS denomination_pending"
+                           "(denom_pub_hash BYTEA PRIMARY KEY"
+                           /* " REFERENCES auditor_denominations 
(denom_pub_hash) ON DELETE CASCADE" // Do we want this? */
+                           ",denom_balance_val INT8 NOT NULL"
+                           ",denom_balance_frac INT4 NOT NULL"
+                           ",denom_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",denom_risk_val INT8 NOT NULL"
+                           ",denom_risk_frac INT4 NOT NULL"
+                           ",denom_risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") 
NOT NULL"
+                           ")"),
+    /* Table with the sum of the outstanding coins from
+       "denomination_pending" (denom_pubs must belong to the
+       respective's exchange's master public key); it represents the
+       balance_summary of the exchange at this point (modulo
+       unexpected historic_loss-style events where denomination keys are
+       compromised) */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS balance_summary"
+                           "(master_pub BYTEA PRIMARY KEY CHECK 
(LENGTH(master_pub)=32)"
+                           ",denom_balance_val INT8 NOT NULL"
+                           ",denom_balance_frac INT4 NOT NULL"
+                           ",denom_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",deposit_fee_balance_val INT8 NOT NULL"
+                           ",deposit_fee_balance_frac INT4 NOT NULL"
+                           ",deposit_fee_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",melt_fee_balance_val INT8 NOT NULL"
+                           ",melt_fee_balance_frac INT4 NOT NULL"
+                           ",melt_fee_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",refund_fee_balance_val INT8 NOT NULL"
+                           ",refund_fee_balance_frac INT4 NOT NULL"
+                           ",refund_fee_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ",risk_val INT8 NOT NULL"
+                           ",risk_frac INT4 NOT NULL"
+                           ",risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
+                           ")"),
+    /* Table with historic profits; basically, when a denom_pub has
+       expired and everything associated with it is garbage collected,
+       the final profits end up in here; note that the "denom_pub" here
+       is not a foreign key, we just keep it as a reference point.
+       "revenue_balance" is the sum of all of the profits we made on the
+       coin except for withdraw fees (which are in
+       historic_reserve_revenue); the deposit, melt and refund fees are given
+       individually; the delta to the revenue_balance is from coins that
+       were withdrawn but never deposited prior to expiration. */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS 
historic_denomination_revenue"
+                           "(master_pub BYTEA NOT NULL CHECK 
(LENGTH(master_pub)=32)"
+                           ",denom_pub_hash BYTEA PRIMARY KEY CHECK 
(LENGTH(denom_pub_hash)=64)"
+                           ",revenue_timestamp INT8 NOT NULL"
+                           ",revenue_balance_val INT8 NOT NULL"
+                           ",revenue_balance_frac INT4 NOT NULL"
+                           ",revenue_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ")"),
+    /* Table with historic losses; basically, when we need to
+       invalidate a denom_pub because the denom_priv was
+       compromised, we incur a loss. These losses are totaled
+       up here. (NOTE: the 'bankrupcy' protocol is not yet
+       implemented, so right now this table is not used.)  */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS historic_losses"
+                           "(master_pub BYTEA NOT NULL CHECK 
(LENGTH(master_pub)=32)"
+                           ",denom_pub_hash BYTEA PRIMARY KEY CHECK 
(LENGTH(denom_pub_hash)=64)"
+                           ",loss_timestamp INT8 NOT NULL"
+                           ",loss_balance_val INT8 NOT NULL"
+                           ",loss_balance_frac INT4 NOT NULL"
+                           ",loss_balance_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ")"),
+    /* Table with historic profits from reserves; we eventually
+       GC "historic_reserve_revenue", and then store the totals
+       in here (by time intervals). */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS 
historic_reserve_summary"
+                           "(master_pub BYTEA NOT NULL CHECK 
(LENGTH(master_pub)=32)"
+                           ",start_date INT8 NOT NULL"
+                           ",end_date INT8 NOT NULL"
+                           ",reserve_profits_val INT8 NOT NULL"
+                           ",reserve_profits_frac INT4 NOT NULL"
+                           ",reserve_profits_curr 
VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+                           ")"),
+    GNUNET_PQ_make_try_execute ("CREATE INDEX 
historic_reserve_summary_by_master_pub_start_date "
+                               "ON 
historic_reserve_summary(master_pub,start_date)"),
+    /* Table with historic business ledger; basically, when the exchange
+       operator decides to use operating costs for anything but wire
+       transfers to merchants, it goes in here.  This happens when the
+       operator users transaction fees for business expenses. "purpose"
+       is free-form but should be a human-readable wire transfer
+       identifier.   This is NOT yet used and outside of the scope of
+       the core auditing logic. However, once we do take fees to use
+       operating costs, and if we still want "predicted_result" to match
+       the tables overall, we'll need a command-line tool to insert rows
+       into this table and update "predicted_result" accordingly.
+       (So this table for now just exists as a reminder of what we'll
+       need in the long term.) */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS historic_ledger"
+                           "(master_pub BYTEA NOT NULL CHECK 
(LENGTH(master_pub)=32)"
+                           ",purpose VARCHAR NOT NULL"
+                           ",timestamp INT8 NOT NULL"
+                           ",balance_val INT8 NOT NULL"
+                           ",balance_frac INT4 NOT NULL"
+                           ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") 
NOT NULL"
+                           ")"),
+    GNUNET_PQ_make_try_execute ("CREATE INDEX 
history_ledger_by_master_pub_and_time "
+                               "ON historic_ledger(master_pub,timestamp)"),
+    /* Table with the sum of the ledger, historic_revenue,
+       historic_losses and the auditor_reserve_balance.  This is the
+       final amount that the exchange should have in its bank account
+       right now. */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS predicted_result"
+                           "(master_pub BYTEA PRIMARY KEY CHECK 
(LENGTH(master_pub)=32)"
+                           ",balance_val INT8 NOT NULL"
+                           ",balance_frac INT4 NOT NULL"
+                           ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") 
NOT NULL"
+                           ")"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
   PGconn *conn;
+  int ret;
 
   conn = connect_to_postgres (pc);
   if (NULL == conn)
     return GNUNET_SYSERR;
-#define SQLEXEC(sql) SQLEXEC_(conn, sql);
-#define SQLEXEC_INDEX(sql) SQLEXEC_IGNORE_ERROR_(conn, sql);
-
-  /* Table with all of the denomination keys that the auditor
-     is aware of. */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS auditor_denominations"
-           "(denom_pub_hash BYTEA PRIMARY KEY CHECK 
(LENGTH(denom_pub_hash)=64)"
-           ",master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
-           ",valid_from INT8 NOT NULL"
-           ",expire_withdraw INT8 NOT NULL"
-           ",expire_deposit INT8 NOT NULL"
-           ",expire_legal INT8 NOT NULL"
-           ",coin_val INT8 NOT NULL" /* value of this denom */
-           ",coin_frac INT4 NOT NULL" /* fractional value of this denom */
-           ",coin_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" /* assuming 
same currency for fees */
-           ",fee_withdraw_val INT8 NOT NULL"
-           ",fee_withdraw_frac INT4 NOT NULL"
-           ",fee_withdraw_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",fee_deposit_val INT8 NOT NULL"
-           ",fee_deposit_frac INT4 NOT NULL"
-           ",fee_deposit_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",fee_refresh_val INT8 NOT NULL"
-           ",fee_refresh_frac INT4 NOT NULL"
-           ",fee_refresh_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",fee_refund_val INT8 NOT NULL"
-           ",fee_refund_frac INT4 NOT NULL"
-           ",fee_refund_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ")");
-
-  /* Table indicating up to which transactions the auditor has
-     processed the exchange database.  Used for SELECTing the
-     statements to process.  We basically trace the exchange's
-     operations by the 6 primary tables: reserves_in,
-     reserves_out, deposits, refresh_sessions, refunds and prewire. The
-     other tables of the exchange DB just provide supporting
-     evidence which is checked alongside the audit of these
-     five tables.  The 6 indices below include the last serial
-     ID from the respective tables that we have processed. Thus,
-     we need to select those table entries that are strictly
-     larger (and process in monotonically increasing order). */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS auditor_progress"
-          "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
-          ",last_reserve_in_serial_id INT8 NOT NULL"
-           ",last_reserve_out_serial_id INT8 NOT NULL"
-           ",last_reserve_payback_serial_id INT8 NOT NULL"
-           ",last_reserve_close_serial_id INT8 NOT NULL"
-           ",last_withdraw_serial_id INT8 NOT NULL"
-          ",last_deposit_serial_id INT8 NOT NULL"
-           ",last_melt_serial_id INT8 NOT NULL"
-          ",last_refund_serial_id INT8 NOT NULL"
-          ",last_wire_out_serial_id INT8 NOT NULL"
-          ")");
-
-  /* Table with all of the customer reserves and their respective
-     balances that the auditor is aware of.
-     "last_reserve_out_serial_id" marks the last withdrawal from
-     "reserves_out" about this reserve that the auditor is aware of,
-     and "last_reserve_in_serial_id" is the last "reserve_in"
-     operation about this reserve that the auditor is aware of. */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS auditor_reserves"
-          "(reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32)"
-           ",master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
-           ",reserve_balance_val INT8 NOT NULL"
-           ",reserve_balance_frac INT4 NOT NULL"
-           ",reserve_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",withdraw_fee_balance_val INT8 NOT NULL"
-           ",withdraw_fee_balance_frac INT4 NOT NULL"
-           ",withdraw_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
-           ",expiration_date INT8 NOT NULL"
-           ",auditor_reserves_rowid BIGSERIAL"
-          ")");
-
-  SQLEXEC_INDEX("CREATE INDEX auditor_reserves_by_reserve_pub "
-                "ON auditor_reserves(reserve_pub)");
-
-  /* Table with the sum of the balances of all customer reserves
-     (by exchange's master public key) */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS auditor_reserve_balance"
-          "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
-          ",reserve_balance_val INT8 NOT NULL"
-           ",reserve_balance_frac INT4 NOT NULL"
-           ",reserve_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",withdraw_fee_balance_val INT8 NOT NULL"
-           ",withdraw_fee_balance_frac INT4 NOT NULL"
-           ",withdraw_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
-          ")");
-
-  /* Table with the sum of the balances of all wire fees
-     (by exchange's master public key) */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS auditor_wire_fee_balance"
-          "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
-          ",wire_fee_balance_val INT8 NOT NULL"
-           ",wire_fee_balance_frac INT4 NOT NULL"
-           ",wire_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-  /* Table with all of the outstanding denomination coins that the
-     exchange is aware of.  "last_deposit_serial_id" marks the
-     deposit_serial_id from "deposits" about this denomination key
-     that the auditor is aware of; "last_melt_serial_id" marks the
-     last melt from "refresh_sessions" that the auditor is aware
-     of; "refund_serial_id" tells us the last entry in "refunds"
-     for this denom_pub that the auditor is aware of. */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS denomination_pending"
-          "(denom_pub_hash BYTEA PRIMARY KEY"
-           /* " REFERENCES auditor_denominations (denom_pub_hash) ON DELETE 
CASCADE" // Do we want this? */
-           ",denom_balance_val INT8 NOT NULL"
-           ",denom_balance_frac INT4 NOT NULL"
-           ",denom_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",denom_risk_val INT8 NOT NULL"
-           ",denom_risk_frac INT4 NOT NULL"
-           ",denom_risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-  /* Table with the sum of the outstanding coins from
-     "denomination_pending" (denom_pubs must belong to the
-     respective's exchange's master public key); it represents the
-     balance_summary of the exchange at this point (modulo
-     unexpected historic_loss-style events where denomination keys are
-     compromised) */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS balance_summary"
-          "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
-          ",denom_balance_val INT8 NOT NULL"
-           ",denom_balance_frac INT4 NOT NULL"
-           ",denom_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",deposit_fee_balance_val INT8 NOT NULL"
-           ",deposit_fee_balance_frac INT4 NOT NULL"
-           ",deposit_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
-           ",melt_fee_balance_val INT8 NOT NULL"
-           ",melt_fee_balance_frac INT4 NOT NULL"
-           ",melt_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ",refund_fee_balance_val INT8 NOT NULL"
-           ",refund_fee_balance_frac INT4 NOT NULL"
-           ",refund_fee_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT 
NULL"
-          ",risk_val INT8 NOT NULL"
-           ",risk_frac INT4 NOT NULL"
-           ",risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-
-  /* Table with historic profits; basically, when a denom_pub has
-     expired and everything associated with it is garbage collected,
-     the final profits end up in here; note that the "denom_pub" here
-     is not a foreign key, we just keep it as a reference point.
-     "revenue_balance" is the sum of all of the profits we made on the
-     coin except for withdraw fees (which are in
-     historic_reserve_revenue); the deposit, melt and refund fees are given
-     individually; the delta to the revenue_balance is from coins that
-     were withdrawn but never deposited prior to expiration. */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS historic_denomination_revenue"
-          "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
-          ",denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)"
-          ",revenue_timestamp INT8 NOT NULL"
-          ",revenue_balance_val INT8 NOT NULL"
-           ",revenue_balance_frac INT4 NOT NULL"
-           ",revenue_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-           ")");
-
-
-  /* Table with historic losses; basically, when we need to
-     invalidate a denom_pub because the denom_priv was
-     compromised, we incur a loss. These losses are totaled
-     up here. (NOTE: the 'bankrupcy' protocol is not yet
-     implemented, so right now this table is not used.)  */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS historic_losses"
-          "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
-          ",denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)"
-          ",loss_timestamp INT8 NOT NULL"
-          ",loss_balance_val INT8 NOT NULL"
-           ",loss_balance_frac INT4 NOT NULL"
-           ",loss_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-  /* Table with historic profits from reserves; we eventually
-     GC "historic_reserve_revenue", and then store the totals
-     in here (by time intervals). */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS historic_reserve_summary"
-          "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
-          ",start_date INT8 NOT NULL"
-          ",end_date INT8 NOT NULL"
-          ",reserve_profits_val INT8 NOT NULL"
-           ",reserve_profits_frac INT4 NOT NULL"
-           ",reserve_profits_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-  SQLEXEC_INDEX("CREATE INDEX 
historic_reserve_summary_by_master_pub_start_date "
-                "ON historic_reserve_summary(master_pub,start_date)");
-
-
-  /* Table with historic business ledger; basically, when the exchange
-     operator decides to use operating costs for anything but wire
-     transfers to merchants, it goes in here.  This happens when the
-     operator users transaction fees for business expenses. "purpose"
-     is free-form but should be a human-readable wire transfer
-     identifier.   This is NOT yet used and outside of the scope of
-     the core auditing logic. However, once we do take fees to use
-     operating costs, and if we still want "predicted_result" to match
-     the tables overall, we'll need a command-line tool to insert rows
-     into this table and update "predicted_result" accordingly.
-     (So this table for now just exists as a reminder of what we'll
-     need in the long term.) */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS historic_ledger"
-          "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)"
-          ",purpose VARCHAR NOT NULL"
-          ",timestamp INT8 NOT NULL"
-          ",balance_val INT8 NOT NULL"
-           ",balance_frac INT4 NOT NULL"
-           ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-  SQLEXEC_INDEX("CREATE INDEX history_ledger_by_master_pub_and_time "
-                "ON historic_ledger(master_pub,timestamp)");
-
-  /* Table with the sum of the ledger, historic_revenue,
-     historic_losses and the auditor_reserve_balance.  This is the
-     final amount that the exchange should have in its bank account
-     right now. */
-  SQLEXEC ("CREATE TABLE IF NOT EXISTS predicted_result"
-          "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)"
-          ",balance_val INT8 NOT NULL"
-           ",balance_frac INT4 NOT NULL"
-           ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
-          ")");
-
-
-#undef SQLEXEC
-#undef SQLEXEC_INDEX
-
+  ret = GNUNET_PQ_exec_statements (conn,
+                                   es);
   PQfinish (conn);
-  return GNUNET_OK;
-
- SQLEXEC_fail:
-  PQfinish (conn);
-  return GNUNET_SYSERR;
+  return ret;
 }
 
 
@@ -503,445 +473,408 @@ postgres_create_tables (void *cls)
 static int
 postgres_prepare (PGconn *db_conn)
 {
-  PGresult *result;
-
-#define PREPARE(name, sql, ...)                                 \
-  do {                                                          \
-    result = PQprepare (db_conn, name, sql, __VA_ARGS__);       \
-    if (PGRES_COMMAND_OK != PQresultStatus (result))            \
-    {                                                           \
-      BREAK_DB_ERR (result);                                    \
-      PQclear (result); result = NULL;                          \
-      return GNUNET_SYSERR;                                     \
-    }                                                           \
-    PQclear (result); result = NULL;                            \
-  } while (0);
-
-  /* Used in #postgres_insert_denomination_info() */
-  PREPARE ("auditor_denominations_insert",
-           "INSERT INTO auditor_denominations "
-           "(denom_pub_hash"
-           ",master_pub"
-           ",valid_from"
-           ",expire_withdraw"
-           ",expire_deposit"
-           ",expire_legal"
-           ",coin_val"
-           ",coin_frac"
-           ",coin_curr"
-           ",fee_withdraw_val"
-           ",fee_withdraw_frac"
-           ",fee_withdraw_curr"
-           ",fee_deposit_val"
-           ",fee_deposit_frac"
-           ",fee_deposit_curr"
-           ",fee_refresh_val"
-           ",fee_refresh_frac"
-           ",fee_refresh_curr"
-           ",fee_refund_val"
-           ",fee_refund_frac"
-           ",fee_refund_curr"
-           ") VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);",
-           21, NULL);
-
-  /* Used in #postgres_insert_denomination_info() */
-  PREPARE ("auditor_denominations_select",
-           "SELECT"
-           " denom_pub_hash"
-           ",valid_from"
-           ",expire_withdraw"
-           ",expire_deposit"
-           ",expire_legal"
-           ",coin_val"
-           ",coin_frac"
-           ",coin_curr"
-           ",fee_withdraw_val"
-           ",fee_withdraw_frac"
-           ",fee_withdraw_curr"
-           ",fee_deposit_val"
-           ",fee_deposit_frac"
-           ",fee_deposit_curr"
-           ",fee_refresh_val"
-           ",fee_refresh_frac"
-           ",fee_refresh_curr"
-           ",fee_refund_val"
-           ",fee_refund_frac"
-           ",fee_refund_curr"
-           " FROM auditor_denominations"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_auditor_progress() */
-  PREPARE ("auditor_progress_insert",
-           "INSERT INTO auditor_progress "
-          "(master_pub"
-          ",last_reserve_in_serial_id"
-           ",last_reserve_out_serial_id"
-           ",last_reserve_payback_serial_id"
-           ",last_reserve_close_serial_id"
-          ",last_withdraw_serial_id"
-          ",last_deposit_serial_id"
-           ",last_melt_serial_id"
-          ",last_refund_serial_id"
-          ",last_wire_out_serial_id"
-           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
-           10, NULL);
-
-  /* Used in #postgres_update_auditor_progress() */
-  PREPARE ("auditor_progress_update",
-           "UPDATE auditor_progress SET "
-          " last_reserve_in_serial_id=$1"
-           ",last_reserve_out_serial_id=$2"
-           ",last_reserve_payback_serial_id=$3"
-           ",last_reserve_close_serial_id=$4"
-          ",last_withdraw_serial_id=$5"
-          ",last_deposit_serial_id=$6"
-           ",last_melt_serial_id=$7"
-          ",last_refund_serial_id=$8"
-          ",last_wire_out_serial_id=$9"
-           " WHERE master_pub=$10",
-           10, NULL);
-
-  /* Used in #postgres_get_auditor_progress() */
-  PREPARE ("auditor_progress_select",
-           "SELECT"
-          " last_reserve_in_serial_id"
-           ",last_reserve_out_serial_id"
-           ",last_reserve_payback_serial_id"
-           ",last_reserve_close_serial_id"
-          ",last_withdraw_serial_id"
-          ",last_deposit_serial_id"
-           ",last_melt_serial_id"
-          ",last_refund_serial_id"
-          ",last_wire_out_serial_id"
-           " FROM auditor_progress"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_reserve_info() */
-  PREPARE ("auditor_reserves_insert",
-           "INSERT INTO auditor_reserves "
-          "(reserve_pub"
-           ",master_pub"
-           ",reserve_balance_val"
-           ",reserve_balance_frac"
-           ",reserve_balance_curr"
-           ",withdraw_fee_balance_val"
-           ",withdraw_fee_balance_frac"
-           ",withdraw_fee_balance_curr"
-           ",expiration_date"
-           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
-           9, NULL);
-
-  /* Used in #postgres_update_reserve_info() */
-  PREPARE ("auditor_reserves_update",
-           "UPDATE auditor_reserves SET"
-           " reserve_balance_val=$1"
-           ",reserve_balance_frac=$2"
-           ",reserve_balance_curr=$3"
-           ",withdraw_fee_balance_val=$4"
-           ",withdraw_fee_balance_frac=$5"
-           ",withdraw_fee_balance_curr=$6"
-           ",expiration_date=$7"
-           " WHERE reserve_pub=$8 AND master_pub=$9;",
-           9, NULL);
-
-  /* Used in #postgres_get_reserve_info() */
-  PREPARE ("auditor_reserves_select",
-           "SELECT"
-           " reserve_balance_val"
-           ",reserve_balance_frac"
-           ",reserve_balance_curr"
-           ",withdraw_fee_balance_val"
-           ",withdraw_fee_balance_frac"
-           ",withdraw_fee_balance_curr"
-           ",expiration_date"
-           ",auditor_reserves_rowid"
-           " FROM auditor_reserves"
-           " WHERE reserve_pub=$1 AND master_pub=$2;",
-           2, NULL);
-
-  /* Used in #postgres_del_reserve_info() */
-  PREPARE ("auditor_reserves_delete",
-           "DELETE"
-           " FROM auditor_reserves"
-           " WHERE reserve_pub=$1 AND master_pub=$2;",
-           2, NULL);
-
-  /* Used in #postgres_insert_reserve_summary() */
-  PREPARE ("auditor_reserve_balance_insert",
-           "INSERT INTO auditor_reserve_balance"
-          "(master_pub"
-          ",reserve_balance_val"
-           ",reserve_balance_frac"
-           ",reserve_balance_curr"
-           ",withdraw_fee_balance_val"
-           ",withdraw_fee_balance_frac"
-           ",withdraw_fee_balance_curr"
-           ") VALUES ($1,$2,$3,$4,$5,$6,$7)",
-           7, NULL);
-
-  /* Used in #postgres_update_reserve_summary() */
-  PREPARE ("auditor_reserve_balance_update",
-           "UPDATE auditor_reserve_balance SET"
-          " reserve_balance_val=$1"
-           ",reserve_balance_frac=$2"
-           ",reserve_balance_curr=$3"
-           ",withdraw_fee_balance_val=$4"
-           ",withdraw_fee_balance_frac=$5"
-           ",withdraw_fee_balance_curr=$6"
-           " WHERE master_pub=$7;",
-           7, NULL);
-
-  /* Used in #postgres_get_reserve_summary() */
-  PREPARE ("auditor_reserve_balance_select",
-           "SELECT"
-          " reserve_balance_val"
-           ",reserve_balance_frac"
-           ",reserve_balance_curr"
-           ",withdraw_fee_balance_val"
-           ",withdraw_fee_balance_frac"
-           ",withdraw_fee_balance_curr"
-           " FROM auditor_reserve_balance"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_wire_fee_summary() */
-  PREPARE ("auditor_wire_fee_balance_insert",
-           "INSERT INTO auditor_wire_fee_balance"
-          "(master_pub"
-          ",wire_fee_balance_val"
-           ",wire_fee_balance_frac"
-           ",wire_fee_balance_curr"
-           ") VALUES ($1,$2,$3,$4)",
-           4, NULL);
-
-  /* Used in #postgres_update_wire_fee_summary() */
-  PREPARE ("auditor_wire_fee_balance_update",
-           "UPDATE auditor_wire_fee_balance SET"
-          " wire_fee_balance_val=$1"
-           ",wire_fee_balance_frac=$2"
-           ",wire_fee_balance_curr=$3"
-           " WHERE master_pub=$4;",
-           4, NULL);
-
-  /* Used in #postgres_get_wire_fee_summary() */
-  PREPARE ("auditor_wire_fee_balance_select",
-           "SELECT"
-          " wire_fee_balance_val"
-           ",wire_fee_balance_frac"
-           ",wire_fee_balance_curr"
-           " FROM auditor_wire_fee_balance"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-
-  /* Used in #postgres_insert_denomination_balance() */
-  PREPARE ("denomination_pending_insert",
-           "INSERT INTO denomination_pending "
-          "(denom_pub_hash"
-           ",denom_balance_val"
-           ",denom_balance_frac"
-           ",denom_balance_curr"
-           ",denom_risk_val"
-           ",denom_risk_frac"
-           ",denom_risk_curr"
-           ") VALUES ($1,$2,$3,$4,$5,$6,$7);",
-           7, NULL);
-
-  /* Used in #postgres_update_denomination_balance() */
-  PREPARE ("denomination_pending_update",
-           "UPDATE denomination_pending SET"
-           " denom_balance_val=$1"
-           ",denom_balance_frac=$2"
-           ",denom_balance_curr=$3"
-           ",denom_risk_val=$4"
-           ",denom_risk_frac=$5"
-           ",denom_risk_curr=$6"
-           " WHERE denom_pub_hash=$7",
-           7, NULL);
-
-  /* Used in #postgres_get_denomination_balance() */
-  PREPARE ("denomination_pending_select",
-           "SELECT"
-           " denom_balance_val"
-           ",denom_balance_frac"
-           ",denom_balance_curr"
-           ",denom_risk_val"
-           ",denom_risk_frac"
-           ",denom_risk_curr"
-           " FROM denomination_pending"
-           " WHERE denom_pub_hash=$1",
-           1, NULL);
-
-  /* Used in #postgres_insert_balance_summary() */
-  PREPARE ("balance_summary_insert",
-           "INSERT INTO balance_summary "
-          "(master_pub"
-          ",denom_balance_val"
-           ",denom_balance_frac"
-           ",denom_balance_curr"
-           ",deposit_fee_balance_val"
-           ",deposit_fee_balance_frac"
-           ",deposit_fee_balance_curr"
-           ",melt_fee_balance_val"
-           ",melt_fee_balance_frac"
-           ",melt_fee_balance_curr"
-           ",refund_fee_balance_val"
-           ",refund_fee_balance_frac"
-           ",refund_fee_balance_curr"
-          ",risk_val"
-           ",risk_frac"
-           ",risk_curr"
-           ") VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);",
-           16, NULL);
-
-  /* Used in #postgres_update_balance_summary() */
-  PREPARE ("balance_summary_update",
-           "UPDATE balance_summary SET"
-          " denom_balance_val=$1"
-           ",denom_balance_frac=$2"
-           ",denom_balance_curr=$3"
-           ",deposit_fee_balance_val=$4"
-           ",deposit_fee_balance_frac=$5"
-           ",deposit_fee_balance_curr=$6"
-           ",melt_fee_balance_val=$7"
-           ",melt_fee_balance_frac=$8"
-           ",melt_fee_balance_curr=$9"
-           ",refund_fee_balance_val=$10"
-           ",refund_fee_balance_frac=$11"
-           ",refund_fee_balance_curr=$12"
-          ",risk_val=$13"
-           ",risk_frac=$14"
-           ",risk_curr=$15"
-           " WHERE master_pub=$16;",
-           16, NULL);
-
-  /* Used in #postgres_get_balance_summary() */
-  PREPARE ("balance_summary_select",
-           "SELECT"
-          " denom_balance_val"
-           ",denom_balance_frac"
-           ",denom_balance_curr"
-           ",deposit_fee_balance_val"
-           ",deposit_fee_balance_frac"
-           ",deposit_fee_balance_curr"
-           ",melt_fee_balance_val"
-           ",melt_fee_balance_frac"
-           ",melt_fee_balance_curr"
-           ",refund_fee_balance_val"
-           ",refund_fee_balance_frac"
-           ",refund_fee_balance_curr"
-          ",risk_val"
-           ",risk_frac"
-           ",risk_curr"
-           " FROM balance_summary"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_historic_denom_revenue() */
-  PREPARE ("historic_denomination_revenue_insert",
-           "INSERT INTO historic_denomination_revenue"
-          "(master_pub"
-          ",denom_pub_hash"
-          ",revenue_timestamp"
-          ",revenue_balance_val"
-           ",revenue_balance_frac"
-           ",revenue_balance_curr"
-           ") VALUES ($1,$2,$3,$4,$5,$6);",
-           6, NULL);
-
-  /* Used in #postgres_select_historic_denom_revenue() */
-  PREPARE ("historic_denomination_revenue_select",
-           "SELECT"
-          " denom_pub_hash"
-          ",revenue_timestamp"
-          ",revenue_balance_val"
-           ",revenue_balance_frac"
-           ",revenue_balance_curr"
-           " FROM historic_denomination_revenue"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_historic_losses() */
-  PREPARE ("historic_losses_insert",
-           "INSERT INTO historic_losses"
-          "(master_pub"
-          ",denom_pub_hash"
-          ",loss_timestamp"
-          ",loss_balance_val"
-           ",loss_balance_frac"
-           ",loss_balance_curr"
-           ") VALUES ($1,$2,$3,$4,$5,$6);",
-           6, NULL);
-
-  /* Used in #postgres_select_historic_losses() */
-  PREPARE ("historic_losses_select",
-           "SELECT"
-          " denom_pub_hash"
-          ",loss_timestamp"
-          ",loss_balance_val"
-           ",loss_balance_frac"
-           ",loss_balance_curr"
-           " FROM historic_losses"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_historic_reserve_revenue() */
-  PREPARE ("historic_reserve_summary_insert",
-           "INSERT INTO historic_reserve_summary"
-          "(master_pub"
-          ",start_date"
-          ",end_date"
-          ",reserve_profits_val"
-           ",reserve_profits_frac"
-           ",reserve_profits_curr"
-           ") VALUES ($1,$2,$3,$4,$5,$6);",
-           6, NULL);
-
-  /* Used in #postgres_select_historic_reserve_revenue() */
-  PREPARE ("historic_reserve_summary_select",
-           "SELECT"
-          " start_date"
-          ",end_date"
-          ",reserve_profits_val"
-           ",reserve_profits_frac"
-           ",reserve_profits_curr"
-           " FROM historic_reserve_summary"
-           " WHERE master_pub=$1;",
-           1, NULL);
-
-  /* Used in #postgres_insert_predicted_result() */
-  PREPARE ("predicted_result_insert",
-           "INSERT INTO predicted_result"
-          "(master_pub"
-          ",balance_val"
-           ",balance_frac"
-           ",balance_curr"
-           ") VALUES ($1,$2,$3,$4);",
-           4, NULL);
-
-  /* Used in #postgres_update_predicted_result() */
-  PREPARE ("predicted_result_update",
-           "UPDATE predicted_result SET"
-          " balance_val=$1"
-           ",balance_frac=$2"
-           ",balance_curr=$3"
-           " WHERE master_pub=$4;",
-           4, NULL);
-
-  /* Used in #postgres_get_predicted_balance() */
-  PREPARE ("predicted_result_select",
-           "SELECT"
-          " balance_val"
-           ",balance_frac"
-           ",balance_curr"
-           " FROM predicted_result"
-           " WHERE master_pub=$1;",
-           1, NULL);
+  struct GNUNET_PQ_PreparedStatement ps[] = {
+    /* used in #postgres_commit */
+    GNUNET_PQ_make_prepare ("do_commit",
+                            "COMMIT",
+                            0),
+    /* Used in #postgres_insert_denomination_info() */
+    GNUNET_PQ_make_prepare ("auditor_denominations_insert",
+                           "INSERT INTO auditor_denominations "
+                           "(denom_pub_hash"
+                           ",master_pub"
+                           ",valid_from"
+                           ",expire_withdraw"
+                           ",expire_deposit"
+                           ",expire_legal"
+                           ",coin_val"
+                           ",coin_frac"
+                           ",coin_curr"
+                           ",fee_withdraw_val"
+                           ",fee_withdraw_frac"
+                           ",fee_withdraw_curr"
+                           ",fee_deposit_val"
+                           ",fee_deposit_frac"
+                           ",fee_deposit_curr"
+                           ",fee_refresh_val"
+                           ",fee_refresh_frac"
+                           ",fee_refresh_curr"
+                           ",fee_refund_val"
+                           ",fee_refund_frac"
+                           ",fee_refund_curr"
+                           ") VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);",
+                           21),
+    /* Used in #postgres_insert_denomination_info() */
+    GNUNET_PQ_make_prepare ("auditor_denominations_select",
+                           "SELECT"
+                           " denom_pub_hash"
+                           ",valid_from"
+                           ",expire_withdraw"
+                           ",expire_deposit"
+                           ",expire_legal"
+                           ",coin_val"
+                           ",coin_frac"
+                           ",coin_curr"
+                           ",fee_withdraw_val"
+                           ",fee_withdraw_frac"
+                           ",fee_withdraw_curr"
+                           ",fee_deposit_val"
+                           ",fee_deposit_frac"
+                           ",fee_deposit_curr"
+                           ",fee_refresh_val"
+                           ",fee_refresh_frac"
+                           ",fee_refresh_curr"
+                           ",fee_refund_val"
+                           ",fee_refund_frac"
+                           ",fee_refund_curr"
+                           " FROM auditor_denominations"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_auditor_progress() */
+    GNUNET_PQ_make_prepare ("auditor_progress_insert",
+                           "INSERT INTO auditor_progress "
+                           "(master_pub"
+                           ",last_reserve_in_serial_id"
+                           ",last_reserve_out_serial_id"
+                           ",last_reserve_payback_serial_id"
+                           ",last_reserve_close_serial_id"
+                           ",last_withdraw_serial_id"
+                           ",last_deposit_serial_id"
+                           ",last_melt_serial_id"
+                           ",last_refund_serial_id"
+                           ",last_wire_out_serial_id"
+                           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
+                           10),
+    /* Used in #postgres_update_auditor_progress() */
+    GNUNET_PQ_make_prepare ("auditor_progress_update",
+                           "UPDATE auditor_progress SET "
+                           " last_reserve_in_serial_id=$1"
+                           ",last_reserve_out_serial_id=$2"
+                           ",last_reserve_payback_serial_id=$3"
+                           ",last_reserve_close_serial_id=$4"
+                           ",last_withdraw_serial_id=$5"
+                           ",last_deposit_serial_id=$6"
+                           ",last_melt_serial_id=$7"
+                           ",last_refund_serial_id=$8"
+                           ",last_wire_out_serial_id=$9"
+                           " WHERE master_pub=$10",
+                           10),
+    /* Used in #postgres_get_auditor_progress() */
+    GNUNET_PQ_make_prepare ("auditor_progress_select",
+                           "SELECT"
+                           " last_reserve_in_serial_id"
+                           ",last_reserve_out_serial_id"
+                           ",last_reserve_payback_serial_id"
+                           ",last_reserve_close_serial_id"
+                           ",last_withdraw_serial_id"
+                           ",last_deposit_serial_id"
+                           ",last_melt_serial_id"
+                           ",last_refund_serial_id"
+                           ",last_wire_out_serial_id"
+                           " FROM auditor_progress"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_reserve_info() */
+    GNUNET_PQ_make_prepare ("auditor_reserves_insert",
+                           "INSERT INTO auditor_reserves "
+                           "(reserve_pub"
+                           ",master_pub"
+                           ",reserve_balance_val"
+                           ",reserve_balance_frac"
+                           ",reserve_balance_curr"
+                           ",withdraw_fee_balance_val"
+                           ",withdraw_fee_balance_frac"
+                           ",withdraw_fee_balance_curr"
+                           ",expiration_date"
+                           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
+                           9),
+    /* Used in #postgres_update_reserve_info() */
+    GNUNET_PQ_make_prepare ("auditor_reserves_update",
+                           "UPDATE auditor_reserves SET"
+                           " reserve_balance_val=$1"
+                           ",reserve_balance_frac=$2"
+                           ",reserve_balance_curr=$3"
+                           ",withdraw_fee_balance_val=$4"
+                           ",withdraw_fee_balance_frac=$5"
+                           ",withdraw_fee_balance_curr=$6"
+                           ",expiration_date=$7"
+                           " WHERE reserve_pub=$8 AND master_pub=$9;",
+                           9),
+    /* Used in #postgres_get_reserve_info() */
+    GNUNET_PQ_make_prepare ("auditor_reserves_select",
+                           "SELECT"
+                           " reserve_balance_val"
+                           ",reserve_balance_frac"
+                           ",reserve_balance_curr"
+                           ",withdraw_fee_balance_val"
+                           ",withdraw_fee_balance_frac"
+                           ",withdraw_fee_balance_curr"
+                           ",expiration_date"
+                           ",auditor_reserves_rowid"
+                           " FROM auditor_reserves"
+                           " WHERE reserve_pub=$1 AND master_pub=$2;",
+                           2),
+    /* Used in #postgres_del_reserve_info() */
+    GNUNET_PQ_make_prepare ("auditor_reserves_delete",
+                           "DELETE"
+                           " FROM auditor_reserves"
+                           " WHERE reserve_pub=$1 AND master_pub=$2;",
+                           2),
+    /* Used in #postgres_insert_reserve_summary() */
+    GNUNET_PQ_make_prepare ("auditor_reserve_balance_insert",
+                           "INSERT INTO auditor_reserve_balance"
+                           "(master_pub"
+                           ",reserve_balance_val"
+                           ",reserve_balance_frac"
+                           ",reserve_balance_curr"
+                           ",withdraw_fee_balance_val"
+                           ",withdraw_fee_balance_frac"
+                           ",withdraw_fee_balance_curr"
+                           ") VALUES ($1,$2,$3,$4,$5,$6,$7)",
+                           7),
+    /* Used in #postgres_update_reserve_summary() */
+    GNUNET_PQ_make_prepare ("auditor_reserve_balance_update",
+                           "UPDATE auditor_reserve_balance SET"
+                           " reserve_balance_val=$1"
+                           ",reserve_balance_frac=$2"
+                           ",reserve_balance_curr=$3"
+                           ",withdraw_fee_balance_val=$4"
+                           ",withdraw_fee_balance_frac=$5"
+                           ",withdraw_fee_balance_curr=$6"
+                           " WHERE master_pub=$7;",
+                           7),
+    /* Used in #postgres_get_reserve_summary() */
+    GNUNET_PQ_make_prepare ("auditor_reserve_balance_select",
+                           "SELECT"
+                           " reserve_balance_val"
+                           ",reserve_balance_frac"
+                           ",reserve_balance_curr"
+                           ",withdraw_fee_balance_val"
+                           ",withdraw_fee_balance_frac"
+                           ",withdraw_fee_balance_curr"
+                           " FROM auditor_reserve_balance"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_wire_fee_summary() */
+    GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_insert",
+                           "INSERT INTO auditor_wire_fee_balance"
+                           "(master_pub"
+                           ",wire_fee_balance_val"
+                           ",wire_fee_balance_frac"
+                           ",wire_fee_balance_curr"
+                           ") VALUES ($1,$2,$3,$4)",
+                           4),
+    /* Used in #postgres_update_wire_fee_summary() */
+    GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_update",
+                           "UPDATE auditor_wire_fee_balance SET"
+                           " wire_fee_balance_val=$1"
+                           ",wire_fee_balance_frac=$2"
+                           ",wire_fee_balance_curr=$3"
+                           " WHERE master_pub=$4;",
+                           4),
+    /* Used in #postgres_get_wire_fee_summary() */
+    GNUNET_PQ_make_prepare ("auditor_wire_fee_balance_select",
+                           "SELECT"
+                           " wire_fee_balance_val"
+                           ",wire_fee_balance_frac"
+                           ",wire_fee_balance_curr"
+                           " FROM auditor_wire_fee_balance"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_denomination_balance() */
+    GNUNET_PQ_make_prepare ("denomination_pending_insert",
+                           "INSERT INTO denomination_pending "
+                           "(denom_pub_hash"
+                           ",denom_balance_val"
+                           ",denom_balance_frac"
+                           ",denom_balance_curr"
+                           ",denom_risk_val"
+                           ",denom_risk_frac"
+                           ",denom_risk_curr"
+                           ") VALUES ($1,$2,$3,$4,$5,$6,$7);",
+                           7),    
+    /* Used in #postgres_update_denomination_balance() */
+    GNUNET_PQ_make_prepare ("denomination_pending_update",
+                           "UPDATE denomination_pending SET"
+                           " denom_balance_val=$1"
+                           ",denom_balance_frac=$2"
+                           ",denom_balance_curr=$3"
+                           ",denom_risk_val=$4"
+                           ",denom_risk_frac=$5"
+                           ",denom_risk_curr=$6"
+                           " WHERE denom_pub_hash=$7",
+                           7),    
+    /* Used in #postgres_get_denomination_balance() */
+    GNUNET_PQ_make_prepare ("denomination_pending_select",
+                           "SELECT"
+                           " denom_balance_val"
+                           ",denom_balance_frac"
+                           ",denom_balance_curr"
+                           ",denom_risk_val"
+                           ",denom_risk_frac"
+                           ",denom_risk_curr"
+                           " FROM denomination_pending"
+                           " WHERE denom_pub_hash=$1",
+                           1),
+    /* Used in #postgres_insert_balance_summary() */
+    GNUNET_PQ_make_prepare ("balance_summary_insert",
+                           "INSERT INTO balance_summary "
+                           "(master_pub"
+                           ",denom_balance_val"
+                           ",denom_balance_frac"
+                           ",denom_balance_curr"
+                           ",deposit_fee_balance_val"
+                           ",deposit_fee_balance_frac"
+                           ",deposit_fee_balance_curr"
+                           ",melt_fee_balance_val"
+                           ",melt_fee_balance_frac"
+                           ",melt_fee_balance_curr"
+                           ",refund_fee_balance_val"
+                           ",refund_fee_balance_frac"
+                           ",refund_fee_balance_curr"
+                           ",risk_val"
+                           ",risk_frac"
+                           ",risk_curr"
+                           ") VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);",
+                           16),
+    /* Used in #postgres_update_balance_summary() */
+    GNUNET_PQ_make_prepare ("balance_summary_update",
+                           "UPDATE balance_summary SET"
+                           " denom_balance_val=$1"
+                           ",denom_balance_frac=$2"
+                           ",denom_balance_curr=$3"
+                           ",deposit_fee_balance_val=$4"
+                           ",deposit_fee_balance_frac=$5"
+                           ",deposit_fee_balance_curr=$6"
+                           ",melt_fee_balance_val=$7"
+                           ",melt_fee_balance_frac=$8"
+                           ",melt_fee_balance_curr=$9"
+                           ",refund_fee_balance_val=$10"
+                           ",refund_fee_balance_frac=$11"
+                           ",refund_fee_balance_curr=$12"
+                           ",risk_val=$13"
+                           ",risk_frac=$14"
+                           ",risk_curr=$15"
+                           " WHERE master_pub=$16;",
+                           16),
+    /* Used in #postgres_get_balance_summary() */
+    GNUNET_PQ_make_prepare ("balance_summary_select",
+                           "SELECT"
+                           " denom_balance_val"
+                           ",denom_balance_frac"
+                           ",denom_balance_curr"
+                           ",deposit_fee_balance_val"
+                           ",deposit_fee_balance_frac"
+                           ",deposit_fee_balance_curr"
+                           ",melt_fee_balance_val"
+                           ",melt_fee_balance_frac"
+                           ",melt_fee_balance_curr"
+                           ",refund_fee_balance_val"
+                           ",refund_fee_balance_frac"
+                           ",refund_fee_balance_curr"
+                           ",risk_val"
+                           ",risk_frac"
+                           ",risk_curr"
+                           " FROM balance_summary"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_historic_denom_revenue() */
+    GNUNET_PQ_make_prepare ("historic_denomination_revenue_insert",
+                           "INSERT INTO historic_denomination_revenue"
+                           "(master_pub"
+                           ",denom_pub_hash"
+                           ",revenue_timestamp"
+                           ",revenue_balance_val"
+                           ",revenue_balance_frac"
+                           ",revenue_balance_curr"
+                           ") VALUES ($1,$2,$3,$4,$5,$6);",
+                           6),
+    /* Used in #postgres_select_historic_denom_revenue() */
+    GNUNET_PQ_make_prepare ("historic_denomination_revenue_select",
+                           "SELECT"
+                           " denom_pub_hash"
+                           ",revenue_timestamp"
+                           ",revenue_balance_val"
+                           ",revenue_balance_frac"
+                           ",revenue_balance_curr"
+                           " FROM historic_denomination_revenue"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_historic_losses() */
+    GNUNET_PQ_make_prepare ("historic_losses_insert",
+                           "INSERT INTO historic_losses"
+                           "(master_pub"
+                           ",denom_pub_hash"
+                           ",loss_timestamp"
+                           ",loss_balance_val"
+                           ",loss_balance_frac"
+                           ",loss_balance_curr"
+                           ") VALUES ($1,$2,$3,$4,$5,$6);",
+                           6),
+    /* Used in #postgres_select_historic_losses() */
+    GNUNET_PQ_make_prepare ("historic_losses_select",
+                           "SELECT"
+                           " denom_pub_hash"
+                           ",loss_timestamp"
+                           ",loss_balance_val"
+                           ",loss_balance_frac"
+                           ",loss_balance_curr"
+                           " FROM historic_losses"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_historic_reserve_revenue() */
+    GNUNET_PQ_make_prepare ("historic_reserve_summary_insert",
+                           "INSERT INTO historic_reserve_summary"
+                           "(master_pub"
+                           ",start_date"
+                           ",end_date"
+                           ",reserve_profits_val"
+                           ",reserve_profits_frac"
+                           ",reserve_profits_curr"
+                           ") VALUES ($1,$2,$3,$4,$5,$6);",
+                           6),    
+    /* Used in #postgres_select_historic_reserve_revenue() */
+    GNUNET_PQ_make_prepare ("historic_reserve_summary_select",
+                           "SELECT"
+                           " start_date"
+                           ",end_date"
+                           ",reserve_profits_val"
+                           ",reserve_profits_frac"
+                           ",reserve_profits_curr"
+                           " FROM historic_reserve_summary"
+                           " WHERE master_pub=$1;",
+                           1),
+    /* Used in #postgres_insert_predicted_result() */
+    GNUNET_PQ_make_prepare ("predicted_result_insert",
+                           "INSERT INTO predicted_result"
+                           "(master_pub"
+                           ",balance_val"
+                           ",balance_frac"
+                           ",balance_curr"
+                           ") VALUES ($1,$2,$3,$4);",
+                           4),
+    /* Used in #postgres_update_predicted_result() */
+    GNUNET_PQ_make_prepare ("predicted_result_update",
+                           "UPDATE predicted_result SET"
+                           " balance_val=$1"
+                           ",balance_frac=$2"
+                           ",balance_curr=$3"
+                           " WHERE master_pub=$4;",
+                           4),
+    /* Used in #postgres_get_predicted_balance() */
+    GNUNET_PQ_make_prepare ("predicted_result_select",
+                           "SELECT"
+                           " balance_val"
+                           ",balance_frac"
+                           ",balance_curr"
+                           " FROM predicted_result"
+                           " WHERE master_pub=$1;",
+                           1),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
 
-  return GNUNET_OK;
-#undef PREPARE
+  return GNUNET_PQ_prepare_statements (db_conn,
+                                       ps);
 }
 
 
@@ -1026,7 +959,6 @@ postgres_start (void *cls,
     PQclear (result);
     return GNUNET_SYSERR;
   }
-
   PQclear (result);
   return GNUNET_OK;
 }
@@ -1058,49 +990,19 @@ postgres_rollback (void *cls,
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @param session the database connection
- * @return #GNUNET_OK on success
+ * @return transaction status code
  */
-static int
+enum GNUNET_DB_QueryStatus
 postgres_commit (void *cls,
                  struct TALER_AUDITORDB_Session *session)
 {
-  PGresult *result;
-
-  result = PQexec (session->conn,
-                   "COMMIT");
-  if (PGRES_COMMAND_OK !=
-      PQresultStatus (result))
-  {
-    const char *sqlstate;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_end
+  };
 
-    sqlstate = PQresultErrorField (result,
-                                   PG_DIAG_SQLSTATE);
-    if (NULL == sqlstate)
-    {
-      /* very unexpected... */
-      GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-    /* 40P01: deadlock, 40001: serialization failure */
-    if ( (0 == strcmp (sqlstate,
-                       "40P01")) ||
-         (0 == strcmp (sqlstate,
-                       "40001")) )
-    {
-      /* These two can be retried and have a fair chance of working
-         the next time */
-      PQclear (result);
-      return GNUNET_NO;
-    }
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-         "Database commit failure: %s\n",
-         sqlstate);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                             "do_commit",
+                                             params);
 }
 
 
@@ -1122,7 +1024,7 @@ postgres_gc (void *cls)
     GNUNET_PQ_query_param_end
   };
   PGconn *conn;
-  PGresult *result;
+  enum GNUNET_DB_QueryStatus qs;
 
   now = GNUNET_TIME_absolute_get ();
   conn = connect_to_postgres (pc);
@@ -1135,17 +1037,15 @@ postgres_gc (void *cls)
     return GNUNET_SYSERR;
   }
   /* FIXME: this is obviously not going to be this easy... */
-  result = GNUNET_PQ_exec_prepared (conn,
-                                    "gc_auditor",
-                                    params_time);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
+  qs = GNUNET_PQ_eval_prepared_non_select (conn,
+                                          "gc_auditor",
+                                          params_time);
+  if (0 > qs)
   {
-    BREAK_DB_ERR (result);
-    PQclear (result);
+    GNUNET_break (0);
     PQfinish (conn);
     return GNUNET_SYSERR;
   }
-  PQclear (result);
   PQfinish (conn);
   return GNUNET_OK;
 }
@@ -1194,7 +1094,6 @@ postgres_insert_denomination_info (void *cls,
   GNUNET_assert (GNUNET_YES ==
                  TALER_amount_cmp_currency_nbo (&issue->value,
                                                &issue->fee_refund));
-
   return GNUNET_PQ_eval_prepared_non_select (session->conn,
                                             "auditor_denominations_insert",
                                             params);
@@ -1202,52 +1101,54 @@ postgres_insert_denomination_info (void *cls,
 
 
 /**
- * Get information about denomination keys of a particular exchange.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param session connection to use
- * @param master_pub master public key of the exchange
- * @param cb function to call with the results
- * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * Closure for #denomination_info_cb().
  */
-static int
-postgres_select_denomination_info (void *cls,
-                                   struct TALER_AUDITORDB_Session *session,
-                                   const struct TALER_MasterPublicKeyP 
*master_pub,
-                                   
TALER_AUDITORDB_DenominationInfoDataCallback cb,
-                                   void *cb_cls)
+struct DenominationInfoContext
 {
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (master_pub),
-    GNUNET_PQ_query_param_end
-  };
-  PGresult *result;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_denominations_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
+  /**
+   * Master public key that is being used.
+   */
+  const struct TALER_MasterPublicKeyP *master_pub;
+  
+  /**
+   * Function to call for each denomination.
+   */
+  TALER_AUDITORDB_DenominationInfoDataCallback cb;
 
-  int ret = GNUNET_OK;
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_select_denomination_info() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i = 0; i < nrows; i++)
-  {
-    struct TALER_DenominationKeyValidityPS issue = { .master = *master_pub };
+  /**
+   * Closure for @e cb
+   */
+  void *cb_cls;
+  
+  /**
+   * Query status to return.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
 
+
+/**
+ * Helper function for #postgres_select_denomination_info().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DenominationInfoContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+denomination_info_cb (void *cls,
+                     PGresult *result,
+                     unsigned int num_results)
+{
+  struct DenominationInfoContext *dic = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    struct TALER_DenominationKeyValidityPS issue = {
+      .master = *dic->master_pub
+    };
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", 
&issue.denom_hash),
       GNUNET_PQ_result_spec_auto_from_type ("valid_from", &issue.start),
@@ -1261,26 +1162,62 @@ postgres_select_denomination_info (void *cls,
       TALER_PQ_result_spec_amount_nbo ("fee_refund", &issue.fee_refund),
       GNUNET_PQ_result_spec_end
     };
+
     if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result, rs, 0))
+        GNUNET_PQ_extract_result (result,
+                                 rs,
+                                 i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-    ret = cb (cb_cls,
-              &issue);
-    switch (ret)
-    {
-    case GNUNET_OK:
-      break;
-
-    default:
-      i = nrows;
+      dic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
     }
+    dic->qs = i + 1;
+    if (GNUNET_OK !=
+       dic->cb (dic->cb_cls,
+                &issue))
+      return;
   }
-  PQclear (result);
-  return ret;
+}
+
+
+/**
+ * Get information about denomination keys of a particular exchange.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param session connection to use
+ * @param master_pub master public key of the exchange
+ * @param cb function to call with the results
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_denomination_info (void *cls,
+                                   struct TALER_AUDITORDB_Session *session,
+                                   const struct TALER_MasterPublicKeyP 
*master_pub,
+                                   
TALER_AUDITORDB_DenominationInfoDataCallback cb,
+                                   void *cb_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (master_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct DenominationInfoContext dic = {
+    .master_pub = master_pub,
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "auditor_denominations_select",
+                                            params,
+                                            &denomination_info_cb,
+                                            &dic);
+  if (qs > 0)
+    return dic.qs;
+  GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+  return qs;
 }
 
 
@@ -1292,15 +1229,14 @@ postgres_select_denomination_info (void *cls,
  * @param session connection to use
  * @param master_pub master key of the exchange
  * @param pp where is the auditor in processing
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_auditor_progress (void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
                                   const struct TALER_AUDITORDB_ProgressPoint 
*pp)
 {
-  PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
@@ -1314,22 +1250,10 @@ postgres_insert_auditor_progress (void *cls,
     GNUNET_PQ_query_param_uint64 (&pp->last_wire_out_serial_id),
     GNUNET_PQ_query_param_end
   };
-  int ret;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_progress_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_progress_insert",
+                                            params);
 }
 
 
@@ -1341,15 +1265,14 @@ postgres_insert_auditor_progress (void *cls,
  * @param session connection to use
  * @param master_pub master key of the exchange
  * @param pp where is the auditor in processing
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-int
+static enum GNUNET_DB_QueryStatus
 postgres_update_auditor_progress (void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
                                   const struct TALER_AUDITORDB_ProgressPoint 
*pp)
 {
-  PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_in_serial_id),
     GNUNET_PQ_query_param_uint64 (&pp->last_reserve_out_serial_id),
@@ -1363,22 +1286,10 @@ postgres_update_auditor_progress (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  int ret;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_progress_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_progress_update",
+                                            params);
 }
 
 
@@ -1389,10 +1300,9 @@ postgres_update_auditor_progress (void *cls,
  * @param session connection to use
  * @param master_pub master key of the exchange
  * @param[out] pp set to where the auditor is in processing
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure;
- *         #GNUNET_NO if we have no records for the @a master_pub
+ * @return transaction status code
  */
-int
+static enum GNUNET_DB_QueryStatus
 postgres_get_auditor_progress (void *cls,
                                struct TALER_AUDITORDB_Session *session,
                                const struct TALER_MasterPublicKeyP *master_pub,
@@ -1402,7 +1312,6 @@ postgres_get_auditor_progress (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id",
                                   &pp->last_reserve_in_serial_id),
@@ -1425,38 +1334,10 @@ postgres_get_auditor_progress (void *cls,
     GNUNET_PQ_result_spec_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_progress_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_auditor_progress() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result,
-                                rs,
-                                0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "auditor_progress_select",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -1472,9 +1353,9 @@ postgres_get_auditor_progress (void *cls,
  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
  *                             due to withdrawals from this reserve
  * @param expiration_date expiration date of the reserve
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_reserve_info (void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct TALER_ReservePublicKeyP 
*reserve_pub,
@@ -1483,8 +1364,6 @@ postgres_insert_reserve_info (void *cls,
                               const struct TALER_Amount *withdraw_fee_balance,
                               struct GNUNET_TIME_Absolute expiration_date)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
     GNUNET_PQ_query_param_auto_from_type (master_pub),
@@ -1498,20 +1377,9 @@ postgres_insert_reserve_info (void *cls,
                  TALER_amount_cmp_currency (reserve_balance,
                                             withdraw_fee_balance));
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_reserves_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_reserves_insert",
+                                            params);
 }
 
 
@@ -1527,9 +1395,9 @@ postgres_insert_reserve_info (void *cls,
  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
  *                             due to withdrawals from this reserve
  * @param expiration_date expiration date of the reserve
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_update_reserve_info (void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct TALER_ReservePublicKeyP 
*reserve_pub,
@@ -1538,8 +1406,6 @@ postgres_update_reserve_info (void *cls,
                               const struct TALER_Amount *withdraw_fee_balance,
                               struct GNUNET_TIME_Absolute expiration_date)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_amount (reserve_balance),
     TALER_PQ_query_param_amount (withdraw_fee_balance),
@@ -1553,20 +1419,9 @@ postgres_update_reserve_info (void *cls,
                  TALER_amount_cmp_currency (reserve_balance,
                                             withdraw_fee_balance));
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_reserves_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_reserves_update",
+                                            params);
 }
 
 
@@ -1577,10 +1432,9 @@ postgres_update_reserve_info (void *cls,
  * @param session connection to use
  * @param reserve_pub public key of the reserve
  * @param master_pub master public key of the exchange
- * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
- *         record about this reserve; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_del_reserve_info (void *cls,
                            struct TALER_AUDITORDB_Session *session,
                            const struct TALER_ReservePublicKeyP *reserve_pub,
@@ -1591,23 +1445,10 @@ postgres_del_reserve_info (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  int ret;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_reserves_delete",
-                                    params);
-  ret = PQresultStatus (result);
-  if (PGRES_COMMAND_OK != ret)
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (0 == strcmp ("0",
-                   PQcmdTuples (result)))
-    return GNUNET_NO;
-  return GNUNET_OK;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_reserves_delete",
+                                            params);
 }
 
 
@@ -1623,10 +1464,9 @@ postgres_del_reserve_info (void *cls,
  * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
  *                             due to withdrawals from this reserve
  * @param[out] expiration_date expiration date of the reserve
- * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
- *         record about this reserve; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_reserve_info (void *cls,
                            struct TALER_AUDITORDB_Session *session,
                            const struct TALER_ReservePublicKeyP *reserve_pub,
@@ -1638,31 +1478,10 @@ postgres_get_reserve_info (void *cls,
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_reserves_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_reserve_info() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     TALER_PQ_result_spec_amount ("reserve_balance", reserve_balance),
     TALER_PQ_result_spec_amount ("withdraw_fee_balance", withdraw_fee_balance),
@@ -1670,15 +1489,11 @@ postgres_get_reserve_info (void *cls,
     GNUNET_PQ_result_spec_uint64 ("auditor_reserves_rowid", rowid),
     GNUNET_PQ_result_spec_end
   };
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result, rs, 0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "auditor_reserves_select",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -1692,17 +1507,15 @@ postgres_get_reserve_info (void *cls,
  * @param reserve_balance amount stored in the reserve
  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
  *                             due to withdrawals from this reserve
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_reserve_summary (void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct TALER_MasterPublicKeyP 
*master_pub,
                                  const struct TALER_Amount *reserve_balance,
                                  const struct TALER_Amount 
*withdraw_fee_balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     TALER_PQ_query_param_amount (reserve_balance),
@@ -1714,20 +1527,9 @@ postgres_insert_reserve_summary (void *cls,
                  TALER_amount_cmp_currency (reserve_balance,
                                             withdraw_fee_balance));
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_reserve_balance_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_reserve_balance_insert",
+                                            params);
 }
 
 
@@ -1741,17 +1543,15 @@ postgres_insert_reserve_summary (void *cls,
  * @param reserve_balance amount stored in the reserve
  * @param withdraw_fee_balance amount the exchange gained in withdraw fees
  *                             due to withdrawals from this reserve
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_update_reserve_summary (void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct TALER_MasterPublicKeyP 
*master_pub,
                                  const struct TALER_Amount *reserve_balance,
                                  const struct TALER_Amount 
*withdraw_fee_balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_amount (reserve_balance),
     TALER_PQ_query_param_amount (withdraw_fee_balance),
@@ -1759,20 +1559,9 @@ postgres_update_reserve_summary (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_reserve_balance_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_reserve_balance_update",
+                                            params);
 }
 
 
@@ -1785,10 +1574,9 @@ postgres_update_reserve_summary (void *cls,
  * @param[out] reserve_balance amount stored in the reserve
  * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
  *                             due to withdrawals from this reserve
- * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
- *         record about this exchange; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_reserve_summary (void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct TALER_MasterPublicKeyP *master_pub,
@@ -1799,47 +1587,18 @@ postgres_get_reserve_summary (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_reserve_balance_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_reserve_summary() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     TALER_PQ_result_spec_amount ("reserve_balance", reserve_balance),
     TALER_PQ_result_spec_amount ("withdraw_fee_balance", withdraw_fee_balance),
 
     GNUNET_PQ_result_spec_end
   };
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result, rs, 0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
-}
-
-
 
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  
"auditor_reserve_balance_select",
+                                                  params,
+                                                  rs);
+}
 
 
 /**
@@ -1850,36 +1609,23 @@ postgres_get_reserve_summary (void *cls,
  * @param session connection to use
  * @param master_pub master public key of the exchange
  * @param wire_fee_balance amount the exchange gained in wire fees
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_wire_fee_summary (void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
                                   const struct TALER_Amount *wire_fee_balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
-     TALER_PQ_query_param_amount (wire_fee_balance),
+    TALER_PQ_query_param_amount (wire_fee_balance),
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_wire_fee_balance_insert",
-                                    params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_wire_fee_balance_insert",
+                                            params);
 }
 
 
@@ -1891,36 +1637,23 @@ postgres_insert_wire_fee_summary (void *cls,
  * @param session connection to use
  * @param master_pub master public key of the exchange
  * @param wire_fee_balance amount the exchange gained in wire fees
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_update_wire_fee_summary (void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
                                   const struct TALER_Amount *wire_fee_balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_amount (wire_fee_balance),
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "auditor_wire_fee_balance_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "auditor_wire_fee_balance_update",
+                                            params);
 }
 
 
@@ -1931,10 +1664,9 @@ postgres_update_wire_fee_summary (void *cls,
  * @param session connection to use
  * @param master_pub master public key of the exchange
  * @param[out] wire_fee_balance set amount the exchange gained in wire fees
- * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
- *         record about this exchange; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_wire_fee_summary (void *cls,
                                struct TALER_AUDITORDB_Session *session,
                                const struct TALER_MasterPublicKeyP *master_pub,
@@ -1944,42 +1676,16 @@ postgres_get_wire_fee_summary (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "auditor_wire_fee_balance_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_wire_fee_summary() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     TALER_PQ_result_spec_amount ("wire_fee_balance", wire_fee_balance),
 
     GNUNET_PQ_result_spec_end
   };
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result, rs, 0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  
"auditor_wire_fee_balance_select",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -1992,17 +1698,15 @@ postgres_get_wire_fee_summary (void *cls,
  * @param denom_pub_hash hash of the denomination public key
  * @param denom_balance value of coins outstanding with this denomination key
  * @param denom_risk value of coins issued with this denomination key
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_denomination_balance (void *cls,
                                       struct TALER_AUDITORDB_Session *session,
                                       const struct GNUNET_HashCode 
*denom_pub_hash,
                                       const struct TALER_Amount *denom_balance,
                                       const struct TALER_Amount *denom_risk)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
     TALER_PQ_query_param_amount (denom_balance),
@@ -2010,20 +1714,9 @@ postgres_insert_denomination_balance (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "denomination_pending_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "denomination_pending_insert",
+                                            params);
 }
 
 
@@ -2036,17 +1729,15 @@ postgres_insert_denomination_balance (void *cls,
  * @param denom_pub_hash hash of the denomination public key
  * @param denom_balance value of coins outstanding with this denomination key
  * @param denom_risk value of coins issued with this denomination key
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_update_denomination_balance (void *cls,
                                       struct TALER_AUDITORDB_Session *session,
                                       const struct GNUNET_HashCode 
*denom_pub_hash,
                                       const struct TALER_Amount *denom_balance,
                                       const struct TALER_Amount *denom_risk)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_amount (denom_balance),
     TALER_PQ_query_param_amount (denom_risk),
@@ -2054,20 +1745,9 @@ postgres_update_denomination_balance (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "denomination_pending_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "denomination_pending_update",
+                                            params);
 }
 
 
@@ -2079,9 +1759,9 @@ postgres_update_denomination_balance (void *cls,
  * @param denom_pub_hash hash of the denomination public key
  * @param[out] denom_balance value of coins outstanding with this denomination 
key
  * @param[out] denom_risk value of coins issued with this denomination key
- * @return #GNUNET_OK on success; #GNUNET_NO if no record found, 
#GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_denomination_balance (void *cls,
                                    struct TALER_AUDITORDB_Session *session,
                                    const struct GNUNET_HashCode 
*denom_pub_hash,
@@ -2092,43 +1772,16 @@ postgres_get_denomination_balance (void *cls,
     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "denomination_pending_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_denomination_balance() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     TALER_PQ_result_spec_amount ("denom_balance", denom_balance),
     TALER_PQ_result_spec_amount ("denom_risk", denom_risk),
     GNUNET_PQ_result_spec_end
   };
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result, rs, 0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  
"denomination_pending_select",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -2144,9 +1797,9 @@ postgres_get_denomination_balance (void *cls,
  * @param melt_fee_balance total melt fees collected for this DK
  * @param refund_fee_balance total refund fees collected for this DK
  * @param risk maximum risk exposure of the exchange
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_balance_summary (void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2156,8 +1809,6 @@ postgres_insert_balance_summary (void *cls,
                                  const struct TALER_Amount *refund_fee_balance,
                                  const struct TALER_Amount *risk)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     TALER_PQ_query_param_amount (denom_balance),
@@ -2180,20 +1831,9 @@ postgres_insert_balance_summary (void *cls,
                  TALER_amount_cmp_currency (denom_balance,
                                             refund_fee_balance));
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "balance_summary_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "balance_summary_insert",
+                                            params);
 }
 
 
@@ -2209,9 +1849,9 @@ postgres_insert_balance_summary (void *cls,
  * @param melt_fee_balance total melt fees collected for this DK
  * @param refund_fee_balance total refund fees collected for this DK
  * @param risk maximum risk exposure of the exchange
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_update_balance_summary (void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2221,8 +1861,6 @@ postgres_update_balance_summary (void *cls,
                                  const struct TALER_Amount *refund_fee_balance,
                                  const struct TALER_Amount *risk)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_amount (denom_balance),
     TALER_PQ_query_param_amount (deposit_fee_balance),
@@ -2233,20 +1871,9 @@ postgres_update_balance_summary (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "balance_summary_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "balance_summary_update",
+                                            params);
 }
 
 
@@ -2261,10 +1888,9 @@ postgres_update_balance_summary (void *cls,
  * @param[out] melt_fee_balance total melt fees collected for this DK
  * @param[out] refund_fee_balance total refund fees collected for this DK
  * @param[out] risk maximum risk exposure of the exchange
- * @return #GNUNET_OK on success; #GNUNET_NO if there is no entry
- *           for this @a master_pub; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_balance_summary (void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct TALER_MasterPublicKeyP *master_pub,
@@ -2278,29 +1904,6 @@ postgres_get_balance_summary (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "balance_summary_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_balance_summary() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     TALER_PQ_result_spec_amount ("denom_balance", denom_balance),
     TALER_PQ_result_spec_amount ("deposit_fee_balance", deposit_fee_balance),
@@ -2309,15 +1912,11 @@ postgres_get_balance_summary (void *cls,
     TALER_PQ_result_spec_amount ("risk", risk),
     GNUNET_PQ_result_spec_end
   };
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result, rs, 0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "balance_summary_select",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -2333,9 +1932,9 @@ postgres_get_balance_summary (void *cls,
  * @param revenue_balance what was the total profit made from
  *                        deposit fees, melting fees, refresh fees
  *                        and coins that were never returned?
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_historic_denom_revenue (void *cls,
                                         struct TALER_AUDITORDB_Session 
*session,
                                         const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2343,8 +1942,6 @@ postgres_insert_historic_denom_revenue (void *cls,
                                         struct GNUNET_TIME_Absolute 
revenue_timestamp,
                                         const struct TALER_Amount 
*revenue_balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
@@ -2353,68 +1950,51 @@ postgres_insert_historic_denom_revenue (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "historic_denomination_revenue_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            
"historic_denomination_revenue_insert",
+                                            params);
 }
 
 
 /**
- * Obtain all of the historic denomination key revenue
- * of the given @a master_pub.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param session connection to use
- * @param master_pub master key of the exchange
- * @param cb function to call with the results
- * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ * Closure for #historic_denom_revenue_cb().
  */
-static int
-postgres_select_historic_denom_revenue (void *cls,
-                                        struct TALER_AUDITORDB_Session 
*session,
-                                        const struct TALER_MasterPublicKeyP 
*master_pub,
-                                        
TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,
-                                        void *cb_cls)
+struct HistoricDenomRevenueContext
 {
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (master_pub),
-    GNUNET_PQ_query_param_end
-  };
-  PGresult *result;
+  /**
+   * Function to call for each result.
+   */
+  TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "historic_denomination_revenue_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
 
-  int ret = GNUNET_OK;
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_select_historic_denom_revenue() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i = 0; i < nrows; i++)
+  /**
+   * Number of results processed.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #postgres_select_historic_denom_revenue().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct HistoricRevenueContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+historic_denom_revenue_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct HistoricDenomRevenueContext *hrc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
   {
     struct GNUNET_HashCode denom_pub_hash;
     struct GNUNET_TIME_Absolute revenue_timestamp;
@@ -2427,28 +2007,62 @@ postgres_select_historic_denom_revenue (void *cls,
     };
 
     if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result, rs, 0))
+        GNUNET_PQ_extract_result (result,
+                                 rs,
+                                 i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
     }
 
-    ret = cb (cb_cls,
-              &denom_pub_hash,
-              revenue_timestamp,
-              &revenue_balance);
-    switch (ret)
-    {
-    case GNUNET_OK:
+    hrc->qs = i + 1;
+    if (GNUNET_OK !=
+       hrc->cb (hrc->cb_cls,
+                &denom_pub_hash,
+                revenue_timestamp,
+                &revenue_balance))
       break;
-
-    default:
-      i = nrows;
-    }
   }
-  PQclear (result);
-  return ret;
+}
+
+
+/**
+ * Obtain all of the historic denomination key revenue
+ * of the given @a master_pub.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param session connection to use
+ * @param master_pub master key of the exchange
+ * @param cb function to call with the results
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_historic_denom_revenue (void *cls,
+                                        struct TALER_AUDITORDB_Session 
*session,
+                                        const struct TALER_MasterPublicKeyP 
*master_pub,
+                                        
TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,
+                                        void *cb_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (master_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct HistoricDenomRevenueContext hrc = {
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            
"historic_denomination_revenue_select",
+                                            params,
+                                            &historic_denom_revenue_cb,
+                                            &hrc);
+  if (qs <= 0)
+    return qs;
+  return hrc.qs;
 }
 
 
@@ -2465,9 +2079,9 @@ postgres_select_historic_denom_revenue (void *cls,
  * @param denom_pub_hash hash of the denomination key
  * @param loss_timestamp when did this profit get realized
  * @param loss_balance what was the total loss
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_historic_losses (void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2475,8 +2089,6 @@ postgres_insert_historic_losses (void *cls,
                                  struct GNUNET_TIME_Absolute loss_timestamp,
                                  const struct TALER_Amount *loss_balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
@@ -2485,20 +2097,79 @@ postgres_insert_historic_losses (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "historic_losses_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "historic_losses_insert",
+                                            params);
+}
+
+
+/**
+ * Closure for #losses_cb.
+ */
+struct LossContext
+{
+  /**
+   * Function to call for each result.
+   */
+  TALER_AUDITORDB_HistoricLossesDataCallback cb;
+
+  /** 
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+  /**
+   * Status code to return.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #postgres_select_historic_denom_revenue().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct HistoricRevenueContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+losses_cb (void *cls,
+          PGresult *result,
+          unsigned int num_results)
+{
+  struct LossContext *lctx = cls;
+  
+  for (unsigned int i = 0; i < num_results; i++)
   {
-    ret = GNUNET_OK;
+    struct GNUNET_HashCode denom_pub_hash;
+    struct GNUNET_TIME_Absolute loss_timestamp;
+    struct TALER_Amount loss_balance;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash),
+      GNUNET_PQ_result_spec_auto_from_type ("loss_timestamp", &loss_timestamp),
+      TALER_PQ_result_spec_amount ("loss_balance", &loss_balance),
+      GNUNET_PQ_result_spec_end
+    };
+    
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                 rs,
+                                 i))
+    {
+      GNUNET_break (0);
+      lctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    lctx->qs = i + 1;
+    if (GNUNET_OK !=
+       lctx->cb (lctx->cb_cls,
+                 &denom_pub_hash,
+                 loss_timestamp,
+                 &loss_balance))
+      break;
   }
-  PQclear (result);
-  return ret;
 }
 
 
@@ -2511,9 +2182,9 @@ postgres_insert_historic_losses (void *cls,
  * @param master_pub master key of the exchange
  * @param cb function to call with the results
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_select_historic_losses (void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2524,65 +2195,20 @@ postgres_select_historic_losses (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "historic_losses_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int ret = GNUNET_OK;
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_select_historic_losses() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i = 0; i < nrows; i++)
-  {
-    struct GNUNET_HashCode denom_pub_hash;
-    struct GNUNET_TIME_Absolute loss_timestamp;
-    struct TALER_Amount loss_balance;
-
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash),
-
-      GNUNET_PQ_result_spec_auto_from_type ("loss_timestamp", &loss_timestamp),
-
-      TALER_PQ_result_spec_amount ("loss_balance", &loss_balance),
-
-      GNUNET_PQ_result_spec_end
-    };
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result, rs, 0))
-    {
-      GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-    ret = cb (cb_cls,
-              &denom_pub_hash,
-              loss_timestamp,
-              &loss_balance);
-    switch (ret)
-    {
-    case GNUNET_OK:
-      break;
-
-    default:
-      i = nrows;
-    }
-  }
-  PQclear (result);
-  return ret;
+  struct LossContext lctx = {
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "historic_losses_select",
+                                            params,
+                                            &losses_cb,
+                                            &lctx);
+  if (qs <= 0)
+    return qs;
+  return lctx.qs;
 }
 
 
@@ -2595,9 +2221,9 @@ postgres_select_historic_losses (void *cls,
  * @param start_time beginning of aggregated time interval
  * @param end_time end of aggregated time interval
  * @param reserve_profits total profits made
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_historic_reserve_revenue (void *cls,
                                           struct TALER_AUDITORDB_Session 
*session,
                                           const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2605,8 +2231,6 @@ postgres_insert_historic_reserve_revenue (void *cls,
                                           struct GNUNET_TIME_Absolute end_time,
                                           const struct TALER_Amount 
*reserve_profits)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_auto_from_type (&start_time),
@@ -2615,100 +2239,117 @@ postgres_insert_historic_reserve_revenue (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "historic_reserve_summary_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "historic_reserve_summary_insert",
+                                            params);
 }
 
 
 /**
- * Return information about an exchange's historic revenue from reserves.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param session connection to use
- * @param master_pub master key of the exchange
- * @param cb function to call with results
- * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * Closure for #historic_reserve_revenue_cb().
  */
-static int
-postgres_select_historic_reserve_revenue (void *cls,
-                                          struct TALER_AUDITORDB_Session 
*session,
-                                          const struct TALER_MasterPublicKeyP 
*master_pub,
-                                          
TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,
-                                          void *cb_cls)
+struct HistoricReserveRevenueContext
 {
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (master_pub),
-    GNUNET_PQ_query_param_end
-  };
-  PGresult *result;
+  /**
+   * Function to call for each result.
+   */
+  TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "historic_reserve_summary_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
 
-  int ret = GNUNET_OK;
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_select_historic_reserve_revenue() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i = 0; i < nrows; i++)
+  /**
+   * Number of results processed.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #postgres_select_historic_reserve_revenue().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct HistoricRevenueContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+historic_reserve_revenue_cb (void *cls,
+                            PGresult *result,
+                            unsigned int num_results)
+{
+  struct HistoricReserveRevenueContext *hrc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
   {
     struct GNUNET_TIME_Absolute start_date;
     struct GNUNET_TIME_Absolute end_date;
     struct TALER_Amount reserve_profits;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("start_date", &start_date),
       GNUNET_PQ_result_spec_auto_from_type ("end_date", &end_date),
       TALER_PQ_result_spec_amount ("reserve_profits", &reserve_profits),
       GNUNET_PQ_result_spec_end
     };
+    
     if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result, rs, 0))
+        GNUNET_PQ_extract_result (result,
+                                 rs,
+                                 i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
     }
-    ret = cb (cb_cls,
-              start_date,
-              end_date,
-              &reserve_profits);
-    switch (ret)
-    {
-    case GNUNET_OK:
+    hrc->qs = i + 1;
+    if (GNUNET_OK !=
+       hrc->cb (hrc->cb_cls,
+                start_date,
+                end_date,
+                &reserve_profits))
       break;
-
-    default:
-      i = nrows;
-    }
   }
-  PQclear (result);
-  return ret;
+}
+
+
+/**
+ * Return information about an exchange's historic revenue from reserves.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param session connection to use
+ * @param master_pub master key of the exchange
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_historic_reserve_revenue (void *cls,
+                                          struct TALER_AUDITORDB_Session 
*session,
+                                          const struct TALER_MasterPublicKeyP 
*master_pub,
+                                          
TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,
+                                          void *cb_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (master_pub),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  struct HistoricReserveRevenueContext hrc = {
+    .cb = cb,
+    .cb_cls = cb_cls
+  };
+  
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "historic_reserve_summary_select",
+                                            params,
+                                            &historic_reserve_revenue_cb,
+                                            &hrc);
+  if (0 >= qs)
+    return qs;
+  return hrc.qs;
 }
 
 
@@ -2720,36 +2361,23 @@ postgres_select_historic_reserve_revenue (void *cls,
  * @param session connection to use
  * @param master_pub master key of the exchange
  * @param balance what the bank account balance of the exchange should show
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_predicted_result (void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
                                   const struct TALER_Amount *balance)
 {
-  PGresult *result;
-  int ret;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     TALER_PQ_query_param_amount (balance),
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "predicted_result_insert",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "predicted_result_insert",
+                                            params);
 }
 
 
@@ -2761,37 +2389,23 @@ postgres_insert_predicted_result (void *cls,
  * @param session connection to use
  * @param master_pub master key of the exchange
  * @param balance what the bank account balance of the exchange should show
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_update_predicted_result (void *cls,
                                   struct TALER_AUDITORDB_Session *session,
                                   const struct TALER_MasterPublicKeyP 
*master_pub,
                                   const struct TALER_Amount *balance)
 {
-  PGresult *result;
-  int ret;
-
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_amount (balance),
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "predicted_result_update",
-                                   params);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    ret = GNUNET_SYSERR;
-    BREAK_DB_ERR (result);
-  }
-  else
-  {
-    ret = GNUNET_OK;
-  }
-  PQclear (result);
-  return ret;
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "predicted_result_update",
+                                            params);
 }
 
 
@@ -2802,10 +2416,9 @@ postgres_update_predicted_result (void *cls,
  * @param session connection to use
  * @param master_pub master key of the exchange
  * @param[out] balance expected bank account balance of the exchange
- * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure;
- *         #GNUNET_NO if we have no records for the @a master_pub
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_predicted_balance (void *cls,
                                 struct TALER_AUDITORDB_Session *session,
                                 const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -2815,43 +2428,16 @@ postgres_get_predicted_balance (void *cls,
     GNUNET_PQ_query_param_auto_from_type (master_pub),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "predicted_result_select",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  int nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "postgres_get_predicted_balance() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     TALER_PQ_result_spec_amount ("balance", balance),
 
     GNUNET_PQ_result_spec_end
   };
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result, rs, 0))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "predicted_result_select",
+                                                  params,
+                                                  rs);
 }
 
 
diff --git a/src/auditordb/test_auditordb.c b/src/auditordb/test_auditordb.c
index 858e6bd..04c6d23 100644
--- a/src/auditordb/test_auditordb.c
+++ b/src/auditordb/test_auditordb.c
@@ -70,7 +70,9 @@ select_denomination_info_result (void *cls,
 {
   const struct TALER_DenominationKeyValidityPS *issue1 = cls;
 
-  if (0 != memcmp (issue1, issue2, sizeof (*issue2)))
+  if (0 != memcmp (issue1,
+                  issue2,
+                  sizeof (*issue2)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "select_denomination_info_result: issue does not match\n");
@@ -202,11 +204,11 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: select_denomination_info\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >=
           plugin->select_denomination_info (plugin->cls,
                                             session,
                                             &master_pub,
-                                            select_denomination_info_result,
+                                            &select_denomination_info_result,
                                             &issue));
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -229,7 +231,7 @@ run (void *cls)
     .last_wire_out_serial_id = 0
   };
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_auditor_progress (plugin->cls,
                                            session,
                                            &master_pub,
@@ -244,7 +246,7 @@ run (void *cls)
   pp.last_refund_serial_id++;
   pp.last_wire_out_serial_id++;
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_auditor_progress (plugin->cls,
                                            session,
                                            &master_pub,
@@ -253,7 +255,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: get_auditor_progress\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_auditor_progress (plugin->cls,
                                         session,
                                         &master_pub,
@@ -278,7 +280,7 @@ run (void *cls)
                  TALER_string_to_amount (CURRENCY ":23.456789",
                                          &withdraw_fee_balance));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_reserve_info (plugin->cls,
                                        session,
                                        &reserve_pub,
@@ -290,7 +292,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: update_reserve_info\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_reserve_info (plugin->cls,
                                        session,
                                        &reserve_pub,
@@ -302,7 +304,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: get_reserve_info\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_reserve_info (plugin->cls,
                                     session,
                                     &reserve_pub,
@@ -319,7 +321,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: insert_reserve_summary\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_reserve_summary (plugin->cls,
                                           session,
                                           &master_pub,
@@ -329,7 +331,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: update_reserve_summary\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_reserve_summary (plugin->cls,
                                           session,
                                           &master_pub,
@@ -342,22 +344,33 @@ run (void *cls)
   ZR_BLK (&reserve_balance2);
   ZR_BLK (&withdraw_fee_balance2);
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_reserve_summary (plugin->cls,
                                        session,
                                        &master_pub,
                                        &reserve_balance2,
                                        &withdraw_fee_balance2));
 
-  FAILIF (0 != memcmp (&reserve_balance2, &reserve_balance, sizeof 
(reserve_balance))
-          || 0 != memcmp (&withdraw_fee_balance2, &withdraw_fee_balance, 
sizeof (withdraw_fee_balance)));
-
+  FAILIF ( (0 != memcmp (&reserve_balance2,
+                        &reserve_balance,
+                        sizeof (reserve_balance)) ||
+           (0 != memcmp (&withdraw_fee_balance2,
+                         &withdraw_fee_balance,
+                         sizeof (withdraw_fee_balance))) ) );
+          
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: insert_denomination_balance\n");
 
-  struct TALER_Amount denom_balance, deposit_fee_balance, melt_fee_balance, 
refund_fee_balance;
-  struct TALER_Amount denom_balance2, deposit_fee_balance2, melt_fee_balance2, 
refund_fee_balance2;
-  struct TALER_Amount rbalance, rbalance2;
+  struct TALER_Amount denom_balance;
+  struct TALER_Amount deposit_fee_balance;
+  struct TALER_Amount melt_fee_balance;
+  struct TALER_Amount refund_fee_balance;
+  struct TALER_Amount denom_balance2;
+  struct TALER_Amount deposit_fee_balance2;
+  struct TALER_Amount melt_fee_balance2;
+  struct TALER_Amount refund_fee_balance2;
+  struct TALER_Amount rbalance;
+  struct TALER_Amount rbalance2;
 
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (CURRENCY ":12.345678",
@@ -375,7 +388,7 @@ run (void *cls)
                  TALER_string_to_amount (CURRENCY ":13.57986",
                                          &rbalance));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_denomination_balance (plugin->cls,
                                                session,
                                                &denom_pub_hash,
@@ -390,7 +403,7 @@ run (void *cls)
   pp.last_melt_serial_id++;
   pp.last_refund_serial_id++;
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_denomination_balance (plugin->cls,
                                                session,
                                                &denom_pub_hash,
@@ -399,7 +412,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: get_denomination_balance\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_denomination_balance (plugin->cls,
                                             session,
                                             &denom_pub_hash,
@@ -413,7 +426,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: insert_balance_summary\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_balance_summary (plugin->cls,
                                                session,
                                                &master_pub,
@@ -426,7 +439,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: update_balance_summary\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_balance_summary (plugin->cls,
                                                session,
                                                &master_pub,
@@ -445,7 +458,7 @@ run (void *cls)
   ZR_BLK (&refund_fee_balance2);
   ZR_BLK (&rbalance2);
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_balance_summary (plugin->cls,
                                             session,
                                             &master_pub,
@@ -455,17 +468,27 @@ run (void *cls)
                                             &refund_fee_balance2,
                                             &rbalance2));
 
-  FAILIF (0 != memcmp (&denom_balance2, &denom_balance, sizeof (denom_balance))
-          || 0 != memcmp (&deposit_fee_balance2, &deposit_fee_balance, sizeof 
(deposit_fee_balance))
-          || 0 != memcmp (&melt_fee_balance2, &melt_fee_balance, sizeof 
(melt_fee_balance))
-          || 0 != memcmp (&refund_fee_balance2, &refund_fee_balance, sizeof 
(refund_fee_balance)));
-  FAILIF (0 != memcmp (&rbalance2, &rbalance, sizeof (rbalance)));
+  FAILIF ( (0 != memcmp (&denom_balance2,
+                        &denom_balance,
+                        sizeof (denom_balance)) ) ||
+          (0 != memcmp (&deposit_fee_balance2,
+                        &deposit_fee_balance,
+                        sizeof (deposit_fee_balance)) ) ||
+          (0 != memcmp (&melt_fee_balance2,
+                        &melt_fee_balance,
+                        sizeof (melt_fee_balance)) ) ||
+          (0 != memcmp (&refund_fee_balance2,
+                        &refund_fee_balance,
+                        sizeof (refund_fee_balance))) );
+  FAILIF (0 != memcmp (&rbalance2,
+                      &rbalance,
+                      sizeof (rbalance)));
 
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: insert_historic_denom_revenue\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_historic_denom_revenue (plugin->cls,
                                                  session,
                                                  &master_pub,
@@ -473,7 +496,7 @@ run (void *cls)
                                                  past,
                                                  &rbalance));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_historic_denom_revenue (plugin->cls,
                                                  session,
                                                  &master_pub,
@@ -511,17 +534,17 @@ run (void *cls)
     return GNUNET_OK;
   }
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >=
           plugin->select_historic_denom_revenue (plugin->cls,
                                                  session,
                                                  &master_pub,
-                                                 
select_historic_denom_revenue_result,
+                                                 
&select_historic_denom_revenue_result,
                                                  NULL));
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: insert_historic_losses\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_historic_losses (plugin->cls,
                                           session,
                                           &master_pub,
@@ -529,7 +552,7 @@ run (void *cls)
                                           past,
                                           &rbalance));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_historic_losses (plugin->cls,
                                           session,
                                           &master_pub,
@@ -568,7 +591,7 @@ run (void *cls)
     return GNUNET_OK;
   }
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >=
           plugin->select_historic_losses (plugin->cls,
                                           session,
                                           &master_pub,
@@ -583,7 +606,7 @@ run (void *cls)
                  TALER_string_to_amount (CURRENCY ":56.789012",
                                          &reserve_profits));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_historic_reserve_revenue (plugin->cls,
                                                    session,
                                                    &master_pub,
@@ -591,7 +614,7 @@ run (void *cls)
                                                    future,
                                                    &reserve_profits));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_historic_reserve_revenue (plugin->cls,
                                                    session,
                                                    &master_pub,
@@ -628,7 +651,7 @@ run (void *cls)
     return GNUNET_OK;
   }
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >=
           plugin->select_historic_reserve_revenue (plugin->cls,
                                                    session,
                                                    &master_pub,
@@ -638,7 +661,7 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: insert_predicted_result\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_predicted_result (plugin->cls,
                                            session,
                                            &master_pub,
@@ -651,18 +674,18 @@ run (void *cls)
                  TALER_string_to_amount (CURRENCY ":78.901234",
                                          &rbalance));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_predicted_result (plugin->cls,
                                            session,
                                            &master_pub,
                                            &rbalance));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_wire_fee_summary (plugin->cls,
                                            session,
                                            &master_pub,
                                            &rbalance));
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_wire_fee_summary (plugin->cls,
                                            session,
                                            &master_pub,
@@ -670,7 +693,7 @@ run (void *cls)
   {
     struct TALER_Amount rprof;
 
-    FAILIF (GNUNET_OK !=
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
             plugin->get_wire_fee_summary (plugin->cls,
                                           session,
                                           &master_pub,
@@ -679,7 +702,7 @@ run (void *cls)
             TALER_amount_cmp (&rprof,
                               &reserve_profits));
   }
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >
           plugin->commit (plugin->cls,
                           session));
 
@@ -691,13 +714,13 @@ run (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Test: get_predicted_balance\n");
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_predicted_balance (plugin->cls,
                                          session,
                                          &master_pub,
                                          &rbalance2));
 
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->del_reserve_info (plugin->cls,
                                     session,
                                     &reserve_pub,
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index 8dd46f7..7bd437b 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -346,18 +346,19 @@ advance_fees (struct WirePlugin *wp,
  * @param wp wire transfer fee data structure to update
  * @param now timestamp to update fees to
  * @param session DB session to use
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if we
- *         lack current fee information (and need to exit)
+ * @return transaction status
  */
-static int
+static enum GNUNET_DB_QueryStatus
 update_fees (struct WirePlugin *wp,
              struct GNUNET_TIME_Absolute now,
              struct TALER_EXCHANGEDB_Session *session)
 {
+  enum GNUNET_DB_QueryStatus qs;
+  
   advance_fees (wp,
                 now);
   if (NULL != wp->af)
-    return GNUNET_OK;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   /* Let's try to load it from disk... */
   wp->af = TALER_EXCHANGEDB_fees_read (cfg,
                                        wp->type);
@@ -367,26 +368,26 @@ update_fees (struct WirePlugin *wp,
        NULL != p;
        p = p->next)
   {
-    if (GNUNET_SYSERR ==
-        db_plugin->insert_wire_fee (db_plugin->cls,
-                                    session,
-                                    wp->type,
-                                    p->start_date,
-                                    p->end_date,
-                                    &p->wire_fee,
-                                    &p->master_sig))
+    qs = db_plugin->insert_wire_fee (db_plugin->cls,
+                                    session,
+                                    wp->type,
+                                    p->start_date,
+                                    p->end_date,
+                                    &p->wire_fee,
+                                    &p->master_sig);
+    if (qs < 0)
     {
       TALER_EXCHANGEDB_fees_free (wp->af);
       wp->af = NULL;
-      return GNUNET_SYSERR;
+      return qs;
     }
   }
   if (NULL != wp->af)
-    return GNUNET_OK;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
               "Failed to find current wire transfer fees for `%s'\n",
               wp->type);
-  return GNUNET_SYSERR;
+  return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
 }
 
 
@@ -425,6 +426,26 @@ find_plugin (const char *type)
   return wp;
 }
 
+
+/**
+ * Free data stored in #au.
+ */
+static void
+cleanup_au (void)
+{
+  if (NULL == au)
+    return;
+  GNUNET_free_non_null (au->additional_rows);
+  if (NULL != au->wire)
+  {
+    json_decref (au->wire);
+    au->wire = NULL;
+  }
+  GNUNET_free (au);
+  au = NULL;
+}
+
+
 /**
  * We're being aborted with CTRL-C (or SIGTERM). Shut down.
  *
@@ -463,11 +484,7 @@ shutdown_task (void *cls)
     }
     db_plugin->rollback (db_plugin->cls,
                          au->session);
-    GNUNET_free_non_null (au->additional_rows);
-    if (NULL != au->wire)
-      json_decref (au->wire);
-    au = NULL;
-    GNUNET_free (au);
+    cleanup_au ();
   }
   if (NULL != ctc)
   {
@@ -564,9 +581,9 @@ exchange_serve_process_config ()
  * @param wire_deadline by which the merchant adviced that he would like the
  *        wire transfer to be executed
  * @param wire wire details for the merchant
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ * @return transaction status code,  #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
-static int
+static enum GNUNET_DB_QueryStatus
 deposit_cb (void *cls,
             uint64_t row_id,
             const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -588,7 +605,7 @@ deposit_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Fatally malformed record at row %llu\n",
                 (unsigned long long) row_id);
-    return GNUNET_SYSERR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
   au->row_id = row_id;
   GNUNET_assert (NULL == au->wire);
@@ -604,38 +621,41 @@ deposit_cb (void *cls,
 
   au->wp = find_plugin (extract_type (au->wire));
   if (NULL == au->wp)
-    return GNUNET_SYSERR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
 
   /* make sure we have current fees */
   au->execution_time = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&au->execution_time);
-  if (GNUNET_OK !=
-      update_fees (au->wp,
-                   au->execution_time,
-                   au->session))
-    return GNUNET_SYSERR;
+  qs = update_fees (au->wp,
+                   au->execution_time,
+                   au->session);
+  if (qs <= 0)
+  {
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      qs = GNUNET_DB_STATUS_HARD_ERROR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
+  }
   au->wire_fee = au->wp->af->wire_fee;
 
-  if (GNUNET_OK !=
-      db_plugin->insert_aggregation_tracking (db_plugin->cls,
-                                              au->session,
-                                              &au->wtid,
-                                              row_id))
+  qs = db_plugin->insert_aggregation_tracking (db_plugin->cls,
+                                              au->session,
+                                              &au->wtid,
+                                              row_id);
+  if (qs <= 0)
   {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
   }
   qs = db_plugin->mark_deposit_done (db_plugin->cls,
                                     au->session,
                                     row_id);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
-    /* FIXME #5010 */
-    GNUNET_break (0);
-    au->failed = GNUNET_YES;
-    return GNUNET_SYSERR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
   }
-  return GNUNET_OK;
+  return qs;
 }
 
 
@@ -653,9 +673,9 @@ deposit_cb (void *cls,
  * @param wire_deadline by which the merchant adviced that he would like the
  *        wire transfer to be executed
  * @param wire wire details for the merchant
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 aggregate_cb (void *cls,
               uint64_t row_id,
               const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -682,9 +702,12 @@ aggregate_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Fatally malformed record at %llu\n",
                 (unsigned long long) row_id);
-    return GNUNET_SYSERR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
   /* add to total */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Adding transaction amount %s to aggregation\n",
+             TALER_amount2s (&delta));
   if (GNUNET_OK !=
       TALER_amount_add (&au->total_amount,
                         &au->total_amount,
@@ -694,14 +717,14 @@ aggregate_cb (void *cls,
                 "Overflow or currency incompatibility during aggregation at 
%llu\n",
                 (unsigned long long) row_id);
     /* Skip this one, but keep going! */
-    return GNUNET_OK;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   }
   if (au->rows_offset >= aggregation_limit)
   {
     /* Bug: we asked for at most #aggregation_limit results! */
     GNUNET_break (0);
     /* Skip this one, but keep going. */
-    return GNUNET_OK;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   }
   if (NULL == au->additional_rows)
     au->additional_rows = GNUNET_new_array (aggregation_limit,
@@ -709,26 +732,27 @@ aggregate_cb (void *cls,
   /* "append" to our list of rows */
   au->additional_rows[au->rows_offset++] = row_id;
   /* insert into aggregation tracking table */
-  if (GNUNET_OK !=
-      db_plugin->insert_aggregation_tracking (db_plugin->cls,
-                                              au->session,
-                                              &au->wtid,
-                                              row_id))
+  qs = db_plugin->insert_aggregation_tracking (db_plugin->cls,
+                                              au->session,
+                                              &au->wtid,
+                                              row_id);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
   }
   qs = db_plugin->mark_deposit_done (db_plugin->cls,
                                     au->session,
                                     row_id);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
-    /* FIXME: #5010 */
-    GNUNET_break (0);
-    au->failed = GNUNET_YES;
-    return GNUNET_SYSERR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
   }
-  return GNUNET_OK;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Added row %llu to aggregation\n",
+             (unsigned long long) row_id);
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -948,15 +972,18 @@ expired_reserve_cb (void *cls,
   }
 
   /* lookup `closing_fee` */
-  if (GNUNET_OK !=
-      update_fees (wp,
-                  now,
-                  session))
+  qs = update_fees (wp,
+                   now,
+                   session);
+  if (qs <= 0)
   {
-    GNUNET_break (0);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      qs = GNUNET_DB_STATUS_HARD_ERROR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
-    return GNUNET_DB_STATUS_HARD_ERROR;
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+      GNUNET_SCHEDULER_shutdown ();
+    return qs;
   }
   closing_fee = &wp->af->closing_fee;
 
@@ -1144,7 +1171,6 @@ run_aggregation (void *cls)
   static int swap;
   struct TALER_EXCHANGEDB_Session *session;
   enum GNUNET_DB_QueryStatus qs;
-  int ret;
   const struct GNUNET_SCHEDULER_TaskContext *tc;
 
   task = NULL;
@@ -1179,19 +1205,16 @@ run_aggregation (void *cls)
   }
   au = GNUNET_new (struct AggregationUnit);
   au->session = session;
-  ret = db_plugin->get_ready_deposit (db_plugin->cls,
-                                      session,
-                                      &deposit_cb,
-                                      au);
-  if (0 >= ret)
+  qs = db_plugin->get_ready_deposit (db_plugin->cls,
+                                    session,
+                                    &deposit_cb,
+                                    au);
+  if (0 >= qs)
   {
-    if (NULL != au->wire)
-      json_decref (au->wire);
-    GNUNET_free (au);
-    au = NULL;
+    cleanup_au ();
     db_plugin->rollback (db_plugin->cls,
                          session);
-    if (GNUNET_SYSERR == ret)
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Failed to execute deposit iteration!\n");
@@ -1199,6 +1222,14 @@ run_aggregation (void *cls)
       GNUNET_SCHEDULER_shutdown ();
       return;
     }
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    {
+      /* should re-try immediately */
+      swap--; /* do not count failed attempts */
+      task = GNUNET_SCHEDULER_add_now (&run_aggregation,
+                                      NULL);
+      return;
+    }
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "No more ready deposits, going to sleep\n");
     if ( (GNUNET_YES == test_mode) &&
@@ -1209,12 +1240,13 @@ run_aggregation (void *cls)
     }
     else
     {
-      /* nothing to do, sleep for a minute and try again */
       if ( (GNUNET_NO == reserves_idle) ||
-           (GNUNET_YES == test_mode) )
+          (GNUNET_YES == test_mode) )
+       /* Possibly more to on reserves, go for it immediately */
        task = GNUNET_SCHEDULER_add_now (&run_reserve_closures,
                                         NULL);
       else
+       /* nothing to do, sleep for a minute and try again */
        task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
                                             &run_aggregation,
                                             NULL);
@@ -1226,29 +1258,37 @@ run_aggregation (void *cls)
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Found ready deposit for %s, aggregating\n",
               TALER_B2S (&au->merchant_pub));
-  ret = db_plugin->iterate_matching_deposits (db_plugin->cls,
-                                              session,
-                                              &au->h_wire,
-                                              &au->merchant_pub,
-                                              &aggregate_cb,
-                                              au,
-                                              aggregation_limit);
-  if ( (GNUNET_SYSERR == ret) ||
+  qs = db_plugin->iterate_matching_deposits (db_plugin->cls,
+                                            session,
+                                            &au->h_wire,
+                                            &au->merchant_pub,
+                                            &aggregate_cb,
+                                            au,
+                                            aggregation_limit);
+  if ( (GNUNET_DB_STATUS_HARD_ERROR == qs) ||
        (GNUNET_YES == au->failed) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Failed to execute deposit iteration!\n");
-    GNUNET_free_non_null (au->additional_rows);
-    json_decref (au->wire);
-    GNUNET_free (au);
-    au = NULL;
+    cleanup_au ();
     db_plugin->rollback (db_plugin->cls,
                          session);
     global_ret = GNUNET_SYSERR;
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
+  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+  {
+    /* serializiability issue, try again */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Serialization issue, trying again later!\n");
+    db_plugin->rollback (db_plugin->cls,
+                         session);
+    task = GNUNET_SCHEDULER_add_now (&run_aggregation,
+                                    NULL);
+    return;
+  }
+  
   /* Subtract wire transfer fee and round to the unit supported by the
      wire transfer method; Check if after rounding down, we still have
      an amount to transfer, and if not mark as 'tiny'. */
@@ -1263,13 +1303,16 @@ run_aggregation (void *cls)
          (0 == au->final_amount.fraction) ) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Aggregate value too low for transfer\n");
+                "Aggregate value too low for transfer (%d/%s)\n",
+               qs,
+               TALER_amount2s (&au->final_amount));
     /* Rollback ongoing transaction, as we will not use the respective
        WTID and thus need to remove the tracking data */
     db_plugin->rollback (db_plugin->cls,
                          session);
-    /* Start another transaction to mark all* of the selected deposits
-       *as minor! */
+
+    /* There were results, just the value was too low.  Start another
+       transaction to mark all* of the selected deposits as minor! */
     if (GNUNET_OK !=
         db_plugin->start (db_plugin->cls,
                           session))
@@ -1277,16 +1320,11 @@ run_aggregation (void *cls)
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Failed to start database transaction!\n");
       global_ret = GNUNET_SYSERR;
+      cleanup_au ();      
       GNUNET_SCHEDULER_shutdown ();
-      GNUNET_free_non_null (au->additional_rows);
-      if (NULL != au->wire)
-        json_decref (au->wire);
-      GNUNET_free (au);
-      au = NULL;
       return;
     }
     /* Mark transactions by row_id as minor */
-    ret = GNUNET_OK;
     qs = db_plugin->mark_deposit_tiny (db_plugin->cls,
                                       session,
                                       au->row_id);
@@ -1303,13 +1341,11 @@ run_aggregation (void *cls)
     }
     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
     {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Serialization issue, trying again later!\n");
       db_plugin->rollback (db_plugin->cls,
                           session);
-      GNUNET_free_non_null (au->additional_rows);
-      if (NULL != au->wire)
-       json_decref (au->wire);
-      GNUNET_free (au);
-      au = NULL;
+      cleanup_au ();
       /* start again */
       task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                       NULL);
@@ -1319,21 +1355,13 @@ run_aggregation (void *cls)
     {
       db_plugin->rollback (db_plugin->cls,
                           session);
-      GNUNET_free_non_null (au->additional_rows);
-      if (NULL != au->wire)
-       json_decref (au->wire);
-      GNUNET_free (au);
-      au = NULL;
+      cleanup_au ();
       GNUNET_SCHEDULER_shutdown ();
       return;
     }
     /* commit */
     (void) commit_or_warn (session);
-    GNUNET_free_non_null (au->additional_rows);
-    if (NULL != au->wire)
-      json_decref (au->wire);
-    GNUNET_free (au);
-    au = NULL;
+    cleanup_au ();
     /* start again */
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
@@ -1361,11 +1389,7 @@ run_aggregation (void *cls)
     GNUNET_break (0); /* why? how to best recover? */
     db_plugin->rollback (db_plugin->cls,
                          session);
-    GNUNET_free_non_null (au->additional_rows);
-    if (NULL != au->wire)
-      json_decref (au->wire);
-    GNUNET_free (au);
-    au = NULL;
+    cleanup_au ();
     /* start again */
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
@@ -1388,8 +1412,10 @@ prepare_cb (void *cls,
             size_t buf_size)
 {
   struct TALER_EXCHANGEDB_Session *session = au->session;
+  enum GNUNET_DB_QueryStatus qs;
 
   GNUNET_free_non_null (au->additional_rows);
+  au->additional_rows = NULL;
   if (NULL == buf)
   {
     GNUNET_break (0); /* why? how to best recover? */
@@ -1398,74 +1424,53 @@ prepare_cb (void *cls,
     /* start again */
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
-    if (NULL != au->wire)
-    {
-      json_decref (au->wire);
-      au->wire = NULL;
-    }
-    GNUNET_free (au);
-    au = NULL;
+    cleanup_au ();
     return;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Storing %u bytes of wire prepare data\n",
+             (unsigned int) buf_size);
   /* Commit our intention to execute the wire transfer! */
-  if (GNUNET_OK !=
-      db_plugin->wire_prepare_data_insert (db_plugin->cls,
-                                           session,
-                                           au->wp->type,
-                                           buf,
-                                           buf_size))
+  qs = db_plugin->wire_prepare_data_insert (db_plugin->cls,
+                                           session,
+                                           au->wp->type,
+                                           buf,
+                                           buf_size);
+  /* Commit the WTID data to 'wire_out' to finally satisfy aggregation
+     table constraints */
+  if (qs >= 0)
+    qs = db_plugin->store_wire_transfer_out (db_plugin->cls,
+                                            session,
+                                            au->execution_time,
+                                            &au->wtid,
+                                            au->wire,
+                                            &au->final_amount);
+  cleanup_au ();
+  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
   {
-    GNUNET_break (0); /* why? how to best recover? */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Serialization issue for prepared wire data; trying again 
later!\n");
     db_plugin->rollback (db_plugin->cls,
                          session);
     /* start again */
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
-    if (NULL != au->wire)
-    {
-      json_decref (au->wire);
-      au->wire = NULL;
-    }
-    GNUNET_free (au);
-    au = NULL;
     return;
   }
-
-  /* Commit the WTID data to 'wire_out' to finally satisfy aggregation
-     table constraints */
-  if (GNUNET_OK !=
-      db_plugin->store_wire_transfer_out (db_plugin->cls,
-                                          session,
-                                          au->execution_time,
-                                          &au->wtid,
-                                          au->wire,
-                                          &au->final_amount))
+  if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   {
-    GNUNET_break (0); /* why? how to best recover? */
+    GNUNET_break (0);
     db_plugin->rollback (db_plugin->cls,
                          session);
-    /* start again */
-    task = GNUNET_SCHEDULER_add_now (&run_aggregation,
-                                     NULL);
-    if (NULL != au->wire)
-    {
-      json_decref (au->wire);
-      au->wire = NULL;
-    }
-    GNUNET_free (au);
-    au = NULL;
+    /* die hard */
+    global_ret = GNUNET_SYSERR;
+    GNUNET_SCHEDULER_shutdown ();
     return;
   }
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Stored wire transfer out instructions\n");
-  if (NULL != au->wire)
-  {
-    json_decref (au->wire);
-    au->wire = NULL;
-  }
-  GNUNET_free (au);
-  au = NULL;
 
   /* Now we can finally commit the overall transaction, as we are
      again consistent if all of this passes. */
@@ -1473,6 +1478,8 @@ prepare_cb (void *cls,
   {
   case GNUNET_DB_STATUS_SOFT_ERROR:
     /* try again */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Commit issue for prepared wire data; trying again later!\n");
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
     return;
@@ -1512,6 +1519,7 @@ wire_confirm_cb (void *cls,
                  const char *emsg)
 {
   struct TALER_EXCHANGEDB_Session *session = wpd->session;
+  enum GNUNET_DB_QueryStatus qs;
 
   wpd->eh = NULL;
   if (GNUNET_SYSERR == success)
@@ -1527,16 +1535,25 @@ wire_confirm_cb (void *cls,
     wpd = NULL;
     return;
   }
-  if (GNUNET_OK !=
-      db_plugin->wire_prepare_data_mark_finished (db_plugin->cls,
-                                                  session,
-                                                  wpd->row_id))
+  qs = db_plugin->wire_prepare_data_mark_finished (db_plugin->cls,
+                                                  session,
+                                                  wpd->row_id);
+  if (0 >= qs)
   {
-    GNUNET_break (0); /* why!? */
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     db_plugin->rollback (db_plugin->cls,
                          session);
-    global_ret = GNUNET_SYSERR;
-    GNUNET_SCHEDULER_shutdown ();
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    {
+      /* try again */
+      task = GNUNET_SCHEDULER_add_now (&run_aggregation,
+                                      NULL);
+    }
+    else
+    {
+      global_ret = GNUNET_SYSERR;
+      GNUNET_SCHEDULER_shutdown ();
+    }
     GNUNET_free (wpd);
     wpd = NULL;
     return;
@@ -1621,7 +1638,7 @@ wire_prepare_cb (void *cls,
 static void
 run_transfers (void *cls)
 {
-  int ret;
+  enum GNUNET_DB_QueryStatus qs;
   struct TALER_EXCHANGEDB_Session *session;
   const struct GNUNET_SCHEDULER_TaskContext *tc;
 
@@ -1651,35 +1668,39 @@ run_transfers (void *cls)
   }
   wpd = GNUNET_new (struct WirePrepareData);
   wpd->session = session;
-  ret = db_plugin->wire_prepare_data_get (db_plugin->cls,
-                                          session,
-                                          &wire_prepare_cb,
-                                          NULL);
-  if (GNUNET_SYSERR == ret)
+  qs = db_plugin->wire_prepare_data_get (db_plugin->cls,
+                                        session,
+                                        &wire_prepare_cb,
+                                        NULL);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    return;  /* continues in #wire_prepare_cb() */
+  db_plugin->rollback (db_plugin->cls,
+                      session);
+  GNUNET_free (wpd);
+  wpd = NULL;
+  switch (qs)
   {
-    GNUNET_break (0); /* why? how to best recover? */
-    db_plugin->rollback (db_plugin->cls,
-                         session);
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    GNUNET_break (0);
     global_ret = GNUNET_SYSERR;
     GNUNET_SCHEDULER_shutdown ();
-    GNUNET_free (wpd);
-    wpd = NULL;
     return;
-  }
-  if (GNUNET_NO == ret)
-  {
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    /* try again */
+    task = GNUNET_SCHEDULER_add_now (&run_transfers,
+                                    NULL);      
+    return;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     /* no more prepared wire transfers, go back to aggregation! */
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "No more pending wire transfers, starting aggregation\n");
-    db_plugin->rollback (db_plugin->cls,
-                         session);
     task = GNUNET_SCHEDULER_add_now (&run_aggregation,
                                      NULL);
-    GNUNET_free (wpd);
-    wpd = NULL;
     return;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    /* should be impossible */
+    GNUNET_assert (0);
   }
-  /* otherwise, continues in #wire_prepare_cb() */
 }
 
 
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 9ec998a..b6241c8 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -30,38 +30,6 @@
 
 #include "plugin_exchangedb_common.c"
 
-/**
- * Error code returned by Postgres for deadlock.
- */
-#define PQ_DIAG_SQLSTATE_DEADLOCK "40P01"
-
-/**
- * Error code returned by Postgres for uniqueness violation.
- */
-#define PQ_DIAG_SQLSTATE_UNIQUE_VIOLATION "23505"
-
-/**
- * Error code returned by Postgres on serialization failure.
- */
-#define PQ_DIAG_SQLSTATE_SERIALIZATION_FAILURE "40001"
-
-
-/**
- * Log a query error.
- *
- * @param result PQ result object of the query that failed
- * @param conn SQL connection that was used
- */
-#define QUERY_ERR(result,conn)                         \
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,             \
-              "Query failed at %s:%u: %s/%s/%s/%s/%s\n", \
-              __FILE__, __LINE__, \
-              PQresultErrorField (result, PG_DIAG_MESSAGE_PRIMARY), \
-              PQresultErrorField (result, PG_DIAG_MESSAGE_DETAIL), \
-              PQresultErrorMessage (result), \
-              PQresStatus (PQresultStatus (result)), \
-              PQerrorMessage (conn));
-
 
 /**
  * Log a really unexpected PQ error with all the details we can get hold of.
@@ -91,24 +59,6 @@ struct TALER_EXCHANGEDB_Session
    */
   PGconn *conn;
 
-  /**
-   * Transaction state.  Set to #GNUNET_OK by #postgres_start().
-   * Set to #GNUNET_NO if any part of the transaction failed in a
-   * transient way (i.e. #PG_DIAG_SQLSTATE_DEADLOCK or
-   * #PG_DIAG_SQLSTATE_SERIALIZATION_FAILURE).  Set to
-   * #GNUNET_SYSERR if any part of the transaction failed in a
-   * hard way or if we are not within a transaction scope.
-   *
-   * If #GNUNET_NO, #postgres_commit() will always just do a
-   * rollback and return #GNUNET_NO as well (to retry).
-   *
-   * If #GNUNET_SYSERR, #postgres_commit() will always just do a
-   * rollback and return #GNUNET_SYSERR as well.
-   *
-   * If #GNUNET_OK, #postgres_commit() will try to commit and
-   * return the result from the commit operation.
-   */
-  int state;
 };
 
 
@@ -475,7 +425,6 @@ postgres_create_tables (void *cls)
     GNUNET_PQ_make_try_execute("CREATE INDEX prepare_iteration_index "
                                "ON prewire(type,finished);"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
-
   };
   PGconn *conn;
   int ret;
@@ -1471,6 +1420,7 @@ postgres_prepare (PGconn *db_conn)
                             ",timestamp"
                             ",denoms.denom_pub"
                             ",coins.denom_sig"
+
                             " FROM payback"
                             "    JOIN known_coins coins"
                             "      USING (coin_pub)"
@@ -1554,7 +1504,6 @@ postgres_get_session (void *cls)
     return NULL;
   }
   session = GNUNET_new (struct TALER_EXCHANGEDB_Session);
-  session->state = GNUNET_SYSERR;
   session->conn = db_conn;
   if (0 != pthread_setspecific (pc->db_conn_threadlocal,
                                 session))
@@ -1592,11 +1541,9 @@ postgres_start (void *cls,
                      PQerrorMessage (session->conn));
     GNUNET_break (0);
     PQclear (result);
-    session->state = GNUNET_SYSERR;
     return GNUNET_SYSERR;
   }
   PQclear (result);
-  session->state = GNUNET_OK;
   return GNUNET_OK;
 }
 
@@ -1619,51 +1566,6 @@ postgres_rollback (void *cls,
   GNUNET_break (PGRES_COMMAND_OK ==
                 PQresultStatus (result));
   PQclear (result);
-  session->state = GNUNET_SYSERR;
-}
-
-
-/**
- * Check the @a result's error code to see what happened.
- * Also logs errors.
- *
- * @param session session used
- * @param result result to check
- * @return #GNUNET_OK if the request/transaction succeeded
- *         #GNUNET_NO if it failed but could succeed if retried
- *         #GNUNET_SYSERR on hard errors
- */
-static int
-evaluate_pq_result (struct TALER_EXCHANGEDB_Session *session,
-                    PGresult *result)
-{
-  if (PGRES_COMMAND_OK !=
-      PQresultStatus (result))
-  {
-    const char *sqlstate;
-
-    sqlstate = PQresultErrorField (result,
-                                   PG_DIAG_SQLSTATE);
-    if (NULL == sqlstate)
-    {
-      /* very unexpected... */
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    if ( (0 == strcmp (sqlstate,
-                       PQ_DIAG_SQLSTATE_DEADLOCK)) ||
-         (0 == strcmp (sqlstate,
-                       PQ_DIAG_SQLSTATE_SERIALIZATION_FAILURE)) )
-    {
-      /* These two can be retried and have a fair chance of working
-         the next time */
-      QUERY_ERR (result, session->conn);
-      return GNUNET_NO;
-    }
-    BREAK_DB_ERR(result, session->conn);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
 }
 
 
@@ -1689,87 +1591,6 @@ postgres_commit (void *cls,
 
 
 /**
- * Update the @a session state based on the latest @a result from
- * the database.  Checks the status code of @a result and possibly
- * sets the state to failed (#GNUNET_SYSERR) or transiently failed
- * (#GNUNET_NO).
- *
- * @param session the session in which the transaction is running
- * @param statement name of the statement we were executing (for logging)
- * @param result the result we got from Postgres
- * @return current session state, i.e.
- *         #GNUNET_OK on success
- *         #GNUNET_NO if the transaction had a transient failure
- *         #GNUNET_SYSERR if the transaction had a hard failure
- */
-static int
-update_session_from_result (struct TALER_EXCHANGEDB_Session *session,
-                            const char *statement,
-                            PGresult *result)
-{
-  int ret;
-
-  if (GNUNET_OK != session->state)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR; /* we already failed, why do we keep going? */
-  }
-  ret = evaluate_pq_result (session,
-                            result);
-  if (GNUNET_OK == ret)
-    return ret;
-  GNUNET_log ((GNUNET_NO == ret)
-              ? GNUNET_ERROR_TYPE_INFO
-              : GNUNET_ERROR_TYPE_ERROR,
-              "Statement `%s' failed: %s/%s/%s/%s/%s",
-              statement,
-              PQresultErrorField (result, PG_DIAG_MESSAGE_PRIMARY),
-              PQresultErrorField (result, PG_DIAG_MESSAGE_DETAIL),
-              PQresultErrorMessage (result),
-              PQresStatus (PQresultStatus (result)),
-              PQerrorMessage (session->conn));
-  session->state = ret;
-  return ret;
-}
-
-
-/**
- * Execute a named prepared @a statement that is NOT a SELECT statement
- * in @a session using the given @a params.  Returns the resulting session
- * state.
- *
- * @param session session to execute the statement in
- * @param statement name of the statement
- * @param params parameters to give to the statement 
(#GNUNET_PQ_query_param_end-terminated)
- * @return #GNUNET_OK on success
- *         #GNUNET_NO if the transaction had a transient failure
- *         #GNUNET_SYSERR if the transaction had a hard failure
- */
-static int
-execute_prepared_non_select (struct TALER_EXCHANGEDB_Session *session,
-                             const char *statement,
-                             const struct GNUNET_PQ_QueryParam *params)
-{
-  PGresult *result;
-  int ret;
-
-  if (GNUNET_OK != session->state)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR; /* we already failed, why keep going? */
-  }
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    statement,
-                                    params);
-  ret = update_session_from_result (session,
-                                    statement,
-                                    result);
-  PQclear (result);
-  return ret;
-}
-
-
-/**
  * Insert a denomination key's public information into the database for
  * reference by auditors and other consistency checks.
  *
@@ -2787,10 +2608,9 @@ postgres_mark_deposit_done (void *cls,
  * @param session connection to the database
  * @param deposit_cb function to call for ONE such deposit
  * @param deposit_cb_cls closure for @a deposit_cb
- * @return number of rows processed, 0 if none exist,
- *         #GNUNET_SYSERR on error
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_ready_deposit (void *cls,
                             struct TALER_EXCHANGEDB_Session *session,
                             TALER_EXCHANGEDB_DepositIterator deposit_cb,
@@ -2801,77 +2621,161 @@ postgres_get_ready_deposit (void *cls,
     GNUNET_PQ_query_param_absolute_time (&now),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  unsigned int n;
-  int ret;
+  struct TALER_Amount amount_with_fee;
+  struct TALER_Amount deposit_fee;
+  struct GNUNET_TIME_Absolute wire_deadline;
+  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_MerchantPublicKeyP merchant_pub;
+  struct TALER_CoinSpendPublicKeyP coin_pub;
+  uint64_t serial_id;
+  json_t *wire;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
+                                 &serial_id),
+    TALER_PQ_result_spec_amount ("amount_with_fee",
+                                &amount_with_fee),
+    TALER_PQ_result_spec_amount ("fee_deposit",
+                                &deposit_fee),
+    GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
+                                        &wire_deadline),
+    GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                         &h_contract_terms),
+    GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                         &merchant_pub),
+    GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                         &coin_pub),
+    TALER_PQ_result_spec_json ("wire",
+                              &wire),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "deposits_get_ready",
-                                   params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (0 == (n = PQntuples (result)))
-  {
-    PQclear (result);
-    return 0;
-  }
-  GNUNET_break (1 == n);
+  qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                "deposits_get_ready",
+                                                params,
+                                                rs);
+  if (qs <= 0)
+    return qs;
+  qs = deposit_cb (deposit_cb_cls,
+                  serial_id,
+                  &merchant_pub,
+                  &coin_pub,
+                  &amount_with_fee,
+                  &deposit_fee,
+                  &h_contract_terms,
+                  wire_deadline,
+                  wire);
+  GNUNET_PQ_cleanup_result (rs);
+  return qs;
+}
+
+
+/**
+ * Closure for #match_deposit_cb().
+ */
+struct MatchingDepositContext
+{
+  /**
+   * Function to call for each result
+   */
+  TALER_EXCHANGEDB_DepositIterator deposit_cb;
+
+  /**
+   * Closure for @e deposit_cb.
+   */
+  void *deposit_cb_cls;
+
+  /**
+   * Public key of the merchant against which we are matching.
+   */
+  const struct TALER_MerchantPublicKeyP *merchant_pub;
+  
+  /**
+   * Maximum number of results to return.
+   */
+  uint32_t limit;
+
+  /**
+   * Loop counter, actual number of results returned.
+   */
+  unsigned int i;
+
+  /**
+   * Set to #GNUNET_SYSERR on hard errors.
+   */
+  int status;
+};
+
+
+/**
+ * Helper function for #postgres_iterate_matching_deposits().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct MatchingDepositContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+match_deposit_cb (void *cls,
+                 PGresult *result,
+                 unsigned int num_results)
+{
+  struct MatchingDepositContext *mdc = cls;
+  
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Found %u/%u matching deposits\n",
+             num_results,
+             mdc->limit);
+  num_results = GNUNET_MIN (num_results,
+                           mdc->limit);
+  for (mdc->i=0;mdc->i<num_results;mdc->i++)
   {
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount deposit_fee;
     struct GNUNET_TIME_Absolute wire_deadline;
     struct GNUNET_HashCode h_contract_terms;
-    struct TALER_MerchantPublicKeyP merchant_pub;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     uint64_t serial_id;
-    json_t *wire;
+    enum GNUNET_DB_QueryStatus qs;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
-                                   &serial_id),
+                                    &serial_id),
       TALER_PQ_result_spec_amount ("amount_with_fee",
                                    &amount_with_fee),
       TALER_PQ_result_spec_amount ("fee_deposit",
                                    &deposit_fee),
       GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
-                                          &wire_deadline),
+                                           &wire_deadline),
       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                           &h_contract_terms),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                           &merchant_pub),
+                                            &h_contract_terms),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                           &coin_pub),
-      TALER_PQ_result_spec_json ("wire",
-                                 &wire),
+                                            &coin_pub),
       GNUNET_PQ_result_spec_end
     };
-
+    
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
-                                  0))
+                                  mdc->i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      mdc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = deposit_cb (deposit_cb_cls,
-                      serial_id,
-                      &merchant_pub,
-                      &coin_pub,
-                      &amount_with_fee,
-                      &deposit_fee,
-                      &h_contract_terms,
-                      wire_deadline,
-                      wire);
+    qs = mdc->deposit_cb (mdc->deposit_cb_cls,
+                         serial_id,
+                         mdc->merchant_pub,
+                         &coin_pub,
+                         &amount_with_fee,
+                         &deposit_fee,
+                         &h_contract_terms,
+                         wire_deadline,
+                         NULL);
     GNUNET_PQ_cleanup_result (rs);
-    PQclear (result);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+      break;
   }
-  return (GNUNET_OK == ret) ? 1 : 0;
 }
 
 
@@ -2889,7 +2793,7 @@ postgres_get_ready_deposit (void *cls,
  * @return transaction status code, if positive:
  *         number of rows processed, 0 if none exist
  */
-static int // FIXME: enum GNUNET_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_iterate_matching_deposits (void *cls,
                                     struct TALER_EXCHANGEDB_Session *session,
                                     const struct GNUNET_HashCode *h_wire,
@@ -2903,75 +2807,27 @@ postgres_iterate_matching_deposits (void *cls,
     GNUNET_PQ_query_param_auto_from_type (h_wire),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  unsigned int i;
-  unsigned int n;
+  struct MatchingDepositContext mdc;
+  enum GNUNET_DB_QueryStatus qs;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "deposits_iterate_matching",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (0 == (n = PQntuples (result)))
-  {
-    PQclear (result);
-    return 0;
-  }
-  if (n > limit)
-    n = limit;
-  for (i=0;i<n;i++)
+  mdc.deposit_cb = deposit_cb;
+  mdc.deposit_cb_cls = deposit_cb_cls;
+  mdc.merchant_pub = merchant_pub;
+  mdc.limit = limit;
+  mdc.status = GNUNET_OK;
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "deposits_iterate_matching",
+                                            params,
+                                            &match_deposit_cb,
+                                            &mdc);
+  if (GNUNET_OK != mdc.status)
   {
-    struct TALER_Amount amount_with_fee;
-    struct TALER_Amount deposit_fee;
-    struct GNUNET_TIME_Absolute wire_deadline;
-    struct GNUNET_HashCode h_contract_terms;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    uint64_t serial_id;
-    int ret;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
-                                    &serial_id),
-      TALER_PQ_result_spec_amount ("amount_with_fee",
-                                   &amount_with_fee),
-      TALER_PQ_result_spec_amount ("fee_deposit",
-                                   &deposit_fee),
-      GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
-                                           &wire_deadline),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                            &h_contract_terms),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &coin_pub),
-      GNUNET_PQ_result_spec_end
-    };
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-    ret = deposit_cb (deposit_cb_cls,
-                      serial_id,
-                      merchant_pub,
-                      &coin_pub,
-                      &amount_with_fee,
-                      &deposit_fee,
-                      &h_contract_terms,
-                      wire_deadline,
-                      NULL);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  PQclear (result);
-  return i;
+  if (qs >= 0)
+    return mdc.i;
+  return qs;
 }
 
 
@@ -2982,67 +2838,31 @@ postgres_iterate_matching_deposits (void *cls,
  * @param session the database session handle
  * @param coin_pub the public key of the coin to search for
  * @param coin_info place holder for the returned coin information object
- * @return #GNUNET_SYSERR upon error; #GNUNET_NO if no coin is found; 
#GNUNET_OK
- *           if upon succesfullying retrieving the record data info @a
- *           coin_info
+ * @return transaction status code
  */
-// FIXME: #5010
-static int
+static enum GNUNET_DB_QueryStatus
 get_known_coin (void *cls,
                 struct TALER_EXCHANGEDB_Session *session,
                 const struct TALER_CoinSpendPublicKeyP *coin_pub,
                 struct TALER_CoinPublicInfo *coin_info)
 {
-  PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_end
   };
-  int nrows;
-
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "get_known_coin",
-                                   params);
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  GNUNET_assert (1 == nrows);   /* due to primary key */
-  if (NULL == coin_info)
-  {
-    PQclear (result);
-    return GNUNET_YES;
-  }
-  {
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            
&coin_info->denom_pub.rsa_public_key),
-      GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                           
&coin_info->denom_sig.rsa_signature),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  0))
-    {
-      PQclear (result);
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-  }
-  PQclear (result);
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
+                                         &coin_info->denom_pub.rsa_public_key),
+    GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
+                                        &coin_info->denom_sig.rsa_signature),
+    GNUNET_PQ_result_spec_end
+  };
+  
   coin_info->coin_pub = *coin_pub;
-  return GNUNET_OK;
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  "get_known_coin",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -3078,24 +2898,67 @@ insert_known_coin (void *cls,
 
 
 /**
- * Insert information about deposited coin into the database.
+ * Make sure the given @a coin is known to the database.
  *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param session connection to the database
- * @param deposit deposit information to store
- * @return query result status
- */
+ * @param cls database connection plugin state
+ * @param session database session
+ * @param coin the coin that must be made known
+ * @return database transaction status, non-negative on success
+ */ 
 static enum GNUNET_DB_QueryStatus
-postgres_insert_deposit (void *cls,
-                         struct TALER_EXCHANGEDB_Session *session,
-                         const struct TALER_EXCHANGEDB_Deposit *deposit)
+ensure_coin_known (struct PostgresClosure *cls,
+                  struct TALER_EXCHANGEDB_Session *session,
+                  const struct TALER_CoinPublicInfo *coin)
 {
-  int ret;
   enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
-    TALER_PQ_query_param_amount (&deposit->amount_with_fee),
-    GNUNET_PQ_query_param_absolute_time (&deposit->timestamp),
+  struct TALER_CoinPublicInfo known_coin;
+
+  /* check if the coin is already known */
+  qs = get_known_coin (cls,
+                      session,
+                      &coin->coin_pub,
+                      &known_coin);
+  if (0 > qs)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* no change! */
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
+  /* if not known, insert it */
+  qs = insert_known_coin (cls,
+                         session,
+                         coin);
+  if (0 >= qs)
+  {
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      qs = GNUNET_DB_STATUS_HARD_ERROR; /* should be impossible */
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
+  }
+  return qs;
+}
+
+
+/**
+ * Insert information about deposited coin into the database.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param session connection to the database
+ * @param deposit deposit information to store
+ * @return query result status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_insert_deposit (void *cls,
+                         struct TALER_EXCHANGEDB_Session *session,
+                         const struct TALER_EXCHANGEDB_Deposit *deposit)
+{
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
+    TALER_PQ_query_param_amount (&deposit->amount_with_fee),
+    GNUNET_PQ_query_param_absolute_time (&deposit->timestamp),
     GNUNET_PQ_query_param_absolute_time (&deposit->refund_deadline),
     GNUNET_PQ_query_param_absolute_time (&deposit->wire_deadline),
     GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
@@ -3106,28 +2969,10 @@ postgres_insert_deposit (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  /* check if the coin is already known */
-  ret = get_known_coin (cls,
-                        session,
-                        &deposit->coin.coin_pub,
-                        NULL);
-  if (GNUNET_SYSERR == ret)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_NO == ret)         /* if not, insert it */
-  {
-    qs = insert_known_coin (cls,
-                           session,
-                           &deposit->coin);
-    if (0 > qs)
-    {
-      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      return qs;
-    }
-  }
-
+  if (0 > (qs = ensure_coin_known (cls,
+                                  session,
+                                  &deposit->coin)))
+    return qs;
   return GNUNET_PQ_eval_prepared_non_select (session->conn,
                                             "insert_deposit",
                                             params);
@@ -3210,14 +3055,14 @@ postgres_get_refresh_session (void *cls,
                                                 params,
                                                 rs);
   if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
-       (GNUNET_OK !=
-       get_known_coin (cls,
-                       session,
-                       &refresh_session->melt.coin.coin_pub,
-                       &refresh_session->melt.coin)) )
+       (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+       (qs = get_known_coin (cls,
+                             session,
+                             &refresh_session->melt.coin.coin_pub,
+                             &refresh_session->melt.coin)) ) )
   {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
   }
   refresh_session->melt.session_hash = *session_hash;
   return qs;
@@ -3248,31 +3093,12 @@ postgres_create_refresh_session (void *cls,
     GNUNET_PQ_query_param_uint16 (&refresh_session->noreveal_index),
     GNUNET_PQ_query_param_end
   };
-  int ret;
   enum GNUNET_DB_QueryStatus qs;
 
-  /* check if the coin is already known (FIXME: #5010) */
-  ret = get_known_coin (cls,
-                        session,
-                        &refresh_session->melt.coin.coin_pub,
-                        NULL);
-  if (GNUNET_SYSERR == ret)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_NO == ret)         /* if not, insert it */
-  {
-    qs = insert_known_coin (cls,
-                           session,
-                           &refresh_session->melt.coin);
-    if (0 > qs)
-    {
-      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      return qs;
-    }
-  }
-  
+  if (0 > (qs = ensure_coin_known (cls,
+                                  session,
+                                  &refresh_session->melt.coin)))
+    return qs;
   return GNUNET_PQ_eval_prepared_non_select (session->conn,
                                             "insert_refresh_session",
                                             params);
@@ -3881,9 +3707,9 @@ struct CoinHistoryContext
   struct TALER_EXCHANGEDB_Session *session;
   
   /**
-   * Set to #GNUNET_SYSERR on errors
+   * Set to transaction status.
    */ 
-  int status;
+  enum GNUNET_DB_QueryStatus status;
 };
 
 
@@ -3906,6 +3732,7 @@ add_coin_deposit (void *cls,
   {
     struct TALER_EXCHANGEDB_Deposit *deposit;
     struct TALER_EXCHANGEDB_TransactionList *tl;
+    enum GNUNET_DB_QueryStatus qs;
     
     deposit = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
     {
@@ -3938,7 +3765,7 @@ add_coin_deposit (void *cls,
       {
        GNUNET_break (0);
        GNUNET_free (deposit);
-       chc->status = GNUNET_SYSERR;
+       chc->status = GNUNET_DB_STATUS_HARD_ERROR;
        return;
       }
       deposit->coin.coin_pub = *chc->coin_pub;
@@ -3947,14 +3774,15 @@ add_coin_deposit (void *cls,
     tl->next = chc->head;
     tl->type = TALER_EXCHANGEDB_TT_DEPOSIT;
     tl->details.deposit = deposit;
-    if (GNUNET_SYSERR == get_known_coin (chc->db_cls,
-                                        chc->session,
-                                        chc->coin_pub,
-                                        &deposit->coin))
+    qs = get_known_coin (chc->db_cls,
+                        chc->session,
+                        chc->coin_pub,
+                        &deposit->coin);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     {
-      GNUNET_break (0);
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
       GNUNET_free (deposit);
-      chc->status = GNUNET_SYSERR;
+      chc->status = qs;
       return;
     }
     chc->head = tl;
@@ -3981,6 +3809,7 @@ add_coin_melt (void *cls,
   {
     struct TALER_EXCHANGEDB_RefreshMelt *melt;
     struct TALER_EXCHANGEDB_TransactionList *tl;
+    enum GNUNET_DB_QueryStatus qs;
 
     melt = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMelt);
     {
@@ -4004,7 +3833,7 @@ add_coin_melt (void *cls,
       {
        GNUNET_break (0);
        GNUNET_free (melt);
-       chc->status = GNUNET_SYSERR;
+       chc->status = GNUNET_DB_STATUS_HARD_ERROR;
        return;
       }
       melt->coin.coin_pub = *chc->coin_pub;
@@ -4013,14 +3842,15 @@ add_coin_melt (void *cls,
     tl->next = chc->head;
     tl->type = TALER_EXCHANGEDB_TT_REFRESH_MELT;
     tl->details.melt = melt;
-    if (GNUNET_SYSERR == get_known_coin (chc->db_cls,
-                                        chc->session,
-                                        chc->coin_pub,
-                                        &melt->coin))
+    qs = get_known_coin (chc->db_cls,
+                        chc->session,
+                        chc->coin_pub,
+                        &melt->coin);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     {
-      GNUNET_break (0);
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
       GNUNET_free (melt);
-      chc->status = GNUNET_SYSERR;
+      chc->status = qs;
       return;
     }
     chc->head = tl;
@@ -4047,6 +3877,7 @@ add_coin_refund (void *cls,
   {
     struct TALER_EXCHANGEDB_Refund *refund;
     struct TALER_EXCHANGEDB_TransactionList *tl;
+    enum GNUNET_DB_QueryStatus qs;
 
     refund = GNUNET_new (struct TALER_EXCHANGEDB_Refund);
     {
@@ -4073,7 +3904,7 @@ add_coin_refund (void *cls,
       {
        GNUNET_break (0);
        GNUNET_free (refund);
-       chc->status = GNUNET_SYSERR;
+       chc->status = GNUNET_DB_STATUS_HARD_ERROR;
        return;
       }
       refund->coin.coin_pub = *chc->coin_pub;
@@ -4082,15 +3913,15 @@ add_coin_refund (void *cls,
     tl->next = chc->head;
     tl->type = TALER_EXCHANGEDB_TT_REFUND;
     tl->details.refund = refund;
-    if (GNUNET_SYSERR ==
-       get_known_coin (chc->db_cls,
-                       chc->session,
-                       chc->coin_pub,
-                       &refund->coin))
+    qs = get_known_coin (chc->db_cls,
+                        chc->session,
+                        chc->coin_pub,
+                        &refund->coin);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     {
-      GNUNET_break (0);
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
       GNUNET_free (refund);
-      chc->status = GNUNET_SYSERR;
+      chc->status = qs;
       return;
     }
     chc->head = tl;
@@ -4145,7 +3976,7 @@ add_coin_payback (void *cls,
       {
        GNUNET_break (0);
        GNUNET_free (payback);
-       chc->status = GNUNET_SYSERR;
+       chc->status = GNUNET_DB_STATUS_HARD_ERROR;
        return;
       }
       payback->coin.coin_pub = *chc->coin_pub;
@@ -4208,7 +4039,7 @@ postgres_get_coin_transactions (void *cls,
   };
 
   chc.head = NULL;
-  chc.status = GNUNET_OK;
+  chc.status = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   chc.coin_pub = coin_pub;
   chc.session = session;
   chc.db_cls = cls;
@@ -4220,14 +4051,14 @@ postgres_get_coin_transactions (void *cls,
                                               work[i].cb,
                                               &chc);
     if ( (0 > qs) ||
-        (GNUNET_OK != chc.status) )
+        (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != chc.status) )
     {
       if (NULL != chc.head)
        common_free_coin_transaction_list (cls,
                                           chc.head);
       *tlp = NULL;
-      if (GNUNET_OK != chc.status)
-       qs = GNUNET_DB_STATUS_HARD_ERROR;
+      if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != chc.status)
+       qs = chc.status;
       return qs;
     }
   }
@@ -4493,11 +4324,9 @@ postgres_wire_lookup_deposit_wtid (void *cls,
  * @param session database connection
  * @param wtid the raw wire transfer identifier we used
  * @param deposit_serial_id row in the deposits table for which this is 
aggregation data
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO on transient errors
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_aggregation_tracking (void *cls,
                                       struct TALER_EXCHANGEDB_Session *session,
                                       const struct 
TALER_WireTransferIdentifierRawP *wtid,
@@ -4510,9 +4339,9 @@ postgres_insert_aggregation_tracking (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  return execute_prepared_non_select (session,
-                                      "insert_aggregation_tracking",
-                                      params);
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_aggregation_tracking",
+                                            params);
 }
 
 
@@ -4569,11 +4398,9 @@ postgres_get_wire_fee (void *cls,
  * @param end_date when does the fee end being valid
  * @param wire_fee how high is the wire transfer fee
  * @param master_sig signature over the above by the exchange master key
- * @return #GNUNET_OK on success or if the record exists,
- *         #GNUNET_NO on transient errors
- *         #GNUNET_SYSERR on failure
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_insert_wire_fee (void *cls,
                           struct TALER_EXCHANGEDB_Session *session,
                           const char *type,
@@ -4594,43 +4421,46 @@ postgres_insert_wire_fee (void *cls,
   struct TALER_MasterSignatureP sig;
   struct GNUNET_TIME_Absolute sd;
   struct GNUNET_TIME_Absolute ed;
+  enum GNUNET_DB_QueryStatus qs;
 
-  if (GNUNET_OK ==
-      postgres_get_wire_fee (cls,
-                             session,
-                             type,
-                             start_date,
-                             &sd,
-                             &ed,
-                             &wf,
-                             &sig))
+  qs = postgres_get_wire_fee (cls,
+                             session,
+                             type,
+                             start_date,
+                             &sd,
+                             &ed,
+                             &wf,
+                             &sig);
+  if (qs < 0)
+    return qs;
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
     if (0 != memcmp (&sig,
                      master_sig,
                      sizeof (sig)))
     {
       GNUNET_break (0);
-      return GNUNET_SYSERR;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
     if (0 != TALER_amount_cmp (wire_fee,
                                &wf))
     {
       GNUNET_break (0);
-      return GNUNET_SYSERR;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
     if ( (sd.abs_value_us != start_date.abs_value_us) ||
          (ed.abs_value_us != end_date.abs_value_us) )
     {
       GNUNET_break (0);
-      return GNUNET_SYSERR;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
     /* equal record already exists */
-    return GNUNET_OK;
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   }
 
-  return execute_prepared_non_select (session,
-                                      "insert_wire_fee",
-                                      params);
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_wire_fee",
+                                            params);
 }
 
 
@@ -4862,9 +4692,9 @@ postgres_wire_prepare_data_insert (void *cls,
  * @param cls closure
  * @param session database connection
  * @param rowid which entry to mark as finished
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_wire_prepare_data_mark_finished (void *cls,
                                           struct TALER_EXCHANGEDB_Session 
*session,
                                           uint64_t rowid)
@@ -4874,9 +4704,9 @@ postgres_wire_prepare_data_mark_finished (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  return execute_prepared_non_select (session,
-                                      "wire_prepare_data_mark_done",
-                                      params);
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "wire_prepare_data_mark_done",
+                                            params);
 }
 
 
@@ -4888,76 +4718,46 @@ postgres_wire_prepare_data_mark_finished (void *cls,
  * @param session database connection
  * @param cb function to call for ONE unfinished item
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO if there are no entries,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_wire_prepare_data_get (void *cls,
                                 struct TALER_EXCHANGEDB_Session *session,
                                 TALER_EXCHANGEDB_WirePreparationIterator cb,
                                 void *cb_cls)
 {
-  PGresult *result;
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_end
   };
+  uint64_t prewire_uuid;
+  char *type;
+  void *buf = NULL;
+  size_t buf_size;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
+                                 &prewire_uuid),
+    GNUNET_PQ_result_spec_string ("type",
+                                 &type),
+    GNUNET_PQ_result_spec_variable_size ("buf",
+                                        &buf,
+                                        &buf_size),
+    GNUNET_PQ_result_spec_end
+  };
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                   "wire_prepare_data_get",
-                                   params);
-  if (PGRES_TUPLES_OK != PQresultStatus (result))
-  {
-    QUERY_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (0 == PQntuples (result))
-  {
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  if (1 != PQntuples (result))
-  {
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-
-  {
-    uint64_t prewire_uuid;
-    char *type;
-    void *buf = NULL;
-    size_t buf_size;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
-                                    &prewire_uuid),
-      GNUNET_PQ_result_spec_string ("type",
-                                    &type),
-      GNUNET_PQ_result_spec_variable_size ("buf",
-                                           &buf,
-                                           &buf_size),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                 rs,
-                                 0))
-    {
-      GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
-    }
-    cb (cb_cls,
-        prewire_uuid,
-        type,
-        buf,
-        buf_size);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                "wire_prepare_data_get",
+                                                params,
+                                                rs);
+  if (0 >= qs)
+    return qs;
+  cb (cb_cls,
+      prewire_uuid,
+      type,
+      buf,
+      buf_size);
+  GNUNET_PQ_cleanup_result (rs);
+  return qs;
 }
 
 
@@ -5003,7 +4803,6 @@ postgres_start_deferred_wire_out (void *cls,
     return GNUNET_SYSERR;
   }
   PQclear (result);
-  session->state = GNUNET_OK;
   return GNUNET_OK;
 }
 
@@ -5017,10 +4816,9 @@ postgres_start_deferred_wire_out (void *cls,
  * @param wtid subject of the wire transfer
  * @param wire_account details about the receiver account of the wire transfer
  * @param amount amount that was transmitted
- * @return #GNUNET_OK on success
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_store_wire_transfer_out (void *cls,
                                   struct TALER_EXCHANGEDB_Session *session,
                                   struct GNUNET_TIME_Absolute date,
@@ -5036,9 +4834,9 @@ postgres_store_wire_transfer_out (void *cls,
     GNUNET_PQ_query_param_end
   };
 
-  return execute_prepared_non_select (session,
-                                      "insert_wire_out",
-                                      params);
+  return GNUNET_PQ_eval_prepared_non_select (session->conn,
+                                            "insert_wire_out",
+                                            params);
 }
 
 
@@ -5063,102 +4861,70 @@ postgres_gc (void *cls)
     GNUNET_PQ_query_param_end
   };
   PGconn *conn;
-  PGresult *result;
-
+  int ret;
+  
   now = GNUNET_TIME_absolute_get ();
   conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
-  if (GNUNET_OK !=
-      postgres_prepare (conn))
-  {
-    PQfinish (conn);
-    return GNUNET_SYSERR;
-  }
-  result = GNUNET_PQ_exec_prepared (conn,
-                                    "gc_prewire",
-                                    params_none);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, conn);
-    PQclear (result);
-    PQfinish (conn);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  result = GNUNET_PQ_exec_prepared (conn,
-                                    "gc_denominations",
-                                    params_time);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, conn);
-    PQclear (result);
-    PQfinish (conn);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  result = GNUNET_PQ_exec_prepared (conn,
-                                    "gc_reserves",
-                                    params_time);
-  if (PGRES_COMMAND_OK != PQresultStatus (result))
+  ret = postgres_prepare (conn);
+  if (GNUNET_OK == ret)
   {
-    BREAK_DB_ERR (result, conn);
-    PQclear (result);
-    PQfinish (conn);
-    return GNUNET_SYSERR;
+    if ( (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+                                                 "gc_prewire",
+                                                 params_none)) ||
+        (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+                                                 "gc_denominations",
+                                                 params_time)) ||
+        (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+                                                 "gc_reserves",
+                                                 params_time)) )
+      ret = GNUNET_SYSERR;
   }
-  PQclear (result);
   PQfinish (conn);
-  return GNUNET_OK;
+  return ret;
 }
 
 
 /**
- * Select deposits above @a serial_id in monotonically increasing
- * order.
- *
- * @param cls closure
- * @param session database connection
- * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call on each result
- * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_SYSERR on DB errors
+ * Closure for #deposit_serial_helper_cb().
  */
-static int
-postgres_select_deposits_above_serial_id (void *cls,
-                                          struct TALER_EXCHANGEDB_Session 
*session,
-                                          uint64_t serial_id,
-                                          TALER_EXCHANGEDB_DepositCallback cb,
-                                          void *cb_cls)
+struct DepositSerialContext
 {
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "audit_get_deposits_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  int nrows;
-  int ret;
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_deposits_above_serial_id() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_DepositCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+deposit_serial_helper_cb (void *cls,
+                         PGresult *result,
+                         unsigned int num_results)
+{
+  struct DepositSerialContext *dsc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct TALER_EXCHANGEDB_Deposit deposit;
     struct TALER_DenominationPublicKey denom_pub;
@@ -5191,39 +4957,39 @@ postgres_select_deposits_above_serial_id (void *cls,
                                     &rowid),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
+    
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      dsc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              deposit.timestamp,
-              &deposit.merchant_pub,
-              &denom_pub,
-              &deposit.coin.coin_pub,
-              &deposit.csig,
-              &deposit.amount_with_fee,
-              &deposit.h_contract_terms,
-              deposit.refund_deadline,
-              deposit.wire_deadline,
-              deposit.receiver_wire_account,
-              done);
+    ret = dsc->cb (dsc->cb_cls,
+                  rowid,
+                  deposit.timestamp,
+                  &deposit.merchant_pub,
+                  &denom_pub,
+                  &deposit.coin.coin_pub,
+                  &deposit.csig,
+                  &deposit.amount_with_fee,
+                  &deposit.h_contract_terms,
+                  deposit.refund_deadline,
+                  deposit.wire_deadline,
+                  deposit.receiver_wire_account,
+                  done);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Select refresh sessions above @a serial_id in monotonically increasing
+ * Select deposits above @a serial_id in monotonically increasing
  * order.
  *
  * @param cls closure
@@ -5231,47 +4997,76 @@ postgres_select_deposits_above_serial_id (void *cls,
  * @param serial_id highest serial ID to exclude (select strictly larger)
  * @param cb function to call on each result
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_refreshs_above_serial_id (void *cls,
-                                          struct TALER_EXCHANGEDB_Session 
*session,
+static enum GNUNET_DB_QueryStatus
+postgres_select_deposits_above_serial_id (void *cls,
+                                          struct TALER_EXCHANGEDB_Session 
*session,
                                           uint64_t serial_id,
-                                          
TALER_EXCHANGEDB_RefreshSessionCallback cb,
+                                          TALER_EXCHANGEDB_DepositCallback cb,
                                           void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  int nrows;
-  int i;
-  int ret;
+  struct DepositSerialContext dsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "audit_get_refresh_sessions_incr",
-                                    params);
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "audit_get_deposits_incr",
+                                            params,
+                                            &deposit_serial_helper_cb,
+                                            &dsc);
+  if (GNUNET_OK != dsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
 
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_refreshs_above_serial_id() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
+/**
+ * Closure for #refreshs_serial_helper_cb().
+ */
+struct RefreshsSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RefreshSessionCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
+
 
-  for (i=0;i<nrows;i++)
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RefreshsSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+refreshs_serial_helper_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct RefreshsSerialContext *rsc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct TALER_DenominationPublicKey denom_pub;
     struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -5281,7 +5076,6 @@ postgres_select_refreshs_above_serial_id (void *cls,
     uint16_t noreveal_index;
     uint64_t rowid;
     struct GNUNET_HashCode session_hash;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
                                             &denom_pub.rsa_public_key),
@@ -5301,35 +5095,35 @@ postgres_select_refreshs_above_serial_id (void *cls,
                                             &session_hash),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
+
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      rsc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              &denom_pub,
-              &coin_pub,
-              &coin_sig,
-              &amount_with_fee,
-              num_newcoins,
-              noreveal_index,
-              &session_hash);
+    ret = rsc->cb (rsc->cb_cls,
+                  rowid,
+                  &denom_pub,
+                  &coin_pub,
+                  &coin_sig,
+                  &amount_with_fee,
+                  num_newcoins,
+                  noreveal_index,
+                  &session_hash);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Select refunds above @a serial_id in monotonically increasing
+ * Select refresh sessions above @a serial_id in monotonically increasing
  * order.
  *
  * @param cls closure
@@ -5337,49 +5131,80 @@ postgres_select_refreshs_above_serial_id (void *cls,
  * @param serial_id highest serial ID to exclude (select strictly larger)
  * @param cb function to call on each result
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_refunds_above_serial_id (void *cls,
-                                         struct TALER_EXCHANGEDB_Session 
*session,
-                                         uint64_t serial_id,
-                                         TALER_EXCHANGEDB_RefundCallback cb,
-                                         void *cb_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_select_refreshs_above_serial_id (void *cls,
+                                          struct TALER_EXCHANGEDB_Session 
*session,
+                                          uint64_t serial_id,
+                                          
TALER_EXCHANGEDB_RefreshSessionCallback cb,
+                                          void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  int nrows;
-  int ret;
+  struct RefreshsSerialContext rsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "audit_get_refunds_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "audit_get_refresh_sessions_incr",
+                                            params,
+                                            &refreshs_serial_helper_cb,
+                                            &rsc);
+  if (GNUNET_OK != rsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_refunds_above_serial_id() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+
+/**
+ * Closure for #refunds_serial_helper_cb().
+ */
+struct RefundsSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_RefundCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RefundsSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+refunds_serial_helper_cb (void *cls,
+                         PGresult *result,
+                         unsigned int num_results)
+{
+  struct RefundsSerialContext *rsc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct TALER_EXCHANGEDB_Refund refund;
     struct TALER_DenominationPublicKey denom_pub;
     uint64_t rowid;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
                                             &refund.merchant_pub),
@@ -5399,80 +5224,112 @@ postgres_select_refunds_above_serial_id (void *cls,
                                     &rowid),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
+    
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      rsc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              &denom_pub,
-              &refund.coin.coin_pub,
-              &refund.merchant_pub,
-              &refund.merchant_sig,
-              &refund.h_contract_terms,
-              refund.rtransaction_id,
-              &refund.refund_amount);
+    ret = rsc->cb (rsc->cb_cls,
+                  rowid,
+                  &denom_pub,
+                  &refund.coin.coin_pub,
+                  &refund.merchant_pub,
+                  &refund.merchant_sig,
+                  &refund.h_contract_terms,
+                  refund.rtransaction_id,
+                  &refund.refund_amount);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Select inbound wire transfers into reserves_in above @a serial_id
- * in monotonically increasing order.
+ * Select refunds above @a serial_id in monotonically increasing
+ * order.
  *
  * @param cls closure
  * @param session database connection
  * @param serial_id highest serial ID to exclude (select strictly larger)
  * @param cb function to call on each result
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_reserves_in_above_serial_id (void *cls,
-                                             struct TALER_EXCHANGEDB_Session 
*session,
-                                             uint64_t serial_id,
-                                             
TALER_EXCHANGEDB_ReserveInCallback cb,
-                                             void *cb_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_select_refunds_above_serial_id (void *cls,
+                                         struct TALER_EXCHANGEDB_Session 
*session,
+                                         uint64_t serial_id,
+                                         TALER_EXCHANGEDB_RefundCallback cb,
+                                         void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "audit_reserves_in_get_transactions_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  int nrows;
-  int ret;
+  struct RefundsSerialContext rsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "audit_get_refunds_incr",
+                                            params,
+                                            &refunds_serial_helper_cb,
+                                            &rsc);
+  if (GNUNET_OK != rsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
+ * Closure for #reserves_in_serial_helper_cb().
+ */
+struct ReservesInSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_ReserveInCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_reserves_in_above_serial_id() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
 
-  for (int i=0;i<nrows;i++)
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesInSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+reserves_in_serial_helper_cb (void *cls,
+                             PGresult *result,
+                             unsigned int num_results)
+{
+  struct ReservesInSerialContext *risc = cls;
+
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct TALER_ReservePublicKeyP reserve_pub;
     struct TALER_Amount credit;
@@ -5481,7 +5338,6 @@ postgres_select_reserves_in_above_serial_id (void *cls,
     uint64_t rowid;
     void *wire_reference;
     size_t wire_reference_size;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
                                             &reserve_pub),
@@ -5498,6 +5354,7 @@ postgres_select_reserves_in_above_serial_id (void *cls,
                                     &rowid),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -5505,29 +5362,26 @@ postgres_select_reserves_in_above_serial_id (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      risc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              &reserve_pub,
-              &credit,
-              sender_account_details,
-              wire_reference,
-              wire_reference_size,
-              execution_date);
+    ret = risc->cb (risc->cb_cls,
+                   rowid,
+                   &reserve_pub,
+                   &credit,
+                   sender_account_details,
+                   wire_reference,
+                   wire_reference_size,
+                   execution_date);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Select withdraw operations from reserves_out above @a serial_id
+ * Select inbound wire transfers into reserves_in above @a serial_id
  * in monotonically increasing order.
  *
  * @param cls closure
@@ -5535,44 +5389,76 @@ postgres_select_reserves_in_above_serial_id (void *cls,
  * @param serial_id highest serial ID to exclude (select strictly larger)
  * @param cb function to call on each result
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO if no records were found
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_reserves_out_above_serial_id (void *cls,
-                                              struct TALER_EXCHANGEDB_Session 
*session,
-                                              uint64_t serial_id,
-                                              
TALER_EXCHANGEDB_WithdrawCallback cb,
-                                              void *cb_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_select_reserves_in_above_serial_id (void *cls,
+                                             struct TALER_EXCHANGEDB_Session 
*session,
+                                             uint64_t serial_id,
+                                             
TALER_EXCHANGEDB_ReserveInCallback cb,
+                                             void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "audit_get_reserves_out_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  int nrows;
-  int ret;
+  struct ReservesInSerialContext risc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            
"audit_reserves_in_get_transactions_incr",
+                                            params,
+                                            &reserves_in_serial_helper_cb,
+                                            &risc);
+  if (GNUNET_OK != risc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_reserves_out_above_serial_id() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+
+/**
+ * Closure for #reserves_out_serial_helper_cb().
+ */
+struct ReservesOutSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WithdrawCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesOutSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+reserves_out_serial_helper_cb (void *cls,
+                              PGresult *result,
+                              unsigned int num_results)
+{
+  struct ReservesOutSerialContext *rosc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     struct GNUNET_HashCode h_blind_ev;
     struct TALER_DenominationPublicKey denom_pub;
@@ -5582,7 +5468,6 @@ postgres_select_reserves_out_above_serial_id (void *cls,
     struct GNUNET_TIME_Absolute execution_date;
     struct TALER_Amount amount_with_fee;
     uint64_t rowid;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
                                             &h_blind_ev),
@@ -5602,89 +5487,118 @@ postgres_select_reserves_out_above_serial_id (void 
*cls,
                                     &rowid),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
+    
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
                                   rs,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      rosc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              &h_blind_ev,
-              &denom_pub,
-              &denom_sig,
-              &reserve_pub,
-              &reserve_sig,
-              execution_date,
-              &amount_with_fee);
+    ret = rosc->cb (rosc->cb_cls,
+                   rowid,
+                   &h_blind_ev,
+                   &denom_pub,
+                   &denom_sig,
+                   &reserve_pub,
+                   &reserve_sig,
+                   execution_date,
+                   &amount_with_fee);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Function called to select all wire transfers the exchange
- * executed.
+ * Select withdraw operations from reserves_out above @a serial_id
+ * in monotonically increasing order.
  *
  * @param cls closure
  * @param session database connection
  * @param serial_id highest serial ID to exclude (select strictly larger)
- * @param cb function to call for ONE unfinished item
+ * @param cb function to call on each result
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO if there are no entries,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_wire_out_above_serial_id (void *cls,
-                                          struct TALER_EXCHANGEDB_Session 
*session,
-                                          uint64_t serial_id,
-                                          
TALER_EXCHANGEDB_WireTransferOutCallback cb,
-                                          void *cb_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_select_reserves_out_above_serial_id (void *cls,
+                                              struct TALER_EXCHANGEDB_Session 
*session,
+                                              uint64_t serial_id,
+                                              
TALER_EXCHANGEDB_WithdrawCallback cb,
+                                              void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  int nrows;
-  int ret;
+  struct ReservesOutSerialContext rosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "audit_get_reserves_out_incr",
+                                            params,
+                                            &reserves_out_serial_helper_cb,
+                                            &rosc);
+  if (GNUNET_OK != rosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
+ * Closure for #wire_out_serial_helper_cb().
+ */
+struct WireOutSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_WireTransferOutCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "audit_get_wire_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_prepare_above_serial_id() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+wire_out_serial_helper_cb (void *cls,
+                          PGresult *result,
+                          unsigned int num_results)
+{
+  struct WireOutSerialContext *wosc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     uint64_t rowid;
     struct GNUNET_TIME_Absolute date;
     struct TALER_WireTransferIdentifierRawP wtid;
     json_t *wire;
     struct TALER_Amount amount;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
                                     &rowid),
@@ -5698,6 +5612,7 @@ postgres_select_wire_out_above_serial_id (void *cls,
                                    &amount),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -5705,73 +5620,101 @@ postgres_select_wire_out_above_serial_id (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      wosc->status = GNUNET_SYSERR;
+      return;
     }
-
-    ret = cb (cb_cls,
-              rowid,
-              date,
-              &wtid,
-              wire,
-              &amount);
+    ret = wosc->cb (wosc->cb_cls,
+                   rowid,
+                   date,
+                   &wtid,
+                   wire,
+                   &amount);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Function called to select payback requests the exchange
- * received, ordered by serial ID (monotonically increasing).
+ * Function called to select all wire transfers the exchange
+ * executed.
  *
  * @param cls closure
  * @param session database connection
- * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param serial_id highest serial ID to exclude (select strictly larger)
  * @param cb function to call for ONE unfinished item
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO if there are no entries,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_payback_above_serial_id (void *cls,
-                                         struct TALER_EXCHANGEDB_Session 
*session,
-                                         uint64_t serial_id,
-                                         TALER_EXCHANGEDB_PaybackCallback cb,
-                                         void *cb_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_select_wire_out_above_serial_id (void *cls,
+                                          struct TALER_EXCHANGEDB_Session 
*session,
+                                          uint64_t serial_id,
+                                          
TALER_EXCHANGEDB_WireTransferOutCallback cb,
+                                          void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "payback_get_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  int nrows;
-  int ret;
+  struct WireOutSerialContext wosc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_prepare_above_serial_id() returned 0 matching rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "audit_get_wire_incr",
+                                            params,
+                                            &wire_out_serial_helper_cb,
+                                            &wosc);
+  if (GNUNET_OK != wosc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
+
+
+/**
+ * Closure for #payback_serial_helper_cb().
+ */
+struct PaybackSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_PaybackCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PaybackSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+payback_serial_helper_cb (void *cls,
+                         PGresult *result,
+                         unsigned int num_results)
+{
+  struct PaybackSerialContext *psc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     uint64_t rowid;
     struct TALER_ReservePublicKeyP reserve_pub;
@@ -5804,6 +5747,7 @@ postgres_select_payback_above_serial_id (void *cls,
                                    &amount),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -5811,74 +5755,103 @@ postgres_select_payback_above_serial_id (void *cls,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      psc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              timestamp,
-              &amount,
-              &reserve_pub,
-              &coin,
-              &coin_sig,
-              &coin_blind);
+    ret = psc->cb (psc->cb_cls,
+                  rowid,
+                  timestamp,
+                  &amount,
+                  &reserve_pub,
+                  &coin,
+                  &coin_sig,
+                  &coin_blind);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
-
-  PQclear (result);
-  return GNUNET_OK;
 }
 
 
 /**
- * Function called to select reserve close operations the aggregator
- * triggered, ordered by serial ID (monotonically increasing).
+ * Function called to select payback requests the exchange
+ * received, ordered by serial ID (monotonically increasing).
  *
  * @param cls closure
  * @param session database connection
  * @param serial_id lowest serial ID to include (select larger or equal)
  * @param cb function to call for ONE unfinished item
  * @param cb_cls closure for @a cb
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO if there are no entries,
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
-postgres_select_reserve_closed_above_serial_id (void *cls,
-                                               struct TALER_EXCHANGEDB_Session 
*session,
-                                               uint64_t serial_id,
-                                               
TALER_EXCHANGEDB_ReserveClosedCallback cb,
-                                               void *cb_cls)
+static enum GNUNET_DB_QueryStatus
+postgres_select_payback_above_serial_id (void *cls,
+                                         struct TALER_EXCHANGEDB_Session 
*session,
+                                         uint64_t serial_id,
+                                         TALER_EXCHANGEDB_PaybackCallback cb,
+                                         void *cb_cls)
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&serial_id),
     GNUNET_PQ_query_param_end
   };
-  PGresult *result;
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "reserves_close_get_incr",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  int nrows;
-  int ret;
+  struct PaybackSerialContext psc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "payback_get_incr",
+                                            params,
+                                            &payback_serial_helper_cb,
+                                            &psc);
+  if (GNUNET_OK != psc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
+}
 
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "select_reserve_closed_above_serial_id() returned 0 matching 
rows\n");
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  for (int i=0;i<nrows;i++)
+
+/**
+ * Closure for #reserve_closed_serial_helper_cb().
+ */
+struct ReserveClosedSerialContext
+{
+
+  /**
+   * Callback to call.
+   */
+  TALER_EXCHANGEDB_ReserveClosedCallback cb;
+  
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+  
+  /**
+   * Status code, set to #GNUNET_SYSERR on hard errors.
+   */ 
+  int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveClosedSerialContext`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+reserve_closed_serial_helper_cb (void *cls,
+                                PGresult *result,
+                                unsigned int num_results)
+{
+  struct ReserveClosedSerialContext *rcsc = cls;
+  
+  for (unsigned int i=0;i<num_results;i++)
   {
     uint64_t rowid;
     struct TALER_ReservePublicKeyP reserve_pub;
@@ -5904,6 +5877,7 @@ postgres_select_reserve_closed_above_serial_id (void *cls,
                                    &closing_fee),
       GNUNET_PQ_result_spec_end
     };
+    int ret;
 
     if (GNUNET_OK !=
         GNUNET_PQ_extract_result (result,
@@ -5911,24 +5885,61 @@ postgres_select_reserve_closed_above_serial_id (void 
*cls,
                                   i))
     {
       GNUNET_break (0);
-      PQclear (result);
-      return GNUNET_SYSERR;
+      rcsc->status = GNUNET_SYSERR;
+      return;
     }
-    ret = cb (cb_cls,
-              rowid,
-              execution_date,
-              &amount_with_fee,
-             &closing_fee,
-              &reserve_pub,
-             receiver_account,
-              &wtid);
+    ret = rcsc->cb (rcsc->cb_cls,
+                   rowid,
+                   execution_date,
+                   &amount_with_fee,
+                   &closing_fee,
+                   &reserve_pub,
+                   receiver_account,
+                   &wtid);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
   }
+}
 
-  PQclear (result);
-  return GNUNET_OK;
+
+/**
+ * Function called to select reserve close operations the aggregator
+ * triggered, ordered by serial ID (monotonically increasing).
+ *
+ * @param cls closure
+ * @param session database connection
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_reserve_closed_above_serial_id (void *cls,
+                                               struct TALER_EXCHANGEDB_Session 
*session,
+                                               uint64_t serial_id,
+                                               
TALER_EXCHANGEDB_ReserveClosedCallback cb,
+                                               void *cb_cls)
+{
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_uint64 (&serial_id),
+    GNUNET_PQ_query_param_end
+  };
+  struct ReserveClosedSerialContext rcsc = {
+    .cb = cb,
+    .cb_cls = cb_cls,
+    .status = GNUNET_OK
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  
+  qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+                                            "reserves_close_get_incr",
+                                            params,
+                                            &reserve_closed_serial_helper_cb,
+                                            &rcsc);
+  if (GNUNET_OK != rcsc.status)
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  return qs;
 }
 
 
@@ -5973,32 +5984,13 @@ postgres_insert_payback_request (void *cls,
     GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
     GNUNET_PQ_query_param_end
   };
-  int ret;
   enum GNUNET_DB_QueryStatus qs;
 
   /* check if the coin is already known */
-  // FIXME: #5010!
-  ret = get_known_coin (cls,
-                        session,
-                        &coin->coin_pub,
-                        NULL);
-  if (GNUNET_SYSERR == ret)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_NO == ret)         /* if not, insert it */
-  {
-    qs = insert_known_coin (cls,
-                           session,
-                           coin);
-    if (0 > qs)
-    {
-      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      return qs;
-    }
-  }
-
+  if (0 > (qs = ensure_coin_known (cls,
+                                  session,
+                                  coin)))
+    return qs;
   /* now store actual payback information */
   qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
                                           "payback_insert",
@@ -6113,11 +6105,9 @@ postgres_insert_denomination_revocation (void *cls,
  * @param denom_pub_hash hash of the revoked denomination key
  * @param[out] master_sig signature affirming the revocation
  * @param[out] rowid row where the information is stored
- * @return #GNUNET_OK on success,
- *         #GNUNET_NO no such entry exists
- *         #GNUNET_SYSERR on DB errors
+ * @return transaction status code
  */
-static int
+static enum GNUNET_DB_QueryStatus
 postgres_get_denomination_revocation (void *cls,
                                       struct TALER_EXCHANGEDB_Session *session,
                                       const struct GNUNET_HashCode 
*denom_pub_hash,
@@ -6133,42 +6123,11 @@ postgres_get_denomination_revocation (void *cls,
     GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id", rowid),
     GNUNET_PQ_result_spec_end
   };
-  PGresult *result;
-  int nrows;
 
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    "denomination_revocation_get",
-                                    params);
-  if (PGRES_TUPLES_OK !=
-      PQresultStatus (result))
-  {
-    BREAK_DB_ERR (result, session->conn);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  nrows = PQntuples (result);
-  if (0 == nrows)
-  {
-    /* no matches found */
-    PQclear (result);
-    return GNUNET_NO;
-  }
-  if (1 != nrows)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result,
-                                rs,
-                                0))
-  {
-    PQclear (result);
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
+  return GNUNET_PQ_eval_prepared_singleton_select (session->conn,
+                                                  
"denomination_revocation_get",
+                                                  params,
+                                                  rs);
 }
 
 
@@ -6288,7 +6247,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->select_reserves_out_above_serial_id = 
&postgres_select_reserves_out_above_serial_id;
   plugin->select_wire_out_above_serial_id = 
&postgres_select_wire_out_above_serial_id;
   plugin->select_payback_above_serial_id = 
&postgres_select_payback_above_serial_id;
-    plugin->select_reserve_closed_above_serial_id = 
&postgres_select_reserve_closed_above_serial_id;
+  plugin->select_reserve_closed_above_serial_id = 
&postgres_select_reserve_closed_above_serial_id;
   plugin->insert_payback_request = &postgres_insert_payback_request;
   plugin->get_reserve_by_h_blind = &postgres_get_reserve_by_h_blind;
   plugin->insert_denomination_revocation = 
&postgres_insert_denomination_revocation;
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 4ca7c39..6b89577 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -98,7 +98,7 @@ mark_prepare_cb (void *cls,
   GNUNET_assert (0 == memcmp (buf,
                               "hello world",
                               buf_size));
-  GNUNET_break (GNUNET_OK ==
+  GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
                 plugin->wire_prepare_data_mark_finished (plugin->cls,
                                                          session,
                                                          rowid));
@@ -114,7 +114,7 @@ mark_prepare_cb (void *cls,
 static int
 test_wire_prepare (struct TALER_EXCHANGEDB_Session *session)
 {
-  FAILIF (GNUNET_NO !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->wire_prepare_data_get (plugin->cls,
                                          session,
                                          &dead_prepare_cb,
@@ -125,12 +125,12 @@ test_wire_prepare (struct TALER_EXCHANGEDB_Session 
*session)
                                             "testcase",
                                             "hello world",
                                             11));
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->wire_prepare_data_get (plugin->cls,
                                          session,
                                          &mark_prepare_cb,
                                          session));
-  FAILIF (GNUNET_NO !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->wire_prepare_data_get (plugin->cls,
                                          session,
                                          &dead_prepare_cb,
@@ -583,7 +583,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
                                       &ret_refresh_session));
 
   auditor_row_cnt = 0;
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
          plugin->select_refreshs_above_serial_id (plugin->cls,
                                                   session,
                                                   0,
@@ -914,10 +914,9 @@ static uint64_t deposit_rowid;
  * @param wire_deadline by which the merchant adviced that he would like the
  *        wire transfer to be executed
  * @param wire wire details for the merchant, NULL from 
iterate_matching_deposits()
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR if deposit does
- *         not match our expectations
+ * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
-static int
+static enum GNUNET_DB_QueryStatus
 deposit_cb (void *cls,
             uint64_t rowid,
             const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -953,10 +952,10 @@ deposit_cb (void *cls,
                        sizeof (struct GNUNET_HashCode))) ) )
   {
     GNUNET_break (0);
-    return GNUNET_SYSERR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
-  return GNUNET_OK;
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -1164,7 +1163,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               &master_sig,
                               sizeof (master_sig));
-  if (GNUNET_OK !=
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
       plugin->insert_wire_fee (plugin->cls,
                                session,
                                "wire-method",
@@ -1176,7 +1175,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  if (GNUNET_OK !=
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
       plugin->insert_wire_fee (plugin->cls,
                                session,
                                "wire-method",
@@ -1329,7 +1328,7 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
                                               NULL));
   }
   /* insert WT data */
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_aggregation_tracking (plugin->cls,
                                                session,
                                                &wire_out_wtid,
@@ -1337,7 +1336,7 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
 
   /* Now let's fix the transient constraint violation by
      putting in the WTID into the wire_out table */
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->store_wire_transfer_out (plugin->cls,
                                            session,
                                            wire_out_date,
@@ -1364,7 +1363,7 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
                                             &merchant_pub_wt,
                                             &cb_wtid_check,
                                             &cb_wtid_never));
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->select_wire_out_above_serial_id (plugin->cls,
                                                    session,
                                                    0,
@@ -1489,7 +1488,7 @@ run (void *cls)
                          session));
 
   /* test DB is empty */
-  FAILIF (GNUNET_NO !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->select_payback_above_serial_id (plugin->cls,
                                                   session,
                                                   0,
@@ -1651,7 +1650,7 @@ run (void *cls)
                                           &value,
                                           &cbc.h_coin_envelope,
                                           deadline));
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->select_payback_above_serial_id (plugin->cls,
                                                   session,
                                                   0,
@@ -1754,13 +1753,13 @@ run (void *cls)
   FAILIF (5 != cnt);
 
   auditor_row_cnt = 0;
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >=
           plugin->select_reserves_in_above_serial_id (plugin->cls,
                                                      session,
                                                      0,
                                                      &audit_reserve_in_cb,
                                                      NULL));
-  FAILIF (GNUNET_OK !=
+  FAILIF (0 >=
           plugin->select_reserves_out_above_serial_id (plugin->cls,
                                                       session,
                                                       0,
@@ -1792,7 +1791,7 @@ run (void *cls)
                                 session,
                                 &deposit));
   auditor_row_cnt = 0;
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->select_deposits_above_serial_id (plugin->cls,
                                                   session,
                                                   0,
@@ -1800,7 +1799,7 @@ run (void *cls)
                                                   NULL));
   FAILIF (1 != auditor_row_cnt);
   result = 9;
-  FAILIF (1 !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->iterate_matching_deposits (plugin->cls,
                                              session,
                                              &deposit.h_wire,
@@ -1808,7 +1807,7 @@ run (void *cls)
                                              &deposit_cb, &deposit,
                                              2));
 
-  FAILIF (1 !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_ready_deposit (plugin->cls,
                                      session,
                                      &deposit_cb,
@@ -1821,16 +1820,16 @@ run (void *cls)
                          session));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->mark_deposit_tiny (plugin->cls,
-                                     session,
+                                    session,
                                      deposit_rowid));
-  FAILIF (0 !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->get_ready_deposit (plugin->cls,
                                      session,
                                      &deposit_cb,
                                      &deposit));
   plugin->rollback (plugin->cls,
                     session);
-  FAILIF (1 !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_ready_deposit (plugin->cls,
                                      session,
                                      &deposit_cb,
@@ -1838,18 +1837,18 @@ run (void *cls)
   FAILIF (GNUNET_OK !=
           plugin->start (plugin->cls,
                          session));
-  FAILIF (GNUNET_NO !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->test_deposit_done (plugin->cls,
                                      session,
                                      &deposit));
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->mark_deposit_done (plugin->cls,
                                      session,
                                      deposit_rowid));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls,
                           session));
-  FAILIF (GNUNET_YES !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->test_deposit_done (plugin->cls,
                                      session,
                                      &deposit));
@@ -1857,17 +1856,18 @@ run (void *cls)
   result = 10;
   deposit2 = deposit;
   RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
-  FAILIF (0 !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->have_deposit (plugin->cls,
                                 session,
                                 &deposit2));
   deposit2.merchant_pub = deposit.merchant_pub;
   RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
-  FAILIF (0 !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->have_deposit (plugin->cls,
                                 session,
                                 &deposit2));
-  FAILIF (GNUNET_OK != test_melting (session));
+  FAILIF (GNUNET_OK !=
+         test_melting (session));
 
 
   /* test insert_refund! */
@@ -1886,7 +1886,7 @@ run (void *cls)
 
   /* test payback / revocation */
   RND_BLK (&master_sig);
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_denomination_revocation (plugin->cls,
                                                   session,
                                                   &dkp_pub_hash,
@@ -1897,7 +1897,7 @@ run (void *cls)
   FAILIF (GNUNET_OK !=
           plugin->start (plugin->cls,
                          session));
-  FAILIF (GNUNET_NO !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->insert_denomination_revocation (plugin->cls,
                                                   session,
                                                   &dkp_pub_hash,
@@ -1937,7 +1937,7 @@ run (void *cls)
                                           deadline));
 
   auditor_row_cnt = 0;
-  FAILIF (GNUNET_OK !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->select_refunds_above_serial_id (plugin->cls,
                                                  session,
                                                  0,
@@ -2131,3 +2131,5 @@ main (int argc,
   GNUNET_free (testname);
   return result;
 }
+
+/* end of test_exchangedb.c */
diff --git a/src/include/taler_auditordb_plugin.h 
b/src/include/taler_auditordb_plugin.h
index e4e6f34..3141ad6 100644
--- a/src/include/taler_auditordb_plugin.h
+++ b/src/include/taler_auditordb_plugin.h
@@ -24,6 +24,7 @@
 
 #include <jansson.h>
 #include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
 #include "taler_auditordb_lib.h"
 #include "taler_signatures.h"
 
@@ -236,10 +237,9 @@ struct TALER_AUDITORDB_Plugin
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to use
-   * @return #GNUNET_OK on success, #GNUNET_NO if the transaction
-   *         can be retried, #GNUNET_SYSERR on hard failures
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*commit) (void *cls,
              struct TALER_AUDITORDB_Session *session);
 
@@ -291,9 +291,9 @@ struct TALER_AUDITORDB_Plugin
    * @param master_pub master public key of the exchange
    * @param cb function to call with the results
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_denomination_info)(void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct TALER_MasterPublicKeyP *master_pub,
@@ -309,9 +309,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master key of the exchange
    * @param pp where is the auditor in processing
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_auditor_progress)(void *cls,
                              struct TALER_AUDITORDB_Session *session,
                              const struct TALER_MasterPublicKeyP *master_pub,
@@ -326,9 +326,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master key of the exchange
    * @param pp where is the auditor in processing
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_auditor_progress)(void *cls,
                              struct TALER_AUDITORDB_Session *session,
                              const struct TALER_MasterPublicKeyP *master_pub,
@@ -342,10 +342,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master key of the exchange
    * @param[out] pp set to where the auditor is in processing
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure;
-   *         #GNUNET_NO if we have no records for the @a master_pub
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_auditor_progress)(void *cls,
                           struct TALER_AUDITORDB_Session *session,
                           const struct TALER_MasterPublicKeyP *master_pub,
@@ -364,9 +363,9 @@ struct TALER_AUDITORDB_Plugin
    * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    *                             due to withdrawals from this reserve
    * @param expiration_date expiration date of the reserve
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_reserve_info)(void *cls,
                          struct TALER_AUDITORDB_Session *session,
                          const struct TALER_ReservePublicKeyP *reserve_pub,
@@ -388,9 +387,9 @@ struct TALER_AUDITORDB_Plugin
    * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    *                             due to withdrawals from this reserve
    * @param expiration_date expiration date of the reserve
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_reserve_info)(void *cls,
                          struct TALER_AUDITORDB_Session *session,
                          const struct TALER_ReservePublicKeyP *reserve_pub,
@@ -412,10 +411,9 @@ struct TALER_AUDITORDB_Plugin
    * @param[out] withdraw_fee_balance amount the exchange gained in withdraw 
fees
    *                             due to withdrawals from this reserve
    * @param[out] expiration_date expiration date of the reserve
-   * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
-   *         record about this reserve; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_reserve_info)(void *cls,
                       struct TALER_AUDITORDB_Session *session,
                       const struct TALER_ReservePublicKeyP *reserve_pub,
@@ -433,10 +431,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param reserve_pub public key of the reserve
    * @param master_pub master public key of the exchange
-   * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
-   *         record about this reserve; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*del_reserve_info)(void *cls,
                       struct TALER_AUDITORDB_Session *session,
                       const struct TALER_ReservePublicKeyP *reserve_pub,
@@ -453,9 +450,9 @@ struct TALER_AUDITORDB_Plugin
    * @param reserve_balance amount stored in the reserve
    * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    *                             due to withdrawals from this reserve
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_reserve_summary)(void *cls,
                             struct TALER_AUDITORDB_Session *session,
                             const struct TALER_MasterPublicKeyP *master_pub,
@@ -473,9 +470,9 @@ struct TALER_AUDITORDB_Plugin
    * @param reserve_balance amount stored in the reserve
    * @param withdraw_fee_balance amount the exchange gained in withdraw fees
    *                             due to withdrawals from this reserve
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_reserve_summary)(void *cls,
                             struct TALER_AUDITORDB_Session *session,
                             const struct TALER_MasterPublicKeyP *master_pub,
@@ -492,10 +489,9 @@ struct TALER_AUDITORDB_Plugin
    * @param[out] reserve_balance amount stored in the reserve
    * @param[out] withdraw_fee_balance amount the exchange gained in withdraw 
fees
    *                             due to withdrawals from this reserve
-   * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
-   *         record about this exchange; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_reserve_summary)(void *cls,
                          struct TALER_AUDITORDB_Session *session,
                          const struct TALER_MasterPublicKeyP *master_pub,
@@ -511,9 +507,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master public key of the exchange
    * @param wire_fee_balance amount the exchange gained in wire fees
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_wire_fee_summary)(void *cls,
                              struct TALER_AUDITORDB_Session *session,
                              const struct TALER_MasterPublicKeyP *master_pub,
@@ -528,9 +524,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master public key of the exchange
    * @param wire_fee_balance amount the exchange gained in wire fees
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_wire_fee_summary)(void *cls,
                              struct TALER_AUDITORDB_Session *session,
                              const struct TALER_MasterPublicKeyP *master_pub,
@@ -544,10 +540,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master public key of the exchange
    * @param[out] wire_fee_balance set amount the exchange gained in wire fees
-   * @return #GNUNET_OK on success; #GNUNET_NO if there is no known
-   *         record about this exchange; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_wire_fee_summary)(void *cls,
                           struct TALER_AUDITORDB_Session *session,
                           const struct TALER_MasterPublicKeyP *master_pub,
@@ -563,9 +558,9 @@ struct TALER_AUDITORDB_Plugin
    * @param denom_pub_hash hash of the denomination public key
    * @param denom_balance value of coins outstanding with this denomination key
    * @param denom_risk value of coins issued with this denomination key
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_denomination_balance)(void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct GNUNET_HashCode *denom_pub_hash,
@@ -582,9 +577,9 @@ struct TALER_AUDITORDB_Plugin
    * @param denom_pub_hash hash of the denomination public key
    * @param denom_balance value of coins outstanding with this denomination key
    * @param denom_risk value of coins issued with this denomination key
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_denomination_balance)(void *cls,
                                  struct TALER_AUDITORDB_Session *session,
                                  const struct GNUNET_HashCode *denom_pub_hash,
@@ -600,9 +595,9 @@ struct TALER_AUDITORDB_Plugin
    * @param denom_pub_hash hash of the denomination public key
    * @param[out] denom_balance value of coins outstanding with this 
denomination key
    * @param[out] denom_risk value of coins issued with this denomination key
-   * @return #GNUNET_OK on success; #GNUNET_NO if no record found, 
#GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_denomination_balance)(void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct GNUNET_HashCode *denom_pub_hash,
@@ -616,9 +611,9 @@ struct TALER_AUDITORDB_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to use
    * @param denom_pub_hash hash of the denomination public key
-   * @return #GNUNET_OK on success; #GNUNET_NO if no record found, 
#GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*del_denomination_balance)(void *cls,
                               struct TALER_AUDITORDB_Session *session,
                               const struct GNUNET_HashCode *denom_pub_hash);
@@ -636,9 +631,9 @@ struct TALER_AUDITORDB_Plugin
    * @param melt_fee_balance total melt fees collected for this DK
    * @param refund_fee_balance total refund fees collected for this DK
    * @param risk maximum risk exposure of the exchange
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_balance_summary)(void *cls,
                             struct TALER_AUDITORDB_Session *session,
                             const struct TALER_MasterPublicKeyP *master_pub,
@@ -661,9 +656,9 @@ struct TALER_AUDITORDB_Plugin
    * @param melt_fee_balance total melt fees collected for this DK
    * @param refund_fee_balance total refund fees collected for this DK
    * @param risk maximum risk exposure of the exchange
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_balance_summary)(void *cls,
                             struct TALER_AUDITORDB_Session *session,
                             const struct TALER_MasterPublicKeyP *master_pub,
@@ -685,10 +680,9 @@ struct TALER_AUDITORDB_Plugin
    * @param[out] melt_fee_balance total melt fees collected for this DK
    * @param[out] refund_fee_balance total refund fees collected for this DK
    * @param[out] risk maximum risk exposure of the exchange
-   * @return #GNUNET_OK on success; #GNUNET_NO if there is no entry
-   *           for this @a master_pub; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_balance_summary)(void *cls,
                          struct TALER_AUDITORDB_Session *session,
                          const struct TALER_MasterPublicKeyP *master_pub,
@@ -711,9 +705,9 @@ struct TALER_AUDITORDB_Plugin
    * @param revenue_balance what was the total profit made from
    *                        deposit fees, melting fees, refresh fees
    *                        and coins that were never returned?
-     * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_historic_denom_revenue)(void *cls,
                                    struct TALER_AUDITORDB_Session *session,
                                    const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -731,9 +725,9 @@ struct TALER_AUDITORDB_Plugin
    * @param master_pub master key of the exchange
    * @param cb function to call with the results
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_historic_denom_revenue)(void *cls,
                                    struct TALER_AUDITORDB_Session *session,
                                    const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -754,9 +748,9 @@ struct TALER_AUDITORDB_Plugin
    * @param denom_pub_hash hash of the denomination key
    * @param loss_timestamp when did this profit get realized
    * @param loss_balance what was the total loss
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_historic_losses)(void *cls,
                             struct TALER_AUDITORDB_Session *session,
                             const struct TALER_MasterPublicKeyP *master_pub,
@@ -773,9 +767,9 @@ struct TALER_AUDITORDB_Plugin
    * @param master_pub master key of the exchange
    * @param cb function to call with the results
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_historic_losses)(void *cls,
                             struct TALER_AUDITORDB_Session *session,
                             const struct TALER_MasterPublicKeyP *master_pub,
@@ -792,9 +786,9 @@ struct TALER_AUDITORDB_Plugin
    * @param start_time beginning of aggregated time interval
    * @param end_time end of aggregated time interval
    * @param reserve_profits total profits made
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_historic_reserve_revenue)(void *cls,
                                      struct TALER_AUDITORDB_Session *session,
                                      const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -811,9 +805,9 @@ struct TALER_AUDITORDB_Plugin
    * @param master_pub master key of the exchange
    * @param cb function to call with results
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_historic_reserve_revenue)(void *cls,
                                      struct TALER_AUDITORDB_Session *session,
                                      const struct TALER_MasterPublicKeyP 
*master_pub,
@@ -830,9 +824,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master key of the exchange
    * @param balance what the bank account balance of the exchange should show
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_predicted_result)(void *cls,
                              struct TALER_AUDITORDB_Session *session,
                              const struct TALER_MasterPublicKeyP *master_pub,
@@ -847,9 +841,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master key of the exchange
    * @param balance what the bank account balance of the exchange should show
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*update_predicted_result)(void *cls,
                              struct TALER_AUDITORDB_Session *session,
                              const struct TALER_MasterPublicKeyP *master_pub,
@@ -863,10 +857,9 @@ struct TALER_AUDITORDB_Plugin
    * @param session connection to use
    * @param master_pub master key of the exchange
    * @param[out] balance expected bank account balance of the exchange
-   * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure;
-   *         #GNUNET_NO if we have no records for the @a master_pub
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_predicted_balance)(void *cls,
                            struct TALER_AUDITORDB_Session *session,
                            const struct TALER_MasterPublicKeyP *master_pub,
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 9f80fda..2cc2c75 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -674,9 +674,9 @@ struct TALER_EXCHANGEDB_Session;
  * @param wire_deadline by which the merchant adviced that he would like the
  *        wire transfer to be executed
  * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
-typedef int
+typedef enum GNUNET_DB_QueryStatus
 (*TALER_EXCHANGEDB_DepositIterator)(void *cls,
                                     uint64_t rowid,
                                     const struct TALER_MerchantPublicKeyP 
*merchant_pub,
@@ -1383,10 +1383,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session connection to the database
    * @param deposit_cb function to call for ONE such deposit
    * @param deposit_cb_cls closure for @a deposit_cb
-   * @return number of rows processed, 0 if none exist,
-   *         #GNUNET_SYSERR on error
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_ready_deposit) (void *cls,
                         struct TALER_EXCHANGEDB_Session *session,
                         TALER_EXCHANGEDB_DepositIterator deposit_cb,
@@ -1418,9 +1417,9 @@ struct TALER_EXCHANGEDB_Plugin
    *        be #TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT, larger values
    *        are not supported, smaller values would be inefficient.
    * @return number of rows processed, 0 if none exist,
-   *         #GNUNET_SYSERR on error
+   *         transaction status code on error
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*iterate_matching_deposits) (void *cls,
                                 struct TALER_EXCHANGEDB_Session *session,
                                 const struct GNUNET_HashCode *h_wire,
@@ -1753,11 +1752,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database connection
    * @param wtid the raw wire transfer identifier we used
    * @param deposit_serial_id row in the deposits table for which this is 
aggregation data
-   * @return #GNUNET_OK on success
-   *         #GNUNET_NO on transient errors
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_aggregation_tracking)(void *cls,
                                  struct TALER_EXCHANGEDB_Session *session,
                                  const struct TALER_WireTransferIdentifierRawP 
*wtid,
@@ -1774,11 +1771,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param end_date when does the fee end being valid
    * @param wire_fee how high is the wire transfer fee
    * @param master_sig signature over the above by the exchange master key
-   * @return #GNUNET_OK on success or if the record exists,
-   *         #GNUNET_NO on transient errors,
-   *         #GNUNET_SYSERR on failure
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*insert_wire_fee)(void *cls,
                      struct TALER_EXCHANGEDB_Session *session,
                      const char *wire_method,
@@ -1787,7 +1782,7 @@ struct TALER_EXCHANGEDB_Plugin
                      const struct TALER_Amount *wire_fee,
                      const struct TALER_MasterSignatureP *master_sig);
 
-
+  
   /**
    * Obtain wire fee from database.
    *
@@ -1879,9 +1874,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param cls closure
    * @param session database connection
    * @param rowid which entry to mark as finished
-   * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*wire_prepare_data_mark_finished)(void *cls,
                                      struct TALER_EXCHANGEDB_Session *session,
                                      uint64_t rowid);
@@ -1895,11 +1890,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param session database connection
    * @param cb function to call for ONE unfinished item
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO if there are no entries,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*wire_prepare_data_get)(void *cls,
                            struct TALER_EXCHANGEDB_Session *session,
                            TALER_EXCHANGEDB_WirePreparationIterator cb,
@@ -1930,10 +1923,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param wtid subject of the wire transfer
    * @param wire_account details about the receiver account of the wire 
transfer
    * @param amount amount that was transmitted
-   * @return #GNUNET_OK on success
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*store_wire_transfer_out)(void *cls,
                              struct TALER_EXCHANGEDB_Session *session,
                              struct GNUNET_TIME_Absolute date,
@@ -1971,10 +1963,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id highest serial ID to exclude (select strictly larger)
    * @param cb function to call on each result
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_deposits_above_serial_id)(void *cls,
                                      struct TALER_EXCHANGEDB_Session *session,
                                      uint64_t serial_id,
@@ -1990,10 +1981,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id highest serial ID to exclude (select strictly larger)
    * @param cb function to call on each result
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_refreshs_above_serial_id)(void *cls,
                                      struct TALER_EXCHANGEDB_Session *session,
                                      uint64_t serial_id,
@@ -2010,10 +2000,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id highest serial ID to exclude (select strictly larger)
    * @param cb function to call on each result
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_refunds_above_serial_id)(void *cls,
                                     struct TALER_EXCHANGEDB_Session *session,
                                     uint64_t serial_id,
@@ -2030,10 +2019,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id highest serial ID to exclude (select strictly larger)
    * @param cb function to call on each result
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_reserves_in_above_serial_id)(void *cls,
                                         struct TALER_EXCHANGEDB_Session 
*session,
                                         uint64_t serial_id,
@@ -2049,11 +2037,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id highest serial ID to exclude (select strictly larger)
    * @param cb function to call on each result
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO if no records were found
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_reserves_out_above_serial_id)(void *cls,
                                          struct TALER_EXCHANGEDB_Session 
*session,
                                          uint64_t serial_id,
@@ -2070,11 +2056,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id lowest serial ID to include (select larger or equal)
    * @param cb function to call for ONE unfinished item
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO if there are no entries,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_wire_out_above_serial_id)(void *cls,
                                      struct TALER_EXCHANGEDB_Session *session,
                                      uint64_t serial_id,
@@ -2091,11 +2075,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id lowest serial ID to include (select larger or equal)
    * @param cb function to call for ONE unfinished item
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO if there are no entries,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_payback_above_serial_id)(void *cls,
                                     struct TALER_EXCHANGEDB_Session *session,
                                     uint64_t serial_id,
@@ -2112,11 +2094,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param serial_id lowest serial ID to include (select larger or equal)
    * @param cb function to call
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO if there are no entries,
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*select_reserve_closed_above_serial_id)(void *cls,
                                           struct TALER_EXCHANGEDB_Session 
*session,
                                           uint64_t serial_id,
@@ -2199,11 +2179,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param denom_pub_hash hash of the revoked denomination key
    * @param[out] master_sig signature affirming the revocation
    * @param[out] rowid row where the information is stored
-   * @return #GNUNET_OK on success,
-   *         #GNUNET_NO no such entry exists
-   *         #GNUNET_SYSERR on DB errors
+   * @return transaction status code
    */
-  int
+  enum GNUNET_DB_QueryStatus
   (*get_denomination_revocation)(void *cls,
                                  struct TALER_EXCHANGEDB_Session *session,
                                  const struct GNUNET_HashCode *denom_pub_hash,

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]