System.Data.SQLite

Check-in [1820415db5]
Login

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

Overview
Comment:Work-in-progress on addressing forum post 76cb35b58d.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | pst-76cb35b58d
Files: files | file ages | folders
SHA1: 1820415db568e9f26b4dcd347c40abecc3dcb5ee
User & Date: mistachkin 2024-05-12 00:39:39.226
Context
2024-05-12
02:58
Further fixes and tests. check-in: 7dd11e276b user: mistachkin tags: pst-76cb35b58d
00:39
Work-in-progress on addressing forum post 76cb35b58d. check-in: 1820415db5 user: mistachkin tags: pst-76cb35b58d
2024-04-27
15:15
Update version history docs. check-in: 1764d76cee user: mistachkin tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to Setup/data/verify.lst.
842
843
844
845
846
847
848

849
850
851
852
853
854
855
  Tests/function.eagle
  Tests/installer.eagle
  Tests/linq.eagle
  Tests/memory.eagle
  Tests/pool.eagle
  Tests/progress.eagle
  Tests/pst-4db2934c2e.eagle

  Tests/pst-eeaefb84ec.eagle
  Tests/pst-f4e718891d.eagle
  Tests/session.eagle
  Tests/speed.eagle
  Tests/stress.eagle
  Tests/template/
  Tests/template/empty.eagle







>







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
  Tests/function.eagle
  Tests/installer.eagle
  Tests/linq.eagle
  Tests/memory.eagle
  Tests/pool.eagle
  Tests/progress.eagle
  Tests/pst-4db2934c2e.eagle
  Tests/pst-76cb35b58d.eagle
  Tests/pst-eeaefb84ec.eagle
  Tests/pst-f4e718891d.eagle
  Tests/session.eagle
  Tests/speed.eagle
  Tests/stress.eagle
  Tests/template/
  Tests/template/empty.eagle
Changes to System.Data.SQLite/SQLiteParameter.cs.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
  using System;
  using System.Data;
  using System.Data.Common;
  using System.ComponentModel;


  /// <summary>
  /// SQLite implementation of DbParameter.
  /// </summary>
  public sealed class SQLiteParameter : DbParameter, ICloneable
  {
    /// <summary>



|









>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
  using System;
  using System.Data;
  using System.Data.Common;
  using System.ComponentModel;
  using System.Globalization;

  /// <summary>
  /// SQLite implementation of DbParameter.
  /// </summary>
  public sealed class SQLiteParameter : DbParameter, ICloneable
  {
    /// <summary>
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    {
        _command = command;
    }

    /// <summary>
    /// Default constructor
    /// </summary>
    public SQLiteParameter() 
      : this(null, UnknownDbType, 0, null, DataRowVersion.Current)
    {
    }

    /// <summary>
    /// Constructs a named parameter given the specified parameter name
    /// </summary>







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    {
        _command = command;
    }

    /// <summary>
    /// Default constructor
    /// </summary>
    public SQLiteParameter()
      : this(null, UnknownDbType, 0, null, DataRowVersion.Current)
    {
    }

    /// <summary>
    /// Constructs a named parameter given the specified parameter name
    /// </summary>
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    /// Constructs a named parameter of the specified type, size, source column and row version
    /// </summary>
    /// <param name="parameterName">The name of the parameter</param>
    /// <param name="parameterType">The data type</param>
    /// <param name="parameterSize">The size of the parameter</param>
    /// <param name="sourceColumn">The source column</param>
    /// <param name="rowVersion">The row version information</param>
    public SQLiteParameter(string parameterName, DbType parameterType, int parameterSize, string sourceColumn, DataRowVersion rowVersion)      
    {
      _parameterName = parameterName;
      _dbType = parameterType;
      _sourceColumn = sourceColumn;
      _rowVersion = rowVersion;
      _dataSize = parameterSize;
      _nullable = true;







|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    /// Constructs a named parameter of the specified type, size, source column and row version
    /// </summary>
    /// <param name="parameterName">The name of the parameter</param>
    /// <param name="parameterType">The data type</param>
    /// <param name="parameterSize">The size of the parameter</param>
    /// <param name="sourceColumn">The source column</param>
    /// <param name="rowVersion">The row version information</param>
    public SQLiteParameter(string parameterName, DbType parameterType, int parameterSize, string sourceColumn, DataRowVersion rowVersion)
    {
      _parameterName = parameterName;
      _dbType = parameterType;
      _sourceColumn = sourceColumn;
      _rowVersion = rowVersion;
      _dataSize = parameterSize;
      _nullable = true;
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
    /// <param name="parameterSize">The size of the parameter</param>
    /// <param name="direction">Only input parameters are supported in SQLite</param>
    /// <param name="isNullable">Ignored</param>
    /// <param name="precision">Ignored</param>
    /// <param name="scale">Ignored</param>
    /// <param name="sourceColumn">The source column</param>
    /// <param name="rowVersion">The row version information</param>
    /// <param name="value">The initial value to assign the parameter</param>   
#if !PLATFORM_COMPACTFRAMEWORK
    [EditorBrowsable(EditorBrowsableState.Advanced)]
#endif
    public SQLiteParameter(string parameterName, DbType parameterType, int parameterSize, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion rowVersion, object value)
      : this(parameterName, parameterType, parameterSize, sourceColumn, rowVersion)
    {
      Direction = direction;







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    /// <param name="parameterSize">The size of the parameter</param>
    /// <param name="direction">Only input parameters are supported in SQLite</param>
    /// <param name="isNullable">Ignored</param>
    /// <param name="precision">Ignored</param>
    /// <param name="scale">Ignored</param>
    /// <param name="sourceColumn">The source column</param>
    /// <param name="rowVersion">The row version information</param>
    /// <param name="value">The initial value to assign the parameter</param>
#if !PLATFORM_COMPACTFRAMEWORK
    [EditorBrowsable(EditorBrowsableState.Advanced)]
#endif
    public SQLiteParameter(string parameterName, DbType parameterType, int parameterSize, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion rowVersion, object value)
      : this(parameterName, parameterType, parameterSize, sourceColumn, rowVersion)
    {
      Direction = direction;
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    /// </summary>
    public IDbCommand Command
    {
      get
      {
        return _command;
      }
      set 
      {
        _command = value;
      }
    }

    /// <summary>
    /// Whether or not the parameter can contain a null value
    /// </summary>
    public override bool IsNullable
    {
      get
      {
        return _nullable;
      }
      set 
      {
        _nullable = value;
      }
    }

    /// <summary>
    /// Returns the datatype of the parameter







|














|







309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    /// </summary>
    public IDbCommand Command
    {
      get
      {
        return _command;
      }
      set
      {
        _command = value;
      }
    }

    /// <summary>
    /// Whether or not the parameter can contain a null value
    /// </summary>
    public override bool IsNullable
    {
      get
      {
        return _nullable;
      }
      set
      {
        _nullable = value;
      }
    }

    /// <summary>
    /// Returns the datatype of the parameter
503
504
505
506
507
508
509
510















511






























    /// <returns>A new, unassociated SQLiteParameter</returns>
    public object Clone()
    {
      SQLiteParameter newparam = new SQLiteParameter(this);

      return newparam;
    }
  }















}





































|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
    /// <returns>A new, unassociated SQLiteParameter</returns>
    public object Clone()
    {
      SQLiteParameter newparam = new SQLiteParameter(this);

      return newparam;
    }

    /// <summary>
    /// Attempts to build a name suitable for use with an index-only
    /// (unnamed) parameter.
    /// </summary>
    /// <param name="index">The index for the parameter.</param>
    /// <param name="placeholder">
    /// Non-zero if the returned name should be a placeholder, i.e.
    /// an unnamed parameter that does not use a syntax supported by
    /// the SQLite core library.
    /// </param>
    /// <returns>The built name -OR- null if it cannot be built.</returns>
    internal static string CreateNameForIndex(int index, bool placeholder)
    {
        return HelperMethods.StringFormat(CultureInfo.InvariantCulture,
            placeholder ? ";{0}" : "?{0}", index + 1);
    }

    /// <summary>
    /// Returns non-zero if the specified parameter name appears to
    /// refer to an unnamed parameter placeholder.
    /// </summary>
    /// <param name="name">
    /// The parameter name to check.
    /// </param>
    /// <param name="index">
    /// The parameter index or negative one if it cannot be determined.
    /// </param>
    /// <returns>
    /// Non-zero if the specified parameter name represents an unnamed
    /// placeholder parameter.
    /// </returns>
    internal static bool IsUnnamedPlaceholder(string name, out int index)
    {
        index = -1;

        if (String.IsNullOrEmpty(name))
            return false;

        if (name[0] != ';')
            return false;

        return int.TryParse(
            name.Substring(1), NumberStyles.None, null, out index);
    }
  }
}
Changes to System.Data.SQLite/SQLiteParameterCollection.cs.
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
      string s;
      int n;
      int y = -1;
      SQLiteStatement stmt;

      foreach(SQLiteParameter p in _parameterList)
      {
        y ++;
        s = p.ParameterName;
        if (s == null)
        {
          s = HelperMethods.StringFormat(CultureInfo.InvariantCulture, ";{0}", nUnnamed);
          nUnnamed++;
        }

        int x;
        bool isMapped = false;

        if (activeStatement == null)







|

|

|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
      string s;
      int n;
      int y = -1;
      SQLiteStatement stmt;

      foreach(SQLiteParameter p in _parameterList)
      {
        y++;
        s = p.ParameterName;
        if (String.IsNullOrEmpty(s))
        {
          s = SQLiteParameter.CreateNameForIndex(nUnnamed, true);
          nUnnamed++;
        }

        int x;
        bool isMapped = false;

        if (activeStatement == null)
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
          stmt = null;
        }

        // If the parameter has a name, but the SQL statement uses unnamed references, this can happen -- attempt to map
        // the parameter by its index in the collection
        if (isMapped == false)
        {
          s = HelperMethods.StringFormat(CultureInfo.InvariantCulture, ";{0}", y);

          stmt = activeStatement;
          for (n = 0; n < x; n++)
          {
            if (stmt == null) stmt = _command._statementList[n];
            if (stmt._paramNames != null)
            {
              if (stmt.MapParameter(s, p) == true)


                isMapped = true;

            }
            stmt = null;
          }
        }
      }
      if (activeStatement == null) _unboundFlag = false;
    }
  }
}







|







|
>
>

>









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
479
480
          stmt = null;
        }

        // If the parameter has a name, but the SQL statement uses unnamed references, this can happen -- attempt to map
        // the parameter by its index in the collection
        if (isMapped == false)
        {
          s = SQLiteParameter.CreateNameForIndex(y, true);

          stmt = activeStatement;
          for (n = 0; n < x; n++)
          {
            if (stmt == null) stmt = _command._statementList[n];
            if (stmt._paramNames != null)
            {
              if (stmt.MapParameter(s, p) ||
                  stmt.MapUnnamedParameter(s, p))
              {
                isMapped = true;
              }
            }
            stmt = null;
          }
        }
      }
      if (activeStatement == null) _unboundFlag = false;
    }
  }
}
Changes to System.Data.SQLite/SQLiteStatement.cs.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        _paramValues = new SQLiteParameter[n];

        for (x = 0; x < n; x++)
        {
          s = _sql.Bind_ParamName(this, _flags, x + 1);
          if (String.IsNullOrEmpty(s))
          {
            s = HelperMethods.StringFormat(CultureInfo.InvariantCulture, ";{0}", nCmdStart);
            nCmdStart++;
            _unnamedParameters++;
          }
          _paramNames[x] = s;
          _paramValues[x] = null;
        }
      }







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        _paramValues = new SQLiteParameter[n];

        for (x = 0; x < n; x++)
        {
          s = _sql.Bind_ParamName(this, _flags, x + 1);
          if (String.IsNullOrEmpty(s))
          {
            s = SQLiteParameter.CreateNameForIndex(nCmdStart, true);
            nCmdStart++;
            _unnamedParameters++;
          }
          _paramNames[x] = s;
          _paramValues[x] = null;
        }
      }
206
207
208
209
210
211
212






































213
214
215
216
217
218
219
        if ((_sql != null) && _sql.IsOpen())
        {
            changes = _sql.Changes;
            readOnly = _sql.IsReadOnly(this);

            return true;
        }







































        return false;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>







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







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
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
        if ((_sql != null) && _sql.IsOpen())
        {
            changes = _sql.Changes;
            readOnly = _sql.IsReadOnly(this);

            return true;
        }

        return false;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// This method attempts to map the specified named placeholder
    /// parameter, i.e. an unnamed parameter that has been given an
    /// placeholder name.
    /// </summary>
    /// <param name="s">The placeholder parameter name to map.</param>
    /// <param name="p">The parameter to assign it.</param>
    internal bool MapUnnamedParameter(string s, SQLiteParameter p)
    {
        if (_paramNames == null)
            return false;

        int index;

        if (SQLiteParameter.IsUnnamedPlaceholder(s, out index))
        {
            s = String.Format("?{0}", s.Substring(index));

            int length = s.Length;
            int count = _paramNames.Length;

            for (int n = 0; n < count; n++)
            {
                if (String.Compare(
                      _paramNames[n], 0, s, 0, length,
                      StringComparison.Ordinal) == 0)
                {
                    _paramValues[n] = p;
                    return true;
                }
            }
        }

        return false;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
Added Tests/pst-76cb35b58d.eagle.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
###############################################################################
#
# pst-76cb35b58d.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

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

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

runTest {test pst-76cb35b58d-1.1 {unnamed parameters "duplicates"} -setup {
  setupDb [set fileName pst-76cb35b58d-1.1.db]
} -body {
  sql execute $db {
    CREATE TABLE t1(x INTEGER, y TEXT);
    INSERT INTO t1 (x, y) VALUES(1, 'one');
    INSERT INTO t1 (x, y) VALUES(2, 'two');
    INSERT INTO t1 (x, y) VALUES(3, 'three');
  }

  set param1 [list "" Int64 99]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(4, 'four');" $param1
  sql execute $db "INSERT INTO t1 (x, y) VALUES(5, ?1);" $param1

  set param1 [list "" Int64 6]

  sql execute $db "INSERT INTO t1 (x, y) VALUES(?1, ?1);" $param1

  sql execute -execute reader -format list $db \
      "SELECT x, y FROM t1 ORDER BY x;"
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain param1
  unset -nocomplain db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -result {1 one 2 two 3 three 4 four 5 99 6 6}}

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

runSQLiteTestEpilogue
runTestEpilogue