System.Data.SQLite
Check-in [910381a7e3]
Not logged in

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

Overview
Comment:Improve SQLiteDataReader performance slightly by caching the connection flags. Add RefreshFlags method to the SQLiteDataReader class to forcibly refresh its connection flags.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 910381a7e357331082a906db6e2d017fb80dcb3b
User & Date: mistachkin 2014-07-19 00:17:05
Context
2014-07-19
00:22
Fix line endings. check-in: 413872c668 user: mistachkin tags: trunk
00:17
Improve SQLiteDataReader performance slightly by caching the connection flags. Add RefreshFlags method to the SQLiteDataReader class to forcibly refresh its connection flags. check-in: 910381a7e3 user: mistachkin tags: trunk
00:14
Bump all versions to 1.0.94.0. check-in: f56f7104f7 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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

19
20
21
22
23
24
25




26
27
28
29
30
31
32
...
104
105
106
107
108
109
110


111
112
113
114
115
116
117
...
311
312
313
314
315
316
317











318
319
320
321
322
323
324
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
...
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
....
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
....
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
....
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
  /// </summary>
  public sealed class SQLiteDataReader : DbDataReader
  {
    /// <summary>
    /// Underlying command this reader is attached to
    /// </summary>
    private SQLiteCommand _command;




    /// <summary>
    /// Index of the current statement in the command being processed
    /// </summary>
    private int _activeStatementIndex;
    /// <summary>
    /// Current statement being Read()
    /// </summary>
................................................................................
      _command = cmd;
      _version = _command.Connection._version;
      _baseSchemaName = _command.Connection._baseSchemaName;

      _commandBehavior = behave;
      _activeStatementIndex = -1;
      _rowsAffected = -1;



      SQLiteConnection.OnChanged(GetConnection(this),
          new ConnectionEventArgs(SQLiteConnectionEventType.NewDataReader,
          null, null, _command, this, null, null, new object[] { behave }));

      if (_command != null)
          NextResult();
................................................................................

        if (_keyInfo == null)
          return _fieldCount;

        return _fieldCount + _keyInfo.Count;
      }
    }












    /// <summary>
    /// Returns the number of rows seen so far in the current result set.
    /// </summary>
    public int StepCount
    {
        get
................................................................................
    /// <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(SQLiteCommand.GetFlags(_command), 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;
................................................................................
    public override string GetDataTypeName(int i)
    {
      CheckDisposed();

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

      SQLiteType typ = GetSQLiteType(SQLiteCommand.GetFlags(_command), 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>
................................................................................
    public override Type GetFieldType(int i)
    {
      CheckDisposed();

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

      return SQLiteConvert.SQLiteTypeToType(GetSQLiteType(SQLiteCommand.GetFlags(_command), i));
    }

    /// <summary>
    /// Returns a column as a float value
    /// </summary>
    /// <param name="i">The index of the column to retrieve</param>
    /// <returns>float</returns>
................................................................................
      tbl.Columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(Boolean));
      tbl.Columns.Add(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(Type));
      tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object));
      tbl.Columns.Add("DataTypeName", typeof(string));
      tbl.Columns.Add("CollationType", typeof(string));
      tbl.BeginLoadData();

      SQLiteConnectionFlags flags = SQLiteCommand.GetFlags(_command);

      for (int n = 0; n < _fieldCount; n++)
      {
        SQLiteType sqlType = GetSQLiteType(flags, n);

        row = tbl.NewRow();

        DbType typ = sqlType.Type;

        // Default settings for the column
        row[SchemaTableColumn.ColumnName] = GetName(n);
................................................................................
    {
      CheckDisposed();
      CheckValidRow();

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

      SQLiteConnectionFlags flags = SQLiteCommand.GetFlags(_command);
      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>
................................................................................
        // NOTE: If the "sticky" flag has been set, use the new behavior,
        //       which returns non-zero if there were ever any rows in
        //       the associated result sets.  Generally, this flag is only
        //       useful when it is necessary to retain compatibility with
        //       other ADO.NET providers that use these same semantics for
        //       the HasRows property.
        //
        if ((GetFlags(this) & SQLiteConnectionFlags.StickyHasRows) == SQLiteConnectionFlags.StickyHasRows)
          return ((_readingState != 1) || (_stepCount > 0));

        //
        // NOTE: This is the default behavior.  It returns non-zero only if
        //       more rows are available (i.e. a call to the Read method is
        //       expected to succeed).  Prior to the introduction of the
        //       "sticky" flag, this is how this property has always worked.
................................................................................
        {
            // do nothing.
        }

        return null;
    }

    /// <summary>
    /// This method attempts to query the flags associated with the database
    /// connection in use.  If the database connection is disposed, the default
    /// flags will be returned.
    /// </summary>
    /// <param name="dataReader">
    /// The data reader containing the databse connection to query the flags from.
    /// </param>
    /// <returns>
    /// The connection flags value.
    /// </returns>
    internal static SQLiteConnectionFlags GetFlags(
        SQLiteDataReader dataReader
        )
    {
        try
        {
            if (dataReader != null)
            {
                SQLiteCommand command = dataReader._command;

                if (command != null)
                    return SQLiteCommand.GetFlags(command);
            }
        }
        catch (ObjectDisposedException)
        {
            // do nothing.
        }

        return SQLiteConnectionFlags.Default;
    }

    /// <summary>
    /// Retrieves the SQLiteType for a given column and row value.
    /// </summary>
    /// <param name="oldType">
    /// The original SQLiteType structure, based only on the column.
    /// </param>
    /// <param name="text">







>
>
>
>







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







|







 







<
<


|







 







<
|
|
|





|






|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
...
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
...
933
934
935
936
937
938
939


940
941
942
943
944
945
946
947
948
949
....
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
1173
....
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
....
1402
1403
1404
1405
1406
1407
1408

































1409
1410
1411
1412
1413
1414
1415
  /// </summary>
  public sealed class SQLiteDataReader : DbDataReader
  {
    /// <summary>
    /// Underlying command this reader is attached to
    /// </summary>
    private SQLiteCommand _command;
    /// <summary>
    /// The flags pertaining to the associated connection (via the command).
    /// </summary>
    private SQLiteConnectionFlags _flags;
    /// <summary>
    /// Index of the current statement in the command being processed
    /// </summary>
    private int _activeStatementIndex;
    /// <summary>
    /// Current statement being Read()
    /// </summary>
................................................................................
      _command = cmd;
      _version = _command.Connection._version;
      _baseSchemaName = _command.Connection._baseSchemaName;

      _commandBehavior = behave;
      _activeStatementIndex = -1;
      _rowsAffected = -1;

      RefreshFlags();

      SQLiteConnection.OnChanged(GetConnection(this),
          new ConnectionEventArgs(SQLiteConnectionEventType.NewDataReader,
          null, null, _command, this, null, null, new object[] { behave }));

      if (_command != null)
          NextResult();
................................................................................

        if (_keyInfo == null)
          return _fieldCount;

        return _fieldCount + _keyInfo.Count;
      }
    }

    /// <summary>
    /// Forces the connection flags cached by this data reader to be refreshed
    /// from the underlying connection.
    /// </summary>
    public void RefreshFlags()
    {
        CheckDisposed();

        _flags = SQLiteCommand.GetFlags(_command);
    }

    /// <summary>
    /// Returns the number of rows seen so far in the current result set.
    /// </summary>
    public int StepCount
    {
        get
................................................................................
    /// <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;
................................................................................
    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>
................................................................................
    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>
................................................................................
      tbl.Columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(Boolean));
      tbl.Columns.Add(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(Type));
      tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object));
      tbl.Columns.Add("DataTypeName", typeof(string));
      tbl.Columns.Add("CollationType", typeof(string));
      tbl.BeginLoadData();



      for (int n = 0; n < _fieldCount; n++)
      {
        SQLiteType sqlType = GetSQLiteType(_flags, n);

        row = tbl.NewRow();

        DbType typ = sqlType.Type;

        // Default settings for the column
        row[SchemaTableColumn.ColumnName] = GetName(n);
................................................................................
    {
      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>
................................................................................
        // NOTE: If the "sticky" flag has been set, use the new behavior,
        //       which returns non-zero if there were ever any rows in
        //       the associated result sets.  Generally, this flag is only
        //       useful when it is necessary to retain compatibility with
        //       other ADO.NET providers that use these same semantics for
        //       the HasRows property.
        //
        if ((_flags & SQLiteConnectionFlags.StickyHasRows) == SQLiteConnectionFlags.StickyHasRows)
          return ((_readingState != 1) || (_stepCount > 0));

        //
        // NOTE: This is the default behavior.  It returns non-zero only if
        //       more rows are available (i.e. a call to the Read method is
        //       expected to succeed).  Prior to the introduction of the
        //       "sticky" flag, this is how this property has always worked.
................................................................................
        {
            // do nothing.
        }

        return null;
    }


































    /// <summary>
    /// Retrieves the SQLiteType for a given column and row value.
    /// </summary>
    /// <param name="oldType">
    /// The original SQLiteType structure, based only on the column.
    /// </param>
    /// <param name="text">