System.Data.SQLite
Check-in [e6cc5d000b]
Not logged in

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

Overview
Comment:Various minor performance enhancements to the SQLiteDataReader class. Pursuant to [e122d26e70].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e6cc5d000b9d9caf2232d9684fc430db3d53b76c
User & Date: mistachkin 2014-10-08 18:49:36
Context
2014-10-08
20:58
Update SQLite core library to the latest trunk code. check-in: da3ee20ded user: mistachkin tags: trunk
18:49
Various minor performance enhancements to the SQLiteDataReader class. Pursuant to [e122d26e70]. check-in: e6cc5d000b user: mistachkin tags: trunk
00:09
Update SQLite core library to the latest trunk code. check-in: 3c2212a03d user: mistachkin tags: trunk
2014-10-07
17:52
More performance adjustments to the data reader class. Pursuant to [e122d26e70]. Closed-Leaf check-in: 53e8310fda user: mistachkin tags: experimental
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Doc/Extra/Provider/version.html.

43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.95.0 - November XX, 2014 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.8.7</a>.</li>
      <li>Make sure SQL statements generated for DbUpdateCommandTree objects are properly delimited.</li>

      <li>In the SQLiteDataReader.VerifyType method, remove duplicate &quot;if&quot; statement for the DbType.SByte value and move the remaining &quot;if&quot; to the Int64 affinity.  Fix for <a href="http://system.data.sqlite.org/index.html/info/c5cc2fb334">[c5cc2fb334]</a>.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    </ul>
    <p><b>1.0.94.0 - September 9, 2014</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_8_6.html">SQLite 3.8.6</a>.</li>
      <li>Updated to <a href="http://www.nuget.org/packages/EntityFramework/6.1.1">Entity Framework 6.1.1</a>.</li>
      <li>Refactor and simplify NuGet packages in order to support per-solution SQLite interop assembly files.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Add RefreshFlags method to the SQLiteDataReader class to forcibly refresh its connection flags.</li>







>
|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    <div id="mainSection">
    <div id="mainBody">
    <h1 class="heading">Version History</h1>
    <p><b>1.0.95.0 - November XX, 2014 <font color="red">(release scheduled)</font></b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.8.7</a>.</li>
      <li>Make sure SQL statements generated for DbUpdateCommandTree objects are properly delimited.</li>
      <li>Various minor performance enhancements to the SQLiteDataReader class. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/e122d26e70">[e122d26e70]</a>.</li>
      <li>In the SQLiteDataReader.VerifyType method, remove duplicate &quot;if&quot; statement for the DbType.SByte value and move the remaining &quot;if&quot; to the Int64 affinity. Fix for <a href="http://system.data.sqlite.org/index.html/info/c5cc2fb334">[c5cc2fb334]</a>.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    </ul>
    <p><b>1.0.94.0 - September 9, 2014</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_8_6.html">SQLite 3.8.6</a>.</li>
      <li>Updated to <a href="http://www.nuget.org/packages/EntityFramework/6.1.1">Entity Framework 6.1.1</a>.</li>
      <li>Refactor and simplify NuGet packages in order to support per-solution SQLite interop assembly files.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Add RefreshFlags method to the SQLiteDataReader class to forcibly refresh its connection flags.</li>

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

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    /// <summary>
    /// The connection the command is associated with
    /// </summary>
    private SQLiteConnection _cnn;
    /// <summary>
    /// The version of the connection the command is associated with
    /// </summary>
    private long _version;
    /// <summary>
    /// Indicates whether or not a DataReader is active on the command.
    /// </summary>
    private WeakReference _activeReader;
    /// <summary>
    /// The timeout for the command, kludged because SQLite doesn't support per-command timeout values
    /// </summary>







|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    /// <summary>
    /// The connection the command is associated with
    /// </summary>
    private SQLiteConnection _cnn;
    /// <summary>
    /// The version of the connection the command is associated with
    /// </summary>
    private int _version;
    /// <summary>
    /// Indicates whether or not a DataReader is active on the command.
    /// </summary>
    private WeakReference _activeReader;
    /// <summary>
    /// The timeout for the command, kludged because SQLite doesn't support per-command timeout values
    /// </summary>

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

516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
    /// Non-zero if the built-in (i.e. framework provided) connection string
    /// parser should be used when opening the connection.
    /// </summary>
    private bool _parseViaFramework;

    internal bool _binaryGuid;

    internal long _version;

    private event SQLiteAuthorizerEventHandler _authorizerHandler;
    private event SQLiteUpdateEventHandler _updateHandler;
    private event SQLiteCommitHandler _commitHandler;
    private event SQLiteTraceEventHandler _traceHandler;
    private event EventHandler _rollbackHandler;








|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
    /// Non-zero if the built-in (i.e. framework provided) connection string
    /// parser should be used when opening the connection.
    /// </summary>
    private bool _parseViaFramework;

    internal bool _binaryGuid;

    internal int _version;

    private event SQLiteAuthorizerEventHandler _authorizerHandler;
    private event SQLiteUpdateEventHandler _updateHandler;
    private event SQLiteCommitHandler _commitHandler;
    private event SQLiteTraceEventHandler _traceHandler;
    private event EventHandler _rollbackHandler;

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

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
265
266
267
268
269
270
271
272


273
274
275
276
277
278
279
...
342
343
344
345
346
347
348





349
350
351
352
353
354
355
356
357
358
359
360
361









362
363
364
365
366
367
368
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399

400
401
402
403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
450
451
452
453
454
455
...
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491
492
493
494
...
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
526
527
528
529
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
...
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
....
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
....
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
....
1258
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
....
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
....
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464


1465


1466

1467

1468

1469
1470
1471
1472
1473
1474
1475
1476
    /// An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified
    /// </summary>
    private SQLiteKeyReader _keyInfo;

    /// <summary>
    /// Matches the version of the connection.
    /// </summary>
    internal long _version;

    /// <summary>
    /// The "stub" (i.e. placeholder) base schema name to use when returning
    /// column schema information.  Matches the base schema name used by the
    /// associated connection.
    /// </summary>
    private string _baseSchemaName;
................................................................................

      if (_command == null)
        throw new InvalidOperationException("DataReader has been closed");

      if (_version == 0)
        throw new SQLiteException("Execution was aborted by the user");

      if (_command.Connection.State != ConnectionState.Open || _command.Connection._version != _version)


        throw new InvalidOperationException("Connection was closed, statement was terminated");
    }

    /// <summary>
    /// Throw an error if a row is not loaded
    /// </summary>
    private void CheckValidRow()
................................................................................
        {
            CheckDisposed();
            CheckClosed();

            return _stepCount;
        }
    }






    /// <summary>
    /// Returns the number of visible fields in the current resultset
    /// </summary>
    public override int VisibleFieldCount
    {
      get
      {
        CheckDisposed();
        CheckClosed();
        return _fieldCount;
      }
    }










    /// <summary>
    /// SQLite is inherently un-typed.  All datatypes in SQLite are natively strings.  The definition of the columns of a table
    /// and the affinity of returned types are all we have to go on to type-restrict data in the reader.
    ///
    /// This function attempts to verify that the type of data being requested of a column matches the datatype of the column.  In
    /// the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob)
................................................................................
    /// <returns>
    /// This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity.
    /// </returns>
    /// <param name="i">The index of the column to type-check</param>
    /// <param name="typ">The type we want to get out of the column</param>
    private TypeAffinity VerifyType(int i, DbType typ)
    {
      CheckClosed();
      CheckValidRow();

      TypeAffinity affinity = GetSQLiteType(_flags, i).Affinity;

      switch (affinity)
      {
        case TypeAffinity.Int64:
          if (typ == DbType.Int16) return affinity;
          if (typ == DbType.Int32) return affinity;
          if (typ == DbType.Int64) return affinity;
          if (typ == DbType.Boolean) return affinity;
          if (typ == DbType.SByte) return affinity;
          if (typ == DbType.Byte) return affinity;
          if (typ == DbType.DateTime) return affinity;
          if (typ == DbType.Single) return affinity;
          if (typ == DbType.Double) return affinity;

          if (typ == DbType.Decimal) return affinity;
          break;
        case TypeAffinity.Double:
          if (typ == DbType.Single) return affinity;
          if (typ == DbType.Double) return affinity;

          if (typ == DbType.Decimal) return affinity;
          if (typ == DbType.DateTime) return affinity;
          break;
        case TypeAffinity.Text:
          if (typ == DbType.String) return affinity;
          if (typ == DbType.Guid) return affinity;
          if (typ == DbType.DateTime) return affinity;
          if (typ == DbType.Decimal) return affinity;
          break;
        case TypeAffinity.Blob:
          if (typ == DbType.Guid) return affinity;
          if (typ == DbType.String) return affinity;
          if (typ == DbType.Binary) return affinity;

          break;
      }

      throw new InvalidCastException();
    }

    /// <summary>
    /// Retrieves the column as a boolean value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>bool</returns>
    public override bool GetBoolean(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetBoolean(i - VisibleFieldCount);

      VerifyType(i, DbType.Boolean);
      return Convert.ToBoolean(GetValue(i), CultureInfo.CurrentCulture);
    }

    /// <summary>
    /// Retrieves the column as a single byte value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>byte</returns>
    public override byte GetByte(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetByte(i - VisibleFieldCount);

      VerifyType(i, DbType.Byte);
      return Convert.ToByte(_activeStatement._sql.GetInt32(_activeStatement, i));
    }

    /// <summary>
    /// Retrieves a column as an array of bytes (blob)
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <param name="fieldOffset">The zero-based index of where to begin reading the data</param>
................................................................................
    /// <param name="length">The number of bytes to retrieve</param>
    /// <returns>The actual number of bytes written into the array</returns>
    /// <remarks>
    /// To determine the number of bytes in the column, pass a null value for the buffer.  The total length will be returned.
    /// </remarks>
    public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetBytes(i - VisibleFieldCount, fieldOffset, buffer, bufferoffset, length);

      VerifyType(i, DbType.Binary);
      return _activeStatement._sql.GetBytes(_activeStatement, i, (int)fieldOffset, buffer, bufferoffset, length);
    }

    /// <summary>
    /// Returns the column as a single character
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>char</returns>
    public override char GetChar(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetChar(i - VisibleFieldCount);

      VerifyType(i, DbType.SByte);
      return Convert.ToChar(_activeStatement._sql.GetInt32(_activeStatement, i));
    }

    /// <summary>
    /// Retrieves a column as an array of chars (blob)
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <param name="fieldoffset">The zero-based index of where to begin reading the data</param>
................................................................................
    /// <param name="length">The number of bytes to retrieve</param>
    /// <returns>The actual number of characters written into the array</returns>
    /// <remarks>
    /// To determine the number of characters in the column, pass a null value for the buffer.  The total length will be returned.
    /// </remarks>
    public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetChars(i - VisibleFieldCount, fieldoffset, buffer, bufferoffset, length);

      VerifyType(i, DbType.String);
      return _activeStatement._sql.GetChars(_activeStatement, i, (int)fieldoffset, buffer, bufferoffset, length);
    }

    /// <summary>
    /// Retrieves the name of the back-end datatype of the column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>string</returns>
    public override string GetDataTypeName(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetDataTypeName(i - VisibleFieldCount);

      SQLiteType typ = GetSQLiteType(_flags, i);
      if (typ.Type == DbType.Object) return SQLiteConvert.SQLiteTypeToType(typ).Name;
      return _activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity);
    }

    /// <summary>
    /// Retrieve the column as a date/time value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>DateTime</returns>
    public override DateTime GetDateTime(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetDateTime(i - VisibleFieldCount);

      VerifyType(i, DbType.DateTime);
      return _activeStatement._sql.GetDateTime(_activeStatement, i);
    }

    /// <summary>
    /// Retrieve the column as a decimal value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>decimal</returns>
    public override decimal GetDecimal(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetDecimal(i - VisibleFieldCount);

      VerifyType(i, DbType.Decimal);
      return Decimal.Parse(_activeStatement._sql.GetText(_activeStatement, i), NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// Returns the column as a double
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>double</returns>
    public override double GetDouble(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetDouble(i - VisibleFieldCount);

      VerifyType(i, DbType.Double);
      return _activeStatement._sql.GetDouble(_activeStatement, i);
    }

    /// <summary>
    /// Returns the .NET type of a given column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Type</returns>
    public override Type GetFieldType(int i)
    {
      CheckDisposed();

      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetFieldType(i - VisibleFieldCount);

      return SQLiteConvert.SQLiteTypeToType(GetSQLiteType(_flags, i));
    }

    /// <summary>
    /// Returns a column as a float value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>float</returns>
    public override float GetFloat(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetFloat(i - VisibleFieldCount);

      VerifyType(i, DbType.Single);
      return Convert.ToSingle(_activeStatement._sql.GetDouble(_activeStatement, i));
    }

    /// <summary>
    /// Returns the column as a Guid
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Guid</returns>
    public override Guid GetGuid(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetGuid(i - VisibleFieldCount);

      TypeAffinity affinity = VerifyType(i, DbType.Guid);
      if (affinity == TypeAffinity.Blob)
      {
        byte[] buffer = new byte[16];
        _activeStatement._sql.GetBytes(_activeStatement, i, 0, buffer, 0, 16);
        return new Guid(buffer);
      }
      else
        return new Guid(_activeStatement._sql.GetText(_activeStatement, i));
    }

    /// <summary>
    /// Returns the column as a short
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Int16</returns>
    public override Int16 GetInt16(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetInt16(i - VisibleFieldCount);

      VerifyType(i, DbType.Int16);
      return Convert.ToInt16(_activeStatement._sql.GetInt32(_activeStatement, i));
    }

    /// <summary>
    /// Retrieves the column as an int
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Int32</returns>
    public override Int32 GetInt32(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetInt32(i - VisibleFieldCount);

      VerifyType(i, DbType.Int32);
      return _activeStatement._sql.GetInt32(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the column as a long
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Int64</returns>
    public override Int64 GetInt64(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetInt64(i - VisibleFieldCount);

      VerifyType(i, DbType.Int64);
      return _activeStatement._sql.GetInt64(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the name of the column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>string</returns>
    public override string GetName(int i)
    {
      CheckDisposed();

      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetName(i - VisibleFieldCount);

      return _activeStatement._sql.ColumnName(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the i of a column, given its name
    /// </summary>
    /// <param name="name">The name of the column to retrieve</param>
    /// <returns>The int i of the column</returns>
    public override int GetOrdinal(string name)
    {
      CheckDisposed();
      CheckClosed();

      if (_throwOnDisposed) SQLiteCommand.Check(_command);

      //
      // NOTE: First, check if the column name cache has been initialized yet.
      //       If not, do it now.
      //
      if (_fieldIndexes == null)
................................................................................
      if (!_fieldIndexes.TryGetValue(name, out r))
      {
          r = _activeStatement._sql.ColumnIndex(_activeStatement, name);

          if (r == -1 && _keyInfo != null)
          {
              r = _keyInfo.GetOrdinal(name);
              if (r > -1) r += VisibleFieldCount;
          }

          _fieldIndexes.Add(name, r);
      }

      return r;
    }
................................................................................
    /// <summary>
    /// Retrieves the column as a string
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>string</returns>
    public override string GetString(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetString(i - VisibleFieldCount);

      VerifyType(i, DbType.String);
      return _activeStatement._sql.GetText(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the column as an object corresponding to the underlying datatype of the column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>object</returns>
    public override object GetValue(int i)
    {
      CheckDisposed();
      CheckValidRow();

      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.GetValue(i - VisibleFieldCount);

      SQLiteType typ = GetSQLiteType(_flags, i);

      if (((_flags & SQLiteConnectionFlags.DetectTextAffinity) == SQLiteConnectionFlags.DetectTextAffinity) &&
          ((typ == null) || (typ.Affinity == TypeAffinity.Text)))
      {
          typ = GetSQLiteType(
              typ, _activeStatement._sql.GetText(_activeStatement, i));
      }
      else if (((_flags & SQLiteConnectionFlags.DetectStringType) == SQLiteConnectionFlags.DetectStringType) &&
          ((typ == null) || SQLiteConvert.IsStringDbType(typ.Type)))
      {
          typ = GetSQLiteType(
              typ, _activeStatement._sql.GetText(_activeStatement, i));
      }

      return _activeStatement._sql.GetValue(_activeStatement, _flags, i, typ);
    }

    /// <summary>
    /// Retreives the values of multiple columns, up to the size of the supplied array
    /// </summary>
    /// <param name="values">The array to fill with values from the columns in the current resultset</param>
    /// <returns>The number of columns retrieved</returns>
................................................................................
    public NameValueCollection GetValues()
    {
        CheckDisposed();

        if ((_activeStatement == null) || (_activeStatement._sql == null))
            throw new InvalidOperationException();

        int nMax = VisibleFieldCount;
        NameValueCollection result = new NameValueCollection(nMax);

        for (int n = 0; n < nMax; n++)
        {
            string name = _activeStatement._sql.ColumnName(_activeStatement, n);
            string value = _activeStatement._sql.GetText(_activeStatement, n);

................................................................................
    /// <summary>
    /// Returns True if the specified column is null
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>True or False</returns>
    public override bool IsDBNull(int i)
    {
      CheckDisposed();


      if (i >= VisibleFieldCount && _keyInfo != null)
        return _keyInfo.IsDBNull(i - VisibleFieldCount);

      return _activeStatement._sql.IsNull(_activeStatement, i);
    }

    /// <summary>
    /// Moves to the next resultset in multiple row-returning SQL command.
    /// </summary>
    /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns>
    public override bool NextResult()
................................................................................
            _readingState = 1; // This command returned columns but no rows, so return true, but HasRows = false and Read() returns false
          }
        }

        // Ahh, we found a row-returning resultset eligible to be returned!
        _activeStatement = stmt;
        _fieldCount = fieldCount;
        _fieldIndexes = null;
        _fieldTypeArray = null;

        if ((_commandBehavior & CommandBehavior.KeyInfo) != 0)
          LoadKeyInfo();

        return true;
      }
    }
................................................................................
    /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
    /// </summary>
    /// <param name="flags">The flags associated with the parent connection object.</param>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>A SQLiteType structure</returns>
    private SQLiteType GetSQLiteType(SQLiteConnectionFlags flags, int i)
    {
      SQLiteType typ;

      // Initialize the field types array if not already initialized
      if (_fieldTypeArray == null)
        _fieldTypeArray = new SQLiteType[VisibleFieldCount];

      // Initialize this column's field type instance
      if (_fieldTypeArray[i] == null) _fieldTypeArray[i] = new SQLiteType();

      typ = _fieldTypeArray[i];

      // If not initialized, then fetch the declared column datatype and attempt to convert it
      // to a known DbType.
      if (typ.Affinity == TypeAffinity.Uninitialized)


        typ.Type = SQLiteConvert.TypeNameToDbType(GetConnection(this), _activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity), flags);


      else

        typ.Affinity = _activeStatement._sql.ColumnAffinity(_activeStatement, i);



      return typ;
    }

    /// <summary>
    /// Reads the next row from the resultset
    /// </summary>
    /// <returns>True if a new row was successfully loaded and is ready for processing</returns>
    public override bool Read()







|







 







|
>
>







 







>
>
>
>
>










|


>
>
>
>
>
>
>
>
>







 







<
<
<
|

|
|
|
|
|
|
|
|
|
|
<
|
>
|
|
|
<
|
>
|
|
|
|
|
|
|
|
|
|
|
<
|
>
|
|

|









|
>

|
|

|
|









|
>

|
|

|
|







 







|
>

|
|

|
|









|
>

|
|

|
|







 







|
>

|
|

|
|









|
>

|
|

|
|
|









|
>

|
|

|
|









|
>

|
|

|
|









|
>

|
|

|
|









|

|
|

|









|
>

|
|

|
|









|
>

|
|

|
|
|
|
|
|
|
|
|









|
>

|
|

|
|









|
>

|
|

|
|









|
>

|
|

|
|









|

|
|

|










|
>







 







|







 







|
>

|
|

|
|









|
|

|
|

|

|
|
|
|
|
|
|
|
|
|
|
|

|







 







|







 







|
>

|
|

|







 







|
|







 







|

<
|
<
|
|
|
|
<

|
|
|
>
>
|
>
>
|
>
|
>
|
>
|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
...
387
388
389
390
391
392
393



394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
....
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
....
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
....
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
....
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
....
1474
1475
1476
1477
1478
1479
1480
1481
1482

1483

1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
    /// An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified
    /// </summary>
    private SQLiteKeyReader _keyInfo;

    /// <summary>
    /// Matches the version of the connection.
    /// </summary>
    internal int _version;

    /// <summary>
    /// The "stub" (i.e. placeholder) base schema name to use when returning
    /// column schema information.  Matches the base schema name used by the
    /// associated connection.
    /// </summary>
    private string _baseSchemaName;
................................................................................

      if (_command == null)
        throw new InvalidOperationException("DataReader has been closed");

      if (_version == 0)
        throw new SQLiteException("Execution was aborted by the user");

      SQLiteConnection connection = _command.Connection;

      if (connection._version != _version || connection.State != ConnectionState.Open)
        throw new InvalidOperationException("Connection was closed, statement was terminated");
    }

    /// <summary>
    /// Throw an error if a row is not loaded
    /// </summary>
    private void CheckValidRow()
................................................................................
        {
            CheckDisposed();
            CheckClosed();

            return _stepCount;
        }
    }

    private int PrivateVisibleFieldCount
    {
        get { return _fieldCount; }
    }

    /// <summary>
    /// Returns the number of visible fields in the current resultset
    /// </summary>
    public override int VisibleFieldCount
    {
      get
      {
        CheckDisposed();
        CheckClosed();
        return PrivateVisibleFieldCount;
      }
    }

    /// <summary>
    /// This method is used to make sure the result set is open and a row is currently available.
    /// </summary>
    private void VerifyForGet()
    {
        CheckClosed();
        CheckValidRow();
    }

    /// <summary>
    /// SQLite is inherently un-typed.  All datatypes in SQLite are natively strings.  The definition of the columns of a table
    /// and the affinity of returned types are all we have to go on to type-restrict data in the reader.
    ///
    /// This function attempts to verify that the type of data being requested of a column matches the datatype of the column.  In
    /// the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob)
................................................................................
    /// <returns>
    /// This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity.
    /// </returns>
    /// <param name="i">The index of the column to type-check</param>
    /// <param name="typ">The type we want to get out of the column</param>
    private TypeAffinity VerifyType(int i, DbType typ)
    {



        TypeAffinity affinity = GetSQLiteType(_flags, i).Affinity;

        switch (affinity)
        {
            case TypeAffinity.Int64:
                if (typ == DbType.Int64) return affinity;
                if (typ == DbType.Int32) return affinity;
                if (typ == DbType.Int16) return affinity;
                if (typ == DbType.Byte) return affinity;
                if (typ == DbType.SByte) return affinity;
                if (typ == DbType.Boolean) return affinity;
                if (typ == DbType.DateTime) return affinity;

                if (typ == DbType.Double) return affinity;
                if (typ == DbType.Single) return affinity;
                if (typ == DbType.Decimal) return affinity;
                break;
            case TypeAffinity.Double:

                if (typ == DbType.Double) return affinity;
                if (typ == DbType.Single) return affinity;
                if (typ == DbType.Decimal) return affinity;
                if (typ == DbType.DateTime) return affinity;
                break;
            case TypeAffinity.Text:
                if (typ == DbType.String) return affinity;
                if (typ == DbType.Guid) return affinity;
                if (typ == DbType.DateTime) return affinity;
                if (typ == DbType.Decimal) return affinity;
                break;
            case TypeAffinity.Blob:
                if (typ == DbType.Guid) return affinity;

                if (typ == DbType.Binary) return affinity;
                if (typ == DbType.String) return affinity;
                break;
        }

        throw new InvalidCastException();
    }

    /// <summary>
    /// Retrieves the column as a boolean value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>bool</returns>
    public override bool GetBoolean(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetBoolean(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Boolean);
        return Convert.ToBoolean(GetValue(i), CultureInfo.CurrentCulture);
    }

    /// <summary>
    /// Retrieves the column as a single byte value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>byte</returns>
    public override byte GetByte(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetByte(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Byte);
        return Convert.ToByte(_activeStatement._sql.GetInt32(_activeStatement, i));
    }

    /// <summary>
    /// Retrieves a column as an array of bytes (blob)
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <param name="fieldOffset">The zero-based index of where to begin reading the data</param>
................................................................................
    /// <param name="length">The number of bytes to retrieve</param>
    /// <returns>The actual number of bytes written into the array</returns>
    /// <remarks>
    /// To determine the number of bytes in the column, pass a null value for the buffer.  The total length will be returned.
    /// </remarks>
    public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetBytes(i - PrivateVisibleFieldCount, fieldOffset, buffer, bufferoffset, length);

        VerifyType(i, DbType.Binary);
        return _activeStatement._sql.GetBytes(_activeStatement, i, (int)fieldOffset, buffer, bufferoffset, length);
    }

    /// <summary>
    /// Returns the column as a single character
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>char</returns>
    public override char GetChar(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetChar(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.SByte);
        return Convert.ToChar(_activeStatement._sql.GetInt32(_activeStatement, i));
    }

    /// <summary>
    /// Retrieves a column as an array of chars (blob)
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <param name="fieldoffset">The zero-based index of where to begin reading the data</param>
................................................................................
    /// <param name="length">The number of bytes to retrieve</param>
    /// <returns>The actual number of characters written into the array</returns>
    /// <remarks>
    /// To determine the number of characters in the column, pass a null value for the buffer.  The total length will be returned.
    /// </remarks>
    public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetChars(i - PrivateVisibleFieldCount, fieldoffset, buffer, bufferoffset, length);

        VerifyType(i, DbType.String);
        return _activeStatement._sql.GetChars(_activeStatement, i, (int)fieldoffset, buffer, bufferoffset, length);
    }

    /// <summary>
    /// Retrieves the name of the back-end datatype of the column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>string</returns>
    public override string GetDataTypeName(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetDataTypeName(i - PrivateVisibleFieldCount);

        SQLiteType typ = GetSQLiteType(_flags, i);
        if (typ.Type == DbType.Object) return SQLiteConvert.SQLiteTypeToType(typ).Name;
        return _activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity);
    }

    /// <summary>
    /// Retrieve the column as a date/time value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>DateTime</returns>
    public override DateTime GetDateTime(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetDateTime(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.DateTime);
        return _activeStatement._sql.GetDateTime(_activeStatement, i);
    }

    /// <summary>
    /// Retrieve the column as a decimal value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>decimal</returns>
    public override decimal GetDecimal(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetDecimal(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Decimal);
        return Decimal.Parse(_activeStatement._sql.GetText(_activeStatement, i), NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// Returns the column as a double
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>double</returns>
    public override double GetDouble(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetDouble(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Double);
        return _activeStatement._sql.GetDouble(_activeStatement, i);
    }

    /// <summary>
    /// Returns the .NET type of a given column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Type</returns>
    public override Type GetFieldType(int i)
    {
        CheckDisposed();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetFieldType(i - PrivateVisibleFieldCount);

        return SQLiteConvert.SQLiteTypeToType(GetSQLiteType(_flags, i));
    }

    /// <summary>
    /// Returns a column as a float value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>float</returns>
    public override float GetFloat(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetFloat(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Single);
        return Convert.ToSingle(_activeStatement._sql.GetDouble(_activeStatement, i));
    }

    /// <summary>
    /// Returns the column as a Guid
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Guid</returns>
    public override Guid GetGuid(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetGuid(i - PrivateVisibleFieldCount);

        TypeAffinity affinity = VerifyType(i, DbType.Guid);
        if (affinity == TypeAffinity.Blob)
        {
            byte[] buffer = new byte[16];
            _activeStatement._sql.GetBytes(_activeStatement, i, 0, buffer, 0, 16);
            return new Guid(buffer);
        }
        else
            return new Guid(_activeStatement._sql.GetText(_activeStatement, i));
    }

    /// <summary>
    /// Returns the column as a short
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Int16</returns>
    public override Int16 GetInt16(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetInt16(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Int16);
        return Convert.ToInt16(_activeStatement._sql.GetInt32(_activeStatement, i));
    }

    /// <summary>
    /// Retrieves the column as an int
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Int32</returns>
    public override Int32 GetInt32(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetInt32(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Int32);
        return _activeStatement._sql.GetInt32(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the column as a long
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>Int64</returns>
    public override Int64 GetInt64(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetInt64(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.Int64);
        return _activeStatement._sql.GetInt64(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the name of the column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>string</returns>
    public override string GetName(int i)
    {
        CheckDisposed();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetName(i - PrivateVisibleFieldCount);

        return _activeStatement._sql.ColumnName(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the i of a column, given its name
    /// </summary>
    /// <param name="name">The name of the column to retrieve</param>
    /// <returns>The int i of the column</returns>
    public override int GetOrdinal(string name)
    {
      CheckDisposed();
      VerifyForGet();

      if (_throwOnDisposed) SQLiteCommand.Check(_command);

      //
      // NOTE: First, check if the column name cache has been initialized yet.
      //       If not, do it now.
      //
      if (_fieldIndexes == null)
................................................................................
      if (!_fieldIndexes.TryGetValue(name, out r))
      {
          r = _activeStatement._sql.ColumnIndex(_activeStatement, name);

          if (r == -1 && _keyInfo != null)
          {
              r = _keyInfo.GetOrdinal(name);
              if (r > -1) r += PrivateVisibleFieldCount;
          }

          _fieldIndexes.Add(name, r);
      }

      return r;
    }
................................................................................
    /// <summary>
    /// Retrieves the column as a string
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>string</returns>
    public override string GetString(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetString(i - PrivateVisibleFieldCount);

        VerifyType(i, DbType.String);
        return _activeStatement._sql.GetText(_activeStatement, i);
    }

    /// <summary>
    /// Retrieves the column as an object corresponding to the underlying datatype of the column
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>object</returns>
    public override object GetValue(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.GetValue(i - PrivateVisibleFieldCount);

        SQLiteType typ = GetSQLiteType(_flags, i);

        if (((_flags & SQLiteConnectionFlags.DetectTextAffinity) == SQLiteConnectionFlags.DetectTextAffinity) &&
            ((typ == null) || (typ.Affinity == TypeAffinity.Text)))
        {
            typ = GetSQLiteType(
                typ, _activeStatement._sql.GetText(_activeStatement, i));
        }
        else if (((_flags & SQLiteConnectionFlags.DetectStringType) == SQLiteConnectionFlags.DetectStringType) &&
            ((typ == null) || SQLiteConvert.IsStringDbType(typ.Type)))
        {
            typ = GetSQLiteType(
                typ, _activeStatement._sql.GetText(_activeStatement, i));
        }

        return _activeStatement._sql.GetValue(_activeStatement, _flags, i, typ);
    }

    /// <summary>
    /// Retreives the values of multiple columns, up to the size of the supplied array
    /// </summary>
    /// <param name="values">The array to fill with values from the columns in the current resultset</param>
    /// <returns>The number of columns retrieved</returns>
................................................................................
    public NameValueCollection GetValues()
    {
        CheckDisposed();

        if ((_activeStatement == null) || (_activeStatement._sql == null))
            throw new InvalidOperationException();

        int nMax = PrivateVisibleFieldCount;
        NameValueCollection result = new NameValueCollection(nMax);

        for (int n = 0; n < nMax; n++)
        {
            string name = _activeStatement._sql.ColumnName(_activeStatement, n);
            string value = _activeStatement._sql.GetText(_activeStatement, n);

................................................................................
    /// <summary>
    /// Returns True if the specified column is null
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>True or False</returns>
    public override bool IsDBNull(int i)
    {
        CheckDisposed();
        VerifyForGet();

        if (i >= PrivateVisibleFieldCount && _keyInfo != null)
            return _keyInfo.IsDBNull(i - PrivateVisibleFieldCount);

        return _activeStatement._sql.IsNull(_activeStatement, i);
    }

    /// <summary>
    /// Moves to the next resultset in multiple row-returning SQL command.
    /// </summary>
    /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns>
    public override bool NextResult()
................................................................................
            _readingState = 1; // This command returned columns but no rows, so return true, but HasRows = false and Read() returns false
          }
        }

        // Ahh, we found a row-returning resultset eligible to be returned!
        _activeStatement = stmt;
        _fieldCount = fieldCount;
        _fieldIndexes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
        _fieldTypeArray = new SQLiteType[PrivateVisibleFieldCount];

        if ((_commandBehavior & CommandBehavior.KeyInfo) != 0)
          LoadKeyInfo();

        return true;
      }
    }
................................................................................
    /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
    /// </summary>
    /// <param name="flags">The flags associated with the parent connection object.</param>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>A SQLiteType structure</returns>
    private SQLiteType GetSQLiteType(SQLiteConnectionFlags flags, int i)
    {
        SQLiteType typ = _fieldTypeArray[i];


        if (typ == null)

        {
            // Initialize this column's field type instance
            typ = _fieldTypeArray[i] = new SQLiteType();
        }


        // If not initialized, then fetch the declared column datatype and attempt to convert it
        // to a known DbType.
        if (typ.Affinity == TypeAffinity.Uninitialized)
        {
            typ.Type = SQLiteConvert.TypeNameToDbType(
                GetConnection(this), _activeStatement._sql.ColumnType(
                _activeStatement, i, out typ.Affinity), flags);
        }
        else
        {
            typ.Affinity = _activeStatement._sql.ColumnAffinity(
                _activeStatement, i);
        }

        return typ;
    }

    /// <summary>
    /// Reads the next row from the resultset
    /// </summary>
    /// <returns>True if a new row was successfully loaded and is ready for processing</returns>
    public override bool Read()

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

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /// </summary>
  public sealed class SQLiteTransaction : DbTransaction
  {
    /// <summary>
    /// The connection to which this transaction is bound
    /// </summary>
    internal SQLiteConnection _cnn;
    internal long _version; // Matches the version of the connection
    private IsolationLevel _level;

    /// <summary>
    /// Constructs the transaction object, binding it to the supplied connection
    /// </summary>
    /// <param name="connection">The connection to open a transaction on</param>
    /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /// </summary>
  public sealed class SQLiteTransaction : DbTransaction
  {
    /// <summary>
    /// The connection to which this transaction is bound
    /// </summary>
    internal SQLiteConnection _cnn;
    internal int _version; // Matches the version of the connection
    private IsolationLevel _level;

    /// <summary>
    /// Constructs the transaction object, binding it to the supplied connection
    /// </summary>
    /// <param name="connection">The connection to open a transaction on</param>
    /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>

Changes to readme.htm.

210
211
212
213
214
215
216

217
218
219
220
221
222
223
224

<p>
    <b>1.0.95.0 - November XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.8.7</a>.</li>
    <li>Make sure SQL statements generated for DbUpdateCommandTree objects are properly delimited.</li>

    <li>In the SQLiteDataReader.VerifyType method, remove duplicate &quot;if&quot; statement for the DbType.SByte value and move the remaining &quot;if&quot; to the Int64 affinity.  Fix for [c5cc2fb334].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.94.0 - September 9, 2014</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_8_6.html">SQLite 3.8.6</a>.</li>
    <li>Updated to <a href="http://www.nuget.org/packages/EntityFramework/6.1.1">Entity Framework 6.1.1</a>.</li>







>
|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

<p>
    <b>1.0.95.0 - November XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.8.7</a>.</li>
    <li>Make sure SQL statements generated for DbUpdateCommandTree objects are properly delimited.</li>
    <li>Various minor performance enhancements to the SQLiteDataReader class. Pursuant to [e122d26e70].</li>
    <li>In the SQLiteDataReader.VerifyType method, remove duplicate &quot;if&quot; statement for the DbType.SByte value and move the remaining &quot;if&quot; to the Int64 affinity. Fix for [c5cc2fb334].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.94.0 - September 9, 2014</b>
</p>
<ul>
    <li>Updated to <a href="http://www.sqlite.org/releaselog/3_8_6.html">SQLite 3.8.6</a>.</li>
    <li>Updated to <a href="http://www.nuget.org/packages/EntityFramework/6.1.1">Entity Framework 6.1.1</a>.</li>

Changes to www/news.wiki.

4
5
6
7
8
9
10

11
12
13
14
15
16
17

<p>
    <b>1.0.95.0 - November XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/src/info/trunk|SQLite 3.8.7].</li>
    <li>Make sure SQL statements generated for DbUpdateCommandTree objects are properly delimited.</li>

    <li>In the SQLiteDataReader.VerifyType method, remove duplicate &quot;if&quot; statement for the DbType.SByte value and move the remaining &quot;if&quot; to the Int64 affinity.  Fix for [c5cc2fb334].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.94.0 - September 9, 2014</b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_8_6.html|SQLite 3.8.6].</li>







>







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

<p>
    <b>1.0.95.0 - November XX, 2014 <font color="red">(release scheduled)</font></b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/src/info/trunk|SQLite 3.8.7].</li>
    <li>Make sure SQL statements generated for DbUpdateCommandTree objects are properly delimited.</li>
    <li>Various minor performance enhancements to the SQLiteDataReader class. Pursuant to [e122d26e70].</li>
    <li>In the SQLiteDataReader.VerifyType method, remove duplicate &quot;if&quot; statement for the DbType.SByte value and move the remaining &quot;if&quot; to the Int64 affinity.  Fix for [c5cc2fb334].&nbsp;<b>** Potentially Incompatible Change **</b></li>
</ul>
<p>
    <b>1.0.94.0 - September 9, 2014</b>
</p>
<ul>
    <li>Updated to [http://www.sqlite.org/releaselog/3_8_6.html|SQLite 3.8.6].</li>