src/Pure/General/sql.scala
changeset 78355 9fbc6a043268
parent 78354 3b8f100f6385
child 78356 974dbe256a37
--- a/src/Pure/General/sql.scala	Sun Jul 16 10:50:40 2023 +0200
+++ b/src/Pure/General/sql.scala	Sun Jul 16 11:03:10 2023 +0200
@@ -242,10 +242,11 @@
     def iterator: Iterator[Table] = list.iterator
 
     // requires transaction
-    def lock(db: Database, create: Boolean = false): Unit = {
+    def lock(db: Database, create: Boolean = false): Boolean = {
       if (create) foreach(db.create_table(_))
       val sql = db.lock_tables(list)
-      if (sql.nonEmpty) db.execute_statement(sql)
+      if (sql.nonEmpty) { db.execute_statement(sql); true }
+      else false
     }
   }
 
@@ -255,9 +256,10 @@
     def transaction_lock[A](
       db: Database,
       create: Boolean = false,
+      log: Logger = new System_Logger,
       synchronized: Boolean = false,
     )(body: => A): A = {
-      def run: A = db.transaction_lock(tables, create = create)(body)
+      def run: A = db.transaction_lock(tables, create = create, log = log)(body)
       if (synchronized) db.synchronized { run } else run
     }
 
@@ -452,8 +454,38 @@
       finally { connection.setAutoCommit(auto_commit) }
     }
 
-    def transaction_lock[A](tables: Tables, create: Boolean = false)(body: => A): A =
-      transaction { tables.lock(db, create = create); body }
+    private var _transaction_count: Int = 0
+    private def transaction_count(): Int =
+      synchronized { _transaction_count += 1; _transaction_count }
+
+    def transaction_lock[A](
+      tables: Tables,
+      create: Boolean = false,
+      log: Logger = new System_Logger
+    )(body: => A): A = {
+      val trace_enabled = System.getProperty("isabelle.transaction_log", "") == "true"
+
+      val trace_count = if (trace_enabled) transaction_count() else 0
+      val trace_start = Time.now()
+
+      def trace(msg: => String, nl: Boolean = false): Unit = {
+        if (trace_enabled) {
+          val trace_time = Time.now() - trace_start
+          log((if (nl) "\n" else "") + trace_time + " transaction " + trace_count + ": " + msg)
+        }
+      }
+
+      val res =
+        transaction {
+          trace("begin", nl = true)
+          if (tables.lock(db, create = create)) trace("locked")
+          val res = Exn.capture { body }
+          trace("end")
+          res
+        }
+      trace("commit")
+      Exn.release(res)
+    }
 
     def lock_tables(tables: List[Table]): Source = ""  // PostgreSQL only