System.Data.SQLite
Check-in [1ab2413f5d]
Not logged in

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

Overview
Comment:Revise how statement parameter binding handles blittable types. Also, allow binding to unsigned integer and long values that do not fit into their associated signed types.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1ab2413f5d760e1c79ab0ceb4e1422a80d2cded9
User & Date: mistachkin 2011-11-29 07:20:15
Context
2011-11-30
00:34
Recognize the TIMESTAMP column data type as a DateTime object. Fix for ticket [bb4b04d457]. check-in: e96f0d17a5 user: mistachkin tags: trunk
2011-11-29
07:20
Revise how statement parameter binding handles blittable types. Also, allow binding to unsigned integer and long values that do not fit into their associated signed types. check-in: 1ab2413f5d user: mistachkin tags: trunk
2011-11-28
09:05
Update downloads page for 1.0.77.0 release. check-in: f643120ddb user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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

439
440
441
442
443
444
445






446
447
448
449
450
451
452
453
454
455










456
457
458
459
460
461
462
    }

    internal override void Bind_Int32(SQLiteStatement stmt, int index, int value)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_int(stmt._sqlite_stmt, index, value);
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }







    internal override void Bind_Int64(SQLiteStatement stmt, int index, long value)
    {
#if !PLATFORM_COMPACTFRAMEWORK
      int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
      int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }











    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
    {
      byte[] b = ToUTF8(value);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }







>
>
>
>
>
>










>
>
>
>
>
>
>
>
>
>







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
471
472
473
474
475
476
477
478
    }

    internal override void Bind_Int32(SQLiteStatement stmt, int index, int value)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_int(stmt._sqlite_stmt, index, value);
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_UInt32(SQLiteStatement stmt, int index, uint value)
    {
      int n = UnsafeNativeMethods.sqlite3_bind_uint(stmt._sqlite_stmt, index, value);
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_Int64(SQLiteStatement stmt, int index, long value)
    {
#if !PLATFORM_COMPACTFRAMEWORK
      int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
#else
      int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
#endif
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_UInt64(SQLiteStatement stmt, int index, ulong value)
    {
#if !PLATFORM_COMPACTFRAMEWORK
      int n = UnsafeNativeMethods.sqlite3_bind_uint64(stmt._sqlite_stmt, index, value);
#else
      int n = UnsafeNativeMethods.sqlite3_bind_uint64_interop(stmt._sqlite_stmt, index, ref value);
#endif
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
    {
      byte[] b = ToUTF8(value);
      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
    }

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

111
112
113
114
115
116
117

118

119
120
121
122
123
124
125
    /// <param name="stmt">The statement to reset</param>
    /// <returns>Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock</returns>
    internal abstract int Reset(SQLiteStatement stmt);
    internal abstract void Cancel();

    internal abstract void Bind_Double(SQLiteStatement stmt, int index, double value);
    internal abstract void Bind_Int32(SQLiteStatement stmt, int index, Int32 value);

    internal abstract void Bind_Int64(SQLiteStatement stmt, int index, Int64 value);

    internal abstract void Bind_Text(SQLiteStatement stmt, int index, string value);
    internal abstract void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData);
    internal abstract void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt);
    internal abstract void Bind_Null(SQLiteStatement stmt, int index);

    internal abstract int Bind_ParamCount(SQLiteStatement stmt);
    internal abstract string Bind_ParamName(SQLiteStatement stmt, int index);







>

>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
    /// <param name="stmt">The statement to reset</param>
    /// <returns>Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock</returns>
    internal abstract int Reset(SQLiteStatement stmt);
    internal abstract void Cancel();

    internal abstract void Bind_Double(SQLiteStatement stmt, int index, double value);
    internal abstract void Bind_Int32(SQLiteStatement stmt, int index, Int32 value);
    internal abstract void Bind_UInt32(SQLiteStatement stmt, int index, UInt32 value);
    internal abstract void Bind_Int64(SQLiteStatement stmt, int index, Int64 value);
    internal abstract void Bind_UInt64(SQLiteStatement stmt, int index, UInt64 value);
    internal abstract void Bind_Text(SQLiteStatement stmt, int index, string value);
    internal abstract void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData);
    internal abstract void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt);
    internal abstract void Bind_Null(SQLiteStatement stmt, int index);

    internal abstract int Bind_ParamCount(SQLiteStatement stmt);
    internal abstract string Bind_ParamName(SQLiteStatement stmt, int index);

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

145
146
147
148
149
150
151























































152
153
154
155
156
157
158
...
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

      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.CurrentCulture));
          _sql.Bind_DateTime(this, index, (obj is string) ?
              _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Int64:


        case DbType.UInt64:
          _sql.Bind_Int64(this, index, Convert.ToInt64(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Boolean:


        case DbType.Int16:


        case DbType.Int32:


        case DbType.UInt16:


        case DbType.UInt32:


        case DbType.SByte:


        case DbType.Byte:
          _sql.Bind_Int32(this, index, Convert.ToInt32(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Single:
        case DbType.Double:
        case DbType.Currency:
        //case DbType.Decimal: // Dont store decimal as double ... loses precision
          _sql.Bind_Double(this, index, Convert.ToDouble(obj, CultureInfo.CurrentCulture));
          break;







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







 







|
>
>
|
|

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







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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
...
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

      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((int)SQLiteErrorCode.Error,
                    String.Format("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.CurrentCulture));
          _sql.Bind_DateTime(this, index, (obj is string) ?
              _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Boolean:
          _sql.Bind_Int32(this, index, ToBoolean(obj, CultureInfo.CurrentCulture) ? 1 : 0);
          break;
        case DbType.SByte:
          _sql.Bind_Int32(this, index, Convert.ToSByte(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Int16:
          _sql.Bind_Int32(this, index, Convert.ToInt16(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Int32:
          _sql.Bind_Int32(this, index, Convert.ToInt32(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Int64:
          _sql.Bind_Int64(this, index, Convert.ToInt64(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Byte:
          _sql.Bind_UInt32(this, index, Convert.ToByte(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.UInt16:
          _sql.Bind_UInt32(this, index, Convert.ToUInt16(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.UInt32:
          _sql.Bind_UInt32(this, index, Convert.ToUInt32(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.UInt64:
          _sql.Bind_UInt64(this, index, Convert.ToUInt64(obj, CultureInfo.CurrentCulture));
          break;
        case DbType.Single:
        case DbType.Double:
        case DbType.Currency:
        //case DbType.Decimal: // Dont store decimal as double ... loses precision
          _sql.Bind_Double(this, index, Convert.ToDouble(obj, CultureInfo.CurrentCulture));
          break;

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

428
429
430
431
432
433
434











435
436
437
438
439
440
441












442
443
444
445
446
447
448
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_bind_int(IntPtr stmt, int index, int value);












#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
    internal static extern int sqlite3_bind_int64(IntPtr stmt, int index, long value);
#else
    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_bind_int64_interop(IntPtr stmt, int index, ref long value);
#endif













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







>
>
>
>
>
>
>
>
>
>
>







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







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
471
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_bind_int(IntPtr stmt, int index, int value);

    //
    // NOTE: This really just calls "sqlite3_bind_int"; however, it has the
    //       correct type signature for an unsigned (32-bit) integer.
    //
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, EntryPoint = "sqlite3_bind_int", CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL, EntryPoint = "sqlite3_bind_int")]
#endif
    internal static extern int sqlite3_bind_uint(IntPtr stmt, int index, uint value);

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
    internal static extern int sqlite3_bind_int64(IntPtr stmt, int index, long value);
#else
    [DllImport(SQLITE_DLL)]
    internal static extern int sqlite3_bind_int64_interop(IntPtr stmt, int index, ref long value);
#endif

    //
    // NOTE: This really just calls "sqlite3_bind_int64"; however, it has the
    //       correct type signature for an unsigned long (64-bit) integer.
    //
#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, EntryPoint = "sqlite3_bind_int64", CallingConvention = CallingConvention.Cdecl)]
    internal static extern int sqlite3_bind_uint64(IntPtr stmt, int index, ulong value);
#else
    [DllImport(SQLITE_DLL, EntryPoint = "sqlite3_bind_int64_interop")]
    internal static extern int sqlite3_bind_uint64_interop(IntPtr stmt, int index, ref ulong value);
#endif

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