Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix handling of copied connection handles when calling Create and Connect virtual methods. Get initial test passing. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | virtualTables |
Files: | files | file ages | folders |
SHA1: |
e1bef414b7415f615eafcb7fa8f2b183 |
User & Date: | mistachkin 2013-06-20 03:08:43.803 |
Context
2013-06-21
| ||
03:11 | Major cleanup and refactoring of the ISQLiteManagedModule interface. Fix a small memory leak in DeclareVirtualTable. Add the ability to persist SQLiteValue values beyond the duration of the method call in progress. Add SQLiteVirtualTable base class. Update SQLiteVirtualTableCursor base class to be IDisposable and to support storing the filtering parameters. Make parameter naming in the ISQLiteManagedModule interface consistent with other managed code. Add SQLiteVirtualTable parameter to the ISQLiteManagedModule interface methods where necessary. Remove incorrect SQLiteIndex object creation from the IndexToIntPtr method. Keep track of all managed table and cursor object instances associated with their native pointers. Zero out the native sqlite3_vtab object right after allocation. Correct declarations for the sqlite3_vtab and sqlite3_vtab_cursor structures. Add SQLiteModuleEnumerable and SQLiteVirtualTableCursorEnumerable classes to allow an IEnumerable to provide the data for a virtual table. check-in: d3ac8fc2c3 user: mistachkin tags: virtualTables | |
2013-06-20
| ||
03:08 | Fix handling of copied connection handles when calling Create and Connect virtual methods. Get initial test passing. check-in: e1bef414b7 user: mistachkin tags: virtualTables | |
01:40 | More work on disposable vtable integration. check-in: 5a2bdec84f user: mistachkin tags: virtualTables | |
Changes
Changes to System.Data.SQLite/SQLite3.cs.
︙ | ︙ | |||
86 87 88 89 90 91 92 | /// <summary> /// The modules created using this connection. /// </summary> protected Dictionary<string, SQLiteModuleBase> _modules; /////////////////////////////////////////////////////////////////////////////////////////////// | | > > > > > > > > > > > | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | /// <summary> /// The modules created using this connection. /// </summary> protected Dictionary<string, SQLiteModuleBase> _modules; /////////////////////////////////////////////////////////////////////////////////////////////// internal SQLite3( SQLiteDateFormats fmt, DateTimeKind kind, string fmtString, IntPtr db, string fileName, bool ownHandle ) : base(fmt, kind, fmtString) { if (db != IntPtr.Zero) { _sql = new SQLiteConnectionHandle(db, ownHandle); _fileName = fileName; _ownHandle = ownHandle; } } /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members private bool disposed; private void CheckDisposed() /* throw */ |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | /// The module object to be used when creating the native disposable module. /// </param> internal override void CreateModule(SQLiteModuleBase module) { if (module == null) throw new ArgumentNullException("module"); SetLoadExtension(true); LoadExtension(UnsafeNativeMethods.SQLITE_DLL, "sqlite3_vtshim_init"); IntPtr pName = IntPtr.Zero; try { | > > > | 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | /// The module object to be used when creating the native disposable module. /// </param> internal override void CreateModule(SQLiteModuleBase module) { if (module == null) throw new ArgumentNullException("module"); if (_sql == null) throw new SQLiteException("connection has an invalid handle"); SetLoadExtension(true); LoadExtension(UnsafeNativeMethods.SQLITE_DLL, "sqlite3_vtshim_init"); IntPtr pName = IntPtr.Zero; try { |
︙ | ︙ | |||
1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 | /// </returns> internal override SQLiteErrorCode DeclareVirtualTable( SQLiteModuleBase module, string strSql, ref string error ) { SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_declare_vtab( _sql, SQLiteMarshal.Utf8IntPtrFromString(strSql)); if ((n == SQLiteErrorCode.Ok) && (module != null)) module.Declared = true; if (n != SQLiteErrorCode.Ok) error = GetLastError(); | > > > > > > | 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 | /// </returns> internal override SQLiteErrorCode DeclareVirtualTable( SQLiteModuleBase module, string strSql, ref string error ) { if (_sql == null) { error = "connection has an invalid handle"; return SQLiteErrorCode.Error; } SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_declare_vtab( _sql, SQLiteMarshal.Utf8IntPtrFromString(strSql)); if ((n == SQLiteErrorCode.Ok) && (module != null)) module.Declared = true; if (n != SQLiteErrorCode.Ok) error = GetLastError(); |
︙ | ︙ |
Changes to System.Data.SQLite/SQLite3_UTF16.cs.
︙ | ︙ | |||
17 18 19 20 21 22 23 | using System.Runtime.InteropServices; /// <summary> /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) /// </summary> internal sealed class SQLite3_UTF16 : SQLite3 { | | > > > > > > > | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | using System.Runtime.InteropServices; /// <summary> /// Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) /// </summary> internal sealed class SQLite3_UTF16 : SQLite3 { internal SQLite3_UTF16( SQLiteDateFormats fmt, DateTimeKind kind, string fmtString, IntPtr db, string fileName, bool ownHandle ) : base(fmt, kind, fmtString, db, fileName, ownHandle) { } /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members private bool disposed; |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConnection.cs.
︙ | ︙ | |||
497 498 499 500 501 502 503 504 505 506 507 | /// <summary> /// Initializes the connection with a pre-existing native connection handle. /// </summary> /// <param name="db"> /// The native connection handle to use. /// </param> /// <param name="ownHandle"> /// Non-zero if this instance owns the native connection handle and /// should dispose of it when it is no longer needed. /// </param> | > > > | | | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | /// <summary> /// Initializes the connection with a pre-existing native connection handle. /// </summary> /// <param name="db"> /// The native connection handle to use. /// </param> /// <param name="fileName"> /// The file name corresponding to the native connection handle. /// </param> /// <param name="ownHandle"> /// Non-zero if this instance owns the native connection handle and /// should dispose of it when it is no longer needed. /// </param> internal SQLiteConnection(IntPtr db, string fileName, bool ownHandle) : this() { _ownHandle = ownHandle; _sql = new SQLite3( SQLiteDateFormats.Default, DateTimeKind.Unspecified, null, db, fileName, _ownHandle); } /// <summary> /// Initializes the connection with the specified connection string. /// </summary> /// <param name="connectionString"> /// The connection string to use. |
︙ | ︙ | |||
1951 1952 1953 1954 1955 1956 1957 | // UTF16 if called from sqlite3_open16(). // _ownHandle = true; if (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", DefaultUseUTF16Encoding.ToString()))) { | | | | 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 | // UTF16 if called from sqlite3_open16(). // _ownHandle = true; if (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", DefaultUseUTF16Encoding.ToString()))) { _sql = new SQLite3_UTF16(dateFormat, kind, dateTimeFormat, IntPtr.Zero, null, _ownHandle); } else { _sql = new SQLite3(dateFormat, kind, dateTimeFormat, IntPtr.Zero, null, _ownHandle); } } SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None; if (!SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", DefaultFailIfMissing.ToString()))) flags |= SQLiteOpenFlagsEnum.Create; |
︙ | ︙ | |||
2383 2384 2385 2386 2387 2388 2389 | // // NOTE: SQLite automatically sets the encoding of the database to // UTF16 if called from sqlite3_open16(). // if (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", DefaultUseUTF16Encoding.ToString()))) { | | | | 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 | // // NOTE: SQLite automatically sets the encoding of the database to // UTF16 if called from sqlite3_open16(). // if (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", DefaultUseUTF16Encoding.ToString()))) { _sql = new SQLite3_UTF16(dateFormat, kind, dateTimeFormat, IntPtr.Zero, null, _ownHandle); } else { _sql = new SQLite3(dateFormat, kind, dateTimeFormat, IntPtr.Zero, null, _ownHandle); } } if (_sql != null) return _sql.Shutdown(); throw new InvalidOperationException("Database connection not active."); } /// Enables or disabled extended result codes returned by SQLite |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteLog.cs.
︙ | ︙ | |||
176 177 178 179 180 181 182 | } #endif // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) | > | | > > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | } #endif // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) { _sql = new SQLite3( SQLiteDateFormats.Default, DateTimeKind.Unspecified, null, IntPtr.Zero, null, true); } // // NOTE: Create a single "global" (i.e. per-process) callback // to register with SQLite. This callback will pass the // event on to any registered handler. We only want to // do this once. // |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteModuleBase.cs.
︙ | ︙ | |||
1704 1705 1706 1707 1708 1709 1710 1711 | IntPtr[] argv, ref IntPtr pVtab, ref IntPtr pError ) { try { using (SQLiteConnection connection = new SQLiteConnection( | > > > | | 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 | IntPtr[] argv, ref IntPtr pVtab, ref IntPtr pError ) { try { string fileName = SQLiteMarshal.StringFromUtf8IntPtr( UnsafeNativeMethods.sqlite3_db_filename(pDb, IntPtr.Zero)); using (SQLiteConnection connection = new SQLiteConnection( pDb, fileName, false)) { string error = null; if (Create(connection, pAux, SQLiteMarshal.StringArrayFromUtf8IntPtrArray(argv), ref error) == SQLiteErrorCode.Ok) { |
︙ | ︙ | |||
1743 1744 1745 1746 1747 1748 1749 1750 | IntPtr[] argv, ref IntPtr pVtab, ref IntPtr pError ) { try { using (SQLiteConnection connection = new SQLiteConnection( | > > > | | 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 | IntPtr[] argv, ref IntPtr pVtab, ref IntPtr pError ) { try { string fileName = SQLiteMarshal.StringFromUtf8IntPtr( UnsafeNativeMethods.sqlite3_db_filename(pDb, IntPtr.Zero)); using (SQLiteConnection connection = new SQLiteConnection( pDb, fileName, false)) { string error = null; if (Connect(connection, pAux, SQLiteMarshal.StringArrayFromUtf8IntPtrArray(argv), ref error) == SQLiteErrorCode.Ok) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteModuleNoop.cs.
1 2 3 4 5 6 7 8 9 10 11 12 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Joe Mistachkin (joe@mistachkin.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { public class SQLiteModuleNoop : SQLiteModuleBase { #region Public Constructors | | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Joe Mistachkin (joe@mistachkin.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { public class SQLiteModuleNoop : SQLiteModuleBase { #region Public Constructors public SQLiteModuleNoop( string name ) : base(name) { // do nothing. } #endregion /////////////////////////////////////////////////////////////////////// |
︙ | ︙ |
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
︙ | ︙ | |||
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_db_handle(IntPtr stmt); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_next_stmt(IntPtr db, IntPtr stmt); | > > > > > > > | 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_db_handle(IntPtr stmt); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_db_filename(IntPtr db, IntPtr dbName); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_next_stmt(IntPtr db, IntPtr stmt); |
︙ | ︙ |
Changes to Tests/vtab.eagle.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | set sql { \ CREATE VIRTUAL TABLE t${id} USING vt${id}; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public sealed class SQLiteModuleTest${id} : SQLiteModuleNoop { public SQLiteModuleTest${id}(string name) : base(name) { // do nothing. } } ///////////////////////////////////////////////////////////////////////// public static class Test${id} { public static void Main() | > > > > > > > > > > > > > > > > > > > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | set sql { \ CREATE VIRTUAL TABLE t${id} USING vt${id}; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data.SQLite; namespace _Dynamic${id} { public sealed class SQLiteModuleTest${id} : SQLiteModuleNoop { public SQLiteModuleTest${id}(string name) : base(name) { // do nothing. } /////////////////////////////////////////////////////////////////////// public override SQLiteErrorCode Create( SQLiteConnection connection, IntPtr pClientData, string\[\] argv, ref string error ) { SQLiteErrorCode rc = DeclareTable( connection, "CREATE TABLE ignored(x);", ref error); if (rc != SQLiteErrorCode.Ok) return rc; return base.Create(connection, pClientData, argv, ref error); } } ///////////////////////////////////////////////////////////////////////// public static class Test${id} { public static void Main() |
︙ | ︙ | |||
76 77 78 79 80 81 82 | [expr {$code eq "Ok" ? [catch { object invoke _Dynamic${id}.Test${id} Main } result] : [set result ""]}] $result } -cleanup { cleanupDb $fileName unset -nocomplain result code results errors sql dataSource id db fileName | | > > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | [expr {$code eq "Ok" ? [catch { object invoke _Dynamic${id}.Test${id} Main } result] : [set result ""]}] $result } -cleanup { cleanupDb $fileName unset -nocomplain result code results errors sql dataSource id db fileName } -constraints [fixConstraints {eagle monoBug28 command.sql compile.DATA SQLite\ System.Data.SQLite}] -match regexp -result {^Ok\ System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |