diff --git a/internal/compiler/resolve.go b/internal/compiler/resolve.go index b1fbb1990e..dba2e7cecc 100644 --- a/internal/compiler/resolve.go +++ b/internal/compiler/resolve.go @@ -67,7 +67,38 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, continue } // If the table name doesn't exist, first check if it's a CTE - if _, qcerr := qc.GetTable(fqn); qcerr != nil { + catTable, qcerr := qc.GetTable(fqn) + if qcerr != nil { + return nil, err + } + + // If it's a CTE, add it to the alias map and add its columns to + // the type map. This is to allow us to resolve references to the + // CTE's columns in a query. + aliasMap[fqn.Name] = fqn + if rv.Alias != nil { + aliasMap[*rv.Alias.Aliasname] = fqn + } + + catCols := make([]*catalog.Column, 0, len(catTable.Columns)) + for _, col := range catTable.Columns { + catCols = append(catCols, &catalog.Column{ + Name: col.Name, + Type: ast.TypeName{Name: col.DataType}, + IsNotNull: col.NotNull, + IsUnsigned: col.Unsigned, + IsArray: col.IsArray, + ArrayDims: col.ArrayDims, + Comment: col.Comment, + Length: col.Length, + }) + } + + err = indexTable(catalog.Table{ + Rel: catTable.Rel, + Columns: catCols, + }) + if err != nil { return nil, err } continue diff --git a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/query.sql.go index 271ac35651..24f9ce475b 100644 --- a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/query.sql.go @@ -7,8 +7,6 @@ package querytest import ( "context" - - "github.com/jackc/pgx/v5/pgtype" ) const badQuery = `-- name: BadQuery :exec @@ -28,7 +26,7 @@ FROM WHERE c1.name = $1 ` -func (q *Queries) BadQuery(ctx context.Context, dollar_1 pgtype.Text) error { - _, err := q.db.Exec(ctx, badQuery, dollar_1) +func (q *Queries) BadQuery(ctx context.Context, name string) error { + _, err := q.db.Exec(ctx, badQuery, name) return err } diff --git a/internal/endtoend/testdata/cte_recursive_union/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_recursive_union/postgresql/pgx/go/query.sql.go index aa74cb5221..9b3b44647a 100644 --- a/internal/endtoend/testdata/cte_recursive_union/postgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/cte_recursive_union/postgresql/pgx/go/query.sql.go @@ -7,8 +7,6 @@ package querytest import ( "context" - - "github.com/jackc/pgx/v5/pgtype" ) const listCaseIntentHistory = `-- name: ListCaseIntentHistory :many @@ -36,7 +34,7 @@ type ListCaseIntentHistoryRow struct { Group string } -func (q *Queries) ListCaseIntentHistory(ctx context.Context, caseIntentID pgtype.Int8) ([]ListCaseIntentHistoryRow, error) { +func (q *Queries) ListCaseIntentHistory(ctx context.Context, caseIntentID int64) ([]ListCaseIntentHistoryRow, error) { rows, err := q.db.Query(ctx, listCaseIntentHistory, caseIntentID) if err != nil { return nil, err diff --git a/internal/endtoend/testdata/cte_resolve_ref/issue.md b/internal/endtoend/testdata/cte_resolve_ref/issue.md new file mode 100644 index 0000000000..9268a7d1f8 --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/issue.md @@ -0,0 +1,2 @@ +https://github.com/sqlc-dev/sqlc/issues/3219 + diff --git a/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..7c111fd4e7 --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.26.0 + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..9099b926b3 --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/models.go @@ -0,0 +1,13 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.26.0 + +package querytest + +type T1 struct { + ID int32 +} + +type T2 struct { + ID int32 +} diff --git a/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..d4fb8b9c5f --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/go/query.sql.go @@ -0,0 +1,44 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.26.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const cTEMultipleRefs = `-- name: CTEMultipleRefs :one +WITH t1_ids AS ( + SELECT id FROM t1 WHERE t1.id = $1 +), +t2_ids AS ( + SELECT id FROM t2 WHERE t2.id = $1 +), +all_ids AS ( + SELECT id FROM t1_ids + UNION + SELECT id FROM t2_ids +) +SELECT id FROM all_ids AS ids WHERE ids.id = $1 +` + +func (q *Queries) CTEMultipleRefs(ctx context.Context, id int32) (int32, error) { + row := q.db.QueryRow(ctx, cTEMultipleRefs, id) + err := row.Scan(&id) + return id, err +} + +const cTERef = `-- name: CTERef :one +WITH t1_ids AS ( + SELECT id FROM t1 +) +SELECT id FROM t1_ids WHERE t1_ids.id = $1 +` + +func (q *Queries) CTERef(ctx context.Context, id int32) (int32, error) { + row := q.db.QueryRow(ctx, cTERef, id) + err := row.Scan(&id) + return id, err +} diff --git a/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/query.sql new file mode 100644 index 0000000000..39c87dfc31 --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/query.sql @@ -0,0 +1,21 @@ +-- name: CTERef :one +WITH t1_ids AS ( + SELECT id FROM t1 +) +SELECT * FROM t1_ids WHERE t1_ids.id = sqlc.arg('id'); + +-- name: CTEMultipleRefs :one +WITH t1_ids AS ( + SELECT id FROM t1 WHERE t1.id = sqlc.arg('id') +), +t2_ids AS ( + SELECT id FROM t2 WHERE t2.id = sqlc.arg('id') +), +all_ids AS ( + SELECT * FROM t1_ids + UNION + SELECT * FROM t2_ids +) +SELECT * FROM all_ids AS ids WHERE ids.id = sqlc.arg('id'); + + diff --git a/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..3029ac89be --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/schema.sql @@ -0,0 +1,9 @@ +CREATE TABLE t1 +( + id SERIAL NOT NULL PRIMARY KEY +); + +CREATE TABLE t2 +( + id SERIAL NOT NULL PRIMARY KEY +); diff --git a/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/cte_resolve_ref/postgresql/pgx/sqlc.yaml @@ -0,0 +1,10 @@ +version: "2" +sql: + - engine: "postgresql" + schema: "schema.sql" + queries: "query.sql" + gen: + go: + package: "querytest" + out: "go" + sql_package: "pgx/v5" \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_update/postgresql/pgx/go/query.sql.go index 1176c852ae..fe4b0e3b94 100644 --- a/internal/endtoend/testdata/cte_update/postgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/cte_update/postgresql/pgx/go/query.sql.go @@ -23,9 +23,9 @@ from updated_attribute ` type UpdateAttributeParams struct { - FilterValue pgtype.Bool - Value pgtype.Text - ID pgtype.Int8 + FilterValue bool + Value string + ID int64 } type UpdateAttributeRow struct {