diff --git a/examples/authors/sqlc.yaml b/examples/authors/sqlc.yaml index 8270782edd..9ba523c0d6 100644 --- a/examples/authors/sqlc.yaml +++ b/examples/authors/sqlc.yaml @@ -7,6 +7,8 @@ sql: engine: postgresql database: managed: true + analyzer: + database: false rules: - sqlc/db-prepare - postgresql-query-too-costly diff --git a/examples/booktest/sqlc.json b/examples/booktest/sqlc.json index 72cd08936d..b1453a2e37 100644 --- a/examples/booktest/sqlc.json +++ b/examples/booktest/sqlc.json @@ -13,6 +13,9 @@ "database": { "managed": true }, + "analyzer": { + "database": false + }, "rules": [ "sqlc/db-prepare" ] diff --git a/examples/jets/sqlc.json b/examples/jets/sqlc.json index 85a35a4f7a..14e80c4291 100644 --- a/examples/jets/sqlc.json +++ b/examples/jets/sqlc.json @@ -13,6 +13,9 @@ "database": { "managed": true }, + "analyzer": { + "database": false + }, "rules": [ "sqlc/db-prepare" ] diff --git a/examples/ondeck/sqlc.json b/examples/ondeck/sqlc.json index c9290db568..0eed50f9d7 100644 --- a/examples/ondeck/sqlc.json +++ b/examples/ondeck/sqlc.json @@ -13,6 +13,9 @@ "database": { "managed": true }, + "analyzer": { + "database": false + }, "rules": [ "sqlc/db-prepare" ], @@ -21,7 +24,7 @@ "emit_interface": true }, { - "path": "mysql", + "path": "mysql", "name": "ondeck", "schema": "mysql/schema", "queries": "mysql/query", diff --git a/go.mod b/go.mod index 0420930358..a040a4edb8 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( require ( github.com/benbjohnson/clock v1.3.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/pingcap/failpoint v0.0.0-20220801062533-2eaa32854a6c // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect diff --git a/go.sum b/go.sum index 94a7acdd04..e8f9fb10c2 100644 --- a/go.sum +++ b/go.sum @@ -100,7 +100,10 @@ github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSlj github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= diff --git a/internal/analyzer/analyzer.go b/internal/analyzer/analyzer.go new file mode 100644 index 0000000000..4ad7034823 --- /dev/null +++ b/internal/analyzer/analyzer.go @@ -0,0 +1,46 @@ +package analyzer + +import ( + "context" + + "github.com/sqlc-dev/sqlc/internal/sql/ast" + "github.com/sqlc-dev/sqlc/internal/sql/named" +) + +type Column struct { + Name string + OriginalName string + DataType string + NotNull bool + Unsigned bool + IsArray bool + ArrayDims int + Comment string + Length *int + IsNamedParam bool + IsFuncCall bool + + // XXX: Figure out what PostgreSQL calls `foo.id` + Scope string + Table *ast.TableName + TableAlias string + Type *ast.TypeName + EmbedTable *ast.TableName + + IsSqlcSlice bool // is this sqlc.slice() +} + +type Parameter struct { + Number int + Column *Column +} + +type Analysis struct { + Columns []Column + Params []Parameter +} + +type Analyzer interface { + Analyze(context.Context, ast.Node, string, []string, *named.ParamSet) (*Analysis, error) + Close(context.Context) error +} diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 4b542d2f42..6e31be3ab8 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -197,7 +197,10 @@ var genCmd = &cobra.Command{ defer trace.StartRegion(cmd.Context(), "generate").End() stderr := cmd.ErrOrStderr() dir, name := getConfigPath(stderr, cmd.Flag("file")) - output, err := Generate(cmd.Context(), ParseEnv(cmd), dir, name, stderr) + output, err := Generate(cmd.Context(), dir, name, &Options{ + Env: ParseEnv(cmd), + Stderr: stderr, + }) if err != nil { os.Exit(1) } @@ -219,7 +222,11 @@ var uploadCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { stderr := cmd.ErrOrStderr() dir, name := getConfigPath(stderr, cmd.Flag("file")) - if err := createPkg(cmd.Context(), ParseEnv(cmd), dir, name, stderr); err != nil { + opts := &Options{ + Env: ParseEnv(cmd), + Stderr: stderr, + } + if err := createPkg(cmd.Context(), dir, name, opts); err != nil { fmt.Fprintf(stderr, "error uploading: %s\n", err) os.Exit(1) } @@ -234,7 +241,11 @@ var checkCmd = &cobra.Command{ defer trace.StartRegion(cmd.Context(), "compile").End() stderr := cmd.ErrOrStderr() dir, name := getConfigPath(stderr, cmd.Flag("file")) - if _, err := Generate(cmd.Context(), ParseEnv(cmd), dir, name, stderr); err != nil { + _, err := Generate(cmd.Context(), dir, name, &Options{ + Env: ParseEnv(cmd), + Stderr: stderr, + }) + if err != nil { os.Exit(1) } return nil @@ -277,7 +288,11 @@ var diffCmd = &cobra.Command{ defer trace.StartRegion(cmd.Context(), "diff").End() stderr := cmd.ErrOrStderr() dir, name := getConfigPath(stderr, cmd.Flag("file")) - if err := Diff(cmd.Context(), ParseEnv(cmd), dir, name, stderr); err != nil { + opts := &Options{ + Env: ParseEnv(cmd), + Stderr: stderr, + } + if err := Diff(cmd.Context(), dir, name, opts); err != nil { os.Exit(1) } return nil diff --git a/internal/cmd/diff.go b/internal/cmd/diff.go index aa1ddc8788..8998971a37 100644 --- a/internal/cmd/diff.go +++ b/internal/cmd/diff.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "io" "os" "runtime/trace" "sort" @@ -13,8 +12,9 @@ import ( "github.com/cubicdaiya/gonp" ) -func Diff(ctx context.Context, e Env, dir, name string, stderr io.Writer) error { - output, err := Generate(ctx, e, dir, name, stderr) +func Diff(ctx context.Context, dir, name string, opts *Options) error { + stderr := opts.Stderr + output, err := Generate(ctx, dir, name, opts) if err != nil { return err } diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go index 21cf0bce77..35a5f06e4e 100644 --- a/internal/cmd/generate.go +++ b/internal/cmd/generate.go @@ -139,8 +139,11 @@ func readConfig(stderr io.Writer, dir, filename string) (string, *config.Config, return configPath, &conf, nil } -func Generate(ctx context.Context, e Env, dir, filename string, stderr io.Writer) (map[string]string, error) { - configPath, conf, err := readConfig(stderr, dir, filename) +func Generate(ctx context.Context, dir, filename string, o *Options) (map[string]string, error) { + e := o.Env + stderr := o.Stderr + + configPath, conf, err := o.ReadConfig(dir, filename) if err != nil { return nil, err } @@ -343,7 +346,12 @@ func remoteGenerate(ctx context.Context, configPath string, conf *config.Config, func parse(ctx context.Context, name, dir string, sql config.SQL, combo config.CombinedSettings, parserOpts opts.Parser, stderr io.Writer) (*compiler.Result, bool) { defer trace.StartRegion(ctx, "parse").End() - c := compiler.NewCompiler(sql, combo) + c, err := compiler.NewCompiler(sql, combo) + defer c.Close(ctx) + if err != nil { + fmt.Fprintf(stderr, "error creating compiler: %s\n", err) + return nil, true + } if err := c.ParseCatalog(sql.Schema); err != nil { fmt.Fprintf(stderr, "# package %s\n", name) if parserErr, ok := err.(*multierr.Error); ok { diff --git a/internal/cmd/options.go b/internal/cmd/options.go new file mode 100644 index 0000000000..8dd99fb04f --- /dev/null +++ b/internal/cmd/options.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "io" + + "github.com/sqlc-dev/sqlc/internal/config" +) + +type Options struct { + Env Env + Stderr io.Writer + MutateConfig func(*config.Config) +} + +func (o *Options) ReadConfig(dir, filename string) (string, *config.Config, error) { + path, conf, err := readConfig(o.Stderr, dir, filename) + if err != nil { + return path, conf, err + } + if o.MutateConfig != nil { + o.MutateConfig(conf) + } + return path, conf, nil +} diff --git a/internal/cmd/package.go b/internal/cmd/package.go index 4b3318d915..c4d3df7fd5 100644 --- a/internal/cmd/package.go +++ b/internal/cmd/package.go @@ -2,13 +2,14 @@ package cmd import ( "context" - "io" "os" "github.com/sqlc-dev/sqlc/internal/bundler" ) -func createPkg(ctx context.Context, e Env, dir, filename string, stderr io.Writer) error { +func createPkg(ctx context.Context, dir, filename string, opts *Options) error { + e := opts.Env + stderr := opts.Stderr configPath, conf, err := readConfig(stderr, dir, filename) if err != nil { return err @@ -17,7 +18,7 @@ func createPkg(ctx context.Context, e Env, dir, filename string, stderr io.Write if err := up.Validate(); err != nil { return err } - output, err := Generate(ctx, e, dir, filename, stderr) + output, err := Generate(ctx, dir, filename, opts) if err != nil { os.Exit(1) } diff --git a/internal/cmd/vet.go b/internal/cmd/vet.go index 48fbc2a411..31aa3ec33c 100644 --- a/internal/cmd/vet.go +++ b/internal/cmd/vet.go @@ -47,8 +47,12 @@ func NewCmdVet() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { defer trace.StartRegion(cmd.Context(), "vet").End() stderr := cmd.ErrOrStderr() + opts := &Options{ + Env: ParseEnv(cmd), + Stderr: stderr, + } dir, name := getConfigPath(stderr, cmd.Flag("file")) - if err := Vet(cmd.Context(), ParseEnv(cmd), dir, name, stderr); err != nil { + if err := Vet(cmd.Context(), dir, name, opts); err != nil { if !errors.Is(err, ErrFailedChecks) { fmt.Fprintf(stderr, "%s\n", err) } @@ -59,7 +63,9 @@ func NewCmdVet() *cobra.Command { } } -func Vet(ctx context.Context, e Env, dir, filename string, stderr io.Writer) error { +func Vet(ctx context.Context, dir, filename string, opts *Options) error { + e := opts.Env + stderr := opts.Stderr configPath, conf, err := readConfig(stderr, dir, filename) if err != nil { return err diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go index 3d96fb1437..953882b144 100644 --- a/internal/codegen/golang/result.go +++ b/internal/codegen/golang/result.go @@ -249,9 +249,7 @@ func buildQueries(req *plugin.CodeGenRequest, options *opts, structs []Struct) ( if len(query.Columns) == 1 && query.Columns[0].EmbedTable == nil { c := query.Columns[0] name := columnName(c, 0) - if c.IsFuncCall { - name = strings.Replace(name, "$", "_", -1) - } + name = strings.Replace(name, "$", "_", -1) gq.Ret = QueryValue{ Name: name, DBName: name, diff --git a/internal/compiler/analyze.go b/internal/compiler/analyze.go new file mode 100644 index 0000000000..739cd07993 --- /dev/null +++ b/internal/compiler/analyze.go @@ -0,0 +1,195 @@ +package compiler + +import ( + "sort" + + "github.com/sqlc-dev/sqlc/internal/analyzer" + "github.com/sqlc-dev/sqlc/internal/config" + "github.com/sqlc-dev/sqlc/internal/source" + "github.com/sqlc-dev/sqlc/internal/sql/ast" + "github.com/sqlc-dev/sqlc/internal/sql/named" + "github.com/sqlc-dev/sqlc/internal/sql/rewrite" + "github.com/sqlc-dev/sqlc/internal/sql/validate" +) + +type analysis struct { + Table *ast.TableName + Columns []*Column + QueryCatalog *QueryCatalog + Parameters []Parameter + Named *named.ParamSet + Query string +} + +func convertColumn(c analyzer.Column) *Column { + return &Column{ + Name: c.Name, + OriginalName: c.OriginalName, + DataType: c.DataType, + NotNull: c.NotNull, + Unsigned: c.Unsigned, + IsArray: c.IsArray, + ArrayDims: c.ArrayDims, + Comment: c.Comment, + Length: c.Length, + IsNamedParam: c.IsNamedParam, + IsFuncCall: c.IsFuncCall, + Scope: c.Scope, + Table: c.Table, + TableAlias: c.TableAlias, + Type: c.Type, + EmbedTable: c.EmbedTable, + IsSqlcSlice: c.IsSqlcSlice, + } +} + +func combineAnalysis(prev *analysis, a *analyzer.Analysis) *analysis { + var cols []*Column + for _, c := range a.Columns { + cols = append(cols, convertColumn(c)) + } + var params []Parameter + for _, p := range a.Params { + params = append(params, Parameter{ + Number: p.Number, + Column: convertColumn(*p.Column), + }) + } + if len(prev.Columns) == len(cols) { + for i := range prev.Columns { + prev.Columns[i].DataType = cols[i].DataType + } + } else { + embedding := false + for i := range prev.Columns { + if prev.Columns[i].EmbedTable != nil { + embedding = true + } + } + if !embedding { + prev.Columns = cols + } + } + if len(prev.Parameters) == len(params) { + for i := range prev.Parameters { + prev.Parameters[i].Column.DataType = params[i].Column.DataType + } + } else { + prev.Parameters = params + } + return prev +} + +func (c *Compiler) analyzeQuery(raw *ast.RawStmt, query string) (*analysis, error) { + return c._analyzeQuery(raw, query, true) +} + +func (c *Compiler) inferQuery(raw *ast.RawStmt, query string) (*analysis, error) { + return c._analyzeQuery(raw, query, false) +} + +func (c *Compiler) _analyzeQuery(raw *ast.RawStmt, query string, failfast bool) (*analysis, error) { + errors := make([]error, 0) + check := func(err error) error { + if failfast { + return err + } + if err != nil { + errors = append(errors, err) + } + return nil + } + + numbers, dollar, err := validate.ParamRef(raw) + if err := check(err); err != nil { + return nil, err + } + + raw, namedParams, edits := rewrite.NamedParameters(c.conf.Engine, raw, numbers, dollar) + + var table *ast.TableName + switch n := raw.Stmt.(type) { + case *ast.CallStmt: + case *ast.SelectStmt: + case *ast.DeleteStmt: + case *ast.DoStmt: + case *ast.InsertStmt: + if err := check(validate.InsertStmt(n)); err != nil { + return nil, err + } + var err error + table, err = ParseTableName(n.Relation) + if err := check(err); err != nil { + return nil, err + } + case *ast.ListenStmt: + case *ast.NotifyStmt: + case *ast.TruncateStmt: + case *ast.UpdateStmt: + case *ast.RefreshMatViewStmt: + default: + if err := check(ErrUnsupportedStatementType); err != nil { + return nil, err + } + } + + if err := check(validate.FuncCall(c.catalog, c.combo, raw)); err != nil { + return nil, err + } + + if err := check(validate.In(c.catalog, raw)); err != nil { + return nil, err + } + rvs := rangeVars(raw.Stmt) + refs, errs := findParameters(raw.Stmt) + if len(errs) > 0 { + if failfast { + return nil, errs[0] + } + errors = append(errors, errs...) + } + refs = uniqueParamRefs(refs, dollar) + if c.conf.Engine == config.EngineMySQL || !dollar { + sort.Slice(refs, func(i, j int) bool { return refs[i].ref.Location < refs[j].ref.Location }) + } else { + sort.Slice(refs, func(i, j int) bool { return refs[i].ref.Number < refs[j].ref.Number }) + } + raw, embeds := rewrite.Embeds(raw) + qc, err := c.buildQueryCatalog(c.catalog, raw.Stmt, embeds) + if err := check(err); err != nil { + return nil, err + } + + params, err := c.resolveCatalogRefs(qc, rvs, refs, namedParams, embeds) + if err := check(err); err != nil { + return nil, err + } + cols, err := c.outputColumns(qc, raw.Stmt) + if err := check(err); err != nil { + return nil, err + } + + expandEdits, err := c.expand(qc, raw) + if check(err); err != nil { + return nil, err + } + edits = append(edits, expandEdits...) + expanded, err := source.Mutate(query, edits) + if err != nil { + return nil, err + } + + var rerr error + if len(errors) > 0 { + rerr = errors[0] + } + + return &analysis{ + Table: table, + Columns: cols, + Parameters: params, + QueryCatalog: qc, + Query: expanded, + Named: namedParams, + }, rerr +} diff --git a/internal/compiler/compile.go b/internal/compiler/compile.go index 5cbfab674a..a6744fc6d2 100644 --- a/internal/compiler/compile.go +++ b/internal/compiler/compile.go @@ -24,7 +24,6 @@ type Parser interface { IsReservedKeyword(string) bool } -// end copypasta func (c *Compiler) parseCatalog(schemas []string) error { files, err := sqlpath.Glob(schemas) if err != nil { @@ -38,6 +37,7 @@ func (c *Compiler) parseCatalog(schemas []string) error { continue } contents := migrations.RemoveRollbackStatements(string(blob)) + c.schema = append(c.schema, contents) stmts, err := c.parser.Parse(strings.NewReader(contents)) if err != nil { merr.Add(filename, contents, 0, err) diff --git a/internal/compiler/engine.go b/internal/compiler/engine.go index 032c1b0ba7..bbef2f00d5 100644 --- a/internal/compiler/engine.go +++ b/internal/compiler/engine.go @@ -1,26 +1,44 @@ package compiler import ( + "context" "fmt" + "github.com/sqlc-dev/sqlc/internal/analyzer" "github.com/sqlc-dev/sqlc/internal/config" "github.com/sqlc-dev/sqlc/internal/engine/dolphin" "github.com/sqlc-dev/sqlc/internal/engine/postgresql" + pganalyze "github.com/sqlc-dev/sqlc/internal/engine/postgresql/analyzer" "github.com/sqlc-dev/sqlc/internal/engine/sqlite" "github.com/sqlc-dev/sqlc/internal/opts" + "github.com/sqlc-dev/sqlc/internal/quickdb" + pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1" "github.com/sqlc-dev/sqlc/internal/sql/catalog" ) type Compiler struct { - conf config.SQL - combo config.CombinedSettings - catalog *catalog.Catalog - parser Parser - result *Result + conf config.SQL + combo config.CombinedSettings + catalog *catalog.Catalog + parser Parser + result *Result + analyzer analyzer.Analyzer + client pb.QuickClient + + schema []string } -func NewCompiler(conf config.SQL, combo config.CombinedSettings) *Compiler { +func NewCompiler(conf config.SQL, combo config.CombinedSettings) (*Compiler, error) { c := &Compiler{conf: conf, combo: combo} + + if conf.Database != nil && conf.Database.Managed { + client, err := quickdb.NewClientFromConfig(combo.Global.Cloud) + if err != nil { + return nil, fmt.Errorf("client error: %w", err) + } + c.client = client + } + switch conf.Engine { case config.EngineSQLite: c.parser = sqlite.NewParser() @@ -31,10 +49,15 @@ func NewCompiler(conf config.SQL, combo config.CombinedSettings) *Compiler { case config.EnginePostgreSQL: c.parser = postgresql.NewParser() c.catalog = postgresql.NewCatalog() + if conf.Database != nil { + if conf.Analyzer.Database == nil || *conf.Analyzer.Database { + c.analyzer = pganalyze.New(c.client, *conf.Database) + } + } default: - panic(fmt.Sprintf("unknown engine: %s", conf.Engine)) + return nil, fmt.Errorf("unknown engine: %s", conf.Engine) } - return c + return c, nil } func (c *Compiler) Catalog() *catalog.Catalog { @@ -57,3 +80,9 @@ func (c *Compiler) ParseQueries(queries []string, o opts.Parser) error { func (c *Compiler) Result() *Result { return c.result } + +func (c *Compiler) Close(ctx context.Context) { + if c.analyzer != nil { + c.analyzer.Close(ctx) + } +} diff --git a/internal/compiler/expand.go b/internal/compiler/expand.go index 29adfa316a..60e654b696 100644 --- a/internal/compiler/expand.go +++ b/internal/compiler/expand.go @@ -2,6 +2,7 @@ package compiler import ( "fmt" + "regexp" "strings" "github.com/sqlc-dev/sqlc/internal/config" @@ -11,6 +12,14 @@ import ( ) func (c *Compiler) expand(qc *QueryCatalog, raw *ast.RawStmt) ([]source.Edit, error) { + // Return early if there are no A_Star nodes to expand + stars := astutils.Search(raw, func(node ast.Node) bool { + _, ok := node.(*ast.A_Star) + return ok + }) + if len(stars.Items) == 0 { + return nil, nil + } list := astutils.Search(raw, func(node ast.Node) bool { switch node.(type) { case *ast.DeleteStmt: @@ -36,14 +45,25 @@ func (c *Compiler) expand(qc *QueryCatalog, raw *ast.RawStmt) ([]source.Edit, er return edits, nil } +var validPostgresIdent = regexp.MustCompile(`^[a-z_][a-z0-9_$]*$`) + func (c *Compiler) quoteIdent(ident string) string { if c.parser.IsReservedKeyword(ident) { return c.quote(ident) } + // SQL identifiers and key words must begin with a letter (a-z, but also + // letters with diacritical marks and non-Latin letters) or an underscore + // (_). Subsequent characters in an identifier or key word can be letters, + // underscores, digits (0-9), or dollar signs ($). + // + // https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS if c.conf.Engine == config.EnginePostgreSQL { // camelCase means the column is also camelCase if strings.ToLower(ident) != ident { - return "\"" + ident + "\"" + return c.quote(ident) + } + if !validPostgresIdent.MatchString(strings.ToLower(ident)) { + return c.quote(ident) } } return ident @@ -134,7 +154,11 @@ func (c *Compiler) expandStmt(qc *QueryCatalog, raw *ast.RawStmt, node ast.Node) } var old []string for _, p := range parts { - old = append(old, c.quoteIdent(p)) + if p == "*" { + old = append(old, p) + } else { + old = append(old, c.quoteIdent(p)) + } } var oldString string @@ -169,5 +193,6 @@ func (c *Compiler) expandStmt(qc *QueryCatalog, raw *ast.RawStmt, node ast.Node) New: strings.Join(cols, ", "), }) } + return edits, nil } diff --git a/internal/compiler/find_params.go b/internal/compiler/find_params.go index 41ffaf8ad7..ca38199b9d 100644 --- a/internal/compiler/find_params.go +++ b/internal/compiler/find_params.go @@ -7,14 +7,13 @@ import ( "github.com/sqlc-dev/sqlc/internal/sql/astutils" ) -func findParameters(root ast.Node) ([]paramRef, error) { +func findParameters(root ast.Node) ([]paramRef, []error) { refs := make([]paramRef, 0) errors := make([]error, 0) v := paramSearch{seen: make(map[int]struct{}), refs: &refs, errs: &errors} astutils.Walk(v, root) if len(*v.errs) > 0 { - problems := *v.errs - return nil, problems[0] + return refs, *v.errs } else { return refs, nil } @@ -54,10 +53,6 @@ func (l *limitOffset) Pos() int { } func (p paramSearch) Visit(node ast.Node) astutils.Visitor { - if len(*p.errs) > 0 { - return p - } - switch n := node.(type) { case *ast.A_Expr: diff --git a/internal/compiler/output_columns.go b/internal/compiler/output_columns.go index 75ff457d63..104957e18a 100644 --- a/internal/compiler/output_columns.go +++ b/internal/compiler/output_columns.go @@ -4,10 +4,9 @@ import ( "errors" "fmt" - "github.com/sqlc-dev/sqlc/internal/sql/catalog" - "github.com/sqlc-dev/sqlc/internal/sql/ast" "github.com/sqlc-dev/sqlc/internal/sql/astutils" + "github.com/sqlc-dev/sqlc/internal/sql/catalog" "github.com/sqlc-dev/sqlc/internal/sql/lang" "github.com/sqlc-dev/sqlc/internal/sql/sqlerr" ) @@ -523,6 +522,7 @@ func (c *Compiler) sourceTables(qc *QueryCatalog, node ast.Node) ([]*Table, erro var tables []*Table for _, item := range list.Items { + item := item switch n := item.(type) { case *ast.RangeFunction: @@ -555,16 +555,32 @@ func (c *Compiler) sourceTables(qc *QueryCatalog, node ast.Node) ([]*Table, erro Name: fn.ReturnType.Name, }) if err != nil { - if n.Alias == nil || len(n.Alias.Colnames.Items) == 0 { - continue - } - - table = &Table{} - for _, colName := range n.Alias.Colnames.Items { - table.Columns = append(table.Columns, &Column{ - Name: colName.(*ast.String).Str, - DataType: "any", - }) + if n.Alias != nil && len(n.Alias.Colnames.Items) > 0 { + table = &Table{} + for _, colName := range n.Alias.Colnames.Items { + table.Columns = append(table.Columns, &Column{ + Name: colName.(*ast.String).Str, + DataType: "any", + }) + } + } else { + colName := fn.Rel.Name + if n.Alias != nil { + colName = *n.Alias.Aliasname + } + table = &Table{ + Rel: &ast.TableName{ + Catalog: fn.Rel.Catalog, + Schema: fn.Rel.Schema, + Name: fn.Rel.Name, + }, + Columns: []*Column{ + { + Name: colName, + DataType: fn.ReturnType.Name, + }, + }, + } } } if n.Alias != nil { diff --git a/internal/compiler/parse.go b/internal/compiler/parse.go index c660ef4fb4..53e3043c7d 100644 --- a/internal/compiler/parse.go +++ b/internal/compiler/parse.go @@ -1,63 +1,40 @@ package compiler import ( + "context" "errors" "fmt" - "sort" "strings" - "github.com/sqlc-dev/sqlc/internal/config" "github.com/sqlc-dev/sqlc/internal/debug" "github.com/sqlc-dev/sqlc/internal/metadata" "github.com/sqlc-dev/sqlc/internal/opts" "github.com/sqlc-dev/sqlc/internal/source" "github.com/sqlc-dev/sqlc/internal/sql/ast" "github.com/sqlc-dev/sqlc/internal/sql/astutils" - "github.com/sqlc-dev/sqlc/internal/sql/rewrite" "github.com/sqlc-dev/sqlc/internal/sql/validate" ) var ErrUnsupportedStatementType = errors.New("parseQuery: unsupported statement type") func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query, error) { + ctx := context.Background() + if o.Debug.DumpAST { debug.Dump(stmt) } - if err := validate.ParamStyle(stmt); err != nil { - return nil, err - } - numbers, dollar, err := validate.ParamRef(stmt) - if err != nil { + + // validate sqlc-specific syntax + if err := validate.SqlcFunctions(stmt); err != nil { return nil, err } + + // rewrite queries to remove sqlc.* functions + raw, ok := stmt.(*ast.RawStmt) if !ok { return nil, errors.New("node is not a statement") } - var table *ast.TableName - switch n := raw.Stmt.(type) { - case *ast.CallStmt: - case *ast.SelectStmt: - case *ast.DeleteStmt: - case *ast.DoStmt: - case *ast.InsertStmt: - if err := validate.InsertStmt(n); err != nil { - return nil, err - } - var err error - table, err = ParseTableName(n.Relation) - if err != nil { - return nil, err - } - case *ast.ListenStmt: - case *ast.NotifyStmt: - case *ast.TruncateStmt: - case *ast.UpdateStmt: - case *ast.RefreshMatViewStmt: - default: - return nil, ErrUnsupportedStatementType - } - rawSQL, err := source.Pluck(src, raw.StmtLocation, raw.StmtLen) if err != nil { return nil, err @@ -65,56 +42,42 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query, if rawSQL == "" { return nil, errors.New("missing semicolon at end of file") } - if err := validate.FuncCall(c.catalog, c.combo, raw); err != nil { - return nil, err - } - if err := validate.In(c.catalog, raw); err != nil { - return nil, err - } + name, cmd, err := metadata.ParseQueryNameAndType(strings.TrimSpace(rawSQL), c.parser.CommentSyntax()) if err != nil { return nil, err } - raw, namedParams, edits := rewrite.NamedParameters(c.conf.Engine, raw, numbers, dollar) if err := validate.Cmd(raw.Stmt, name, cmd); err != nil { return nil, err } - rvs := rangeVars(raw.Stmt) - refs, err := findParameters(raw.Stmt) - if err != nil { - return nil, err - } - refs = uniqueParamRefs(refs, dollar) - if c.conf.Engine == config.EngineMySQL || !dollar { - sort.Slice(refs, func(i, j int) bool { return refs[i].ref.Location < refs[j].ref.Location }) - } else { - sort.Slice(refs, func(i, j int) bool { return refs[i].ref.Number < refs[j].ref.Number }) - } - raw, embeds := rewrite.Embeds(raw) - qc, err := c.buildQueryCatalog(c.catalog, raw.Stmt, embeds) - if err != nil { - return nil, err - } - params, err := c.resolveCatalogRefs(qc, rvs, refs, namedParams, embeds) - if err != nil { - return nil, err - } - cols, err := c.outputColumns(qc, raw.Stmt) - if err != nil { - return nil, err - } + var anlys *analysis + if c.analyzer != nil { + // TODO: Handle panics + inference, _ := c.inferQuery(raw, rawSQL) + if inference == nil { + inference = &analysis{} + } + if inference.Query == "" { + inference.Query = rawSQL + } - expandEdits, err := c.expand(qc, raw) - if err != nil { - return nil, err - } - edits = append(edits, expandEdits...) - expanded, err := source.Mutate(rawSQL, edits) - if err != nil { - return nil, err + result, err := c.analyzer.Analyze(ctx, raw, inference.Query, c.schema, inference.Named) + if err != nil { + return nil, err + } + + // FOOTGUN: combineAnalysis mutates inference + anlys = combineAnalysis(inference, result) + } else { + anlys, err = c.analyzeQuery(raw, rawSQL) + if err != nil { + return nil, err + } } + expanded := anlys.Query + // If the query string was edited, make sure the syntax is valid if expanded != rawSQL { if _, err := c.parser.Parse(strings.NewReader(expanded)); err != nil { @@ -138,10 +101,10 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query, Comments: comments, Name: name, Flags: flags, - Params: params, - Columns: cols, + Params: anlys.Parameters, + Columns: anlys.Columns, SQL: trimmed, - InsertIntoTable: table, + InsertIntoTable: anlys.Table, }, nil } diff --git a/internal/compiler/query_catalog.go b/internal/compiler/query_catalog.go index ea1190c0de..42088446d2 100644 --- a/internal/compiler/query_catalog.go +++ b/internal/compiler/query_catalog.go @@ -36,9 +36,22 @@ func (comp *Compiler) buildQueryCatalog(c *catalog.Catalog, node ast.Node, embed if err != nil { return nil, err } + var names []string + if cte.Aliascolnames != nil { + for _, item := range cte.Aliascolnames.Items { + if val, ok := item.(*ast.String); ok { + names = append(names, val.Str) + } else { + names = append(names, "") + } + } + } rel := &ast.TableName{Name: *cte.Ctename} for i := range cols { cols[i].Table = rel + if len(names) > i { + cols[i].Name = names[i] + } } qc.ctes[*cte.Ctename] = &Table{ Rel: rel, @@ -67,7 +80,7 @@ func ConvertColumn(rel *ast.TableName, c *catalog.Column) *Column { func (qc QueryCatalog) GetTable(rel *ast.TableName) (*Table, error) { cte, exists := qc.ctes[rel.Name] if exists { - return cte, nil + return &Table{Rel: rel, Columns: cte.Columns}, nil } src, err := qc.catalog.GetTable(rel) if err != nil { diff --git a/internal/compiler/resolve.go b/internal/compiler/resolve.go index 0a91b45f25..2cb93fabc3 100644 --- a/internal/compiler/resolve.go +++ b/internal/compiler/resolve.go @@ -2,6 +2,7 @@ package compiler import ( "fmt" + "log/slog" "strconv" "github.com/sqlc-dev/sqlc/internal/sql/ast" @@ -580,8 +581,6 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, }) } } - } else { - fmt.Println("------------------------") } if found == 0 { @@ -600,7 +599,7 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, } default: - fmt.Printf("unsupported reference type: %T\n", n) + slog.Debug("unsupported reference type", "type", fmt.Sprintf("%T", n)) } } return a, nil diff --git a/internal/config/config.go b/internal/config/config.go index 1ca0642947..abf264c8e1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -111,6 +111,11 @@ type SQL struct { Gen SQLGen `json:"gen" yaml:"gen"` Codegen []Codegen `json:"codegen" yaml:"codegen"` Rules []string `json:"rules" yaml:"rules"` + Analyzer Analyzer `json:"analyzer" yaml:"analyzer"` +} + +type Analyzer struct { + Database *bool `json:"database" yaml:"database"` } // TODO: Figure out a better name for this diff --git a/internal/config/v_one.go b/internal/config/v_one.go index e7bf7271ee..8f8a1052c0 100644 --- a/internal/config/v_one.go +++ b/internal/config/v_one.go @@ -21,6 +21,7 @@ type v1PackageSettings struct { Name string `json:"name" yaml:"name"` Engine Engine `json:"engine,omitempty" yaml:"engine"` Database *Database `json:"database,omitempty" yaml:"database"` + Analyzer Analyzer `json:"analyzer" yaml:"analyzer"` Path string `json:"path" yaml:"path"` Schema Paths `json:"schema" yaml:"schema"` Queries Paths `json:"queries" yaml:"queries"` diff --git a/internal/config/v_one.json b/internal/config/v_one.json index 0d23f5af76..166888ab93 100644 --- a/internal/config/v_one.json +++ b/internal/config/v_one.json @@ -75,6 +75,14 @@ } } }, + "analyzer": { + "type": "object", + "properties": { + "database": { + "type": "boolean" + } + } + }, "strict_function_checks": { "type": "boolean" }, diff --git a/internal/config/v_two.json b/internal/config/v_two.json index e67be2070e..c2f1b03142 100644 --- a/internal/config/v_two.json +++ b/internal/config/v_two.json @@ -75,6 +75,14 @@ } } }, + "analyzer": { + "type": "object", + "properties": { + "database": { + "type": "boolean" + } + } + }, "strict_function_checks": { "type": "boolean" }, diff --git a/internal/endtoend/endtoend_test.go b/internal/endtoend/endtoend_test.go index 236b37d7ad..cb4838543f 100644 --- a/internal/endtoend/endtoend_test.go +++ b/internal/endtoend/endtoend_test.go @@ -4,9 +4,11 @@ import ( "bytes" "context" "encoding/json" + "fmt" "os" osexec "os/exec" "path/filepath" + "slices" "strings" "testing" @@ -14,11 +16,12 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/sqlc-dev/sqlc/internal/cmd" + "github.com/sqlc-dev/sqlc/internal/config" "github.com/sqlc-dev/sqlc/internal/opts" ) func TestExamples(t *testing.T) { - t.Parallel() + // t.Parallel() ctx := context.Background() examples, err := filepath.Abs(filepath.Join("..", "..", "examples")) @@ -37,10 +40,14 @@ func TestExamples(t *testing.T) { } tc := replay.Name() t.Run(tc, func(t *testing.T) { - t.Parallel() + // t.Parallel() path := filepath.Join(examples, tc) var stderr bytes.Buffer - output, err := cmd.Generate(ctx, cmd.Env{}, path, "", &stderr) + opts := &cmd.Options{ + Env: cmd.Env{}, + Stderr: &stderr, + } + output, err := cmd.Generate(ctx, path, "", opts) if err != nil { t.Fatalf("sqlc generate failed: %s", stderr.String()) } @@ -68,18 +75,27 @@ func BenchmarkExamples(b *testing.B) { path := filepath.Join(examples, tc) for i := 0; i < b.N; i++ { var stderr bytes.Buffer - cmd.Generate(ctx, cmd.Env{}, path, "", &stderr) + opts := &cmd.Options{ + Env: cmd.Env{}, + Stderr: &stderr, + } + cmd.Generate(ctx, path, "", opts) } }) } } +type textContext struct { + Mutate func(*config.Config) + Enabled func() bool +} + func TestReplay(t *testing.T) { // Ensure that this environment variable is always set to true when running // end-to-end tests os.Setenv("SQLC_DUMMY_VALUE", "true") - t.Parallel() + // t.Parallel() ctx := context.Background() var dirs []string err := filepath.Walk("testdata", func(path string, info os.FileInfo, err error) error { @@ -95,52 +111,96 @@ func TestReplay(t *testing.T) { if err != nil { t.Fatal(err) } + + contexts := map[string]textContext{ + "base": { + Mutate: func(c *config.Config) {}, + Enabled: func() bool { return true }, + }, + "managed-db": { + Mutate: func(c *config.Config) { + c.Cloud.Project = "01HAQMMECEYQYKFJN8MP16QC41" // TODO: Read from environment + for i := range c.SQL { + c.SQL[i].Database = &config.Database{ + Managed: true, + } + } + }, + Enabled: func() bool { + if len(os.Getenv("CI")) > 0 { + return false + } + return len(os.Getenv("SQLC_AUTH_TOKEN")) > 0 + }, + }, + } + for _, replay := range dirs { tc := replay - t.Run(tc, func(t *testing.T) { - t.Parallel() + for name, testctx := range contexts { + name := name + testctx := testctx - var stderr bytes.Buffer - var output map[string]string - var err error + if !testctx.Enabled() { + continue + } - path, _ := filepath.Abs(tc) - args := parseExec(t, path) - expected := expectedStderr(t, path) + t.Run(filepath.Join(name, tc), func(t *testing.T) { + t.Parallel() + var stderr bytes.Buffer + var output map[string]string + var err error + + path, _ := filepath.Abs(tc) + args := parseExec(t, path) - if args.Process != "" { - _, err := osexec.LookPath(args.Process) - if err != nil { - t.Skipf("executable not found: %s %s", args.Process, err) + if args.Process != "" { + _, err := osexec.LookPath(args.Process) + if err != nil { + t.Skipf("executable not found: %s %s", args.Process, err) + } } - } - env := cmd.Env{ - Debug: opts.DebugFromString(args.Env["SQLCDEBUG"]), - NoRemote: true, - } - switch args.Command { - case "diff": - err = cmd.Diff(ctx, env, path, "", &stderr) - case "generate": - output, err = cmd.Generate(ctx, env, path, "", &stderr) - if err == nil { - cmpDirectory(t, path, output) + if len(args.Contexts) > 0 { + if !slices.Contains(args.Contexts, name) { + t.Skipf("unsupported context: %s", name) + } } - case "vet": - err = cmd.Vet(ctx, env, path, "", &stderr) - default: - t.Fatalf("unknown command") - } - if len(expected) == 0 && err != nil { - t.Fatalf("sqlc %s failed: %s", args.Command, stderr.String()) - } + expected := expectedStderr(t, path, name) + opts := cmd.Options{ + Env: cmd.Env{ + Debug: opts.DebugFromString(args.Env["SQLCDEBUG"]), + NoRemote: true, + }, + Stderr: &stderr, + MutateConfig: testctx.Mutate, + } - if diff := cmp.Diff(expected, stderr.String()); diff != "" { - t.Errorf("stderr differed (-want +got):\n%s", diff) - } - }) + switch args.Command { + case "diff": + err = cmd.Diff(ctx, path, "", &opts) + case "generate": + output, err = cmd.Generate(ctx, path, "", &opts) + if err == nil { + cmpDirectory(t, path, output) + } + case "vet": + err = cmd.Vet(ctx, path, "", &opts) + default: + t.Fatalf("unknown command") + } + + if len(expected) == 0 && err != nil { + t.Fatalf("sqlc %s failed: %s", args.Command, stderr.String()) + } + + diff := cmp.Diff(strings.TrimSpace(expected), strings.TrimSpace(stderr.String())) + if diff != "" { + t.Fatalf("stderr differed (-want +got):\n%s", diff) + } + }) + } } } @@ -192,37 +252,40 @@ func cmpDirectory(t *testing.T, dir string, actual map[string]string) { t.Errorf("%s contents differ", dir) for name, contents := range expected { name := name - tn := strings.Replace(name, dir+"/", "", -1) - t.Run(tn, func(t *testing.T) { - if actual[name] == "" { - t.Errorf("%s is empty", name) - return - } - if diff := cmp.Diff(contents, actual[name]); diff != "" { - t.Errorf("%s differed (-want +got):\n%s", name, diff) - } - }) + if actual[name] == "" { + t.Errorf("%s is empty", name) + return + } + if diff := cmp.Diff(contents, actual[name]); diff != "" { + t.Errorf("%s differed (-want +got):\n%s", name, diff) + } } } } -func expectedStderr(t *testing.T, dir string) string { +func expectedStderr(t *testing.T, dir, testctx string) string { t.Helper() - path := filepath.Join(dir, "stderr.txt") - if _, err := os.Stat(path); !os.IsNotExist(err) { - blob, err := os.ReadFile(path) - if err != nil { - t.Fatal(err) + paths := []string{ + filepath.Join(dir, "stderr", fmt.Sprintf("%s.txt", testctx)), + filepath.Join(dir, "stderr.txt"), + } + for _, path := range paths { + if _, err := os.Stat(path); !os.IsNotExist(err) { + blob, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + return string(blob) } - return string(blob) } return "" } type exec struct { - Command string `json:"command"` - Process string `json:"process"` - Env map[string]string `json:"env"` + Command string `json:"command"` + Process string `json:"process"` + Contexts []string `json:"contexts"` + Env map[string]string `json:"env"` } func parseExec(t *testing.T, dir string) exec { @@ -266,7 +329,11 @@ func BenchmarkReplay(b *testing.B) { path, _ := filepath.Abs(tc) for i := 0; i < b.N; i++ { var stderr bytes.Buffer - cmd.Generate(ctx, cmd.Env{}, path, "", &stderr) + opts := &cmd.Options{ + Env: cmd.Env{}, + Stderr: &stderr, + } + cmd.Generate(ctx, path, "", opts) } }) } diff --git a/internal/endtoend/testdata/alias/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/alias/postgresql/stdlib/schema.sql index 638370ab15..b7ee888d47 100644 --- a/internal/endtoend/testdata/alias/postgresql/stdlib/schema.sql +++ b/internal/endtoend/testdata/alias/postgresql/stdlib/schema.sql @@ -1,2 +1 @@ -CREATE TABLE bar (id serial not null); - +CREATE TABLE bar (id serial not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/exec.json b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/db.go b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/db.go similarity index 100% rename from internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/db.go rename to internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/db.go diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/models.go b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/models.go similarity index 69% rename from internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/models.go rename to internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/models.go index 950971b7c2..fcb8c8cb65 100644 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/models.go +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/models.go @@ -8,7 +8,7 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -type User struct { - ID pgtype.Int4 - FirstName string +type Foo struct { + Bar pgtype.Text + Baz pgtype.Int8 } diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/query.sql.go b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/query.sql.go new file mode 100644 index 0000000000..b3288a3529 --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/go/query.sql.go @@ -0,0 +1,43 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const sumBaz = `-- name: SumBaz :many +SELECT bar, coalesce(sum(baz), 0) as quantity +FROM foo +GROUP BY 1 +` + +type SumBazRow struct { + Bar pgtype.Text + Quantity pgtype.Numeric +} + +func (q *Queries) SumBaz(ctx context.Context) ([]SumBazRow, error) { + rows, err := q.db.Query(ctx, sumBaz) + if err != nil { + return nil, err + } + defer rows.Close() + var items []SumBazRow + for rows.Next() { + var i SumBazRow + if err := rows.Scan(&i.Bar, &i.Quantity); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/query.sql b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/query.sql new file mode 100644 index 0000000000..3f51061f8b --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/query.sql @@ -0,0 +1,4 @@ +-- name: SumBaz :many +SELECT bar, coalesce(sum(baz), 0) as quantity +FROM foo +GROUP BY 1; diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/schema.sql b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/schema.sql new file mode 100644 index 0000000000..b7a16c0e28 --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE foo ( + bar text, + baz bigint +); + diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/sqlc.json b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/sqlc.json new file mode 100644 index 0000000000..f5e265377f --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pganalyze/sqlc.json @@ -0,0 +1,19 @@ +{ + "version": "1", + "cloud": { + "project": "01HAQMMECEYQYKFJN8MP16QC41" + }, + "packages": [ + { + "path": "go", + "engine": "postgresql", + "sql_package": "pgx/v5", + "database": { + "managed": true + }, + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pgx/v4/exec.json b/internal/endtoend/testdata/coalesce_as/postgresql/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/pgx/v5/exec.json b/internal/endtoend/testdata/coalesce_as/postgresql/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/coalesce_as/postgresql/stdlib/exec.json b/internal/endtoend/testdata/coalesce_as/postgresql/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/coalesce_as/postgresql/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/codegen_json/exec.json b/internal/endtoend/testdata/codegen_json/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/codegen_json/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/codegen_struct_field_names/stdlib/go/query.sql.go b/internal/endtoend/testdata/codegen_struct_field_names/stdlib/go/query.sql.go index 1cda1616eb..e9e1b43553 100644 --- a/internal/endtoend/testdata/codegen_struct_field_names/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/codegen_struct_field_names/stdlib/go/query.sql.go @@ -10,7 +10,7 @@ import ( ) const test = `-- name: test :one -SELECT id, !!!nobody,_,-would-believe---this-...?!, parent id from bar limit 1 +SELECT id, "!!!nobody,_,-would-believe---this-...?!", "parent id" from bar limit 1 ` func (q *Queries) test(ctx context.Context) (Bar, error) { diff --git a/internal/endtoend/testdata/cte_left_join/issue.md b/internal/endtoend/testdata/cte_left_join/issue.md new file mode 100644 index 0000000000..6027f3c6a8 --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1236 \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/exec.json b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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_left_join/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..0744a36cde --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/models.go @@ -0,0 +1,21 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Author struct { + ID int64 + Name string + Bio pgtype.Text +} + +type Fake struct { + ID int64 + Name string + Bio pgtype.Text +} 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 new file mode 100644 index 0000000000..98e03ba495 --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/go/query.sql.go @@ -0,0 +1,39 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const badQuery = `-- name: BadQuery :exec +WITH + q + AS ( + SELECT + authors.name, authors.bio + FROM + authors + LEFT JOIN fake ON authors.name = fake.name + ) +SELECT + name, bio +FROM + q AS c1 +WHERE c1.name = $1 +` + +type BadQueryRow struct { + Name string + Bio pgtype.Text +} + +func (q *Queries) BadQuery(ctx context.Context, dollar_1 pgtype.Text) error { + _, err := q.db.Exec(ctx, badQuery, dollar_1) + return err +} diff --git a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/query.sql new file mode 100644 index 0000000000..d201807360 --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/query.sql @@ -0,0 +1,15 @@ +-- name: BadQuery :exec +WITH + q + AS ( + SELECT + authors.name, authors.bio + FROM + authors + LEFT JOIN fake ON authors.name = fake.name + ) +SELECT + * +FROM + q AS c1 +WHERE c1.name = $1; \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..3d2f5be610 --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/schema.sql @@ -0,0 +1,11 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + +CREATE TABLE fake ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_left_join/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_left_join/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/cte_left_join/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_multiple_alias/issue.md b/internal/endtoend/testdata/cte_multiple_alias/issue.md new file mode 100644 index 0000000000..5e4ec565bb --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1237 \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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_multiple_alias/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..0744a36cde --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/models.go @@ -0,0 +1,21 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Author struct { + ID int64 + Name string + Bio pgtype.Text +} + +type Fake struct { + ID int64 + Name string + Bio pgtype.Text +} diff --git a/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..b6e66ed0be --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/go/query.sql.go @@ -0,0 +1,48 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const badQuery = `-- name: BadQuery :one +WITH + q + AS ( + SELECT + authors.name, authors.bio + FROM + authors + LEFT JOIN fake ON authors.name = fake.name + ) +SELECT + c1.name, c1.bio, c2.name, c2.bio +FROM + q AS c1, + q as c2 +` + +type BadQueryRow struct { + Name string + Bio pgtype.Text + Name_2 string + Bio_2 pgtype.Text +} + +func (q *Queries) BadQuery(ctx context.Context) (BadQueryRow, error) { + row := q.db.QueryRow(ctx, badQuery) + var i BadQueryRow + err := row.Scan( + &i.Name, + &i.Bio, + &i.Name_2, + &i.Bio_2, + ) + return i, err +} diff --git a/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/query.sql new file mode 100644 index 0000000000..75d770582f --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/query.sql @@ -0,0 +1,15 @@ +-- name: BadQuery :one +WITH + q + AS ( + SELECT + authors.name, authors.bio + FROM + authors + LEFT JOIN fake ON authors.name = fake.name + ) +SELECT + * +FROM + q AS c1, + q as c2; \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..3d2f5be610 --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/schema.sql @@ -0,0 +1,11 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + +CREATE TABLE fake ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_multiple_alias/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/cte_multiple_alias/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_recursive_employees/issue.md b/internal/endtoend/testdata/cte_recursive_employees/issue.md new file mode 100644 index 0000000000..2bc033582e --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1219 \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/exec.json b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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_recursive_employees/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..5e503d675f --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Employee struct { + ID int64 + Name string + Manager pgtype.Text +} diff --git a/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..e81ce16986 --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/go/query.sql.go @@ -0,0 +1,56 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const getSubordinates = `-- name: GetSubordinates :many +WITH RECURSIVE subordinates(name, manager) AS ( + SELECT + NULL, $1::TEXT + UNION + SELECT + s.manager, e.name + FROM + subordinates AS s + LEFT OUTER JOIN + employees AS e + ON + e.manager = s.manager + WHERE + s.manager IS NOT NULL +) +SELECT + s.name +FROM + subordinates AS s +WHERE + s.name != $1 +` + +func (q *Queries) GetSubordinates(ctx context.Context, name pgtype.Text) ([]pgtype.Text, error) { + rows, err := q.db.Query(ctx, getSubordinates, name) + if err != nil { + return nil, err + } + defer rows.Close() + var items []pgtype.Text + for rows.Next() { + var name pgtype.Text + if err := rows.Scan(&name); err != nil { + return nil, err + } + items = append(items, name) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/query.sql new file mode 100644 index 0000000000..00d490a4b9 --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/query.sql @@ -0,0 +1,22 @@ +-- name: GetSubordinates :many +WITH RECURSIVE subordinates(name, manager) AS ( + SELECT + NULL, sqlc.arg(name)::TEXT + UNION + SELECT + s.manager, e.name + FROM + subordinates AS s + LEFT OUTER JOIN + employees AS e + ON + e.manager = s.manager + WHERE + s.manager IS NOT NULL +) +SELECT + s.name +FROM + subordinates AS s +WHERE + s.name != sqlc.arg(name); \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..b95effb369 --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE employees ( + id BIGSERIAL PRIMARY KEY, + name text UNIQUE NOT NULL, + manager text REFERENCES employees(name) +); \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_recursive_employees/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_employees/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_recursive_star/issue.md b/internal/endtoend/testdata/cte_recursive_star/issue.md new file mode 100644 index 0000000000..2bc033582e --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1219 \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/exec.json b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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_recursive_star/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..962822a87a --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/models.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Dict struct { + ID string + AppID string + Code pgtype.Text + ParentCode string + Label string + Value pgtype.Text + Weight int32 + IsDefault bool + IsVirtual bool + Status int16 + CreateAt pgtype.Timestamptz + CreateBy string + UpdateAt pgtype.Timestamptz + UpdateBy pgtype.Text + IsDelete bool +} diff --git a/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..d96dd07b08 --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/go/query.sql.go @@ -0,0 +1,59 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const getDictTree = `-- name: GetDictTree :many +with recursive dictTree(id, code, parent_code, label, value, path, depth) AS ( + select id, code, parent_code, label, value, ARRAY[COALESCE((select id from dict where code=''),'virtual_root'), id], 1 as depth from dict where app_id = '1' and parent_code = '' and is_delete=false + union + select d.id, d.code, d.parent_code, d.label, d.value, t.path || ARRAY[d.id], t.depth+1 as depth from dict d join dictTree t on d.parent_code = t.code and not d.id = ANY(t.path) and d.is_delete=false +) +select id, code, parent_code, label, value, path, depth from dictTree d order by depth, parent_code +` + +type GetDictTreeRow struct { + ID string + Code pgtype.Text + ParentCode string + Label string + Value pgtype.Text + Path pgtype.Text + Depth int32 +} + +func (q *Queries) GetDictTree(ctx context.Context) ([]GetDictTreeRow, error) { + rows, err := q.db.Query(ctx, getDictTree) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetDictTreeRow + for rows.Next() { + var i GetDictTreeRow + if err := rows.Scan( + &i.ID, + &i.Code, + &i.ParentCode, + &i.Label, + &i.Value, + &i.Path, + &i.Depth, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/query.sql new file mode 100644 index 0000000000..a48253d0ab --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/query.sql @@ -0,0 +1,7 @@ +-- name: GetDictTree :many +with recursive dictTree(id, code, parent_code, label, value, path, depth) AS ( + select id, code, parent_code, label, value, ARRAY[COALESCE((select id from dict where code=''),'virtual_root'), id], 1 as depth from dict where app_id = '1' and parent_code = '' and is_delete=false + union + select d.id, d.code, d.parent_code, d.label, d.value, t.path || ARRAY[d.id], t.depth+1 as depth from dict d join dictTree t on d.parent_code = t.code and not d.id = ANY(t.path) and d.is_delete=false +) +select * from dictTree d order by depth, parent_code; \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..c4257ab8bb --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/schema.sql @@ -0,0 +1,17 @@ +create table dict( + id VARCHAR(36) PRIMARY KEY DEFAULT gen_random_uuid(), + app_id VARCHAR(36) NOT NULL, + code VARCHAR(64), + parent_code VARCHAR(64) NOT NULL, + label TEXT NOT NULL DEFAULT '', + value TEXT NULL, + weight INT NOT NULL DEFAULT 0, + is_default BOOLEAN NOT NULL DEFAULT false, + is_virtual BOOLEAN NOT NULL DEFAULT false, + status SMALLINT NOT NULL DEFAULT 1, + create_at TIMESTAMPTZ(0) NOT NULL DEFAULT now(), + create_by VARCHAR(36) NOT NULL DEFAULT '', + update_at TIMESTAMPTZ(0), + update_by VARCHAR(36), + is_delete BOOLEAN NOT NULL DEFAULT false +); diff --git a/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_recursive_star/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/cte_recursive_star/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_select_one/issue.md b/internal/endtoend/testdata/cte_select_one/issue.md new file mode 100644 index 0000000000..f87f5c14cb --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/issue.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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_select_one/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..de69b77ccc --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/go/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const testRecursive = `-- name: TestRecursive :one +WITH t1 AS ( + select 1 as foo +) +SELECT foo FROM t1 +` + +func (q *Queries) TestRecursive(ctx context.Context) (int32, error) { + row := q.db.QueryRow(ctx, testRecursive) + var foo int32 + err := row.Scan(&foo) + return foo, err +} diff --git a/internal/endtoend/testdata/cte_select_one/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/query.sql new file mode 100644 index 0000000000..9f4fdf08de --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/query.sql @@ -0,0 +1,5 @@ +-- name: TestRecursive :one +WITH t1 AS ( + select 1 as foo +) +SELECT * FROM t1; \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_select_one/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..af3b9497d9 --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/schema.sql @@ -0,0 +1 @@ +-- TODO \ No newline at end of file diff --git a/internal/endtoend/testdata/cte_select_one/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_select_one/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/cte_select_one/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_with_in/postgresql/pganalyze/exec.json b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/db.go b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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_with_in/postgresql/pganalyze/go/models.go b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/models.go new file mode 100644 index 0000000000..6b81cce5f3 --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/models.go @@ -0,0 +1,20 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type L struct { + ID int64 + ParentID pgtype.Int4 +} + +type T struct { + ID int64 + LID pgtype.Int4 + F pgtype.Text +} diff --git a/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/query.sql.go b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/query.sql.go new file mode 100644 index 0000000000..2cfc581465 --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/go/query.sql.go @@ -0,0 +1,164 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const getAll = `-- name: GetAll :many +SELECT id, parent_id FROM L +` + +func (q *Queries) GetAll(ctx context.Context) ([]L, error) { + rows, err := q.db.Query(ctx, getAll) + if err != nil { + return nil, err + } + defer rows.Close() + var items []L + for rows.Next() { + var i L + if err := rows.Scan(&i.ID, &i.ParentID); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAll1 = `-- name: GetAll1 :many +with recursive cte as ( + select id, L_ID, F from T + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 +) select id, l_id, f from cte +` + +type GetAll1Row struct { + ID int64 + LID pgtype.Int4 + F pgtype.Text +} + +func (q *Queries) GetAll1(ctx context.Context, lID pgtype.Int4) ([]GetAll1Row, error) { + rows, err := q.db.Query(ctx, getAll1, lID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetAll1Row + for rows.Next() { + var i GetAll1Row + if err := rows.Scan(&i.ID, &i.LID, &i.F); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAll2 = `-- name: GetAll2 :many +with recursive cte as ( + select id, L_ID, F from T where T.ID=2 + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 +) select id, l_id, f from cte +` + +type GetAll2Row struct { + ID int64 + LID pgtype.Int4 + F pgtype.Text +} + +func (q *Queries) GetAll2(ctx context.Context, lID pgtype.Int4) ([]GetAll2Row, error) { + rows, err := q.db.Query(ctx, getAll2, lID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetAll2Row + for rows.Next() { + var i GetAll2Row + if err := rows.Scan(&i.ID, &i.LID, &i.F); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAll3 = `-- name: GetAll3 :many +select id from T where L_ID in( + with recursive cte as ( + select id, L_ID, F from T where T.ID =2 + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 + ) select l_id from cte +) +` + +func (q *Queries) GetAll3(ctx context.Context, dollar_1 pgtype.Int4) ([]int64, error) { + rows, err := q.db.Query(ctx, getAll3, dollar_1) + if err != nil { + return nil, err + } + defer rows.Close() + var items []int64 + for rows.Next() { + var id int64 + 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 getAll4 = `-- name: GetAll4 :many +select id from T where L_ID in( + with recursive L as ( + select id, L_ID, F from T where T.ID =2 + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 + ) select l_id from L +) +` + +func (q *Queries) GetAll4(ctx context.Context, lID pgtype.Int4) ([]int64, error) { + rows, err := q.db.Query(ctx, getAll4, lID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []int64 + for rows.Next() { + var id int64 + 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 +} diff --git a/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/query.sql b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/query.sql new file mode 100644 index 0000000000..4a27713beb --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/query.sql @@ -0,0 +1,34 @@ +-- name: GetAll :many +SELECT * FROM L; + +-- name: GetAll1 :many +with recursive cte as ( + select id, L_ID, F from T + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 +) select id, l_id, f from cte; + +-- name: GetAll2 :many +with recursive cte as ( + select id, L_ID, F from T where T.ID=2 + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 +) select id, l_id, f from cte; + +-- name: GetAll4 :many +select id from T where L_ID in( + with recursive L as ( + select id, L_ID, F from T where T.ID =2 + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 + ) select l_id from L +); + +-- name: GetAll3 :many +select id from T where L_ID in( + with recursive cte as ( + select id, L_ID, F from T where T.ID =2 + union all + select c.id, c.L_ID, c.F from T as c where c.L_ID = $1 + ) select l_id from cte +); diff --git a/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/schema.sql b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/schema.sql new file mode 100644 index 0000000000..cf970e3331 --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/schema.sql @@ -0,0 +1,12 @@ +-- https://github.com/sqlc-dev/sqlc/issues/2153 + +CREATE TABLE L ( + id BIGSERIAL PRIMARY KEY, + parent_id int null +); + +CREATE TABLE T ( + id BIGSERIAL PRIMARY KEY, + L_ID int, + F varchar(256) +); diff --git a/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/sqlc.json b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/sqlc.json new file mode 100644 index 0000000000..4905a64003 --- /dev/null +++ b/internal/endtoend/testdata/cte_with_in/postgresql/pganalyze/sqlc.json @@ -0,0 +1,14 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "name": "querytest", + "engine": "postgresql", + "schema": "schema.sql", + "queries": "query.sql", + "sql_package": "pgx/v5" + } + ] +} + diff --git a/internal/endtoend/testdata/diff_output/stderr.txt b/internal/endtoend/testdata/diff_output/stderr.txt index 4db48d8d44..e7e455436e 100644 --- a/internal/endtoend/testdata/diff_output/stderr.txt +++ b/internal/endtoend/testdata/diff_output/stderr.txt @@ -52,3 +52,4 @@ + err := row.Scan(&column_1) + return column_1, err +} + diff --git a/internal/endtoend/testdata/enum/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/enum/postgresql/pgx/v4/go/query.sql.go index 03d3d94c31..3d89ba41e9 100644 --- a/internal/endtoend/testdata/enum/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/enum/postgresql/pgx/v4/go/query.sql.go @@ -58,18 +58,16 @@ func (q *Queries) GetAll(ctx context.Context, db DBTX) ([]User, error) { const newUser = `-- name: NewUser :exec INSERT INTO users ( - id, first_name, last_name, age, shoe_size, shirt_size ) VALUES -($1, $2, $3, $4, $5, $6) +($1, $2, $3, $4, $5) ` type NewUserParams struct { - ID int32 FirstName string LastName sql.NullString Age int32 @@ -79,7 +77,6 @@ type NewUserParams struct { func (q *Queries) NewUser(ctx context.Context, db DBTX, arg NewUserParams) error { _, err := db.Exec(ctx, newUser, - arg.ID, arg.FirstName, arg.LastName, arg.Age, diff --git a/internal/endtoend/testdata/enum/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/enum/postgresql/pgx/v4/query.sql index 5b7ed159f9..818eafd10d 100644 --- a/internal/endtoend/testdata/enum/postgresql/pgx/v4/query.sql +++ b/internal/endtoend/testdata/enum/postgresql/pgx/v4/query.sql @@ -3,14 +3,13 @@ SELECT * FROM users; -- name: NewUser :exec INSERT INTO users ( - id, first_name, last_name, age, shoe_size, shirt_size ) VALUES -($1, $2, $3, $4, $5, $6); +($1, $2, $3, $4, $5); -- name: UpdateSizes :exec UPDATE users diff --git a/internal/endtoend/testdata/enum/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/enum/postgresql/pgx/v5/go/query.sql.go index 7e3b425e15..d3b28468ad 100644 --- a/internal/endtoend/testdata/enum/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/enum/postgresql/pgx/v5/go/query.sql.go @@ -59,18 +59,16 @@ func (q *Queries) GetAll(ctx context.Context, db DBTX) ([]User, error) { const newUser = `-- name: NewUser :exec INSERT INTO users ( - id, first_name, last_name, age, shoe_size, shirt_size ) VALUES -($1, $2, $3, $4, $5, $6) +($1, $2, $3, $4, $5) ` type NewUserParams struct { - ID int32 FirstName string LastName pgtype.Text Age int32 @@ -80,7 +78,6 @@ type NewUserParams struct { func (q *Queries) NewUser(ctx context.Context, db DBTX, arg NewUserParams) error { _, err := db.Exec(ctx, newUser, - arg.ID, arg.FirstName, arg.LastName, arg.Age, diff --git a/internal/endtoend/testdata/enum/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/enum/postgresql/pgx/v5/query.sql index 5b7ed159f9..1902312c1a 100644 --- a/internal/endtoend/testdata/enum/postgresql/pgx/v5/query.sql +++ b/internal/endtoend/testdata/enum/postgresql/pgx/v5/query.sql @@ -3,14 +3,13 @@ SELECT * FROM users; -- name: NewUser :exec INSERT INTO users ( - id, first_name, last_name, age, shoe_size, shirt_size ) VALUES -($1, $2, $3, $4, $5, $6); +($1, $2, $3, $4, $5); -- name: UpdateSizes :exec UPDATE users @@ -19,4 +18,4 @@ WHERE id = $1; -- name: DeleteBySize :exec DELETE FROM users -WHERE shoe_size = $1 AND shirt_size = $2; \ No newline at end of file +WHERE shoe_size = $1 AND shirt_size = $2; diff --git a/internal/endtoend/testdata/enum/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/enum/postgresql/stdlib/go/query.sql.go index 037574c405..ef7aab07c0 100644 --- a/internal/endtoend/testdata/enum/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/enum/postgresql/stdlib/go/query.sql.go @@ -61,18 +61,16 @@ func (q *Queries) GetAll(ctx context.Context, db DBTX) ([]User, error) { const newUser = `-- name: NewUser :exec INSERT INTO users ( - id, first_name, last_name, age, shoe_size, shirt_size ) VALUES -($1, $2, $3, $4, $5, $6) +($1, $2, $3, $4, $5) ` type NewUserParams struct { - ID int32 FirstName string LastName sql.NullString Age int32 @@ -82,7 +80,6 @@ type NewUserParams struct { func (q *Queries) NewUser(ctx context.Context, db DBTX, arg NewUserParams) error { _, err := db.ExecContext(ctx, newUser, - arg.ID, arg.FirstName, arg.LastName, arg.Age, diff --git a/internal/endtoend/testdata/enum/postgresql/stdlib/query.sql b/internal/endtoend/testdata/enum/postgresql/stdlib/query.sql index 5b7ed159f9..1902312c1a 100644 --- a/internal/endtoend/testdata/enum/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/enum/postgresql/stdlib/query.sql @@ -3,14 +3,13 @@ SELECT * FROM users; -- name: NewUser :exec INSERT INTO users ( - id, first_name, last_name, age, shoe_size, shirt_size ) VALUES -($1, $2, $3, $4, $5, $6); +($1, $2, $3, $4, $5); -- name: UpdateSizes :exec UPDATE users @@ -19,4 +18,4 @@ WHERE id = $1; -- name: DeleteBySize :exec DELETE FROM users -WHERE shoe_size = $1 AND shirt_size = $2; \ No newline at end of file +WHERE shoe_size = $1 AND shirt_size = $2; diff --git a/internal/endtoend/testdata/func_aggregate/pganalyze/exec.json b/internal/endtoend/testdata/func_aggregate/pganalyze/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/func_aggregate/pganalyze/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/func_aggregate/go/db.go b/internal/endtoend/testdata/func_aggregate/pganalyze/go/db.go similarity index 100% rename from internal/endtoend/testdata/func_aggregate/go/db.go rename to internal/endtoend/testdata/func_aggregate/pganalyze/go/db.go diff --git a/internal/endtoend/testdata/func_aggregate/go/models.go b/internal/endtoend/testdata/func_aggregate/pganalyze/go/models.go similarity index 100% rename from internal/endtoend/testdata/func_aggregate/go/models.go rename to internal/endtoend/testdata/func_aggregate/pganalyze/go/models.go diff --git a/internal/endtoend/testdata/func_aggregate/pganalyze/go/query.sql.go b/internal/endtoend/testdata/func_aggregate/pganalyze/go/query.sql.go new file mode 100644 index 0000000000..ab5777dd4e --- /dev/null +++ b/internal/endtoend/testdata/func_aggregate/pganalyze/go/query.sql.go @@ -0,0 +1,22 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const percentile = `-- name: Percentile :one +select percentile_disc(0.5) within group (order by authors.name) +from authors +` + +func (q *Queries) Percentile(ctx context.Context) (string, error) { + row := q.db.QueryRowContext(ctx, percentile) + var percentile_disc string + err := row.Scan(&percentile_disc) + return percentile_disc, err +} diff --git a/internal/endtoend/testdata/func_aggregate/query.sql b/internal/endtoend/testdata/func_aggregate/pganalyze/query.sql similarity index 100% rename from internal/endtoend/testdata/func_aggregate/query.sql rename to internal/endtoend/testdata/func_aggregate/pganalyze/query.sql diff --git a/internal/endtoend/testdata/func_aggregate/schema.sql b/internal/endtoend/testdata/func_aggregate/pganalyze/schema.sql similarity index 100% rename from internal/endtoend/testdata/func_aggregate/schema.sql rename to internal/endtoend/testdata/func_aggregate/pganalyze/schema.sql diff --git a/internal/endtoend/testdata/func_aggregate/sqlc.json b/internal/endtoend/testdata/func_aggregate/pganalyze/sqlc.json similarity index 100% rename from internal/endtoend/testdata/func_aggregate/sqlc.json rename to internal/endtoend/testdata/func_aggregate/pganalyze/sqlc.json diff --git a/internal/endtoend/testdata/func_aggregate/postgresql/exec.json b/internal/endtoend/testdata/func_aggregate/postgresql/exec.json new file mode 100644 index 0000000000..c16f123ce3 --- /dev/null +++ b/internal/endtoend/testdata/func_aggregate/postgresql/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} \ No newline at end of file diff --git a/internal/endtoend/testdata/func_return/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/func_aggregate/postgresql/go/db.go similarity index 100% rename from internal/endtoend/testdata/func_return/postgresql/stdlib/go/db.go rename to internal/endtoend/testdata/func_aggregate/postgresql/go/db.go diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/models.go b/internal/endtoend/testdata/func_aggregate/postgresql/go/models.go similarity index 64% rename from internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/models.go rename to internal/endtoend/testdata/func_aggregate/postgresql/go/models.go index 18a0ebb3e7..2727f2e2de 100644 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/models.go +++ b/internal/endtoend/testdata/func_aggregate/postgresql/go/models.go @@ -8,7 +8,8 @@ import ( "database/sql" ) -type User struct { - ID sql.NullInt32 - FirstName string +type Author struct { + ID int64 + Name string + Bio sql.NullString } diff --git a/internal/endtoend/testdata/func_aggregate/go/query.sql.go b/internal/endtoend/testdata/func_aggregate/postgresql/go/query.sql.go similarity index 100% rename from internal/endtoend/testdata/func_aggregate/go/query.sql.go rename to internal/endtoend/testdata/func_aggregate/postgresql/go/query.sql.go diff --git a/internal/endtoend/testdata/func_aggregate/postgresql/query.sql b/internal/endtoend/testdata/func_aggregate/postgresql/query.sql new file mode 100644 index 0000000000..cdda8237c9 --- /dev/null +++ b/internal/endtoend/testdata/func_aggregate/postgresql/query.sql @@ -0,0 +1,3 @@ +-- name: Percentile :one +select percentile_disc(0.5) within group (order by authors.name) +from authors; diff --git a/internal/endtoend/testdata/func_aggregate/postgresql/schema.sql b/internal/endtoend/testdata/func_aggregate/postgresql/schema.sql new file mode 100644 index 0000000000..290bbe1642 --- /dev/null +++ b/internal/endtoend/testdata/func_aggregate/postgresql/schema.sql @@ -0,0 +1,7 @@ +-- Example queries for sqlc +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + diff --git a/internal/endtoend/testdata/func_aggregate/postgresql/sqlc.json b/internal/endtoend/testdata/func_aggregate/postgresql/sqlc.json new file mode 100644 index 0000000000..dbe55e66a6 --- /dev/null +++ b/internal/endtoend/testdata/func_aggregate/postgresql/sqlc.json @@ -0,0 +1,11 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/go/query.sql.go index b5d079a8b9..d1d80d7fa1 100644 --- a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/go/query.sql.go @@ -15,8 +15,8 @@ const demo = `-- name: Demo :one SELECT uuid_generate_v5('7c4597a0-8cfa-4c19-8da0-b8474a36440d', $1)::uuid as col1 ` -func (q *Queries) Demo(ctx context.Context, uuidGenerateV5 interface{}) (uuid.UUID, error) { - row := q.db.QueryRow(ctx, demo, uuidGenerateV5) +func (q *Queries) Demo(ctx context.Context, name string) (uuid.UUID, error) { + row := q.db.QueryRow(ctx, demo, name) var col1 uuid.UUID err := row.Scan(&col1) return col1, err diff --git a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/schema.sql b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/schema.sql index e69de29bb2..682131d3bf 100644 --- a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/schema.sql +++ b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v4/schema.sql @@ -0,0 +1 @@ +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; \ No newline at end of file diff --git a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/go/query.sql.go index 973118c2bb..e32d8a6983 100644 --- a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/go/query.sql.go @@ -15,8 +15,8 @@ const demo = `-- name: Demo :one SELECT uuid_generate_v5('7c4597a0-8cfa-4c19-8da0-b8474a36440d', $1)::uuid as col1 ` -func (q *Queries) Demo(ctx context.Context, uuidGenerateV5 interface{}) (pgtype.UUID, error) { - row := q.db.QueryRow(ctx, demo, uuidGenerateV5) +func (q *Queries) Demo(ctx context.Context, name string) (pgtype.UUID, error) { + row := q.db.QueryRow(ctx, demo, name) var col1 pgtype.UUID err := row.Scan(&col1) return col1, err diff --git a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/schema.sql index e69de29bb2..682131d3bf 100644 --- a/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/schema.sql +++ b/internal/endtoend/testdata/func_call_cast/postgresql/pgx/v5/schema.sql @@ -0,0 +1 @@ +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; \ No newline at end of file diff --git a/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/go/query.sql.go index 55b1e9432b..0d22c19e45 100644 --- a/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/go/query.sql.go @@ -15,8 +15,8 @@ const demo = `-- name: Demo :one SELECT uuid_generate_v5('7c4597a0-8cfa-4c19-8da0-b8474a36440d', $1)::uuid as col1 ` -func (q *Queries) Demo(ctx context.Context, uuidGenerateV5 interface{}) (uuid.UUID, error) { - row := q.db.QueryRowContext(ctx, demo, uuidGenerateV5) +func (q *Queries) Demo(ctx context.Context, name string) (uuid.UUID, error) { + row := q.db.QueryRowContext(ctx, demo, name) var col1 uuid.UUID err := row.Scan(&col1) return col1, err diff --git a/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/schema.sql index e69de29bb2..682131d3bf 100644 --- a/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/schema.sql +++ b/internal/endtoend/testdata/func_call_cast/postgresql/stdlib/schema.sql @@ -0,0 +1 @@ +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; \ No newline at end of file diff --git a/internal/endtoend/testdata/func_match_types/postgresql/go/models.go b/internal/endtoend/testdata/func_match_types/postgresql/go/models.go index 4d16f82923..315221c85b 100644 --- a/internal/endtoend/testdata/func_match_types/postgresql/go/models.go +++ b/internal/endtoend/testdata/func_match_types/postgresql/go/models.go @@ -10,5 +10,5 @@ type Book struct { ID int32 Title string Author string - Pages string + Pages int32 } diff --git a/internal/endtoend/testdata/func_match_types/postgresql/schema.sql b/internal/endtoend/testdata/func_match_types/postgresql/schema.sql index db9215b088..cf91381e3f 100644 --- a/internal/endtoend/testdata/func_match_types/postgresql/schema.sql +++ b/internal/endtoend/testdata/func_match_types/postgresql/schema.sql @@ -1,6 +1,6 @@ CREATE TABLE books ( - id integer PRIMARY KEY, - title text NOT NULL, - author text NOT NULL, - pages numeric NOT NULL + id integer PRIMARY KEY, + title text NOT NULL, + author text NOT NULL, + pages integer NOT NULL ); diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/query.sql.go deleted file mode 100644 index 4bca42ab68..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/query.sql.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.22.0 -// source: query.sql - -package querytest - -import ( - "context" - - "github.com/jackc/pgtype" -) - -const generateSeries = `-- name: GenerateSeries :many -SELECT ($1::inet) + i -FROM generate_series(0, $2::int) AS i -LIMIT 1 -` - -type GenerateSeriesParams struct { - Column1 pgtype.Inet - Column2 int32 -} - -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int32, error) { - rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) - if err != nil { - return nil, err - } - defer rows.Close() - var items []int32 - for rows.Next() { - var column_1 int32 - if err := rows.Scan(&column_1); err != nil { - return nil, err - } - items = append(items, column_1) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDate = `-- name: GetDate :one -SELECT from CURRENT_DATE -` - -type GetDateRow struct { -} - -func (q *Queries) GetDate(ctx context.Context) (GetDateRow, error) { - row := q.db.QueryRow(ctx, getDate) - var i GetDateRow - err := row.Scan() - return i, err -} - -const getUsers = `-- name: GetUsers :many -SELECT id, first_name -FROM users_func() -WHERE first_name != '' -` - -func (q *Queries) GetUsers(ctx context.Context) ([]User, error) { - rows, err := q.db.Query(ctx, getUsers) - 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.FirstName); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/func_return/postgresql/pgx/v4/query.sql deleted file mode 100644 index c2fe0b941b..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/query.sql +++ /dev/null @@ -1,13 +0,0 @@ - -/* name: GetUsers :many */ -SELECT * -FROM users_func() -WHERE first_name != ''; - -/* name: GenerateSeries :many */ -SELECT ($1::inet) + i -FROM generate_series(0, $2::int) AS i -LIMIT 1; - -/* name: GetDate :one */ -SELECT * from CURRENT_DATE; \ No newline at end of file diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/schema.sql b/internal/endtoend/testdata/func_return/postgresql/pgx/v4/schema.sql deleted file mode 100644 index adc43acdb6..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/schema.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE users ( - id integer, - first_name varchar(255) NOT NULL -); - -CREATE FUNCTION users_func() RETURNS SETOF users AS $func$ - BEGIN - SELECT * - FROM users; - END; -$func$ LANGUAGE plpgsql; diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/query.sql.go deleted file mode 100644 index 19f4053aa9..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/go/query.sql.go +++ /dev/null @@ -1,82 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.22.0 -// source: query.sql - -package querytest - -import ( - "context" - "net/netip" -) - -const generateSeries = `-- name: GenerateSeries :many -SELECT ($1::inet) + i -FROM generate_series(0, $2::int) AS i -LIMIT 1 -` - -type GenerateSeriesParams struct { - Column1 netip.Addr - Column2 int32 -} - -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int32, error) { - rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) - if err != nil { - return nil, err - } - defer rows.Close() - var items []int32 - for rows.Next() { - var column_1 int32 - if err := rows.Scan(&column_1); err != nil { - return nil, err - } - items = append(items, column_1) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDate = `-- name: GetDate :one -SELECT from CURRENT_DATE -` - -type GetDateRow struct { -} - -func (q *Queries) GetDate(ctx context.Context) (GetDateRow, error) { - row := q.db.QueryRow(ctx, getDate) - var i GetDateRow - err := row.Scan() - return i, err -} - -const getUsers = `-- name: GetUsers :many -SELECT id, first_name -FROM users_func() -WHERE first_name != '' -` - -func (q *Queries) GetUsers(ctx context.Context) ([]User, error) { - rows, err := q.db.Query(ctx, getUsers) - 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.FirstName); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/func_return/postgresql/pgx/v5/query.sql deleted file mode 100644 index c2fe0b941b..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/query.sql +++ /dev/null @@ -1,13 +0,0 @@ - -/* name: GetUsers :many */ -SELECT * -FROM users_func() -WHERE first_name != ''; - -/* name: GenerateSeries :many */ -SELECT ($1::inet) + i -FROM generate_series(0, $2::int) AS i -LIMIT 1; - -/* name: GetDate :one */ -SELECT * from CURRENT_DATE; \ No newline at end of file diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/func_return/postgresql/pgx/v5/schema.sql deleted file mode 100644 index adc43acdb6..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/schema.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE users ( - id integer, - first_name varchar(255) NOT NULL -); - -CREATE FUNCTION users_func() RETURNS SETOF users AS $func$ - BEGIN - SELECT * - FROM users; - END; -$func$ LANGUAGE plpgsql; diff --git a/internal/endtoend/testdata/func_return/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/func_return/postgresql/stdlib/go/query.sql.go deleted file mode 100644 index 5bda0df50d..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/stdlib/go/query.sql.go +++ /dev/null @@ -1,89 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.22.0 -// source: query.sql - -package querytest - -import ( - "context" - - "github.com/sqlc-dev/pqtype" -) - -const generateSeries = `-- name: GenerateSeries :many -SELECT ($1::inet) + i -FROM generate_series(0, $2::int) AS i -LIMIT 1 -` - -type GenerateSeriesParams struct { - Column1 pqtype.Inet - Column2 int32 -} - -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int32, error) { - rows, err := q.db.QueryContext(ctx, generateSeries, arg.Column1, arg.Column2) - if err != nil { - return nil, err - } - defer rows.Close() - var items []int32 - for rows.Next() { - var column_1 int32 - if err := rows.Scan(&column_1); err != nil { - return nil, err - } - items = append(items, column_1) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDate = `-- name: GetDate :one -SELECT from CURRENT_DATE -` - -type GetDateRow struct { -} - -func (q *Queries) GetDate(ctx context.Context) (GetDateRow, error) { - row := q.db.QueryRowContext(ctx, getDate) - var i GetDateRow - err := row.Scan() - return i, err -} - -const getUsers = `-- name: GetUsers :many -SELECT id, first_name -FROM users_func() -WHERE first_name != '' -` - -func (q *Queries) GetUsers(ctx context.Context) ([]User, error) { - rows, err := q.db.QueryContext(ctx, getUsers) - 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.FirstName); 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/func_return/postgresql/stdlib/query.sql b/internal/endtoend/testdata/func_return/postgresql/stdlib/query.sql deleted file mode 100644 index c2fe0b941b..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/stdlib/query.sql +++ /dev/null @@ -1,13 +0,0 @@ - -/* name: GetUsers :many */ -SELECT * -FROM users_func() -WHERE first_name != ''; - -/* name: GenerateSeries :many */ -SELECT ($1::inet) + i -FROM generate_series(0, $2::int) AS i -LIMIT 1; - -/* name: GetDate :one */ -SELECT * from CURRENT_DATE; \ No newline at end of file diff --git a/internal/endtoend/testdata/func_return/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/func_return/postgresql/stdlib/schema.sql deleted file mode 100644 index adc43acdb6..0000000000 --- a/internal/endtoend/testdata/func_return/postgresql/stdlib/schema.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE users ( - id integer, - first_name varchar(255) NOT NULL -); - -CREATE FUNCTION users_func() RETURNS SETOF users AS $func$ - BEGIN - SELECT * - FROM users; - END; -$func$ LANGUAGE plpgsql; diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/exec.json b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/db.go b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/func_return_date/postgresql/pganalyze/go/models.go b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/query.sql.go b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/query.sql.go new file mode 100644 index 0000000000..9597c2cdeb --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/go/query.sql.go @@ -0,0 +1,23 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const getDate = `-- name: GetDate :one +SELECT now from NOW() +` + +func (q *Queries) GetDate(ctx context.Context) (pgtype.Timestamptz, error) { + row := q.db.QueryRow(ctx, getDate) + var now pgtype.Timestamptz + err := row.Scan(&now) + return now, err +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/query.sql b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/query.sql new file mode 100644 index 0000000000..8f71309953 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/query.sql @@ -0,0 +1,2 @@ +/* name: GetDate :one */ +SELECT * from NOW(); \ No newline at end of file diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/schema.sql b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v5/sqlc.json b/internal/endtoend/testdata/func_return_date/postgresql/pganalyze/sqlc.json similarity index 100% rename from internal/endtoend/testdata/func_return/postgresql/pgx/v5/sqlc.json rename to internal/endtoend/testdata/func_return_date/postgresql/pganalyze/sqlc.json diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/exec.json b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/db.go b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/func_return_date/postgresql/pgx/v5/go/models.go b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/query.sql.go new file mode 100644 index 0000000000..092a37679b --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/go/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const getDate = `-- name: GetDate :one +SELECT from CURRENT_DATE +` + +type GetDateRow struct { +} + +func (q *Queries) GetDate(ctx context.Context) (GetDateRow, error) { + row := q.db.QueryRow(ctx, getDate) + var i GetDateRow + err := row.Scan() + return i, err +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/query.sql new file mode 100644 index 0000000000..b5696a969e --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/query.sql @@ -0,0 +1,2 @@ +/* name: GetDate :one */ +SELECT * from CURRENT_DATE; diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/sqlc.json b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/sqlc.json new file mode 100644 index 0000000000..32ede07158 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/pgx/v5/sqlc.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "sql_package": "pgx/v5", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/stdlib/exec.json b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..a457fb76b2 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/func_return_date/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..e6f9c7e038 --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const getDate = `-- name: GetDate :one +SELECT from CURRENT_DATE +` + +type GetDateRow struct { +} + +func (q *Queries) GetDate(ctx context.Context) (GetDateRow, error) { + row := q.db.QueryRowContext(ctx, getDate) + var i GetDateRow + err := row.Scan() + return i, err +} diff --git a/internal/endtoend/testdata/func_return_date/postgresql/stdlib/query.sql b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..b5696a969e --- /dev/null +++ b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/query.sql @@ -0,0 +1,2 @@ +/* name: GetDate :one */ +SELECT * from CURRENT_DATE; diff --git a/internal/endtoend/testdata/func_return_date/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/func_return/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/func_return_date/postgresql/stdlib/sqlc.json similarity index 100% rename from internal/endtoend/testdata/func_return/postgresql/stdlib/sqlc.json rename to internal/endtoend/testdata/func_return_date/postgresql/stdlib/sqlc.json diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/db.go b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/db.go similarity index 100% rename from internal/endtoend/testdata/func_return/postgresql/pgx/v4/go/db.go rename to internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/db.go diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/models.go b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/query.sql.go new file mode 100644 index 0000000000..7167ba9f5b --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/go/query.sql.go @@ -0,0 +1,41 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const generateSeries = `-- name: GenerateSeries :many +SELECT ($1::int) + i +FROM generate_series(0, $2::int) AS i +LIMIT 1 +` + +type GenerateSeriesParams struct { + Column1 int32 + Column2 int32 +} + +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int32, error) { + rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) + if err != nil { + return nil, err + } + defer rows.Close() + var items []int32 + for rows.Next() { + var column_1 int32 + if err := rows.Scan(&column_1); err != nil { + return nil, err + } + items = append(items, column_1) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/query.sql new file mode 100644 index 0000000000..ac5a434493 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/query.sql @@ -0,0 +1,4 @@ +/* name: GenerateSeries :many */ +SELECT ($1::int) + i +FROM generate_series(0, $2::int) AS i +LIMIT 1; diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/schema.sql b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/func_return/postgresql/pgx/v4/sqlc.json b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/sqlc.json similarity index 100% rename from internal/endtoend/testdata/func_return/postgresql/pgx/v4/sqlc.json rename to internal/endtoend/testdata/func_return_series/postgresql/pgx/v4/sqlc.json diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/db.go b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/func_return_series/postgresql/pgx/v5/go/models.go b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/query.sql.go new file mode 100644 index 0000000000..7167ba9f5b --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/go/query.sql.go @@ -0,0 +1,41 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const generateSeries = `-- name: GenerateSeries :many +SELECT ($1::int) + i +FROM generate_series(0, $2::int) AS i +LIMIT 1 +` + +type GenerateSeriesParams struct { + Column1 int32 + Column2 int32 +} + +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int32, error) { + rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) + if err != nil { + return nil, err + } + defer rows.Close() + var items []int32 + for rows.Next() { + var column_1 int32 + if err := rows.Scan(&column_1); err != nil { + return nil, err + } + items = append(items, column_1) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/query.sql new file mode 100644 index 0000000000..ac5a434493 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/query.sql @@ -0,0 +1,4 @@ +/* name: GenerateSeries :many */ +SELECT ($1::int) + i +FROM generate_series(0, $2::int) AS i +LIMIT 1; diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/sqlc.json b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/sqlc.json new file mode 100644 index 0000000000..32ede07158 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/pgx/v5/sqlc.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "sql_package": "pgx/v5", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..a457fb76b2 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/func_return_series/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..172574ab22 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/models.go @@ -0,0 +1,7 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () diff --git a/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..563fd9df33 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,44 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const generateSeries = `-- name: GenerateSeries :many +SELECT ($1::int) + i +FROM generate_series(0, $2::int) AS i +LIMIT 1 +` + +type GenerateSeriesParams struct { + Column1 int32 + Column2 int32 +} + +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int32, error) { + rows, err := q.db.QueryContext(ctx, generateSeries, arg.Column1, arg.Column2) + if err != nil { + return nil, err + } + defer rows.Close() + var items []int32 + for rows.Next() { + var column_1 int32 + if err := rows.Scan(&column_1); err != nil { + return nil, err + } + items = append(items, column_1) + } + 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/func_return_series/postgresql/stdlib/query.sql b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..ac5a434493 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/query.sql @@ -0,0 +1,4 @@ +/* name: GenerateSeries :many */ +SELECT ($1::int) + i +FROM generate_series(0, $2::int) AS i +LIMIT 1; diff --git a/internal/endtoend/testdata/func_return_series/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/func_return_series/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..f717ca2e66 --- /dev/null +++ b/internal/endtoend/testdata/func_return_series/postgresql/stdlib/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/func_variadic/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/func_variadic/postgresql/stdlib/go/query.sql.go index 5ad9d9edda..07cd383acf 100644 --- a/internal/endtoend/testdata/func_variadic/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/func_variadic/postgresql/stdlib/go/query.sql.go @@ -14,25 +14,25 @@ const updateJ = `-- name: UpdateJ :exec UPDATE test SET - j = jsonb_build_object($1, $2, $3, $4) + j = jsonb_build_object($1::text, $2::text, $3::text, $4::text) WHERE id = $5 ` type UpdateJParams struct { - JsonbBuildObject interface{} - JsonbBuildObject_2 interface{} - JsonbBuildObject_3 interface{} - JsonbBuildObject_4 interface{} - ID sql.NullInt32 + Column1 string + Column2 string + Column3 string + Column4 string + ID sql.NullInt32 } func (q *Queries) UpdateJ(ctx context.Context, arg UpdateJParams) error { _, err := q.db.ExecContext(ctx, updateJ, - arg.JsonbBuildObject, - arg.JsonbBuildObject_2, - arg.JsonbBuildObject_3, - arg.JsonbBuildObject_4, + arg.Column1, + arg.Column2, + arg.Column3, + arg.Column4, arg.ID, ) return err diff --git a/internal/endtoend/testdata/func_variadic/postgresql/stdlib/query.sql b/internal/endtoend/testdata/func_variadic/postgresql/stdlib/query.sql index c3f9b32b36..235e7cbb90 100644 --- a/internal/endtoend/testdata/func_variadic/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/func_variadic/postgresql/stdlib/query.sql @@ -2,6 +2,6 @@ UPDATE test SET - j = jsonb_build_object($1, $2, $3, $4) + j = jsonb_build_object($1::text, $2::text, $3::text, $4::text) WHERE id = $5; \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/query.sql index 41b0289d23..fad60fef89 100644 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/query.sql +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (bar text); - -- name: InsertFoo :exec INSERT INTO foo (bar) -SELECT 1, $1, $2; +SELECT 1, $1, $2; \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/schema.sql b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/schema.sql new file mode 100644 index 0000000000..be35e943bd --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text); \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/sqlc.json b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/sqlc.json index 9403bd0279..d1244c9e7a 100644 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/sqlc.json +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v4", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr.txt deleted file mode 100644 index 063b2a149a..0000000000 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:4:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr/base.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr/base.txt new file mode 100644 index 0000000000..77fedb8c3a --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr/base.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:1:1: INSERT has more expressions than target columns \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr/managed-db.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr/managed-db.txt new file mode 100644 index 0000000000..7448a74a95 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v4/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:3:11: INSERT has more expressions than target columns \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/query.sql index 41b0289d23..fad60fef89 100644 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/query.sql +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (bar text); - -- name: InsertFoo :exec INSERT INTO foo (bar) -SELECT 1, $1, $2; +SELECT 1, $1, $2; \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/schema.sql new file mode 100644 index 0000000000..be35e943bd --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text); \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/sqlc.json b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/sqlc.json index 6645ccbd1b..32ede07158 100644 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/sqlc.json +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v5", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr.txt deleted file mode 100644 index 063b2a149a..0000000000 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:4:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr/base.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr/base.txt new file mode 100644 index 0000000000..77fedb8c3a --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr/base.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:1:1: INSERT has more expressions than target columns \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr/managed-db.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr/managed-db.txt new file mode 100644 index 0000000000..7448a74a95 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/pgx/v5/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:3:11: INSERT has more expressions than target columns \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/query.sql b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/query.sql index 41b0289d23..fad60fef89 100644 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (bar text); - -- name: InsertFoo :exec INSERT INTO foo (bar) -SELECT 1, $1, $2; +SELECT 1, $1, $2; \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/schema.sql new file mode 100644 index 0000000000..be35e943bd --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text); \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/sqlc.json index de427d069f..cd518671ac 100644 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/sqlc.json +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/sqlc.json @@ -5,7 +5,7 @@ "engine": "postgresql", "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr.txt deleted file mode 100644 index 063b2a149a..0000000000 --- a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:4:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr/base.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr/base.txt new file mode 100644 index 0000000000..77fedb8c3a --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr/base.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:1:1: INSERT has more expressions than target columns \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr/managed-db.txt b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr/managed-db.txt new file mode 100644 index 0000000000..95a26a4d4f --- /dev/null +++ b/internal/endtoend/testdata/insert_select_invalid/postgresql/stdlib/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:3:11: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/insert_select_param/issue.md b/internal/endtoend/testdata/insert_select_param/issue.md new file mode 100644 index 0000000000..bbb421e88d --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1328 \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_param/postgresql/pgx/exec.json b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/db.go b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/insert_select_param/postgresql/pgx/go/models.go b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..b320134bd5 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Author struct { + ID int64 + Name string + Bio pgtype.Text +} diff --git a/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..7bee61fcc9 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/go/query.sql.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const insertSelect = `-- name: InsertSelect :exec +INSERT INTO authors (id, name, bio) +SELECT $1, name, bio +FROM authors +WHERE name = $2 +` + +type InsertSelectParams struct { + ID pgtype.Int8 + Name pgtype.Text +} + +func (q *Queries) InsertSelect(ctx context.Context, arg InsertSelectParams) error { + _, err := q.db.Exec(ctx, insertSelect, arg.ID, arg.Name) + return err +} diff --git a/internal/endtoend/testdata/insert_select_param/postgresql/pgx/query.sql b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/query.sql new file mode 100644 index 0000000000..ab990b0339 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/query.sql @@ -0,0 +1,5 @@ +-- name: InsertSelect :exec +INSERT INTO authors (id, name, bio) +SELECT @id, name, bio +FROM authors +WHERE name = @name; \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_param/postgresql/pgx/schema.sql b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..6684317695 --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_select_param/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/insert_select_param/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/insert_select_param/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/insert_values_only/issue.md b/internal/endtoend/testdata/insert_values_only/issue.md new file mode 100644 index 0000000000..a7ea8fc1ac --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/938 \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_values_only/postgresql/pgx/exec.json b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/db.go b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/insert_values_only/postgresql/pgx/go/models.go b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..84227cc11f --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/models.go @@ -0,0 +1,12 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () + +type Status struct { + ID int32 + Name string +} diff --git a/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..69ef568232 --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/go/query.sql.go @@ -0,0 +1,26 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const insertStatus = `-- name: InsertStatus :exec +INSERT INTO status VALUES ($1, $2) +` + +type InsertStatusParams struct { + Column1 pgtype.Int4 + Column2 pgtype.Text +} + +func (q *Queries) InsertStatus(ctx context.Context, arg InsertStatusParams) error { + _, err := q.db.Exec(ctx, insertStatus, arg.Column1, arg.Column2) + return err +} diff --git a/internal/endtoend/testdata/insert_values_only/postgresql/pgx/query.sql b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/query.sql new file mode 100644 index 0000000000..97313e7b17 --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/query.sql @@ -0,0 +1,2 @@ +-- name: InsertStatus :exec +INSERT INTO status VALUES ($1, $2); \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_values_only/postgresql/pgx/schema.sql b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..fc8f305d1e --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/schema.sql @@ -0,0 +1,6 @@ +CREATE TABLE status +( + id integer, + name varchar(100) NOT NULL, + PRIMARY KEY(id) +); \ No newline at end of file diff --git a/internal/endtoend/testdata/insert_values_only/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/insert_values_only/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..5dc63e3f91 --- /dev/null +++ b/internal/endtoend/testdata/insert_values_only/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" diff --git a/internal/endtoend/testdata/interval/pgx/v4/exec.json b/internal/endtoend/testdata/interval/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/interval/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/interval/pgx/v5/exec.json b/internal/endtoend/testdata/interval/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/interval/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/interval/stdlib/exec.json b/internal/endtoend/testdata/interval/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/interval/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v4/schema.sql b/internal/endtoend/testdata/invalid_func_args/pgx/v4/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v4/sqlc.json b/internal/endtoend/testdata/invalid_func_args/pgx/v4/sqlc.json index 9403bd0279..d1244c9e7a 100644 --- a/internal/endtoend/testdata/invalid_func_args/pgx/v4/sqlc.json +++ b/internal/endtoend/testdata/invalid_func_args/pgx/v4/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v4", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr.txt b/internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr/base.txt similarity index 100% rename from internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr.txt rename to internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr/base.txt diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr/managed-db.txt new file mode 100644 index 0000000000..34430f733e --- /dev/null +++ b/internal/endtoend/testdata/invalid_func_args/pgx/v4/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:1:8: function random(integer) does not exist diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v5/schema.sql b/internal/endtoend/testdata/invalid_func_args/pgx/v5/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v5/sqlc.json b/internal/endtoend/testdata/invalid_func_args/pgx/v5/sqlc.json index 6645ccbd1b..32ede07158 100644 --- a/internal/endtoend/testdata/invalid_func_args/pgx/v5/sqlc.json +++ b/internal/endtoend/testdata/invalid_func_args/pgx/v5/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v5", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr.txt b/internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr/base.txt similarity index 100% rename from internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr.txt rename to internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr/base.txt diff --git a/internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr/managed-db.txt new file mode 100644 index 0000000000..34430f733e --- /dev/null +++ b/internal/endtoend/testdata/invalid_func_args/pgx/v5/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:1:8: function random(integer) does not exist diff --git a/internal/endtoend/testdata/invalid_func_args/stdlib/schema.sql b/internal/endtoend/testdata/invalid_func_args/stdlib/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/invalid_func_args/stdlib/sqlc.json b/internal/endtoend/testdata/invalid_func_args/stdlib/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/invalid_func_args/stdlib/sqlc.json +++ b/internal/endtoend/testdata/invalid_func_args/stdlib/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_func_args/stdlib/stderr.txt b/internal/endtoend/testdata/invalid_func_args/stdlib/stderr/base.txt similarity index 100% rename from internal/endtoend/testdata/invalid_func_args/stdlib/stderr.txt rename to internal/endtoend/testdata/invalid_func_args/stdlib/stderr/base.txt diff --git a/internal/endtoend/testdata/invalid_func_args/stdlib/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_func_args/stdlib/stderr/managed-db.txt new file mode 100644 index 0000000000..34430f733e --- /dev/null +++ b/internal/endtoend/testdata/invalid_func_args/stdlib/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:1:8: function random(integer) does not exist diff --git a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/query.sql b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/query.sql index fdfa7e4e05..8275f8cfe1 100644 --- a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/query.sql +++ b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/query.sql @@ -1,10 +1,4 @@ -CREATE TABLE authors ( - id BIGSERIAL PRIMARY KEY, - name text NOT NULL, - bio text -); - -- name: ListAuthors :many SELECT * FROM authors -GROUP BY invalid_reference; +GROUP BY invalid_reference; \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/schema.sql b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/schema.sql new file mode 100644 index 0000000000..69b607d902 --- /dev/null +++ b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/sqlc.json b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/sqlc.json index af57681f66..a590361309 100644 --- a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/sqlc.json +++ b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/sqlc.json @@ -5,7 +5,7 @@ "path": "go", "engine": "postgresql", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr.txt b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr.txt deleted file mode 100644 index e9dd12bc6f..0000000000 --- a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:10:10: column reference "invalid_reference" not found diff --git a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr/base.txt b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr/base.txt new file mode 100644 index 0000000000..d686d4f4d8 --- /dev/null +++ b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr/base.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:4:10: column reference "invalid_reference" not found diff --git a/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr/managed-db.txt new file mode 100644 index 0000000000..d13cdbaf62 --- /dev/null +++ b/internal/endtoend/testdata/invalid_group_by_reference/postgresql/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:4:22: column "invalid_reference" does not exist diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/issue.md b/internal/endtoend/testdata/invalid_insert_unknown_column/issue.md new file mode 100644 index 0000000000..70cc5f22a5 --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/381 diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/db.go b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/db.go new file mode 100644 index 0000000000..bcfcc9d2f4 --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package db + +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/invalid_insert_unknown_column/postgresql/pgx/db/models.go b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/models.go new file mode 100644 index 0000000000..62f0b05e93 --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package db + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Author struct { + ID int64 + Name string + Bio pgtype.Text +} diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/query.sql.go b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/query.sql.go new file mode 100644 index 0000000000..ebde66829e --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/db/query.sql.go @@ -0,0 +1,33 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package db + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const createAuthor = `-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio, missing_column +) VALUES ( + $1, $2, true +) +RETURNING id, name, bio +` + +type CreateAuthorParams struct { + Name string + Bio pgtype.Text +} + +func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (Author, error) { + row := q.db.QueryRow(ctx, createAuthor, arg.Name, arg.Bio) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + return i, err +} diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/exec.json b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/query.sql b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/query.sql new file mode 100644 index 0000000000..db75df36e8 --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/query.sql @@ -0,0 +1,7 @@ +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio, missing_column +) VALUES ( + $1, $2, true +) +RETURNING *; diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/schema.sql b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..69b607d902 --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/sqlc.json b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/sqlc.json new file mode 100644 index 0000000000..7b7c623e56 --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/sqlc.json @@ -0,0 +1,19 @@ +{ + "version": "1", + "cloud": { + "project": "01HAQMMECEYQYKFJN8MP16QC41" + }, + "packages": [ + { + "path": "db", + "engine": "postgresql", + "database": { + "managed": true + }, + "sql_package": "pgx/v5", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} + diff --git a/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/stderr.txt b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/stderr.txt new file mode 100644 index 0000000000..60421d56bd --- /dev/null +++ b/internal/endtoend/testdata/invalid_insert_unknown_column/postgresql/pgx/stderr.txt @@ -0,0 +1,2 @@ +# package db +query.sql:3:14: column "missing_column" of relation "authors" does not exist \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/query.sql b/internal/endtoend/testdata/invalid_params/pgx/v4/query.sql index e65eb9970d..8a798cbb8c 100644 --- a/internal/endtoend/testdata/invalid_params/pgx/v4/query.sql +++ b/internal/endtoend/testdata/invalid_params/pgx/v4/query.sql @@ -1,9 +1,7 @@ -CREATE TABLE bar (id serial not null); - -- name: baz :one SELECT foo FROM bar WHERE baz = $4; --- name: bar +-- name: bar :one SELECT foo FROM bar WHERE baz = $1 AND baz = $3; -- name: foo :one diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/schema.sql b/internal/endtoend/testdata/invalid_params/pgx/v4/schema.sql new file mode 100644 index 0000000000..b7ee888d47 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/pgx/v4/schema.sql @@ -0,0 +1 @@ +CREATE TABLE bar (id serial not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/sqlc.json b/internal/endtoend/testdata/invalid_params/pgx/v4/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/invalid_params/pgx/v4/sqlc.json +++ b/internal/endtoend/testdata/invalid_params/pgx/v4/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/stderr.txt b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr.txt deleted file mode 100644 index 722c3e2408..0000000000 --- a/internal/endtoend/testdata/invalid_params/pgx/v4/stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -# package querytest -query.sql:4:1: could not determine data type of parameter $1 -query.sql:7:1: could not determine data type of parameter $2 -query.sql:10:8: column "foo" does not exist -query.sql:13:1: could not determine data type of parameter $2 diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt new file mode 100644 index 0000000000..c74f98d2c2 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/base.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:1:1: could not determine data type of parameter $1 +query.sql:5:1: could not determine data type of parameter $2 +query.sql:8:8: column "foo" does not exist +query.sql:11:1: could not determine data type of parameter $2 diff --git a/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/managed-db.txt new file mode 100644 index 0000000000..a7eff89c6a --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/pgx/v4/stderr/managed-db.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:2:8: column "foo" does not exist +query.sql:5:8: column "foo" does not exist +query.sql:8:8: column "foo" does not exist +query.sql:8:20: could not determine data type of parameter $3 diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/query.sql b/internal/endtoend/testdata/invalid_params/pgx/v5/query.sql index e65eb9970d..8a798cbb8c 100644 --- a/internal/endtoend/testdata/invalid_params/pgx/v5/query.sql +++ b/internal/endtoend/testdata/invalid_params/pgx/v5/query.sql @@ -1,9 +1,7 @@ -CREATE TABLE bar (id serial not null); - -- name: baz :one SELECT foo FROM bar WHERE baz = $4; --- name: bar +-- name: bar :one SELECT foo FROM bar WHERE baz = $1 AND baz = $3; -- name: foo :one diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/schema.sql b/internal/endtoend/testdata/invalid_params/pgx/v5/schema.sql new file mode 100644 index 0000000000..b7ee888d47 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/pgx/v5/schema.sql @@ -0,0 +1 @@ +CREATE TABLE bar (id serial not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/sqlc.json b/internal/endtoend/testdata/invalid_params/pgx/v5/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/invalid_params/pgx/v5/sqlc.json +++ b/internal/endtoend/testdata/invalid_params/pgx/v5/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/stderr.txt b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr.txt deleted file mode 100644 index 722c3e2408..0000000000 --- a/internal/endtoend/testdata/invalid_params/pgx/v5/stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -# package querytest -query.sql:4:1: could not determine data type of parameter $1 -query.sql:7:1: could not determine data type of parameter $2 -query.sql:10:8: column "foo" does not exist -query.sql:13:1: could not determine data type of parameter $2 diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt new file mode 100644 index 0000000000..c74f98d2c2 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/base.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:1:1: could not determine data type of parameter $1 +query.sql:5:1: could not determine data type of parameter $2 +query.sql:8:8: column "foo" does not exist +query.sql:11:1: could not determine data type of parameter $2 diff --git a/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/managed-db.txt new file mode 100644 index 0000000000..a7eff89c6a --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/pgx/v5/stderr/managed-db.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:2:8: column "foo" does not exist +query.sql:5:8: column "foo" does not exist +query.sql:8:8: column "foo" does not exist +query.sql:8:20: could not determine data type of parameter $3 diff --git a/internal/endtoend/testdata/invalid_params/stdlib/query.sql b/internal/endtoend/testdata/invalid_params/stdlib/query.sql index e65eb9970d..8a798cbb8c 100644 --- a/internal/endtoend/testdata/invalid_params/stdlib/query.sql +++ b/internal/endtoend/testdata/invalid_params/stdlib/query.sql @@ -1,9 +1,7 @@ -CREATE TABLE bar (id serial not null); - -- name: baz :one SELECT foo FROM bar WHERE baz = $4; --- name: bar +-- name: bar :one SELECT foo FROM bar WHERE baz = $1 AND baz = $3; -- name: foo :one diff --git a/internal/endtoend/testdata/invalid_params/stdlib/schema.sql b/internal/endtoend/testdata/invalid_params/stdlib/schema.sql new file mode 100644 index 0000000000..b7ee888d47 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/stdlib/schema.sql @@ -0,0 +1 @@ +CREATE TABLE bar (id serial not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_params/stdlib/sqlc.json b/internal/endtoend/testdata/invalid_params/stdlib/sqlc.json index 9403bd0279..d1244c9e7a 100644 --- a/internal/endtoend/testdata/invalid_params/stdlib/sqlc.json +++ b/internal/endtoend/testdata/invalid_params/stdlib/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v4", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_params/stdlib/stderr.txt b/internal/endtoend/testdata/invalid_params/stdlib/stderr.txt deleted file mode 100644 index 722c3e2408..0000000000 --- a/internal/endtoend/testdata/invalid_params/stdlib/stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -# package querytest -query.sql:4:1: could not determine data type of parameter $1 -query.sql:7:1: could not determine data type of parameter $2 -query.sql:10:8: column "foo" does not exist -query.sql:13:1: could not determine data type of parameter $2 diff --git a/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt b/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt new file mode 100644 index 0000000000..c74f98d2c2 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/stdlib/stderr/base.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:1:1: could not determine data type of parameter $1 +query.sql:5:1: could not determine data type of parameter $2 +query.sql:8:8: column "foo" does not exist +query.sql:11:1: could not determine data type of parameter $2 diff --git a/internal/endtoend/testdata/invalid_params/stdlib/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_params/stdlib/stderr/managed-db.txt new file mode 100644 index 0000000000..a7eff89c6a --- /dev/null +++ b/internal/endtoend/testdata/invalid_params/stdlib/stderr/managed-db.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:2:8: column "foo" does not exist +query.sql:5:8: column "foo" does not exist +query.sql:8:8: column "foo" does not exist +query.sql:8:20: could not determine data type of parameter $3 diff --git a/internal/endtoend/testdata/invalid_params_type_mismatch/issue.md b/internal/endtoend/testdata/invalid_params_type_mismatch/issue.md new file mode 100644 index 0000000000..93fc67215f --- /dev/null +++ b/internal/endtoend/testdata/invalid_params_type_mismatch/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/297 diff --git a/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/exec.json b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/query.sql b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/query.sql new file mode 100644 index 0000000000..c00d547905 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/query.sql @@ -0,0 +1,4 @@ +-- name: UpdateAuthor :exec +UPDATE authors +SET name = $1 +WHERE id = $1; diff --git a/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/schema.sql b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..e37a99f69f --- /dev/null +++ b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name boolean NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/sqlc.json b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/sqlc.json new file mode 100644 index 0000000000..14bbe813d1 --- /dev/null +++ b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/sqlc.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "packages": [ + { + "path": "db", + "engine": "postgresql", + "sql_package": "pgx/v5", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} + diff --git a/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/stderr.txt b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/stderr.txt new file mode 100644 index 0000000000..459c2d432f --- /dev/null +++ b/internal/endtoend/testdata/invalid_params_type_mismatch/postgresql/pgx/stderr.txt @@ -0,0 +1,2 @@ +# package db +query.sql:3:12: column "name" is of type boolean but expression is of type bigint diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/query.sql b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/query.sql index 49d9d60f1f..19aaf34061 100644 --- a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/query.sql +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/query.sql @@ -1,3 +1,5 @@ -CREATE TABLE foo (bar text not null, baz text not null); +-- name: InsertBarBaz :exec INSERT INTO foo (bar, baz) VALUES ($1); + +-- name: InsertBar :exec INSERT INTO foo (bar) VALUES ($1, $2); diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/schema.sql b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/schema.sql new file mode 100644 index 0000000000..4904704639 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text not null, baz text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/sqlc.json b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/sqlc.json index 9403bd0279..d1244c9e7a 100644 --- a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/sqlc.json +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v4", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr.txt b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr.txt deleted file mode 100644 index a496038cd1..0000000000 --- a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -# package querytest -query.sql:2:1: INSERT has more target columns than expressions -query.sql:3:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr/base.txt b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr/base.txt new file mode 100644 index 0000000000..1e06800df3 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr/base.txt @@ -0,0 +1,3 @@ +# package querytest +query.sql:1:1: INSERT has more target columns than expressions +query.sql:5:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr/managed-db.txt new file mode 100644 index 0000000000..143dcf6c0d --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v4/stderr/managed-db.txt @@ -0,0 +1,3 @@ +# package querytest +query.sql:2:23: INSERT has more target columns than expressions +query.sql:5:35: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/query.sql b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/query.sql index 49d9d60f1f..ef02b5e99c 100644 --- a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/query.sql +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/query.sql @@ -1,3 +1,5 @@ -CREATE TABLE foo (bar text not null, baz text not null); +-- name: InsertBarBaz :exec INSERT INTO foo (bar, baz) VALUES ($1); -INSERT INTO foo (bar) VALUES ($1, $2); + +-- name: InsertBar :exec +INSERT INTO foo (bar) VALUES ($1, $2); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/schema.sql b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/schema.sql new file mode 100644 index 0000000000..4904704639 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text not null, baz text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/sqlc.json b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/sqlc.json index 6645ccbd1b..32ede07158 100644 --- a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/sqlc.json +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v5", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr.txt b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr.txt deleted file mode 100644 index a496038cd1..0000000000 --- a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -# package querytest -query.sql:2:1: INSERT has more target columns than expressions -query.sql:3:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr/base.txt b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr/base.txt new file mode 100644 index 0000000000..1e06800df3 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr/base.txt @@ -0,0 +1,3 @@ +# package querytest +query.sql:1:1: INSERT has more target columns than expressions +query.sql:5:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr/managed-db.txt new file mode 100644 index 0000000000..143dcf6c0d --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/pgx/v5/stderr/managed-db.txt @@ -0,0 +1,3 @@ +# package querytest +query.sql:2:23: INSERT has more target columns than expressions +query.sql:5:35: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/stdlib/query.sql b/internal/endtoend/testdata/invalid_queries_bar/stdlib/query.sql index 49d9d60f1f..ef02b5e99c 100644 --- a/internal/endtoend/testdata/invalid_queries_bar/stdlib/query.sql +++ b/internal/endtoend/testdata/invalid_queries_bar/stdlib/query.sql @@ -1,3 +1,5 @@ -CREATE TABLE foo (bar text not null, baz text not null); +-- name: InsertBarBaz :exec INSERT INTO foo (bar, baz) VALUES ($1); -INSERT INTO foo (bar) VALUES ($1, $2); + +-- name: InsertBar :exec +INSERT INTO foo (bar) VALUES ($1, $2); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_bar/stdlib/schema.sql b/internal/endtoend/testdata/invalid_queries_bar/stdlib/schema.sql new file mode 100644 index 0000000000..4904704639 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/stdlib/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text not null, baz text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_bar/stdlib/sqlc.json b/internal/endtoend/testdata/invalid_queries_bar/stdlib/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/invalid_queries_bar/stdlib/sqlc.json +++ b/internal/endtoend/testdata/invalid_queries_bar/stdlib/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr.txt b/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr.txt deleted file mode 100644 index a496038cd1..0000000000 --- a/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -# package querytest -query.sql:2:1: INSERT has more target columns than expressions -query.sql:3:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr/base.txt b/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr/base.txt new file mode 100644 index 0000000000..1e06800df3 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr/base.txt @@ -0,0 +1,3 @@ +# package querytest +query.sql:1:1: INSERT has more target columns than expressions +query.sql:5:1: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr/managed-db.txt new file mode 100644 index 0000000000..143dcf6c0d --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_bar/stdlib/stderr/managed-db.txt @@ -0,0 +1,3 @@ +# package querytest +query.sql:2:23: INSERT has more target columns than expressions +query.sql:5:35: INSERT has more expressions than target columns diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/query.sql b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/query.sql index ef84ae740c..0e98fb622d 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/query.sql +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (id text not null); - -- name: ListFoos SELECT id FROM foo; diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/schema.sql b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/schema.sql new file mode 100644 index 0000000000..de835103e1 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (id text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/sqlc.json b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/sqlc.json index 9403bd0279..d1244c9e7a 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/sqlc.json +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v4", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt index cbe1df4446..6b0840fc37 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt @@ -1,7 +1,7 @@ # package querytest -query.sql:4:1: invalid query comment: -- name: ListFoos -query.sql:7:1: invalid query comment: -- name: ListFoos :one :many -query.sql:10:1: invalid query type: :two -query.sql:13:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause -query.sql:16:1: query "UpdateFoo" specifies parameter ":one" without containing a RETURNING clause -query.sql:19:1: query "InsertFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:1:1: invalid query comment: -- name: ListFoos +query.sql:5:1: invalid query comment: -- name: ListFoos :one :many +query.sql:8:1: invalid query type: :two +query.sql:11:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:14:1: query "UpdateFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:17:1: query "InsertFoo" specifies parameter ":one" without containing a RETURNING clause \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/query.sql b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/query.sql index ef84ae740c..0e98fb622d 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/query.sql +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (id text not null); - -- name: ListFoos SELECT id FROM foo; diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/schema.sql b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/schema.sql new file mode 100644 index 0000000000..de835103e1 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (id text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/sqlc.json b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/sqlc.json index 6645ccbd1b..32ede07158 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/sqlc.json +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v5", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt index cbe1df4446..6b0840fc37 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt +++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt @@ -1,7 +1,7 @@ # package querytest -query.sql:4:1: invalid query comment: -- name: ListFoos -query.sql:7:1: invalid query comment: -- name: ListFoos :one :many -query.sql:10:1: invalid query type: :two -query.sql:13:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause -query.sql:16:1: query "UpdateFoo" specifies parameter ":one" without containing a RETURNING clause -query.sql:19:1: query "InsertFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:1:1: invalid query comment: -- name: ListFoos +query.sql:5:1: invalid query comment: -- name: ListFoos :one :many +query.sql:8:1: invalid query type: :two +query.sql:11:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:14:1: query "UpdateFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:17:1: query "InsertFoo" specifies parameter ":one" without containing a RETURNING clause \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_foo/stdlib/query.sql b/internal/endtoend/testdata/invalid_queries_foo/stdlib/query.sql index ef84ae740c..0e98fb622d 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/stdlib/query.sql +++ b/internal/endtoend/testdata/invalid_queries_foo/stdlib/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (id text not null); - -- name: ListFoos SELECT id FROM foo; diff --git a/internal/endtoend/testdata/invalid_queries_foo/stdlib/schema.sql b/internal/endtoend/testdata/invalid_queries_foo/stdlib/schema.sql new file mode 100644 index 0000000000..de835103e1 --- /dev/null +++ b/internal/endtoend/testdata/invalid_queries_foo/stdlib/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (id text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_queries_foo/stdlib/sqlc.json b/internal/endtoend/testdata/invalid_queries_foo/stdlib/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/stdlib/sqlc.json +++ b/internal/endtoend/testdata/invalid_queries_foo/stdlib/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt b/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt index cbe1df4446..6b0840fc37 100644 --- a/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt +++ b/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt @@ -1,7 +1,7 @@ # package querytest -query.sql:4:1: invalid query comment: -- name: ListFoos -query.sql:7:1: invalid query comment: -- name: ListFoos :one :many -query.sql:10:1: invalid query type: :two -query.sql:13:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause -query.sql:16:1: query "UpdateFoo" specifies parameter ":one" without containing a RETURNING clause -query.sql:19:1: query "InsertFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:1:1: invalid query comment: -- name: ListFoos +query.sql:5:1: invalid query comment: -- name: ListFoos :one :many +query.sql:8:1: invalid query type: :two +query.sql:11:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:14:1: query "UpdateFoo" specifies parameter ":one" without containing a RETURNING clause +query.sql:17:1: query "InsertFoo" specifies parameter ":one" without containing a RETURNING clause \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_table_alias/postgresql/query.sql b/internal/endtoend/testdata/invalid_table_alias/postgresql/query.sql index 76e872ab65..f09a94b585 100644 --- a/internal/endtoend/testdata/invalid_table_alias/postgresql/query.sql +++ b/internal/endtoend/testdata/invalid_table_alias/postgresql/query.sql @@ -1,10 +1,3 @@ --- https://github.com/sqlc-dev/sqlc/issues/437 -CREATE TABLE authors ( - id BIGSERIAL PRIMARY KEY, - name text NOT NULL, - bio text -); - -- name: GetAuthor :one SELECT * FROM authors a diff --git a/internal/endtoend/testdata/invalid_table_alias/postgresql/schema.sql b/internal/endtoend/testdata/invalid_table_alias/postgresql/schema.sql new file mode 100644 index 0000000000..9c4b796adb --- /dev/null +++ b/internal/endtoend/testdata/invalid_table_alias/postgresql/schema.sql @@ -0,0 +1,6 @@ +-- https://github.com/sqlc-dev/sqlc/issues/437 +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_table_alias/postgresql/sqlc.json b/internal/endtoend/testdata/invalid_table_alias/postgresql/sqlc.json index af57681f66..a590361309 100644 --- a/internal/endtoend/testdata/invalid_table_alias/postgresql/sqlc.json +++ b/internal/endtoend/testdata/invalid_table_alias/postgresql/sqlc.json @@ -5,7 +5,7 @@ "path": "go", "engine": "postgresql", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr.txt b/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr.txt deleted file mode 100644 index 810c893a70..0000000000 --- a/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:11:9: table alias "p" does not exist diff --git a/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr/base.txt b/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr/base.txt new file mode 100644 index 0000000000..1eddeaac99 --- /dev/null +++ b/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr/base.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:4:9: table alias "p" does not exist diff --git a/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr/managed-db.txt b/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr/managed-db.txt new file mode 100644 index 0000000000..2de34ae434 --- /dev/null +++ b/internal/endtoend/testdata/invalid_table_alias/postgresql/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:5:3: missing FROM-clause entry for table "p" diff --git a/internal/endtoend/testdata/invalid_update_unknown_column/issue.md b/internal/endtoend/testdata/invalid_update_unknown_column/issue.md new file mode 100644 index 0000000000..822c605060 --- /dev/null +++ b/internal/endtoend/testdata/invalid_update_unknown_column/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/884 \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/exec.json b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/query.sql b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/query.sql new file mode 100644 index 0000000000..59d42df34b --- /dev/null +++ b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/query.sql @@ -0,0 +1,7 @@ +-- name: UpdateArticles :exec +UPDATE + public.articles +SET + is_deleted = TRUE +WHERE + id = $1; \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/schema.sql b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..6f94b60c66 --- /dev/null +++ b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE public.articles ( + id integer NOT NULL, + company integer NOT NULL, + name text NOT NULL, + sort_order integer DEFAULT 0 NOT NULL, + object_type smallint NOT NULL, + image text, + "group" integer, + notes text DEFAULT ''::text NOT NULL +); \ No newline at end of file diff --git a/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/invalid_update_unknown_column/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/invalid_update_unknown_column/postgresql/pgx/stderr.txt b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/stderr.txt new file mode 100644 index 0000000000..8260c8f792 --- /dev/null +++ b/internal/endtoend/testdata/invalid_update_unknown_column/postgresql/pgx/stderr.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:5:2: column "is_deleted" of relation "articles" does not exist \ No newline at end of file diff --git a/internal/endtoend/testdata/join_left/postgresql/exec.json b/internal/endtoend/testdata/join_left/postgresql/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/join_left/postgresql/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/join_validate_columns/issue.md b/internal/endtoend/testdata/join_validate_columns/issue.md new file mode 100644 index 0000000000..0050218dca --- /dev/null +++ b/internal/endtoend/testdata/join_validate_columns/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1239 \ No newline at end of file diff --git a/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/exec.json b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/query.sql b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/query.sql new file mode 100644 index 0000000000..8fe51af829 --- /dev/null +++ b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/query.sql @@ -0,0 +1,2 @@ +-- name: ListAuthors :many +SELECT * FROM authors JOIN books ON authors.id = book.author_id1; \ No newline at end of file diff --git a/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/schema.sql b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..d322893016 --- /dev/null +++ b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL +); + +CREATE TABLE books ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + author_id BIGSERIAL REFERENCES authors(id) +); \ No newline at end of file diff --git a/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..5dc63e3f91 --- /dev/null +++ b/internal/endtoend/testdata/join_validate_columns/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" diff --git a/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/stderr.txt b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/stderr.txt new file mode 100644 index 0000000000..0dfd315960 --- /dev/null +++ b/internal/endtoend/testdata/join_validate_columns/postgresql/pgx/stderr.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:2:65: missing FROM-clause entry for table "book" \ No newline at end of file diff --git a/internal/endtoend/testdata/json_param_type/issue.md b/internal/endtoend/testdata/json_param_type/issue.md new file mode 100644 index 0000000000..a04d7dab14 --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/743 \ No newline at end of file diff --git a/internal/endtoend/testdata/json_param_type/postgresql/pgx/exec.json b/internal/endtoend/testdata/json_param_type/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/db.go b/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/json_param_type/postgresql/pgx/go/models.go b/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..ecdaf1e0a2 --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/models.go @@ -0,0 +1,12 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () + +type User struct { + ID int32 + Metadata []byte +} diff --git a/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..850280d5b2 --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/postgresql/pgx/go/query.sql.go @@ -0,0 +1,23 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const findByAddress = `-- name: FindByAddress :one +SELECT id, metadata FROM "user" WHERE "metadata"->>'address1' = $1 LIMIT 1 +` + +func (q *Queries) FindByAddress(ctx context.Context, metadata pgtype.Text) (User, error) { + row := q.db.QueryRow(ctx, findByAddress, metadata) + var i User + err := row.Scan(&i.ID, &i.Metadata) + return i, err +} diff --git a/internal/endtoend/testdata/json_param_type/postgresql/pgx/query.sql b/internal/endtoend/testdata/json_param_type/postgresql/pgx/query.sql new file mode 100644 index 0000000000..61da05b8ec --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/postgresql/pgx/query.sql @@ -0,0 +1,2 @@ +-- name: FindByAddress :one +SELECT * FROM "user" WHERE "metadata"->>'address1' = $1 LIMIT 1; diff --git a/internal/endtoend/testdata/json_param_type/postgresql/pgx/schema.sql b/internal/endtoend/testdata/json_param_type/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..9d2499cf7c --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/postgresql/pgx/schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE "user" ( + "id" INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + "metadata" JSONB +); diff --git a/internal/endtoend/testdata/json_param_type/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/json_param_type/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/json_param_type/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/limit/pgx/v4/exec.json b/internal/endtoend/testdata/limit/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/limit/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/limit/pgx/v5/exec.json b/internal/endtoend/testdata/limit/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/limit/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/limit/stdlib/exec.json b/internal/endtoend/testdata/limit/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/limit/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v4/query.sql b/internal/endtoend/testdata/missing_semicolon/pgx/v4/query.sql index cdd62d5ad7..80c83545ce 100644 --- a/internal/endtoend/testdata/missing_semicolon/pgx/v4/query.sql +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v4/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (email text not null); - -- name: FirstQuery :many SELECT * FROM foo; diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v4/schema.sql b/internal/endtoend/testdata/missing_semicolon/pgx/v4/schema.sql new file mode 100644 index 0000000000..e2b1d89074 --- /dev/null +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v4/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (email text not null); diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v4/sqlc.json b/internal/endtoend/testdata/missing_semicolon/pgx/v4/sqlc.json index 9403bd0279..d1244c9e7a 100644 --- a/internal/endtoend/testdata/missing_semicolon/pgx/v4/sqlc.json +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v4/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v4", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v4/stderr.txt b/internal/endtoend/testdata/missing_semicolon/pgx/v4/stderr.txt index 5cd2f160b8..7544904cf6 100644 --- a/internal/endtoend/testdata/missing_semicolon/pgx/v4/stderr.txt +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v4/stderr.txt @@ -1,2 +1,2 @@ # package querytest -query.sql:7:1: missing semicolon at end of file +query.sql:5:1: missing semicolon at end of file diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v5/query.sql b/internal/endtoend/testdata/missing_semicolon/pgx/v5/query.sql index cdd62d5ad7..80c83545ce 100644 --- a/internal/endtoend/testdata/missing_semicolon/pgx/v5/query.sql +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v5/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (email text not null); - -- name: FirstQuery :many SELECT * FROM foo; diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v5/schema.sql b/internal/endtoend/testdata/missing_semicolon/pgx/v5/schema.sql new file mode 100644 index 0000000000..28f5b2d13e --- /dev/null +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v5/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (email text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v5/sqlc.json b/internal/endtoend/testdata/missing_semicolon/pgx/v5/sqlc.json index 6645ccbd1b..32ede07158 100644 --- a/internal/endtoend/testdata/missing_semicolon/pgx/v5/sqlc.json +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v5/sqlc.json @@ -6,7 +6,7 @@ "engine": "postgresql", "sql_package": "pgx/v5", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/missing_semicolon/pgx/v5/stderr.txt b/internal/endtoend/testdata/missing_semicolon/pgx/v5/stderr.txt index 5cd2f160b8..7544904cf6 100644 --- a/internal/endtoend/testdata/missing_semicolon/pgx/v5/stderr.txt +++ b/internal/endtoend/testdata/missing_semicolon/pgx/v5/stderr.txt @@ -1,2 +1,2 @@ # package querytest -query.sql:7:1: missing semicolon at end of file +query.sql:5:1: missing semicolon at end of file diff --git a/internal/endtoend/testdata/missing_semicolon/stdlib/query.sql b/internal/endtoend/testdata/missing_semicolon/stdlib/query.sql index cdd62d5ad7..80c83545ce 100644 --- a/internal/endtoend/testdata/missing_semicolon/stdlib/query.sql +++ b/internal/endtoend/testdata/missing_semicolon/stdlib/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE foo (email text not null); - -- name: FirstQuery :many SELECT * FROM foo; diff --git a/internal/endtoend/testdata/missing_semicolon/stdlib/schema.sql b/internal/endtoend/testdata/missing_semicolon/stdlib/schema.sql new file mode 100644 index 0000000000..28f5b2d13e --- /dev/null +++ b/internal/endtoend/testdata/missing_semicolon/stdlib/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (email text not null); \ No newline at end of file diff --git a/internal/endtoend/testdata/missing_semicolon/stdlib/sqlc.json b/internal/endtoend/testdata/missing_semicolon/stdlib/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/missing_semicolon/stdlib/sqlc.json +++ b/internal/endtoend/testdata/missing_semicolon/stdlib/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/missing_semicolon/stdlib/stderr.txt b/internal/endtoend/testdata/missing_semicolon/stdlib/stderr.txt index 5cd2f160b8..7544904cf6 100644 --- a/internal/endtoend/testdata/missing_semicolon/stdlib/stderr.txt +++ b/internal/endtoend/testdata/missing_semicolon/stdlib/stderr.txt @@ -1,2 +1,2 @@ # package querytest -query.sql:7:1: missing semicolon at end of file +query.sql:5:1: missing semicolon at end of file diff --git a/internal/endtoend/testdata/mix_param_types/postgresql/exec.json b/internal/endtoend/testdata/mix_param_types/postgresql/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/mix_param_types/postgresql/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/nested_select/issue.md b/internal/endtoend/testdata/nested_select/issue.md new file mode 100644 index 0000000000..2c10d6d8fe --- /dev/null +++ b/internal/endtoend/testdata/nested_select/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/708 diff --git a/internal/endtoend/testdata/nested_select/postgresql/pgx/exec.json b/internal/endtoend/testdata/nested_select/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/nested_select/postgresql/pgx/go/db.go b/internal/endtoend/testdata/nested_select/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/nested_select/postgresql/pgx/go/models.go b/internal/endtoend/testdata/nested_select/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..3cb0ee9c81 --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/go/models.go @@ -0,0 +1,13 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () + +type Test struct { + ID int64 + UpdateTime int64 + Count int64 +} diff --git a/internal/endtoend/testdata/nested_select/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/nested_select/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..2a46b8800d --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/go/query.sql.go @@ -0,0 +1,42 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const nestedSelect = `-- name: NestedSelect :one +SELECT latest.id, t.count +FROM ( + SELECT id, max(update_time) AS update_time + FROM test + WHERE id = ANY ($1::bigint[]) + -- ERROR HERE on update_time + AND update_time >= $2 + GROUP BY id +) latest +INNER JOIN test t USING (id, update_time) +` + +type NestedSelectParams struct { + IDs []int64 + StartTime pgtype.Int8 +} + +type NestedSelectRow struct { + ID int64 + Count int64 +} + +func (q *Queries) NestedSelect(ctx context.Context, arg NestedSelectParams) (NestedSelectRow, error) { + row := q.db.QueryRow(ctx, nestedSelect, arg.IDs, arg.StartTime) + var i NestedSelectRow + err := row.Scan(&i.ID, &i.Count) + return i, err +} diff --git a/internal/endtoend/testdata/nested_select/postgresql/pgx/query.sql b/internal/endtoend/testdata/nested_select/postgresql/pgx/query.sql new file mode 100644 index 0000000000..755521fa4a --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/query.sql @@ -0,0 +1,11 @@ +-- name: NestedSelect :one +SELECT latest.id, t.count +FROM ( + SELECT id, max(update_time) AS update_time + FROM test + WHERE id = ANY (sqlc.arg('IDs')::bigint[]) + -- ERROR HERE on update_time + AND update_time >= sqlc.arg('StartTime') + GROUP BY id +) latest +INNER JOIN test t USING (id, update_time); diff --git a/internal/endtoend/testdata/nested_select/postgresql/pgx/schema.sql b/internal/endtoend/testdata/nested_select/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..02f5f8203c --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE test ( + id bigint NOT NULL, + update_time bigint NOT NULL, + count bigint NOT NULL +); diff --git a/internal/endtoend/testdata/nested_select/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/nested_select/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..2f12715923 --- /dev/null +++ b/internal/endtoend/testdata/nested_select/postgresql/pgx/sqlc.yaml @@ -0,0 +1,14 @@ +version: "2" +cloud: + project: "01HAQMMECEYQYKFJN8MP16QC41" +sql: + - engine: "postgresql" + schema: "schema.sql" + queries: "query.sql" + gen: + go: + package: "querytest" + out: "go" + sql_package: "pgx/v5" + database: + managed: true diff --git a/internal/endtoend/testdata/null_if_type/issue.md b/internal/endtoend/testdata/null_if_type/issue.md new file mode 100644 index 0000000000..c83cc42660 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/133 diff --git a/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/db.go b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/db.go new file mode 100644 index 0000000000..3d2b5bf3a3 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package db + +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/null_if_type/postgresql/pganalyzer/db/models.go b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/models.go new file mode 100644 index 0000000000..e3c353f521 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/models.go @@ -0,0 +1,11 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package db + +import () + +type Author struct { + ID int64 +} diff --git a/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/query.sql.go b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/query.sql.go new file mode 100644 index 0000000000..62a6229d99 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/db/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getRestrictedId = `-- name: GetRestrictedId :one +SELECT + NULLIF(id, $1) restricted_id +FROM + author +` + +func (q *Queries) GetRestrictedId(ctx context.Context, id int64) (int64, error) { + row := q.db.QueryRowContext(ctx, getRestrictedId, id) + var restricted_id int64 + err := row.Scan(&restricted_id) + return restricted_id, err +} diff --git a/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/exec.json b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/query.sql b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/query.sql new file mode 100644 index 0000000000..fc800b4f6d --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/query.sql @@ -0,0 +1,5 @@ +-- name: GetRestrictedId :one +SELECT + NULLIF(id, $1) restricted_id +FROM + author; diff --git a/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/schema.sql b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/schema.sql new file mode 100644 index 0000000000..c1afecad09 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/schema.sql @@ -0,0 +1,3 @@ +CREATE TABLE author ( + id bigserial NOT NULL +); diff --git a/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/sqlc.json b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/sqlc.json new file mode 100644 index 0000000000..a682c52d42 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/pganalyzer/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "db", + "engine": "postgresql", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} + diff --git a/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/db.go b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/db.go new file mode 100644 index 0000000000..3d2b5bf3a3 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package db + +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/null_if_type/postgresql/stdlib/db/models.go b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/models.go new file mode 100644 index 0000000000..e3c353f521 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/models.go @@ -0,0 +1,11 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package db + +import () + +type Author struct { + ID int64 +} diff --git a/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/query.sql.go b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/query.sql.go new file mode 100644 index 0000000000..0c377bcb16 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/db/query.sql.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getRestrictedId = `-- name: GetRestrictedId :one +SELECT + NULLIF(id, $1) restricted_id +FROM + author +` + +func (q *Queries) GetRestrictedId(ctx context.Context, id int64) (bool, error) { + row := q.db.QueryRowContext(ctx, getRestrictedId, id) + var restricted_id bool + err := row.Scan(&restricted_id) + return restricted_id, err +} diff --git a/internal/endtoend/testdata/null_if_type/postgresql/stdlib/exec.json b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/null_if_type/postgresql/stdlib/query.sql b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..fc800b4f6d --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/query.sql @@ -0,0 +1,5 @@ +-- name: GetRestrictedId :one +SELECT + NULLIF(id, $1) restricted_id +FROM + author; diff --git a/internal/endtoend/testdata/null_if_type/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/schema.sql new file mode 100644 index 0000000000..c1afecad09 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/schema.sql @@ -0,0 +1,3 @@ +CREATE TABLE author ( + id bigserial NOT NULL +); diff --git a/internal/endtoend/testdata/null_if_type/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..a682c52d42 --- /dev/null +++ b/internal/endtoend/testdata/null_if_type/postgresql/stdlib/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "db", + "engine": "postgresql", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} + diff --git a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/go/query.sql.go index 6b8e361255..5225c21e02 100644 --- a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/go/query.sql.go @@ -7,27 +7,14 @@ package querytest import ( "context" - "database/sql" ) -const test = `-- name: Test :one -select txt from Demo -where txt ~~ '%' || $1 || '%' -` - -func (q *Queries) Test(ctx context.Context, val string) (string, error) { - row := q.db.QueryRow(ctx, test, val) - var txt string - err := row.Scan(&txt) - return txt, err -} - const test2 = `-- name: Test2 :one select txt from Demo -where txt like '%' || $1 || '%' +where txt like '%' || $1::text || '%' ` -func (q *Queries) Test2(ctx context.Context, val sql.NullString) (string, error) { +func (q *Queries) Test2(ctx context.Context, val string) (string, error) { row := q.db.QueryRow(ctx, test2, val) var txt string err := row.Scan(&txt) @@ -36,10 +23,10 @@ func (q *Queries) Test2(ctx context.Context, val sql.NullString) (string, error) const test3 = `-- name: Test3 :one select txt from Demo -where txt like concat('%', $1, '%') +where txt like concat('%', $1::text, '%') ` -func (q *Queries) Test3(ctx context.Context, val interface{}) (string, error) { +func (q *Queries) Test3(ctx context.Context, val string) (string, error) { row := q.db.QueryRow(ctx, test3, val) var txt string err := row.Scan(&txt) diff --git a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/query.sql index c4a088508c..3133d4c299 100644 --- a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/query.sql +++ b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v4/query.sql @@ -1,11 +1,7 @@ --- name: Test :one -select * from Demo -where txt ~~ '%' || sqlc.arg('val') || '%'; - -- name: Test2 :one select * from Demo -where txt like '%' || sqlc.arg('val') || '%'; +where txt like '%' || sqlc.arg('val')::text || '%'; -- name: Test3 :one select * from Demo -where txt like concat('%', sqlc.arg('val'), '%'); +where txt like concat('%', sqlc.arg('val')::text, '%'); diff --git a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/go/query.sql.go index 33d2f3cefc..5225c21e02 100644 --- a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/go/query.sql.go @@ -7,28 +7,14 @@ package querytest import ( "context" - - "github.com/jackc/pgx/v5/pgtype" ) -const test = `-- name: Test :one -select txt from Demo -where txt ~~ '%' || $1 || '%' -` - -func (q *Queries) Test(ctx context.Context, val string) (string, error) { - row := q.db.QueryRow(ctx, test, val) - var txt string - err := row.Scan(&txt) - return txt, err -} - const test2 = `-- name: Test2 :one select txt from Demo -where txt like '%' || $1 || '%' +where txt like '%' || $1::text || '%' ` -func (q *Queries) Test2(ctx context.Context, val pgtype.Text) (string, error) { +func (q *Queries) Test2(ctx context.Context, val string) (string, error) { row := q.db.QueryRow(ctx, test2, val) var txt string err := row.Scan(&txt) @@ -37,10 +23,10 @@ func (q *Queries) Test2(ctx context.Context, val pgtype.Text) (string, error) { const test3 = `-- name: Test3 :one select txt from Demo -where txt like concat('%', $1, '%') +where txt like concat('%', $1::text, '%') ` -func (q *Queries) Test3(ctx context.Context, val interface{}) (string, error) { +func (q *Queries) Test3(ctx context.Context, val string) (string, error) { row := q.db.QueryRow(ctx, test3, val) var txt string err := row.Scan(&txt) diff --git a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/query.sql index c4a088508c..3133d4c299 100644 --- a/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/query.sql +++ b/internal/endtoend/testdata/operator_string_concat/postgresql/pgx/v5/query.sql @@ -1,11 +1,7 @@ --- name: Test :one -select * from Demo -where txt ~~ '%' || sqlc.arg('val') || '%'; - -- name: Test2 :one select * from Demo -where txt like '%' || sqlc.arg('val') || '%'; +where txt like '%' || sqlc.arg('val')::text || '%'; -- name: Test3 :one select * from Demo -where txt like concat('%', sqlc.arg('val'), '%'); +where txt like concat('%', sqlc.arg('val')::text, '%'); diff --git a/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/go/query.sql.go index de8b4f6f9c..0b72579e02 100644 --- a/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/go/query.sql.go @@ -7,27 +7,14 @@ package querytest import ( "context" - "database/sql" ) -const test = `-- name: Test :one -select txt from Demo -where txt ~~ '%' || $1 || '%' -` - -func (q *Queries) Test(ctx context.Context, val string) (string, error) { - row := q.db.QueryRowContext(ctx, test, val) - var txt string - err := row.Scan(&txt) - return txt, err -} - const test2 = `-- name: Test2 :one select txt from Demo -where txt like '%' || $1 || '%' +where txt like '%' || $1::text || '%' ` -func (q *Queries) Test2(ctx context.Context, val sql.NullString) (string, error) { +func (q *Queries) Test2(ctx context.Context, val string) (string, error) { row := q.db.QueryRowContext(ctx, test2, val) var txt string err := row.Scan(&txt) @@ -36,10 +23,10 @@ func (q *Queries) Test2(ctx context.Context, val sql.NullString) (string, error) const test3 = `-- name: Test3 :one select txt from Demo -where txt like concat('%', $1, '%') +where txt like concat('%', $1::text, '%') ` -func (q *Queries) Test3(ctx context.Context, val interface{}) (string, error) { +func (q *Queries) Test3(ctx context.Context, val string) (string, error) { row := q.db.QueryRowContext(ctx, test3, val) var txt string err := row.Scan(&txt) diff --git a/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/query.sql b/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/query.sql index c4a088508c..3133d4c299 100644 --- a/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/operator_string_concat/postgresql/stdlib/query.sql @@ -1,11 +1,7 @@ --- name: Test :one -select * from Demo -where txt ~~ '%' || sqlc.arg('val') || '%'; - -- name: Test2 :one select * from Demo -where txt like '%' || sqlc.arg('val') || '%'; +where txt like '%' || sqlc.arg('val')::text || '%'; -- name: Test3 :one select * from Demo -where txt like concat('%', sqlc.arg('val'), '%'); +where txt like concat('%', sqlc.arg('val')::text, '%'); diff --git a/internal/endtoend/testdata/order_by_binds/pganalyze/exec.json b/internal/endtoend/testdata/order_by_binds/pganalyze/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/order_by_binds/pganalyze/go/db.go b/internal/endtoend/testdata/order_by_binds/pganalyze/go/db.go new file mode 100644 index 0000000000..a457fb76b2 --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/func_return/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/order_by_binds/pganalyze/go/models.go similarity index 64% rename from internal/endtoend/testdata/func_return/postgresql/stdlib/go/models.go rename to internal/endtoend/testdata/order_by_binds/pganalyze/go/models.go index 18a0ebb3e7..2727f2e2de 100644 --- a/internal/endtoend/testdata/func_return/postgresql/stdlib/go/models.go +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/go/models.go @@ -8,7 +8,8 @@ import ( "database/sql" ) -type User struct { - ID sql.NullInt32 - FirstName string +type Author struct { + ID int64 + Name string + Bio sql.NullString } diff --git a/internal/endtoend/testdata/order_by_binds/pganalyze/go/query.sql.go b/internal/endtoend/testdata/order_by_binds/pganalyze/go/query.sql.go new file mode 100644 index 0000000000..f3d1c12b6c --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/go/query.sql.go @@ -0,0 +1,74 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const listAuthorsColumnSort = `-- name: ListAuthorsColumnSort :many +SELECT id, name, bio FROM authors +WHERE id > $1 +ORDER BY CASE WHEN $2 = 'name' THEN name END +` + +type ListAuthorsColumnSortParams struct { + MinID int64 + SortColumn sql.NullString +} + +func (q *Queries) ListAuthorsColumnSort(ctx context.Context, arg ListAuthorsColumnSortParams) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsColumnSort, arg.MinID, arg.SortColumn) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); 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 +} + +const listAuthorsNameSort = `-- name: ListAuthorsNameSort :many +SELECT id, name, bio FROM authors +WHERE id > $1 +ORDER BY name ASC +` + +func (q *Queries) ListAuthorsNameSort(ctx context.Context, minID int64) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsNameSort, minID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); 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/order_by_binds/pganalyze/query.sql b/internal/endtoend/testdata/order_by_binds/pganalyze/query.sql new file mode 100644 index 0000000000..e662d8f06a --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/query.sql @@ -0,0 +1,9 @@ +-- name: ListAuthorsColumnSort :many +SELECT * FROM authors +WHERE id > sqlc.arg(min_id) +ORDER BY CASE WHEN sqlc.arg(sort_column) = 'name' THEN name END; + +-- name: ListAuthorsNameSort :many +SELECT * FROM authors +WHERE id > sqlc.arg(min_id) +ORDER BY name ASC; diff --git a/internal/endtoend/testdata/order_by_binds/pganalyze/schema.sql b/internal/endtoend/testdata/order_by_binds/pganalyze/schema.sql new file mode 100644 index 0000000000..f388f86c34 --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/schema.sql @@ -0,0 +1,6 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + diff --git a/internal/endtoend/testdata/order_by_binds/pganalyze/sqlc.json b/internal/endtoend/testdata/order_by_binds/pganalyze/sqlc.json new file mode 100644 index 0000000000..a590361309 --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/pganalyze/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/order_by_binds/postgresql/exec.json b/internal/endtoend/testdata/order_by_binds/postgresql/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/postgresql/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/order_by_non_existing_column/mysql/query.sql b/internal/endtoend/testdata/order_by_non_existing_column/mysql/query.sql deleted file mode 100644 index b1a4b4f638..0000000000 --- a/internal/endtoend/testdata/order_by_non_existing_column/mysql/query.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Example queries for sqlc -CREATE TABLE authors ( - id INT -); - --- name: ListAuthors :many -SELECT id FROM authors -ORDER BY adfadsf; \ No newline at end of file diff --git a/internal/endtoend/testdata/order_by_non_existing_column/mysql/sqlc.yaml b/internal/endtoend/testdata/order_by_non_existing_column/mysql/sqlc.yaml deleted file mode 100644 index c4b3831631..0000000000 --- a/internal/endtoend/testdata/order_by_non_existing_column/mysql/sqlc.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: 1 -packages: - - path: "go" - name: "querytest" - engine: "postgresql" - schema: "query.sql" - queries: "query.sql" \ No newline at end of file diff --git a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/query.sql b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/query.sql index b1a4b4f638..ba81cfdbc5 100644 --- a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/query.sql +++ b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/query.sql @@ -1,8 +1,3 @@ --- Example queries for sqlc -CREATE TABLE authors ( - id INT -); - -- name: ListAuthors :many SELECT id FROM authors ORDER BY adfadsf; \ No newline at end of file diff --git a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/schema.sql b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/schema.sql new file mode 100644 index 0000000000..acba948a66 --- /dev/null +++ b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/schema.sql @@ -0,0 +1,5 @@ +-- Example queries for sqlc +CREATE TABLE authors ( + id INT +); + diff --git a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/sqlc.yaml b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/sqlc.yaml index c4b3831631..9ae3fc0cae 100644 --- a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/sqlc.yaml +++ b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/sqlc.yaml @@ -3,5 +3,5 @@ packages: - path: "go" name: "querytest" engine: "postgresql" - schema: "query.sql" + schema: "schema.sql" queries: "query.sql" \ No newline at end of file diff --git a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr.txt b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr.txt deleted file mode 100644 index 166178156e..0000000000 --- a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:7:1: column reference "adfadsf" not found: if you want to skip this validation, set 'strict_order_by' to false diff --git a/internal/endtoend/testdata/order_by_non_existing_column/mysql/stderr.txt b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr/base.txt similarity index 54% rename from internal/endtoend/testdata/order_by_non_existing_column/mysql/stderr.txt rename to internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr/base.txt index 166178156e..5d9a674dc6 100644 --- a/internal/endtoend/testdata/order_by_non_existing_column/mysql/stderr.txt +++ b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr/base.txt @@ -1,2 +1,2 @@ # package querytest -query.sql:7:1: column reference "adfadsf" not found: if you want to skip this validation, set 'strict_order_by' to false +query.sql:1:1: column reference "adfadsf" not found: if you want to skip this validation, set 'strict_order_by' to false diff --git a/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr/managed-db.txt b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr/managed-db.txt new file mode 100644 index 0000000000..55cbb71463 --- /dev/null +++ b/internal/endtoend/testdata/order_by_non_existing_column/postgresql/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:3:10: column "adfadsf" does not exist diff --git a/internal/endtoend/testdata/order_by_non_existing_column/sqlite/query.sql b/internal/endtoend/testdata/order_by_non_existing_column/sqlite/query.sql deleted file mode 100644 index b1a4b4f638..0000000000 --- a/internal/endtoend/testdata/order_by_non_existing_column/sqlite/query.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Example queries for sqlc -CREATE TABLE authors ( - id INT -); - --- name: ListAuthors :many -SELECT id FROM authors -ORDER BY adfadsf; \ No newline at end of file diff --git a/internal/endtoend/testdata/order_by_non_existing_column/sqlite/sqlc.yaml b/internal/endtoend/testdata/order_by_non_existing_column/sqlite/sqlc.yaml deleted file mode 100644 index c4b3831631..0000000000 --- a/internal/endtoend/testdata/order_by_non_existing_column/sqlite/sqlc.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: 1 -packages: - - path: "go" - name: "querytest" - engine: "postgresql" - schema: "query.sql" - queries: "query.sql" \ No newline at end of file diff --git a/internal/endtoend/testdata/order_by_non_existing_column/sqlite/stderr.txt b/internal/endtoend/testdata/order_by_non_existing_column/sqlite/stderr.txt deleted file mode 100644 index 166178156e..0000000000 --- a/internal/endtoend/testdata/order_by_non_existing_column/sqlite/stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# package querytest -query.sql:7:1: column reference "adfadsf" not found: if you want to skip this validation, set 'strict_order_by' to false diff --git a/internal/endtoend/testdata/params_location/postgresql/pgx/v4/exec.json b/internal/endtoend/testdata/params_location/postgresql/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/params_location/postgresql/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/params_location/postgresql/pgx/v5/exec.json b/internal/endtoend/testdata/params_location/postgresql/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/params_location/postgresql/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/params_location/postgresql/stdlib/exec.json b/internal/endtoend/testdata/params_location/postgresql/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/params_location/postgresql/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/params_placeholder_in_left_expr/postgresql/exec.json b/internal/endtoend/testdata/params_placeholder_in_left_expr/postgresql/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/params_placeholder_in_left_expr/postgresql/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/pg_dump/exec.json b/internal/endtoend/testdata/pg_dump/exec.json new file mode 100644 index 0000000000..c16f123ce3 --- /dev/null +++ b/internal/endtoend/testdata/pg_dump/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} \ No newline at end of file diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/exec.json b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/go/query.sql.go index d9146cf3d8..a156949e24 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/go/query.sql.go @@ -8,12 +8,10 @@ package querytest import ( "context" "time" - - "github.com/jackc/pgtype" ) const generateSeries = `-- name: GenerateSeries :many -SELECT generate_series($1::timestamp, $2::timestamp) +SELECT generate_series($1::timestamp, $2::timestamp, '10 hours') ` type GenerateSeriesParams struct { @@ -21,15 +19,15 @@ type GenerateSeriesParams struct { Column2 time.Time `json:"column_2"` } -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]pgtype.Numeric, error) { +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int64, error) { rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) if err != nil { return nil, err } defer rows.Close() - var items []pgtype.Numeric + var items []int64 for rows.Next() { - var generate_series pgtype.Numeric + var generate_series int64 if err := rows.Scan(&generate_series); err != nil { return nil, err } diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/query.sql index c00238feda..3d483e89ec 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/query.sql +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v4/query.sql @@ -1,2 +1,2 @@ -- name: GenerateSeries :many -SELECT generate_series($1::timestamp, $2::timestamp); +SELECT generate_series($1::timestamp, $2::timestamp, '10 hours'); diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/exec.json b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/go/query.sql.go index de11bf7555..73d2f1855f 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/go/query.sql.go @@ -12,7 +12,7 @@ import ( ) const generateSeries = `-- name: GenerateSeries :many -SELECT generate_series($1::timestamp, $2::timestamp) +SELECT generate_series($1::timestamp, $2::timestamp, '10 hours') ` type GenerateSeriesParams struct { @@ -20,15 +20,15 @@ type GenerateSeriesParams struct { Column2 pgtype.Timestamp `json:"column_2"` } -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]pgtype.Numeric, error) { +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int64, error) { rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) if err != nil { return nil, err } defer rows.Close() - var items []pgtype.Numeric + var items []int64 for rows.Next() { - var generate_series pgtype.Numeric + var generate_series int64 if err := rows.Scan(&generate_series); err != nil { return nil, err } diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/query.sql index c00238feda..3d483e89ec 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/query.sql +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/v5/query.sql @@ -1,2 +1,2 @@ -- name: GenerateSeries :many -SELECT generate_series($1::timestamp, $2::timestamp); +SELECT generate_series($1::timestamp, $2::timestamp, '10 hours'); diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/exec.json b/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/go/query.sql.go index 26487587ed..392a60099f 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/go/query.sql.go @@ -11,7 +11,7 @@ import ( ) const generateSeries = `-- name: GenerateSeries :many -SELECT generate_series($1::timestamp, $2::timestamp) +SELECT generate_series($1::timestamp, $2::timestamp, '10 hours') ` type GenerateSeriesParams struct { @@ -19,15 +19,15 @@ type GenerateSeriesParams struct { Column2 time.Time `json:"column_2"` } -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]string, error) { +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]int64, error) { rows, err := q.db.QueryContext(ctx, generateSeries, arg.Column1, arg.Column2) if err != nil { return nil, err } defer rows.Close() - var items []string + var items []int64 for rows.Next() { - var generate_series string + var generate_series int64 if err := rows.Scan(&generate_series); err != nil { return nil, err } diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/query.sql b/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/query.sql index c00238feda..3d483e89ec 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/stdlib/query.sql @@ -1,2 +1,2 @@ -- name: GenerateSeries :many -SELECT generate_series($1::timestamp, $2::timestamp); +SELECT generate_series($1::timestamp, $2::timestamp, '10 hours'); diff --git a/internal/endtoend/testdata/pointer_type_import/postgresql/pgx/v5/exec.json b/internal/endtoend/testdata/pointer_type_import/postgresql/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/pointer_type_import/postgresql/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/process_plugin_sqlc_gen_json/exec.json b/internal/endtoend/testdata/process_plugin_sqlc_gen_json/exec.json index 5be7ac8c74..2e996ca79d 100644 --- a/internal/endtoend/testdata/process_plugin_sqlc_gen_json/exec.json +++ b/internal/endtoend/testdata/process_plugin_sqlc_gen_json/exec.json @@ -1,3 +1,3 @@ { - "process": "sqlc-gen-json" + "contexts": ["base"] } diff --git a/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/query.sql b/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/query.sql index 7afab0139a..b96c66b9b3 100644 --- a/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/query.sql +++ b/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/query.sql @@ -1,5 +1,3 @@ -CREATE TABLE bar (id serial not null, name text not null, primary key (id)); - -- name: DeleteBarByID :execrows DELETE FROM bar WHERE id = $1; diff --git a/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/schema.sql b/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/schema.sql new file mode 100644 index 0000000000..fd3ca97902 --- /dev/null +++ b/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/schema.sql @@ -0,0 +1 @@ +CREATE TABLE bar (id serial not null, name text not null, primary key (id)); \ No newline at end of file diff --git a/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/sqlc.json b/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/sqlc.json index 3a7bd37085..d431feabb5 100644 --- a/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/sqlc.json +++ b/internal/endtoend/testdata/query_parameter_limit/-1/python_postgresql/sqlc.json @@ -11,7 +11,7 @@ ], "sql": [ { - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql", "engine": "postgresql", "codegen": [ diff --git a/internal/endtoend/testdata/relation_does_not_exist/postgresql/schema.sql b/internal/endtoend/testdata/relation_does_not_exist/postgresql/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/relation_does_not_exist/postgresql/sqlc.json b/internal/endtoend/testdata/relation_does_not_exist/postgresql/sqlc.json index ac7c2ed829..dbe55e66a6 100644 --- a/internal/endtoend/testdata/relation_does_not_exist/postgresql/sqlc.json +++ b/internal/endtoend/testdata/relation_does_not_exist/postgresql/sqlc.json @@ -4,7 +4,7 @@ { "path": "go", "name": "querytest", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql" } ] diff --git a/internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr.txt b/internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr/base.txt similarity index 100% rename from internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr.txt rename to internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr/base.txt diff --git a/internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr/managed-db.txt b/internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr/managed-db.txt new file mode 100644 index 0000000000..5621f9739e --- /dev/null +++ b/internal/endtoend/testdata/relation_does_not_exist/postgresql/stderr/managed-db.txt @@ -0,0 +1,5 @@ +# package querytest +query.sql:2:15: relation "nonexisting_relation" does not exist +query.sql:5:15: relation "nonexisting_relation" does not exist +query.sql:8:8: relation "nonexisting_relation" does not exist +query.sql:11:13: relation "nonexisting_relation" does not exist diff --git a/internal/endtoend/testdata/select_limit/postgresql/pgx/v4/exec.json b/internal/endtoend/testdata/select_limit/postgresql/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/select_limit/postgresql/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/select_limit/postgresql/pgx/v5/exec.json b/internal/endtoend/testdata/select_limit/postgresql/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/select_limit/postgresql/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/select_limit/postgresql/stdlib/exec.json b/internal/endtoend/testdata/select_limit/postgresql/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/select_limit/postgresql/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/select_union/postgres/pgx/v4/exec.json b/internal/endtoend/testdata/select_union/postgres/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/select_union/postgres/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/select_union/postgres/pgx/v5/exec.json b/internal/endtoend/testdata/select_union/postgres/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/select_union/postgres/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/select_union/postgres/stdlib/exec.json b/internal/endtoend/testdata/select_union/postgres/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/select_union/postgres/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go index a904edc966..fa0c265bbd 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go @@ -54,7 +54,7 @@ func (q *Queries) GetUser(ctx context.Context, sub uuid.UUID) (uuid.UUID, error) const setDefaultName = `-- name: SetDefaultName :one UPDATE authors -SET name = "Default Name" +SET name = 'Default Name' WHERE id = $1 RETURNING id ` diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/query.sql index 3e209ba5a4..ca3fc5c6a4 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/query.sql +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/query.sql @@ -20,6 +20,6 @@ LIMIT 1; -- name: SetDefaultName :one UPDATE authors -SET name = "Default Name" +SET name = 'Default Name' WHERE id = $1 RETURNING id; diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go index f00070c371..9e8923565e 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go @@ -54,7 +54,7 @@ func (q *Queries) GetUser(ctx context.Context, sub pgtype.UUID) (pgtype.UUID, er const setDefaultName = `-- name: SetDefaultName :one UPDATE authors -SET name = "Default Name" +SET name = 'Default Name' WHERE id = $1 RETURNING id ` diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/query.sql index 3e209ba5a4..ca3fc5c6a4 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/query.sql +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/query.sql @@ -20,6 +20,6 @@ LIMIT 1; -- name: SetDefaultName :one UPDATE authors -SET name = "Default Name" +SET name = 'Default Name' WHERE id = $1 RETURNING id; diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go index 1d992e3b85..be987b8417 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go @@ -54,7 +54,7 @@ func (q *Queries) GetUser(ctx context.Context, sub uuid.UUID) (uuid.UUID, error) const setDefaultName = `-- name: SetDefaultName :one UPDATE authors -SET name = "Default Name" +SET name = 'Default Name' WHERE id = $1 RETURNING id ` diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/query.sql b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/query.sql index 3e209ba5a4..ca3fc5c6a4 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/query.sql @@ -20,6 +20,6 @@ LIMIT 1; -- name: SetDefaultName :one UPDATE authors -SET name = "Default Name" +SET name = 'Default Name' WHERE id = $1 RETURNING id; diff --git a/internal/endtoend/testdata/sqlc_arg_invalid/mysql/stderr.txt b/internal/endtoend/testdata/sqlc_arg_invalid/mysql/stderr.txt index 8009988505..be38c8b505 100644 --- a/internal/endtoend/testdata/sqlc_arg_invalid/mysql/stderr.txt +++ b/internal/endtoend/testdata/sqlc_arg_invalid/mysql/stderr.txt @@ -2,5 +2,5 @@ query.sql:7:1: function "sqlc.argh" does not exist query.sql:10:45: expected 1 parameter to sqlc.arg; got 2 query.sql:13:45: expected 1 parameter to sqlc.arg; got 0 -query.sql:16:54: Invalid argument to sqlc.arg() -query.sql:19:54: Invalid argument to sqlc.arg() +query.sql:16:45: expected parameter to sqlc.arg to be string or reference; got *ast.FuncCall +query.sql:19:45: expected parameter to sqlc.arg to be string or reference; got *ast.ParamRef diff --git a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/query.sql b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/query.sql index fe25398cce..397850187a 100644 --- a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/query.sql +++ b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/query.sql @@ -1,8 +1,3 @@ -CREATE TABLE users ( - id serial, - first_name text not null -); - -- name: WrongFunc :one select id, first_name from users where id = sqlc.argh(target_id); diff --git a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/schema.sql b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/schema.sql new file mode 100644 index 0000000000..0a380b5f9d --- /dev/null +++ b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE users ( + id serial, + first_name text not null +); \ No newline at end of file diff --git a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/sqlc.json b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/sqlc.json index 696ed223db..f5a835c5a6 100644 --- a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/sqlc.json +++ b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/sqlc.json @@ -4,7 +4,7 @@ { "name": "querytest", "path": "go", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql", "engine": "postgresql" } diff --git a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/stderr.txt b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/stderr.txt index 8009988505..8dbea1f949 100644 --- a/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/stderr.txt +++ b/internal/endtoend/testdata/sqlc_arg_invalid/postgresql/stderr.txt @@ -1,6 +1,7 @@ # package querytest -query.sql:7:1: function "sqlc.argh" does not exist -query.sql:10:45: expected 1 parameter to sqlc.arg; got 2 -query.sql:13:45: expected 1 parameter to sqlc.arg; got 0 -query.sql:16:54: Invalid argument to sqlc.arg() -query.sql:19:54: Invalid argument to sqlc.arg() +query.sql:1:1: function "sqlc.argh" does not exist +query.sql:5:45: expected 1 parameter to sqlc.arg; got 2 +query.sql:8:45: expected 1 parameter to sqlc.arg; got 0 +query.sql:11:45: expected parameter to sqlc.arg to be string or reference; got *ast.FuncCall +query.sql:14:45: expected parameter to sqlc.arg to be string or reference; got *ast.ParamRef + diff --git a/internal/endtoend/testdata/sqlc_arg_invalid/sqlite/stderr.txt b/internal/endtoend/testdata/sqlc_arg_invalid/sqlite/stderr.txt index 8009988505..be38c8b505 100644 --- a/internal/endtoend/testdata/sqlc_arg_invalid/sqlite/stderr.txt +++ b/internal/endtoend/testdata/sqlc_arg_invalid/sqlite/stderr.txt @@ -2,5 +2,5 @@ query.sql:7:1: function "sqlc.argh" does not exist query.sql:10:45: expected 1 parameter to sqlc.arg; got 2 query.sql:13:45: expected 1 parameter to sqlc.arg; got 0 -query.sql:16:54: Invalid argument to sqlc.arg() -query.sql:19:54: Invalid argument to sqlc.arg() +query.sql:16:45: expected parameter to sqlc.arg to be string or reference; got *ast.FuncCall +query.sql:19:45: expected parameter to sqlc.arg to be string or reference; got *ast.ParamRef diff --git a/internal/endtoend/testdata/strict_function_checks/postgresql/schema.sql b/internal/endtoend/testdata/strict_function_checks/postgresql/schema.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/endtoend/testdata/strict_function_checks/postgresql/sqlc.json b/internal/endtoend/testdata/strict_function_checks/postgresql/sqlc.json index 935bb9f278..6cb9103c1a 100644 --- a/internal/endtoend/testdata/strict_function_checks/postgresql/sqlc.json +++ b/internal/endtoend/testdata/strict_function_checks/postgresql/sqlc.json @@ -4,7 +4,7 @@ { "name": "querytest", "path": "go", - "schema": "query.sql", + "schema": "schema.sql", "queries": "query.sql", "engine": "postgresql", "strict_function_checks": true diff --git a/internal/endtoend/testdata/strict_function_checks/postgresql/stderr.txt b/internal/endtoend/testdata/strict_function_checks/postgresql/stderr/base.txt similarity index 100% rename from internal/endtoend/testdata/strict_function_checks/postgresql/stderr.txt rename to internal/endtoend/testdata/strict_function_checks/postgresql/stderr/base.txt diff --git a/internal/endtoend/testdata/strict_function_checks/postgresql/stderr/managed-db.txt b/internal/endtoend/testdata/strict_function_checks/postgresql/stderr/managed-db.txt new file mode 100644 index 0000000000..16996b66fd --- /dev/null +++ b/internal/endtoend/testdata/strict_function_checks/postgresql/stderr/managed-db.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:2:8: function doesntexist() does not exist diff --git a/internal/endtoend/testdata/sum_type/issue.md b/internal/endtoend/testdata/sum_type/issue.md new file mode 100644 index 0000000000..b125c05134 --- /dev/null +++ b/internal/endtoend/testdata/sum_type/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1106 \ No newline at end of file diff --git a/internal/endtoend/testdata/sum_type/postgresql/pgx/exec.json b/internal/endtoend/testdata/sum_type/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/sum_type/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/sum_type/postgresql/pgx/go/db.go b/internal/endtoend/testdata/sum_type/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/sum_type/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/sum_type/postgresql/pgx/go/models.go b/internal/endtoend/testdata/sum_type/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..39fe1356af --- /dev/null +++ b/internal/endtoend/testdata/sum_type/postgresql/pgx/go/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Order struct { + ID int64 + Quantity pgtype.Numeric + OrderCatalog pgtype.Int4 +} diff --git a/internal/endtoend/testdata/sum_type/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/sum_type/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..33f9e045aa --- /dev/null +++ b/internal/endtoend/testdata/sum_type/postgresql/pgx/go/query.sql.go @@ -0,0 +1,23 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const sumOrder = `-- name: SumOrder :one +SELECT SUM(quantity) FROM orders +` + +func (q *Queries) SumOrder(ctx context.Context) (pgtype.Numeric, error) { + row := q.db.QueryRow(ctx, sumOrder) + var sum pgtype.Numeric + err := row.Scan(&sum) + return sum, err +} diff --git a/internal/endtoend/testdata/sum_type/postgresql/pgx/query.sql b/internal/endtoend/testdata/sum_type/postgresql/pgx/query.sql new file mode 100644 index 0000000000..7effc6e765 --- /dev/null +++ b/internal/endtoend/testdata/sum_type/postgresql/pgx/query.sql @@ -0,0 +1,2 @@ +-- name: SumOrder :one +SELECT SUM(quantity) FROM orders; \ No newline at end of file diff --git a/internal/endtoend/testdata/sum_type/postgresql/pgx/schema.sql b/internal/endtoend/testdata/sum_type/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..85df079afe --- /dev/null +++ b/internal/endtoend/testdata/sum_type/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE orders ( + id BIGSERIAL PRIMARY KEY, + quantity decimal NOT NULL, + order_catalog int +); \ No newline at end of file diff --git a/internal/endtoend/testdata/sum_type/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/sum_type/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/sum_type/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/table_function/postgresql/pgx/v4/go/models.go b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/models.go index d0fd4d84a9..6f38d05c40 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/models.go +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/models.go @@ -4,11 +4,13 @@ package querytest -import () +import ( + "github.com/jackc/pgtype" +) type Transaction struct { ID int64 Uri string ProgramID string - Data string + Data pgtype.JSONB } diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/query.sql.go index c42aee02b5..783392c21b 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/go/query.sql.go @@ -7,36 +7,36 @@ package querytest import ( "context" + + "github.com/jackc/pgtype" ) const getTransaction = `-- name: GetTransaction :many SELECT - json_extract(transactions.data, '$.transaction.signatures[0]'), - json_group_array(instructions.value) + jsonb_extract_path(transactions.data, '$.transaction.signatures[0]'), + jsonb_agg(instructions.value) FROM transactions, - json_each(json_extract(transactions.data, '$.transaction.message.instructions')) AS instructions + jsonb_each(jsonb_extract_path(transactions.data, '$.transaction.message.instructions[0]')) AS instructions WHERE transactions.program_id = $1 - AND json_extract(transactions.data, '$.transaction.signatures[0]') > $2 - AND json_extract(json_extract(transactions.data, '$.transaction.message.accountKeys'), '$[' || json_extract(instructions.value, '$.programIdIndex') || ']') = transactions.program_id + AND jsonb_extract_path(transactions.data, '$.transaction.signatures[0]') @> to_jsonb($2::text) + AND jsonb_extract_path(jsonb_extract_path(transactions.data, '$.transaction.message.accountKeys'), 'key') = to_jsonb(transactions.program_id) GROUP BY transactions.id -LIMIT $3 ` type GetTransactionParams struct { ProgramID string Data string - Limit int32 } type GetTransactionRow struct { - JsonExtract interface{} - JsonGroupArray interface{} + JsonbExtractPath pgtype.JSONB + JsonbAgg pgtype.JSONB } func (q *Queries) GetTransaction(ctx context.Context, arg GetTransactionParams) ([]GetTransactionRow, error) { - rows, err := q.db.Query(ctx, getTransaction, arg.ProgramID, arg.Data, arg.Limit) + rows, err := q.db.Query(ctx, getTransaction, arg.ProgramID, arg.Data) if err != nil { return nil, err } @@ -44,7 +44,7 @@ func (q *Queries) GetTransaction(ctx context.Context, arg GetTransactionParams) var items []GetTransactionRow for rows.Next() { var i GetTransactionRow - if err := rows.Scan(&i.JsonExtract, &i.JsonGroupArray); err != nil { + if err := rows.Scan(&i.JsonbExtractPath, &i.JsonbAgg); err != nil { return nil, err } items = append(items, i) diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/query.sql index cbf49a037b..99f02a70ef 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/query.sql +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/query.sql @@ -1,13 +1,12 @@ /* name: GetTransaction :many */ SELECT - json_extract(transactions.data, '$.transaction.signatures[0]'), - json_group_array(instructions.value) + jsonb_extract_path(transactions.data, '$.transaction.signatures[0]'), + jsonb_agg(instructions.value) FROM transactions, - json_each(json_extract(transactions.data, '$.transaction.message.instructions')) AS instructions + jsonb_each(jsonb_extract_path(transactions.data, '$.transaction.message.instructions[0]')) AS instructions WHERE - transactions.program_id = $1 - AND json_extract(transactions.data, '$.transaction.signatures[0]') > $2 - AND json_extract(json_extract(transactions.data, '$.transaction.message.accountKeys'), '$[' || json_extract(instructions.value, '$.programIdIndex') || ']') = transactions.program_id -GROUP BY transactions.id -LIMIT $3; \ No newline at end of file + transactions.program_id = sqlc.arg('program_id') + AND jsonb_extract_path(transactions.data, '$.transaction.signatures[0]') @> to_jsonb(sqlc.arg('data')::text) + AND jsonb_extract_path(jsonb_extract_path(transactions.data, '$.transaction.message.accountKeys'), 'key') = to_jsonb(transactions.program_id) +GROUP BY transactions.id; \ No newline at end of file diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/schema.sql b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/schema.sql index 46b1f13951..455651b8ad 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v4/schema.sql +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v4/schema.sql @@ -1,7 +1,7 @@ CREATE TABLE transactions ( - id BIGSERIAL PRIMARY KEY, - uri text NOT NULL, - program_id text NOT NULL, - data text NOT NULL + id BIGSERIAL PRIMARY KEY, + uri TEXT NOT NULL, + program_id TEXT NOT NULL, + data JSONB NOT NULL ); diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/models.go b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/models.go index d0fd4d84a9..b4ee022e62 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/models.go +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/models.go @@ -10,5 +10,5 @@ type Transaction struct { ID int64 Uri string ProgramID string - Data string + Data []byte } diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/query.sql.go index c42aee02b5..21e32608e7 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/go/query.sql.go @@ -11,32 +11,30 @@ import ( const getTransaction = `-- name: GetTransaction :many SELECT - json_extract(transactions.data, '$.transaction.signatures[0]'), - json_group_array(instructions.value) + jsonb_extract_path(transactions.data, '$.transaction.signatures[0]'), + jsonb_agg(instructions.value) FROM transactions, - json_each(json_extract(transactions.data, '$.transaction.message.instructions')) AS instructions + jsonb_each(jsonb_extract_path(transactions.data, '$.transaction.message.instructions[0]')) AS instructions WHERE transactions.program_id = $1 - AND json_extract(transactions.data, '$.transaction.signatures[0]') > $2 - AND json_extract(json_extract(transactions.data, '$.transaction.message.accountKeys'), '$[' || json_extract(instructions.value, '$.programIdIndex') || ']') = transactions.program_id + AND jsonb_extract_path(transactions.data, '$.transaction.signatures[0]') @> to_jsonb($2::text) + AND jsonb_extract_path(jsonb_extract_path(transactions.data, '$.transaction.message.accountKeys'), 'key') = to_jsonb(transactions.program_id) GROUP BY transactions.id -LIMIT $3 ` type GetTransactionParams struct { ProgramID string Data string - Limit int32 } type GetTransactionRow struct { - JsonExtract interface{} - JsonGroupArray interface{} + JsonbExtractPath []byte + JsonbAgg []byte } func (q *Queries) GetTransaction(ctx context.Context, arg GetTransactionParams) ([]GetTransactionRow, error) { - rows, err := q.db.Query(ctx, getTransaction, arg.ProgramID, arg.Data, arg.Limit) + rows, err := q.db.Query(ctx, getTransaction, arg.ProgramID, arg.Data) if err != nil { return nil, err } @@ -44,7 +42,7 @@ func (q *Queries) GetTransaction(ctx context.Context, arg GetTransactionParams) var items []GetTransactionRow for rows.Next() { var i GetTransactionRow - if err := rows.Scan(&i.JsonExtract, &i.JsonGroupArray); err != nil { + if err := rows.Scan(&i.JsonbExtractPath, &i.JsonbAgg); err != nil { return nil, err } items = append(items, i) diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/query.sql index cbf49a037b..99f02a70ef 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/query.sql +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/query.sql @@ -1,13 +1,12 @@ /* name: GetTransaction :many */ SELECT - json_extract(transactions.data, '$.transaction.signatures[0]'), - json_group_array(instructions.value) + jsonb_extract_path(transactions.data, '$.transaction.signatures[0]'), + jsonb_agg(instructions.value) FROM transactions, - json_each(json_extract(transactions.data, '$.transaction.message.instructions')) AS instructions + jsonb_each(jsonb_extract_path(transactions.data, '$.transaction.message.instructions[0]')) AS instructions WHERE - transactions.program_id = $1 - AND json_extract(transactions.data, '$.transaction.signatures[0]') > $2 - AND json_extract(json_extract(transactions.data, '$.transaction.message.accountKeys'), '$[' || json_extract(instructions.value, '$.programIdIndex') || ']') = transactions.program_id -GROUP BY transactions.id -LIMIT $3; \ No newline at end of file + transactions.program_id = sqlc.arg('program_id') + AND jsonb_extract_path(transactions.data, '$.transaction.signatures[0]') @> to_jsonb(sqlc.arg('data')::text) + AND jsonb_extract_path(jsonb_extract_path(transactions.data, '$.transaction.message.accountKeys'), 'key') = to_jsonb(transactions.program_id) +GROUP BY transactions.id; \ No newline at end of file diff --git a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/schema.sql b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/schema.sql index 46b1f13951..455651b8ad 100644 --- a/internal/endtoend/testdata/table_function/postgresql/pgx/v5/schema.sql +++ b/internal/endtoend/testdata/table_function/postgresql/pgx/v5/schema.sql @@ -1,7 +1,7 @@ CREATE TABLE transactions ( - id BIGSERIAL PRIMARY KEY, - uri text NOT NULL, - program_id text NOT NULL, - data text NOT NULL + id BIGSERIAL PRIMARY KEY, + uri TEXT NOT NULL, + program_id TEXT NOT NULL, + data JSONB NOT NULL ); diff --git a/internal/endtoend/testdata/table_function/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/table_function/postgresql/stdlib/go/models.go index d0fd4d84a9..62525257f0 100644 --- a/internal/endtoend/testdata/table_function/postgresql/stdlib/go/models.go +++ b/internal/endtoend/testdata/table_function/postgresql/stdlib/go/models.go @@ -4,11 +4,13 @@ package querytest -import () +import ( + "encoding/json" +) type Transaction struct { ID int64 Uri string ProgramID string - Data string + Data json.RawMessage } diff --git a/internal/endtoend/testdata/table_function/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/table_function/postgresql/stdlib/go/query.sql.go index f59f708b45..2b9fa93fe7 100644 --- a/internal/endtoend/testdata/table_function/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/table_function/postgresql/stdlib/go/query.sql.go @@ -7,36 +7,35 @@ package querytest import ( "context" + "encoding/json" ) const getTransaction = `-- name: GetTransaction :many SELECT - json_extract(transactions.data, '$.transaction.signatures[0]'), - json_group_array(instructions.value) + jsonb_extract_path(transactions.data, '$.transaction.signatures[0]'), + jsonb_agg(instructions.value) FROM transactions, - json_each(json_extract(transactions.data, '$.transaction.message.instructions')) AS instructions + jsonb_each(jsonb_extract_path(transactions.data, '$.transaction.message.instructions[0]')) AS instructions WHERE transactions.program_id = $1 - AND json_extract(transactions.data, '$.transaction.signatures[0]') > $2 - AND json_extract(json_extract(transactions.data, '$.transaction.message.accountKeys'), '$[' || json_extract(instructions.value, '$.programIdIndex') || ']') = transactions.program_id + AND jsonb_extract_path(transactions.data, '$.transaction.signatures[0]') @> to_jsonb($2::text) + AND jsonb_extract_path(jsonb_extract_path(transactions.data, '$.transaction.message.accountKeys'), 'key') = to_jsonb(transactions.program_id) GROUP BY transactions.id -LIMIT $3 ` type GetTransactionParams struct { ProgramID string Data string - Limit int32 } type GetTransactionRow struct { - JsonExtract interface{} - JsonGroupArray interface{} + JsonbExtractPath json.RawMessage + JsonbAgg json.RawMessage } func (q *Queries) GetTransaction(ctx context.Context, arg GetTransactionParams) ([]GetTransactionRow, error) { - rows, err := q.db.QueryContext(ctx, getTransaction, arg.ProgramID, arg.Data, arg.Limit) + rows, err := q.db.QueryContext(ctx, getTransaction, arg.ProgramID, arg.Data) if err != nil { return nil, err } @@ -44,7 +43,7 @@ func (q *Queries) GetTransaction(ctx context.Context, arg GetTransactionParams) var items []GetTransactionRow for rows.Next() { var i GetTransactionRow - if err := rows.Scan(&i.JsonExtract, &i.JsonGroupArray); err != nil { + if err := rows.Scan(&i.JsonbExtractPath, &i.JsonbAgg); err != nil { return nil, err } items = append(items, i) diff --git a/internal/endtoend/testdata/table_function/postgresql/stdlib/query.sql b/internal/endtoend/testdata/table_function/postgresql/stdlib/query.sql index 2ed11a193e..99f02a70ef 100644 --- a/internal/endtoend/testdata/table_function/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/table_function/postgresql/stdlib/query.sql @@ -1,13 +1,12 @@ /* name: GetTransaction :many */ SELECT - json_extract(transactions.data, '$.transaction.signatures[0]'), - json_group_array(instructions.value) + jsonb_extract_path(transactions.data, '$.transaction.signatures[0]'), + jsonb_agg(instructions.value) FROM transactions, - json_each(json_extract(transactions.data, '$.transaction.message.instructions')) AS instructions + jsonb_each(jsonb_extract_path(transactions.data, '$.transaction.message.instructions[0]')) AS instructions WHERE - transactions.program_id = $1 - AND json_extract(transactions.data, '$.transaction.signatures[0]') > $2 - AND json_extract(json_extract(transactions.data, '$.transaction.message.accountKeys'), '$[' || json_extract(instructions.value, '$.programIdIndex') || ']') = transactions.program_id -GROUP BY transactions.id -LIMIT $3; + transactions.program_id = sqlc.arg('program_id') + AND jsonb_extract_path(transactions.data, '$.transaction.signatures[0]') @> to_jsonb(sqlc.arg('data')::text) + AND jsonb_extract_path(jsonb_extract_path(transactions.data, '$.transaction.message.accountKeys'), 'key') = to_jsonb(transactions.program_id) +GROUP BY transactions.id; \ No newline at end of file diff --git a/internal/endtoend/testdata/table_function/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/table_function/postgresql/stdlib/schema.sql index 46b1f13951..455651b8ad 100644 --- a/internal/endtoend/testdata/table_function/postgresql/stdlib/schema.sql +++ b/internal/endtoend/testdata/table_function/postgresql/stdlib/schema.sql @@ -1,7 +1,7 @@ CREATE TABLE transactions ( - id BIGSERIAL PRIMARY KEY, - uri text NOT NULL, - program_id text NOT NULL, - data text NOT NULL + id BIGSERIAL PRIMARY KEY, + uri TEXT NOT NULL, + program_id TEXT NOT NULL, + data JSONB NOT NULL ); diff --git a/internal/endtoend/testdata/unknown_func/pganalyze/exec.json b/internal/endtoend/testdata/unknown_func/pganalyze/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pganalyze/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/unknown_func/pganalyze/query.sql b/internal/endtoend/testdata/unknown_func/pganalyze/query.sql new file mode 100644 index 0000000000..36b697c8bb --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pganalyze/query.sql @@ -0,0 +1,2 @@ +-- name: ListFoos :one +SELECT id FROM foo WHERE id = frobnicate($1); diff --git a/internal/endtoend/testdata/unknown_func/pganalyze/schema.sql b/internal/endtoend/testdata/unknown_func/pganalyze/schema.sql new file mode 100644 index 0000000000..15fe2093e0 --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pganalyze/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (id text not null); diff --git a/internal/endtoend/testdata/unknown_func/pganalyze/sqlc.json b/internal/endtoend/testdata/unknown_func/pganalyze/sqlc.json new file mode 100644 index 0000000000..32ede07158 --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pganalyze/sqlc.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "sql_package": "pgx/v5", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/unknown_func/pganalyze/stderr.txt b/internal/endtoend/testdata/unknown_func/pganalyze/stderr.txt new file mode 100644 index 0000000000..8e63375c83 --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pganalyze/stderr.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:2:31: function frobnicate(unknown) does not exist \ No newline at end of file diff --git a/internal/endtoend/testdata/unknown_func/pgx/v4/exec.json b/internal/endtoend/testdata/unknown_func/pgx/v4/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pgx/v4/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/unknown_func/pgx/v5/exec.json b/internal/endtoend/testdata/unknown_func/pgx/v5/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/pgx/v5/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/unknown_func/stdlib/exec.json b/internal/endtoend/testdata/unknown_func/stdlib/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/unknown_func/stdlib/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/unnest_star/issue.md b/internal/endtoend/testdata/unnest_star/issue.md new file mode 100644 index 0000000000..d0aede56b3 --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1185 \ No newline at end of file diff --git a/internal/endtoend/testdata/unnest_star/postgresql/pgx/exec.json b/internal/endtoend/testdata/unnest_star/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/db.go b/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/db.go new file mode 100644 index 0000000000..8a010ccc48 --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/unnest_star/postgresql/pgx/go/models.go b/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/models.go new file mode 100644 index 0000000000..9f0b7ce585 --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/models.go @@ -0,0 +1,21 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import () + +type Item struct { + ItemID int64 +} + +type Plan struct { + PlanID int64 +} + +type PlanItem struct { + PlanItemID int64 + PlanID int64 + ItemID int64 +} diff --git a/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/query.sql.go new file mode 100644 index 0000000000..cf64948cd8 --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/postgresql/pgx/go/query.sql.go @@ -0,0 +1,57 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const getPlanItems = `-- name: GetPlanItems :many +SELECT p.plan_id, p.item_id +FROM (SELECT unnest FROM unnest($1::bigint[])) AS i(req_item_id), +LATERAL ( + SELECT plan_id, item_id + FROM plan_items + WHERE + item_id = i.req_item_id AND + ($2 = 0 OR plan_id < $2) + ORDER BY plan_id DESC + LIMIT $3 +) p +` + +type GetPlanItemsParams struct { + Ids []int64 + After pgtype.Int4 + LimitCount int64 +} + +type GetPlanItemsRow struct { + PlanID int64 + ItemID int64 +} + +func (q *Queries) GetPlanItems(ctx context.Context, arg GetPlanItemsParams) ([]GetPlanItemsRow, error) { + rows, err := q.db.Query(ctx, getPlanItems, arg.Ids, arg.After, arg.LimitCount) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetPlanItemsRow + for rows.Next() { + var i GetPlanItemsRow + if err := rows.Scan(&i.PlanID, &i.ItemID); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/unnest_star/postgresql/pgx/query.sql b/internal/endtoend/testdata/unnest_star/postgresql/pgx/query.sql new file mode 100644 index 0000000000..01b5c77430 --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/postgresql/pgx/query.sql @@ -0,0 +1,12 @@ +-- name: GetPlanItems :many +SELECT p.plan_id, p.item_id +FROM (SELECT * FROM unnest(@ids::bigint[])) AS i(req_item_id), +LATERAL ( + SELECT plan_id, item_id + FROM plan_items + WHERE + item_id = i.req_item_id AND + (@after = 0 OR plan_id < @after) + ORDER BY plan_id DESC + LIMIT @limit_count +) p; \ No newline at end of file diff --git a/internal/endtoend/testdata/unnest_star/postgresql/pgx/schema.sql b/internal/endtoend/testdata/unnest_star/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..787caf88c7 --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/postgresql/pgx/schema.sql @@ -0,0 +1,13 @@ +create table plans ( + plan_id bigint generated by default as identity primary key +); + +create table items ( + item_id bigint generated by default as identity primary key +); + +create table plan_items ( + plan_item_id bigint generated by default as identity primary key, + plan_id bigint not null REFERENCES plans, + item_id bigint not null REFERENCES items +); \ No newline at end of file diff --git a/internal/endtoend/testdata/unnest_star/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/unnest_star/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/unnest_star/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/update_set_on_conflict/issue.md b/internal/endtoend/testdata/update_set_on_conflict/issue.md new file mode 100644 index 0000000000..27f06c09ab --- /dev/null +++ b/internal/endtoend/testdata/update_set_on_conflict/issue.md @@ -0,0 +1 @@ +https://github.com/sqlc-dev/sqlc/issues/1128 \ No newline at end of file diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql new file mode 100644 index 0000000000..3f9e9d9b86 --- /dev/null +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql @@ -0,0 +1,4 @@ +-- name: UpsertServer :exec +INSERT INTO servers(code, name) VALUES ($1, $2) +ON CONFLICT (code) +DO UPDATE SET name_typo = 1111; \ No newline at end of file diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..3ff1ccd6b3 --- /dev/null +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql @@ -0,0 +1,4 @@ +CREATE TABLE servers ( + code varchar PRIMARY KEY, + name text NOT NULL +); \ No newline at end of file diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..01489e0ffc --- /dev/null +++ b/internal/endtoend/testdata/update_set_on_conflict/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/update_set_on_conflict/postgresql/pgx/stderr.txt b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/stderr.txt new file mode 100644 index 0000000000..adbb13a418 --- /dev/null +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/stderr.txt @@ -0,0 +1,2 @@ +# package querytest +query.sql:4:15: column "name_typo" of relation "servers" does not exist \ No newline at end of file diff --git a/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/exec.json b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/exec.json new file mode 100644 index 0000000000..ee1b7ecd9e --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["managed-db"] +} diff --git a/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/db.go b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/db.go new file mode 100644 index 0000000000..a457fb76b2 --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.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/valid_group_by_reference/pganalyzer/go/models.go b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/models.go new file mode 100644 index 0000000000..ff5f263f68 --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/models.go @@ -0,0 +1,36 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "database/sql" + "time" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString +} + +type WeatherMetric struct { + Time time.Time + TimezoneShift sql.NullInt32 + CityName sql.NullString + TempC sql.NullFloat64 + FeelsLikeC sql.NullFloat64 + TempMinC sql.NullFloat64 + TempMaxC sql.NullFloat64 + PressureHpa sql.NullFloat64 + HumidityPercent sql.NullFloat64 + WindSpeedMs sql.NullFloat64 + WindDeg sql.NullInt32 + Rain1hMm sql.NullFloat64 + Rain3hMm sql.NullFloat64 + Snow1hMm sql.NullFloat64 + Snow3hMm sql.NullFloat64 + CloudsPercent sql.NullInt32 + WeatherTypeID sql.NullInt32 +} diff --git a/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/query.sql.go b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/query.sql.go new file mode 100644 index 0000000000..81a9cad7df --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/go/query.sql.go @@ -0,0 +1,105 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" + "time" +) + +const listAuthors = `-- name: ListAuthors :many +SELECT id, name as name, bio +FROM authors +` + +func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthors) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); 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 +} + +const listAuthorsIdenticalAlias = `-- name: ListAuthorsIdenticalAlias :many +SELECT id, name as name, bio +FROM authors +` + +func (q *Queries) ListAuthorsIdenticalAlias(ctx context.Context) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsIdenticalAlias) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); 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 +} + +const listMetrics = `-- name: ListMetrics :many +SELECT date_trunc('day', time) AS bucket, city_name, AVG(temp_c) +FROM weather_metrics +WHERE time > NOW() - (6 * INTERVAL '1 month') +GROUP BY bucket, city_name +ORDER BY bucket DESC +` + +type ListMetricsRow struct { + Bucket time.Time + CityName sql.NullString + Avg float64 +} + +func (q *Queries) ListMetrics(ctx context.Context) ([]ListMetricsRow, error) { + rows, err := q.db.QueryContext(ctx, listMetrics) + if err != nil { + return nil, err + } + defer rows.Close() + var items []ListMetricsRow + for rows.Next() { + var i ListMetricsRow + if err := rows.Scan(&i.Bucket, &i.CityName, &i.Avg); 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/valid_group_by_reference/pganalyzer/query.sql b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/query.sql new file mode 100644 index 0000000000..839f5414c9 --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/query.sql @@ -0,0 +1,14 @@ +-- name: ListAuthors :many +SELECT id, name as name, bio +FROM authors; + +-- name: ListAuthorsIdenticalAlias :many +SELECT id, name as name, bio +FROM authors; + +-- name: ListMetrics :many +SELECT date_trunc('day', time) AS bucket, city_name, AVG(temp_c) +FROM weather_metrics +WHERE time > NOW() - (6 * INTERVAL '1 month') +GROUP BY bucket, city_name +ORDER BY bucket DESC; diff --git a/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/schema.sql b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/schema.sql new file mode 100644 index 0000000000..910e1da151 --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/schema.sql @@ -0,0 +1,26 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + +CREATE TABLE IF NOT EXISTS weather_metrics +( + time TIMESTAMP WITHOUT TIME ZONE NOT NULL, + timezone_shift INT NULL, + city_name TEXT NULL, + temp_c DOUBLE PRECISION NULL, + feels_like_c DOUBLE PRECISION NULL, + temp_min_c DOUBLE PRECISION NULL, + temp_max_c DOUBLE PRECISION NULL, + pressure_hpa DOUBLE PRECISION NULL, + humidity_percent DOUBLE PRECISION NULL, + wind_speed_ms DOUBLE PRECISION NULL, + wind_deg INT NULL, + rain_1h_mm DOUBLE PRECISION NULL, + rain_3h_mm DOUBLE PRECISION NULL, + snow_1h_mm DOUBLE PRECISION NULL, + snow_3h_mm DOUBLE PRECISION NULL, + clouds_percent INT NULL, + weather_type_id INT NULL +); diff --git a/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/sqlc.json b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/sqlc.json new file mode 100644 index 0000000000..a590361309 --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/pganalyzer/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/valid_group_by_reference/postgresql/exec.json b/internal/endtoend/testdata/valid_group_by_reference/postgresql/exec.json new file mode 100644 index 0000000000..2e996ca79d --- /dev/null +++ b/internal/endtoend/testdata/valid_group_by_reference/postgresql/exec.json @@ -0,0 +1,3 @@ +{ + "contexts": ["base"] +} diff --git a/internal/endtoend/testdata/valid_group_by_reference/postgresql/go/query.sql.go b/internal/endtoend/testdata/valid_group_by_reference/postgresql/go/query.sql.go index e6af3b89fb..a32cf68206 100644 --- a/internal/endtoend/testdata/valid_group_by_reference/postgresql/go/query.sql.go +++ b/internal/endtoend/testdata/valid_group_by_reference/postgresql/go/query.sql.go @@ -13,7 +13,6 @@ import ( const listAuthors = `-- name: ListAuthors :many SELECT id, name as name, bio FROM authors -GROUP BY name ` func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { @@ -42,7 +41,6 @@ func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { const listAuthorsIdenticalAlias = `-- name: ListAuthorsIdenticalAlias :many SELECT id, name as name, bio FROM authors -GROUP BY name ` func (q *Queries) ListAuthorsIdenticalAlias(ctx context.Context) ([]Author, error) { @@ -69,7 +67,7 @@ func (q *Queries) ListAuthorsIdenticalAlias(ctx context.Context) ([]Author, erro } const listMetrics = `-- name: ListMetrics :many -SELECT time_bucket('15 days', time) AS bucket, city_name, AVG(temp_c) +SELECT date_trunc('day', time) AS bucket, city_name, AVG(temp_c) FROM weather_metrics WHERE time > NOW() - (6 * INTERVAL '1 month') GROUP BY bucket, city_name @@ -77,7 +75,7 @@ ORDER BY bucket DESC ` type ListMetricsRow struct { - Bucket interface{} + Bucket int64 CityName sql.NullString Avg float64 } diff --git a/internal/endtoend/testdata/valid_group_by_reference/postgresql/query.sql b/internal/endtoend/testdata/valid_group_by_reference/postgresql/query.sql index 0217b406a0..839f5414c9 100644 --- a/internal/endtoend/testdata/valid_group_by_reference/postgresql/query.sql +++ b/internal/endtoend/testdata/valid_group_by_reference/postgresql/query.sql @@ -1,15 +1,13 @@ -- name: ListAuthors :many SELECT id, name as name, bio -FROM authors -GROUP BY name; +FROM authors; -- name: ListAuthorsIdenticalAlias :many SELECT id, name as name, bio -FROM authors -GROUP BY name; +FROM authors; -- name: ListMetrics :many -SELECT time_bucket('15 days', time) AS bucket, city_name, AVG(temp_c) +SELECT date_trunc('day', time) AS bucket, city_name, AVG(temp_c) FROM weather_metrics WHERE time > NOW() - (6 * INTERVAL '1 month') GROUP BY bucket, city_name diff --git a/internal/endtoend/vet_test.go b/internal/endtoend/vet_test.go index f5fc47ac92..56b5837ed3 100644 --- a/internal/endtoend/vet_test.go +++ b/internal/endtoend/vet_test.go @@ -70,7 +70,11 @@ func TestExamplesVet(t *testing.T) { } var stderr bytes.Buffer - err := cmd.Vet(ctx, cmd.Env{}, path, "", &stderr) + opts := &cmd.Options{ + Stderr: &stderr, + Env: cmd.Env{}, + } + err := cmd.Vet(ctx, path, "", opts) if err != nil { t.Fatalf("sqlc vet failed: %s %s", err, stderr.String()) } diff --git a/internal/engine/postgresql/analyzer/analyze.go b/internal/engine/postgresql/analyzer/analyze.go new file mode 100644 index 0000000000..160dcc83ac --- /dev/null +++ b/internal/engine/postgresql/analyzer/analyze.go @@ -0,0 +1,321 @@ +package analyzer + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + "time" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" + "github.com/jackc/pgx/v5/pgxpool" + + core "github.com/sqlc-dev/sqlc/internal/analyzer" + "github.com/sqlc-dev/sqlc/internal/config" + pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1" + "github.com/sqlc-dev/sqlc/internal/sql/ast" + "github.com/sqlc-dev/sqlc/internal/sql/named" + "github.com/sqlc-dev/sqlc/internal/sql/sqlerr" +) + +type Analyzer struct { + db config.Database + client pb.QuickClient + pool *pgxpool.Pool + + formats sync.Map + columns sync.Map + tables sync.Map +} + +func New(client pb.QuickClient, db config.Database) *Analyzer { + return &Analyzer{ + db: db, + client: client, + } +} + +const columnQuery = ` +SELECT + pg_catalog.format_type(pg_attribute.atttypid, pg_attribute.atttypmod) AS data_type, + pg_attribute.attnotnull as not_null, + pg_attribute.attndims as array_dims +FROM + pg_catalog.pg_attribute +WHERE + attrelid = $1 + AND attnum = $2; +` + +const tableQuery = ` +SELECT + pg_class.relname as table_name, + pg_namespace.nspname as schema_name +FROM + pg_catalog.pg_class +JOIN + pg_catalog.pg_namespace ON pg_namespace.oid = pg_class.relnamespace +WHERE + pg_class.oid = $1; +` + +type pgTable struct { + TableName string `db:"table_name"` + SchemaName string `db:"schema_name"` +} + +// Cache these types in memory +func (a *Analyzer) tableInfo(ctx context.Context, oid uint32) (*pgTable, error) { + ctbl, ok := a.tables.Load(oid) + if ok { + return ctbl.(*pgTable), nil + } + rows, err := a.pool.Query(ctx, tableQuery, oid) + if err != nil { + return nil, err + } + tbl, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[pgTable]) + if err != nil { + return nil, err + } + a.tables.Store(oid, &tbl) + return &tbl, nil +} + +type pgColumn struct { + DataType string `db:"data_type"` + NotNull bool `db:"not_null"` + ArrayDims int `db:"array_dims"` +} + +type columnKey struct { + OID uint32 + Attr uint16 +} + +// Cache these types in memory +func (a *Analyzer) columnInfo(ctx context.Context, field pgconn.FieldDescription) (*pgColumn, error) { + key := columnKey{field.TableOID, field.TableAttributeNumber} + cinfo, ok := a.columns.Load(key) + if ok { + return cinfo.(*pgColumn), nil + } + + rows, err := a.pool.Query(ctx, columnQuery, field.TableOID, field.TableAttributeNumber) + if err != nil { + return nil, err + } + col, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[pgColumn]) + if err != nil { + return nil, err + } + a.columns.Store(key, &col) + return &col, nil +} + +type formatKey struct { + OID uint32 + Modified int32 +} + +// TODO: Use PGX to do the lookup for basic OID types +func (a *Analyzer) formatType(ctx context.Context, oid uint32, modifier int32) (string, error) { + key := formatKey{oid, modifier} + ftyp, ok := a.formats.Load(key) + if ok { + return ftyp.(string), nil + } + rows, err := a.pool.Query(ctx, `SELECT format_type($1, $2)`, oid, modifier) + if err != nil { + return "", err + } + dt, err := pgx.CollectOneRow(rows, pgx.RowTo[string]) + if err != nil { + return "", err + } + a.formats.Store(key, dt) + return dt, err +} + +// TODO: This is bad +func rewriteType(dt string) string { + switch { + case strings.HasPrefix(dt, "character("): + return "pg_catalog.bpchar" + case strings.HasPrefix(dt, "character varying"): + return "pg_catalog.varchar" + case strings.HasPrefix(dt, "bit varying"): + return "pg_catalog.varbit" + case strings.HasPrefix(dt, "bit("): + return "pg_catalog.bit" + } + switch dt { + case "bpchar": + return "pg_catalog.bpchar" + case "timestamp without time zone": + return "pg_catalog.timestamp" + case "timestamp with time zone": + return "pg_catalog.timestamptz" + case "time without time zone": + return "pg_catalog.time" + case "time with time zone": + return "pg_catalog.timetz" + } + return dt +} + +func parseType(dt string) (string, bool, int) { + size := 0 + for { + trimmed := strings.TrimSuffix(dt, "[]") + if trimmed == dt { + return rewriteType(dt), size > 0, size + } + size += 1 + dt = trimmed + } +} + +// Don't create a database per query +func (a *Analyzer) Analyze(ctx context.Context, n ast.Node, query string, migrations []string, ps *named.ParamSet) (*core.Analysis, error) { + extractSqlErr := func(e error) error { + var pgErr *pgconn.PgError + if errors.As(e, &pgErr) { + return &sqlerr.Error{ + Code: pgErr.Code, + Message: pgErr.Message, + Location: max(n.Pos()+int(pgErr.Position)-1, 0), + } + } + return e + } + + if a.pool == nil { + var uri string + if a.db.Managed { + if a.client == nil { + return nil, fmt.Errorf("client is nil") + } + edb, err := a.client.CreateEphemeralDatabase(ctx, &pb.CreateEphemeralDatabaseRequest{ + Engine: "postgresql", + Migrations: migrations, + }) + if err != nil { + return nil, err + } + uri = edb.Uri + } else { + uri = a.db.URI + } + conf, err := pgxpool.ParseConfig(uri) + if err != nil { + return nil, err + } + conf.MaxConns = 2 + conf.MinConns = 0 + conf.MaxConnLifetime = time.Second * 1 + pool, err := pgxpool.NewWithConfig(ctx, conf) + if err != nil { + return nil, err + } + a.pool = pool + } + + c, err := a.pool.Acquire(ctx) + if err != nil { + return nil, err + } + defer c.Release() + + // TODO: Pick a random name + desc, err := c.Conn().Prepare(ctx, "foo", query) + if err != nil { + return nil, extractSqlErr(err) + } + + if err := c.Conn().Deallocate(ctx, "foo"); err != nil { + return nil, err + } + + var result core.Analysis + for _, field := range desc.Fields { + if field.TableOID > 0 { + col, err := a.columnInfo(ctx, field) + if err != nil { + return nil, err + } + // debug.Dump(i, field, col) + tbl, err := a.tableInfo(ctx, field.TableOID) + if err != nil { + return nil, err + } + // TODO: Why are these dims different? + dt, isArray, _ := parseType(col.DataType) + notNull := col.NotNull + name := field.Name + result.Columns = append(result.Columns, core.Column{ + Name: name, + OriginalName: field.Name, + DataType: dt, + NotNull: notNull, + IsArray: isArray, + ArrayDims: col.ArrayDims, + Table: &ast.TableName{ + Schema: tbl.SchemaName, + Name: tbl.TableName, + }, + }) + } else { + dataType, err := a.formatType(ctx, field.DataTypeOID, field.TypeModifier) + if err != nil { + return nil, err + } + // debug.Dump(i, field, dataType) + notNull := false + name := field.Name + dt, isArray, dims := parseType(dataType) + result.Columns = append(result.Columns, core.Column{ + Name: name, + OriginalName: field.Name, + DataType: dt, + NotNull: notNull, + IsArray: isArray, + ArrayDims: dims, + }) + } + } + + for i, oid := range desc.ParamOIDs { + dataType, err := a.formatType(ctx, oid, -1) + if err != nil { + return nil, err + } + notNull := false + dt, isArray, dims := parseType(dataType) + name := "" + if ps != nil { + name, _ = ps.NameFor(i + 1) + } + result.Params = append(result.Params, core.Parameter{ + Number: i + 1, + Column: &core.Column{ + Name: name, + DataType: dt, + IsArray: isArray, + ArrayDims: dims, + NotNull: notNull, + }, + }) + } + + return &result, nil +} + +func (a *Analyzer) Close(_ context.Context) error { + if a.pool != nil { + a.pool.Close() + } + return nil +} diff --git a/internal/sql/named/param_set.go b/internal/sql/named/param_set.go index b30de738b3..d47617a39e 100644 --- a/internal/sql/named/param_set.go +++ b/internal/sql/named/param_set.go @@ -14,6 +14,13 @@ type ParamSet struct { argn int } +// Return the name for a given parameter number and a boolean indicating if it +// was found. +func (p *ParamSet) NameFor(idx int) (string, bool) { + name, ok := p.positionToName[idx] + return name, ok +} + func (p *ParamSet) nextArgNum() int { for { if _, ok := p.positionToName[p.argn]; !ok { diff --git a/internal/sql/validate/cmd.go b/internal/sql/validate/cmd.go index 079c10c3f9..962e340dea 100644 --- a/internal/sql/validate/cmd.go +++ b/internal/sql/validate/cmd.go @@ -6,6 +6,8 @@ import ( "github.com/sqlc-dev/sqlc/internal/metadata" "github.com/sqlc-dev/sqlc/internal/sql/ast" + "github.com/sqlc-dev/sqlc/internal/sql/astutils" + "github.com/sqlc-dev/sqlc/internal/sql/named" ) func validateCopyfrom(n ast.Node) error { @@ -45,8 +47,13 @@ func validateCopyfrom(n ast.Node) error { } func validateBatch(n ast.Node) error { - nums, _, _ := ParamRef(n) - if len(nums) == 0 { + funcs := astutils.Search(n, named.IsParamFunc) + params := astutils.Search(n, named.IsParamSign) + args := astutils.Search(n, func(n ast.Node) bool { + _, ok := n.(*ast.ParamRef) + return ok + }) + if (len(params.Items) + len(funcs.Items) + len(args.Items)) == 0 { return errors.New(":batch* commands require parameters") } return nil diff --git a/internal/sql/validate/func_call.go b/internal/sql/validate/func_call.go index 383366c68f..dad621eb12 100644 --- a/internal/sql/validate/func_call.go +++ b/internal/sql/validate/func_call.go @@ -2,7 +2,6 @@ package validate import ( "errors" - "fmt" "github.com/sqlc-dev/sqlc/internal/config" "github.com/sqlc-dev/sqlc/internal/sql/ast" @@ -31,34 +30,7 @@ func (v *funcCallVisitor) Visit(node ast.Node) astutils.Visitor { return v } - // Custom validation for sqlc.arg, sqlc.narg and sqlc.slice - // TODO: Replace this once type-checking is implemented if fn.Schema == "sqlc" { - if !(fn.Name == "arg" || fn.Name == "narg" || fn.Name == "slice" || fn.Name == "embed") { - v.err = sqlerr.FunctionNotFound("sqlc." + fn.Name) - return nil - } - - if len(call.Args.Items) != 1 { - v.err = &sqlerr.Error{ - Message: fmt.Sprintf("expected 1 parameter to sqlc.%s; got %d", fn.Name, len(call.Args.Items)), - Location: call.Pos(), - } - return nil - } - switch n := call.Args.Items[0].(type) { - case *ast.A_Const: - case *ast.ColumnRef: - default: - v.err = &sqlerr.Error{ - Message: fmt.Sprintf("expected parameter to sqlc.%s to be string or reference; got %T", fn.Name, n), - Location: call.Pos(), - } - return nil - } - - // If we have sqlc.arg or sqlc.narg, there is no need to resolve the function call. - // It won't resolve anyway, sinc it is not a real function. return nil } diff --git a/internal/sql/validate/param_ref.go b/internal/sql/validate/param_ref.go index 1ee04bb5e7..ab9413f40f 100644 --- a/internal/sql/validate/param_ref.go +++ b/internal/sql/validate/param_ref.go @@ -38,7 +38,7 @@ func ParamRef(n ast.Node) (map[int]bool, bool, error) { } for i := 1; i <= len(seen); i += 1 { if _, ok := seen[i]; !ok { - return nil, false, &sqlerr.Error{ + return seen, !nodollar, &sqlerr.Error{ Code: "42P18", Message: fmt.Sprintf("could not determine data type of parameter $%d", i), } diff --git a/internal/sql/validate/param_style.go b/internal/sql/validate/param_style.go index 64f8bd9c87..1182051d20 100644 --- a/internal/sql/validate/param_style.go +++ b/internal/sql/validate/param_style.go @@ -1,48 +1,68 @@ package validate import ( + "fmt" + "github.com/sqlc-dev/sqlc/internal/sql/ast" "github.com/sqlc-dev/sqlc/internal/sql/astutils" - "github.com/sqlc-dev/sqlc/internal/sql/named" "github.com/sqlc-dev/sqlc/internal/sql/sqlerr" ) -// A query can use one (and only one) of the following formats: -// - positional parameters $1 -// - named parameter operator @param -// - named parameter function calls sqlc.arg(param) -func ParamStyle(n ast.Node) error { - namedFunc := astutils.Search(n, named.IsParamFunc) - for _, f := range namedFunc.Items { - if fc, ok := f.(*ast.FuncCall); ok { - args := fc.Args.Items - - if len(args) == 0 { - continue - } +type sqlcFuncVisitor struct { + err error +} + +func (v *sqlcFuncVisitor) Visit(node ast.Node) astutils.Visitor { + if v.err != nil { + return nil + } + + call, ok := node.(*ast.FuncCall) + if !ok { + return v + } + fn := call.Func + if fn == nil { + return v + } - switch val := args[0].(type) { - case *ast.FuncCall: - return &sqlerr.Error{ - Code: "", // TODO: Pick a new error code - Message: "Invalid argument to sqlc.arg()", - Location: val.Location, - } - case *ast.ParamRef: - return &sqlerr.Error{ - Code: "", // TODO: Pick a new error code - Message: "Invalid argument to sqlc.arg()", - Location: val.Location, - } - case *ast.A_Const, *ast.ColumnRef: - default: - return &sqlerr.Error{ - Code: "", // TODO: Pick a new error code - Message: "Invalid argument to sqlc.arg()", - } + // Custom validation for sqlc.arg, sqlc.narg and sqlc.slice + // TODO: Replace this once type-checking is implemented + if fn.Schema == "sqlc" { + if !(fn.Name == "arg" || fn.Name == "narg" || fn.Name == "slice" || fn.Name == "embed") { + v.err = sqlerr.FunctionNotFound("sqlc." + fn.Name) + return nil + } + + if len(call.Args.Items) != 1 { + v.err = &sqlerr.Error{ + Message: fmt.Sprintf("expected 1 parameter to sqlc.%s; got %d", fn.Name, len(call.Args.Items)), + Location: call.Pos(), + } + return nil + } + switch n := call.Args.Items[0].(type) { + case *ast.A_Const: + case *ast.ColumnRef: + default: + v.err = &sqlerr.Error{ + Message: fmt.Sprintf("expected parameter to sqlc.%s to be string or reference; got %T", fn.Name, n), + Location: call.Pos(), } + return nil } + + // If we have sqlc.arg or sqlc.narg, there is no need to resolve the function call. + // It won't resolve anyway, sinc it is not a real function. + return nil } + return nil } + +func SqlcFunctions(n ast.Node) error { + visitor := sqlcFuncVisitor{} + astutils.Walk(&visitor, n) + return visitor.err +}