Explorar o código

Merge branch 'web-stack' of Tilo15/Invercargill-Sql into master

Billy Barrow hai 1 mes
pai
achega
65fd516c0f
Modificáronse 2 ficheiros con 83 adicións e 2 borrados
  1. 14 2
      src/sqlite/sqlite-result-enumerable.vala
  2. 69 0
      src/tests/sqlite-test.vala

+ 14 - 2
src/sqlite/sqlite-result-enumerable.vala

@@ -97,10 +97,22 @@ namespace InvercargillSql {
                 return true;
                 return true;
             }
             }
             
             
-            // No more rows - cleanup
-            _stmt.reset();
             _enumerated = true;
             _enumerated = true;
             row = null;
             row = null;
+            
+            if (result != Sqlite.DONE) {
+                string message = _connection.get_database().errmsg();
+                _stmt.reset();
+                error(
+                    "SqliteResultEnumerable: statement step failed with sqlite code %d (%s): %s — treated as a hard read failure, not end-of-rows",
+                    result,
+                    result == Sqlite.BUSY ? "SQLITE_BUSY" : result == Sqlite.LOCKED ? "SQLITE_LOCKED" : "unexpected status",
+                    message
+                );
+            }
+            
+            // Clean end of rows
+            _stmt.reset();
             return false;
             return false;
         }
         }
         
         

+ 69 - 0
src/tests/sqlite-test.vala

@@ -10,6 +10,18 @@ using Sqlite;
 public int main(string[] args) {
 public int main(string[] args) {
     print("=== SQLite Integration Tests ===\n\n");
     print("=== SQLite Integration Tests ===\n\n");
     
     
+    if (args.length > 1 && args[1] == "--busy-child") {
+        try {
+            run_busy_child();
+        }
+        catch (Error e) {
+            printerr("busy-child unexpected failure: %s\n", e.message);
+            return 1;
+        }
+        printerr("busy-child completed without hitting the step failure\n");
+        return 1;
+    }
+    
     try {
     try {
         // Element type conversion tests
         // Element type conversion tests
         print("--- Integer Element Tests ---\n");
         print("--- Integer Element Tests ---\n");
@@ -42,6 +54,7 @@ public int main(string[] args) {
         print("\n--- Complex Integration Tests ---\n");
         print("\n--- Complex Integration Tests ---\n");
         test_mixed_type_table();
         test_mixed_type_table();
         test_element_assignable_types();
         test_element_assignable_types();
+        test_step_failure_is_fatal_not_empty(args);
         
         
         print("\n=== All SQLite integration tests passed! ===\n");
         print("\n=== All SQLite integration tests passed! ===\n");
         return 0;
         return 0;
@@ -51,6 +64,62 @@ public int main(string[] args) {
     }
     }
 }
 }
 
 
+void run_busy_child() throws SqlError {
+    string path = GLib.Path.build_filename(
+        GLib.Environment.get_tmp_dir(), "invercargill-sql-busy-test.db");
+    GLib.FileUtils.remove(path);
+    GLib.FileUtils.remove(path + "-wal");
+    GLib.FileUtils.remove(path + "-shm");
+    string cs = "sqlite://" + path;
+
+    var locker = ConnectionFactory.create_and_open(cs);
+    locker.execute("PRAGMA journal_mode=DELETE");
+    locker.execute("CREATE TABLE busy_t (id INTEGER PRIMARY KEY, v TEXT)");
+    locker.execute("INSERT INTO busy_t (v) VALUES ('one')");
+    locker.execute("INSERT INTO busy_t (v) VALUES ('two')");
+
+    var reader = ConnectionFactory.create_and_open(cs);
+    reader.execute("PRAGMA journal_mode=DELETE");
+    var command = reader.create_command("SELECT v FROM busy_t");
+    reader.execute("PRAGMA busy_timeout=1");
+
+    locker.execute("BEGIN EXCLUSIVE");
+
+    var results = command.execute_query();
+    uint count = 0;
+    foreach (var row in results) {
+        count++;
+    }
+    print("rows=%u\n", count);
+}
+
+void test_step_failure_is_fatal_not_empty(string[] args) throws Error {
+    print("Test: step failure is fatal, not empty results... ");
+
+    string exe;
+    if (GLib.Path.is_absolute(args[0])) {
+        exe = args[0];
+    }
+    else {
+        exe = GLib.Path.build_filename(GLib.Environment.get_current_dir(), args[0]);
+    }
+    assert_true(GLib.File.new_for_path(exe).query_exists());
+    string[] argv = { exe, "--busy-child" };
+    int status;
+    string child_stdout;
+    string child_stderr;
+    GLib.Process.spawn_sync(
+        null, argv, GLib.Environ.get(),
+        GLib.SpawnFlags.SEARCH_PATH,
+        null, out child_stdout, out child_stderr, out status);
+
+    assert_true(GLib.Process.if_signaled(status));
+    assert_true(child_stderr.contains("SQLITE_BUSY"));
+    assert_false(child_stdout.contains("rows="));
+
+    print("passed\n");
+}
+
 // ============================================================================
 // ============================================================================
 // Integer Element Tests
 // Integer Element Tests
 // ============================================================================
 // ============================================================================