System.Data.SQLite

Check-in [19447f0a41]
Login

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

Overview
Comment:Add experimental WaitForEnlistmentReset connection flag and WaitTimeout connection string property.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 19447f0a41c9a204209fe445beea78346281667d
User & Date: mistachkin 2018-01-30 21:16:05.328
Context
2018-02-02
17:35
Set 'Configuration' property to the base configuration when building C# projects from the batch build tool. check-in: 0e4ae42add user: mistachkin tags: trunk
2018-01-30
21:16
Add experimental WaitForEnlistmentReset connection flag and WaitTimeout connection string property. check-in: 19447f0a41 user: mistachkin tags: trunk
20:18
Update version history docs. check-in: 0fbe0dab3c user: mistachkin tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteBase.cs.
1267
1268
1269
1270
1271
1272
1273









1274
1275
1276
1277
1278
1279
1280

      /// <summary>
      /// When returning <see cref="Decimal" /> column values, always use
      /// the invariant culture when converting their values from strings.
      /// </summary>
      GetInvariantDecimal = 0x80000000000,










      /// <summary>
      /// When binding parameter values or returning column values, always
      /// treat them as though they were plain text (i.e. no numeric,
      /// date/time, or other conversions should be attempted).
      /// </summary>
      BindAndGetAllAsText = BindAllAsText | GetAllAsText,








>
>
>
>
>
>
>
>
>







1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289

      /// <summary>
      /// When returning <see cref="Decimal" /> column values, always use
      /// the invariant culture when converting their values from strings.
      /// </summary>
      GetInvariantDecimal = 0x80000000000,

      /// <summary>
      /// <b>EXPERIMENTAL</b> --
      /// Enable waiting for the enlistment to be reset prior to attempting
      /// to create a new enlistment.  This may be necessary due to the
      /// semantics used by distributed transactions, which complete
      /// asynchronously.
      /// </summary>
      WaitForEnlistmentReset = 0x100000000000,

      /// <summary>
      /// When binding parameter values or returning column values, always
      /// treat them as though they were plain text (i.e. no numeric,
      /// date/time, or other conversions should be attempted).
      /// </summary>
      BindAndGetAllAsText = BindAllAsText | GetAllAsText,

Changes to System.Data.SQLite/SQLiteConnection.cs.
1198
1199
1200
1201
1202
1203
1204










1205
1206
1207
1208
1209
1210
1211
  /// </item>
  /// <item>
  /// <description>BusyTimeout</description>
  /// <description>{time in milliseconds}<br/>Sets the busy timeout for the core library.</description>
  /// <description>N</description>
  /// <description>0</description>
  /// </item>










  /// <item>
  /// <description>Journal Mode</description>
  /// <description>
  /// <b>Delete</b> - Delete the journal file after a commit.
  /// <br/>
  /// <b>Persist</b> - Zero out and leave the journal file on disk after a
  /// commit.







>
>
>
>
>
>
>
>
>
>







1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
  /// </item>
  /// <item>
  /// <description>BusyTimeout</description>
  /// <description>{time in milliseconds}<br/>Sets the busy timeout for the core library.</description>
  /// <description>N</description>
  /// <description>0</description>
  /// </item>
  /// <item>
  /// <description>WaitTimeout</description>
  /// <description>{time in milliseconds}<br/>
  /// <b>EXPERIMENTAL</b> -- The wait timeout to use with
  /// <see cref="WaitForEnlistmentReset" /> method.  This is only used when
  /// waiting for the enlistment to be reset prior to enlisting in a transaction,
  /// and then only when the appropriate connection flag is set.</description>
  /// <description>N</description>
  /// <description>30000</description>
  /// </item>
  /// <item>
  /// <description>Journal Mode</description>
  /// <description>
  /// <b>Delete</b> - Delete the journal file after a commit.
  /// <br/>
  /// <b>Persist</b> - Zero out and leave the journal file on disk after a
  /// commit.
1351
1352
1353
1354
1355
1356
1357

1358
1359
1360
1361
1362
1363
1364
    private const int DefaultVersion = 3;
    private const int DefaultPageSize = 4096;
    private const int DefaultMaxPageCount = 0;
    private const int DefaultCacheSize = -2000;
    private const int DefaultMaxPoolSize = 100;
    private const int DefaultConnectionTimeout = 30;
    private const int DefaultBusyTimeout = 0;

    private const bool DefaultNoDefaultFlags = false;
    private const bool DefaultNoSharedFlags = false;
    private const bool DefaultFailIfMissing = false;
    private const bool DefaultReadOnly = false;
    internal const bool DefaultBinaryGUID = true;
    private const bool DefaultUseUTF16Encoding = false;
    private const bool DefaultToFullPath = true;







>







1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
    private const int DefaultVersion = 3;
    private const int DefaultPageSize = 4096;
    private const int DefaultMaxPageCount = 0;
    private const int DefaultCacheSize = -2000;
    private const int DefaultMaxPoolSize = 100;
    private const int DefaultConnectionTimeout = 30;
    private const int DefaultBusyTimeout = 0;
    private const int DefaultWaitTimeout = 30000;
    private const bool DefaultNoDefaultFlags = false;
    private const bool DefaultNoSharedFlags = false;
    private const bool DefaultFailIfMissing = false;
    private const bool DefaultReadOnly = false;
    internal const bool DefaultBinaryGUID = true;
    private const bool DefaultUseUTF16Encoding = false;
    private const bool DefaultToFullPath = true;
1567
1568
1569
1570
1571
1572
1573








1574
1575
1576
1577
1578
1579
1580

    /// <summary>
    /// The default busy timeout to use with the SQLite core library.  This is
    /// only used when opening a connection.
    /// </summary>
    private int _busyTimeout = DefaultBusyTimeout;









    /// <summary>
    /// The maximum number of retries when preparing SQL to be executed.  This
    /// normally only applies to preparation errors resulting from the database
    /// schema being changed.
    /// </summary>
    internal int _prepareRetries = DefaultPrepareRetries;








>
>
>
>
>
>
>
>







1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599

    /// <summary>
    /// The default busy timeout to use with the SQLite core library.  This is
    /// only used when opening a connection.
    /// </summary>
    private int _busyTimeout = DefaultBusyTimeout;

    /// <summary>
    /// The default wait timeout to use with <see cref="WaitForEnlistmentReset" />
    /// method.  This is only used when waiting for the enlistment to be reset
    /// prior to enlisting in a transaction, and then only when the appropriate
    /// connection flag is set.
    /// </summary>
    private int _waitTimeout = DefaultWaitTimeout;

    /// <summary>
    /// The maximum number of retries when preparing SQL to be executed.  This
    /// normally only applies to preparation errors resulting from the database
    /// schema being changed.
    /// </summary>
    internal int _prepareRetries = DefaultPrepareRetries;

3411
3412
3413
3414
3415
3416
3417















3418
3419
3420
3421
3422
3423
3424
    /// Manual distributed transaction enlistment support
    /// </summary>
    /// <param name="transaction">The distributed transaction to enlist in</param>
    public override void EnlistTransaction(System.Transactions.Transaction transaction)
    {
        CheckDisposed();
















        lock (_enlistmentSyncRoot) /* TRANSACTIONAL */
        {
            if (_enlistment != null && transaction == _enlistment._scope)
                return;
            else if (_enlistment != null)
                throw new ArgumentException("Already enlisted in a transaction");








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







3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
    /// Manual distributed transaction enlistment support
    /// </summary>
    /// <param name="transaction">The distributed transaction to enlist in</param>
    public override void EnlistTransaction(System.Transactions.Transaction transaction)
    {
        CheckDisposed();

        bool waitForEnlistmentReset;
        int waitTimeout;

        lock (_enlistmentSyncRoot) /* TRANSACTIONAL */
        {
            waitForEnlistmentReset = ((_flags & SQLiteConnectionFlags.WaitForEnlistmentReset) ==
                SQLiteConnectionFlags.WaitForEnlistmentReset);

            waitTimeout = _waitTimeout;
        }

        if (waitForEnlistmentReset)
            /* IGNORED */
            WaitForEnlistmentReset(waitTimeout);

        lock (_enlistmentSyncRoot) /* TRANSACTIONAL */
        {
            if (_enlistment != null && transaction == _enlistment._scope)
                return;
            else if (_enlistment != null)
                throw new ArgumentException("Already enlisted in a transaction");

3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
            OnChanged(this, new ConnectionEventArgs(
                SQLiteConnectionEventType.EnlistTransaction, null, null, null, null,
                null, null, new object[] { _enlistment }));
        }
    }

    /// <summary>
    /// <![CDATA[<b>]]>EXPERIMENTAL<![CDATA[</b>]]>
    /// Waits for the enlistment associated with this connection to be reset.
    /// </summary>
    /// <param name="timeoutMilliseconds">
    /// The approximate maximum number of milliseconds to wait before timing
    /// out the wait operation.
    /// </param>
    /// <returns>







|







3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
            OnChanged(this, new ConnectionEventArgs(
                SQLiteConnectionEventType.EnlistTransaction, null, null, null, null,
                null, null, new object[] { _enlistment }));
        }
    }

    /// <summary>
    /// <b>EXPERIMENTAL</b> --
    /// Waits for the enlistment associated with this connection to be reset.
    /// </summary>
    /// <param name="timeoutMilliseconds">
    /// The approximate maximum number of milliseconds to wait before timing
    /// out the wait operation.
    /// </param>
    /// <returns>
4110
4111
4112
4113
4114
4115
4116

4117
4118
4119
4120
4121
4122
4123
      try
      {
        bool usePooling = SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", GetDefaultPooling().ToString()));
        int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", SQLiteConvert.ToString(DefaultMaxPoolSize)), CultureInfo.InvariantCulture);

        _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", SQLiteConvert.ToString(DefaultConnectionTimeout)), CultureInfo.InvariantCulture);
        _busyTimeout = Convert.ToInt32(FindKey(opts, "BusyTimeout", SQLiteConvert.ToString(DefaultBusyTimeout)), CultureInfo.InvariantCulture);

        _prepareRetries = Convert.ToInt32(FindKey(opts, "PrepareRetries", SQLiteConvert.ToString(DefaultPrepareRetries)), CultureInfo.InvariantCulture);
        _progressOps = Convert.ToInt32(FindKey(opts, "ProgressOps", SQLiteConvert.ToString(DefaultProgressOps)), CultureInfo.InvariantCulture);

        enumValue = TryParseEnum(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", DefaultIsolationLevel.ToString()), true);
        _defaultIsolation = (enumValue is IsolationLevel) ? (IsolationLevel)enumValue : DefaultIsolationLevel;
        _defaultIsolation = GetEffectiveIsolationLevel(_defaultIsolation);








>







4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
      try
      {
        bool usePooling = SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", GetDefaultPooling().ToString()));
        int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", SQLiteConvert.ToString(DefaultMaxPoolSize)), CultureInfo.InvariantCulture);

        _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", SQLiteConvert.ToString(DefaultConnectionTimeout)), CultureInfo.InvariantCulture);
        _busyTimeout = Convert.ToInt32(FindKey(opts, "BusyTimeout", SQLiteConvert.ToString(DefaultBusyTimeout)), CultureInfo.InvariantCulture);
        _waitTimeout = Convert.ToInt32(FindKey(opts, "WaitTimeout", SQLiteConvert.ToString(DefaultWaitTimeout)), CultureInfo.InvariantCulture);
        _prepareRetries = Convert.ToInt32(FindKey(opts, "PrepareRetries", SQLiteConvert.ToString(DefaultPrepareRetries)), CultureInfo.InvariantCulture);
        _progressOps = Convert.ToInt32(FindKey(opts, "ProgressOps", SQLiteConvert.ToString(DefaultProgressOps)), CultureInfo.InvariantCulture);

        enumValue = TryParseEnum(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", DefaultIsolationLevel.ToString()), true);
        _defaultIsolation = (enumValue is IsolationLevel) ? (IsolationLevel)enumValue : DefaultIsolationLevel;
        _defaultIsolation = GetEffectiveIsolationLevel(_defaultIsolation);

4385
4386
4387
4388
4389
4390
4391













4392
4393
4394
4395
4396
4397
4398
    /// opening a connection.
    /// </summary>
    public int BusyTimeout
    {
        get { CheckDisposed(); return _busyTimeout; }
        set { CheckDisposed(); _busyTimeout = value; }
    }














    /// <summary>
    /// The maximum number of retries when preparing SQL to be executed.  This
    /// normally only applies to preparation errors resulting from the database
    /// schema being changed.
    /// </summary>
    public int PrepareRetries







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







4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
    /// opening a connection.
    /// </summary>
    public int BusyTimeout
    {
        get { CheckDisposed(); return _busyTimeout; }
        set { CheckDisposed(); _busyTimeout = value; }
    }

    /// <summary>
    /// <b>EXPERIMENTAL</b> --
    /// The wait timeout to use with <see cref="WaitForEnlistmentReset" /> method.
    /// This is only used when waiting for the enlistment to be reset prior to
    /// enlisting in a transaction, and then only when the appropriate connection
    /// flag is set.
    /// </summary>
    public int WaitTimeout
    {
        get { CheckDisposed(); return _waitTimeout; }
        set { CheckDisposed(); _waitTimeout = value; }
    }

    /// <summary>
    /// The maximum number of retries when preparing SQL to be executed.  This
    /// normally only applies to preparation errors resulting from the database
    /// schema being changed.
    /// </summary>
    public int PrepareRetries
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
267
268
269
270
271
272
273

























274
275
276
277
278
279
280
        return Convert.ToInt32(value, CultureInfo.CurrentCulture);
      }
      set
      {
        this["busytimeout"] = value;
      }
    }


























    /// <summary>
    /// Gets/sets the maximum number of retries when preparing SQL to be executed.
    /// This normally only applies to preparation errors resulting from the database
    /// schema being changed.
    /// </summary>
    [DisplayName("Prepare Retries")]







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







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
300
301
302
303
304
305
        return Convert.ToInt32(value, CultureInfo.CurrentCulture);
      }
      set
      {
        this["busytimeout"] = value;
      }
    }

    /// <summary>
    /// <b>EXPERIMENTAL</b> --
    /// The wait timeout to use with
    /// <see cref="SQLiteConnection.WaitForEnlistmentReset" /> method.
    /// This is only used when waiting for the enlistment to be reset
    /// prior to enlisting in a transaction, and then only when the
    /// appropriate connection flag is set.
    /// </summary>
    [DisplayName("Wait Timeout")]
    [Browsable(true)]
    [DefaultValue(30000)]
    public int WaitTimeout
    {
      get
      {
        object value;
        TryGetValue("waittimeout", out value);
        return Convert.ToInt32(value, CultureInfo.CurrentCulture);
      }
      set
      {
        this["waittimeout"] = value;
      }
    }

    /// <summary>
    /// Gets/sets the maximum number of retries when preparing SQL to be executed.
    /// This normally only applies to preparation errors resulting from the database
    /// schema being changed.
    /// </summary>
    [DisplayName("Prepare Retries")]
Changes to Tests/basic.eagle.
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
                   Enlist FailIfMissing "Legacy Format" "Read Only" \
                   Password "Page Size" "Max Page Count" "Cache Size" \
                   DateTimeFormat DateTimeKind DateTimeFormatString \
                   BaseSchemaName "Journal Mode" "Default IsolationLevel" \
                   "Foreign Keys" Flags SetDefaults ToFullPath HexPassword \
                   DefaultDbType DefaultTypeName NoSharedFlags PrepareRetries \
                   ZipVfsVersion VfsName BusyTimeout ProgressOps \
                   NoDefaultFlags "Recursive Triggers"]

    set values [list null 3 Normal True False \
                     True test.db test.db file:test.db 60 \
                     False True False True \
                     secret 4096 1024 8192 \
                     UnixEpoch Utc yyyy-MM-dd sqlite_schema \
                     Memory Serializable False \
                     Default False False 736563726574 String \
                     TEXT True 20 v2 test 1000 2000 True True]

    set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \
                            BinaryGUID DataSource Uri FullUri DefaultTimeout \
                            Enlist FailIfMissing LegacyFormat ReadOnly \
                            Password PageSize MaxPageCount CacheSize \
                            DateTimeFormat DateTimeKind DateTimeFormatString \
                            BaseSchemaName JournalMode DefaultIsolationLevel \
                            ForeignKeys Flags SetDefaults ToFullPath \
                            HexPassword DefaultDbType DefaultTypeName \
                            NoSharedFlags PrepareRetries ZipVfsVersion \
                            VfsName BusyTimeout ProgressOps NoDefaultFlags \
                            RecursiveTriggers]

    foreach key $keys value $values propertyName $propertyNames {
      set code [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            $key $value $propertyName
      } result]








|








|











|







1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
                   Enlist FailIfMissing "Legacy Format" "Read Only" \
                   Password "Page Size" "Max Page Count" "Cache Size" \
                   DateTimeFormat DateTimeKind DateTimeFormatString \
                   BaseSchemaName "Journal Mode" "Default IsolationLevel" \
                   "Foreign Keys" Flags SetDefaults ToFullPath HexPassword \
                   DefaultDbType DefaultTypeName NoSharedFlags PrepareRetries \
                   ZipVfsVersion VfsName BusyTimeout ProgressOps \
                   NoDefaultFlags "Recursive Triggers" WaitTimeout]

    set values [list null 3 Normal True False \
                     True test.db test.db file:test.db 60 \
                     False True False True \
                     secret 4096 1024 8192 \
                     UnixEpoch Utc yyyy-MM-dd sqlite_schema \
                     Memory Serializable False \
                     Default False False 736563726574 String \
                     TEXT True 20 v2 test 1000 2000 True True 30000]

    set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \
                            BinaryGUID DataSource Uri FullUri DefaultTimeout \
                            Enlist FailIfMissing LegacyFormat ReadOnly \
                            Password PageSize MaxPageCount CacheSize \
                            DateTimeFormat DateTimeKind DateTimeFormatString \
                            BaseSchemaName JournalMode DefaultIsolationLevel \
                            ForeignKeys Flags SetDefaults ToFullPath \
                            HexPassword DefaultDbType DefaultTypeName \
                            NoSharedFlags PrepareRetries ZipVfsVersion \
                            VfsName BusyTimeout ProgressOps NoDefaultFlags \
                            RecursiveTriggers WaitTimeout]

    foreach key $keys value $values propertyName $propertyNames {
      set code [catch {
        object invoke _Dynamic${id}.Test${id} GetConnectionString \
            $key $value $propertyName
      } result]

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
Keys=False\} 0 \{(?:Default|LogCallbackException),\
Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\
\{False, ToFullPath=False\} 0 {736563726574, HexPassword=736563726574} 0\
\{String, DefaultDbType=String\} 0 \{TEXT, DefaultTypeName=TEXT\} 0 \{True,\
NoSharedFlags=True\} 0 \{20, PrepareRetries=20\} 0 \{v2, ZipVfsVersion=v2\} 0\
\{test, VfsName=test\} 0 \{1000, BusyTimeout=1000\} 0 \{2000,\
ProgressOps=2000\} 0 \{True, NoDefaultFlags=True\} 0 \{True, Recursive\
Triggers=True\}$}}

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

runTest {test data-1.18 {SQLiteConvert ToDateTime (Julian Day)} -body {
  set dateTime [object invoke -create System.Data.SQLite.SQLiteConvert \
      ToDateTime 2455928.0 Utc]








|







1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
Keys=False\} 0 \{(?:Default|LogCallbackException),\
Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\
\{False, ToFullPath=False\} 0 {736563726574, HexPassword=736563726574} 0\
\{String, DefaultDbType=String\} 0 \{TEXT, DefaultTypeName=TEXT\} 0 \{True,\
NoSharedFlags=True\} 0 \{20, PrepareRetries=20\} 0 \{v2, ZipVfsVersion=v2\} 0\
\{test, VfsName=test\} 0 \{1000, BusyTimeout=1000\} 0 \{2000,\
ProgressOps=2000\} 0 \{True, NoDefaultFlags=True\} 0 \{True, Recursive\
Triggers=True\} 0 \{30000, WaitTimeout=30000\}$}}

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

runTest {test data-1.18 {SQLiteConvert ToDateTime (Julian Day)} -body {
  set dateTime [object invoke -create System.Data.SQLite.SQLiteConvert \
      ToDateTime 2455928.0 Utc]