###############################################################################
#
# tkt-e235a52c82.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

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

for {set i 1} {$i < 3} {incr i} {
  runTest {test [appendArgs tkt-e235a52c82-1. $i] {isolation level} \
      -setup {
    set fileName [appendArgs tkt-e235a52c82-1. $i .db]
    set isolationLevel [expr {$i == 1 ? "ReadCommitted" : "Serializable"}]
  } -body {
    setupDb $fileName

    sql execute $db {
      CREATE TABLE t1(x);
      INSERT INTO t1 (x) VALUES('1');
      INSERT INTO t1 (x) VALUES('2');
    }

    cleanupDb $fileName db true false false

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

    set sql { \
      SELECT x FROM t1 ORDER BY x; \
    }

    unset -nocomplain results errors

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

      namespace _Dynamic${id}
      {
        public sealed class Query${id}
        {
          private IDbConnection connection;
          private IDbTransaction transaction;
          private bool opened;

          /////////////////////////////////////////////////////////////////////

          private void EnsureConnection()
          {
            if (connection == null)
            {
              connection = new SQLiteConnection("Data Source=${dataSource};" +
                  "Default IsolationLevel=${isolationLevel};");
            }

            if (connection.State == ConnectionState.Closed)
            {
              connection.Open();
              opened = true;
            }

            if (transaction == null)
              transaction = connection.BeginTransaction();
          }

          /////////////////////////////////////////////////////////////////////

          private void ReleaseConnection()
          {
            if (connection == null)
              throw new Exception("cannot release connection");

            if (opened)
            {
              connection.Close();
              opened = false;
            }
          }

          /////////////////////////////////////////////////////////////////////

          private IDbCommand CreateCommand(
            string commandText
            )
          {
            if (connection == null)
              throw new Exception("cannot create command");

            IDbCommand command = connection.CreateCommand();
            command.CommandText = commandText;

            return command;
          }

          /////////////////////////////////////////////////////////////////////

          public object ExecuteReader(
            string commandText
            )
          {
            object result;
            EnsureConnection();
            IDataReader reader = null;

            try
            {
              reader = CreateCommand(commandText).ExecuteReader();
            }
            catch
            {
              ReleaseConnection();
              throw;
            }

            ///////////////////////////////////////////////////////////////////

            try
            {
              result = reader.GetValue(0);
            }
            catch
            {
              reader.Dispose();
              ReleaseConnection();
              throw;
            }

            return result;
          }
        }

        ///////////////////////////////////////////////////////////////////////

        public static class Test${id}
        {
          public static string\[\] GetData()
          {
            return new string\[\] {
              new Query${id}().ExecuteReader("${sql}").ToString(),
              new Query${id}().ExecuteReader("${sql}").ToString()
            };
          }

          /////////////////////////////////////////////////////////////////////

          public static void Main()
          {
            // do nothing.
          }
        }
      }
    }] 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} GetData
        } result] : [set result ""]}] $result
  } -cleanup {
    cleanupDb $fileName

    unset -nocomplain result results errors code sql dataSource id db \
        isolationLevel fileName
  } -constraints {eagle monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -match regexp -result [expr {$i == 1 ? {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{1 1\}$} : {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 1\
\{System\.Reflection\.TargetInvocationException: Exception has been thrown by\
the target of an invocation\. ---> System\.Data\.SQLite\.SQLiteException:\
database is locked.*$}}]}
}

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

unset -nocomplain i

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

runSQLiteTestEpilogue
runTestEpilogue
