Repository: sqlc-dev/sqlc
Pull request #3553 (2024-08-18 07:53:53)

Fix incorrect generate model names for "metadata" suffix
Fix [Table "bonuses" and "product_metadata" incorrectly generates model name. #3552](https://github.com/sqlc-dev/sqlc/issues/3552)


Patch:
diff --git a/docs/reference/config.md b/docs/reference/config.md
index 2629babf4..9d334834f 100644
--- a/docs/reference/config.md
+++ b/docs/reference/config.md
@@ -135,6 +135,8 @@ The `gen` mapping supports the following keys:
   - Output directory for generated code.
 - `sql_package`:
   - Either `pgx/v4`, `pgx/v5` or `database/sql`. Defaults to `database/sql`.
+- `sql_driver`:
+  - Either `github.com/jackc/pgx/v4`, `github.com/jackc/pgx/v5`, `github.com/lib/pq` or `github.com/go-sql-driver/mysql`. No defaults. Required if query annotation `:copyfrom` is used.
 - `emit_db_tags`:
   - If true, add DB tags to generated structs. Defaults to `false`.
 - `emit_prepared_queries`:
diff --git a/docs/reference/query-annotations.md b/docs/reference/query-annotations.md
index 0045f49fa..4fabe05aa 100644
--- a/docs/reference/query-annotations.md
+++ b/docs/reference/query-annotations.md
@@ -222,3 +222,9 @@ func (b *CreateBookBatchResults) Close() error {
 	//...
 }
 ```
+
+## `:copyfrom`
+
+__NOTE: This command is driver and package specific, see [how to insert](../howto/insert.md#using-copyfrom)
+
+This command is used to insert rows a lot faster than sequential inserts.
diff --git a/docs/tutorials/getting-started-sqlite.md b/docs/tutorials/getting-started-sqlite.md
index f855e41af..b5dea7ee3 100644
--- a/docs/tutorials/getting-started-sqlite.md
+++ b/docs/tutorials/getting-started-sqlite.md
@@ -128,7 +128,7 @@ import (
 	"log"
 	"reflect"
 
-	_ "github.com/mattn/go-sqlite3"
+	_ "modernc.org/sqlite"
 
 	"tutorial.sqlc.dev/app/tutorial"
 )
@@ -139,7 +139,7 @@ var ddl string
 func run() error {
 	ctx := context.Background()
 
-	db, err := sql.Open("sqlite3", ":memory:")
+	db, err := sql.Open("sqlite", ":memory:")
 	if err != nil {
 		return err
 	}
diff --git a/internal/codegen/golang/reserved.go b/internal/codegen/golang/reserved.go
index fee711c57..0461c4a2d 100644
--- a/internal/codegen/golang/reserved.go
+++ b/internal/codegen/golang/reserved.go
@@ -59,6 +59,8 @@ func IsReserved(s string) bool {
 		return true
 	case "var":
 		return true
+	case "q":
+		return true
 	default:
 		return false
 	}
diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go
index 02d80bc48..29c06fb28 100644
--- a/internal/engine/sqlite/convert.go
+++ b/internal/engine/sqlite/convert.go
@@ -203,7 +203,7 @@ type Delete_stmt interface {
 func (c *cc) convertDelete_stmtContext(n Delete_stmt) ast.Node {
 	if qualifiedName, ok := n.Qualified_table_name().(*parser.Qualified_table_nameContext); ok {
 
-		tableName := qualifiedName.Table_name().GetText()
+		tableName := identifier(qualifiedName.Table_name().GetText())
 		relation := &ast.RangeVar{
 			Relname: &tableName,
 		}
@@ -854,7 +854,7 @@ func (c *cc) convertReturning_caluseContext(n parser.IReturning_clauseContext) *
 }
 
 func (c *cc) convertInsert_stmtContext(n *parser.Insert_stmtContext) ast.Node {
-	tableName := n.Table_name().GetText()
+	tableName := identifier(n.Table_name().GetText())
 	rel := &ast.RangeVar{
 		Relname: &tableName,
 	}
@@ -936,7 +936,7 @@ func (c *cc) convertTablesOrSubquery(n []parser.ITable_or_subqueryContext) []ast
 		}
 
 		if from.Table_name() != nil {
-			rel := from.Table_name().GetText()
+			rel := identifier(from.Table_name().GetText())
 			rv := &ast.RangeVar{
 				Relname:  &rel,
 				Location: from.GetStart().GetStart(),
diff --git a/internal/engine/sqlite/utils.go b/internal/engine/sqlite/utils.go
index f3b5ee289..874d53ab4 100644
--- a/internal/engine/sqlite/utils.go
+++ b/internal/engine/sqlite/utils.go
@@ -12,7 +12,7 @@ type tableNamer interface {
 
 func parseTableName(c tableNamer) *ast.TableName {
 	name := ast.TableName{
-		Name: c.Table_name().GetText(),
+		Name: identifier(c.Table_name().GetText()),
 	}
 	if c.Schema_name() != nil {
 		name.Schema = c.Schema_name().GetText()
diff --git a/internal/inflection/singular.go b/internal/inflection/singular.go
index edac92760..64e042a6a 100644
--- a/internal/inflection/singular.go
+++ b/internal/inflection/singular.go
@@ -43,5 +43,10 @@ func Singular(s SingularParams) string {
 	if strings.ToLower(s.Name) == "waves" {
 		return "wave"
 	}
+
+	if strings.ToLower(s.Name) == "metadata" {
+		return "metadata"
+	}
+
 	return upstream.Singular(s.Name)
 }


Test patch:
diff --git a/internal/endtoend/testdata/inflection/mysql/go/models.go b/internal/endtoend/testdata/inflection/mysql/go/models.go
index cc60f3658..1fa48e00f 100644
--- a/internal/endtoend/testdata/inflection/mysql/go/models.go
+++ b/internal/endtoend/testdata/inflection/mysql/go/models.go
@@ -12,6 +12,10 @@ type Campus struct {
 	ID string
 }
 
+type ProductMetadatum struct {
+	ID string
+}
+
 type ProductMetum struct {
 	ID string
 }
diff --git a/internal/endtoend/testdata/inflection/mysql/go/query.sql.go b/internal/endtoend/testdata/inflection/mysql/go/query.sql.go
index f6282ccee..c33eea852 100644
--- a/internal/endtoend/testdata/inflection/mysql/go/query.sql.go
+++ b/internal/endtoend/testdata/inflection/mysql/go/query.sql.go
@@ -9,6 +9,33 @@ import (
 	"context"
 )
 
+const getProductMetadata = `-- name: GetProductMetadata :many
+SELECT id FROM product_metadata
+`
+
+func (q *Queries) GetProductMetadata(ctx context.Context) ([]string, error) {
+	rows, err := q.db.QueryContext(ctx, getProductMetadata)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []string
+	for rows.Next() {
+		var id string
+		if err := rows.Scan(&id); err != nil {
+			return nil, err
+		}
+		items = append(items, id)
+	}
+	if err := rows.Close(); err != nil {
+		return nil, err
+	}
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
 const listCalories = `-- name: ListCalories :many
 SELECT id FROM calories
 `
diff --git a/internal/endtoend/testdata/inflection/mysql/query.sql b/internal/endtoend/testdata/inflection/mysql/query.sql
index e3917086b..74e1aaf8c 100644
--- a/internal/endtoend/testdata/inflection/mysql/query.sql
+++ b/internal/endtoend/testdata/inflection/mysql/query.sql
@@ -9,3 +9,6 @@ SELECT * FROM product_meta;
 
 /* name: ListCalories :many */
 SELECT * FROM calories;
+
+/* name: GetProductMetadata :many */
+SELECT * FROM product_metadata;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/mysql/schema.sql b/internal/endtoend/testdata/inflection/mysql/schema.sql
index b0d88c869..f7d5c7c2a 100644
--- a/internal/endtoend/testdata/inflection/mysql/schema.sql
+++ b/internal/endtoend/testdata/inflection/mysql/schema.sql
@@ -2,4 +2,4 @@ CREATE TABLE campus (id text not null);
 CREATE TABLE students (id text not null);
 CREATE TABLE product_meta (id text not null);
 CREATE TABLE calories (id text not null);
-
+CREATE TABLE product_metadata (id text not null);
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/models.go b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/models.go
index cc60f3658..1fa48e00f 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/models.go
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/models.go
@@ -12,6 +12,10 @@ type Campus struct {
 	ID string
 }
 
+type ProductMetadatum struct {
+	ID string
+}
+
 type ProductMetum struct {
 	ID string
 }
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/query.sql.go
index 279114491..31a544075 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/query.sql.go
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/go/query.sql.go
@@ -9,6 +9,30 @@ import (
 	"context"
 )
 
+const getProductMetadata = `-- name: GetProductMetadata :many
+SELECT id FROM product_metadata
+`
+
+func (q *Queries) GetProductMetadata(ctx context.Context) ([]string, error) {
+	rows, err := q.db.Query(ctx, getProductMetadata)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []string
+	for rows.Next() {
+		var id string
+		if err := rows.Scan(&id); err != nil {
+			return nil, err
+		}
+		items = append(items, id)
+	}
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
 const listCalories = `-- name: ListCalories :many
 SELECT id FROM calories
 `
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/query.sql
index 6e2828d45..abc0da2ef 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/query.sql
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/query.sql
@@ -9,3 +9,6 @@ SELECT * FROM product_meta;
 
 -- name: ListCalories :many
 SELECT * FROM calories;
+
+-- name: GetProductMetadata :many
+SELECT * FROM product_metadata;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/schema.sql b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/schema.sql
index b0d88c869..ad17ad742 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v4/schema.sql
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v4/schema.sql
@@ -2,4 +2,4 @@ CREATE TABLE campus (id text not null);
 CREATE TABLE students (id text not null);
 CREATE TABLE product_meta (id text not null);
 CREATE TABLE calories (id text not null);
-
+CREATE TABLE product_metadata (id text not null);
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/models.go b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/models.go
index cc60f3658..1fa48e00f 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/models.go
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/models.go
@@ -12,6 +12,10 @@ type Campus struct {
 	ID string
 }
 
+type ProductMetadatum struct {
+	ID string
+}
+
 type ProductMetum struct {
 	ID string
 }
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/query.sql.go
index 279114491..31a544075 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/query.sql.go
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/go/query.sql.go
@@ -9,6 +9,30 @@ import (
 	"context"
 )
 
+const getProductMetadata = `-- name: GetProductMetadata :many
+SELECT id FROM product_metadata
+`
+
+func (q *Queries) GetProductMetadata(ctx context.Context) ([]string, error) {
+	rows, err := q.db.Query(ctx, getProductMetadata)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []string
+	for rows.Next() {
+		var id string
+		if err := rows.Scan(&id); err != nil {
+			return nil, err
+		}
+		items = append(items, id)
+	}
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
 const listCalories = `-- name: ListCalories :many
 SELECT id FROM calories
 `
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/query.sql
index 6e2828d45..abc0da2ef 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/query.sql
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/query.sql
@@ -9,3 +9,6 @@ SELECT * FROM product_meta;
 
 -- name: ListCalories :many
 SELECT * FROM calories;
+
+-- name: GetProductMetadata :many
+SELECT * FROM product_metadata;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/schema.sql
index b0d88c869..ad17ad742 100644
--- a/internal/endtoend/testdata/inflection/postgresql/pgx/v5/schema.sql
+++ b/internal/endtoend/testdata/inflection/postgresql/pgx/v5/schema.sql
@@ -2,4 +2,4 @@ CREATE TABLE campus (id text not null);
 CREATE TABLE students (id text not null);
 CREATE TABLE product_meta (id text not null);
 CREATE TABLE calories (id text not null);
-
+CREATE TABLE product_metadata (id text not null);
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/inflection/postgresql/stdlib/go/models.go
index cc60f3658..1fa48e00f 100644
--- a/internal/endtoend/testdata/inflection/postgresql/stdlib/go/models.go
+++ b/internal/endtoend/testdata/inflection/postgresql/stdlib/go/models.go
@@ -12,6 +12,10 @@ type Campus struct {
 	ID string
 }
 
+type ProductMetadatum struct {
+	ID string
+}
+
 type ProductMetum struct {
 	ID string
 }
diff --git a/internal/endtoend/testdata/inflection/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/inflection/postgresql/stdlib/go/query.sql.go
index f6282ccee..c33eea852 100644
--- a/internal/endtoend/testdata/inflection/postgresql/stdlib/go/query.sql.go
+++ b/internal/endtoend/testdata/inflection/postgresql/stdlib/go/query.sql.go
@@ -9,6 +9,33 @@ import (
 	"context"
 )
 
+const getProductMetadata = `-- name: GetProductMetadata :many
+SELECT id FROM product_metadata
+`
+
+func (q *Queries) GetProductMetadata(ctx context.Context) ([]string, error) {
+	rows, err := q.db.QueryContext(ctx, getProductMetadata)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []string
+	for rows.Next() {
+		var id string
+		if err := rows.Scan(&id); err != nil {
+			return nil, err
+		}
+		items = append(items, id)
+	}
+	if err := rows.Close(); err != nil {
+		return nil, err
+	}
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
 const listCalories = `-- name: ListCalories :many
 SELECT id FROM calories
 `
diff --git a/internal/endtoend/testdata/inflection/postgresql/stdlib/query.sql b/internal/endtoend/testdata/inflection/postgresql/stdlib/query.sql
index 6e2828d45..abc0da2ef 100644
--- a/internal/endtoend/testdata/inflection/postgresql/stdlib/query.sql
+++ b/internal/endtoend/testdata/inflection/postgresql/stdlib/query.sql
@@ -9,3 +9,6 @@ SELECT * FROM product_meta;
 
 -- name: ListCalories :many
 SELECT * FROM calories;
+
+-- name: GetProductMetadata :many
+SELECT * FROM product_metadata;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/inflection/postgresql/stdlib/schema.sql
index b0d88c869..ad17ad742 100644
--- a/internal/endtoend/testdata/inflection/postgresql/stdlib/schema.sql
+++ b/internal/endtoend/testdata/inflection/postgresql/stdlib/schema.sql
@@ -2,4 +2,4 @@ CREATE TABLE campus (id text not null);
 CREATE TABLE students (id text not null);
 CREATE TABLE product_meta (id text not null);
 CREATE TABLE calories (id text not null);
-
+CREATE TABLE product_metadata (id text not null);
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/sqlite/go/models.go b/internal/endtoend/testdata/inflection/sqlite/go/models.go
index cc60f3658..1fa48e00f 100644
--- a/internal/endtoend/testdata/inflection/sqlite/go/models.go
+++ b/internal/endtoend/testdata/inflection/sqlite/go/models.go
@@ -12,6 +12,10 @@ type Campus struct {
 	ID string
 }
 
+type ProductMetadatum struct {
+	ID string
+}
+
 type ProductMetum struct {
 	ID string
 }
diff --git a/internal/endtoend/testdata/inflection/sqlite/go/query.sql.go b/internal/endtoend/testdata/inflection/sqlite/go/query.sql.go
index f6282ccee..c33eea852 100644
--- a/internal/endtoend/testdata/inflection/sqlite/go/query.sql.go
+++ b/internal/endtoend/testdata/inflection/sqlite/go/query.sql.go
@@ -9,6 +9,33 @@ import (
 	"context"
 )
 
+const getProductMetadata = `-- name: GetProductMetadata :many
+SELECT id FROM product_metadata
+`
+
+func (q *Queries) GetProductMetadata(ctx context.Context) ([]string, error) {
+	rows, err := q.db.QueryContext(ctx, getProductMetadata)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []string
+	for rows.Next() {
+		var id string
+		if err := rows.Scan(&id); err != nil {
+			return nil, err
+		}
+		items = append(items, id)
+	}
+	if err := rows.Close(); err != nil {
+		return nil, err
+	}
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
 const listCalories = `-- name: ListCalories :many
 SELECT id FROM calories
 `
diff --git a/internal/endtoend/testdata/inflection/sqlite/query.sql b/internal/endtoend/testdata/inflection/sqlite/query.sql
index e3917086b..74e1aaf8c 100644
--- a/internal/endtoend/testdata/inflection/sqlite/query.sql
+++ b/internal/endtoend/testdata/inflection/sqlite/query.sql
@@ -9,3 +9,6 @@ SELECT * FROM product_meta;
 
 /* name: ListCalories :many */
 SELECT * FROM calories;
+
+/* name: GetProductMetadata :many */
+SELECT * FROM product_metadata;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/inflection/sqlite/schema.sql b/internal/endtoend/testdata/inflection/sqlite/schema.sql
index b0d88c869..ad17ad742 100644
--- a/internal/endtoend/testdata/inflection/sqlite/schema.sql
+++ b/internal/endtoend/testdata/inflection/sqlite/schema.sql
@@ -2,4 +2,4 @@ CREATE TABLE campus (id text not null);
 CREATE TABLE students (id text not null);
 CREATE TABLE product_meta (id text not null);
 CREATE TABLE calories (id text not null);
-
+CREATE TABLE product_metadata (id text not null);
\ No newline at end of file
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/go/models.go b/internal/endtoend/testdata/params_go_keywords/postgresql/go/models.go
index e6e549432..1c6b61b89 100644
--- a/internal/endtoend/testdata/params_go_keywords/postgresql/go/models.go
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/go/models.go
@@ -34,4 +34,5 @@ type GoKeyword struct {
 	Import      pgtype.Text
 	Return      pgtype.Text
 	Var         pgtype.Text
+	Q           pgtype.Text
 }
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go b/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go
index ba0ad8806..8fa0810d6 100644
--- a/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go
@@ -173,6 +173,15 @@ func (q *Queries) KeywordPackage(ctx context.Context, package_ string) error {
 	return err
 }
 
+const keywordQ = `-- name: KeywordQ :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordQ(ctx context.Context, q_ string) error {
+	_, err := q.db.Exec(ctx, keywordQ, q_)
+	return err
+}
+
 const keywordRange = `-- name: KeywordRange :exec
 SELECT $1::text
 `
@@ -434,6 +443,17 @@ func (q *Queries) SelectPackage(ctx context.Context) (pgtype.Text, error) {
 	return package_, err
 }
 
+const selectQ = `-- name: SelectQ :one
+SELECT "q" FROM go_keywords
+`
+
+func (q *Queries) SelectQ(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectQ)
+	var q_ pgtype.Text
+	err := row.Scan(&q_)
+	return q_, err
+}
+
 const selectRange = `-- name: SelectRange :one
 SELECT "range" FROM go_keywords
 `
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql b/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql
index 70796e4e3..bc45b1166 100644
--- a/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql
@@ -73,6 +73,9 @@ SELECT sqlc.arg('return')::text;
 -- name: KeywordVar :exec
 SELECT sqlc.arg('var')::text;
 
+-- name: KeywordQ :exec
+SELECT sqlc.arg('q')::text;
+
 -- name: SelectBreak :one
 SELECT "break" FROM go_keywords;
 
@@ -147,3 +150,6 @@ SELECT "return" FROM go_keywords;
 
 -- name: SelectVar :one
 SELECT "var" FROM go_keywords;
+
+-- name: SelectQ :one
+SELECT "q" FROM go_keywords;
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql b/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql
index 11a04beef..100be5021 100644
--- a/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql
@@ -23,5 +23,6 @@ CREATE TABLE go_keywords (
     "for" TEXT,
     "import" TEXT,
     "return" TEXT,
-    "var" TEXT
+    "var" TEXT,
+    "q" TEXT
 );
diff --git a/internal/endtoend/testdata/quoted_tablename/sqlite/go/db.go b/internal/endtoend/testdata/quoted_tablename/sqlite/go/db.go
new file mode 100644
index 000000000..0ea90b328
--- /dev/null
+++ b/internal/endtoend/testdata/quoted_tablename/sqlite/go/db.go
@@ -0,0 +1,31 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.27.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_tablename/sqlite/go/models.go b/internal/endtoend/testdata/quoted_tablename/sqlite/go/models.go
new file mode 100644
index 000000000..69573be60
--- /dev/null
+++ b/internal/endtoend/testdata/quoted_tablename/sqlite/go/models.go
@@ -0,0 +1,9 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.27.0
+
+package querytest
+
+type User struct {
+	ID string
+}
diff --git a/internal/endtoend/testdata/quoted_tablename/sqlite/go/query.sql.go b/internal/endtoend/testdata/quoted_tablename/sqlite/go/query.sql.go
new file mode 100644
index 000000000..5cb25a79e
--- /dev/null
+++ b/internal/endtoend/testdata/quoted_tablename/sqlite/go/query.sql.go
@@ -0,0 +1,37 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.27.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const testList = `-- name: TestList :many
+SELECT id FROM users
+`
+
+func (q *Queries) TestList(ctx context.Context) ([]string, error) {
+	rows, err := q.db.QueryContext(ctx, testList)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []string
+	for rows.Next() {
+		var id string
+		if err := rows.Scan(&id); err != nil {
+			return nil, err
+		}
+		items = append(items, id)
+	}
+	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/quoted_tablename/sqlite/query.sql b/internal/endtoend/testdata/quoted_tablename/sqlite/query.sql
new file mode 100644
index 000000000..0d3b8e238
--- /dev/null
+++ b/internal/endtoend/testdata/quoted_tablename/sqlite/query.sql
@@ -0,0 +1,2 @@
+-- name: TestList :many
+SELECT * FROM users;
diff --git a/internal/endtoend/testdata/quoted_tablename/sqlite/schema.sql b/internal/endtoend/testdata/quoted_tablename/sqlite/schema.sql
new file mode 100644
index 000000000..078fa24bf
--- /dev/null
+++ b/internal/endtoend/testdata/quoted_tablename/sqlite/schema.sql
@@ -0,0 +1,6 @@
+-- Example queries for sqlc
+CREATE TABLE "users"
+(
+    id TEXT NOT NULL
+);
+
diff --git a/internal/endtoend/testdata/quoted_tablename/sqlite/sqlc.json b/internal/endtoend/testdata/quoted_tablename/sqlite/sqlc.json
new file mode 100644
index 000000000..ea4a23425
--- /dev/null
+++ b/internal/endtoend/testdata/quoted_tablename/sqlite/sqlc.json
@@ -0,0 +1,12 @@
+{
+    "version": "1",
+    "packages": [
+        {
+            "path": "go",
+            "engine": "sqlite",
+            "schema": "schema.sql",
+            "queries": "query.sql",
+            "name": "querytest"
+        }
+    ]
+}
\ No newline at end of file