diff --git a/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/db.go b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/db.go new file mode 100644 index 0000000000..a92cd6e8eb --- /dev/null +++ b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/models.go b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/models.go new file mode 100644 index 0000000000..49d3f59b52 --- /dev/null +++ b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/models.go @@ -0,0 +1,16 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package querytest + +import ( + "database/sql" +) + +type User struct { + ID int64 + FullName sql.NullString + EmailAddress sql.NullString + CreatedAt sql.NullString +} diff --git a/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/query.sql.go new file mode 100644 index 0000000000..69e858e68f --- /dev/null +++ b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/go/query.sql.go @@ -0,0 +1,60 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const insertUser = `-- name: InsertUser :exec +INSERT INTO Users (full_name, "EmailAddress", created_at) +VALUES (?, ?, ?) +` + +type InsertUserParams struct { + FullName sql.NullString + EmailAddress sql.NullString + CreatedAt sql.NullString +} + +func (q *Queries) InsertUser(ctx context.Context, arg InsertUserParams) error { + _, err := q.db.ExecContext(ctx, insertUser, arg.FullName, arg.EmailAddress, arg.CreatedAt) + return err +} + +const selectUsers = `-- name: SelectUsers :many +SELECT id, full_name, "EmailAddress", created_at +FROM Users +` + +func (q *Queries) SelectUsers(ctx context.Context) ([]User, error) { + rows, err := q.db.QueryContext(ctx, selectUsers) + if err != nil { + return nil, err + } + defer rows.Close() + var items []User + for rows.Next() { + var i User + if err := rows.Scan( + &i.ID, + &i.FullName, + &i.EmailAddress, + &i.CreatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/query.sql b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/query.sql new file mode 100644 index 0000000000..79989697e8 --- /dev/null +++ b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/query.sql @@ -0,0 +1,7 @@ +-- name: InsertUser :exec +INSERT INTO Users (full_name, "EmailAddress", created_at) +VALUES (?, ?, ?); + +-- name: SelectUsers :many +SELECT id, full_name, "EmailAddress", created_at +FROM Users; diff --git a/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/schema.sql b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/schema.sql new file mode 100644 index 0000000000..5b8af0ac35 --- /dev/null +++ b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/schema.sql @@ -0,0 +1,10 @@ +-- Test ALTER TABLE operations with mixed case table and column names +-- Verifies consistent handling of case sensitivity in DDL operations +CREATE TABLE Users (id integer primary key, name text, "Email" text); + +-- Test renaming columns with different case formats +ALTER TABLE Users RENAME COLUMN name TO full_name; +ALTER TABLE Users RENAME COLUMN "Email" TO "EmailAddress"; + +-- Test adding a simple column +ALTER TABLE Users ADD COLUMN created_at text; diff --git a/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/sqlc.json new file mode 100644 index 0000000000..cd66df063b --- /dev/null +++ b/internal/endtoend/testdata/ddl_alter_table_case_sensitivity/sqlite/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "sqlite", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/ddl_drop_table/sqlite/schema.sql b/internal/endtoend/testdata/ddl_drop_table/sqlite/schema.sql index d2ea37a051..c0b8f00ed1 100644 --- a/internal/endtoend/testdata/ddl_drop_table/sqlite/schema.sql +++ b/internal/endtoend/testdata/ddl_drop_table/sqlite/schema.sql @@ -1,2 +1,8 @@ CREATE TABLE venues (hi text); -DROP TABLE venues; \ No newline at end of file +DROP TABLE venues; + +CREATE TABLE Authors (id integer); +DROP TABLE Authors; + +CREATE TABLE "Books" (id integer); +DROP TABLE "Books"; diff --git a/internal/endtoend/testdata/quoted_names_complex/sqlite/go/db.go b/internal/endtoend/testdata/quoted_names_complex/sqlite/go/db.go new file mode 100644 index 0000000000..a92cd6e8eb --- /dev/null +++ b/internal/endtoend/testdata/quoted_names_complex/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/quoted_names_complex/sqlite/go/models.go b/internal/endtoend/testdata/quoted_names_complex/sqlite/go/models.go new file mode 100644 index 0000000000..c157a76881 --- /dev/null +++ b/internal/endtoend/testdata/quoted_names_complex/sqlite/go/models.go @@ -0,0 +1,5 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package querytest diff --git a/internal/endtoend/testdata/quoted_names_complex/sqlite/go/query.sql.go b/internal/endtoend/testdata/quoted_names_complex/sqlite/go/query.sql.go new file mode 100644 index 0000000000..079840519b --- /dev/null +++ b/internal/endtoend/testdata/quoted_names_complex/sqlite/go/query.sql.go @@ -0,0 +1,19 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const placeholder = `-- name: Placeholder :exec +SELECT 1 +` + +func (q *Queries) Placeholder(ctx context.Context) error { + _, err := q.db.ExecContext(ctx, placeholder) + return err +} diff --git a/internal/endtoend/testdata/quoted_names_complex/sqlite/query.sql b/internal/endtoend/testdata/quoted_names_complex/sqlite/query.sql new file mode 100644 index 0000000000..6520aef4b6 --- /dev/null +++ b/internal/endtoend/testdata/quoted_names_complex/sqlite/query.sql @@ -0,0 +1,2 @@ +-- name: Placeholder :exec +SELECT 1; diff --git a/internal/endtoend/testdata/quoted_names_complex/sqlite/schema.sql b/internal/endtoend/testdata/quoted_names_complex/sqlite/schema.sql new file mode 100644 index 0000000000..fc6a73756e --- /dev/null +++ b/internal/endtoend/testdata/quoted_names_complex/sqlite/schema.sql @@ -0,0 +1,22 @@ +-- Test complex quoted table and column names with special characters +-- Covers spaces, hyphens, uppercase, and mixed operations +CREATE TABLE "user profiles" (id integer primary key, data text); +CREATE TABLE "ORDERS" (id integer primary key, data text); +CREATE TABLE products (id integer primary key, data text); +CREATE TABLE "item-categories" (id integer primary key, data text); + +-- Test ALTER statements with complex identifiers +ALTER TABLE "user profiles" RENAME COLUMN data TO "profile data"; +ALTER TABLE "ORDERS" RENAME TO "customer_orders"; +ALTER TABLE products ADD COLUMN "Price Info" text; + +-- Test mixed case operations across different statement types +INSERT INTO "user profiles" ("profile data") VALUES ('test data'); +UPDATE "ORDERS" SET data = 'updated' WHERE id = 1; +DELETE FROM products WHERE id = 1; + +-- Test DROP with various identifier formats +DROP TABLE "user profiles"; +DROP TABLE "customer_orders"; +DROP TABLE "item-categories"; +DROP TABLE products; diff --git a/internal/endtoend/testdata/quoted_names_complex/sqlite/sqlc.json b/internal/endtoend/testdata/quoted_names_complex/sqlite/sqlc.json new file mode 100644 index 0000000000..cd66df063b --- /dev/null +++ b/internal/endtoend/testdata/quoted_names_complex/sqlite/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "sqlite", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/db.go b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/db.go new file mode 100644 index 0000000000..a92cd6e8eb --- /dev/null +++ b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/models.go b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/models.go new file mode 100644 index 0000000000..aaf95d8522 --- /dev/null +++ b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/models.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package querytest + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name sql.NullString +} + +type Book struct { + ID int64 + Title sql.NullString +} + +type User struct { + ID int64 + Name sql.NullString +} diff --git a/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/query.sql.go b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/query.sql.go new file mode 100644 index 0000000000..f083e84a02 --- /dev/null +++ b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/go/query.sql.go @@ -0,0 +1,183 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const deleteAuthor = `-- name: DeleteAuthor :exec +DELETE FROM "Authors" WHERE id = ? +` + +func (q *Queries) DeleteAuthor(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteAuthor, id) + return err +} + +const deleteBook = `-- name: DeleteBook :exec +DELETE FROM Books WHERE id = ? +` + +func (q *Queries) DeleteBook(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteBook, id) + return err +} + +const deleteUser = `-- name: DeleteUser :exec +DELETE FROM users WHERE id = ? +` + +func (q *Queries) DeleteUser(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteUser, id) + return err +} + +const deleteUserMixedCase = `-- name: DeleteUserMixedCase :exec +DELETE FROM users WHERE id = ? +` + +func (q *Queries) DeleteUserMixedCase(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteUserMixedCase, id) + return err +} + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name FROM "Authors" WHERE id = ? +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRowContext(ctx, getAuthor, id) + var i Author + err := row.Scan(&i.ID, &i.Name) + return i, err +} + +const getBook = `-- name: GetBook :one +SELECT id, title FROM Books WHERE id = ? +` + +func (q *Queries) GetBook(ctx context.Context, id int64) (Book, error) { + row := q.db.QueryRowContext(ctx, getBook, id) + var i Book + err := row.Scan(&i.ID, &i.Title) + return i, err +} + +const getUser = `-- name: GetUser :one +SELECT id, name FROM users WHERE id = ? +` + +func (q *Queries) GetUser(ctx context.Context, id int64) (User, error) { + row := q.db.QueryRowContext(ctx, getUser, id) + var i User + err := row.Scan(&i.ID, &i.Name) + return i, err +} + +const getUserMixedCase = `-- name: GetUserMixedCase :one +SELECT id, name FROM users WHERE id = ? +` + +func (q *Queries) GetUserMixedCase(ctx context.Context, id int64) (User, error) { + row := q.db.QueryRowContext(ctx, getUserMixedCase, id) + var i User + err := row.Scan(&i.ID, &i.Name) + return i, err +} + +const insertAuthor = `-- name: InsertAuthor :exec +INSERT INTO "Authors" (name) VALUES (?) +` + +func (q *Queries) InsertAuthor(ctx context.Context, name sql.NullString) error { + _, err := q.db.ExecContext(ctx, insertAuthor, name) + return err +} + +const insertBook = `-- name: InsertBook :exec +INSERT INTO Books (title) VALUES (?) +` + +func (q *Queries) InsertBook(ctx context.Context, title sql.NullString) error { + _, err := q.db.ExecContext(ctx, insertBook, title) + return err +} + +const insertUser = `-- name: InsertUser :exec +INSERT INTO users (name) VALUES (?) +` + +func (q *Queries) InsertUser(ctx context.Context, name sql.NullString) error { + _, err := q.db.ExecContext(ctx, insertUser, name) + return err +} + +const insertUserMixedCase = `-- name: InsertUserMixedCase :exec +INSERT INTO users (name) VALUES (?) +` + +func (q *Queries) InsertUserMixedCase(ctx context.Context, name sql.NullString) error { + _, err := q.db.ExecContext(ctx, insertUserMixedCase, name) + return err +} + +const updateAuthor = `-- name: UpdateAuthor :exec +UPDATE "Authors" SET name = ? WHERE id = ? +` + +type UpdateAuthorParams struct { + Name sql.NullString + ID int64 +} + +func (q *Queries) UpdateAuthor(ctx context.Context, arg UpdateAuthorParams) error { + _, err := q.db.ExecContext(ctx, updateAuthor, arg.Name, arg.ID) + return err +} + +const updateBook = `-- name: UpdateBook :exec +UPDATE Books SET title = ? WHERE id = ? +` + +type UpdateBookParams struct { + Title sql.NullString + ID int64 +} + +func (q *Queries) UpdateBook(ctx context.Context, arg UpdateBookParams) error { + _, err := q.db.ExecContext(ctx, updateBook, arg.Title, arg.ID) + return err +} + +const updateUser = `-- name: UpdateUser :exec +UPDATE users SET name = ? WHERE id = ? +` + +type UpdateUserParams struct { + Name sql.NullString + ID int64 +} + +func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) error { + _, err := q.db.ExecContext(ctx, updateUser, arg.Name, arg.ID) + return err +} + +const updateUserMixedCase = `-- name: UpdateUserMixedCase :exec +UPDATE users SET name = ? WHERE id = ? +` + +type UpdateUserMixedCaseParams struct { + Name sql.NullString + ID int64 +} + +func (q *Queries) UpdateUserMixedCase(ctx context.Context, arg UpdateUserMixedCaseParams) error { + _, err := q.db.ExecContext(ctx, updateUserMixedCase, arg.Name, arg.ID) + return err +} diff --git a/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/query.sql b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/query.sql new file mode 100644 index 0000000000..6312be57a5 --- /dev/null +++ b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/query.sql @@ -0,0 +1,47 @@ +-- name: InsertUser :exec +INSERT INTO users (name) VALUES (?); + +-- name: InsertUserMixedCase :exec +INSERT INTO users (name) VALUES (?); + +-- name: InsertAuthor :exec +INSERT INTO "Authors" (name) VALUES (?); + +-- name: InsertBook :exec +INSERT INTO Books (title) VALUES (?); + +-- name: UpdateUser :exec +UPDATE users SET name = ? WHERE id = ?; + +-- name: UpdateUserMixedCase :exec +UPDATE users SET name = ? WHERE id = ?; + +-- name: UpdateAuthor :exec +UPDATE "Authors" SET name = ? WHERE id = ?; + +-- name: UpdateBook :exec +UPDATE Books SET title = ? WHERE id = ?; + +-- name: DeleteUser :exec +DELETE FROM users WHERE id = ?; + +-- name: DeleteUserMixedCase :exec +DELETE FROM users WHERE id = ?; + +-- name: DeleteAuthor :exec +DELETE FROM "Authors" WHERE id = ?; + +-- name: DeleteBook :exec +DELETE FROM Books WHERE id = ?; + +-- name: GetUser :one +SELECT * FROM users WHERE id = ?; + +-- name: GetUserMixedCase :one +SELECT * FROM users WHERE id = ?; + +-- name: GetAuthor :one +SELECT * FROM "Authors" WHERE id = ?; + +-- name: GetBook :one +SELECT * FROM Books WHERE id = ?; diff --git a/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/schema.sql b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/schema.sql new file mode 100644 index 0000000000..3c43ae1d5d --- /dev/null +++ b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/schema.sql @@ -0,0 +1,13 @@ +-- Test table name case sensitivity handling across different SQLite operations +-- Create tables with different case patterns to verify consistent name resolution +CREATE TABLE users (id integer primary key, name text); +CREATE TABLE "Authors" (id integer primary key, name text); +CREATE TABLE Books (id integer primary key, title text); + +-- Create a temporary table to test drop operations +CREATE TABLE temp_orders (id integer primary key); +DROP TABLE temp_orders; + +-- Create another temp table with quoted identifier +CREATE TABLE "temp_products" (id integer primary key); +DROP TABLE "temp_products"; diff --git a/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/sqlc.json b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/sqlc.json new file mode 100644 index 0000000000..cd66df063b --- /dev/null +++ b/internal/endtoend/testdata/table_name_case_sensitivity/sqlite/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "sqlite", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index e86dd8ac82..658a9d7f33 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -42,7 +42,7 @@ func NewIdentifier(t string) *ast.String { func (c *cc) convertAlter_table_stmtContext(n *parser.Alter_table_stmtContext) ast.Node { if n.RENAME_() != nil { if newTable, ok := n.New_table_name().(*parser.New_table_nameContext); ok { - name := newTable.Any_name().GetText() + name := identifier(newTable.Any_name().GetText()) return &ast.RenameTableStmt{ Table: parseTableName(n), NewName: &name, @@ -50,11 +50,11 @@ func (c *cc) convertAlter_table_stmtContext(n *parser.Alter_table_stmtContext) a } if newCol, ok := n.GetNew_column_name().(*parser.Column_nameContext); ok { - name := newCol.Any_name().GetText() + name := identifier(newCol.Any_name().GetText()) return &ast.RenameColumnStmt{ Table: parseTableName(n), Col: &ast.ColumnRef{ - Name: n.GetOld_column_name().GetText(), + Name: identifier(n.GetOld_column_name().GetText()), }, NewName: &name, } @@ -254,7 +254,7 @@ func (c *cc) convertDelete_stmtContext(n Delete_stmt) ast.Node { func (c *cc) convertDrop_stmtContext(n *parser.Drop_stmtContext) ast.Node { if n.TABLE_() != nil || n.VIEW_() != nil { name := ast.TableName{ - Name: n.Any_name().GetText(), + Name: identifier(n.Any_name().GetText()), } if n.Schema_name() != nil { name.Schema = n.Schema_name().GetText() @@ -1035,7 +1035,7 @@ func (c *cc) convertUpdate_stmtContext(n Update_stmt) ast.Node { } relations := &ast.List{} - tableName := n.Qualified_table_name().GetText() + tableName := identifier(n.Qualified_table_name().GetText()) rel := ast.RangeVar{ Relname: &tableName, Location: n.GetStart().GetStart(),