###############################################################################
#
# tkt-1f7bfff467.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

###############################################################################

runTest {test tkt-1f7bfff467-1.0 {rollback nested transaction} -setup {
  setupDb [set fileName tkt-1f7bfff467-1.0.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(1);
    INSERT INTO t1(x) VALUES(2);
    INSERT INTO t1(x) VALUES(3);
  }

  catch {
    set result [list]

    lappend result [sql execute \
        -execute scalar $db "SELECT COUNT(*) FROM t1;"]

    set transaction(1) [sql transaction begin $db]

    sql execute -transaction $transaction(1) $db \
        "INSERT INTO t1(x) VALUES(4);"

    lappend result [sql execute -transaction $transaction(1) \
        -execute reader -format list $db \
        "SELECT x FROM t1 ORDER BY x;"]

    set transaction(2) [sql transaction begin $db]

    sql execute -transaction $transaction(2) $db \
        "DELETE FROM t1 WHERE x = 2;"

    lappend result [sql execute -transaction $transaction(2) \
        -execute reader -format list $db \
        "SELECT x FROM t1 ORDER BY x;"]

    sql transaction rollback $transaction(2)

    sql execute -transaction $transaction(1) $db \
        "UPDATE t1 SET x = 9 WHERE x = 3;"

    sql transaction commit $transaction(1)

    lappend result [sql execute \
        -execute reader -format list $db \
        "SELECT x FROM t1 ORDER BY x;"]

    set result
  } error

  extractSystemDataSQLiteExceptionMessage $error
} -cleanup {
  catch {sql transaction rollback $transaction(2)}
  catch {sql transaction rollback $transaction(1)}

  cleanupDb $fileName

  catch {removeDbTransaction $transaction(2)}
  catch {removeDbTransaction $transaction(1)}

  unset -nocomplain error result transaction db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result {unknown error -- No transaction is active on this\
connection}}

###############################################################################

runTest {test tkt-1f7bfff467-1.1 {rollback nested transaction} -setup {
  setupDb [set fileName tkt-1f7bfff467-1.1.db] "" "" "" AllowNestedTransactions
} -body {
  sql execute $db {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(1);
    INSERT INTO t1(x) VALUES(2);
    INSERT INTO t1(x) VALUES(3);
  }

  set result [list]

  lappend result [sql execute \
      -execute scalar $db "SELECT COUNT(*) FROM t1;"]

  set transaction(1) [sql transaction begin $db]

  sql execute -transaction $transaction(1) $db \
      "INSERT INTO t1(x) VALUES(4);"

  lappend result [sql execute -transaction $transaction(1) \
      -execute reader -format list $db \
      "SELECT x FROM t1 ORDER BY x;"]

  set transaction(2) [sql transaction begin $db]

  sql execute -transaction $transaction(2) $db \
      "DELETE FROM t1 WHERE x = 2;"

  lappend result [sql execute -transaction $transaction(2) \
      -execute reader -format list $db \
      "SELECT x FROM t1 ORDER BY x;"]

  sql transaction rollback $transaction(2)

  sql execute -transaction $transaction(1) $db \
      "UPDATE t1 SET x = 9 WHERE x = 3;"

  sql transaction commit $transaction(1)

  lappend result [sql execute \
      -execute reader -format list $db \
      "SELECT x FROM t1 ORDER BY x;"]

  set result
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result transaction db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result {3 {1 2 3 4} {1 3 4} {1 2 4 9}}}

###############################################################################

runTest {test tkt-1f7bfff467-1.2 {commit outer transaction} -setup {
  setupDb [set fileName tkt-1f7bfff467-1.2.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(1);
  }

  set sql(1) { \
    INSERT INTO t1(x) VALUES(2); \
  }

  set sql(2) { \
    INSERT INTO t1(x) VALUES(3); \
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set flags AllowNestedTransactions

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};[getTestProperties ${flags}]"))
          {
            connection.Open();

            using (SQLiteTransaction transaction1 =
                connection.BeginTransaction())
            {
              using (SQLiteCommand command1 = new SQLiteCommand(
                  "${sql(1)}", connection))
              {
                command1.Transaction = transaction1;
                command1.ExecuteNonQuery();
              }

              using (SQLiteTransaction transaction2 =
                  connection.BeginTransaction())
              {
                using (SQLiteCommand command2 = new SQLiteCommand(
                    "${sql(2)}", connection))
                {
                  command2.Transaction = transaction2;
                  command2.ExecuteNonQuery();

                  transaction1.Commit();
                }
              }
            }
          }
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result \
      [sql execute -execute reader -format list $db \
          "SELECT x FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result results errors code
  unset -nocomplain sql flags dataSource id db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -match regexp -result {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\} \{1 2 3\}$}}

###############################################################################

runTest {test tkt-1f7bfff467-1.3 {rollback outer transaction} -setup {
  setupDb [set fileName tkt-1f7bfff467-1.3.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(1);
  }

  set sql(1) { \
    INSERT INTO t1(x) VALUES(2); \
  }

  set sql(2) { \
    INSERT INTO t1(x) VALUES(3); \
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set flags AllowNestedTransactions

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};[getTestProperties ${flags}]"))
          {
            connection.Open();

            using (SQLiteTransaction transaction1 =
                connection.BeginTransaction())
            {
              using (SQLiteCommand command1 = new SQLiteCommand(
                  "${sql(1)}", connection))
              {
                command1.Transaction = transaction1;
                command1.ExecuteNonQuery();
              }

              using (SQLiteTransaction transaction2 =
                  connection.BeginTransaction())
              {
                using (SQLiteCommand command2 = new SQLiteCommand(
                    "${sql(2)}", connection))
                {
                  command2.Transaction = transaction2;
                  command2.ExecuteNonQuery();

                  transaction1.Rollback();
                }
              }
            }
          }
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result \
      [sql execute -execute reader -format list $db \
          "SELECT x FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result results errors code
  unset -nocomplain sql flags dataSource id db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -match regexp -result {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\} 1$}}

###############################################################################

runTest {test tkt-1f7bfff467-1.4 {commit middle transaction} -setup {
  setupDb [set fileName tkt-1f7bfff467-1.4.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(1);
  }

  set sql(1) { \
    INSERT INTO t1(x) VALUES(2); \
  }

  set sql(2) { \
    INSERT INTO t1(x) VALUES(3); \
  }

  set sql(3) { \
    INSERT INTO t1(x) VALUES(4); \
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set flags AllowNestedTransactions

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};[getTestProperties ${flags}]"))
          {
            connection.Open();

            using (SQLiteTransaction transaction1 =
                connection.BeginTransaction())
            {
              using (SQLiteCommand command1 = new SQLiteCommand(
                  "${sql(1)}", connection))
              {
                command1.Transaction = transaction1;
                command1.ExecuteNonQuery();
              }

              using (SQLiteTransaction transaction2 =
                  connection.BeginTransaction())
              {
                using (SQLiteCommand command2 = new SQLiteCommand(
                    "${sql(2)}", connection))
                {
                  command2.Transaction = transaction2;
                  command2.ExecuteNonQuery();
                }

                using (SQLiteTransaction transaction3 =
                    connection.BeginTransaction())
                {
                  using (SQLiteCommand command3 = new SQLiteCommand(
                      "${sql(3)}", connection))
                  {
                    command3.Transaction = transaction3;
                    command3.ExecuteNonQuery();

                    transaction2.Commit();
                  }
                }
              }

              transaction1.Commit();
            }
          }
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result \
      [sql execute -execute reader -format list $db \
          "SELECT x FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result results errors code
  unset -nocomplain sql flags dataSource id db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -match regexp -result {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\} \{1 2 3 4\}$}}

###############################################################################

runTest {test tkt-1f7bfff467-1.5 {rollback middle transaction} -setup {
  setupDb [set fileName tkt-1f7bfff467-1.5.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(1);
  }

  set sql(1) { \
    INSERT INTO t1(x) VALUES(2); \
  }

  set sql(2) { \
    INSERT INTO t1(x) VALUES(3); \
  }

  set sql(3) { \
    INSERT INTO t1(x) VALUES(4); \
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set flags AllowNestedTransactions

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      public static class Test${id}
      {
        public static void Main()
        {
          using (SQLiteConnection connection = new SQLiteConnection(
              "Data Source=${dataSource};[getTestProperties ${flags}]"))
          {
            connection.Open();

            using (SQLiteTransaction transaction1 =
                connection.BeginTransaction())
            {
              using (SQLiteCommand command1 = new SQLiteCommand(
                  "${sql(1)}", connection))
              {
                command1.Transaction = transaction1;
                command1.ExecuteNonQuery();
              }

              using (SQLiteTransaction transaction2 =
                  connection.BeginTransaction())
              {
                using (SQLiteCommand command2 = new SQLiteCommand(
                    "${sql(2)}", connection))
                {
                  command2.Transaction = transaction2;
                  command2.ExecuteNonQuery();
                }

                using (SQLiteTransaction transaction3 =
                    connection.BeginTransaction())
                {
                  using (SQLiteCommand command3 = new SQLiteCommand(
                      "${sql(3)}", connection))
                  {
                    command3.Transaction = transaction3;
                    command3.ExecuteNonQuery();

                    transaction2.Rollback();
                  }
                }
              }

              transaction1.Commit();
            }
          }
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result \
      [sql execute -execute reader -format list $db \
          "SELECT x FROM t1 ORDER BY x;"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result results errors code
  unset -nocomplain sql flags dataSource id db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -match regexp -result {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\} \{1 2\}$}}

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue
