SQLITE_NOTICE(283): recovered 2 frames from WAL file /fossil/dotnet.fossil-wal

System.Data.SQLite: Check-in [c64aaed9f4]
System.Data.SQLite
Check-in [c64aaed9f4]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge all diagnostic enhancements and fixes related to ticket [e30b820248] to trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c64aaed9f4b4ad8ae6e729460010549ad59babde
User & Date: mistachkin 2011-11-15 05:14:26
Context
2011-11-15
05:20
In the vendor-specific initialization file, skip setting the TestPath property of the Eagle interpreter if it already has the correct value. check-in: c9bb751d40 user: mistachkin tags: trunk
05:14
Merge all diagnostic enhancements and fixes related to ticket [e30b820248] to trunk. check-in: c64aaed9f4 user: mistachkin tags: trunk
05:02
Plug memory leak in the sqlite3_close_interop function when a statement cannot be finalized. Have the vendor-specific initialization file for Eagle automatically set the TestPath of the interpreter. Closed-Leaf check-in: 10d400ebd0 user: mistachkin tags: tkt-e30b820248
2011-11-13
22:03
More updates to docs for release 77. check-in: f0a39e8e34 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Externals/Eagle/lib/Eagle1.0/init.eagle.

   764    764             System.CodeDom.Compiler.CompilerParameters]
   765    765   
   766    766         #
   767    767         # NOTE: By default, we do not want to persist the generated assembly
   768    768         #       to disk.
   769    769         #
   770    770         $parameters GenerateInMemory true
          771  +
          772  +      #
          773  +      # NOTE: Make sure that the "standard" preprocessor defines match those
          774  +      #       for the platform (i.e. the ones used to compile the Eagle core
          775  +      #       library assembly).
          776  +      #
          777  +      set platformOptions [expr { \
          778  +          [info exists ::eagle_platform(compileOptions)] ? \
          779  +          $::eagle_platform(compileOptions) : [list]}]
          780  +
          781  +      if {[llength $platformOptions] > 0} then {
          782  +        #
          783  +        # NOTE: Grab the existing compiler options, if any.
          784  +        #
          785  +        set compilerOptions [$parameters CompilerOptions]
          786  +
          787  +        if {"DEBUG" in $platformOptions} then {
          788  +          append compilerOptions " /define:DEBUG"
          789  +        }
          790  +
          791  +        if {"TRACE" in $platformOptions} then {
          792  +          append compilerOptions " /define:TRACE"
          793  +        }
          794  +
          795  +        #
          796  +        # NOTE: Reset the compiler options to the pre-existing ones plus the
          797  +        #       extra defines we may have added (above).
          798  +        #
          799  +        $parameters CompilerOptions $compilerOptions
          800  +      }
   771    801   
   772    802         #
   773    803         # NOTE: Process any extra compiler settings the caller may have
   774    804         #       provided.
   775    805         #
   776    806         foreach {name value} $args {
   777    807           $parameters -nocase $name $value

Changes to Externals/Eagle/lib/Eagle1.0/vendor.eagle.

    29     29   #
    30     30   # NOTE: Use our own namespace here because even though we do not directly
    31     31   #       support namespaces ourselves, we do not want to pollute the global
    32     32   #       namespace if this script actually ends up being evaluated in Tcl.
    33     33   #
    34     34   namespace eval ::Eagle {
    35     35     if {[isEagle]} then {
    36         -    #
    37         -    # NOTE: This script library helper procedure helps to establish the link
    38         -    #       between the System.Data.SQLite test package and Eagle.
    39         -    #
    40         -    proc addTestSuiteToAutoPath { channel quiet } {
           36  +    proc checkForTestOverrides { channel varNames quiet } {
           37  +      set result 0
           38  +
           39  +      foreach varName $varNames {
           40  +        if {[uplevel 1 [list info exists $varName]]} then {
           41  +          incr result
           42  +
           43  +          if {!$quiet} then {
           44  +            puts -nonewline $channel [appendArgs \
           45  +                "Found vendor-specific test override \"" $varName "\".\n"]
           46  +          }
           47  +        }
           48  +      }
           49  +
           50  +      return $result
           51  +    }
           52  +
           53  +    proc addTestSuiteToAutoPath { channel varName quiet } {
    41     54         #
    42     55         # NOTE: Start with the directory containing this file.
    43     56         #
    44     57         set dir [file normalize [file dirname [info script]]]
    45     58   
    46     59         #
    47     60         # NOTE: Keep going until the directory name is empty OR is actually the
................................................................................
    53     66           # NOTE: Does this directory have the necessary sub-directory that
    54     67           #       contains a package index file?
    55     68           #
    56     69           if {[file exists [file join $dir Tests]] && \
    57     70               [file isdirectory [file join $dir Tests]] && \
    58     71               [file exists [file join $dir Tests pkgIndex.eagle]] && \
    59     72               [file isfile [file join $dir Tests pkgIndex.eagle]]} then {
           73  +          #
           74  +          # NOTE: If requested, give the caller access to the name of the
           75  +          #       directory we just found.
           76  +          #
           77  +          if {[string length $varName] > 0} then {
           78  +            upvar 1 $varName dir2
           79  +          }
           80  +
    60     81             #
    61     82             # NOTE: Ok, show the directory we found.
    62     83             #
    63         -          set dir [file join $dir Tests]
           84  +          set dir2 [file join $dir Tests]
    64     85   
    65     86             #
    66     87             # NOTE: We found the necessary directory to add to the auto-path;
    67     88             #       However, we cannot simply add it to the auto-path directly
    68     89             #       because the auto-path is dynamically constructed after this
    69     90             #       script is evaluated; therefore, set the Eagle library path
    70     91             #       environment variable and force the appropriate internal path
    71     92             #       list to be refreshed.
    72     93             #
    73     94             if {![info exists ::env(EAGLELIBPATH)] || \
    74         -              [lsearch -exact $::env(EAGLELIBPATH) $dir] == -1} then {
           95  +              [lsearch -exact $::env(EAGLELIBPATH) $dir2] == -1} then {
    75     96               #
    76     97               # NOTE: If we have NOT been instructed to be quiet, report now.
    77     98               #
    78     99               if {!$quiet} then {
    79    100                 puts -nonewline $channel [appendArgs \
    80         -                  "Found vendor-specific test package directory \"" $dir \
          101  +                  "Found vendor-specific test package directory \"" $dir2 \
    81    102                     "\", adding...\n"]
    82    103               }
    83    104   
    84    105               #
    85    106               # NOTE: Append the directory to the necessary environment variable
    86    107               #       so that it will get picked up when Eagle actually rebuilds
    87    108               #       the auto-path list (below).
    88    109               #
    89         -            lappend ::env(EAGLELIBPATH) $dir
          110  +            lappend ::env(EAGLELIBPATH) $dir2
    90    111   
    91    112               #
    92    113               # NOTE: Force Eagle to rebuild the auto-path list for the current
    93    114               #       interpreter right now.
    94    115               #
    95    116               object invoke Utility RefreshAutoPathList
    96    117             }
................................................................................
   117    138   
   118    139         #
   119    140         # NOTE: Directory not found, return failure.
   120    141         #
   121    142         return false
   122    143       }
   123    144   
   124         -    proc checkForTestOverrides { channel varNames quiet } {
   125         -      set result 0
          145  +    proc setupInterpreterTestPath { channel dir quiet } {
          146  +      object invoke -flags +NonPublic Interpreter.GetActive TestPath $dir
   126    147   
   127         -      foreach varName $varNames {
   128         -        if {[uplevel 1 [list info exists $varName]]} then {
   129         -          incr result
   130         -
   131         -          if {!$quiet} then {
   132         -            puts -nonewline $channel [appendArgs \
   133         -                "Found vendor-specific test override \"" $varName "\".\n"]
   134         -          }
   135         -        }
          148  +      if {!$quiet} then {
          149  +        puts -nonewline $channel [appendArgs \
          150  +            "Set interpreter test path to \"" $dir \".\n]
   136    151         }
   137         -
   138         -      return $result
   139    152       }
   140    153   
   141    154       checkForTestOverrides stdout \
   142    155           [list binary_directory build_base_directory build_directory \
   143    156                 common_directory datetime_format test_configuration \
   144    157                 test_year] false
   145    158   
   146         -    addTestSuiteToAutoPath stdout false
          159  +    #
          160  +    # NOTE: This variable will contain the name of the directory containing the
          161  +    #       vendor-specific testing infrastructure.
          162  +    #
          163  +    set ::vendor_directory ""
          164  +
          165  +    #
          166  +    # NOTE: This procedure will attempt to find the vendor-specific testing
          167  +    #       infrastructure directory and add it to the auto-path for the
          168  +    #       current interpreter.
          169  +    #
          170  +    addTestSuiteToAutoPath stdout ::vendor_directory false
          171  +
          172  +    #
          173  +    # NOTE: If we actually found a vendor-specific testing infrastructure
          174  +    #       directory then modify the TestPath property of the current
          175  +    #       interpreter to point directly to it.
          176  +    #
          177  +    if {[string length $::vendor_directory] > 0} then {
          178  +      setupInterpreterTestPath stdout $::vendor_directory false
          179  +    }
   147    180     }
   148    181   }
   149    182   
   150    183   ###############################################################################
   151    184   ############################### END VENDOR CODE ###############################
   152    185   ###############################################################################

Changes to SQLite.Interop/src/win/interop.c.

    79     79         db->pVdbe = p;
    80     80         ret = sqlite3_finalize((sqlite3_stmt *)p); // This will also free the copy's memory
    81     81         if (ret)
    82     82         {
    83     83           // finalize failed -- so we must put back anything we munged
    84     84           CopyMemory(po, p, sizeof(Vdbe));
    85     85           db->pVdbe = po;
           86  +
           87  +        //
           88  +        // NOTE: Ok, we must free this block that *we* allocated (above) since
           89  +        //       finalize did not do so.
           90  +        //
           91  +        sqlite3DbFree_interop(db, p);
    86     92           break;
    87     93         }
    88     94         else
    89     95         {
    90     96           ZeroMemory(po, sizeof(Vdbe));
    91     97           po->magic = VDBE_MAGIC_DEAD;
    92     98         }

Changes to System.Data.SQLite/SQLite3.cs.

     4      4    * 
     5      5    * Released to the public domain, use at your own risk!
     6      6    ********************************************************/
     7      7   
     8      8   namespace System.Data.SQLite
     9      9   {
    10     10     using System;
           11  +#if DEBUG
           12  +  using System.Diagnostics;
           13  +#endif
    11     14     using System.Runtime.InteropServices;
    12     15   
    13     16   #if !PLATFORM_COMPACTFRAMEWORK
    14     17     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    15     18   #endif
    16     19     internal delegate void SQLiteLogCallback(IntPtr puser, int err_code, IntPtr message);
    17     20   
................................................................................
    43     46       internal SQLite3(SQLiteDateFormats fmt, DateTimeKind kind)
    44     47         : base(fmt, kind)
    45     48       {
    46     49       }
    47     50   
    48     51       protected override void Dispose(bool bDisposing)
    49     52       {
    50         -      if (bDisposing)
    51         -        Close();
           53  +      Close();
    52     54       }
    53     55   
    54     56       // It isn't necessary to cleanup any functions we've registered.  If the connection
    55     57       // goes to the pool and is resurrected later, re-registered functions will overwrite the
    56     58       // previous functions.  The SQLiteFunctionCookieHandle will take care of freeing unmanaged
    57     59       // resources belonging to the previously-registered functions.
    58     60       internal override void Close()
................................................................................
    87     89       internal static string SQLiteVersion
    88     90       {
    89     91         get
    90     92         {
    91     93           return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1);
    92     94         }
    93     95       }
           96  +
           97  +    internal static string SQLiteSourceId
           98  +    {
           99  +      get
          100  +      {
          101  +        return UTF8ToString(UnsafeNativeMethods.sqlite3_sourceid(), -1);
          102  +      }
          103  +    }
    94    104   
    95    105       internal override bool AutoCommit
    96    106       {
    97    107         get
    98    108         {
    99    109           return IsAutocommit(_sql);
   100    110         }
................................................................................
   164    174           IntPtr db;
   165    175   
   166    176   #if !SQLITE_STANDARD
   167    177           int n = UnsafeNativeMethods.sqlite3_open_interop(ToUTF8(strFilename), (int)flags, out db);
   168    178   #else
   169    179           int n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero);
   170    180   #endif
          181  +
          182  +#if DEBUG
          183  +        Trace.WriteLine(String.Format("Open: {0}", db));
          184  +#endif
          185  +
   171    186           if (n > 0) throw new SQLiteException(n, null);
   172    187   
   173    188           _sql = db;
   174    189         }
   175    190         // Bind functions to this connection.  If any previous functions of the same name
   176    191         // were already bound, then the new bindings replace the old.
   177    192         _functionsArray = SQLiteFunction.BindFunctions(this);
................................................................................
   319    334           {
   320    335   #if !SQLITE_STANDARD
   321    336             n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len);
   322    337   #else
   323    338             n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr);
   324    339             len = -1;
   325    340   #endif
          341  +
          342  +#if DEBUG
          343  +          Trace.WriteLine(String.Format("Prepare: {0}", stmt));
          344  +#endif
   326    345   
   327    346             if (n == 17)
   328    347               retries++;
   329    348             else if (n == 1)
   330    349             {
   331    350               if (String.Compare(SQLiteLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0)
   332    351               {

Changes to System.Data.SQLite/SQLite3_UTF16.cs.

     4      4    * 
     5      5    * Released to the public domain, use at your own risk!
     6      6    ********************************************************/
     7      7   
     8      8   namespace System.Data.SQLite
     9      9   {
    10     10     using System;
           11  +#if DEBUG
           12  +  using System.Diagnostics;
           13  +#endif
    11     14     using System.Runtime.InteropServices;
    12     15   
    13     16     /// <summary>
    14     17     /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
    15     18     /// </summary>
    16     19     internal class SQLite3_UTF16 : SQLite3
    17     20     {
................................................................................
    60     63           int n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), (int)flags, out db);
    61     64   #else
    62     65           if ((flags & SQLiteOpenFlagsEnum.Create) == 0 && System.IO.File.Exists(strFilename) == false)
    63     66             throw new SQLiteException((int)SQLiteErrorCode.CantOpen, strFilename);
    64     67   
    65     68           int n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db);
    66     69   #endif
           70  +
           71  +#if DEBUG
           72  +        Trace.WriteLine(String.Format("Open: {0}", db));
           73  +#endif
           74  +
    67     75           if (n > 0) throw new SQLiteException(n, null);
    68     76   
    69     77           _sql = db;
    70     78         }
    71     79         _functionsArray = SQLiteFunction.BindFunctions(this);
    72     80       }
    73     81   

Changes to System.Data.SQLite/SQLiteCommand.cs.

   217    217       /// </summary>
   218    218       internal SQLiteStatement BuildNextCommand()
   219    219       {
   220    220         SQLiteStatement stmt = null;
   221    221   
   222    222         try
   223    223         {
   224         -        if (_statementList == null)
   225         -          _remainingText = _commandText;
   226         -
   227         -        stmt = _cnn._sql.Prepare(_cnn, _remainingText, (_statementList == null) ? null : _statementList[_statementList.Count - 1], (uint)(_commandTimeout * 1000), out _remainingText);
   228         -        if (stmt != null)
          224  +        if ((_cnn != null) && (_cnn._sql != null))
   229    225           {
   230         -          stmt._command = this;
   231    226             if (_statementList == null)
   232         -            _statementList = new List<SQLiteStatement>();
          227  +            _remainingText = _commandText;
   233    228   
   234         -          _statementList.Add(stmt);
          229  +          stmt = _cnn._sql.Prepare(_cnn, _remainingText, (_statementList == null) ? null : _statementList[_statementList.Count - 1], (uint)(_commandTimeout * 1000), out _remainingText);
   235    230   
   236         -          _parameterCollection.MapParameters(stmt);
   237         -          stmt.BindParameters();
   238         -        }        
          231  +          if (stmt != null)
          232  +          {
          233  +            stmt._command = this;
          234  +
          235  +            if (_statementList == null)
          236  +              _statementList = new List<SQLiteStatement>();
          237  +
          238  +            _statementList.Add(stmt);
          239  +
          240  +            _parameterCollection.MapParameters(stmt);
          241  +            stmt.BindParameters();
          242  +          }
          243  +        }
   239    244           return stmt;
   240    245         }
   241    246         catch (Exception)
   242    247         {
   243    248           if (stmt != null)
   244    249           {
   245         -          if (_statementList.Contains(stmt))
          250  +          if ((_statementList != null) && _statementList.Contains(stmt))
   246    251               _statementList.Remove(stmt);
   247    252   
   248    253             stmt.Dispose();
   249    254           }
   250    255   
   251    256           // If we threw an error compiling the statement, we cannot continue on so set the remaining text to null.
   252    257           _remainingText = null;

Changes to System.Data.SQLite/SQLiteConnection.cs.

   483    483             _sql = null;
   484    484             _enlistment = null;
   485    485           }
   486    486   #endif
   487    487           if (_sql != null)
   488    488           {
   489    489             _sql.Close();
          490  +          _sql = null;
   490    491           }
   491         -        _sql = null;
   492    492           _transactionLevel = 0;
   493    493         }
   494    494         OnStateChange(ConnectionState.Closed);
   495    495       }
   496    496   
   497    497       /// <summary>
   498    498       /// Clears the connection pool associated with the connection.  Any other active connections using the same database file
................................................................................
  1075   1075       /// <summary>
  1076   1076       /// Returns the version of the underlying SQLite database engine
  1077   1077       /// </summary>
  1078   1078       public static string SQLiteVersion
  1079   1079       {
  1080   1080         get { return SQLite3.SQLiteVersion; }
  1081   1081       }
         1082  +
         1083  +    /// <summary>
         1084  +    /// This method returns the string whose value is the same as the
         1085  +    /// SQLITE_SOURCE_ID C preprocessor macro used when compiling the
         1086  +    /// SQLite core library.
         1087  +    /// </summary>
         1088  +    public static string SQLiteSourceId
         1089  +    {
         1090  +      get { return SQLite3.SQLiteSourceId; }
         1091  +    }
  1082   1092   
  1083   1093       /// <summary>
  1084   1094       /// Returns the state of the connection.
  1085   1095       /// </summary>
  1086   1096   #if !PLATFORM_COMPACTFRAMEWORK
  1087   1097       [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  1088   1098   #endif

Changes to System.Data.SQLite/SQLiteLog.cs.

   281    281           /// disabled.  When logging is disabled, no logging events will fire.
   282    282           /// </summary>
   283    283           public static bool Enabled
   284    284           {
   285    285               get { lock (syncRoot) { return _enabled; } }
   286    286               set { lock (syncRoot) { _enabled = value; } }
   287    287           }
          288  +
          289  +        /// <summary>
          290  +        /// Log a message to all the registered log event handlers without going
          291  +        /// through the SQLite library.
          292  +        /// </summary>
          293  +        /// <param name="errorCode">The error code or zero for success.</param>
          294  +        /// <param name="message">The message to be logged.</param>
          295  +        public static void LogMessage(
          296  +            int errorCode,
          297  +            string message
          298  +            )
          299  +        {
          300  +            bool enabled;
          301  +            SQLiteLogEventHandler handlers;
          302  +
          303  +            lock (syncRoot)
          304  +            {
          305  +                enabled = _enabled;
          306  +                handlers = _handlers;
          307  +            }
          308  +
          309  +            if (enabled && (handlers != null))
          310  +                handlers(null, new LogEventArgs(
          311  +                    IntPtr.Zero, errorCode, message, null));
          312  +        }
   288    313   
   289    314           /// <summary>
   290    315           /// Creates and initializes the default log event handler.
   291    316           /// </summary>
   292    317           private static void InitializeDefaultHandler()
   293    318           {
   294    319               lock (syncRoot)
................................................................................
   353    378           {
   354    379               if (e == null)
   355    380                   return;
   356    381   
   357    382               string message = e.Message;
   358    383   
   359    384               if (message == null)
          385  +            {
   360    386                   message = "<null>";
   361         -            else if (message.Length == 0)
   362         -                message = "<empty>";
          387  +            }
          388  +            else
          389  +            {
          390  +                message = message.Trim();
          391  +
          392  +                if (message.Length == 0)
          393  +                    message = "<empty>";
          394  +            }
          395  +
          396  +            int errorCode = e.ErrorCode;
   363    397   
   364         -            Trace.WriteLine(String.Format("SQLite error ({0}): {1}",
   365         -                e.ErrorCode, message));
          398  +            Trace.WriteLine(String.Format(
          399  +                "SQLite {0} ({1}): {2}", errorCode == 0 ?
          400  +                "message" : "error", errorCode, message));
   366    401           }
   367    402       }
   368    403   #endif
   369    404   }

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.

     4      4    * 
     5      5    * Released to the public domain, use at your own risk!
     6      6    ********************************************************/
     7      7   
     8      8   namespace System.Data.SQLite
     9      9   {
    10     10     using System;
           11  +#if DEBUG
           12  +  using System.Diagnostics;
           13  +#endif
    11     14   
    12     15   #if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
    13     16     using System.Security;
    14     17   #endif
    15     18   
    16     19     using System.Runtime.InteropServices;
    17     20   
................................................................................
   347    350   #if !PLATFORM_COMPACTFRAMEWORK
   348    351       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   349    352   #else
   350    353       [DllImport(SQLITE_DLL)]
   351    354   #endif
   352    355       internal static extern IntPtr sqlite3_libversion();
   353    356   
          357  +#if !PLATFORM_COMPACTFRAMEWORK
          358  +    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
          359  +#else
          360  +    [DllImport(SQLITE_DLL)]
          361  +#endif
          362  +    internal static extern IntPtr sqlite3_sourceid();
          363  +
   354    364   #if !PLATFORM_COMPACTFRAMEWORK
   355    365       [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
   356    366   #else
   357    367       [DllImport(SQLITE_DLL)]
   358    368   #endif
   359    369       internal static extern void sqlite3_interrupt(IntPtr db);
   360    370   
................................................................................
   870    880       }
   871    881   
   872    882       protected override bool ReleaseHandle()
   873    883       {
   874    884         try
   875    885         {
   876    886           SQLiteBase.CloseConnection(this);
          887  +
          888  +#if DEBUG
          889  +        try
          890  +        {
          891  +          Trace.WriteLine(String.Format(
          892  +              "CloseConnection: {0}", handle));
          893  +        }
          894  +        catch
          895  +        {
          896  +        }
          897  +#endif
          898  +
          899  +#if DEBUG
          900  +        return true;
          901  +#endif
   877    902         }
          903  +#if DEBUG
          904  +      catch (SQLiteException e)
          905  +#else
   878    906         catch (SQLiteException)
          907  +#endif
   879    908         {
          909  +#if DEBUG
          910  +        try
          911  +        {
          912  +          Trace.WriteLine(String.Format(
          913  +              "CloseConnection: {0}, exception: {1}",
          914  +              handle, e));
          915  +        }
          916  +        catch
          917  +        {
          918  +        }
          919  +#endif
   880    920         }
          921  +#if DEBUG
          922  +      return false;
          923  +#else
   881    924         return true;
          925  +#endif
   882    926       }
   883    927   
   884    928       public override bool IsInvalid
   885    929       {
   886    930         get { return (handle == IntPtr.Zero); }
   887    931       }
   888    932     }
................................................................................
   912    956       }
   913    957   
   914    958       protected override bool ReleaseHandle()
   915    959       {
   916    960         try
   917    961         {
   918    962           SQLiteBase.FinalizeStatement(this);
          963  +
          964  +#if DEBUG
          965  +        try
          966  +        {
          967  +          Trace.WriteLine(String.Format(
          968  +              "FinalizeStatement: {0}", handle));
          969  +        }
          970  +        catch
          971  +        {
          972  +        }
          973  +#endif
          974  +
          975  +#if DEBUG
          976  +        return true;
          977  +#endif
   919    978         }
          979  +#if DEBUG
          980  +      catch (SQLiteException e)
          981  +#else
   920    982         catch (SQLiteException)
          983  +#endif
   921    984         {
          985  +#if DEBUG
          986  +        try
          987  +        {
          988  +          Trace.WriteLine(String.Format(
          989  +              "FinalizeStatement: {0}, exception: {1}",
          990  +              handle, e));
          991  +        }
          992  +        catch
          993  +        {
          994  +        }
          995  +#endif
   922    996         }
          997  +#if DEBUG
          998  +      return false;
          999  +#else
   923   1000         return true;
         1001  +#endif
   924   1002       }
   925   1003   
   926   1004       public override bool IsInvalid
   927   1005       {
   928   1006         get { return (handle == IntPtr.Zero); }
   929   1007       }
   930   1008     }
   931   1009   }

Changes to Tests/common.eagle.

   300    300       }
   301    301   
   302    302       proc checkForSQLite { channel } {
   303    303         tputs $channel "---- checking for core SQLite library... "
   304    304   
   305    305         if {[catch {object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \
   306    306                 SQLiteVersion} version] == 0} then {
          307  +        #
          308  +        # NOTE: Attempt to query the Fossil source identifier for the SQLite
          309  +        #       core library.
          310  +        #
          311  +        if {[catch {object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \
          312  +                SQLiteSourceId} sourceId]} then {
          313  +          #
          314  +          # NOTE: We failed to query the Fossil source identifier.
          315  +          #
          316  +          set sourceId unknown
          317  +        }
          318  +
   307    319           #
   308    320           # NOTE: Yes, the SQLite core library appears to be available.
   309    321           #
   310    322           addConstraint SQLite
   311    323   
   312         -        tputs $channel [appendArgs "yes (" $version ")\n"]
          324  +        tputs $channel [appendArgs "yes (" $version " " $sourceId ")\n"]
   313    325         } else {
   314    326           tputs $channel no\n
   315    327         }
   316    328       }
   317    329   
   318    330       proc getDateTimeFormat {} {
   319    331         #
................................................................................
   398    410         #       the temporary directory.  Each database used by a test should be
   399    411         #       cleaned up by that test using the "cleanupDb" procedure, below.
   400    412         #
   401    413         set fileName [file join [getTemporaryPath] [file tail $fileName]]
   402    414   
   403    415         #
   404    416         # NOTE: By default, delete any pre-existing database with the same file
   405         -      #       name.
          417  +      #       name if it currently exists.
   406    418         #
   407         -      if {$delete} then {
   408         -        catch {file delete $fileName}
          419  +      if {$delete && [file exists $fileName]} then {
          420  +        if {[catch {file delete $fileName} error]} then {
          421  +          #
          422  +          # NOTE: We somehow failed to delete the file, report why.
          423  +          #
          424  +          tputs $::test_channel [appendArgs \
          425  +              "==== WARNING: failed to delete database file \"" $fileName \
          426  +              "\" during setup, error: " \n\t $error \n]
          427  +        }
   409    428         }
   410    429   
   411    430         #
   412    431         # NOTE: Refer to the specified variable (e.g. "db") in the context of the
   413    432         #       caller.  The handle to the opened database will be stored there.
   414    433         #
   415    434         upvar 1 $varName db
................................................................................
   466    485         #
   467    486         upvar 1 $varName db
   468    487   
   469    488         #
   470    489         # NOTE: Close the connection to the database now.  This should allow us to
   471    490         #       delete the underlying database file.
   472    491         #
   473         -      catch {sql close $db}
          492  +      if {[info exists db] && [catch {sql close $db} error]} then {
          493  +        #
          494  +        # NOTE: We somehow failed to close the database, report why.
          495  +        #
          496  +        tputs $::test_channel [appendArgs \
          497  +            "==== WARNING: failed to close database \"" $db "\", error: " \
          498  +            \n\t $error \n]
          499  +      }
   474    500   
   475    501         #
   476         -      # NOTE: Delete the test database file now.  For now, all test database
   477         -      #       files are stored in the temporary directory.
          502  +      # NOTE: Attempt to delete the test database file now.  For now, all test
          503  +      #       database files are stored in the temporary directory.
   478    504         #
   479         -      catch {file delete [file join [getTemporaryPath] [file tail $fileName]]}
          505  +      set fileName [file join [getTemporaryPath] [file tail $fileName]]
          506  +
          507  +      if {[set code [catch {file delete $fileName} error]]} then {
          508  +        #
          509  +        # NOTE: We somehow failed to delete the file, report why.
          510  +        #
          511  +        tputs $::test_channel [appendArgs \
          512  +            "==== WARNING: failed to delete database file \"" $fileName \
          513  +            "\" during cleanup, error: " \n\t $error \n]
          514  +      }
          515  +
          516  +      return $code
   480    517       }
   481    518   
   482         -    proc reportSQLiteResources { channel } {
   483         -      tputs $channel "---- current memory in use by SQLite... "
          519  +    proc reportSQLiteResources { channel {quiet false} } {
          520  +      #
          521  +      # NOTE: Skip all output if we are running in "quiet" mode.
          522  +      #
          523  +      if {!$quiet} then {
          524  +        tputs $channel "---- current memory in use by SQLite... "
          525  +      }
   484    526   
   485    527         if {[catch {object invoke -flags +NonPublic \
   486    528                 System.Data.SQLite.UnsafeNativeMethods \
   487    529                 sqlite3_memory_used} memory] == 0} then {
   488         -        tputs $channel [appendArgs $memory " bytes\n"]
          530  +        if {!$quiet} then {
          531  +          tputs $channel [appendArgs $memory " bytes\n"]
          532  +        }
   489    533         } else {
   490    534           #
   491    535           # NOTE: Maybe the SQLite native library is unavailable?
   492    536           #
   493         -        tputs $channel unknown\n
          537  +        set memory unknown
          538  +
          539  +        if {!$quiet} then {
          540  +          tputs $channel [appendArgs $memory \n]
          541  +        }
   494    542         }
   495    543   
   496         -      tputs $channel "---- maximum memory in use by SQLite... "
          544  +      set result $memory; # NOTE: Return memory in-use to caller.
          545  +
          546  +      if {!$quiet} then {
          547  +        tputs $channel "---- maximum memory in use by SQLite... "
          548  +      }
   497    549   
   498    550         if {[catch {object invoke -flags +NonPublic \
   499    551                 System.Data.SQLite.UnsafeNativeMethods \
   500    552                 sqlite3_memory_highwater 0} memory] == 0} then {
   501         -        tputs $channel [appendArgs $memory " bytes\n"]
          553  +        if {!$quiet} then {
          554  +          tputs $channel [appendArgs $memory " bytes\n"]
          555  +        }
   502    556         } else {
   503    557           #
   504    558           # NOTE: Maybe the SQLite native library is unavailable?
   505    559           #
   506         -        tputs $channel unknown\n
          560  +        set memory unknown
          561  +
          562  +        if {!$quiet} then {
          563  +          tputs $channel [appendArgs $memory \n]
          564  +        }
   507    565         }
          566  +
          567  +      return $result
   508    568       }
   509    569   
   510    570       proc runSQLiteTestPrologue {} {
   511    571         #
   512    572         # NOTE: Skip running our custom prologue if the main one has been skipped.
   513    573         #
   514    574         if {![info exists ::no(prologue.eagle)]} then {
................................................................................
   517    577           #       copying, and loading) if we are so instructed.
   518    578           #
   519    579           if {![info exists ::no(sqliteFiles)]} then {
   520    580             #
   521    581             # NOTE: Skip trying to delete any files if we are so instructed.
   522    582             #
   523    583             if {![info exists ::no(deleteSqliteFiles)]} then {
          584  +            tryDeleteAssembly sqlite3.dll
   524    585               tryDeleteAssembly SQLite.Interop.dll
   525    586               tryDeleteAssembly System.Data.SQLite.dll
   526    587               tryDeleteAssembly System.Data.SQLite.Linq.dll
   527    588             }
   528    589   
   529    590             #
   530    591             # NOTE: Skip trying to copy any files if we are so instructed.
   531    592             #
   532    593             if {![info exists ::no(copySqliteFiles)]} then {
          594  +            tryCopyAssembly sqlite3.dll
   533    595               tryCopyAssembly SQLite.Interop.dll
   534    596               tryCopyAssembly System.Data.SQLite.dll
   535    597               tryCopyAssembly System.Data.SQLite.Linq.dll
   536    598             }
   537    599   
   538    600             #
   539    601             # NOTE: Skip trying to load any files if we are so instructed.

Added Tests/tkt-e30b820248.eagle.

            1  +###############################################################################
            2  +#
            3  +# tkt-e30b820248.eagle --
            4  +#
            5  +# Written by Joe Mistachkin.
            6  +# Released to the public domain, use at your own risk!
            7  +#
            8  +###############################################################################
            9  +
           10  +package require Eagle
           11  +package require EagleLibrary
           12  +package require EagleTest
           13  +
           14  +runTestPrologue
           15  +
           16  +###############################################################################
           17  +
           18  +package require System.Data.SQLite.Test
           19  +runSQLiteTestPrologue
           20  +
           21  +###############################################################################
           22  +
           23  +set memory_used [reportSQLiteResources $test_channel true]
           24  +
           25  +###############################################################################
           26  +
           27  +runTest {test tkt-e30b820248-1.1 {disposal ordering} -setup {
           28  +  set fileName tkt-e30b820248-1.1.db
           29  +} -body {
           30  +  set id [object invoke Interpreter.GetActive NextId]
           31  +  set dataSource [file join [getTemporaryPath] $fileName]
           32  +  set name [file rootname [file tail $fileName]]
           33  +
           34  +  set sql { \
           35  +    CREATE TABLE t1 (id1 INTEGER); \
           36  +    INSERT INTO t1 (id1) VALUES (1); \
           37  +    INSERT INTO t1 (id1) VALUES (2); \
           38  +    INSERT INTO t1 (id1) VALUES (?); \
           39  +    INSERT INTO t1 (id1) VALUES (?); \
           40  +    INSERT INTO t1 (id1) VALUES (?); \
           41  +    SELECT * FROM t1 ORDER BY id1; \
           42  +  }
           43  +
           44  +  unset -nocomplain results errors
           45  +
           46  +  set code [compileCSharpWith [subst {
           47  +    using System.Data.SQLite;
           48  +    using System.Diagnostics;
           49  +    using System.IO;
           50  +
           51  +    namespace _Dynamic${id}
           52  +    {
           53  +      public class Test${id}
           54  +      {
           55  +        public static void Main()
           56  +        {
           57  +          using (TraceListener listener = new TextWriterTraceListener(
           58  +              new FileStream("${test_log}", FileMode.Append,
           59  +                  FileAccess.Write, FileShare.ReadWrite), "${name}"))
           60  +          {
           61  +            Trace.Listeners.Add(listener);
           62  +            Trace.WriteLine("---- START TRACE \\"${name}\\"");
           63  +
           64  +            using (SQLiteConnection connection = new SQLiteConnection(
           65  +                "Data Source=${dataSource};"))
           66  +            {
           67  +              connection.Open();
           68  +              connection.LogMessage(0, "Connection opened.");
           69  +
           70  +              using (SQLiteTransaction transaction =
           71  +                  connection.BeginTransaction())
           72  +              {
           73  +                connection.LogMessage(0, "Transaction started.");
           74  +
           75  +                using (SQLiteCommand command = connection.CreateCommand())
           76  +                {
           77  +                  command.Transaction = transaction;
           78  +                  command.CommandText = "${sql}";
           79  +
           80  +                  command.Parameters.AddWithValue("x", 3);
           81  +                  command.Parameters.AddWithValue("y", 4);
           82  +                  command.Parameters.AddWithValue("z", 5);
           83  +
           84  +                  command.ExecuteNonQuery();
           85  +                  connection.LogMessage(0, "Command executed.");
           86  +                }
           87  +
           88  +                transaction.Commit();
           89  +                connection.LogMessage(0, "Transaction committed.");
           90  +              }
           91  +            }
           92  +
           93  +            Trace.WriteLine("---- END TRACE \\"${name}\\"");
           94  +            Trace.Listeners.Remove(listener);
           95  +          }
           96  +        }
           97  +      }
           98  +    }
           99  +  }] results errors System.Data.SQLite.dll]
          100  +
          101  +  list $code $results \
          102  +      [expr {[info exists errors] ? $errors : ""}] \
          103  +      [expr {$code eq "Ok" ? [catch {
          104  +        object invoke _Dynamic${id}.Test${id} Main
          105  +      } result] : [set result ""]}] $result \
          106  +      [reportSQLiteResources $test_channel true]
          107  +} -cleanup {
          108  +  cleanupDb $fileName
          109  +
          110  +  unset -nocomplain result code results errors sql dataSource id db fileName
          111  +} -constraints \
          112  +{eagle logFile monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
          113  +-match regexp -result [appendArgs "^Ok\
          114  +System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}
          115  +
          116  +###############################################################################
          117  +
          118  +for {set i 2} {$i < 5} {incr i} {
          119  +  set memory_used [reportSQLiteResources $test_channel true]
          120  +
          121  +  #############################################################################
          122  +
          123  +  runTest {test [appendArgs tkt-e30b820248-1. $i] {disposal ordering} -setup {
          124  +    set fileName [appendArgs tkt-e30b820248-1. $i .db]
          125  +  } -body {
          126  +    set id [object invoke Interpreter.GetActive NextId]
          127  +    set dataSource [file join [getTemporaryPath] $fileName]
          128  +    set name [file rootname [file tail $fileName]]
          129  +
          130  +    set sql { \
          131  +      CREATE TABLE t1 (id1 INTEGER); \
          132  +      INSERT INTO t1 (id1) VALUES (1); \
          133  +      INSERT INTO t1 (id1) VALUES (2); \
          134  +      INSERT INTO t1 (id1) VALUES (3); \
          135  +      INSERT INTO t1 (id1) VALUES (4); \
          136  +      INSERT INTO t1 (id1) VALUES (5); \
          137  +      SELECT * FROM t1 ORDER BY id1; \
          138  +    }
          139  +
          140  +    unset -nocomplain results errors
          141  +
          142  +    set code [compileCSharpWith [subst {
          143  +      using System;
          144  +      using System.Data.SQLite;
          145  +      using System.Diagnostics;
          146  +      using System.IO;
          147  +
          148  +      namespace _Dynamic${id}
          149  +      {
          150  +        public class Test${id}
          151  +        {
          152  +          #region Private Static Data
          153  +          private static SQLiteConnection connection;
          154  +          #endregion
          155  +
          156  +          /////////////////////////////////////////////////////////////////////
          157  +
          158  +          #region Public Static Methods
          159  +          public static void OpenConnection()
          160  +          {
          161  +            connection = new SQLiteConnection("Data Source=${dataSource};");
          162  +            connection.Open();
          163  +            connection.LogMessage(0, "Connection opened.");
          164  +          }
          165  +
          166  +          /////////////////////////////////////////////////////////////////////
          167  +
          168  +          public static SQLiteCommand CreateCommand(string sql)
          169  +          {
          170  +            SQLiteCommand command = connection.CreateCommand();
          171  +            command.CommandText = sql;
          172  +            connection.LogMessage(0, "Command created.");
          173  +            return command;
          174  +          }
          175  +
          176  +          /////////////////////////////////////////////////////////////////////
          177  +
          178  +          public static SQLiteDataReader ExecuteReader(SQLiteCommand command)
          179  +          {
          180  +            SQLiteDataReader dataReader = command.ExecuteReader();
          181  +            connection.LogMessage(0, "Command executed.");
          182  +            return dataReader;
          183  +          }
          184  +
          185  +          /////////////////////////////////////////////////////////////////////
          186  +
          187  +          public static SQLiteDataReader ExecuteReader(string sql)
          188  +          {
          189  +            SQLiteCommand command = CreateCommand(sql);
          190  +            SQLiteDataReader dataReader = command.ExecuteReader();
          191  +            connection.LogMessage(0, "Command executed.");
          192  +            return dataReader;
          193  +          }
          194  +
          195  +          /////////////////////////////////////////////////////////////////////
          196  +
          197  +          public static void CloseConnection()
          198  +          {
          199  +            connection.LogMessage(0, "Closing connection...");
          200  +            connection.Close();
          201  +          }
          202  +          #endregion
          203  +
          204  +          /////////////////////////////////////////////////////////////////////
          205  +
          206  +          public static void Main()
          207  +          {
          208  +            using (TraceListener listener = new TextWriterTraceListener(
          209  +                new FileStream("${test_log}", FileMode.Append,
          210  +                    FileAccess.Write, FileShare.ReadWrite), "${name}"))
          211  +            {
          212  +              Trace.Listeners.Add(listener);
          213  +              Trace.WriteLine("---- START TRACE \\"${name}\\"");
          214  +
          215  +              OpenConnection();
          216  +              SQLiteDataReader dataReader = ExecuteReader("${sql}");
          217  +
          218  +              [expr {$i <= 2 ? {
          219  +                GC.Collect();
          220  +                GC.WaitForPendingFinalizers();
          221  +                GC.Collect();
          222  +              } : ""}]
          223  +
          224  +              dataReader.Close();
          225  +
          226  +              [expr {$i <= 3 ? {
          227  +                GC.Collect();
          228  +                GC.WaitForPendingFinalizers();
          229  +                GC.Collect();
          230  +              } : ""}]
          231  +
          232  +              CloseConnection();
          233  +
          234  +              [expr {$i <= 4 ? {
          235  +                GC.Collect();
          236  +                GC.WaitForPendingFinalizers();
          237  +                GC.Collect();
          238  +              } : ""}]
          239  +
          240  +              Trace.WriteLine("---- END TRACE \\"${name}\\"");
          241  +              Trace.Listeners.Remove(listener);
          242  +            }
          243  +          }
          244  +        }
          245  +      }
          246  +    }] results errors System.Data.SQLite.dll]
          247  +
          248  +    list $code $results \
          249  +        [expr {[info exists errors] ? $errors : ""}] \
          250  +        [expr {$code eq "Ok" ? [catch {
          251  +          object invoke _Dynamic${id}.Test${id} Main
          252  +        } result] : [set result ""]}] $result \
          253  +        [reportSQLiteResources $test_channel true]
          254  +  } -cleanup {
          255  +    cleanupDb $fileName
          256  +
          257  +    unset -nocomplain result code results errors sql dataSource id db fileName
          258  +  } -constraints {eagle logFile monoBug28 command.sql compile.DATA SQLite\
          259  +System.Data.SQLite} -match regexp -result [appendArgs "^Ok\
          260  +System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}
          261  +}
          262  +
          263  +###############################################################################
          264  +
          265  +unset -nocomplain i
          266  +
          267  +###############################################################################
          268  +
          269  +unset -nocomplain memory_used
          270  +
          271  +###############################################################################
          272  +
          273  +runSQLiteTestEpilogue
          274  +runTestEpilogue