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 | SQL archive |
Timelines: | family | ancestors | descendants | both | virtualTables |
Files: | files | file ages | folders |
SHA1: |
e1bef414b7415f615eafcb7fa8f2b183 |
User & Date: | mistachkin 2013-06-20 03:08:43 |
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 93 94 95 96 97 98 99 100 101 102 103 .... 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 .... 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 |
/// <summary> /// The modules created using this connection. /// </summary> protected Dictionary<string, SQLiteModuleBase> _modules; /////////////////////////////////////////////////////////////////////////////////////////////// internal SQLite3(SQLiteDateFormats fmt, DateTimeKind kind, string fmtString, bool ownHandle) : base(fmt, kind, fmtString) { _ownHandle = ownHandle; } /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members private bool disposed; private void CheckDisposed() /* throw */ ................................................................................ /// 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 { ................................................................................ /// </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(); |
> | > > > > > > > > > > | > > > > > > > > > > |
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 .... 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 .... 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 |
/// <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 */ ................................................................................ /// 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 { ................................................................................ /// </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 24 25 26 27 28 29 30 31 32 |
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, bool ownHandle)
: base(fmt, kind, fmtString, ownHandle)
{
}
///////////////////////////////////////////////////////////////////////////////////////////////
#region IDisposable "Pattern" Members
private bool disposed;
|
| > > > > > > > | |
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 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 .... 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 .... 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 |
/// <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> internal SQLiteConnection(IntPtr db, bool ownHandle) : this() { _ownHandle = ownHandle; _sql = new SQLite3( SQLiteDateFormats.Default, DateTimeKind.Unspecified, null, _ownHandle); } /// <summary> /// Initializes the connection with the specified connection string. /// </summary> /// <param name="connectionString"> /// The connection string to use. ................................................................................ // UTF16 if called from sqlite3_open16(). // _ownHandle = true; if (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", DefaultUseUTF16Encoding.ToString()))) { _sql = new SQLite3_UTF16(dateFormat, kind, dateTimeFormat, _ownHandle); } else { _sql = new SQLite3(dateFormat, kind, dateTimeFormat, _ownHandle); } } SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None; if (!SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", DefaultFailIfMissing.ToString()))) flags |= SQLiteOpenFlagsEnum.Create; ................................................................................ // // 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, _ownHandle); } else { _sql = new SQLite3(dateFormat, kind, dateTimeFormat, _ownHandle); } } if (_sql != null) return _sql.Shutdown(); throw new InvalidOperationException("Database connection not active."); } /// Enables or disabled extended result codes returned by SQLite |
> > > | | | | | | |
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 .... 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 .... 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 |
/// <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. ................................................................................ // 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; ................................................................................ // // 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 183 184 185 186 187 188 189 190 191 |
} #endif // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) _sql = new SQLite3(SQLiteDateFormats.Default, DateTimeKind.Unspecified, 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. // |
> | | > > |
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
1712
1713
1714
1715
1716
1717
1718
1719
....
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
|
IntPtr[] argv, ref IntPtr pVtab, ref IntPtr pError ) { try { using (SQLiteConnection connection = new SQLiteConnection( pDb, false)) { string error = null; if (Create(connection, pAux, SQLiteMarshal.StringArrayFromUtf8IntPtrArray(argv), ref error) == SQLiteErrorCode.Ok) { ................................................................................ IntPtr[] argv, ref IntPtr pVtab, ref IntPtr pError ) { try { using (SQLiteConnection connection = new SQLiteConnection( pDb, false)) { string error = null; if (Connect(connection, pAux, SQLiteMarshal.StringArrayFromUtf8IntPtrArray(argv), ref error) == SQLiteErrorCode.Ok) { |
>
>
>
<
>
>
>
>
<
>
|
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
....
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 (Create(connection, pAux, SQLiteMarshal.StringArrayFromUtf8IntPtrArray(argv), ref error) == SQLiteErrorCode.Ok) { ................................................................................ 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.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
********************************************************/
namespace System.Data.SQLite
{
public class SQLiteModuleNoop : SQLiteModuleBase
{
#region Public Constructors
public SQLiteModuleNoop(string name)
: base(name)
{
// do nothing.
}
#endregion
///////////////////////////////////////////////////////////////////////
|
| > > |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
********************************************************/ 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
..
76
77
78
79
80
81
82
83
84
85
86
87
88
|
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() ................................................................................ [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 |
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
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
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
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() ................................................................................ [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 |