From 033470713807c59433a2b60ed681c95326391063 Mon Sep 17 00:00:00 2001 From: User Date: Sun, 22 Feb 2026 08:46:46 +0800 Subject: [PATCH] fix(sqlite): normalize column names in ALTER TABLE ADD/DROP COLUMN Fixes #4307 When ALTER TABLE ADD COLUMN or DROP COLUMN statements use mixed-case column names (e.g., barBaz), the column name was stored in the catalog with its original case. However, SELECT queries normalize all unquoted identifiers to lowercase via the identifier() function, causing a mismatch and 'column does not exist' errors. This fix ensures ALTER TABLE ADD/DROP COLUMN also normalize column names using identifier(), matching the behavior of CREATE TABLE and SELECT queries. This aligns with SQLite's case-insensitive identifier handling. Changes: - internal/engine/sqlite/convert.go: Apply identifier() to column names in ALTER TABLE ADD COLUMN and DROP COLUMN handlers - internal/engine/sqlite/catalog_test.go: Add regression test for mixed-case column names in ALTER TABLE ADD COLUMN --- internal/engine/sqlite/catalog_test.go | 32 ++++++++++++++++++++++++++ internal/engine/sqlite/convert.go | 4 ++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/internal/engine/sqlite/catalog_test.go b/internal/engine/sqlite/catalog_test.go index bf6dcd8316..89c29d5962 100644 --- a/internal/engine/sqlite/catalog_test.go +++ b/internal/engine/sqlite/catalog_test.go @@ -82,6 +82,38 @@ func TestUpdate(t *testing.T) { }, }, }, + { + // Regression test for #4307: mixed-case column name in ALTER TABLE ADD COLUMN + ` + CREATE TABLE foo (id INTEGER NOT NULL, xYz INTEGER NOT NULL DEFAULT 0); + ALTER TABLE foo ADD COLUMN barBaz TEXT NOT NULL DEFAULT ''; + `, + &catalog.Schema{ + Name: "main", + Tables: []*catalog.Table{ + { + Rel: &ast.TableName{Name: "foo"}, + Columns: []*catalog.Column{ + { + Name: "id", + Type: ast.TypeName{Name: "INTEGER"}, + IsNotNull: true, + }, + { + Name: "xyz", + Type: ast.TypeName{Name: "INTEGER"}, + IsNotNull: true, + }, + { + Name: "barbaz", + Type: ast.TypeName{Name: "TEXT"}, + IsNotNull: true, + }, + }, + }, + }, + }, + }, { ` CREATE TABLE foo (bar text); diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index e9868f5be6..7e7c3c7864 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -67,7 +67,7 @@ func (c *cc) convertAlter_table_stmtContext(n *parser.Alter_table_stmtContext) a Table: parseTableName(n), Cmds: &ast.List{}, } - name := def.Column_name().GetText() + name := identifier(def.Column_name().GetText()) stmt.Cmds.Items = append(stmt.Cmds.Items, &ast.AlterTableCmd{ Name: &name, Subtype: ast.AT_AddColumn, @@ -88,7 +88,7 @@ func (c *cc) convertAlter_table_stmtContext(n *parser.Alter_table_stmtContext) a Table: parseTableName(n), Cmds: &ast.List{}, } - name := n.Column_name(0).GetText() + name := identifier(n.Column_name(0).GetText()) stmt.Cmds.Items = append(stmt.Cmds.Items, &ast.AlterTableCmd{ Name: &name, Subtype: ast.AT_DropColumn,