Index: testce/Program.cs
==================================================================
--- testce/Program.cs
+++ testce/Program.cs
@@ -4,38 +4,43 @@
*
* Released to the public domain, use at your own risk!
********************************************************/
using System;
-using System.Data.Common;
+using System.Data.Common;
using System.Data.SQLite;
using System.IO;
using System.Reflection;
-using System.Windows.Forms;
-
-namespace test
-{
- class Program
+using System.Windows.Forms;
+
+namespace test
+{
+ class Program
{
private static readonly string DefaultConnectionString =
- "Data Source={DataDirectory}\\test.db;Password=yVXL39etehPX;";
-
- [MTAThread]
- static void Main()
+ "Data Source={DataDirectory}\\test.db;Password=yVXL39etehPX;";
+
+ [MTAThread]
+ static int Main(string[] args)
{
+ bool autoClose = false;
+ int exitCode = 2; /* INCOMPLETE */
Assembly assembly = Assembly.GetExecutingAssembly();
AssemblyName assemblyName = assembly.GetName();
- string directory = Path.GetDirectoryName(assemblyName.CodeBase);
+ string directory = Path.GetDirectoryName(assemblyName.CodeBase);
+
+ if (args.Length > 0)
+ autoClose = bool.Parse(args[0]);
try { File.Delete(directory + "\\test.db"); } catch { }
SQLiteFunction.RegisterFunction(typeof(TestFunc));
SQLiteFunction.RegisterFunction(typeof(MyCount));
SQLiteFunction.RegisterFunction(typeof(MySequence));
- using (DbConnection cnn = new SQLiteConnection())
- {
+ using (DbConnection cnn = new SQLiteConnection())
+ {
string connectionString = DefaultConnectionString;
try
{
//
@@ -70,15 +75,22 @@
"{DataDirectory}", directory);
cnn.ConnectionString = connectionString;
cnn.Open();
- TestCases tests = new TestCases();
+ TestCases tests = new TestCases(autoClose);
tests.Run(cnn);
Application.Run(tests.frm);
- }
- }
- }
- }
-}
+
+ if (tests.Succeeded())
+ exitCode = 0; /* SUCCESS */
+ else
+ exitCode = 1; /* FAILURE */
+ }
+ }
+
+ return exitCode;
+ }
+ }
+}
Index: testce/TestCases.cs
==================================================================
--- testce/TestCases.cs
+++ testce/TestCases.cs
@@ -2,83 +2,97 @@
* 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!
********************************************************/
-
-using System;
-using System.Data.Common;
-using System.Data;
-using System.Data.SQLite;
-
-namespace test
-{
-
- ///
- /// Scalar user-defined function. In this example, the same class is declared twice with
- /// different function names to demonstrate how to use alias names for user-defined functions.
- ///
- [SQLiteFunction(Name = "Foo", Arguments = 2, FuncType = FunctionType.Scalar)]
- [SQLiteFunction(Name = "TestFunc", Arguments = 2, FuncType = FunctionType.Scalar)]
- class TestFunc : SQLiteFunction
- {
- public override object Invoke(object[] args)
- {
- if (args[0].GetType() != typeof(int)) return args[0];
-
- int Param1 = Convert.ToInt32(args[0]); // First parameter
- int Param2 = Convert.ToInt32(args[1]); // Second parameter
-
- return Param1 + Param2;
- }
- }
-
- ///
- /// Aggregate user-defined function. Arguments = -1 means any number of arguments is acceptable
- ///
- [SQLiteFunction(Name = "MyCount", Arguments = -1, FuncType = FunctionType.Aggregate)]
- class MyCount : SQLiteFunction
- {
- public override void Step(object[] args, int nStep, ref object contextData)
- {
- if (contextData == null)
- {
- contextData = 1;
- }
- else
- contextData = (int)contextData + 1;
- }
-
- public override object Final(object contextData)
- {
- return contextData;
- }
- }
-
- ///
- /// User-defined collating sequence.
- ///
- [SQLiteFunction(Name = "MYSEQUENCE", FuncType = FunctionType.Collation)]
- class MySequence : SQLiteFunction
- {
- public override int Compare(string param1, string param2)
- {
- // Make sure the string "Field3" is sorted out of order
- if (param1 == "Field3") return 1;
- if (param2 == "Field3") return -1;
- return String.Compare(param1, param2, true);
- }
- }
-
- internal class TestCases
- {
- internal Form1 frm;
-
- internal void Run(DbConnection cnn)
- {
- frm = new Form1();
-
+
+using System;
+using System.Data.Common;
+using System.Data;
+using System.Data.SQLite;
+
+namespace test
+{
+
+ ///
+ /// Scalar user-defined function. In this example, the same class is declared twice with
+ /// different function names to demonstrate how to use alias names for user-defined functions.
+ ///
+ [SQLiteFunction(Name = "Foo", Arguments = 2, FuncType = FunctionType.Scalar)]
+ [SQLiteFunction(Name = "TestFunc", Arguments = 2, FuncType = FunctionType.Scalar)]
+ class TestFunc : SQLiteFunction
+ {
+ public override object Invoke(object[] args)
+ {
+ if (args[0].GetType() != typeof(int)) return args[0];
+
+ int Param1 = Convert.ToInt32(args[0]); // First parameter
+ int Param2 = Convert.ToInt32(args[1]); // Second parameter
+
+ return Param1 + Param2;
+ }
+ }
+
+ ///
+ /// Aggregate user-defined function. Arguments = -1 means any number of arguments is acceptable
+ ///
+ [SQLiteFunction(Name = "MyCount", Arguments = -1, FuncType = FunctionType.Aggregate)]
+ class MyCount : SQLiteFunction
+ {
+ public override void Step(object[] args, int nStep, ref object contextData)
+ {
+ if (contextData == null)
+ {
+ contextData = 1;
+ }
+ else
+ contextData = (int)contextData + 1;
+ }
+
+ public override object Final(object contextData)
+ {
+ return contextData;
+ }
+ }
+
+ ///
+ /// User-defined collating sequence.
+ ///
+ [SQLiteFunction(Name = "MYSEQUENCE", FuncType = FunctionType.Collation)]
+ class MySequence : SQLiteFunction
+ {
+ public override int Compare(string param1, string param2)
+ {
+ // Make sure the string "Field3" is sorted out of order
+ if (param1 == "Field3") return 1;
+ if (param2 == "Field3") return -1;
+ return String.Compare(param1, param2, true);
+ }
+ }
+
+ internal class TestCases
+ {
+ private bool autoClose;
+ internal Form1 frm;
+ internal int total;
+ internal int passed;
+ internal int failed;
+
+ internal TestCases(bool autoExit)
+ {
+ this.autoClose = autoExit;
+ }
+
+ internal bool Succeeded()
+ {
+ return (failed == 0) && (passed == total);
+ }
+
+ internal void Run(DbConnection cnn)
+ {
+ frm = new Form1();
+
frm.Show();
Type type = cnn.GetType();
frm.WriteLine("\r\nBeginning Test on " + type.ToString());
@@ -86,759 +100,784 @@
if (cnn2 != null)
{
cnn2 = null;
frm.WriteLine("SQLite v" + SQLiteConnection.SQLiteVersion +
" [" + SQLiteConnection.SQLiteSourceId + "]");
- }
-
- try { CreateTable(cnn); frm.WriteLine("SUCCESS - CreateTable"); }
- catch (Exception) { frm.WriteLine("FAIL - CreateTable"); }
-
- try { DataTypeTest(cnn); frm.WriteLine("SUCCESS - DataType Test"); }
- catch (Exception) { frm.WriteLine("FAIL - DataType Test"); }
-
- try { FullTextTest(cnn); frm.WriteLine("SUCCESS - Full Text Search"); }
- catch (Exception) { frm.WriteLine("FAIL - Full Text Search"); }
-
- try { KeyInfoTest(cnn); frm.WriteLine("SUCCESS - KeyInfo Fetch"); }
- catch (Exception) { frm.WriteLine("FAIL - KeyInfo Fetch"); }
-
- try { InsertTable(cnn); frm.WriteLine("SUCCESS - InsertTable"); }
- catch (Exception) { frm.WriteLine("FAIL - InsertTable"); }
-
- try { VerifyInsert(cnn); frm.WriteLine("SUCCESS - VerifyInsert"); }
- catch (Exception) { frm.WriteLine("FAIL - VerifyInsert"); }
-
- try { CoersionTest(cnn); frm.WriteLine("FAIL - CoersionTest"); }
- catch (Exception) { frm.WriteLine("SUCCESS - CoersionTest"); }
-
- try { ParameterizedInsert(cnn); frm.WriteLine("SUCCESS - ParameterizedInsert"); }
- catch (Exception) { frm.WriteLine("FAIL - ParameterizedInsert"); }
-
- try { BinaryInsert(cnn); frm.WriteLine("SUCCESS - BinaryInsert"); }
- catch (Exception) { frm.WriteLine("FAIL - BinaryInsert"); }
-
- try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); }
- catch (Exception) { frm.WriteLine("FAIL - VerifyBinaryData"); }
-
- try { LockTest(cnn); frm.WriteLine("SUCCESS - LockTest"); }
- catch (Exception) { frm.WriteLine("FAIL - LockTest"); }
-
- try { ParameterizedInsertMissingParams(cnn); frm.WriteLine("FAIL - ParameterizedInsertMissingParams"); }
- catch (Exception) { frm.WriteLine("SUCCESS - ParameterizedInsertMissingParams"); }
-
- try { InsertMany(cnn, false); frm.WriteLine("SUCCESS - InsertMany"); }
- catch (Exception) { frm.WriteLine("FAIL - InsertMany"); }
-
- try { InsertMany(cnn, true); frm.WriteLine("SUCCESS - InsertManyWithIdentityFetch"); }
- catch (Exception) { frm.WriteLine("FAIL - InsertManyWithIdentityFetch"); }
-
- try { FastInsertMany(cnn); frm.WriteLine("SUCCESS - FastInsertMany"); }
- catch (Exception) { frm.WriteLine("FAIL - FastInsertMany"); }
-
- try { IterationTest(cnn); frm.WriteLine("SUCCESS - Iteration Test"); }
- catch (Exception) { frm.WriteLine("FAIL - Iteration Test"); }
-
- try { UserFunction(cnn); frm.WriteLine("SUCCESS - UserFunction"); }
- catch (Exception) { frm.WriteLine("FAIL - UserFunction"); }
-
- try { UserAggregate(cnn); frm.WriteLine("SUCCESS - UserAggregate"); }
- catch (Exception) { frm.WriteLine("FAIL - UserAggregate"); }
-
- try { UserCollation(cnn); frm.WriteLine("SUCCESS - UserCollation"); }
- catch (Exception) { frm.WriteLine("FAIL - UserCollation"); }
-
- try { DropTable(cnn); frm.WriteLine("SUCCESS - DropTable"); }
- catch (Exception) { frm.WriteLine("FAIL - DropTable"); }
-
- frm.WriteLine("\r\nTests Finished.");
- }
-
- internal static void KeyInfoTest(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- // First test against integer primary key (optimized) keyinfo fetch
- cmd.CommandText = "Create table keyinfotest (id integer primary key, myuniquevalue integer unique not null, myvalue varchar(50))";
- cmd.ExecuteNonQuery();
-
- cmd.CommandText = "Select * from keyinfotest";
- using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
- {
- using (DataTable tbl = reader.GetSchemaTable())
- {
- if (tbl.Rows.Count != 3) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
- }
- }
-
- cmd.CommandText = "SELECT MyValue FROM keyinfotest";
- using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
- {
- using (DataTable tbl = reader.GetSchemaTable())
- {
- if (tbl.Rows.Count != 2) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
- }
- }
-
- cmd.CommandText = "DROP TABLE keyinfotest";
- cmd.ExecuteNonQuery();
-
- // Now test against non-integer primary key (unoptimized) subquery keyinfo fetch
- cmd.CommandText = "Create table keyinfotest (id char primary key, myuniquevalue integer unique not null, myvalue varchar(50))";
- cmd.ExecuteNonQuery();
-
- cmd.CommandText = "SELECT MyValue FROM keyinfotest";
- using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
- {
- using (DataTable tbl = reader.GetSchemaTable())
- {
- if (tbl.Rows.Count != 2) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
- }
- }
-
- cmd.CommandText = "Select * from keyinfotest";
- using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
- {
- using (DataTable tbl = reader.GetSchemaTable())
- {
- if (tbl.Rows.Count != 3) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
- }
- }
-
- // Make sure commandbuilder can generate an update command with the correct parameter count
- using (DbDataAdapter adp = new SQLiteDataAdapter())
- using (DbCommandBuilder builder = new SQLiteCommandBuilder())
- {
- adp.SelectCommand = cmd;
- builder.DataAdapter = adp;
- builder.ConflictOption = ConflictOption.OverwriteChanges;
-
- using (DbCommand updatecmd = builder.GetUpdateCommand())
- {
- if (updatecmd.Parameters.Count != 4)
- throw new ArgumentOutOfRangeException("Wrong number of parameters in update command!");
- }
- }
- }
- }
-
- internal static void DataTypeTest(DbConnection cnn)
- {
- DateTime now = DateTime.Now;
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "create table datatypetest(id integer primary key, myvalue, datetimevalue datetime, decimalvalue decimal)";
- cmd.ExecuteNonQuery();
-
- cmd.CommandText = "insert into datatypetest(myvalue, datetimevalue, decimalvalue) values(?,?,?)";
- DbParameter p1 = cmd.CreateParameter();
- DbParameter p2 = cmd.CreateParameter();
- DbParameter p3 = cmd.CreateParameter();
-
- cmd.Parameters.Add(p1);
- cmd.Parameters.Add(p2);
- cmd.Parameters.Add(p3);
-
- p1.Value = 1;
- p2.Value = DateTime.MinValue;
- p3.Value = (Decimal)1.05;
- cmd.ExecuteNonQuery();
-
- p1.ResetDbType();
- p2.ResetDbType();
- p3.ResetDbType();
-
- p1.Value = "One";
- p2.Value = "2001-01-01";
- p3.Value = (Decimal)1.0;
- cmd.ExecuteNonQuery();
-
- p1.ResetDbType();
- p2.ResetDbType();
- p3.ResetDbType();
-
- p1.Value = 1.01;
- p2.Value = now;
- p3.Value = (Decimal)9.91;
- cmd.ExecuteNonQuery();
-
- cmd.CommandText = "select myvalue, datetimevalue, decimalvalue from datatypetest";
- using (DbDataReader reader = cmd.ExecuteReader())
- {
- for (int n = 0; n < 3; n++)
- {
- reader.Read();
- if (reader.GetValue(1).GetType() != reader.GetDateTime(1).GetType()) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).GetType() != reader.GetDecimal(2).GetType()) throw new ArgumentOutOfRangeException();
-
- switch (n)
- {
- case 0:
- if (reader.GetValue(0).GetType() != typeof(long)) throw new ArgumentOutOfRangeException();
-
- if (reader.GetValue(0).Equals((long)1) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(1).Equals(DateTime.MinValue) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).Equals((Decimal)1.05) == false) throw new ArgumentOutOfRangeException();
-
- if (reader.GetInt64(0) != (long)1) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(1).Equals(reader.GetDateTime(1)) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).Equals(reader.GetDecimal(2)) == false) throw new ArgumentOutOfRangeException();
- break;
- case 1:
- if (reader.GetValue(0).GetType() != typeof(string)) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(0).Equals("One") == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(1).Equals(new DateTime(2001, 1, 1)) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).Equals((Decimal)1.0) == false) throw new ArgumentOutOfRangeException();
-
- if (reader.GetString(0) != "One") throw new ArgumentOutOfRangeException();
- if (reader.GetValue(1).Equals(reader.GetDateTime(1)) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).Equals(reader.GetDecimal(2)) == false) throw new ArgumentOutOfRangeException();
- break;
- case 2:
- if (reader.GetValue(0).GetType() != typeof(double)) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(0).Equals(1.01) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(1).Equals(now) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).Equals((Decimal)9.91) == false) throw new ArgumentOutOfRangeException();
-
- if (reader.GetDouble(0) != 1.01) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(1).Equals(reader.GetDateTime(1)) == false) throw new ArgumentOutOfRangeException();
- if (reader.GetValue(2).Equals(reader.GetDecimal(2)) == false) throw new ArgumentOutOfRangeException();
- break;
- }
- }
- }
- }
- }
-
- internal static void FullTextTest(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "CREATE VIRTUAL TABLE FullText USING FTS3(name, ingredients);";
- cmd.ExecuteNonQuery();
-
- string[] names = { "broccoli stew", "pumpkin stew", "broccoli pie", "pumpkin pie" };
- string[] ingredients = { "broccoli peppers cheese tomatoes", "pumpkin onions garlic celery", "broccoli cheese onions flour", "pumpkin sugar flour butter" };
- int n;
-
- cmd.CommandText = "insert into FullText (name, ingredients) values (@name, @ingredient);";
- DbParameter name = cmd.CreateParameter();
- DbParameter ingredient = cmd.CreateParameter();
-
- name.ParameterName = "@name";
- ingredient.ParameterName = "@ingredient";
-
- cmd.Parameters.Add(name);
- cmd.Parameters.Add(ingredient);
-
- for (n = 0; n < names.Length; n++)
- {
- name.Value = names[n];
- ingredient.Value = ingredients[n];
-
- cmd.ExecuteNonQuery();
- }
-
- cmd.CommandText = "select rowid, name, ingredients from FullText where name match 'pie';";
-
- int[] rowids = { 3, 4 };
- n = 0;
-
- using (DbDataReader reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- if (reader.GetInt64(0) != rowids[n++])
- throw new ArgumentException("Unexpected rowid returned");
-
- if (n > rowids.Length) throw new ArgumentException("Too many rows returned");
- }
- }
- }
- }
-
- internal void CreateTable(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "CREATE TABLE TestCase (ID integer primary key autoincrement, Field1 Integer, Field2 Float, Field3 VARCHAR(50), Field4 CHAR(10), Field5 DateTime, Field6 Image)";
- //cmd.CommandText = "CREATE TABLE TestCase (ID bigint primary key identity, Field1 Integer, Field2 Float, Field3 VARCHAR(50), Field4 CHAR(10), Field5 DateTime, Field6 Image)";
- cmd.ExecuteNonQuery();
- }
- }
-
- internal void DropTable(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "DROP TABLE TestCase";
- cmd.ExecuteNonQuery();
- }
- }
-
- internal void InsertTable(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(1, 3.14159, 'Field3', 'Field4', '2005-01-01 13:49:00')";
- cmd.ExecuteNonQuery();
- }
- }
-
- internal void VerifyInsert(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5 FROM TestCase";
- cmd.Prepare();
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- if (rd.Read())
- {
- long Field1 = rd.GetInt64(0);
- double Field2 = rd.GetDouble(1);
- string Field3 = rd.GetString(2);
- string Field4 = rd.GetString(3).TrimEnd();
- DateTime Field5 = rd.GetDateTime(4);
-
- if (Field1 != 1) throw new ArgumentOutOfRangeException("Non-Match on Field1");
- if (Field2 != 3.14159) throw new ArgumentOutOfRangeException("Non-Match on Field2");
- if (Field3 != "Field3") throw new ArgumentOutOfRangeException("Non-Match on Field3");
- if (Field4 != "Field4") throw new ArgumentOutOfRangeException("Non-Match on Field4");
- if (Field5.CompareTo(DateTime.Parse("2005-01-01 13:49:00")) != 0) throw new ArgumentOutOfRangeException("Non-Match on Field5");
- }
- else throw new ArgumentOutOfRangeException("No data in table");
- }
- }
- }
-
- internal void CoersionTest(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5, 'A', 1, 1 + 1, 3.14159 FROM TestCase";
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- if (rd.Read())
- {
- object Field1 = rd.GetInt32(0);
- object Field2 = rd.GetDouble(1);
- object Field3 = rd.GetString(2);
- object Field4 = rd.GetString(3).TrimEnd();
- object Field5 = rd.GetDateTime(4);
-
- // The next statement should cause an exception
- Field1 = rd.GetString(0);
- Field2 = rd.GetString(1);
- Field3 = rd.GetString(2);
- Field4 = rd.GetString(3);
- Field5 = rd.GetString(4);
-
- Field1 = rd.GetInt32(0);
- Field2 = rd.GetInt32(1);
- Field3 = rd.GetInt32(2);
- Field4 = rd.GetInt32(3);
- Field5 = rd.GetInt32(4);
-
- Field1 = rd.GetDecimal(0);
- Field2 = rd.GetDecimal(1);
- Field3 = rd.GetDecimal(2);
- Field4 = rd.GetDecimal(3);
- Field5 = rd.GetDecimal(4);
- }
- else throw new ArgumentOutOfRangeException("No data in table");
- }
- }
- }
-
- internal void ParameterizedInsert(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(?,?,?,?,?)";
- DbParameter Field1 = cmd.CreateParameter();
- DbParameter Field2 = cmd.CreateParameter();
- DbParameter Field3 = cmd.CreateParameter();
- DbParameter Field4 = cmd.CreateParameter();
- DbParameter Field5 = cmd.CreateParameter();
-
- Field1.Value = 2;
- Field2.Value = 3.14159;
- Field3.Value = "Param Field3";
- Field4.Value = "Field4 Par";
- Field5.Value = DateTime.Now;
-
- cmd.Parameters.Add(Field1);
- cmd.Parameters.Add(Field2);
- cmd.Parameters.Add(Field3);
- cmd.Parameters.Add(Field4);
- cmd.Parameters.Add(Field5);
-
- cmd.ExecuteNonQuery();
- }
- }
-
- internal void BinaryInsert(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "INSERT INTO TestCase(Field6) VALUES(?)";
- DbParameter Field6 = cmd.CreateParameter();
-
- byte[] b = new byte[4000];
- b[0] = 1;
- b[100] = 2;
- b[1000] = 3;
- b[2000] = 4;
- b[3000] = 5;
-
- Field6.Value = b;
-
- cmd.Parameters.Add(Field6);
-
- cmd.ExecuteNonQuery();
- }
- }
-
- internal void VerifyBinaryData(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "SELECT Field6 FROM TestCase WHERE Field6 IS NOT NULL";
- byte[] b = new byte[4000];
-
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- if (rd.Read() == false) throw new ArgumentOutOfRangeException();
-
- rd.GetBytes(0, 0, b, 0, 4000);
-
- if (b[0] != 1) throw new ArgumentException();
- if (b[100] != 2) throw new ArgumentException();
- if (b[1000] != 3) throw new ArgumentException();
- if (b[2000] != 4) throw new ArgumentException();
- if (b[3000] != 5) throw new ArgumentException();
- }
- }
- }
-
- internal static void LockTest(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "SELECT Field6 FROM TestCase WHERE Field6 IS NOT NULL";
- byte[] b = new byte[4000];
-
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- if (rd.Read() == false) throw new ArgumentOutOfRangeException();
-
- rd.GetBytes(0, 0, b, 0, 4000);
-
- if (b[0] != 1) throw new ArgumentException();
- if (b[100] != 2) throw new ArgumentException();
- if (b[1000] != 3) throw new ArgumentException();
- if (b[2000] != 4) throw new ArgumentException();
- if (b[3000] != 5) throw new ArgumentException();
-
- using (DbConnection clone = (DbConnection)((ICloneable)cnn).Clone())
- {
- using (DbCommand newcmd = clone.CreateCommand())
- {
- newcmd.CommandText = "DELETE FROM TestCase WHERE Field6 IS NULL";
- newcmd.CommandTimeout = 2;
- int cmdStart = Environment.TickCount;
- int cmdEnd;
-
- try
- {
- newcmd.ExecuteNonQuery(); // should fail because there's a reader on the database
- throw new ArgumentException(); // If we got here, the test failed
- }
- catch
- {
- cmdEnd = Environment.TickCount;
- if (cmdEnd - cmdStart < 2000 || cmdEnd - cmdStart > 3000)
- throw new ArgumentException(); // Didn't wait the right amount of time
- }
- }
- }
- }
- }
- }
-
- internal void ParameterizedInsertMissingParams(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(?,?,?,?,?)";
- DbParameter Field1 = cmd.CreateParameter();
- DbParameter Field2 = cmd.CreateParameter();
- DbParameter Field3 = cmd.CreateParameter();
- DbParameter Field4 = cmd.CreateParameter();
- DbParameter Field5 = cmd.CreateParameter();
-
- Field1.DbType = System.Data.DbType.Int32;
-
- Field1.Value = 2;
- Field2.Value = 3.14159;
- Field3.Value = "Field3 Param";
- Field4.Value = "Field4 Par";
- Field5.Value = DateTime.Now;
-
- cmd.Parameters.Add(Field1);
- cmd.Parameters.Add(Field2);
- cmd.Parameters.Add(Field3);
- cmd.Parameters.Add(Field4);
-
- // Assertion here, not enough parameters
- cmd.ExecuteNonQuery();
- }
- }
-
- // Utilizes the SQLiteCommandBuilder, which in turn utilizes SQLiteDataReader's GetSchemaTable() functionality
- internal void InsertMany(DbConnection cnn, bool bWithIdentity)
- {
- int nmax = 1000;
-
- using (DbTransaction dbTrans = cnn.BeginTransaction())
- {
- using (DbDataAdapter adp = new SQLiteDataAdapter())
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.Transaction = dbTrans;
- cmd.CommandText = "SELECT * FROM TestCase WHERE 1=2";
- adp.SelectCommand = cmd;
-
- using (DbCommandBuilder bld = new SQLiteCommandBuilder())
- {
- bld.DataAdapter = adp;
- using (adp.InsertCommand = (SQLiteCommand)((ICloneable)bld.GetInsertCommand()).Clone())
- {
- bld.DataAdapter = null;
- if (bWithIdentity)
- {
- adp.InsertCommand.CommandText += ";SELECT last_insert_rowid() AS [ID]";
- adp.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
- }
-
- using (DataTable tbl = new DataTable())
- {
- adp.Fill(tbl);
- for (int n = 0; n < nmax; n++)
- {
- DataRow row = tbl.NewRow();
- row[1] = n + nmax;
- tbl.Rows.Add(row);
- }
-
- frm.Write(String.Format(" InsertMany{0} ({1} rows) Begins ... ", (bWithIdentity == true) ? "WithIdentityFetch" : " ", nmax));
- int dtStart = Environment.TickCount;
- adp.Update(tbl);
- int dtEnd = Environment.TickCount;
- dtEnd -= dtStart;
- frm.Write(String.Format("Ends in {0} ms ... ", (dtEnd)));
-
- dtStart = Environment.TickCount;
- dbTrans.Commit();
- dtEnd = Environment.TickCount;
- dtEnd -= dtStart;
- frm.WriteLine(String.Format("Commits in {0} ms", (dtEnd)));
- }
- }
- }
- }
- }
- }
- }
-
- internal void FastInsertMany(DbConnection cnn)
- {
- using (DbTransaction dbTrans = cnn.BeginTransaction())
- {
- int dtStart;
- int dtEnd;
-
- using (DbCommand cmd = cnn.CreateCommand())
- {
- cmd.CommandText = "INSERT INTO TestCase(Field1) VALUES(?)";
- DbParameter Field1 = cmd.CreateParameter();
-
- cmd.Parameters.Add(Field1);
-
- frm.WriteLine(String.Format(" Fast insert using parameters and prepared statement\r\n -> (10,000 rows) Begins ... "));
- dtStart = Environment.TickCount;
- for (int n = 0; n < 10000; n++)
- {
- Field1.Value = n + 100000;
- cmd.ExecuteNonQuery();
- }
-
- dtEnd = Environment.TickCount;
- dtEnd -= dtStart;
- frm.Write(String.Format(" -> Ends in {0} ms ... ", (dtEnd)));
- }
-
- dtStart = Environment.TickCount;
- dbTrans.Rollback();
- dtEnd = Environment.TickCount;
- dtEnd -= dtStart;
- frm.WriteLine(String.Format("Rolled back in {0} ms", (dtEnd)));
- }
- }
-
- // Causes the user-defined function to be called
- internal void UserFunction(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- int nTimes;
- int dtStart;
-
- nTimes = 0;
- cmd.CommandText = "SELECT Foo('ee','foo')";
- dtStart = Environment.TickCount;
- while (Environment.TickCount - dtStart < 1000)
- {
- cmd.ExecuteNonQuery();
- nTimes++;
- }
- frm.WriteLine(String.Format(" User (text) command executed {0} times in 1 second.", nTimes));
-
- nTimes = 0;
- cmd.CommandText = "SELECT Foo(10,11)";
- dtStart = Environment.TickCount;
- while (Environment.TickCount - dtStart < 1000)
- {
- cmd.ExecuteNonQuery();
- nTimes++;
- }
- frm.WriteLine(String.Format(" UserFunction command executed {0} times in 1 second.", nTimes));
-
- nTimes = 0;
- cmd.CommandText = "SELECT ABS(1)";
- dtStart = Environment.TickCount;
- while (Environment.TickCount - dtStart < 1000)
- {
- cmd.ExecuteNonQuery();
- nTimes++;
- }
- frm.WriteLine(String.Format(" Intrinsic command executed {0} times in 1 second.", nTimes));
-
- nTimes = 0;
- cmd.CommandText = "SELECT lower('FOO')";
- dtStart = Environment.TickCount;
- while (Environment.TickCount - dtStart < 1000)
- {
- cmd.ExecuteNonQuery();
- nTimes++;
- }
- frm.WriteLine(String.Format(" Intrin (txt) command executed {0} times in 1 second.", nTimes));
-
- nTimes = 0;
- cmd.CommandText = "SELECT 1";
- dtStart = Environment.TickCount;
- while (Environment.TickCount - dtStart < 1000)
- {
- cmd.ExecuteNonQuery();
- nTimes++;
- }
- frm.WriteLine(String.Format(" Raw Value command executed {0} times in 1 second.", nTimes));
- }
- }
-
- internal void IterationTest(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- int dtStart;
- int dtEnd;
- int nCount;
- long n;
-
- cmd.CommandText = "SELECT Foo(ID, ID) FROM TestCase";
- cmd.Prepare();
- dtStart = Environment.TickCount;
- nCount = 0;
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- while (rd.Read())
- {
- n = rd.GetInt64(0);
- nCount++;
- }
- dtEnd = Environment.TickCount;
- }
- frm.WriteLine(String.Format(" User Function iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart)));
-
- cmd.CommandText = "SELECT ID FROM TestCase";
- cmd.Prepare();
- dtStart = Environment.TickCount;
- nCount = 0;
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- while (rd.Read())
- {
- n = rd.GetInt64(0);
- nCount++;
- }
- dtEnd = Environment.TickCount;
- }
- frm.WriteLine(String.Format(" Raw iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart)));
-
- cmd.CommandText = "SELECT ABS(ID) FROM TestCase";
- cmd.Prepare();
- dtStart = Environment.TickCount;
- nCount = 0;
- using (DbDataReader rd = cmd.ExecuteReader())
- {
- while (rd.Read())
- {
- n = rd.GetInt64(0);
- nCount++;
- }
- dtEnd = Environment.TickCount;
- }
- frm.WriteLine(String.Format(" Intrinsic Function iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart)));
-
- }
- }
-
- // Causes the user-defined aggregate to be iterated through
- internal void UserAggregate(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- int dtStart;
- int n = 0;
- int nCount;
-
- cmd.CommandText = "SELECT MyCount(*) FROM TestCase";
-
- nCount = 0;
- dtStart = Environment.TickCount;
- while (Environment.TickCount - dtStart < 1000)
- {
- n = Convert.ToInt32(cmd.ExecuteScalar());
- nCount++;
- }
- if (n != 2003) throw new ArgumentOutOfRangeException("Unexpected count");
- frm.WriteLine(String.Format(" UserAggregate executed {0} times in 1 second.", nCount));
- }
- }
-
- // Causes the user-defined collation sequence to be iterated through
- internal void UserCollation(DbConnection cnn)
- {
- using (DbCommand cmd = cnn.CreateCommand())
- {
- // Using a default collating sequence in descending order, "Param Field3" will appear at the top
- // and "Field3" will be next, followed by a NULL. Our user-defined collating sequence will
- // deliberately place them out of order so Field3 is first.
- cmd.CommandText = "SELECT Field3 FROM TestCase ORDER BY Field3 COLLATE MYSEQUENCE DESC";
- string s = (string)cmd.ExecuteScalar();
- if (s != "Field3") throw new ArgumentOutOfRangeException("MySequence didn't sort properly");
- }
- }
- }
-}
+ }
+
+ total++;
+ try { CreateTable(cnn); frm.WriteLine("SUCCESS - CreateTable"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - CreateTable"); failed++; }
+
+ total++;
+ try { DataTypeTest(cnn); frm.WriteLine("SUCCESS - DataType Test"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - DataType Test"); failed++; }
+
+ total++;
+ try { FullTextTest(cnn); frm.WriteLine("SUCCESS - Full Text Search"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - Full Text Search"); failed++; }
+
+ total++;
+ try { KeyInfoTest(cnn); frm.WriteLine("SUCCESS - KeyInfo Fetch"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - KeyInfo Fetch"); failed++; }
+
+ total++;
+ try { InsertTable(cnn); frm.WriteLine("SUCCESS - InsertTable"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - InsertTable"); failed++; }
+
+ total++;
+ try { VerifyInsert(cnn); frm.WriteLine("SUCCESS - VerifyInsert"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - VerifyInsert"); failed++; }
+
+ total++;
+ try { CoersionTest(cnn); frm.WriteLine("FAIL - CoersionTest"); failed++; }
+ catch (Exception) { frm.WriteLine("SUCCESS - CoersionTest"); passed++; }
+
+ total++;
+ try { ParameterizedInsert(cnn); frm.WriteLine("SUCCESS - ParameterizedInsert"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - ParameterizedInsert"); failed++; }
+
+ total++;
+ try { BinaryInsert(cnn); frm.WriteLine("SUCCESS - BinaryInsert"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - BinaryInsert"); failed++; }
+
+ total++;
+ try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - VerifyBinaryData"); failed++; }
+
+ total++;
+ try { LockTest(cnn); frm.WriteLine("SUCCESS - LockTest"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - LockTest"); failed++; }
+
+ total++;
+ try { ParameterizedInsertMissingParams(cnn); frm.WriteLine("FAIL - ParameterizedInsertMissingParams"); failed++; }
+ catch (Exception) { frm.WriteLine("SUCCESS - ParameterizedInsertMissingParams"); passed++; }
+
+ total++;
+ try { InsertMany(cnn, false); frm.WriteLine("SUCCESS - InsertMany"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - InsertMany"); failed++; }
+
+ total++;
+ try { InsertMany(cnn, true); frm.WriteLine("SUCCESS - InsertManyWithIdentityFetch"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - InsertManyWithIdentityFetch"); failed++; }
+
+ total++;
+ try { FastInsertMany(cnn); frm.WriteLine("SUCCESS - FastInsertMany"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - FastInsertMany"); failed++; }
+
+ total++;
+ try { IterationTest(cnn); frm.WriteLine("SUCCESS - Iteration Test"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - Iteration Test"); failed++; }
+
+ total++;
+ try { UserFunction(cnn); frm.WriteLine("SUCCESS - UserFunction"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - UserFunction"); failed++; }
+
+ total++;
+ try { UserAggregate(cnn); frm.WriteLine("SUCCESS - UserAggregate"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - UserAggregate"); failed++; }
+
+ total++;
+ try { UserCollation(cnn); frm.WriteLine("SUCCESS - UserCollation"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - UserCollation"); failed++; }
+
+ total++;
+ try { DropTable(cnn); frm.WriteLine("SUCCESS - DropTable"); passed++; }
+ catch (Exception) { frm.WriteLine("FAIL - DropTable"); failed++; }
+
+ frm.WriteLine("\r\nTests Finished.");
+ frm.WriteLine(String.Format("\r\nCounts: {0} total, {1} passed, {2} failed", total, passed, failed));
+ frm.WriteLine(String.Format("Result: {0}", Succeeded() ? "SUCCESS" : "FAILURE"));
+
+ if (autoClose)
+ frm.Close();
+ }
+
+ internal static void KeyInfoTest(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ // First test against integer primary key (optimized) keyinfo fetch
+ cmd.CommandText = "Create table keyinfotest (id integer primary key, myuniquevalue integer unique not null, myvalue varchar(50))";
+ cmd.ExecuteNonQuery();
+
+ cmd.CommandText = "Select * from keyinfotest";
+ using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
+ {
+ using (DataTable tbl = reader.GetSchemaTable())
+ {
+ if (tbl.Rows.Count != 3) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
+ }
+ }
+
+ cmd.CommandText = "SELECT MyValue FROM keyinfotest";
+ using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
+ {
+ using (DataTable tbl = reader.GetSchemaTable())
+ {
+ if (tbl.Rows.Count != 2) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
+ }
+ }
+
+ cmd.CommandText = "DROP TABLE keyinfotest";
+ cmd.ExecuteNonQuery();
+
+ // Now test against non-integer primary key (unoptimized) subquery keyinfo fetch
+ cmd.CommandText = "Create table keyinfotest (id char primary key, myuniquevalue integer unique not null, myvalue varchar(50))";
+ cmd.ExecuteNonQuery();
+
+ cmd.CommandText = "SELECT MyValue FROM keyinfotest";
+ using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
+ {
+ using (DataTable tbl = reader.GetSchemaTable())
+ {
+ if (tbl.Rows.Count != 2) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
+ }
+ }
+
+ cmd.CommandText = "Select * from keyinfotest";
+ using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
+ {
+ using (DataTable tbl = reader.GetSchemaTable())
+ {
+ if (tbl.Rows.Count != 3) throw new ArgumentOutOfRangeException("Wrong number of columns returned");
+ }
+ }
+
+ // Make sure commandbuilder can generate an update command with the correct parameter count
+ using (DbDataAdapter adp = new SQLiteDataAdapter())
+ using (DbCommandBuilder builder = new SQLiteCommandBuilder())
+ {
+ adp.SelectCommand = cmd;
+ builder.DataAdapter = adp;
+ builder.ConflictOption = ConflictOption.OverwriteChanges;
+
+ using (DbCommand updatecmd = builder.GetUpdateCommand())
+ {
+ if (updatecmd.Parameters.Count != 4)
+ throw new ArgumentOutOfRangeException("Wrong number of parameters in update command!");
+ }
+ }
+ }
+ }
+
+ internal static void DataTypeTest(DbConnection cnn)
+ {
+ DateTime now = DateTime.Now;
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "create table datatypetest(id integer primary key, myvalue, datetimevalue datetime, decimalvalue decimal)";
+ cmd.ExecuteNonQuery();
+
+ cmd.CommandText = "insert into datatypetest(myvalue, datetimevalue, decimalvalue) values(?,?,?)";
+ DbParameter p1 = cmd.CreateParameter();
+ DbParameter p2 = cmd.CreateParameter();
+ DbParameter p3 = cmd.CreateParameter();
+
+ cmd.Parameters.Add(p1);
+ cmd.Parameters.Add(p2);
+ cmd.Parameters.Add(p3);
+
+ p1.Value = 1;
+ p2.Value = DateTime.MinValue;
+ p3.Value = (Decimal)1.05;
+ cmd.ExecuteNonQuery();
+
+ p1.ResetDbType();
+ p2.ResetDbType();
+ p3.ResetDbType();
+
+ p1.Value = "One";
+ p2.Value = "2001-01-01";
+ p3.Value = (Decimal)1.0;
+ cmd.ExecuteNonQuery();
+
+ p1.ResetDbType();
+ p2.ResetDbType();
+ p3.ResetDbType();
+
+ p1.Value = 1.01;
+ p2.Value = now;
+ p3.Value = (Decimal)9.91;
+ cmd.ExecuteNonQuery();
+
+ cmd.CommandText = "select myvalue, datetimevalue, decimalvalue from datatypetest";
+ using (DbDataReader reader = cmd.ExecuteReader())
+ {
+ for (int n = 0; n < 3; n++)
+ {
+ reader.Read();
+ if (reader.GetValue(1).GetType() != reader.GetDateTime(1).GetType()) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).GetType() != reader.GetDecimal(2).GetType()) throw new ArgumentOutOfRangeException();
+
+ switch (n)
+ {
+ case 0:
+ if (reader.GetValue(0).GetType() != typeof(long)) throw new ArgumentOutOfRangeException();
+
+ if (reader.GetValue(0).Equals((long)1) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(1).Equals(DateTime.MinValue) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).Equals((Decimal)1.05) == false) throw new ArgumentOutOfRangeException();
+
+ if (reader.GetInt64(0) != (long)1) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(1).Equals(reader.GetDateTime(1)) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).Equals(reader.GetDecimal(2)) == false) throw new ArgumentOutOfRangeException();
+ break;
+ case 1:
+ if (reader.GetValue(0).GetType() != typeof(string)) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(0).Equals("One") == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(1).Equals(new DateTime(2001, 1, 1)) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).Equals((Decimal)1.0) == false) throw new ArgumentOutOfRangeException();
+
+ if (reader.GetString(0) != "One") throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(1).Equals(reader.GetDateTime(1)) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).Equals(reader.GetDecimal(2)) == false) throw new ArgumentOutOfRangeException();
+ break;
+ case 2:
+ if (reader.GetValue(0).GetType() != typeof(double)) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(0).Equals(1.01) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(1).Equals(now) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).Equals((Decimal)9.91) == false) throw new ArgumentOutOfRangeException();
+
+ if (reader.GetDouble(0) != 1.01) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(1).Equals(reader.GetDateTime(1)) == false) throw new ArgumentOutOfRangeException();
+ if (reader.GetValue(2).Equals(reader.GetDecimal(2)) == false) throw new ArgumentOutOfRangeException();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ internal static void FullTextTest(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "CREATE VIRTUAL TABLE FullText USING FTS3(name, ingredients);";
+ cmd.ExecuteNonQuery();
+
+ string[] names = { "broccoli stew", "pumpkin stew", "broccoli pie", "pumpkin pie" };
+ string[] ingredients = { "broccoli peppers cheese tomatoes", "pumpkin onions garlic celery", "broccoli cheese onions flour", "pumpkin sugar flour butter" };
+ int n;
+
+ cmd.CommandText = "insert into FullText (name, ingredients) values (@name, @ingredient);";
+ DbParameter name = cmd.CreateParameter();
+ DbParameter ingredient = cmd.CreateParameter();
+
+ name.ParameterName = "@name";
+ ingredient.ParameterName = "@ingredient";
+
+ cmd.Parameters.Add(name);
+ cmd.Parameters.Add(ingredient);
+
+ for (n = 0; n < names.Length; n++)
+ {
+ name.Value = names[n];
+ ingredient.Value = ingredients[n];
+
+ cmd.ExecuteNonQuery();
+ }
+
+ cmd.CommandText = "select rowid, name, ingredients from FullText where name match 'pie';";
+
+ int[] rowids = { 3, 4 };
+ n = 0;
+
+ using (DbDataReader reader = cmd.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ if (reader.GetInt64(0) != rowids[n++])
+ throw new ArgumentException("Unexpected rowid returned");
+
+ if (n > rowids.Length) throw new ArgumentException("Too many rows returned");
+ }
+ }
+ }
+ }
+
+ internal void CreateTable(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "CREATE TABLE TestCase (ID integer primary key autoincrement, Field1 Integer, Field2 Float, Field3 VARCHAR(50), Field4 CHAR(10), Field5 DateTime, Field6 Image)";
+ //cmd.CommandText = "CREATE TABLE TestCase (ID bigint primary key identity, Field1 Integer, Field2 Float, Field3 VARCHAR(50), Field4 CHAR(10), Field5 DateTime, Field6 Image)";
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ internal void DropTable(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "DROP TABLE TestCase";
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ internal void InsertTable(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(1, 3.14159, 'Field3', 'Field4', '2005-01-01 13:49:00')";
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ internal void VerifyInsert(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5 FROM TestCase";
+ cmd.Prepare();
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ if (rd.Read())
+ {
+ long Field1 = rd.GetInt64(0);
+ double Field2 = rd.GetDouble(1);
+ string Field3 = rd.GetString(2);
+ string Field4 = rd.GetString(3).TrimEnd();
+ DateTime Field5 = rd.GetDateTime(4);
+
+ if (Field1 != 1) throw new ArgumentOutOfRangeException("Non-Match on Field1");
+ if (Field2 != 3.14159) throw new ArgumentOutOfRangeException("Non-Match on Field2");
+ if (Field3 != "Field3") throw new ArgumentOutOfRangeException("Non-Match on Field3");
+ if (Field4 != "Field4") throw new ArgumentOutOfRangeException("Non-Match on Field4");
+ if (Field5.CompareTo(DateTime.Parse("2005-01-01 13:49:00")) != 0) throw new ArgumentOutOfRangeException("Non-Match on Field5");
+ }
+ else throw new ArgumentOutOfRangeException("No data in table");
+ }
+ }
+ }
+
+ internal void CoersionTest(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "SELECT Field1, Field2, Field3, Field4, Field5, 'A', 1, 1 + 1, 3.14159 FROM TestCase";
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ if (rd.Read())
+ {
+ object Field1 = rd.GetInt32(0);
+ object Field2 = rd.GetDouble(1);
+ object Field3 = rd.GetString(2);
+ object Field4 = rd.GetString(3).TrimEnd();
+ object Field5 = rd.GetDateTime(4);
+
+ // The next statement should cause an exception
+ Field1 = rd.GetString(0);
+ Field2 = rd.GetString(1);
+ Field3 = rd.GetString(2);
+ Field4 = rd.GetString(3);
+ Field5 = rd.GetString(4);
+
+ Field1 = rd.GetInt32(0);
+ Field2 = rd.GetInt32(1);
+ Field3 = rd.GetInt32(2);
+ Field4 = rd.GetInt32(3);
+ Field5 = rd.GetInt32(4);
+
+ Field1 = rd.GetDecimal(0);
+ Field2 = rd.GetDecimal(1);
+ Field3 = rd.GetDecimal(2);
+ Field4 = rd.GetDecimal(3);
+ Field5 = rd.GetDecimal(4);
+ }
+ else throw new ArgumentOutOfRangeException("No data in table");
+ }
+ }
+ }
+
+ internal void ParameterizedInsert(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(?,?,?,?,?)";
+ DbParameter Field1 = cmd.CreateParameter();
+ DbParameter Field2 = cmd.CreateParameter();
+ DbParameter Field3 = cmd.CreateParameter();
+ DbParameter Field4 = cmd.CreateParameter();
+ DbParameter Field5 = cmd.CreateParameter();
+
+ Field1.Value = 2;
+ Field2.Value = 3.14159;
+ Field3.Value = "Param Field3";
+ Field4.Value = "Field4 Par";
+ Field5.Value = DateTime.Now;
+
+ cmd.Parameters.Add(Field1);
+ cmd.Parameters.Add(Field2);
+ cmd.Parameters.Add(Field3);
+ cmd.Parameters.Add(Field4);
+ cmd.Parameters.Add(Field5);
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ internal void BinaryInsert(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "INSERT INTO TestCase(Field6) VALUES(?)";
+ DbParameter Field6 = cmd.CreateParameter();
+
+ byte[] b = new byte[4000];
+ b[0] = 1;
+ b[100] = 2;
+ b[1000] = 3;
+ b[2000] = 4;
+ b[3000] = 5;
+
+ Field6.Value = b;
+
+ cmd.Parameters.Add(Field6);
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ internal void VerifyBinaryData(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "SELECT Field6 FROM TestCase WHERE Field6 IS NOT NULL";
+ byte[] b = new byte[4000];
+
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ if (rd.Read() == false) throw new ArgumentOutOfRangeException();
+
+ rd.GetBytes(0, 0, b, 0, 4000);
+
+ if (b[0] != 1) throw new ArgumentException();
+ if (b[100] != 2) throw new ArgumentException();
+ if (b[1000] != 3) throw new ArgumentException();
+ if (b[2000] != 4) throw new ArgumentException();
+ if (b[3000] != 5) throw new ArgumentException();
+ }
+ }
+ }
+
+ internal static void LockTest(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "SELECT Field6 FROM TestCase WHERE Field6 IS NOT NULL";
+ byte[] b = new byte[4000];
+
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ if (rd.Read() == false) throw new ArgumentOutOfRangeException();
+
+ rd.GetBytes(0, 0, b, 0, 4000);
+
+ if (b[0] != 1) throw new ArgumentException();
+ if (b[100] != 2) throw new ArgumentException();
+ if (b[1000] != 3) throw new ArgumentException();
+ if (b[2000] != 4) throw new ArgumentException();
+ if (b[3000] != 5) throw new ArgumentException();
+
+ using (DbConnection clone = (DbConnection)((ICloneable)cnn).Clone())
+ {
+ using (DbCommand newcmd = clone.CreateCommand())
+ {
+ newcmd.CommandText = "DELETE FROM TestCase WHERE Field6 IS NULL";
+ newcmd.CommandTimeout = 2;
+ int cmdStart = Environment.TickCount;
+ int cmdEnd;
+
+ try
+ {
+ newcmd.ExecuteNonQuery(); // should fail because there's a reader on the database
+ throw new ArgumentException(); // If we got here, the test failed
+ }
+ catch
+ {
+ cmdEnd = Environment.TickCount;
+ if (cmdEnd - cmdStart < 2000 || cmdEnd - cmdStart > 3000)
+ throw new ArgumentException(); // Didn't wait the right amount of time
+ }
+ }
+ }
+ }
+ }
+ }
+
+ internal void ParameterizedInsertMissingParams(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "INSERT INTO TestCase(Field1, Field2, Field3, Field4, Field5) VALUES(?,?,?,?,?)";
+ DbParameter Field1 = cmd.CreateParameter();
+ DbParameter Field2 = cmd.CreateParameter();
+ DbParameter Field3 = cmd.CreateParameter();
+ DbParameter Field4 = cmd.CreateParameter();
+ DbParameter Field5 = cmd.CreateParameter();
+
+ Field1.DbType = System.Data.DbType.Int32;
+
+ Field1.Value = 2;
+ Field2.Value = 3.14159;
+ Field3.Value = "Field3 Param";
+ Field4.Value = "Field4 Par";
+ Field5.Value = DateTime.Now;
+
+ cmd.Parameters.Add(Field1);
+ cmd.Parameters.Add(Field2);
+ cmd.Parameters.Add(Field3);
+ cmd.Parameters.Add(Field4);
+
+ // Assertion here, not enough parameters
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ // Utilizes the SQLiteCommandBuilder, which in turn utilizes SQLiteDataReader's GetSchemaTable() functionality
+ internal void InsertMany(DbConnection cnn, bool bWithIdentity)
+ {
+ int nmax = 1000;
+
+ using (DbTransaction dbTrans = cnn.BeginTransaction())
+ {
+ using (DbDataAdapter adp = new SQLiteDataAdapter())
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.Transaction = dbTrans;
+ cmd.CommandText = "SELECT * FROM TestCase WHERE 1=2";
+ adp.SelectCommand = cmd;
+
+ using (DbCommandBuilder bld = new SQLiteCommandBuilder())
+ {
+ bld.DataAdapter = adp;
+ using (adp.InsertCommand = (SQLiteCommand)((ICloneable)bld.GetInsertCommand()).Clone())
+ {
+ bld.DataAdapter = null;
+ if (bWithIdentity)
+ {
+ adp.InsertCommand.CommandText += ";SELECT last_insert_rowid() AS [ID]";
+ adp.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
+ }
+
+ using (DataTable tbl = new DataTable())
+ {
+ adp.Fill(tbl);
+ for (int n = 0; n < nmax; n++)
+ {
+ DataRow row = tbl.NewRow();
+ row[1] = n + nmax;
+ tbl.Rows.Add(row);
+ }
+
+ frm.Write(String.Format(" InsertMany{0} ({1} rows) Begins ... ", (bWithIdentity == true) ? "WithIdentityFetch" : " ", nmax));
+ int dtStart = Environment.TickCount;
+ adp.Update(tbl);
+ int dtEnd = Environment.TickCount;
+ dtEnd -= dtStart;
+ frm.Write(String.Format("Ends in {0} ms ... ", (dtEnd)));
+
+ dtStart = Environment.TickCount;
+ dbTrans.Commit();
+ dtEnd = Environment.TickCount;
+ dtEnd -= dtStart;
+ frm.WriteLine(String.Format("Commits in {0} ms", (dtEnd)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ internal void FastInsertMany(DbConnection cnn)
+ {
+ using (DbTransaction dbTrans = cnn.BeginTransaction())
+ {
+ int dtStart;
+ int dtEnd;
+
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ cmd.CommandText = "INSERT INTO TestCase(Field1) VALUES(?)";
+ DbParameter Field1 = cmd.CreateParameter();
+
+ cmd.Parameters.Add(Field1);
+
+ frm.WriteLine(String.Format(" Fast insert using parameters and prepared statement\r\n -> (10,000 rows) Begins ... "));
+ dtStart = Environment.TickCount;
+ for (int n = 0; n < 10000; n++)
+ {
+ Field1.Value = n + 100000;
+ cmd.ExecuteNonQuery();
+ }
+
+ dtEnd = Environment.TickCount;
+ dtEnd -= dtStart;
+ frm.Write(String.Format(" -> Ends in {0} ms ... ", (dtEnd)));
+ }
+
+ dtStart = Environment.TickCount;
+ dbTrans.Rollback();
+ dtEnd = Environment.TickCount;
+ dtEnd -= dtStart;
+ frm.WriteLine(String.Format("Rolled back in {0} ms", (dtEnd)));
+ }
+ }
+
+ // Causes the user-defined function to be called
+ internal void UserFunction(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ int nTimes;
+ int dtStart;
+
+ nTimes = 0;
+ cmd.CommandText = "SELECT Foo('ee','foo')";
+ dtStart = Environment.TickCount;
+ while (Environment.TickCount - dtStart < 1000)
+ {
+ cmd.ExecuteNonQuery();
+ nTimes++;
+ }
+ frm.WriteLine(String.Format(" User (text) command executed {0} times in 1 second.", nTimes));
+
+ nTimes = 0;
+ cmd.CommandText = "SELECT Foo(10,11)";
+ dtStart = Environment.TickCount;
+ while (Environment.TickCount - dtStart < 1000)
+ {
+ cmd.ExecuteNonQuery();
+ nTimes++;
+ }
+ frm.WriteLine(String.Format(" UserFunction command executed {0} times in 1 second.", nTimes));
+
+ nTimes = 0;
+ cmd.CommandText = "SELECT ABS(1)";
+ dtStart = Environment.TickCount;
+ while (Environment.TickCount - dtStart < 1000)
+ {
+ cmd.ExecuteNonQuery();
+ nTimes++;
+ }
+ frm.WriteLine(String.Format(" Intrinsic command executed {0} times in 1 second.", nTimes));
+
+ nTimes = 0;
+ cmd.CommandText = "SELECT lower('FOO')";
+ dtStart = Environment.TickCount;
+ while (Environment.TickCount - dtStart < 1000)
+ {
+ cmd.ExecuteNonQuery();
+ nTimes++;
+ }
+ frm.WriteLine(String.Format(" Intrin (txt) command executed {0} times in 1 second.", nTimes));
+
+ nTimes = 0;
+ cmd.CommandText = "SELECT 1";
+ dtStart = Environment.TickCount;
+ while (Environment.TickCount - dtStart < 1000)
+ {
+ cmd.ExecuteNonQuery();
+ nTimes++;
+ }
+ frm.WriteLine(String.Format(" Raw Value command executed {0} times in 1 second.", nTimes));
+ }
+ }
+
+ internal void IterationTest(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ int dtStart;
+ int dtEnd;
+ int nCount;
+ long n;
+
+ cmd.CommandText = "SELECT Foo(ID, ID) FROM TestCase";
+ cmd.Prepare();
+ dtStart = Environment.TickCount;
+ nCount = 0;
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ while (rd.Read())
+ {
+ n = rd.GetInt64(0);
+ nCount++;
+ }
+ dtEnd = Environment.TickCount;
+ }
+ frm.WriteLine(String.Format(" User Function iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart)));
+
+ cmd.CommandText = "SELECT ID FROM TestCase";
+ cmd.Prepare();
+ dtStart = Environment.TickCount;
+ nCount = 0;
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ while (rd.Read())
+ {
+ n = rd.GetInt64(0);
+ nCount++;
+ }
+ dtEnd = Environment.TickCount;
+ }
+ frm.WriteLine(String.Format(" Raw iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart)));
+
+ cmd.CommandText = "SELECT ABS(ID) FROM TestCase";
+ cmd.Prepare();
+ dtStart = Environment.TickCount;
+ nCount = 0;
+ using (DbDataReader rd = cmd.ExecuteReader())
+ {
+ while (rd.Read())
+ {
+ n = rd.GetInt64(0);
+ nCount++;
+ }
+ dtEnd = Environment.TickCount;
+ }
+ frm.WriteLine(String.Format(" Intrinsic Function iteration of {0} records in {1} ms", nCount, (dtEnd - dtStart)));
+
+ }
+ }
+
+ // Causes the user-defined aggregate to be iterated through
+ internal void UserAggregate(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ int dtStart;
+ int n = 0;
+ int nCount;
+
+ cmd.CommandText = "SELECT MyCount(*) FROM TestCase";
+
+ nCount = 0;
+ dtStart = Environment.TickCount;
+ while (Environment.TickCount - dtStart < 1000)
+ {
+ n = Convert.ToInt32(cmd.ExecuteScalar());
+ nCount++;
+ }
+ if (n != 2003) throw new ArgumentOutOfRangeException("Unexpected count");
+ frm.WriteLine(String.Format(" UserAggregate executed {0} times in 1 second.", nCount));
+ }
+ }
+
+ // Causes the user-defined collation sequence to be iterated through
+ internal void UserCollation(DbConnection cnn)
+ {
+ using (DbCommand cmd = cnn.CreateCommand())
+ {
+ // Using a default collating sequence in descending order, "Param Field3" will appear at the top
+ // and "Field3" will be next, followed by a NULL. Our user-defined collating sequence will
+ // deliberately place them out of order so Field3 is first.
+ cmd.CommandText = "SELECT Field3 FROM TestCase ORDER BY Field3 COLLATE MYSEQUENCE DESC";
+ string s = (string)cmd.ExecuteScalar();
+ if (s != "Field3") throw new ArgumentOutOfRangeException("MySequence didn't sort properly");
+ }
+ }
+ }
+}