System.Data.SQLite

Check-in [41ad3433f5]
Login

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

Overview
Comment:Added support for sqlite3_extended_result_codes(), sqlite3_errcode(), and sqlite3_extended_errcode().
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 41ad3433f5c79d69f4d6f5bab1c41bfa2392e1af
User & Date: shaneh 2011-04-15 17:33:20.820
Context
2011-04-22
18:08
Initial implementation of SQLITE_CONFIG_LOG interface. check-in: fc3e41ac85 user: shaneh tags: trunk
2011-04-15
17:33
Added support for sqlite3_extended_result_codes(), sqlite3_errcode(), and sqlite3_extended_errcode(). check-in: 41ad3433f5 user: shaneh tags: trunk
2011-04-14
01:25
Fix download links on downloads.wiki page. check-in: 0d40eb222b user: shaneh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to SQLite.Interop/src/win/interop.c.
91
92
93
94
95
96
97


















98
99
100
101
102
103
104
  if (!ret)
  {
    if(!DbHasProperty(*ppdb, 0, DB_SchemaLoaded))
      ENC(*ppdb) = SQLITE_UTF16NATIVE;
  }
  return ret;
}



















__declspec(dllexport) const char * WINAPI sqlite3_errmsg_interop(sqlite3 *db, int *plen)
{
  const char *pval = sqlite3_errmsg(db);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
116
117
118
119
120
121
122
  if (!ret)
  {
    if(!DbHasProperty(*ppdb, 0, DB_SchemaLoaded))
      ENC(*ppdb) = SQLITE_UTF16NATIVE;
  }
  return ret;
}

__declspec(dllexport) int WINAPI sqlite3_extended_result_codes_interop(sqlite3 *db, int onoff)
{
  int rc = sqlite3_extended_result_codes(db, onoff);
  return rc;
}

__declspec(dllexport) int WINAPI sqlite3_errcode_interop(sqlite3 *db)
{
  int rc = sqlite3_errcode(db);
  return rc;
}

__declspec(dllexport) int WINAPI sqlite3_extended_errcode_interop(sqlite3 *db)
{
  int rc = sqlite3_extended_errcode(db);
  return rc;
}

__declspec(dllexport) const char * WINAPI sqlite3_errmsg_interop(sqlite3 *db, int *plen)
{
  const char *pval = sqlite3_errmsg(db);
  *plen = (pval != 0) ? strlen(pval) : 0;
  return pval;
}
Changes to System.Data.SQLite/SQLite3.cs.
845
846
847
848
849
850
851




























852
853
854
855
856
857
858
      UnsafeNativeMethods.sqlite3_result_text(context, ToUTF8(value), b.Length - 1, (IntPtr)(-1));
    }

    internal override IntPtr AggregateContext(IntPtr context)
    {
      return UnsafeNativeMethods.sqlite3_aggregate_context(context, 1);
    }





























    internal override void SetPassword(byte[] passwordBytes)
    {
      int n = UnsafeNativeMethods.sqlite3_key(_sql, passwordBytes, passwordBytes.Length);
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
      UnsafeNativeMethods.sqlite3_result_text(context, ToUTF8(value), b.Length - 1, (IntPtr)(-1));
    }

    internal override IntPtr AggregateContext(IntPtr context)
    {
      return UnsafeNativeMethods.sqlite3_aggregate_context(context, 1);
    }

    /// Enables or disabled extended result codes returned by SQLite
    internal override void SetExtendedResultCodes(bool bOnOff)
    {
#if !SQLITE_STANDARD
      UnsafeNativeMethods.sqlite3_extended_result_codes_interop(_sql, (bOnOff ? -1 : 0));
#else
      UnsafeNativeMethods.sqlite3_extended_result_codes(_sql, (bOnOff ? -1 : 0));
#endif
    }
    /// Gets the last SQLite error code
    internal override int ResultCode()
    {
#if !SQLITE_STANDARD
      return UnsafeNativeMethods.sqlite3_errcode_interop(_sql);
#else
      return UnsafeNativeMethods.sqlite3_errcode(_sql);
#endif
    }
    /// Gets the last SQLite extended error code
    internal override int ExtendedResultCode()
    {
#if !SQLITE_STANDARD
      return UnsafeNativeMethods.sqlite3_extended_errcode_interop(_sql);
#else
      return UnsafeNativeMethods.sqlite3_extended_errcode(_sql);
#endif
    }

    internal override void SetPassword(byte[] passwordBytes)
    {
      int n = UnsafeNativeMethods.sqlite3_key(_sql, passwordBytes, passwordBytes.Length);
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

Changes to System.Data.SQLite/SQLiteBase.cs.
146
147
148
149
150
151
152



















153
154
155
156
157
158
159
    internal abstract void ReturnDouble(IntPtr context, double value);
    internal abstract void ReturnError(IntPtr context, string value);
    internal abstract void ReturnInt32(IntPtr context, Int32 value);
    internal abstract void ReturnInt64(IntPtr context, Int64 value);
    internal abstract void ReturnNull(IntPtr context);
    internal abstract void ReturnText(IntPtr context, string value);




















    internal abstract void SetPassword(byte[] passwordBytes);
    internal abstract void ChangePassword(byte[] newPasswordBytes);

    internal abstract void SetUpdateHook(SQLiteUpdateCallback func);
    internal abstract void SetCommitHook(SQLiteCommitCallback func);
    internal abstract void SetTraceCallback(SQLiteTraceCallback func);
    internal abstract void SetRollbackHook(SQLiteRollbackCallback func);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    internal abstract void ReturnDouble(IntPtr context, double value);
    internal abstract void ReturnError(IntPtr context, string value);
    internal abstract void ReturnInt32(IntPtr context, Int32 value);
    internal abstract void ReturnInt64(IntPtr context, Int64 value);
    internal abstract void ReturnNull(IntPtr context);
    internal abstract void ReturnText(IntPtr context, string value);

    /// <summary>
    /// Enables or disabled extened result codes returned by SQLite
    /// </summary>
    /// <param name="bOnOff">true to enable extended result codes, false to disable.</param>
    /// <returns></returns>
    internal abstract void SetExtendedResultCodes(bool bOnOff);
    /// <summary>
    /// Returns the numeric result code for the most recent failed SQLite API call 
    /// associated with the database connection. 
    /// </summary>
    /// <returns>Result code</returns>
    internal abstract int ResultCode();
    /// <summary>
    /// Returns the extended numeric result code for the most recent failed SQLite API call 
    /// associated with the database connection. 
    /// </summary>
    /// <returns>Extended result code</returns>
    internal abstract int ExtendedResultCode();

    internal abstract void SetPassword(byte[] passwordBytes);
    internal abstract void ChangePassword(byte[] newPasswordBytes);

    internal abstract void SetUpdateHook(SQLiteUpdateCallback func);
    internal abstract void SetCommitHook(SQLiteCommitCallback func);
    internal abstract void SetTraceCallback(SQLiteTraceCallback func);
    internal abstract void SetRollbackHook(SQLiteRollbackCallback func);
247
248
249
250
251
252
253

254
255
256
257
258
259
260
      }
    }

    internal static bool IsAutocommit(SQLiteConnectionHandle hdl)
    {
      return (UnsafeNativeMethods.sqlite3_get_autocommit(hdl) == 1);
    }

  }

  internal interface ISQLiteSchemaExtensions
  {
    void BuildTempSchema(SQLiteConnection cnn);
  }








>







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
      }
    }

    internal static bool IsAutocommit(SQLiteConnectionHandle hdl)
    {
      return (UnsafeNativeMethods.sqlite3_get_autocommit(hdl) == 1);
    }

  }

  internal interface ISQLiteSchemaExtensions
  {
    void BuildTempSchema(SQLiteConnection cnn);
  }

Changes to System.Data.SQLite/SQLiteConnection.cs.
971
972
973
974
975
976
977




















978
979
980
981
982
983
984
    public override ConnectionState State
    {
      get
      {
        return _connectionState;
      }
    }





















    /// <summary>
    /// Change the password (or assign a password) to an open database.
    /// </summary>
    /// <remarks>
    /// No readers or writers may be active for this process.  The database must already be open
    /// and if it already was password protected, the existing password must already have been supplied.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
    public override ConnectionState State
    {
      get
      {
        return _connectionState;
      }
    }

    /// Enables or disabled extended result codes returned by SQLite
    public void SetExtendedResultCodes(bool bOnOff)
    {
      if (_sql != null) _sql.SetExtendedResultCodes(bOnOff);
    }
    /// Enables or disabled extended result codes returned by SQLite
    public int ResultCode()
    {
      if (_sql == null) 
        throw new InvalidOperationException("Database connection not valid for getting result code.");
      return _sql.ResultCode();
    }
    /// Enables or disabled extended result codes returned by SQLite
    public int ExtendedResultCode()
    {
      if (_sql == null)
        throw new InvalidOperationException("Database connection not valid for getting extended result code.");
      return _sql.ExtendedResultCode();
    }

    /// <summary>
    /// Change the password (or assign a password) to an open database.
    /// </summary>
    /// <remarks>
    /// No readers or writers may be active for this process.  The database must already be open
    /// and if it already was password protected, the existing password must already have been supplied.
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
74
75
76
77
78
79
80









81
82
83
84
85
86
87

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_column_text_interop(IntPtr stmt, int index, out int len);

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_column_text16_interop(IntPtr stmt, int index, out int len);










    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_errmsg_interop(IntPtr db, out int len);

    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_prepare_interop(IntPtr db, IntPtr pSql, int nBytes, out IntPtr stmt, out IntPtr ptrRemain, out int nRemain);

    [DllImport(SQLITE_DLL)]







>
>
>
>
>
>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_column_text_interop(IntPtr stmt, int index, out int len);

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_column_text16_interop(IntPtr stmt, int index, out int len);

    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_extended_result_codes_interop(IntPtr db, int onoff);

    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_errcode_interop(IntPtr db);

    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_extended_errcode_interop(IntPtr db);

    [DllImport(SQLITE_DLL)]
    internal static extern IntPtr sqlite3_errmsg_interop(IntPtr db, out int len);

    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_prepare_interop(IntPtr db, IntPtr pSql, int nBytes, out IntPtr stmt, out IntPtr ptrRemain, out int nRemain);

    [DllImport(SQLITE_DLL)]
256
257
258
259
260
261
262





















263
264
265
266
267
268
269
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index);






















#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_errmsg(IntPtr db);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_column_text16(IntPtr stmt, int index);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_extended_result_codes(IntPtr db, int onoff);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_errcode(IntPtr db);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_extended_errcode(IntPtr db);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_errmsg(IntPtr db);

Changes to test/TestCases.cs.
1
2
3
4
5
6
7

8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.Data.Common;
using System.Data;
using System.Data.SQLite;
using System.Transactions;
using System.Collections.Generic;
using System.Text;


namespace test
{
  internal class TestCases : TestCaseBase
  {
    private List<string> droptables = new List<string>();
    private List<string> maydroptable = new List<string>();


    internal TestCases()
    {
    }

    internal TestCases(DbProviderFactory factory, string connectionString)
      : base(factory, connectionString)
    {
    }

    /// <summary>
    /// Inserts binary data into the database using a named parameter
    /// </summary>
    internal void BinaryInsert()







>







>





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Data.Common;
using System.Data;
using System.Data.SQLite;
using System.Transactions;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace test
{
  internal class TestCases : TestCaseBase
  {
    private List<string> droptables = new List<string>();
    private List<string> maydroptable = new List<string>();
    

    internal TestCases()
    {
    }

    internal TestCases(DbProviderFactory factory, string connectionString, string factoryString)
      : base(factory, connectionString, factoryString)
    {
    }

    /// <summary>
    /// Inserts binary data into the database using a named parameter
    /// </summary>
    internal void BinaryInsert()
1499
1500
1501
1502
1503
1504
1505






















1506
1507
1508
1509
1510
1511
1512
          newcnn.Close();
        }
        newcnn.ConnectionString = RO_connectionString;
        newcnn.Open();
        newcnn.Dispose();
      } 
    }























    /// <summary>
    /// Open a reader and then attempt to write to test the writer's command timeout property
    /// SQLite doesn't allow a write when a reader is active.
    /// *** NOTE AS OF 3.3.8 this test no longer blocks because SQLite now allows you to update table(s)
    /// while a reader is active on the same connection.  Therefore the timeout test is invalid
    /// </summary>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
          newcnn.Close();
        }
        newcnn.ConnectionString = RO_connectionString;
        newcnn.Open();
        newcnn.Dispose();
      } 
    }

    /// <summary>
    /// Checks to extended error code result support.
    /// </summary>
    [Test]
    internal void ExtendedResultCodesTest()
    {
      if (_factstring.ToLower().Contains("sqlite"))
      {
        SQLiteConnection cnn = new SQLiteConnection(_cnnstring.ConnectionString);

        cnn.Open();

        // Turn on extended result codes
        cnn.SetExtendedResultCodes(true);

        int rc = cnn.ResultCode();
        int xrc = cnn.ExtendedResultCode();

        cnn.Close();
      }
    }

    /// <summary>
    /// Open a reader and then attempt to write to test the writer's command timeout property
    /// SQLite doesn't allow a write when a reader is active.
    /// *** NOTE AS OF 3.3.8 this test no longer blocks because SQLite now allows you to update table(s)
    /// while a reader is active on the same connection.  Therefore the timeout test is invalid
    /// </summary>
1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999

  delegate void TestCompletedEvent(object sender, TestEventArgs args);
  delegate void TestStartingEvent(object sender, TestEventArgs args);

  internal abstract class TestCaseBase
  {
    protected DbProviderFactory _fact;

    protected DbConnection _cnn = null;
    protected DbConnectionStringBuilder _cnnstring;
    protected Dictionary<string, bool> _tests = new Dictionary<string,bool>();

    public event TestCompletedEvent OnTestFinished;
    public event TestStartingEvent OnTestStarting;
    public event EventHandler OnAllTestsDone;







>







2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024

  delegate void TestCompletedEvent(object sender, TestEventArgs args);
  delegate void TestStartingEvent(object sender, TestEventArgs args);

  internal abstract class TestCaseBase
  {
    protected DbProviderFactory _fact;
    protected string _factstring;
    protected DbConnection _cnn = null;
    protected DbConnectionStringBuilder _cnnstring;
    protected Dictionary<string, bool> _tests = new Dictionary<string,bool>();

    public event TestCompletedEvent OnTestFinished;
    public event TestStartingEvent OnTestStarting;
    public event EventHandler OnAllTestsDone;
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028

      foreach (KeyValuePair<TestAttribute, System.Reflection.MethodInfo> pair in items)
      {
        _tests.Add(pair.Value.Name, true);
      }
    }

    protected TestCaseBase(DbProviderFactory factory, string connectionString)
    {
      _fact = factory;

      _cnn = _fact.CreateConnection();
      _cnn.ConnectionString = connectionString;
      _cnnstring = _fact.CreateConnectionStringBuilder();
      _cnnstring.ConnectionString = connectionString;
      _cnn.Open();
    }








|


>







2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054

      foreach (KeyValuePair<TestAttribute, System.Reflection.MethodInfo> pair in items)
      {
        _tests.Add(pair.Value.Name, true);
      }
    }

    protected TestCaseBase(DbProviderFactory factory, string connectionString, string factoryString)
    {
      _fact = factory;
      _factstring = factoryString;
      _cnn = _fact.CreateConnection();
      _cnn.ConnectionString = connectionString;
      _cnnstring = _fact.CreateConnectionStringBuilder();
      _cnnstring.ConnectionString = connectionString;
      _cnn.Open();
    }

Changes to test/TestCasesDialog.cs.
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
      ToolStripMenuItem item = sender as ToolStripMenuItem;
      if (item != null)
        _testitems.Tests[item.Text] = item.Checked;
    }

    private void runButton_Click(object sender, EventArgs e)
    {

      DbProviderFactory factory = DbProviderFactories.GetFactory(_provider.SelectedItem.ToString());
      _test = new TestCases(factory, _connectionString.Text);
      _test.Tests = _testitems.Tests;

      _test.OnTestStarting += new TestStartingEvent(_test_OnTestStarting);
      _test.OnTestFinished += new TestCompletedEvent(_test_OnTestFinished);
      _test.OnAllTestsDone += new EventHandler(_test_OnAllTestsDone);
      _grid.Rows.Clear();
      runButton.Enabled = false;







>
|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
      ToolStripMenuItem item = sender as ToolStripMenuItem;
      if (item != null)
        _testitems.Tests[item.Text] = item.Checked;
    }

    private void runButton_Click(object sender, EventArgs e)
    {
      string factoryString = _provider.SelectedItem.ToString();
      DbProviderFactory factory = DbProviderFactories.GetFactory(factoryString);
      _test = new TestCases(factory, _connectionString.Text, factoryString);
      _test.Tests = _testitems.Tests;

      _test.OnTestStarting += new TestStartingEvent(_test_OnTestStarting);
      _test.OnTestFinished += new TestCompletedEvent(_test_OnTestFinished);
      _test.OnAllTestsDone += new EventHandler(_test_OnAllTestsDone);
      _grid.Rows.Clear();
      runButton.Enabled = false;