Index: Doc/Extra/version.html
==================================================================
--- Doc/Extra/version.html
+++ Doc/Extra/version.html
@@ -50,10 +50,11 @@
Check the result of sqlite3_column_name function against NULL.
Return false for the SQLiteParameterCollection.IsSynchronized property because it is not thread-safe.
Raise the static SQLiteConnection.Changed event when any SQLiteCommand, SQLiteDataReader, or CriticalHandle derived object instance is created. Fix for [aba4549801].
Add SQLiteCommand.Execute, SQLiteCommand.ExecuteNonQuery, and SQLiteCommand.ExecuteScalar method overloads that take a CommandBehavior parameter.
Revise how the extra object data is passed to the static SQLiteConnection.Changed event. ** Potentially Incompatible Change **
+ Make sure the database cannot be changed by a query when the CommandBehavior.SchemaOnly flag is used. Fix for [f8dbab8baf]. ** Potentially Incompatible Change **
Include the XML documentation files in the NuGet packages. Fix for [5970d5b0a6].
1.0.88.0 - August 7, 2013
- Various fixes to managed virtual table integration infrastructure.
Index: System.Data.SQLite/SQLiteDataReader.cs
==================================================================
--- System.Data.SQLite/SQLiteDataReader.cs
+++ System.Data.SQLite/SQLiteDataReader.cs
@@ -1237,40 +1237,41 @@
CheckDisposed();
CheckClosed();
if (_throwOnDisposed) SQLiteCommand.Check(_command);
SQLiteStatement stmt = null;
- int fieldCount;
+ int fieldCount;
+ bool schemaOnly = ((_commandBehavior & CommandBehavior.SchemaOnly) != 0);
while (true)
{
if (stmt == null && _activeStatement != null && _activeStatement._sql != null && _activeStatement._sql.IsOpen())
{
- // Reset the previously-executed statement
- _activeStatement._sql.Reset(_activeStatement);
+ // Reset the previously-executed statement
+ if (!schemaOnly) _activeStatement._sql.Reset(_activeStatement);
// If we're only supposed to return a single rowset, step through all remaining statements once until
// they are all done and return false to indicate no more resultsets exist.
if ((_commandBehavior & CommandBehavior.SingleResult) != 0)
{
for (; ; )
{
stmt = _command.GetStatement(_activeStatementIndex + 1);
if (stmt == null) break;
- _activeStatementIndex++;
-
- stmt._sql.Step(stmt);
+ _activeStatementIndex++;
+
+ if (!schemaOnly) stmt._sql.Step(stmt);
if (stmt._sql.ColumnCount(stmt) == 0)
{
if (_rowsAffected == -1) _rowsAffected = 0;
int changes = 0;
if (stmt.TryGetChanges(ref changes))
_rowsAffected += changes;
else
return false;
- }
- stmt._sql.Reset(stmt); // Gotta reset after every step to release any locks and such!
+ }
+ if (!schemaOnly) stmt._sql.Reset(stmt); // Gotta reset after every step to release any locks and such!
}
return false;
}
}
@@ -1285,34 +1286,34 @@
if (_readingState < 1)
_readingState = 1;
_activeStatementIndex++;
- fieldCount = stmt._sql.ColumnCount(stmt);
-
+ fieldCount = stmt._sql.ColumnCount(stmt);
+
// If the statement is not a select statement or we're not retrieving schema only, then perform the initial step
- if ((_commandBehavior & CommandBehavior.SchemaOnly) == 0 || fieldCount == 0)
- {
- if (stmt._sql.Step(stmt))
- {
- _readingState = -1;
- }
- else if (fieldCount == 0) // No rows returned, if fieldCount is zero, skip to the next statement
- {
- if (_rowsAffected == -1) _rowsAffected = 0;
- int changes = 0;
- if (stmt.TryGetChanges(ref changes))
- _rowsAffected += changes;
- else
- return false;
- stmt._sql.Reset(stmt);
- continue; // Skip this command and move to the next, it was not a row-returning resultset
- }
- else // No rows, fieldCount is non-zero so stop here
- {
- _readingState = 1; // This command returned columns but no rows, so return true, but HasRows = false and Read() returns false
- }
+ if (!schemaOnly || (fieldCount == 0))
+ {
+ if (!schemaOnly && stmt._sql.Step(stmt))
+ {
+ _readingState = -1;
+ }
+ else if (fieldCount == 0) // No rows returned, if fieldCount is zero, skip to the next statement
+ {
+ if (_rowsAffected == -1) _rowsAffected = 0;
+ int changes = 0;
+ if (stmt.TryGetChanges(ref changes))
+ _rowsAffected += changes;
+ else
+ return false;
+ if (!schemaOnly) stmt._sql.Reset(stmt);
+ continue; // Skip this command and move to the next, it was not a row-returning resultset
+ }
+ else // No rows, fieldCount is non-zero so stop here
+ {
+ _readingState = 1; // This command returned columns but no rows, so return true, but HasRows = false and Read() returns false
+ }
}
// Ahh, we found a row-returning resultset eligible to be returned!
_activeStatement = stmt;
_fieldCount = fieldCount;
@@ -1360,11 +1361,14 @@
/// True if a new row was successfully loaded and is ready for processing
public override bool Read()
{
CheckDisposed();
CheckClosed();
- if (_throwOnDisposed) SQLiteCommand.Check(_command);
+ if (_throwOnDisposed) SQLiteCommand.Check(_command);
+
+ if ((_commandBehavior & CommandBehavior.SchemaOnly) != 0)
+ return false;
if (_readingState == -1) // First step was already done at the NextResult() level, so don't step again, just return true.
{
_readingState = 0;
return true;
Index: Tests/common.eagle
==================================================================
--- Tests/common.eagle
+++ Tests/common.eagle
@@ -917,10 +917,28 @@
# NOTE: Is the specified database file name really an in-memory database?
#
return [expr {$fileName eq ":memory:" || \
[string range $fileName 0 12] eq "file::memory:"}]
}
+
+ proc isTableInDb { name {varName db} } {
+ #
+ # NOTE: Refer to the specified variable (e.g. "db") in the context of our
+ # caller. It contains the database connection handle that will be
+ # used to execute the query used to determine if the named table is
+ # present in that database.
+ #
+ upvar 1 $varName db
+
+ #
+ # NOTE: Execute the SQL query against the sqlite_master table to check if
+ # the named table is present and return non-zero if it is.
+ #
+ return [expr {[sql execute -execute scalar $db \
+ "SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = ?;" \
+ [list param1 String $name]] > 0}]
+ }
proc executeSql { sql {execute none} {fileName ""} } {
if {[string length $fileName] == 0} then {set fileName :memory:}
setupDb $fileName "" "" "" "" "" false false false false memDb
ADDED Tests/tkt-f8dbab8baf.eagle
Index: Tests/tkt-f8dbab8baf.eagle
==================================================================
--- /dev/null
+++ Tests/tkt-f8dbab8baf.eagle
@@ -0,0 +1,143 @@
+###############################################################################
+#
+# tkt-f8dbab8baf.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 tkt-f8dbab8baf-1.1 {SchemaOnly with CREATE TABLE} -setup {
+ setupDb [set fileName tkt-f8dbab8baf-1.1.db]
+} -body {
+ sql execute -execute reader -format none -behavior SchemaOnly $db \
+ "CREATE TABLE t1(x);"
+
+ isTableInDb t1
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+{False}}
+
+###############################################################################
+
+runTest {test tkt-f8dbab8baf-1.2 {SchemaOnly with ALTER TABLE} -setup {
+ setupDb [set fileName tkt-f8dbab8baf-1.2.db]
+} -body {
+ sql execute $db "CREATE TABLE t1(x);"
+
+ sql execute -execute reader -format none -behavior SchemaOnly $db \
+ "ALTER TABLE t1 RENAME TO t2;"
+
+ list [isTableInDb t1] [isTableInDb t2]
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+{True False}}
+
+###############################################################################
+
+runTest {test tkt-f8dbab8baf-1.3 {SchemaOnly with DROP TABLE} -setup {
+ setupDb [set fileName tkt-f8dbab8baf-1.3.db]
+} -body {
+ sql execute $db "CREATE TABLE t1(x);"
+
+ sql execute -execute reader -format none -behavior SchemaOnly $db \
+ "DROP TABLE t1;"
+
+ isTableInDb t1
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+{True}}
+
+###############################################################################
+
+runTest {test tkt-f8dbab8baf-1.4 {CREATE/SELECT success} -setup {
+ setupDb [set fileName tkt-f8dbab8baf-1.4.db]
+} -body {
+ sql execute -execute reader $db {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 (x) VALUEs(1);
+ SELECT x FROM t1;
+ }
+
+ list [isTableInDb t1] \
+ [expr {[info exists rows(count)] ? $rows(count) : -1}] \
+ [expr {[info exists rows(names)] ? $rows(names) : ""}]
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain rows db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+{True 1 x}}
+
+###############################################################################
+
+runTest {test tkt-f8dbab8baf-1.5 {SchemaOnly CREATE/SELECT success} -setup {
+ setupDb [set fileName tkt-f8dbab8baf-1.5.db]
+} -body {
+ sql execute $db "CREATE TABLE t1(x);"
+ sql execute $db "INSERT INTO t1 (x) VALUEs(1);"
+ sql execute -execute reader -behavior SchemaOnly $db "SELECT x FROM t1;"
+
+ list [isTableInDb t1] \
+ [expr {[info exists rows(count)] ? $rows(count) : -1}] \
+ [expr {[info exists rows(names)] ? $rows(names) : ""}]
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain rows db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \
+{True 0 x}}
+
+###############################################################################
+
+runTest {test tkt-f8dbab8baf-1.6 {SchemaOnly CREATE/SELECT failure} -setup {
+ setupDb [set fileName tkt-f8dbab8baf-1.6.db]
+} -body {
+ sql execute -execute reader -format none -behavior SchemaOnly $db \
+ "CREATE TABLE t1(x); SELECT x FROM t1;"
+
+ list [isTableInDb t1] \
+ [expr {[info exists rows(count)] ? $rows(count) : -1}] \
+ [expr {[info exists rows(names)] ? $rows(names) : ""}]
+} -cleanup {
+ cleanupDb $fileName
+
+ unset -nocomplain rows db fileName
+} -constraints \
+{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
+-returnCodes 1 -match regexp -result [string map [list \n \r\n] \
+{^System\.Data\.SQLite\.SQLiteException \(0x80004005\): SQL logic error or\
+missing database
+no such table: t1.*$}]}
+
+###############################################################################
+
+runSQLiteTestEpilogue
+runTestEpilogue
Index: readme.htm
==================================================================
--- readme.htm
+++ readme.htm
@@ -195,10 +195,11 @@
- Check the result of sqlite3_column_name function against NULL.
- Return false for the SQLiteParameterCollection.IsSynchronized property because it is not thread-safe.
- Raise the static SQLiteConnection.Changed event when any SQLiteCommand, SQLiteDataReader, or CriticalHandle derived object instance is created. Fix for [aba4549801].
- Add SQLiteCommand.Execute, SQLiteCommand.ExecuteNonQuery, and SQLiteCommand.ExecuteScalar method overloads that take a CommandBehavior parameter.
- Revise how the extra object data is passed to the static SQLiteConnection.Changed event. ** Potentially Incompatible Change **
+ - Make sure the database cannot be changed by a query when the CommandBehavior.SchemaOnly flag is used. Fix for [f8dbab8baf]. ** Potentially Incompatible Change **
- Include the XML documentation files in the NuGet packages. Fix for [5970d5b0a6].
1.0.88.0 - August 7, 2013
Index: www/news.wiki
==================================================================
--- www/news.wiki
+++ www/news.wiki
@@ -11,10 +11,11 @@
Check the result of sqlite3_column_name function against NULL.
Return false for the SQLiteParameterCollection.IsSynchronized property because it is not thread-safe.
Raise the static SQLiteConnection.Changed event when any SQLiteCommand, SQLiteDataReader, or CriticalHandle derived object instance is created. Fix for [aba4549801].
Add SQLiteCommand.Execute, SQLiteCommand.ExecuteNonQuery, and SQLiteCommand.ExecuteScalar method overloads that take a CommandBehavior parameter.
Revise how the extra object data is passed to the static SQLiteConnection.Changed event. ** Potentially Incompatible Change **
+ Make sure the database cannot be changed by a query when the CommandBehavior.SchemaOnly flag is used. Fix for [f8dbab8baf]. ** Potentially Incompatible Change **
Include the XML documentation files in the NuGet packages. Fix for [5970d5b0a6].
1.0.88.0 - August 7, 2013