System.Data.SQLite
Check-in [5b282efc5f]
Not logged in

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

Overview
Comment:Fix a FormatException in the SQLiteConnection.Schema_Indexes method when the default type has been changed to String. Pursuant to [3c00ec5b52].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5b282efc5fd0118c9b78c50d80d560dbff792a22
User & Date: mistachkin 2014-05-15 23:44:22
References
2014-05-15
23:44 Ticket [3c00ec5b52] Columns without defined type are not identified as text status still Pending with 4 other changes artifact: f934850d88 user: mistachkin
Context
2014-05-20
23:38
Fix bug in documentation generator automation that prevented some internal documentation links from working. check-in: 531ddfa82a user: mistachkin tags: trunk
2014-05-18
06:57
Add experimental MapTextToAffinity connection flag to permit automatic attempts to map textual column values onto values with an appropriate type affinity. check-in: f5dd5dcfde user: mistachkin tags: tkt-3c00ec5b52
2014-05-17
01:33
For the System.Data.SQLite.EF6 assembly, rename the IsStoreGenerated metadata column in the SSDL to IsServerGenerated. Pursuant to [3c00ec5b52]. check-in: 7a7ec7f341 user: mistachkin tags: mistake
2014-05-15
23:44
Fix a FormatException in the SQLiteConnection.Schema_Indexes method when the default type has been changed to String. Pursuant to [3c00ec5b52]. check-in: 5b282efc5f user: mistachkin tags: trunk
18:58
Fix a usage inconsistency where Convert.ToBoolean was being called instead of SQLiteConvert.ToBoolean. check-in: 4ea6f54d61 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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

3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
                  {
                    row = tbl.NewRow();

                    row["TABLE_CATALOG"] = strCatalog;
                    row["TABLE_NAME"] = rdTables.GetString(2);
                    row["INDEX_CATALOG"] = strCatalog;
                    row["INDEX_NAME"] = rd.GetString(1);
                    row["UNIQUE"] = rd.GetBoolean(2);
                    row["PRIMARY_KEY"] = false;

                    // get the index definition
                    using (SQLiteCommand cmdIndexes = new SQLiteCommand(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM [{0}].[{2}] WHERE [type] LIKE 'index' AND [name] LIKE '{1}'", strCatalog, rd.GetString(1).Replace("'", "''"), master), this))
                    using (SQLiteDataReader rdIndexes = cmdIndexes.ExecuteReader())
                    {
                      while (rdIndexes.Read())







|







3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
                  {
                    row = tbl.NewRow();

                    row["TABLE_CATALOG"] = strCatalog;
                    row["TABLE_NAME"] = rdTables.GetString(2);
                    row["INDEX_CATALOG"] = strCatalog;
                    row["INDEX_NAME"] = rd.GetString(1);
                    row["UNIQUE"] = SQLiteConvert.ToBoolean(rd.GetValue(2), CultureInfo.InvariantCulture, false);
                    row["PRIMARY_KEY"] = false;

                    // get the index definition
                    using (SQLiteCommand cmdIndexes = new SQLiteCommand(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM [{0}].[{2}] WHERE [type] LIKE 'index' AND [name] LIKE '{1}'", strCatalog, rd.GetString(1).Replace("'", "''"), master), this))
                    using (SQLiteDataReader rdIndexes = cmdIndexes.ExecuteReader())
                    {
                      while (rdIndexes.Read())

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

776
777
778
779
780
781
782










































































783
784
785
786
787
788
789
        IConvertible convertible = obj as IConvertible;

        if (convertible != null)
            return convertible.ToString(provider);

        return obj.ToString(); /* not IConvertible */
    }











































































    /// <summary>
    /// Convert a value to true or false.
    /// </summary>
    /// <param name="source">A string or number representing true or false</param>
    /// <returns></returns>
    public static bool ToBoolean(object source)







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







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
        IConvertible convertible = obj as IConvertible;

        if (convertible != null)
            return convertible.ToString(provider);

        return obj.ToString(); /* not IConvertible */
    }

    /// <summary>
    /// Attempts to convert an arbitrary object to the Boolean data type.
    /// Null object values are converted to false.  Throws an exception
    /// upon failure.
    /// </summary>
    /// <param name="obj">
    /// The object value to convert.
    /// </param>
    /// <param name="provider">
    /// The format provider to use.
    /// </param>
    /// <param name="viaFramework">
    /// If non-zero, a string value will be converted using the
    /// <see cref="Convert.ToBoolean(Object, IFormatProvider)" />
    /// method; otherwise, the <see cref="ToBoolean(String)" />
    /// method will be used.
    /// </param>
    /// <returns>
    /// The converted boolean value.
    /// </returns>
    internal static bool ToBoolean(
        object obj,
        IFormatProvider provider,
        bool viaFramework
        )
    {
        if (obj == null)
            return false;

        TypeCode typeCode = Type.GetTypeCode(obj.GetType());

        switch (typeCode)
        {
            case TypeCode.Empty:
            case TypeCode.DBNull:
                return false;
            case TypeCode.Boolean:
                return (bool)obj;
            case TypeCode.Char:
                return ((char)obj) != (char)0 ? true : false;
            case TypeCode.SByte:
                return ((sbyte)obj) != (sbyte)0 ? true : false;
            case TypeCode.Byte:
                return ((byte)obj) != (byte)0 ? true : false;
            case TypeCode.Int16:
                return ((short)obj) != (short)0 ? true : false;
            case TypeCode.UInt16:
                return ((ushort)obj) != (ushort)0 ? true : false;
            case TypeCode.Int32:
                return ((int)obj) != (int)0 ? true : false;
            case TypeCode.UInt32:
                return ((uint)obj) != (uint)0 ? true : false;
            case TypeCode.Int64:
                return ((long)obj) != (long)0 ? true : false;
            case TypeCode.UInt64:
                return ((ulong)obj) != (ulong)0 ? true : false;
            case TypeCode.Single:
                return ((float)obj) != (float)0.0 ? true : false;
            case TypeCode.Double:
                return ((double)obj) != (double)0.0 ? true : false;
            case TypeCode.Decimal:
                return ((decimal)obj) != Decimal.Zero ? true : false;
            case TypeCode.String:
                return viaFramework ?
                    Convert.ToBoolean(obj, provider) :
                    ToBoolean(ToStringWithProvider(obj, provider));
            default:
                throw new SQLiteException(String.Format(
                    CultureInfo.CurrentCulture,
                    "Cannot convert type {0} to boolean",
                    typeCode));
        }
    }

    /// <summary>
    /// Convert a value to true or false.
    /// </summary>
    /// <param name="source">A string or number representing true or false</param>
    /// <returns></returns>
    public static bool ToBoolean(object source)

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

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
      int x = _paramNames.Length;
      for (int n = 0; n < x; n++)
      {
        BindParameter(n + 1, _paramValues[n]);
      }
    }

    /// <summary>
    /// Attempts to convert an arbitrary object to the Boolean data type.
    /// Null object values are converted to false.  Throws a SQLiteException
    /// upon failure.
    /// </summary>
    /// <param name="obj">The object value to convert.</param>
    /// <param name="provider">The format provider to use.</param>
    /// <returns>The converted boolean value.</returns>
    private static bool ToBoolean(object obj, IFormatProvider provider)
    {
        if (obj == null)
            return false;

        TypeCode typeCode = Type.GetTypeCode(obj.GetType());

        switch (typeCode)
        {
            case TypeCode.Empty:
            case TypeCode.DBNull:
                return false;
            case TypeCode.Boolean:
                return (bool)obj;
            case TypeCode.Char:
                return ((char)obj) != (char)0 ? true : false;
            case TypeCode.SByte:
                return ((sbyte)obj) != (sbyte)0 ? true : false;
            case TypeCode.Byte:
                return ((byte)obj) != (byte)0 ? true : false;
            case TypeCode.Int16:
                return ((short)obj) != (short)0 ? true : false;
            case TypeCode.UInt16:
                return ((ushort)obj) != (ushort)0 ? true : false;
            case TypeCode.Int32:
                return ((int)obj) != (int)0 ? true : false;
            case TypeCode.UInt32:
                return ((uint)obj) != (uint)0 ? true : false;
            case TypeCode.Int64:
                return ((long)obj) != (long)0 ? true : false;
            case TypeCode.UInt64:
                return ((ulong)obj) != (ulong)0 ? true : false;
            case TypeCode.Single:
                return ((float)obj) != (float)0.0 ? true : false;
            case TypeCode.Double:
                return ((double)obj) != (double)0.0 ? true : false;
            case TypeCode.Decimal:
                return ((decimal)obj) != Decimal.Zero ? true : false;
            case TypeCode.String:
                return Convert.ToBoolean(obj, provider);
            default:
                throw new SQLiteException(String.Format(
                    CultureInfo.CurrentCulture,
                    "Cannot convert type {0} to boolean",
                    typeCode));
        }
    }

    /// <summary>
    /// Perform the bind operation for an individual parameter
    /// </summary>
    /// <param name="index">The index of the parameter to bind</param>
    /// <param name="param">The parameter we're binding</param>
    private void BindParameter(int index, SQLiteParameter param)
    {
................................................................................
          // NOTE: The old method (commented below) does not honor the selected date format
          //       for the connection.
          // _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, cultureInfo));
            _sql.Bind_DateTime(this, _flags, index, (obj is string) ?
              _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, cultureInfo));
          break;
        case DbType.Boolean:
          _sql.Bind_Int32(this, _flags, index, ToBoolean(obj, cultureInfo) ? 1 : 0);
          break;
        case DbType.SByte:
          _sql.Bind_Int32(this, _flags, index, Convert.ToSByte(obj, cultureInfo));
          break;
        case DbType.Int16:
          _sql.Bind_Int32(this, _flags, index, Convert.ToInt16(obj, cultureInfo));
          break;







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







 







|







225
226
227
228
229
230
231
























































232
233
234
235
236
237
238
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
      int x = _paramNames.Length;
      for (int n = 0; n < x; n++)
      {
        BindParameter(n + 1, _paramValues[n]);
      }
    }

























































    /// <summary>
    /// Perform the bind operation for an individual parameter
    /// </summary>
    /// <param name="index">The index of the parameter to bind</param>
    /// <param name="param">The parameter we're binding</param>
    private void BindParameter(int index, SQLiteParameter param)
    {
................................................................................
          // NOTE: The old method (commented below) does not honor the selected date format
          //       for the connection.
          // _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, cultureInfo));
            _sql.Bind_DateTime(this, _flags, index, (obj is string) ?
              _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, cultureInfo));
          break;
        case DbType.Boolean:
          _sql.Bind_Int32(this, _flags, index, SQLiteConvert.ToBoolean(obj, cultureInfo, true) ? 1 : 0);
          break;
        case DbType.SByte:
          _sql.Bind_Int32(this, _flags, index, Convert.ToSByte(obj, cultureInfo));
          break;
        case DbType.Int16:
          _sql.Bind_Int32(this, _flags, index, Convert.ToInt16(obj, cultureInfo));
          break;

Changes to Tests/tkt-3c00ec5b52.eagle.

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
166
167
168
169
170
171
172



































173
174
175
176
177
178
179
180
181
182
      uplevel 1 [list unset -nocomplain env($name)]
    }
  }
}

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

runTest {test tkt-3c00ec5b52-1.1 {per-connection default types} -setup {
  setupDb [set fileName tkt-3c00ec5b52-1.1.db] "" "" "" UseConnectionTypes \
      "DefaultDbType=String;DefaultTypeName=TEXT;"
} -body {
  set connection [getDbConnection]
  set result [list]

  lappend result [object invoke -flags +NonPublic \
................................................................................
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{String TEXT}}

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

runTest {test tkt-3c00ec5b52-1.2 {per-connection default types} -setup {
  setupDb [set fileName tkt-3c00ec5b52-1.2.db] "" "" "" UseConnectionTypes
} -body {
  set connection [getDbConnection]
  set result [list]

  lappend result [object invoke -flags +NonPublic \
      System.Data.SQLite.SQLiteConvert TypeNameToDbType $connection "" None]
................................................................................
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{Object {}}}

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

runTest {test tkt-3c00ec5b52-1.3 {per-connection default types} -setup {
  setupDb [set fileName tkt-3c00ec5b52-1.3.db]
} -body {
  set connection [getDbConnection]
  set result [list]

  lappend result [object invoke -flags +NonPublic \
      System.Data.SQLite.SQLiteConvert TypeNameToDbType $connection "" None]
................................................................................
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{Object {}}}

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

runTest {test tkt-3c00ec5b52-1.4 {per-connection default types} -setup {
  saveSQLiteConvertEnvironment

  set env(Use_SQLiteConvert_DefaultDbType) String
  set env(Use_SQLiteConvert_DefaultTypeName) TEXT

  setupDb [set fileName tkt-3c00ec5b52-1.4.db]
} -body {
................................................................................
  cleanupDb $fileName
  restoreSQLiteConvertEnvironment

  unset -nocomplain db fileName savedEnv
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{String TEXT}}




































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

rename restoreSQLiteConvertEnvironment ""
rename saveSQLiteConvertEnvironment ""

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

runSQLiteTestEpilogue
runTestEpilogue







|







 







|







 







|







 







|







 







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










54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
      uplevel 1 [list unset -nocomplain env($name)]
    }
  }
}

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

runTest {test tkt-3c00ec5b52-1.1 {default types, via connection} -setup {
  setupDb [set fileName tkt-3c00ec5b52-1.1.db] "" "" "" UseConnectionTypes \
      "DefaultDbType=String;DefaultTypeName=TEXT;"
} -body {
  set connection [getDbConnection]
  set result [list]

  lappend result [object invoke -flags +NonPublic \
................................................................................
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{String TEXT}}

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

runTest {test tkt-3c00ec5b52-1.2 {fallback default types w/flag} -setup {
  setupDb [set fileName tkt-3c00ec5b52-1.2.db] "" "" "" UseConnectionTypes
} -body {
  set connection [getDbConnection]
  set result [list]

  lappend result [object invoke -flags +NonPublic \
      System.Data.SQLite.SQLiteConvert TypeNameToDbType $connection "" None]
................................................................................
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{Object {}}}

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

runTest {test tkt-3c00ec5b52-1.3 {fallback default types w/o flag} -setup {
  setupDb [set fileName tkt-3c00ec5b52-1.3.db]
} -body {
  set connection [getDbConnection]
  set result [list]

  lappend result [object invoke -flags +NonPublic \
      System.Data.SQLite.SQLiteConvert TypeNameToDbType $connection "" None]
................................................................................
  unset -nocomplain db fileName
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{Object {}}}

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

runTest {test tkt-3c00ec5b52-1.4 {default types, via environment} -setup {
  saveSQLiteConvertEnvironment

  set env(Use_SQLiteConvert_DefaultDbType) String
  set env(Use_SQLiteConvert_DefaultTypeName) TEXT

  setupDb [set fileName tkt-3c00ec5b52-1.4.db]
} -body {
................................................................................
  cleanupDb $fileName
  restoreSQLiteConvertEnvironment

  unset -nocomplain db fileName savedEnv
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{String TEXT}}

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

runTest {test tkt-3c00ec5b52-1.5 {default types, with unique index} -setup {
  saveSQLiteConvertEnvironment

  set env(Use_SQLiteConvert_DefaultDbType) String
  set env(Use_SQLiteConvert_DefaultTypeName) TEXT

  setupDb [set fileName tkt-3c00ec5b52-1.5.db]
} -body {
  sql execute $db "CREATE TABLE t1(x UNIQUE);"

  set connection [getDbConnection]
  set dataTable [$connection -alias GetSchema INDEXES]
  set results [list]

  object foreach -alias dataRow [set dataRows [$dataTable -alias Rows]] {
    lappend results [list [$dataRow Item TABLE_NAME] \
        [$dataRow Item INDEX_NAME] [$dataRow Item UNIQUE]]
  }

  set results
} -cleanup {
  freeDbConnection

  unset -nocomplain results dataRow dataRows dataTable connection

  cleanupDb $fileName
  restoreSQLiteConvertEnvironment

  unset -nocomplain db fileName savedEnv
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
{{t1 sqlite_autoindex_t1_1 True}}}

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

rename restoreSQLiteConvertEnvironment ""
rename saveSQLiteConvertEnvironment ""

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

runSQLiteTestEpilogue
runTestEpilogue