commit 935916bce92eaed0844e284c7aba1b6cb1c4035e
parent 16d84e8a146dd3eacab92315ad2f654066e11066
Author: Christian Grothoff <christian@grothoff.org>
Date: Thu, 6 Aug 2026 00:07:38 +0200
remove bogus COMMIT in the middle of sql_global_procedures
Diffstat:
3 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/src/backenddb/gc.sql b/src/backenddb/gc.sql
@@ -53,5 +53,10 @@ COMMENT ON PROCEDURE merchant_do_gc
' For each'
' instance runs merchant_statistic_*_gc and DELETEs expired tan_challenges'
' / merchant_unclaim_signatures.';
-
-COMMIT;
+-- Note: deliberately no COMMIT here. gen-procedures.sh wraps the entire
+-- concatenation of sql_global_procedures in a single BEGIN ... COMMIT;
+-- a COMMIT in this file would close that transaction early, so everything
+-- appended after this file would be installed outside of it (and the
+-- generator's own trailing COMMIT would warn 'there is no transaction in
+-- progress'). The COMMIT inside the procedure body above is a plpgsql
+-- transaction-control statement and is unrelated.
diff --git a/src/backenddb/sql-schema/check-procedures-tx.sh b/src/backenddb/sql-schema/check-procedures-tx.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+# This file is part of TALER
+# Copyright (C) 2026 Taler Systems SA
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+#
+# Checks that none of the SQL files that gen-procedures.sh concatenates into
+# global_procedures.sql / instance_procedures.sql contains a transaction
+# control statement at the top level: gen-procedures.sh wraps the WHOLE
+# concatenation in a single BEGIN ... COMMIT, so a stray COMMIT would close
+# that transaction early and everything appended after it would be installed
+# outside of it. Transaction control inside a $$-quoted procedure body is a
+# plpgsql statement and is fine.
+
+set -eu
+
+if [ $# -lt 1 ]; then
+ echo "Usage: $0 SQLFILES..." >&2
+ exit 1
+fi
+
+status=0
+for x in "$@"; do
+ if ! awk -v fname="$x" '
+ {
+ line = $0;
+ sub(/--.*/, "", line);
+ # An odd number of dollar quotes ($$, $FN$, ...) on a line enters
+ # or leaves a procedure body.
+ n = gsub(/\$[A-Za-z_0-9]*\$/, "", line);
+ if (n % 2 == 1)
+ inbody = ! inbody;
+ if (inbody)
+ next;
+ if (line ~ /^[ \t]*(BEGIN|COMMIT|ROLLBACK|START[ \t]+TRANSACTION)[ \t]*;/)
+ {
+ printf "%s:%d: top-level transaction control statement: %s\n",
+ fname, NR, $0;
+ bad = 1;
+ }
+ }
+ END { exit bad ? 1 : 0 }' "$x"
+ then
+ status=1
+ fi
+done
+
+if [ 0 != "$status" ]; then
+ echo "Top-level transaction control found in a procedure file;" >&2
+ echo "gen-procedures.sh already wraps them in BEGIN ... COMMIT." >&2
+fi
+exit "$status"
diff --git a/src/backenddb/sql-schema/meson.build b/src/backenddb/sql-schema/meson.build
@@ -78,6 +78,16 @@ iprocedures_sql = custom_target('instance_procedures',
install: true,
install_dir: sqldir)
+# gen-procedures.sh wraps each concatenation above in a single
+# BEGIN ... COMMIT; make sure no input file closes that transaction early.
+test(
+ 'sql-procedures-transactions',
+ find_program('check-procedures-tx.sh'),
+ args: sql_global_procedures + sql_instance_procedures,
+ workdir: meson.current_source_dir(),
+ suite: ['backenddb'],
+)
+
generated_sql = [
['drop.sql'],
['versioning.sql'],