Skip to content

Commit 37d308c

Browse files
electrolyclaude
andcommitted
Suppress spurious result columns from ALTER TABLE in SQLite 3.52.0
SQLite 3.52.0 uses internal nested SELECTs (sqlite_fail()) for ALTER TABLE constraint validation. These leak through sqlite3_column_count, producing empty result sets that appear as query output. Fix this in QueryCore by using SQLite's own tokenizer to detect ALTER statements and suppressing result collection for them. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 00f34ce commit 37d308c

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

src/SqlNotebookScript/Core/Notebook.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,14 @@ Action onRow
475475

476476
lock (_lock)
477477
{
478+
// SQLite 3.52.0+ uses internal nested SELECTs for ALTER TABLE constraint validation
479+
// (e.g. sqlite_fail()). These leak through sqlite3_column_count, producing spurious
480+
// empty result sets. ALTER TABLE never returns meaningful data.
481+
if (returnResult && GetFirstTokenType(sql) == TokenType.Alter)
482+
{
483+
returnResult = false;
484+
}
485+
478486
using PreparedStatement statement = new(db, sql);
479487
var argArray =
480488
namedArgs != null ? statement.GetArgs(namedArgs)
@@ -489,6 +497,18 @@ public string GetFilePath()
489497
return OriginalFilePath;
490498
}
491499

500+
// Returns the TokenType of the first non-whitespace, non-comment token in sql,
501+
// using SQLite's own tokenizer. Caller must hold _lock.
502+
private static TokenType GetFirstTokenType(string sql)
503+
{
504+
using NativeString sqlNative = new(sql);
505+
using NativeBuffer scratch = new(IntPtr.Size);
506+
var oldPos = 0;
507+
var pos = 0;
508+
var tokenType = GetToken(sqlNative.Ptr, ref oldPos, ref pos, sqlNative.ByteCount, scratch);
509+
return tokenType > 0 ? (TokenType)tokenType : default;
510+
}
511+
492512
public static IReadOnlyList<Token> Tokenize(string input)
493513
{
494514
lock (_lock)

0 commit comments

Comments
 (0)