Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 18, 2025

  • Understand the issue: sqlite3_changes() returns the previous change count for DDL statements
  • Add test to reproduce the issue
  • Fix SqliteDataReader.NextResult() to use sqlite3_total_changes() before and after statement execution
  • Run existing tests to verify no regressions (Microsoft.Data.Sqlite.Tests: 680 passed, EFCore.Sqlite.Tests: 838 passed)
  • Request code review
  • Run CodeQL security scan
  • Address PR review feedback (round 1):
    • Renamed handle to connectionHandle
    • Changed int changes to var changes
    • Added explanatory comment about sqlite3_changes() issue
    • Split test into two separate tests with descriptive names
    • Updated tests to use using blocks and assert from within
  • Address PR review feedback (round 2):
    • Changed both tests to use using (var connection = ...) blocks for consistency
    • Removed unnecessary connection.ExecuteNonQuery("CREATE TABLE foo...") line
    • Changed DROP TABLE foo to DROP TABLE IF EXISTS foo to avoid error
  • Address PR review feedback (round 3):
    • Removed unnecessary DROP TABLE IF EXISTS foo statement from test
  • Address PR review feedback (round 4):
    • Removed if condition and always call AddChanges(changes) even when changes is 0
    • Updated test expectation: CREATE INDEX now returns 0 instead of -1
Original prompt

This section details on the original issue you should resolve

<issue_title>Microsoft.Data.Sqlite incorrectly adds to RecordsAffected for additional statements</issue_title>
<issue_description>### Bug description

When doing a multi-statement transaction using Microsoft.Data.Sqlite that causes records to be affected, the provider seems to add the number of records affected on to the total for any statements that don't affect any records. This keeps happening for subsequent statements until there's another statement which affects records, at which point that new number is added for this statement and all subsequent statements that don't affect any records. The result is an incorrect number of records affected at the end of the statement. The repro code below shows this issue; when a DROP statement is added, records affected is incorrectly incremented by 1, the number of records affected by the most recent statement that affected records. When a CREATE statement is also added the results again incorrectly increments by 1.

Your code

using Microsoft.Data.Sqlite;

namespace SqliteBugRepro;

internal class Program {
	private const string _dbFile = "testDb.sqlite";
	private const string _createAndInsert = "CREATE TABLE foo(bar TEXT NOT NULL); CREATE TABLE xyz(aaa TEXT NOT NULL); INSERT INTO foo(bar) VALUES('baz'); INSERT INTO foo(bar) VALUES('baz2');";
	private const string _drop = "DROP TABLE xyz;";
	private const string _create = "CREATE TABLE xyz(aaa TEXT NOT NULL);";

	static void Main(string[] args) {
		Console.WriteLine("Creating new SQLite DB.");
		CreateSqliteDb();

		int recordsAffected;

		Console.WriteLine("Doing DB commands (no DROP).");
		recordsAffected = DoCommandsNoDrop();

		Console.WriteLine($"Records affected: {recordsAffected}"); // 2

		Console.WriteLine("Creating new SQLite DB.");
		CreateSqliteDb();

		Console.WriteLine("Doing DB commands (with DROP).");
		recordsAffected = DoCommandsWithDrop();

		Console.WriteLine($"Records affected: {recordsAffected}"); // 3 (???)

		Console.WriteLine("Creating new SQLite DB.");
		CreateSqliteDb();

		Console.WriteLine("Doing DB commands (with DROP and CREATE).");
		recordsAffected = DoCommandsWithDropAndCreate();

		Console.WriteLine($"Records affected: {recordsAffected}"); // 4 (???)
	}

	private static void CreateSqliteDb() {
		File.WriteAllBytes(_dbFile, []);
	}

	private static int DoCommandsNoDrop() {
		var connStringBuilder = new SqliteConnectionStringBuilder {
			Pooling = false,
			DataSource = _dbFile
		};

		using var conn = new SqliteConnection(connStringBuilder.ConnectionString);
		conn.Open();

		using var cmd = conn.CreateCommand();
		cmd.CommandText = $"{_createAndInsert}";
		using var reader = cmd.ExecuteReader();

		do {
			var currentRecordsAffected = reader.RecordsAffected;
		}
		while (reader.NextResult());

		return reader.RecordsAffected;
	}

	private static int DoCommandsWithDrop() {
		var connStringBuilder = new SqliteConnectionStringBuilder {
			Pooling = false,
			DataSource = _dbFile
		};

		using var conn = new SqliteConnection(connStringBuilder.ConnectionString);
		conn.Open();

		using var cmd = conn.CreateCommand();
		cmd.CommandText = $"{_createAndInsert} {_drop}";
		using var reader = cmd.ExecuteReader();

		do {
			var currentRecordsAffected = reader.RecordsAffected;
		}
		while (reader.NextResult());

		return reader.RecordsAffected;
	}

	private static int DoCommandsWithDropAndCreate() {
		var connStringBuilder = new SqliteConnectionStringBuilder {
			Pooling = false,
			DataSource = _dbFile
		};

		using var conn = new SqliteConnection(connStringBuilder.ConnectionString);
		conn.Open();

		using var cmd = conn.CreateCommand();
		cmd.CommandText = $"{_createAndInsert} {_drop} {_create}";
		using var reader = cmd.ExecuteReader();

		do {
			var currentRecordsAffected = reader.RecordsAffected;
		}
		while (reader.NextResult());

		return reader.RecordsAffected;
	}
}

Stack traces


Microsoft.Data.Sqlite version

9.0.2

Target framework

.NET 9.0

Operating system

Windows 10</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix incorrect RecordsAffected calculation in Microsoft.Data.Sqlite Fix RecordsAffected incorrectly accumulating counts from DDL statements Dec 18, 2025
Copilot AI requested a review from cincuranet December 18, 2025 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Microsoft.Data.Sqlite incorrectly adds to RecordsAffected for additional statements

2 participants