Repository: sqlc-dev/sqlc
Pull request #2850 (2023-10-13 05:34:36)

feat(compiler): Parse query parameter metadata from comments
Groundwork for https://github.com/sqlc-dev/sqlc/issues/2800 (explicit type annotations in query comments metadata).

There are lots of tests that failed while I was refactoring this, so I have a fairly high degree of confidence that this refactor doesn't break anything. The changed endtoend test output is due to parsing bugs I fixed.

I chose to add a new `Metadata` struct type to house the growing set of stuff we associate with a query, but I don't have to so let me know if an alternative approach is preferred.


Patch:
diff --git a/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Models.kt b/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Models.kt
index 4cb2a9579..a034c3600 100644
--- a/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Models.kt
+++ b/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Models.kt
@@ -7,12 +7,12 @@ package com.example.ondeck.mysql
 import java.sql.Timestamp
 import java.time.Instant
 
-enum class VenuesStatus(val value: String) {
+enum class VenueStatus(val value: String) {
   OPEN("open"),
   CLOSED("closed");
 
   companion object {
-    private val map = VenuesStatus.values().associateBy(VenuesStatus::value)
+    private val map = VenueStatus.values().associateBy(VenueStatus::value)
     fun lookup(value: String) = map[value]
   }
 }
@@ -26,7 +26,7 @@ data class City (
 data class Venue (
   val id: Long,
   // Venues can be either open or closed
-  val status: VenuesStatus,
+  val status: VenueStatus,
   val statuses: String?,
   // This value appears in public URLs
   val slug: String,
diff --git a/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Queries.kt b/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Queries.kt
index 5e97478f4..7cacad0d1 100644
--- a/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Queries.kt
+++ b/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/Queries.kt
@@ -20,7 +20,7 @@ interface Queries {
       name: String,
       city: String,
       spotifyPlaylist: String,
-      status: VenuesStatus,
+      status: VenueStatus,
       statuses: String?,
       tags: String?): Long
   
diff --git a/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/QueriesImpl.kt b/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/QueriesImpl.kt
index c3cba3036..172967cde 100644
--- a/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/QueriesImpl.kt
+++ b/examples/kotlin/src/main/kotlin/com/example/ondeck/mysql/QueriesImpl.kt
@@ -116,7 +116,7 @@ class QueriesImpl(private val conn: Connection) : Queries {
       name: String,
       city: String,
       spotifyPlaylist: String,
-      status: VenuesStatus,
+      status: VenueStatus,
       statuses: String?,
       tags: String?): Long {
     return conn.prepareStatement(createVenue, Statement.RETURN_GENERATED_KEYS).use { stmt ->
@@ -180,7 +180,7 @@ class QueriesImpl(private val conn: Connection) : Queries {
       }
       val ret = Venue(
                 results.getLong(1),
-                VenuesStatus.lookup(results.getString(2))!!,
+                VenueStatus.lookup(results.getString(2))!!,
                 results.getString(3),
                 results.getString(4),
                 results.getString(5),
@@ -223,7 +223,7 @@ class QueriesImpl(private val conn: Connection) : Queries {
       while (results.next()) {
           ret.add(Venue(
                 results.getLong(1),
-                VenuesStatus.lookup(results.getString(2))!!,
+                VenueStatus.lookup(results.getString(2))!!,
                 results.getString(3),
                 results.getString(4),
                 results.getString(5),
diff --git a/examples/ondeck/mysql/models.go b/examples/ondeck/mysql/models.go
index 0ca972f6a..12e87cd90 100644
--- a/examples/ondeck/mysql/models.go
+++ b/examples/ondeck/mysql/models.go
@@ -11,46 +11,46 @@ import (
 	"time"
 )
 
-type VenuesStatus string
+type VenueStatus string
 
 const (
-	VenuesStatusOpen   VenuesStatus = "open"
-	VenuesStatusClosed VenuesStatus = "closed"
+	VenueStatusOpen   VenueStatus = "open"
+	VenueStatusClosed VenueStatus = "closed"
 )
 
-func (e *VenuesStatus) Scan(src interface{}) error {
+func (e *VenueStatus) Scan(src interface{}) error {
 	switch s := src.(type) {
 	case []byte:
-		*e = VenuesStatus(s)
+		*e = VenueStatus(s)
 	case string:
-		*e = VenuesStatus(s)
+		*e = VenueStatus(s)
 	default:
-		return fmt.Errorf("unsupported scan type for VenuesStatus: %T", src)
+		return fmt.Errorf("unsupported scan type for VenueStatus: %T", src)
 	}
 	return nil
 }
 
-type NullVenuesStatus struct {
-	VenuesStatus VenuesStatus `json:"venues_status"`
-	Valid        bool         `json:"valid"` // Valid is true if VenuesStatus is not NULL
+type NullVenueStatus struct {
+	VenueStatus VenueStatus `json:"venue_status"`
+	Valid       bool        `json:"valid"` // Valid is true if VenueStatus is not NULL
 }
 
 // Scan implements the Scanner interface.
-func (ns *NullVenuesStatus) Scan(value interface{}) error {
+func (ns *NullVenueStatus) Scan(value interface{}) error {
 	if value == nil {
-		ns.VenuesStatus, ns.Valid = "", false
+		ns.VenueStatus, ns.Valid = "", false
 		return nil
 	}
 	ns.Valid = true
-	return ns.VenuesStatus.Scan(value)
+	return ns.VenueStatus.Scan(value)
 }
 
 // Value implements the driver Valuer interface.
-func (ns NullVenuesStatus) Value() (driver.Value, error) {
+func (ns NullVenueStatus) Value() (driver.Value, error) {
 	if !ns.Valid {
 		return nil, nil
 	}
-	return string(ns.VenuesStatus), nil
+	return string(ns.VenueStatus), nil
 }
 
 type City struct {
@@ -62,7 +62,7 @@ type City struct {
 type Venue struct {
 	ID uint64 `json:"id"`
 	// Venues can be either open or closed
-	Status   VenuesStatus   `json:"status"`
+	Status   VenueStatus    `json:"status"`
 	Statuses sql.NullString `json:"statuses"`
 	// This value appears in public URLs
 	Slug            string         `json:"slug"`
diff --git a/examples/ondeck/mysql/venue.sql.go b/examples/ondeck/mysql/venue.sql.go
index 55d37ad78..13b5e28d0 100644
--- a/examples/ondeck/mysql/venue.sql.go
+++ b/examples/ondeck/mysql/venue.sql.go
@@ -37,7 +37,7 @@ type CreateVenueParams struct {
 	Name            string         `json:"name"`
 	City            string         `json:"city"`
 	SpotifyPlaylist string         `json:"spotify_playlist"`
-	Status          VenuesStatus   `json:"status"`
+	Status          VenueStatus    `json:"status"`
 	Statuses        sql.NullString `json:"statuses"`
 	Tags            sql.NullString `json:"tags"`
 }
diff --git a/internal/cmd/shim.go b/internal/cmd/shim.go
index 5f108868c..587c8bff6 100644
--- a/internal/cmd/shim.go
+++ b/internal/cmd/shim.go
@@ -57,20 +57,48 @@ func pluginSettings(r *compiler.Result, cs config.CombinedSettings) *plugin.Sett
 		Queries:   []string(cs.Package.Queries),
 		Overrides: over,
 		Rename:    cs.Rename,
-		Codegen:   pluginCodegen(cs.Codegen),
+		Codegen:   pluginCodegen(cs, cs.Codegen),
 	}
 }
 
-func pluginCodegen(s config.Codegen) *plugin.Codegen {
+func pluginCodegen(cs config.CombinedSettings, s config.Codegen) *plugin.Codegen {
 	opts, err := convert.YAMLtoJSON(s.Options)
 	if err != nil {
 		panic(err)
 	}
-	return &plugin.Codegen{
+	cg := &plugin.Codegen{
 		Out:     s.Out,
 		Plugin:  s.Plugin,
 		Options: opts,
 	}
+	for _, p := range cs.Global.Plugins {
+		if p.Name == s.Plugin {
+			cg.Env = p.Env
+			cg.Process = pluginProcess(p)
+			cg.Wasm = pluginWASM(p)
+			return cg
+		}
+	}
+	return cg
+}
+
+func pluginProcess(p config.Plugin) *plugin.Codegen_Process {
+	if p.Process != nil {
+		return &plugin.Codegen_Process{
+			Cmd: p.Process.Cmd,
+		}
+	}
+	return nil
+}
+
+func pluginWASM(p config.Plugin) *plugin.Codegen_WASM {
+	if p.WASM != nil {
+		return &plugin.Codegen_WASM{
+			Url:    p.WASM.URL,
+			Sha256: p.WASM.SHA256,
+		}
+	}
+	return nil
 }
 
 func pluginGoType(o config.Override) *plugin.ParsedGoType {
@@ -181,13 +209,13 @@ func pluginQueries(r *compiler.Result) []*plugin.Query {
 			}
 		}
 		out = append(out, &plugin.Query{
-			Name:            q.Name,
-			Cmd:             q.Cmd,
+			Name:            q.Metadata.Name,
+			Cmd:             q.Metadata.Cmd,
 			Text:            q.SQL,
-			Comments:        q.Comments,
+			Comments:        q.Metadata.Comments,
 			Columns:         columns,
 			Params:          params,
-			Filename:        q.Filename,
+			Filename:        q.Metadata.Filename,
 			InsertIntoTable: iit,
 		})
 	}
diff --git a/internal/cmd/vet.go b/internal/cmd/vet.go
index 31aa3ec33..4f79fc8e8 100644
--- a/internal/cmd/vet.go
+++ b/internal/cmd/vet.go
@@ -545,7 +545,7 @@ func (c *checker) checkSQL(ctx context.Context, s config.SQL) error {
 	req := codeGenRequest(result, combo)
 	cfg := vetConfig(req)
 	for i, query := range req.Queries {
-		if result.Queries[i].Flags[QueryFlagSqlcVetDisable] {
+		if result.Queries[i].Metadata.Flags[QueryFlagSqlcVetDisable] {
 			if debug.Active {
 				log.Printf("Skipping vet rules for query: %s\n", query.Name)
 			}
diff --git a/internal/codegen/golang/gen.go b/internal/codegen/golang/gen.go
index e5762374b..c5f1956e0 100644
--- a/internal/codegen/golang/gen.go
+++ b/internal/codegen/golang/gen.go
@@ -108,6 +108,10 @@ func Generate(ctx context.Context, req *plugin.CodeGenRequest) (*plugin.CodeGenR
 		return nil, err
 	}
 
+	if err := validateOpts(options); err != nil {
+		return nil, err
+	}
+
 	enums := buildEnums(req, options)
 	structs := buildStructs(req, options)
 	queries, err := buildQueries(req, options, structs)
diff --git a/internal/codegen/golang/opts.go b/internal/codegen/golang/opts.go
index af90dcc6b..53be53688 100644
--- a/internal/codegen/golang/opts.go
+++ b/internal/codegen/golang/opts.go
@@ -39,7 +39,7 @@ type opts struct {
 	OmitUnusedStructs           bool     `json:"omit_unused_structs,omitempty"`
 	BuildTags                   string   `json:"build_tags,omitempty"`
 
-	// Unused but left in for parsing convenience
+	// Unused but included in marshaled json we receive
 	Overrides json.RawMessage `json:"overrides,omitempty"`
 	Rename    json.RawMessage `json:"rename,omitempty"`
 }
@@ -59,3 +59,11 @@ func parseOpts(req *plugin.CodeGenRequest) (*opts, error) {
 
 	return options, nil
 }
+
+func validateOpts(opts *opts) error {
+	if opts.EmitMethodsWithDbArgument && opts.EmitPreparedQueries {
+		return fmt.Errorf("invalid options: emit_methods_with_db_argument and emit_prepared_queries options are mutually exclusive")
+	}
+
+	return nil
+}
diff --git a/internal/codegen/golang/query.go b/internal/codegen/golang/query.go
index a52c6249d..b82178686 100644
--- a/internal/codegen/golang/query.go
+++ b/internal/codegen/golang/query.go
@@ -61,7 +61,7 @@ func (v QueryValue) Pairs() []Argument {
 		var out []Argument
 		for _, f := range v.Struct.Fields {
 			out = append(out, Argument{
-				Name: toLowerCase(f.Name),
+				Name: escape(toLowerCase(f.Name)),
 				Type: f.Type,
 			})
 		}
@@ -69,7 +69,7 @@ func (v QueryValue) Pairs() []Argument {
 	}
 	return []Argument{
 		{
-			Name: v.Name,
+			Name: escape(v.Name),
 			Type: v.DefineType(),
 		},
 	}
@@ -102,9 +102,9 @@ func (v *QueryValue) DefineType() string {
 
 func (v *QueryValue) ReturnName() string {
 	if v.IsPointer() {
-		return "&" + v.Name
+		return "&" + escape(v.Name)
 	}
-	return v.Name
+	return escape(v.Name)
 }
 
 func (v QueryValue) UniqueFields() []Field {
@@ -129,16 +129,16 @@ func (v QueryValue) Params() string {
 	var out []string
 	if v.Struct == nil {
 		if !v.Column.IsSqlcSlice && strings.HasPrefix(v.Typ, "[]") && v.Typ != "[]byte" && !v.SQLDriver.IsPGX() {
-			out = append(out, "pq.Array("+v.Name+")")
+			out = append(out, "pq.Array("+escape(v.Name)+")")
 		} else {
-			out = append(out, v.Name)
+			out = append(out, escape(v.Name))
 		}
 	} else {
 		for _, f := range v.Struct.Fields {
 			if !f.HasSqlcSlice() && strings.HasPrefix(f.Type, "[]") && f.Type != "[]byte" && !v.SQLDriver.IsPGX() {
-				out = append(out, "pq.Array("+v.VariableForField(f)+")")
+				out = append(out, "pq.Array("+escape(v.VariableForField(f))+")")
 			} else {
-				out = append(out, v.VariableForField(f))
+				out = append(out, escape(v.VariableForField(f)))
 			}
 		}
 	}
diff --git a/internal/codegen/golang/reserved.go b/internal/codegen/golang/reserved.go
new file mode 100644
index 000000000..fee711c57
--- /dev/null
+++ b/internal/codegen/golang/reserved.go
@@ -0,0 +1,65 @@
+package golang
+
+func escape(s string) string {
+	if IsReserved(s) {
+		return s + "_"
+	}
+	return s
+}
+
+func IsReserved(s string) bool {
+	switch s {
+	case "break":
+		return true
+	case "default":
+		return true
+	case "func":
+		return true
+	case "interface":
+		return true
+	case "select":
+		return true
+	case "case":
+		return true
+	case "defer":
+		return true
+	case "go":
+		return true
+	case "map":
+		return true
+	case "struct":
+		return true
+	case "chan":
+		return true
+	case "else":
+		return true
+	case "goto":
+		return true
+	case "package":
+		return true
+	case "switch":
+		return true
+	case "const":
+		return true
+	case "fallthrough":
+		return true
+	case "if":
+		return true
+	case "range":
+		return true
+	case "type":
+		return true
+	case "continue":
+		return true
+	case "for":
+		return true
+	case "import":
+		return true
+	case "return":
+		return true
+	case "var":
+		return true
+	default:
+		return false
+	}
+}
diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go
index 953882b14..03e2d21fc 100644
--- a/internal/codegen/golang/result.go
+++ b/internal/codegen/golang/result.go
@@ -215,7 +215,7 @@ func buildQueries(req *plugin.CodeGenRequest, options *opts, structs []Struct) (
 		if len(query.Params) == 1 && qpl != 0 {
 			p := query.Params[0]
 			gq.Arg = QueryValue{
-				Name:      paramName(p),
+				Name:      escape(paramName(p)),
 				DBName:    p.Column.GetName(),
 				Typ:       goType(req, options, p.Column),
 				SQLDriver: sqlpkg,
@@ -251,7 +251,7 @@ func buildQueries(req *plugin.CodeGenRequest, options *opts, structs []Struct) (
 			name := columnName(c, 0)
 			name = strings.Replace(name, "$", "_", -1)
 			gq.Ret = QueryValue{
-				Name:      name,
+				Name:      escape(name),
 				DBName:    name,
 				Typ:       goType(req, options, c),
 				SQLDriver: sqlpkg,
diff --git a/internal/compiler/compile.go b/internal/compiler/compile.go
index a6744fc6d..9f4a5170e 100644
--- a/internal/compiler/compile.go
+++ b/internal/compiler/compile.go
@@ -8,10 +8,10 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/sqlc-dev/sqlc/internal/metadata"
 	"github.com/sqlc-dev/sqlc/internal/migrations"
 	"github.com/sqlc-dev/sqlc/internal/multierr"
 	"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/sqlerr"
 	"github.com/sqlc-dev/sqlc/internal/sql/sqlpath"
@@ -20,7 +20,7 @@ import (
 // TODO: Rename this interface Engine
 type Parser interface {
 	Parse(io.Reader) ([]ast.Statement, error)
-	CommentSyntax() metadata.CommentSyntax
+	CommentSyntax() source.CommentSyntax
 	IsReservedKeyword(string) bool
 }
 
@@ -90,14 +90,15 @@ func (c *Compiler) parseQueries(o opts.Parser) (*Result, error) {
 				merr.Add(filename, src, loc, err)
 				continue
 			}
-			if query.Name != "" {
-				if _, exists := set[query.Name]; exists {
-					merr.Add(filename, src, stmt.Raw.Pos(), fmt.Errorf("duplicate query name: %s", query.Name))
+			queryName := query.Metadata.Name
+			if queryName != "" {
+				if _, exists := set[queryName]; exists {
+					merr.Add(filename, src, stmt.Raw.Pos(), fmt.Errorf("duplicate query name: %s", queryName))
 					continue
 				}
-				set[query.Name] = struct{}{}
+				set[queryName] = struct{}{}
 			}
-			query.Filename = filepath.Base(filename)
+			query.Metadata.Filename = filepath.Base(filename)
 			if query != nil {
 				q = append(q, query)
 			}
diff --git a/internal/compiler/output_columns.go b/internal/compiler/output_columns.go
index 8dfca0c5d..6ced89ae2 100644
--- a/internal/compiler/output_columns.go
+++ b/internal/compiler/output_columns.go
@@ -608,6 +608,9 @@ func (c *Compiler) sourceTables(qc *QueryCatalog, node ast.Node) ([]*Table, erro
 			if err != nil {
 				return nil, err
 			}
+			if qc == nil {
+				return nil, fmt.Errorf("query catalog is empty")
+			}
 			table, cerr := qc.GetTable(fqn)
 			if cerr != nil {
 				// TODO: Update error location
diff --git a/internal/compiler/parse.go b/internal/compiler/parse.go
index 53e3043c7..0b626e108 100644
--- a/internal/compiler/parse.go
+++ b/internal/compiler/parse.go
@@ -43,14 +43,31 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
 		return nil, errors.New("missing semicolon at end of file")
 	}
 
-	name, cmd, err := metadata.ParseQueryNameAndType(strings.TrimSpace(rawSQL), c.parser.CommentSyntax())
+	name, cmd, err := metadata.ParseQueryNameAndType(rawSQL, metadata.CommentSyntax(c.parser.CommentSyntax()))
 	if err != nil {
 		return nil, err
 	}
+
 	if err := validate.Cmd(raw.Stmt, name, cmd); err != nil {
 		return nil, err
 	}
 
+	md := metadata.Metadata{
+		Name: name,
+		Cmd:  cmd,
+	}
+
+	// TODO eventually can use this for name and type/cmd parsing too
+	cleanedComments, err := source.CleanedComments(rawSQL, c.parser.CommentSyntax())
+	if err != nil {
+		return nil, err
+	}
+
+	md.Params, md.Flags, err = metadata.ParseParamsAndFlags(cleanedComments)
+	if err != nil {
+		return nil, err
+	}
+
 	var anlys *analysis
 	if c.analyzer != nil {
 		// TODO: Handle panics
@@ -90,17 +107,11 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
 		return nil, err
 	}
 
-	flags, err := metadata.ParseQueryFlags(comments)
-	if err != nil {
-		return nil, err
-	}
+	md.Comments = comments
 
 	return &Query{
 		RawStmt:         raw,
-		Cmd:             cmd,
-		Comments:        comments,
-		Name:            name,
-		Flags:           flags,
+		Metadata:        md,
 		Params:          anlys.Parameters,
 		Columns:         anlys.Columns,
 		SQL:             trimmed,
diff --git a/internal/compiler/query.go b/internal/compiler/query.go
index 117cf4481..df580c197 100644
--- a/internal/compiler/query.go
+++ b/internal/compiler/query.go
@@ -1,6 +1,7 @@
 package compiler
 
 import (
+	"github.com/sqlc-dev/sqlc/internal/metadata"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 )
 
@@ -41,15 +42,9 @@ type Column struct {
 
 type Query struct {
 	SQL      string
-	Name     string
-	Cmd      string // TODO: Pick a better name. One of: one, many, exec, execrows, copyFrom
-	Flags    map[string]bool
+	Metadata metadata.Metadata
 	Columns  []*Column
 	Params   []Parameter
-	Comments []string
-
-	// XXX: Hack
-	Filename string
 
 	// Needed for CopyFrom
 	InsertIntoTable *ast.TableName
diff --git a/internal/compiler/resolve.go b/internal/compiler/resolve.go
index 4624c5a45..508c5600f 100644
--- a/internal/compiler/resolve.go
+++ b/internal/compiler/resolve.go
@@ -63,7 +63,10 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
 		}
 		table, err := c.GetTable(fqn)
 		if err != nil {
-			// If the table name doesn't exist, fisrt check if it's a CTE
+			if qc == nil {
+				continue
+			}
+			// If the table name doesn't exist, first check if it's a CTE
 			if _, qcerr := qc.GetTable(fqn); qcerr != nil {
 				return nil, err
 			}
diff --git a/internal/config/override.go b/internal/config/override.go
index f2337a79d..0bb050443 100644
--- a/internal/config/override.go
+++ b/internal/config/override.go
@@ -6,7 +6,6 @@ import (
 	"strings"
 
 	"github.com/sqlc-dev/sqlc/internal/pattern"
-	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 )
 
 type Override struct {
@@ -49,39 +48,6 @@ type Override struct {
 	GoStructTags map[string]string
 }
 
-func (o *Override) Matches(n *ast.TableName, defaultSchema string) bool {
-	if n == nil {
-		return false
-	}
-
-	schema := n.Schema
-	if n.Schema == "" {
-		schema = defaultSchema
-	}
-
-	if o.TableCatalog != nil && !o.TableCatalog.MatchString(n.Catalog) {
-		return false
-	}
-
-	if o.TableSchema == nil && schema != "" {
-		return false
-	}
-
-	if o.TableSchema != nil && !o.TableSchema.MatchString(schema) {
-		return false
-	}
-
-	if o.TableRel == nil && n.Name != "" {
-		return false
-	}
-
-	if o.TableRel != nil && !o.TableRel.MatchString(n.Name) {
-		return false
-	}
-
-	return true
-}
-
 func (o *Override) Parse() (err error) {
 
 	// validate deprecated postgres_type field
diff --git a/internal/config/python_type.go b/internal/config/python_type.go
deleted file mode 100644
index e90844805..000000000
--- a/internal/config/python_type.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package config
-
-type PythonType struct {
-	Module string `json:"module" yaml:"module"`
-	Name   string `json:"name" yaml:"name"`
-}
-
-func (t PythonType) IsSet() bool {
-	return t.Module != "" || t.Name != ""
-}
-
-func (t PythonType) TypeString() string {
-	if t.Name != "" && t.Module == "" {
-		return t.Name
-	}
-	return t.Module + "." + t.Name
-}
diff --git a/internal/config/validate.go b/internal/config/validate.go
index 207a888ec..b374a40c6 100644
--- a/internal/config/validate.go
+++ b/internal/config/validate.go
@@ -4,13 +4,6 @@ import "fmt"
 
 func Validate(c *Config) error {
 	for _, sql := range c.SQL {
-		sqlGo := sql.Gen.Go
-		if sqlGo == nil {
-			continue
-		}
-		if sqlGo.EmitMethodsWithDBArgument && sqlGo.EmitPreparedQueries {
-			return fmt.Errorf("invalid config: emit_methods_with_db_argument and emit_prepared_queries settings are mutually exclusive")
-		}
 		if sql.Database != nil {
 			if sql.Database.URI == "" && !sql.Database.Managed {
 				return fmt.Errorf("invalid config: database must be managed or have a non-empty URI")
diff --git a/internal/engine/dolphin/convert.go b/internal/engine/dolphin/convert.go
index b16e0a2a3..6d1f12fd0 100644
--- a/internal/engine/dolphin/convert.go
+++ b/internal/engine/dolphin/convert.go
@@ -43,20 +43,10 @@ func (c *cc) convertAlterTableStmt(n *pcast.AlterTableStmt) ast.Node {
 		case pcast.AlterTableAddColumns:
 			for _, def := range spec.NewColumns {
 				name := def.Name.String()
-				columnDef := ast.ColumnDef{
-					Colname:    def.Name.String(),
-					TypeName:   &ast.TypeName{Name: types.TypeToStr(def.Tp.GetType(), def.Tp.GetCharset())},
-					IsNotNull:  isNotNull(def),
-					IsUnsigned: isUnsigned(def),
-				}
-				if def.Tp.GetFlen() >= 0 {
-					length := def.Tp.GetFlen()
-					columnDef.Length = &length
-				}
 				alt.Cmds.Items = append(alt.Cmds.Items, &ast.AlterTableCmd{
 					Name:    &name,
 					Subtype: ast.AT_AddColumn,
-					Def:     &columnDef,
+					Def:     convertColumnDef(def),
 				})
 			}
 
@@ -77,36 +67,16 @@ func (c *cc) convertAlterTableStmt(n *pcast.AlterTableStmt) ast.Node {
 
 			for _, def := range spec.NewColumns {
 				name := def.Name.String()
-				columnDef := ast.ColumnDef{
-					Colname:    def.Name.String(),
-					TypeName:   &ast.TypeName{Name: types.TypeToStr(def.Tp.GetType(), def.Tp.GetCharset())},
-					IsNotNull:  isNotNull(def),
-					IsUnsigned: isUnsigned(def),
-				}
-				if def.Tp.GetFlen() >= 0 {
-					length := def.Tp.GetFlen()
-					columnDef.Length = &length
-				}
 				alt.Cmds.Items = append(alt.Cmds.Items, &ast.AlterTableCmd{
 					Name:    &name,
 					Subtype: ast.AT_AddColumn,
-					Def:     &columnDef,
+					Def:     convertColumnDef(def),
 				})
 			}
 
 		case pcast.AlterTableModifyColumn:
 			for _, def := range spec.NewColumns {
 				name := def.Name.String()
-				columnDef := ast.ColumnDef{
-					Colname:    def.Name.String(),
-					TypeName:   &ast.TypeName{Name: types.TypeToStr(def.Tp.GetType(), def.Tp.GetCharset())},
-					IsNotNull:  isNotNull(def),
-					IsUnsigned: isUnsigned(def),
-				}
-				if def.Tp.GetFlen() >= 0 {
-					length := def.Tp.GetFlen()
-					columnDef.Length = &length
-				}
 				alt.Cmds.Items = append(alt.Cmds.Items, &ast.AlterTableCmd{
 					Name:    &name,
 					Subtype: ast.AT_DropColumn,
@@ -114,7 +84,7 @@ func (c *cc) convertAlterTableStmt(n *pcast.AlterTableStmt) ast.Node {
 				alt.Cmds.Items = append(alt.Cmds.Items, &ast.AlterTableCmd{
 					Name:    &name,
 					Subtype: ast.AT_AddColumn,
-					Def:     &columnDef,
+					Def:     convertColumnDef(def),
 				})
 			}
 
@@ -249,37 +219,7 @@ func (c *cc) convertCreateTableStmt(n *pcast.CreateTableStmt) ast.Node {
 		create.ReferTable = parseTableName(n.ReferTable)
 	}
 	for _, def := range n.Cols {
-		var vals *ast.List
-		if len(def.Tp.GetElems()) > 0 {
-			vals = &ast.List{}
-			for i := range def.Tp.GetElems() {
-				vals.Items = append(vals.Items, &ast.String{
-					Str: def.Tp.GetElems()[i],
-				})
-			}
-		}
-		comment := ""
-		for _, opt := range def.Options {
-			switch opt.Tp {
-			case pcast.ColumnOptionComment:
-				if value, ok := opt.Expr.(*driver.ValueExpr); ok {
-					comment = value.GetString()
-				}
-			}
-		}
-		columnDef := ast.ColumnDef{
-			Colname:    def.Name.String(),
-			TypeName:   &ast.TypeName{Name: types.TypeToStr(def.Tp.GetType(), def.Tp.GetCharset())},
-			IsNotNull:  isNotNull(def),
-			IsUnsigned: isUnsigned(def),
-			Comment:    comment,
-			Vals:       vals,
-		}
-		if def.Tp.GetFlen() >= 0 {
-			length := def.Tp.GetFlen()
-			columnDef.Length = &length
-		}
-		create.Cols = append(create.Cols, &columnDef)
+		create.Cols = append(create.Cols, convertColumnDef(def))
 	}
 	for _, opt := range n.Options {
 		switch opt.Tp {
@@ -290,6 +230,41 @@ func (c *cc) convertCreateTableStmt(n *pcast.CreateTableStmt) ast.Node {
 	return create
 }
 
+func convertColumnDef(def *pcast.ColumnDef) *ast.ColumnDef {
+	var vals *ast.List
+	if len(def.Tp.GetElems()) > 0 {
+		vals = &ast.List{}
+		for i := range def.Tp.GetElems() {
+			vals.Items = append(vals.Items, &ast.String{
+				Str: def.Tp.GetElems()[i],
+			})
+		}
+	}
+	comment := ""
+	for _, opt := range def.Options {
+		switch opt.Tp {
+		case pcast.ColumnOptionComment:
+			if value, ok := opt.Expr.(*driver.ValueExpr); ok {
+				comment = value.GetString()
+			}
+		}
+	}
+	columnDef := ast.ColumnDef{
+		Colname:    def.Name.String(),
+		TypeName:   &ast.TypeName{Name: types.TypeToStr(def.Tp.GetType(), def.Tp.GetCharset())},
+		IsNotNull:  isNotNull(def),
+		IsUnsigned: isUnsigned(def),
+		Comment:    comment,
+		Vals:       vals,
+	}
+	if def.Tp.GetFlen() >= 0 {
+		length := def.Tp.GetFlen()
+		columnDef.Length = &length
+	}
+
+	return &columnDef
+}
+
 func (c *cc) convertColumnNameExpr(n *pcast.ColumnNameExpr) *ast.ColumnRef {
 	var items []ast.Node
 	if schema := n.Name.Schema.String(); schema != "" {
@@ -745,6 +720,7 @@ func (c *cc) convertCaseExpr(n *pcast.CaseExpr) ast.Node {
 		list.Items = append(list.Items, c.convertWhenClause(n))
 	}
 	return &ast.CaseExpr{
+		Arg:       c.convert(n.Value),
 		Args:      list,
 		Defresult: c.convert(n.ElseClause),
 		Location:  n.OriginTextPosition(),
diff --git a/internal/engine/dolphin/parse.go b/internal/engine/dolphin/parse.go
index 676362c44..22d3a1d22 100644
--- a/internal/engine/dolphin/parse.go
+++ b/internal/engine/dolphin/parse.go
@@ -10,7 +10,7 @@ import (
 	"github.com/pingcap/tidb/parser"
 	_ "github.com/pingcap/tidb/parser/test_driver"
 
-	"github.com/sqlc-dev/sqlc/internal/metadata"
+	"github.com/sqlc-dev/sqlc/internal/source"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 	"github.com/sqlc-dev/sqlc/internal/sql/sqlerr"
 )
@@ -86,8 +86,8 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) {
 }
 
 // https://dev.mysql.com/doc/refman/8.0/en/comments.html
-func (p *Parser) CommentSyntax() metadata.CommentSyntax {
-	return metadata.CommentSyntax{
+func (p *Parser) CommentSyntax() source.CommentSyntax {
+	return source.CommentSyntax{
 		Dash:      true,
 		SlashStar: true,
 		Hash:      true,
diff --git a/internal/engine/postgresql/analyzer/analyze.go b/internal/engine/postgresql/analyzer/analyze.go
index 160dcc83a..ab34eb348 100644
--- a/internal/engine/postgresql/analyzer/analyze.go
+++ b/internal/engine/postgresql/analyzer/analyze.go
@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"strings"
 	"sync"
-	"time"
 
 	"github.com/jackc/pgx/v5"
 	"github.com/jackc/pgx/v5/pgconn"
@@ -102,7 +101,6 @@ func (a *Analyzer) columnInfo(ctx context.Context, field pgconn.FieldDescription
 	if ok {
 		return cinfo.(*pgColumn), nil
 	}
-
 	rows, err := a.pool.Query(ctx, columnQuery, field.TableOID, field.TableAttributeNumber)
 	if err != nil {
 		return nil, err
@@ -213,9 +211,6 @@ func (a *Analyzer) Analyze(ctx context.Context, n ast.Node, query string, migrat
 		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
diff --git a/internal/engine/postgresql/parse.go b/internal/engine/postgresql/parse.go
index c1ac83381..296a14e85 100644
--- a/internal/engine/postgresql/parse.go
+++ b/internal/engine/postgresql/parse.go
@@ -12,7 +12,7 @@ import (
 	nodes "github.com/pganalyze/pg_query_go/v4"
 	"github.com/pganalyze/pg_query_go/v4/parser"
 
-	"github.com/sqlc-dev/sqlc/internal/metadata"
+	"github.com/sqlc-dev/sqlc/internal/source"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 	"github.com/sqlc-dev/sqlc/internal/sql/sqlerr"
 )
@@ -199,8 +199,8 @@ func normalizeErr(err error) error {
 }
 
 // https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-COMMENTS
-func (p *Parser) CommentSyntax() metadata.CommentSyntax {
-	return metadata.CommentSyntax{
+func (p *Parser) CommentSyntax() source.CommentSyntax {
+	return source.CommentSyntax{
 		Dash:      true,
 		SlashStar: true,
 	}
@@ -236,7 +236,7 @@ func translate(node *nodes.Node) (ast.Node, error) {
 		n := inner.AlterObjectSchemaStmt
 		switch n.ObjectType {
 
-		case nodes.ObjectType_OBJECT_TABLE:
+		case nodes.ObjectType_OBJECT_TABLE, nodes.ObjectType_OBJECT_VIEW, nodes.ObjectType_OBJECT_MATVIEW:
 			rel := parseRelationFromRangeVar(n.Relation)
 			return &ast.AlterTableSetSchemaStmt{
 				Table:     rel.TableName(),
diff --git a/internal/engine/sqlite/parse.go b/internal/engine/sqlite/parse.go
index bf0bacad9..56005dd2e 100644
--- a/internal/engine/sqlite/parse.go
+++ b/internal/engine/sqlite/parse.go
@@ -8,7 +8,7 @@ import (
 	"github.com/antlr/antlr4/runtime/Go/antlr/v4"
 
 	"github.com/sqlc-dev/sqlc/internal/engine/sqlite/parser"
-	"github.com/sqlc-dev/sqlc/internal/metadata"
+	"github.com/sqlc-dev/sqlc/internal/source"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 )
 
@@ -86,8 +86,8 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) {
 	return stmts, nil
 }
 
-func (p *Parser) CommentSyntax() metadata.CommentSyntax {
-	return metadata.CommentSyntax{
+func (p *Parser) CommentSyntax() source.CommentSyntax {
+	return source.CommentSyntax{
 		Dash:      true,
 		Hash:      false,
 		SlashStar: true,
diff --git a/internal/metadata/meta.go b/internal/metadata/meta.go
index 4176da1e2..97ff36dbd 100644
--- a/internal/metadata/meta.go
+++ b/internal/metadata/meta.go
@@ -1,15 +1,24 @@
 package metadata
 
 import (
+	"bufio"
 	"fmt"
 	"strings"
 	"unicode"
+
+	"github.com/sqlc-dev/sqlc/internal/source"
 )
 
-type CommentSyntax struct {
-	Dash      bool
-	Hash      bool
-	SlashStar bool
+type CommentSyntax source.CommentSyntax
+
+type Metadata struct {
+	Name     string
+	Cmd      string
+	Comments []string
+	Params   map[string]string
+	Flags    map[string]bool
+
+	Filename string
 }
 
 const (
@@ -83,7 +92,7 @@ func ParseQueryNameAndType(t string, commentStyle CommentSyntax) (string, string
 		if prefix == "/*" {
 			part = part[:len(part)-1] // removes the trailing "*/" element
 		}
-		if len(part) == 2 {
+		if len(part) == 3 {
 			return "", "", fmt.Errorf("missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: %s", line)
 		}
 		if len(part) != 4 {
@@ -104,19 +113,39 @@ func ParseQueryNameAndType(t string, commentStyle CommentSyntax) (string, string
 	return "", "", nil
 }
 
-func ParseQueryFlags(comments []string) (map[string]bool, error) {
+func ParseParamsAndFlags(comments []string) (map[string]string, map[string]bool, error) {
+	params := make(map[string]string)
 	flags := make(map[string]bool)
+
 	for _, line := range comments {
-		cleanLine := strings.TrimPrefix(line, "--")
-		cleanLine = strings.TrimPrefix(cleanLine, "/*")
-		cleanLine = strings.TrimPrefix(cleanLine, "#")
-		cleanLine = strings.TrimSuffix(cleanLine, "*/")
-		cleanLine = strings.TrimSpace(cleanLine)
-		if strings.HasPrefix(cleanLine, "@") {
-			flagName := strings.SplitN(cleanLine, " ", 2)[0]
-			flags[flagName] = true
+		s := bufio.NewScanner(strings.NewReader(line))
+		s.Split(bufio.ScanWords)
+
+		s.Scan()
+		token := s.Text()
+
+		if !strings.HasPrefix(token, "@") {
 			continue
 		}
+
+		switch token {
+		case "@param":
+			s.Scan()
+			name := s.Text()
+			var rest []string
+			for s.Scan() {
+				paramToken := s.Text()
+				rest = append(rest, paramToken)
+			}
+			params[name] = strings.Join(rest, " ")
+		default:
+			flags[token] = true
+		}
+
+		if s.Err() != nil {
+			return params, flags, s.Err()
+		}
 	}
-	return flags, nil
+
+	return params, flags, nil
 }
diff --git a/internal/plugin/codegen.pb.go b/internal/plugin/codegen.pb.go
index bdfe790fc..7b3347c6e 100644
--- a/internal/plugin/codegen.pb.go
+++ b/internal/plugin/codegen.pb.go
@@ -362,9 +362,12 @@ type Codegen struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Out     string `protobuf:"bytes,1,opt,name=out,proto3" json:"out,omitempty"`
-	Plugin  string `protobuf:"bytes,2,opt,name=plugin,proto3" json:"plugin,omitempty"`
-	Options []byte `protobuf:"bytes,3,opt,name=options,proto3" json:"options,omitempty"`
+	Out     string           `protobuf:"bytes,1,opt,name=out,proto3" json:"out,omitempty"`
+	Plugin  string           `protobuf:"bytes,2,opt,name=plugin,proto3" json:"plugin,omitempty"`
+	Options []byte           `protobuf:"bytes,3,opt,name=options,proto3" json:"options,omitempty"`
+	Env     []string         `protobuf:"bytes,4,rep,name=env,proto3" json:"env,omitempty"`
+	Process *Codegen_Process `protobuf:"bytes,5,opt,name=process,proto3" json:"process,omitempty"`
+	Wasm    *Codegen_WASM    `protobuf:"bytes,6,opt,name=wasm,proto3" json:"wasm,omitempty"`
 }
 
 func (x *Codegen) Reset() {
@@ -420,6 +423,27 @@ func (x *Codegen) GetOptions() []byte {
 	return nil
 }
 
+func (x *Codegen) GetEnv() []string {
+	if x != nil {
+		return x.Env
+	}
+	return nil
+}
+
+func (x *Codegen) GetProcess() *Codegen_Process {
+	if x != nil {
+		return x.Process
+	}
+	return nil
+}
+
+func (x *Codegen) GetWasm() *Codegen_WASM {
+	if x != nil {
+		return x.Wasm
+	}
+	return nil
+}
+
 type Catalog struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1266,6 +1290,108 @@ func (x *CodeGenResponse) GetFiles() []*File {
 	return nil
 }
 
+type Codegen_Process struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Cmd string `protobuf:"bytes,1,opt,name=cmd,proto3" json:"cmd,omitempty"`
+}
+
+func (x *Codegen_Process) Reset() {
+	*x = Codegen_Process{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_plugin_codegen_proto_msgTypes[18]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Codegen_Process) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Codegen_Process) ProtoMessage() {}
+
+func (x *Codegen_Process) ProtoReflect() protoreflect.Message {
+	mi := &file_plugin_codegen_proto_msgTypes[18]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Codegen_Process.ProtoReflect.Descriptor instead.
+func (*Codegen_Process) Descriptor() ([]byte, []int) {
+	return file_plugin_codegen_proto_rawDescGZIP(), []int{4, 0}
+}
+
+func (x *Codegen_Process) GetCmd() string {
+	if x != nil {
+		return x.Cmd
+	}
+	return ""
+}
+
+type Codegen_WASM struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Url    string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+	Sha256 string `protobuf:"bytes,2,opt,name=sha256,proto3" json:"sha256,omitempty"`
+}
+
+func (x *Codegen_WASM) Reset() {
+	*x = Codegen_WASM{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_plugin_codegen_proto_msgTypes[19]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Codegen_WASM) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Codegen_WASM) ProtoMessage() {}
+
+func (x *Codegen_WASM) ProtoReflect() protoreflect.Message {
+	mi := &file_plugin_codegen_proto_msgTypes[19]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Codegen_WASM.ProtoReflect.Descriptor instead.
+func (*Codegen_WASM) Descriptor() ([]byte, []int) {
+	return file_plugin_codegen_proto_rawDescGZIP(), []int{4, 1}
+}
+
+func (x *Codegen_WASM) GetUrl() string {
+	if x != nil {
+		return x.Url
+	}
+	return ""
+}
+
+func (x *Codegen_WASM) GetSha256() string {
+	if x != nil {
+		return x.Sha256
+	}
+	return ""
+}
+
 var File_plugin_codegen_proto protoreflect.FileDescriptor
 
 var file_plugin_codegen_proto_rawDesc = []byte{
@@ -1330,134 +1456,146 @@ var file_plugin_codegen_proto_rawDesc = []byte{
 	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
 	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08,
 	0x09, 0x10, 0x0a, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x22,
-	0x4d, 0x0a, 0x07, 0x43, 0x6f, 0x64, 0x65, 0x67, 0x65, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x75,
-	0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06,
-	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c,
-	0x75, 0x67, 0x69, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x88,
-	0x01, 0x0a, 0x07, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f,
-	0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d,
-	0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f,
-	0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65,
-	0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0x28, 0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61,
-	0x52, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x06, 0x53, 0x63,
-	0x68, 0x65, 0x6d, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
-	0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c,
-	0x65, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x65, 0x6e, 0x75,
-	0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69,
-	0x6e, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x12, 0x3e, 0x0a,
-	0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73,
-	0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
-	0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x63,
-	0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3d, 0x0a,
-	0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x04,
-	0x45, 0x6e, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x61, 0x6c, 0x73,
-	0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07,
-	0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63,
-	0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x71, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12,
-	0x24, 0x0a, 0x03, 0x72, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72,
-	0x52, 0x03, 0x72, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73,
-	0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
-	0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12,
-	0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x0a, 0x49, 0x64, 0x65,
-	0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c,
-	0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
-	0x67, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8e, 0x04,
-	0x0a, 0x06, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08,
-	0x6e, 0x6f, 0x74, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
-	0x6e, 0x6f, 0x74, 0x4e, 0x75, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x61, 0x72,
-	0x72, 0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72,
-	0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06,
-	0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65,
-	0x6e, 0x67, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x64,
-	0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73,
-	0x4e, 0x61, 0x6d, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73,
-	0x5f, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08,
-	0x52, 0x0a, 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x14, 0x0a, 0x05,
-	0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f,
-	0x70, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74,
-	0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
-	0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x26, 0x0a,
-	0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c,
+	0x8b, 0x02, 0x0a, 0x07, 0x43, 0x6f, 0x64, 0x65, 0x67, 0x65, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6f,
+	0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a,
+	0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70,
+	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+	0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e,
+	0x76, 0x12, 0x31, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65,
+	0x67, 0x65, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x07, 0x70, 0x72, 0x6f,
+	0x63, 0x65, 0x73, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x77, 0x61, 0x73, 0x6d, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x64, 0x65,
+	0x67, 0x65, 0x6e, 0x2e, 0x57, 0x41, 0x53, 0x4d, 0x52, 0x04, 0x77, 0x61, 0x73, 0x6d, 0x1a, 0x1b,
+	0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x1a, 0x30, 0x0a, 0x04, 0x57,
+	0x41, 0x53, 0x4d, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x22, 0x88, 0x01,
+	0x0a, 0x07, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d,
+	0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d,
+	0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73,
+	0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x66,
+	0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28,
+	0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52,
+	0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x06, 0x53, 0x63, 0x68,
+	0x65, 0x6d, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65,
+	0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x65, 0x6e, 0x75, 0x6d,
+	0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x0f,
+	0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18,
+	0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43,
+	0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x63, 0x6f,
+	0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x0d,
+	0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x04, 0x45,
+	0x6e, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x18,
+	0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63,
+	0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f,
+	0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x71, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24,
+	0x0a, 0x03, 0x72, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c,
 	0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52,
-	0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x73, 0x71, 0x6c, 0x63,
-	0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73,
-	0x53, 0x71, 0x6c, 0x63, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x0b, 0x65, 0x6d, 0x62,
-	0x65, 0x64, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
-	0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
-	0x65, 0x72, 0x52, 0x0a, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x23,
-	0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-	0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x4e,
-	0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x18,
-	0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x12,
-	0x1d, 0x0a, 0x0a, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x64, 0x69, 0x6d, 0x73, 0x18, 0x11, 0x20,
-	0x01, 0x28, 0x05, 0x52, 0x09, 0x61, 0x72, 0x72, 0x61, 0x79, 0x44, 0x69, 0x6d, 0x73, 0x22, 0x94,
-	0x02, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04,
-	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-	0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63,
-	0x6d, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x04, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c,
-	0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x2d, 0x0a, 0x06,
-	0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52,
-	0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63,
-	0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63,
-	0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e,
-	0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x6e,
-	0x74, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
-	0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
-	0x65, 0x72, 0x52, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f,
-	0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x4b, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
-	0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x6f,
-	0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75,
-	0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75,
-	0x6d, 0x6e, 0x22, 0xde, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
-	0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69,
-	0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x61,
-	0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x27,
-	0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x07,
-	0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x71, 0x6c, 0x63, 0x5f,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73,
-	0x71, 0x6c, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x70,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69,
-	0x6f, 0x6e, 0x73, 0x22, 0x35, 0x0a, 0x0f, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18,
-	0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x46,
-	0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x7c, 0x0a, 0x0a, 0x63, 0x6f,
-	0x6d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x42, 0x0c, 0x43, 0x6f, 0x64, 0x65, 0x67, 0x65,
-	0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
-	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x73, 0x71,
-	0x6c, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67,
-	0x69, 0x6e, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69,
-	0x6e, 0xca, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xe2, 0x02, 0x12, 0x50, 0x6c, 0x75,
-	0x67, 0x69, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea,
-	0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x03, 0x72, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18,
+	0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43,
+	0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x18,
+	0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x0a, 0x49, 0x64, 0x65, 0x6e,
+	0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
+	0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67,
+	0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8e, 0x04, 0x0a,
+	0x06, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e,
+	0x6f, 0x74, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e,
+	0x6f, 0x74, 0x4e, 0x75, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x61, 0x72, 0x72,
+	0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61,
+	0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c,
+	0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e,
+	0x67, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x5f,
+	0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x4e,
+	0x61, 0x6d, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x5f,
+	0x66, 0x75, 0x6e, 0x63, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x0a, 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73,
+	0x63, 0x6f, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70,
+	0x65, 0x12, 0x28, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
+	0x66, 0x69, 0x65, 0x72, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74,
+	0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x26, 0x0a, 0x04,
+	0x74, 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x04,
+	0x74, 0x79, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x73, 0x71, 0x6c, 0x63, 0x5f,
+	0x73, 0x6c, 0x69, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x53,
+	0x71, 0x6c, 0x63, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x0b, 0x65, 0x6d, 0x62, 0x65,
+	0x64, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65,
+	0x72, 0x52, 0x0a, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x23, 0x0a,
+	0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x4e, 0x61,
+	0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x18, 0x10,
+	0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x12, 0x1d,
+	0x0a, 0x0a, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x64, 0x69, 0x6d, 0x73, 0x18, 0x11, 0x20, 0x01,
+	0x28, 0x05, 0x52, 0x09, 0x61, 0x72, 0x72, 0x61, 0x79, 0x44, 0x69, 0x6d, 0x73, 0x22, 0x94, 0x02,
+	0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+	0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d,
+	0x64, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75,
+	0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x70,
+	0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a,
+	0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f,
+	0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f,
+	0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
+	0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x74,
+	0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65,
+	0x72, 0x52, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x74,
+	0x61, 0x62, 0x6c, 0x65, 0x22, 0x4b, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
+	0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x6f, 0x6c,
+	0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67,
+	0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x22, 0xde, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
+	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
+	0x67, 0x73, 0x12, 0x29, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x61, 0x74,
+	0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x27, 0x0a,
+	0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d,
+	0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x07, 0x71,
+	0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x71, 0x6c, 0x63, 0x5f, 0x76,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x71,
+	0x6c, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x70, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x0e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f,
+	0x6e, 0x73, 0x22, 0x35, 0x0a, 0x0f, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x46, 0x69,
+	0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x7c, 0x0a, 0x0a, 0x63, 0x6f, 0x6d,
+	0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x42, 0x0c, 0x43, 0x6f, 0x64, 0x65, 0x67, 0x65, 0x6e,
+	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+	0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x73, 0x71, 0x6c,
+	0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
+	0x6e, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0xca, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xe2, 0x02, 0x12, 0x50, 0x6c, 0x75, 0x67,
+	0x69, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
+	0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1472,7 +1610,7 @@ func file_plugin_codegen_proto_rawDescGZIP() []byte {
 	return file_plugin_codegen_proto_rawDescData
 }
 
-var file_plugin_codegen_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
+var file_plugin_codegen_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
 var file_plugin_codegen_proto_goTypes = []interface{}{
 	(*File)(nil),            // 0: plugin.File
 	(*Override)(nil),        // 1: plugin.Override
@@ -1492,6 +1630,8 @@ var file_plugin_codegen_proto_goTypes = []interface{}{
 	(*CodeGenResponse)(nil), // 15: plugin.CodeGenResponse
 	nil,                     // 16: plugin.ParsedGoType.StructTagsEntry
 	nil,                     // 17: plugin.Settings.RenameEntry
+	(*Codegen_Process)(nil), // 18: plugin.Codegen.Process
+	(*Codegen_WASM)(nil),    // 19: plugin.Codegen.WASM
 }
 var file_plugin_codegen_proto_depIdxs = []int32{
 	10, // 0: plugin.Override.table:type_name -> plugin.Identifier
@@ -1500,28 +1640,30 @@ var file_plugin_codegen_proto_depIdxs = []int32{
 	17, // 3: plugin.Settings.rename:type_name -> plugin.Settings.RenameEntry
 	1,  // 4: plugin.Settings.overrides:type_name -> plugin.Override
 	4,  // 5: plugin.Settings.codegen:type_name -> plugin.Codegen
-	6,  // 6: plugin.Catalog.schemas:type_name -> plugin.Schema
-	9,  // 7: plugin.Schema.tables:type_name -> plugin.Table
-	8,  // 8: plugin.Schema.enums:type_name -> plugin.Enum
-	7,  // 9: plugin.Schema.composite_types:type_name -> plugin.CompositeType
-	10, // 10: plugin.Table.rel:type_name -> plugin.Identifier
-	11, // 11: plugin.Table.columns:type_name -> plugin.Column
-	10, // 12: plugin.Column.table:type_name -> plugin.Identifier
-	10, // 13: plugin.Column.type:type_name -> plugin.Identifier
-	10, // 14: plugin.Column.embed_table:type_name -> plugin.Identifier
-	11, // 15: plugin.Query.columns:type_name -> plugin.Column
-	13, // 16: plugin.Query.params:type_name -> plugin.Parameter
-	10, // 17: plugin.Query.insert_into_table:type_name -> plugin.Identifier
-	11, // 18: plugin.Parameter.column:type_name -> plugin.Column
-	3,  // 19: plugin.CodeGenRequest.settings:type_name -> plugin.Settings
-	5,  // 20: plugin.CodeGenRequest.catalog:type_name -> plugin.Catalog
-	12, // 21: plugin.CodeGenRequest.queries:type_name -> plugin.Query
-	0,  // 22: plugin.CodeGenResponse.files:type_name -> plugin.File
-	23, // [23:23] is the sub-list for method output_type
-	23, // [23:23] is the sub-list for method input_type
-	23, // [23:23] is the sub-list for extension type_name
-	23, // [23:23] is the sub-list for extension extendee
-	0,  // [0:23] is the sub-list for field type_name
+	18, // 6: plugin.Codegen.process:type_name -> plugin.Codegen.Process
+	19, // 7: plugin.Codegen.wasm:type_name -> plugin.Codegen.WASM
+	6,  // 8: plugin.Catalog.schemas:type_name -> plugin.Schema
+	9,  // 9: plugin.Schema.tables:type_name -> plugin.Table
+	8,  // 10: plugin.Schema.enums:type_name -> plugin.Enum
+	7,  // 11: plugin.Schema.composite_types:type_name -> plugin.CompositeType
+	10, // 12: plugin.Table.rel:type_name -> plugin.Identifier
+	11, // 13: plugin.Table.columns:type_name -> plugin.Column
+	10, // 14: plugin.Column.table:type_name -> plugin.Identifier
+	10, // 15: plugin.Column.type:type_name -> plugin.Identifier
+	10, // 16: plugin.Column.embed_table:type_name -> plugin.Identifier
+	11, // 17: plugin.Query.columns:type_name -> plugin.Column
+	13, // 18: plugin.Query.params:type_name -> plugin.Parameter
+	10, // 19: plugin.Query.insert_into_table:type_name -> plugin.Identifier
+	11, // 20: plugin.Parameter.column:type_name -> plugin.Column
+	3,  // 21: plugin.CodeGenRequest.settings:type_name -> plugin.Settings
+	5,  // 22: plugin.CodeGenRequest.catalog:type_name -> plugin.Catalog
+	12, // 23: plugin.CodeGenRequest.queries:type_name -> plugin.Query
+	0,  // 24: plugin.CodeGenResponse.files:type_name -> plugin.File
+	25, // [25:25] is the sub-list for method output_type
+	25, // [25:25] is the sub-list for method input_type
+	25, // [25:25] is the sub-list for extension type_name
+	25, // [25:25] is the sub-list for extension extendee
+	0,  // [0:25] is the sub-list for field type_name
 }
 
 func init() { file_plugin_codegen_proto_init() }
@@ -1722,6 +1864,30 @@ func file_plugin_codegen_proto_init() {
 				return nil
 			}
 		}
+		file_plugin_codegen_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Codegen_Process); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_plugin_codegen_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Codegen_WASM); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -1729,7 +1895,7 @@ func file_plugin_codegen_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_plugin_codegen_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   18,
+			NumMessages:   20,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/internal/plugin/codegen_vtproto.pb.go b/internal/plugin/codegen_vtproto.pb.go
index f77e1c096..3ff0dc600 100644
--- a/internal/plugin/codegen_vtproto.pb.go
+++ b/internal/plugin/codegen_vtproto.pb.go
@@ -139,19 +139,63 @@ func (m *Settings) CloneMessageVT() proto.Message {
 	return m.CloneVT()
 }
 
+func (m *Codegen_Process) CloneVT() *Codegen_Process {
+	if m == nil {
+		return (*Codegen_Process)(nil)
+	}
+	r := &Codegen_Process{
+		Cmd: m.Cmd,
+	}
+	if len(m.unknownFields) > 0 {
+		r.unknownFields = make([]byte, len(m.unknownFields))
+		copy(r.unknownFields, m.unknownFields)
+	}
+	return r
+}
+
+func (m *Codegen_Process) CloneMessageVT() proto.Message {
+	return m.CloneVT()
+}
+
+func (m *Codegen_WASM) CloneVT() *Codegen_WASM {
+	if m == nil {
+		return (*Codegen_WASM)(nil)
+	}
+	r := &Codegen_WASM{
+		Url:    m.Url,
+		Sha256: m.Sha256,
+	}
+	if len(m.unknownFields) > 0 {
+		r.unknownFields = make([]byte, len(m.unknownFields))
+		copy(r.unknownFields, m.unknownFields)
+	}
+	return r
+}
+
+func (m *Codegen_WASM) CloneMessageVT() proto.Message {
+	return m.CloneVT()
+}
+
 func (m *Codegen) CloneVT() *Codegen {
 	if m == nil {
 		return (*Codegen)(nil)
 	}
 	r := &Codegen{
-		Out:    m.Out,
-		Plugin: m.Plugin,
+		Out:     m.Out,
+		Plugin:  m.Plugin,
+		Process: m.Process.CloneVT(),
+		Wasm:    m.Wasm.CloneVT(),
 	}
 	if rhs := m.Options; rhs != nil {
 		tmpBytes := make([]byte, len(rhs))
 		copy(tmpBytes, rhs)
 		r.Options = tmpBytes
 	}
+	if rhs := m.Env; rhs != nil {
+		tmpContainer := make([]string, len(rhs))
+		copy(tmpContainer, rhs)
+		r.Env = tmpContainer
+	}
 	if len(m.unknownFields) > 0 {
 		r.unknownFields = make([]byte, len(m.unknownFields))
 		copy(r.unknownFields, m.unknownFields)
@@ -641,6 +685,47 @@ func (this *Settings) EqualMessageVT(thatMsg proto.Message) bool {
 	}
 	return this.EqualVT(that)
 }
+func (this *Codegen_Process) EqualVT(that *Codegen_Process) bool {
+	if this == that {
+		return true
+	} else if this == nil || that == nil {
+		return false
+	}
+	if this.Cmd != that.Cmd {
+		return false
+	}
+	return string(this.unknownFields) == string(that.unknownFields)
+}
+
+func (this *Codegen_Process) EqualMessageVT(thatMsg proto.Message) bool {
+	that, ok := thatMsg.(*Codegen_Process)
+	if !ok {
+		return false
+	}
+	return this.EqualVT(that)
+}
+func (this *Codegen_WASM) EqualVT(that *Codegen_WASM) bool {
+	if this == that {
+		return true
+	} else if this == nil || that == nil {
+		return false
+	}
+	if this.Url != that.Url {
+		return false
+	}
+	if this.Sha256 != that.Sha256 {
+		return false
+	}
+	return string(this.unknownFields) == string(that.unknownFields)
+}
+
+func (this *Codegen_WASM) EqualMessageVT(thatMsg proto.Message) bool {
+	that, ok := thatMsg.(*Codegen_WASM)
+	if !ok {
+		return false
+	}
+	return this.EqualVT(that)
+}
 func (this *Codegen) EqualVT(that *Codegen) bool {
 	if this == that {
 		return true
@@ -656,6 +741,21 @@ func (this *Codegen) EqualVT(that *Codegen) bool {
 	if string(this.Options) != string(that.Options) {
 		return false
 	}
+	if len(this.Env) != len(that.Env) {
+		return false
+	}
+	for i, vx := range this.Env {
+		vy := that.Env[i]
+		if vx != vy {
+			return false
+		}
+	}
+	if !this.Process.EqualVT(that.Process) {
+		return false
+	}
+	if !this.Wasm.EqualVT(that.Wasm) {
+		return false
+	}
 	return string(this.unknownFields) == string(that.unknownFields)
 }
 
@@ -1473,6 +1573,93 @@ func (m *Settings) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
+func (m *Codegen_Process) MarshalVT() (dAtA []byte, err error) {
+	if m == nil {
+		return nil, nil
+	}
+	size := m.SizeVT()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBufferVT(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Codegen_Process) MarshalToVT(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVT(dAtA[:size])
+}
+
+func (m *Codegen_Process) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
+	if m == nil {
+		return 0, nil
+	}
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.unknownFields != nil {
+		i -= len(m.unknownFields)
+		copy(dAtA[i:], m.unknownFields)
+	}
+	if len(m.Cmd) > 0 {
+		i -= len(m.Cmd)
+		copy(dAtA[i:], m.Cmd)
+		i = encodeVarint(dAtA, i, uint64(len(m.Cmd)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Codegen_WASM) MarshalVT() (dAtA []byte, err error) {
+	if m == nil {
+		return nil, nil
+	}
+	size := m.SizeVT()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBufferVT(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Codegen_WASM) MarshalToVT(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVT(dAtA[:size])
+}
+
+func (m *Codegen_WASM) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
+	if m == nil {
+		return 0, nil
+	}
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.unknownFields != nil {
+		i -= len(m.unknownFields)
+		copy(dAtA[i:], m.unknownFields)
+	}
+	if len(m.Sha256) > 0 {
+		i -= len(m.Sha256)
+		copy(dAtA[i:], m.Sha256)
+		i = encodeVarint(dAtA, i, uint64(len(m.Sha256)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Url) > 0 {
+		i -= len(m.Url)
+		copy(dAtA[i:], m.Url)
+		i = encodeVarint(dAtA, i, uint64(len(m.Url)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
 func (m *Codegen) MarshalVT() (dAtA []byte, err error) {
 	if m == nil {
 		return nil, nil
@@ -1503,6 +1690,35 @@ func (m *Codegen) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
 		i -= len(m.unknownFields)
 		copy(dAtA[i:], m.unknownFields)
 	}
+	if m.Wasm != nil {
+		size, err := m.Wasm.MarshalToSizedBufferVT(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x32
+	}
+	if m.Process != nil {
+		size, err := m.Process.MarshalToSizedBufferVT(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x2a
+	}
+	if len(m.Env) > 0 {
+		for iNdEx := len(m.Env) - 1; iNdEx >= 0; iNdEx-- {
+			i -= len(m.Env[iNdEx])
+			copy(dAtA[i:], m.Env[iNdEx])
+			i = encodeVarint(dAtA, i, uint64(len(m.Env[iNdEx])))
+			i--
+			dAtA[i] = 0x22
+		}
+	}
 	if len(m.Options) > 0 {
 		i -= len(m.Options)
 		copy(dAtA[i:], m.Options)
@@ -2691,7 +2907,7 @@ func (m *Settings) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
-func (m *Codegen) MarshalVTStrict() (dAtA []byte, err error) {
+func (m *Codegen_Process) MarshalVTStrict() (dAtA []byte, err error) {
 	if m == nil {
 		return nil, nil
 	}
@@ -2704,12 +2920,12 @@ func (m *Codegen) MarshalVTStrict() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *Codegen) MarshalToVTStrict(dAtA []byte) (int, error) {
+func (m *Codegen_Process) MarshalToVTStrict(dAtA []byte) (int, error) {
 	size := m.SizeVT()
 	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
 }
 
-func (m *Codegen) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
+func (m *Codegen_Process) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 	if m == nil {
 		return 0, nil
 	}
@@ -2721,31 +2937,17 @@ func (m *Codegen) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 		i -= len(m.unknownFields)
 		copy(dAtA[i:], m.unknownFields)
 	}
-	if len(m.Options) > 0 {
-		i -= len(m.Options)
-		copy(dAtA[i:], m.Options)
-		i = encodeVarint(dAtA, i, uint64(len(m.Options)))
-		i--
-		dAtA[i] = 0x1a
-	}
-	if len(m.Plugin) > 0 {
-		i -= len(m.Plugin)
-		copy(dAtA[i:], m.Plugin)
-		i = encodeVarint(dAtA, i, uint64(len(m.Plugin)))
-		i--
-		dAtA[i] = 0x12
-	}
-	if len(m.Out) > 0 {
-		i -= len(m.Out)
-		copy(dAtA[i:], m.Out)
-		i = encodeVarint(dAtA, i, uint64(len(m.Out)))
+	if len(m.Cmd) > 0 {
+		i -= len(m.Cmd)
+		copy(dAtA[i:], m.Cmd)
+		i = encodeVarint(dAtA, i, uint64(len(m.Cmd)))
 		i--
 		dAtA[i] = 0xa
 	}
 	return len(dAtA) - i, nil
 }
 
-func (m *Catalog) MarshalVTStrict() (dAtA []byte, err error) {
+func (m *Codegen_WASM) MarshalVTStrict() (dAtA []byte, err error) {
 	if m == nil {
 		return nil, nil
 	}
@@ -2758,12 +2960,12 @@ func (m *Catalog) MarshalVTStrict() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *Catalog) MarshalToVTStrict(dAtA []byte) (int, error) {
+func (m *Codegen_WASM) MarshalToVTStrict(dAtA []byte) (int, error) {
 	size := m.SizeVT()
 	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
 }
 
-func (m *Catalog) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
+func (m *Codegen_WASM) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 	if m == nil {
 		return 0, nil
 	}
@@ -2775,43 +2977,24 @@ func (m *Catalog) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 		i -= len(m.unknownFields)
 		copy(dAtA[i:], m.unknownFields)
 	}
-	if len(m.Schemas) > 0 {
-		for iNdEx := len(m.Schemas) - 1; iNdEx >= 0; iNdEx-- {
-			size, err := m.Schemas[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
-			if err != nil {
-				return 0, err
-			}
-			i -= size
-			i = encodeVarint(dAtA, i, uint64(size))
-			i--
-			dAtA[i] = 0x22
-		}
-	}
-	if len(m.Name) > 0 {
-		i -= len(m.Name)
-		copy(dAtA[i:], m.Name)
-		i = encodeVarint(dAtA, i, uint64(len(m.Name)))
-		i--
-		dAtA[i] = 0x1a
-	}
-	if len(m.DefaultSchema) > 0 {
-		i -= len(m.DefaultSchema)
-		copy(dAtA[i:], m.DefaultSchema)
-		i = encodeVarint(dAtA, i, uint64(len(m.DefaultSchema)))
+	if len(m.Sha256) > 0 {
+		i -= len(m.Sha256)
+		copy(dAtA[i:], m.Sha256)
+		i = encodeVarint(dAtA, i, uint64(len(m.Sha256)))
 		i--
 		dAtA[i] = 0x12
 	}
-	if len(m.Comment) > 0 {
-		i -= len(m.Comment)
-		copy(dAtA[i:], m.Comment)
-		i = encodeVarint(dAtA, i, uint64(len(m.Comment)))
+	if len(m.Url) > 0 {
+		i -= len(m.Url)
+		copy(dAtA[i:], m.Url)
+		i = encodeVarint(dAtA, i, uint64(len(m.Url)))
 		i--
 		dAtA[i] = 0xa
 	}
 	return len(dAtA) - i, nil
 }
 
-func (m *Schema) MarshalVTStrict() (dAtA []byte, err error) {
+func (m *Codegen) MarshalVTStrict() (dAtA []byte, err error) {
 	if m == nil {
 		return nil, nil
 	}
@@ -2824,12 +3007,12 @@ func (m *Schema) MarshalVTStrict() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *Schema) MarshalToVTStrict(dAtA []byte) (int, error) {
+func (m *Codegen) MarshalToVTStrict(dAtA []byte) (int, error) {
 	size := m.SizeVT()
 	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
 }
 
-func (m *Schema) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
+func (m *Codegen) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 	if m == nil {
 		return 0, nil
 	}
@@ -2841,31 +3024,180 @@ func (m *Schema) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
 		i -= len(m.unknownFields)
 		copy(dAtA[i:], m.unknownFields)
 	}
-	if len(m.CompositeTypes) > 0 {
-		for iNdEx := len(m.CompositeTypes) - 1; iNdEx >= 0; iNdEx-- {
-			size, err := m.CompositeTypes[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
-			if err != nil {
-				return 0, err
-			}
-			i -= size
-			i = encodeVarint(dAtA, i, uint64(size))
-			i--
-			dAtA[i] = 0x2a
+	if m.Wasm != nil {
+		size, err := m.Wasm.MarshalToSizedBufferVTStrict(dAtA[:i])
+		if err != nil {
+			return 0, err
 		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x32
 	}
-	if len(m.Enums) > 0 {
-		for iNdEx := len(m.Enums) - 1; iNdEx >= 0; iNdEx-- {
-			size, err := m.Enums[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
-			if err != nil {
-				return 0, err
-			}
-			i -= size
-			i = encodeVarint(dAtA, i, uint64(size))
-			i--
-			dAtA[i] = 0x22
+	if m.Process != nil {
+		size, err := m.Process.MarshalToSizedBufferVTStrict(dAtA[:i])
+		if err != nil {
+			return 0, err
 		}
-	}
-	if len(m.Tables) > 0 {
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x2a
+	}
+	if len(m.Env) > 0 {
+		for iNdEx := len(m.Env) - 1; iNdEx >= 0; iNdEx-- {
+			i -= len(m.Env[iNdEx])
+			copy(dAtA[i:], m.Env[iNdEx])
+			i = encodeVarint(dAtA, i, uint64(len(m.Env[iNdEx])))
+			i--
+			dAtA[i] = 0x22
+		}
+	}
+	if len(m.Options) > 0 {
+		i -= len(m.Options)
+		copy(dAtA[i:], m.Options)
+		i = encodeVarint(dAtA, i, uint64(len(m.Options)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.Plugin) > 0 {
+		i -= len(m.Plugin)
+		copy(dAtA[i:], m.Plugin)
+		i = encodeVarint(dAtA, i, uint64(len(m.Plugin)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Out) > 0 {
+		i -= len(m.Out)
+		copy(dAtA[i:], m.Out)
+		i = encodeVarint(dAtA, i, uint64(len(m.Out)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Catalog) MarshalVTStrict() (dAtA []byte, err error) {
+	if m == nil {
+		return nil, nil
+	}
+	size := m.SizeVT()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Catalog) MarshalToVTStrict(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
+}
+
+func (m *Catalog) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
+	if m == nil {
+		return 0, nil
+	}
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.unknownFields != nil {
+		i -= len(m.unknownFields)
+		copy(dAtA[i:], m.unknownFields)
+	}
+	if len(m.Schemas) > 0 {
+		for iNdEx := len(m.Schemas) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.Schemas[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0x22
+		}
+	}
+	if len(m.Name) > 0 {
+		i -= len(m.Name)
+		copy(dAtA[i:], m.Name)
+		i = encodeVarint(dAtA, i, uint64(len(m.Name)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.DefaultSchema) > 0 {
+		i -= len(m.DefaultSchema)
+		copy(dAtA[i:], m.DefaultSchema)
+		i = encodeVarint(dAtA, i, uint64(len(m.DefaultSchema)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Comment) > 0 {
+		i -= len(m.Comment)
+		copy(dAtA[i:], m.Comment)
+		i = encodeVarint(dAtA, i, uint64(len(m.Comment)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Schema) MarshalVTStrict() (dAtA []byte, err error) {
+	if m == nil {
+		return nil, nil
+	}
+	size := m.SizeVT()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Schema) MarshalToVTStrict(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
+}
+
+func (m *Schema) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
+	if m == nil {
+		return 0, nil
+	}
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.unknownFields != nil {
+		i -= len(m.unknownFields)
+		copy(dAtA[i:], m.unknownFields)
+	}
+	if len(m.CompositeTypes) > 0 {
+		for iNdEx := len(m.CompositeTypes) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.CompositeTypes[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0x2a
+		}
+	}
+	if len(m.Enums) > 0 {
+		for iNdEx := len(m.Enums) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.Enums[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0x22
+		}
+	}
+	if len(m.Tables) > 0 {
 		for iNdEx := len(m.Tables) - 1; iNdEx >= 0; iNdEx-- {
 			size, err := m.Tables[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
 			if err != nil {
@@ -3700,6 +4032,38 @@ func (m *Settings) SizeVT() (n int) {
 	return n
 }
 
+func (m *Codegen_Process) SizeVT() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Cmd)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	n += len(m.unknownFields)
+	return n
+}
+
+func (m *Codegen_WASM) SizeVT() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Url)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	l = len(m.Sha256)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	n += len(m.unknownFields)
+	return n
+}
+
 func (m *Codegen) SizeVT() (n int) {
 	if m == nil {
 		return 0
@@ -3718,6 +4082,20 @@ func (m *Codegen) SizeVT() (n int) {
 	if l > 0 {
 		n += 1 + l + sov(uint64(l))
 	}
+	if len(m.Env) > 0 {
+		for _, s := range m.Env {
+			l = len(s)
+			n += 1 + l + sov(uint64(l))
+		}
+	}
+	if m.Process != nil {
+		l = m.Process.SizeVT()
+		n += 1 + l + sov(uint64(l))
+	}
+	if m.Wasm != nil {
+		l = m.Wasm.SizeVT()
+		n += 1 + l + sov(uint64(l))
+	}
 	n += len(m.unknownFields)
 	return n
 }
@@ -5137,6 +5515,204 @@ func (m *Settings) UnmarshalVT(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *Codegen_Process) UnmarshalVT(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflow
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Codegen_Process: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Codegen_Process: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Cmd", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLength
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLength
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Cmd = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skip(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLength
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *Codegen_WASM) UnmarshalVT(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflow
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Codegen_WASM: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Codegen_WASM: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Url", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLength
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLength
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Url = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Sha256", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLength
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLength
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Sha256 = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skip(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLength
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *Codegen) UnmarshalVT(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -5264,6 +5840,110 @@ func (m *Codegen) UnmarshalVT(dAtA []byte) error {
 				m.Options = []byte{}
 			}
 			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Env", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLength
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLength
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Env = append(m.Env, string(dAtA[iNdEx:postIndex]))
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Process", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLength
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLength
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Process == nil {
+				m.Process = &Codegen_Process{}
+			}
+			if err := m.Process.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Wasm", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLength
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLength
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Wasm == nil {
+				m.Wasm = &Codegen_WASM{}
+			}
+			if err := m.Wasm.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skip(dAtA[iNdEx:])
diff --git a/internal/source/code.go b/internal/source/code.go
index f34e3e368..8b88a2413 100644
--- a/internal/source/code.go
+++ b/internal/source/code.go
@@ -15,6 +15,12 @@ type Edit struct {
 	OldFunc  func(string) int
 }
 
+type CommentSyntax struct {
+	Dash      bool
+	Hash      bool
+	SlashStar bool
+}
+
 func LineNumber(source string, head int) (int, int) {
 	// Calculate the true line and column number for a query, ignoring spaces
 	var comment bool
@@ -101,6 +107,9 @@ func StripComments(sql string) (string, []string, error) {
 		if strings.HasPrefix(t, "/* name:") && strings.HasSuffix(t, "*/") {
 			continue
 		}
+		if strings.HasPrefix(t, "# name:") {
+			continue
+		}
 		if strings.HasPrefix(t, "--") {
 			comments = append(comments, strings.TrimPrefix(t, "--"))
 			continue
@@ -111,7 +120,46 @@ func StripComments(sql string) (string, []string, error) {
 			comments = append(comments, t)
 			continue
 		}
+		if strings.HasPrefix(t, "#") {
+			comments = append(comments, strings.TrimPrefix(t, "#"))
+			continue
+		}
 		lines = append(lines, t)
 	}
 	return strings.Join(lines, "\n"), comments, s.Err()
 }
+
+func CleanedComments(rawSQL string, cs CommentSyntax) ([]string, error) {
+	s := bufio.NewScanner(strings.NewReader(strings.TrimSpace(rawSQL)))
+	var comments []string
+	for s.Scan() {
+		line := s.Text()
+		var prefix string
+		if strings.HasPrefix(line, "--") {
+			if !cs.Dash {
+				continue
+			}
+			prefix = "--"
+		}
+		if strings.HasPrefix(line, "/*") {
+			if !cs.SlashStar {
+				continue
+			}
+			prefix = "/*"
+		}
+		if strings.HasPrefix(line, "#") {
+			if !cs.Hash {
+				continue
+			}
+			prefix = "#"
+		}
+		if prefix == "" {
+			continue
+		}
+
+		rest := line[len(prefix):]
+		rest = strings.TrimSuffix(rest, "*/")
+		comments = append(comments, rest)
+	}
+	return comments, s.Err()
+}
diff --git a/internal/sql/catalog/table.go b/internal/sql/catalog/table.go
index 5598da4df..bfa2da027 100644
--- a/internal/sql/catalog/table.go
+++ b/internal/sql/catalog/table.go
@@ -41,7 +41,7 @@ func (table *Table) isExistColumn(cmd *ast.AlterTableCmd) (int, error) {
 	return -1, nil
 }
 
-func (table *Table) addColumn(cmd *ast.AlterTableCmd) error {
+func (c *Catalog) addColumn(table *Table, cmd *ast.AlterTableCmd) error {
 	for _, c := range table.Columns {
 		if c.Name == cmd.Def.Colname {
 			if !cmd.MissingOk {
@@ -50,16 +50,11 @@ func (table *Table) addColumn(cmd *ast.AlterTableCmd) error {
 			return nil
 		}
 	}
-
-	table.Columns = append(table.Columns, &Column{
-		Name:       cmd.Def.Colname,
-		Type:       *cmd.Def.TypeName,
-		IsNotNull:  cmd.Def.IsNotNull,
-		IsUnsigned: cmd.Def.IsUnsigned,
-		IsArray:    cmd.Def.IsArray,
-		ArrayDims:  cmd.Def.ArrayDims,
-		Length:     cmd.Def.Length,
-	})
+	tc, err := c.defineColumn(table.Rel, cmd.Def)
+	if err != nil {
+		return err
+	}
+	table.Columns = append(table.Columns, tc)
 	return nil
 }
 
@@ -76,14 +71,26 @@ func (table *Table) alterColumnType(cmd *ast.AlterTableCmd) error {
 	return nil
 }
 
-func (table *Table) dropColumn(cmd *ast.AlterTableCmd) error {
+func (c *Catalog) dropColumn(table *Table, cmd *ast.AlterTableCmd) error {
 	index, err := table.isExistColumn(cmd)
 	if err != nil {
 		return err
 	}
-	if index >= 0 {
-		table.Columns = append(table.Columns[:index], table.Columns[index+1:]...)
+	if index < 0 {
+		return nil
+	}
+	col := table.Columns[index]
+	if col.linkedType {
+		drop := &ast.DropTypeStmt{
+			Types: []*ast.TypeName{
+				&col.Type,
+			},
+		}
+		if err := c.dropType(drop); err != nil {
+			return err
+		}
 	}
+	table.Columns = append(table.Columns[:index], table.Columns[index+1:]...)
 	return nil
 }
 
@@ -121,6 +128,8 @@ type Column struct {
 	ArrayDims  int
 	Comment    string
 	Length     *int
+
+	linkedType bool
 }
 
 // An interface is used to resolve a circular import between the catalog and compiler packages.
@@ -187,7 +196,7 @@ func (c *Catalog) alterTable(stmt *ast.AlterTableStmt) error {
 		case *ast.AlterTableCmd:
 			switch cmd.Subtype {
 			case ast.AT_AddColumn:
-				if err := table.addColumn(cmd); err != nil {
+				if err := c.addColumn(table, cmd); err != nil {
 					return err
 				}
 			case ast.AT_AlterColumnType:
@@ -195,7 +204,7 @@ func (c *Catalog) alterTable(stmt *ast.AlterTableStmt) error {
 					return err
 				}
 			case ast.AT_DropColumn:
-				if err := table.dropColumn(cmd); err != nil {
+				if err := c.dropColumn(table, cmd); err != nil {
 					return err
 				}
 			case ast.AT_DropNotNull:
@@ -304,26 +313,9 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
 				}
 				continue
 			}
-
-			tc := &Column{
-				Name:       col.Colname,
-				Type:       *col.TypeName,
-				IsNotNull:  col.IsNotNull,
-				IsUnsigned: col.IsUnsigned,
-				IsArray:    col.IsArray,
-				ArrayDims:  col.ArrayDims,
-				Comment:    col.Comment,
-				Length:     col.Length,
-			}
-			if col.Vals != nil {
-				typeName := ast.TypeName{
-					Name: fmt.Sprintf("%s_%s", stmt.Name.Name, col.Colname),
-				}
-				s := &ast.CreateEnumStmt{TypeName: &typeName, Vals: col.Vals}
-				if err := c.createEnum(s); err != nil {
-					return err
-				}
-				tc.Type = typeName
+			tc, err := c.defineColumn(stmt.Name, col)
+			if err != nil {
+				return err
 			}
 			tbl.Columns = append(tbl.Columns, tc)
 		}
@@ -340,6 +332,31 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
 	return nil
 }
 
+func (c *Catalog) defineColumn(table *ast.TableName, col *ast.ColumnDef) (*Column, error) {
+	tc := &Column{
+		Name:       col.Colname,
+		Type:       *col.TypeName,
+		IsNotNull:  col.IsNotNull,
+		IsUnsigned: col.IsUnsigned,
+		IsArray:    col.IsArray,
+		ArrayDims:  col.ArrayDims,
+		Comment:    col.Comment,
+		Length:     col.Length,
+	}
+	if col.Vals != nil {
+		typeName := ast.TypeName{
+			Name: fmt.Sprintf("%s_%s", table.Name, col.Colname),
+		}
+		s := &ast.CreateEnumStmt{TypeName: &typeName, Vals: col.Vals}
+		if err := c.createEnum(s); err != nil {
+			return nil, err
+		}
+		tc.Type = typeName
+		tc.linkedType = true
+	}
+	return tc, nil
+}
+
 func (c *Catalog) dropTable(stmt *ast.DropTableStmt) error {
 	for _, name := range stmt.Tables {
 		ns := name.Schema
@@ -353,13 +370,24 @@ func (c *Catalog) dropTable(stmt *ast.DropTableStmt) error {
 			return err
 		}
 
-		_, idx, err := schema.getTable(name)
+		tbl, idx, err := schema.getTable(name)
 		if errors.Is(err, sqlerr.NotFound) && stmt.IfExists {
 			continue
 		} else if err != nil {
 			return err
 		}
 
+		drop := &ast.DropTypeStmt{}
+		for _, col := range tbl.Columns {
+			if !col.linkedType {
+				continue
+			}
+			drop.Types = append(drop.Types, &col.Type)
+		}
+		if err := c.dropType(drop); err != nil {
+			return err
+		}
+
 		schema.Tables = append(schema.Tables[:idx], schema.Tables[idx+1:]...)
 	}
 	return nil
@@ -383,6 +411,18 @@ func (c *Catalog) renameColumn(stmt *ast.RenameColumnStmt) error {
 		return sqlerr.ColumnNotFound(tbl.Rel.Name, stmt.Col.Name)
 	}
 	tbl.Columns[idx].Name = *stmt.NewName
+
+	if tbl.Columns[idx].linkedType {
+		name := fmt.Sprintf("%s_%s", tbl.Rel.Name, *stmt.NewName)
+		rename := &ast.RenameTypeStmt{
+			Type:    &tbl.Columns[idx].Type,
+			NewName: &name,
+		}
+		if err := c.renameType(rename); err != nil {
+			return err
+		}
+	}
+
 	return nil
 }
 
@@ -397,6 +437,20 @@ func (c *Catalog) renameTable(stmt *ast.RenameTableStmt) error {
 	if stmt.NewName != nil {
 		tbl.Rel.Name = *stmt.NewName
 	}
+
+	for idx := range tbl.Columns {
+		if tbl.Columns[idx].linkedType {
+			name := fmt.Sprintf("%s_%s", *stmt.NewName, tbl.Columns[idx].Name)
+			rename := &ast.RenameTypeStmt{
+				Type:    &tbl.Columns[idx].Type,
+				NewName: &name,
+			}
+			if err := c.renameType(rename); err != nil {
+				return err
+			}
+		}
+	}
+
 	return nil
 }
 
diff --git a/internal/sql/catalog/types.go b/internal/sql/catalog/types.go
index e92a3a219..464472bcf 100644
--- a/internal/sql/catalog/types.go
+++ b/internal/sql/catalog/types.go
@@ -3,6 +3,7 @@ package catalog
 import (
 	"errors"
 	"fmt"
+
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 	"github.com/sqlc-dev/sqlc/internal/sql/sqlerr"
 )
diff --git a/protos/plugin/codegen.proto b/protos/plugin/codegen.proto
index eb18aa6a9..380ecf277 100644
--- a/protos/plugin/codegen.proto
+++ b/protos/plugin/codegen.proto
@@ -60,9 +60,19 @@ message Settings {
 }
 
 message Codegen {
+  message Process {
+    string cmd = 1;
+  }
+  message WASM {
+    string url = 1;
+    string sha256 = 2;
+  }
   string out = 1 [json_name = "out"];
   string plugin = 2 [json_name = "plugin"];
   bytes options = 3 [json_name = "options"];
+  repeated string env = 4 [json_name = "env"];
+  Process process = 5 [json_name = "process"];
+  WASM wasm = 6 [json_name = "wasm"];
 }
 
 message Catalog {


Test patch:
diff --git a/examples/kotlin/src/test/kotlin/com/example/ondeck/mysql/QueriesImplTest.kt b/examples/kotlin/src/test/kotlin/com/example/ondeck/mysql/QueriesImplTest.kt
index e946157ba..27fac2353 100644
--- a/examples/kotlin/src/test/kotlin/com/example/ondeck/mysql/QueriesImplTest.kt
+++ b/examples/kotlin/src/test/kotlin/com/example/ondeck/mysql/QueriesImplTest.kt
@@ -25,8 +25,8 @@ class QueriesImplTest {
             name = "The Fillmore",
             city = city.slug,
             spotifyPlaylist = "spotify=uri",
-            status = VenuesStatus.OPEN,
-            statuses = listOf(VenuesStatus.OPEN, VenuesStatus.CLOSED).joinToString(","),
+            status = VenueStatus.OPEN,
+            statuses = listOf(VenueStatus.OPEN, VenueStatus.CLOSED).joinToString(","),
             tags = listOf("rock", "punk").joinToString(",")
         )
         val venue = q.getVenue(
diff --git a/examples/ondeck/mysql/db_test.go b/examples/ondeck/mysql/db_test.go
index b4b343f9d..a6ddecc18 100644
--- a/examples/ondeck/mysql/db_test.go
+++ b/examples/ondeck/mysql/db_test.go
@@ -45,8 +45,8 @@ func runOnDeckQueries(t *testing.T, q *Queries) {
 		Name:            "The Fillmore",
 		City:            city.Slug,
 		SpotifyPlaylist: "spotify:uri",
-		Status:          VenuesStatusOpen,
-		Statuses:        join(string(VenuesStatusOpen), string(VenuesStatusClosed)),
+		Status:          VenueStatusOpen,
+		Statuses:        join(string(VenueStatusOpen), string(VenueStatusClosed)),
 		Tags:            join("rock", "punk"),
 	})
 	if err != nil {
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index d643eeb9f..240a4b4e1 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -79,13 +79,12 @@ func FuzzConfig(f *testing.F) {
 func TestInvalidConfig(t *testing.T) {
 	err := Validate(&Config{
 		SQL: []SQL{{
-			Gen: SQLGen{
-				Go: &SQLGo{
-					EmitMethodsWithDBArgument: true,
-					EmitPreparedQueries:       true,
-				},
+			Database: &Database{
+				URI:     "",
+				Managed: false,
 			},
-		}}})
+		}},
+	})
 	if err == nil {
 		t.Errorf("expected err; got nil")
 	}
diff --git a/internal/endtoend/testdata/case_value_param/issue.md b/internal/endtoend/testdata/case_value_param/issue.md
new file mode 100644
index 000000000..c8ac2fa39
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/issue.md
@@ -0,0 +1,1 @@
+https://github.com/sqlc-dev/sqlc/issues/2847
diff --git a/internal/endtoend/testdata/case_value_param/mysql/go/db.go b/internal/endtoend/testdata/case_value_param/mysql/go/db.go
new file mode 100644
index 000000000..a457fb76b
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/mysql/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/case_value_param/mysql/go/models.go b/internal/endtoend/testdata/case_value_param/mysql/go/models.go
new file mode 100644
index 000000000..03c6b31ce
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/mysql/go/models.go
@@ -0,0 +1,14 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import (
+	"database/sql"
+)
+
+type Testing struct {
+	ID    int32
+	Value sql.NullString
+}
diff --git a/internal/endtoend/testdata/case_value_param/mysql/go/query.sql.go b/internal/endtoend/testdata/case_value_param/mysql/go/query.sql.go
new file mode 100644
index 000000000..97eb3800f
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/mysql/go/query.sql.go
@@ -0,0 +1,21 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+	"database/sql"
+)
+
+const update = `-- name: Update :exec
+UPDATE testing
+SET value = CASE ? WHEN true THEN 'Hello' WHEN false THEN 'Goodbye' ELSE value END
+`
+
+func (q *Queries) Update(ctx context.Context, value sql.NullString) error {
+	_, err := q.db.ExecContext(ctx, update, value)
+	return err
+}
diff --git a/internal/endtoend/testdata/case_value_param/mysql/query.sql b/internal/endtoend/testdata/case_value_param/mysql/query.sql
new file mode 100644
index 000000000..2c4e1f988
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/mysql/query.sql
@@ -0,0 +1,3 @@
+-- name: Update :exec
+UPDATE testing
+SET value = CASE ? WHEN true THEN 'Hello' WHEN false THEN 'Goodbye' ELSE value END;
diff --git a/internal/endtoend/testdata/case_value_param/mysql/schema.sql b/internal/endtoend/testdata/case_value_param/mysql/schema.sql
new file mode 100644
index 000000000..556ca0b53
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/mysql/schema.sql
@@ -0,0 +1,4 @@
+CREATE TABLE testing (
+  id    int PRIMARY KEY,
+  value text
+);
diff --git a/internal/endtoend/testdata/case_value_param/mysql/sqlc.yaml b/internal/endtoend/testdata/case_value_param/mysql/sqlc.yaml
new file mode 100644
index 000000000..b843ef55e
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/mysql/sqlc.yaml
@@ -0,0 +1,9 @@
+version: "2"
+sql:
+  - engine: "mysql"
+    schema: "schema.sql"
+    queries: "query.sql"
+    gen:
+      go:
+        package: "querytest"
+        out: "go"
diff --git a/internal/endtoend/testdata/case_value_param/postgresql/go/db.go b/internal/endtoend/testdata/case_value_param/postgresql/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/postgresql/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/case_value_param/postgresql/go/models.go b/internal/endtoend/testdata/case_value_param/postgresql/go/models.go
new file mode 100644
index 000000000..a613e3544
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/postgresql/go/models.go
@@ -0,0 +1,14 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import (
+	"github.com/jackc/pgx/v5/pgtype"
+)
+
+type Testing struct {
+	ID    int32
+	Value pgtype.Text
+}
diff --git a/internal/endtoend/testdata/case_value_param/postgresql/go/query.sql.go b/internal/endtoend/testdata/case_value_param/postgresql/go/query.sql.go
new file mode 100644
index 000000000..841cfb52b
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/postgresql/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"
+
+	"github.com/jackc/pgx/v5/pgtype"
+)
+
+const update = `-- name: Update :exec
+UPDATE testing
+SET value = CASE $1 WHEN true THEN 'Hello' WHEN false THEN 'Goodbye' ELSE value END
+`
+
+func (q *Queries) Update(ctx context.Context, value pgtype.Text) error {
+	_, err := q.db.Exec(ctx, update, value)
+	return err
+}
diff --git a/internal/endtoend/testdata/case_value_param/postgresql/query.sql b/internal/endtoend/testdata/case_value_param/postgresql/query.sql
new file mode 100644
index 000000000..106653b43
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/postgresql/query.sql
@@ -0,0 +1,3 @@
+-- name: Update :exec
+UPDATE testing
+SET value = CASE $1 WHEN true THEN 'Hello' WHEN false THEN 'Goodbye' ELSE value END;
diff --git a/internal/endtoend/testdata/case_value_param/postgresql/schema.sql b/internal/endtoend/testdata/case_value_param/postgresql/schema.sql
new file mode 100644
index 000000000..556ca0b53
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/postgresql/schema.sql
@@ -0,0 +1,4 @@
+CREATE TABLE testing (
+  id    int PRIMARY KEY,
+  value text
+);
diff --git a/internal/endtoend/testdata/case_value_param/postgresql/sqlc.yaml b/internal/endtoend/testdata/case_value_param/postgresql/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/case_value_param/postgresql/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/codegen_json/gen/codegen.json b/internal/endtoend/testdata/codegen_json/gen/codegen.json
index 0710f6427..5dc5b15d6 100644
--- a/internal/endtoend/testdata/codegen_json/gen/codegen.json
+++ b/internal/endtoend/testdata/codegen_json/gen/codegen.json
@@ -13,7 +13,10 @@
     "codegen": {
       "out": "",
       "plugin": "",
-      "options": ""
+      "options": "",
+      "env": [],
+      "process": null,
+      "wasm": null
     }
   },
   "catalog": {
diff --git a/internal/endtoend/testdata/comment_syntax/mysql/go/query.sql.go b/internal/endtoend/testdata/comment_syntax/mysql/go/query.sql.go
index 7f4b91615..29909a8da 100644
--- a/internal/endtoend/testdata/comment_syntax/mysql/go/query.sql.go
+++ b/internal/endtoend/testdata/comment_syntax/mysql/go/query.sql.go
@@ -22,7 +22,6 @@ func (q *Queries) DoubleDash(ctx context.Context) (sql.NullString, error) {
 }
 
 const hash = `-- name: Hash :one
-# name: Hash :one
 SELECT bar FROM foo LIMIT 1
 `
 
diff --git a/internal/endtoend/testdata/cte_update/issue.md b/internal/endtoend/testdata/cte_update/issue.md
new file mode 100644
index 000000000..5f1a5921e
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/issue.md
@@ -0,0 +1,1 @@
+https://github.com/sqlc-dev/sqlc/issues/1515
diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/exec.json b/internal/endtoend/testdata/cte_update/postgresql/pgx/exec.json
new file mode 100644
index 000000000..ee1b7ecd9
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/postgresql/pgx/exec.json
@@ -0,0 +1,3 @@
+{
+  "contexts": ["managed-db"]
+}
diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/go/db.go b/internal/endtoend/testdata/cte_update/postgresql/pgx/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/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_update/postgresql/pgx/go/models.go b/internal/endtoend/testdata/cte_update/postgresql/pgx/go/models.go
new file mode 100644
index 000000000..9e014185e
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/postgresql/pgx/go/models.go
@@ -0,0 +1,18 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import ()
+
+type Attribute struct {
+	ID   int64
+	Name string
+}
+
+type AttributeValue struct {
+	ID        int64
+	Val       string
+	Attribute int64
+}
diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/cte_update/postgresql/pgx/go/query.sql.go
new file mode 100644
index 000000000..4bcad215e
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/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 updateAttribute = `-- name: UpdateAttribute :one
+with updated_attribute as (UPDATE attribute_value
+    SET
+        val = CASE WHEN $1::bool THEN $2 ELSE val END
+    WHERE attribute_value.id = $3
+    RETURNING id,attribute,val)
+select updated_attribute.id, val, name
+from updated_attribute
+         left join attribute on updated_attribute.attribute = attribute.id
+`
+
+type UpdateAttributeParams struct {
+	FilterValue pgtype.Bool
+	Value       pgtype.Text
+	ID          pgtype.Int8
+}
+
+type UpdateAttributeRow struct {
+	ID   int64
+	Val  string
+	Name pgtype.Text
+}
+
+func (q *Queries) UpdateAttribute(ctx context.Context, arg UpdateAttributeParams) (UpdateAttributeRow, error) {
+	row := q.db.QueryRow(ctx, updateAttribute, arg.FilterValue, arg.Value, arg.ID)
+	var i UpdateAttributeRow
+	err := row.Scan(&i.ID, &i.Val, &i.Name)
+	return i, err
+}
diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/query.sql b/internal/endtoend/testdata/cte_update/postgresql/pgx/query.sql
new file mode 100644
index 000000000..6ba9aa4e7
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/postgresql/pgx/query.sql
@@ -0,0 +1,9 @@
+-- name: UpdateAttribute :one
+with updated_attribute as (UPDATE attribute_value
+    SET
+        val = CASE WHEN @filter_value::bool THEN @value ELSE val END
+    WHERE attribute_value.id = @id
+    RETURNING id,attribute,val)
+select updated_attribute.id, val, name
+from updated_attribute
+         left join attribute on updated_attribute.attribute = attribute.id;
diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/schema.sql b/internal/endtoend/testdata/cte_update/postgresql/pgx/schema.sql
new file mode 100644
index 000000000..6273c9a7e
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/postgresql/pgx/schema.sql
@@ -0,0 +1,12 @@
+create table attribute_value
+(
+    id              bigserial not null,
+    val             text      not null,
+    attribute       bigint    not null
+);
+
+create table attribute
+(
+    id              bigserial      not null,
+    name            text           not null
+);
diff --git a/internal/endtoend/testdata/cte_update/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/cte_update/postgresql/pgx/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/cte_update/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/ddl_alter_materialized_views_set_schema/issue.md b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/issue.md
new file mode 100644
index 000000000..c51bd7f6d
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/issue.md
@@ -0,0 +1,1 @@
+https://github.com/sqlc-dev/sqlc/issues/1519
diff --git a/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/db.go b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/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/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/models.go b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/models.go
new file mode 100644
index 000000000..5a759a440
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/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 ComputedTablesSomething struct {
+	ID        pgtype.Int4
+	EventType string
+	CreatedAt pgtype.Timestamptz
+}
+
+type Event struct {
+	ID        pgtype.Int4
+	EventType string
+	CreatedAt pgtype.Timestamptz
+}
diff --git a/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/query.sql.go
new file mode 100644
index 000000000..3d0ab335c
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/go/query.sql.go
@@ -0,0 +1,36 @@
+// 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 someQuery = `-- name: SomeQuery :many
+select id from "computed_tables"."something"
+`
+
+func (q *Queries) SomeQuery(ctx context.Context) ([]pgtype.Int4, error) {
+	rows, err := q.db.Query(ctx, someQuery)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []pgtype.Int4
+	for rows.Next() {
+		var id pgtype.Int4
+		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/ddl_alter_materialized_views_set_schema/postgresql/pgx/query.sql b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/query.sql
new file mode 100644
index 000000000..24dafea7e
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/query.sql
@@ -0,0 +1,2 @@
+-- name: SomeQuery :many
+select id from "computed_tables"."something";
diff --git a/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/schema.sql b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/schema.sql
new file mode 100644
index 000000000..2b788e097
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/schema.sql
@@ -0,0 +1,13 @@
+create table events (
+  id int,
+  event_type text not null,
+  created_at timestamptz
+);
+
+CREATE MATERIALIZED VIEW something AS
+select * from events
+where event_type = 'sale'
+order by created_at desc;
+
+create schema computed_tables;
+alter materialized view something set schema computed_tables;
diff --git a/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/postgresql/pgx/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_materialized_views_set_schema/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/enum_column/issue.md b/internal/endtoend/testdata/enum_column/issue.md
new file mode 100644
index 000000000..e618d6c24
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/issue.md
@@ -0,0 +1,3 @@
+https://github.com/sqlc-dev/sqlc/issues/1503
+https://github.com/sqlc-dev/sqlc/issues/2475
+
diff --git a/internal/endtoend/testdata/enum_column/mysql/go/db.go b/internal/endtoend/testdata/enum_column/mysql/go/db.go
new file mode 100644
index 000000000..a457fb76b
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/mysql/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/enum_column/mysql/go/models.go b/internal/endtoend/testdata/enum_column/mysql/go/models.go
new file mode 100644
index 000000000..84d959387
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/mysql/go/models.go
@@ -0,0 +1,271 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import (
+	"database/sql/driver"
+	"fmt"
+)
+
+type AuthorsAddItem string
+
+const (
+	AuthorsAddItemOk    AuthorsAddItem = "ok"
+	AuthorsAddItemAdded AuthorsAddItem = "added"
+)
+
+func (e *AuthorsAddItem) Scan(src interface{}) error {
+	switch s := src.(type) {
+	case []byte:
+		*e = AuthorsAddItem(s)
+	case string:
+		*e = AuthorsAddItem(s)
+	default:
+		return fmt.Errorf("unsupported scan type for AuthorsAddItem: %T", src)
+	}
+	return nil
+}
+
+type NullAuthorsAddItem struct {
+	AuthorsAddItem AuthorsAddItem
+	Valid          bool // Valid is true if AuthorsAddItem is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullAuthorsAddItem) Scan(value interface{}) error {
+	if value == nil {
+		ns.AuthorsAddItem, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return ns.AuthorsAddItem.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullAuthorsAddItem) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return string(ns.AuthorsAddItem), nil
+}
+
+type AuthorsAdded string
+
+const (
+	AuthorsAddedOk AuthorsAdded = "ok"
+)
+
+func (e *AuthorsAdded) Scan(src interface{}) error {
+	switch s := src.(type) {
+	case []byte:
+		*e = AuthorsAdded(s)
+	case string:
+		*e = AuthorsAdded(s)
+	default:
+		return fmt.Errorf("unsupported scan type for AuthorsAdded: %T", src)
+	}
+	return nil
+}
+
+type NullAuthorsAdded struct {
+	AuthorsAdded AuthorsAdded
+	Valid        bool // Valid is true if AuthorsAdded is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullAuthorsAdded) Scan(value interface{}) error {
+	if value == nil {
+		ns.AuthorsAdded, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return ns.AuthorsAdded.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullAuthorsAdded) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return string(ns.AuthorsAdded), nil
+}
+
+type AuthorsBar string
+
+const (
+	AuthorsBarOk AuthorsBar = "ok"
+)
+
+func (e *AuthorsBar) Scan(src interface{}) error {
+	switch s := src.(type) {
+	case []byte:
+		*e = AuthorsBar(s)
+	case string:
+		*e = AuthorsBar(s)
+	default:
+		return fmt.Errorf("unsupported scan type for AuthorsBar: %T", src)
+	}
+	return nil
+}
+
+type NullAuthorsBar struct {
+	AuthorsBar AuthorsBar
+	Valid      bool // Valid is true if AuthorsBar is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullAuthorsBar) Scan(value interface{}) error {
+	if value == nil {
+		ns.AuthorsBar, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return ns.AuthorsBar.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullAuthorsBar) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return string(ns.AuthorsBar), nil
+}
+
+type AuthorsFoo string
+
+const (
+	AuthorsFooOk AuthorsFoo = "ok"
+)
+
+func (e *AuthorsFoo) Scan(src interface{}) error {
+	switch s := src.(type) {
+	case []byte:
+		*e = AuthorsFoo(s)
+	case string:
+		*e = AuthorsFoo(s)
+	default:
+		return fmt.Errorf("unsupported scan type for AuthorsFoo: %T", src)
+	}
+	return nil
+}
+
+type NullAuthorsFoo struct {
+	AuthorsFoo AuthorsFoo
+	Valid      bool // Valid is true if AuthorsFoo is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullAuthorsFoo) Scan(value interface{}) error {
+	if value == nil {
+		ns.AuthorsFoo, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return ns.AuthorsFoo.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullAuthorsFoo) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return string(ns.AuthorsFoo), nil
+}
+
+type AuthorsRemoveItem string
+
+const (
+	AuthorsRemoveItemOk AuthorsRemoveItem = "ok"
+)
+
+func (e *AuthorsRemoveItem) Scan(src interface{}) error {
+	switch s := src.(type) {
+	case []byte:
+		*e = AuthorsRemoveItem(s)
+	case string:
+		*e = AuthorsRemoveItem(s)
+	default:
+		return fmt.Errorf("unsupported scan type for AuthorsRemoveItem: %T", src)
+	}
+	return nil
+}
+
+type NullAuthorsRemoveItem struct {
+	AuthorsRemoveItem AuthorsRemoveItem
+	Valid             bool // Valid is true if AuthorsRemoveItem is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullAuthorsRemoveItem) Scan(value interface{}) error {
+	if value == nil {
+		ns.AuthorsRemoveItem, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return ns.AuthorsRemoveItem.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullAuthorsRemoveItem) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return string(ns.AuthorsRemoveItem), nil
+}
+
+type BooksFoo string
+
+const (
+	BooksFooOk BooksFoo = "ok"
+)
+
+func (e *BooksFoo) Scan(src interface{}) error {
+	switch s := src.(type) {
+	case []byte:
+		*e = BooksFoo(s)
+	case string:
+		*e = BooksFoo(s)
+	default:
+		return fmt.Errorf("unsupported scan type for BooksFoo: %T", src)
+	}
+	return nil
+}
+
+type NullBooksFoo struct {
+	BooksFoo BooksFoo
+	Valid    bool // Valid is true if BooksFoo is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (ns *NullBooksFoo) Scan(value interface{}) error {
+	if value == nil {
+		ns.BooksFoo, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return ns.BooksFoo.Scan(value)
+}
+
+// Value implements the driver Valuer interface.
+func (ns NullBooksFoo) Value() (driver.Value, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return string(ns.BooksFoo), nil
+}
+
+type Author struct {
+	ID         int64
+	Foo        AuthorsFoo
+	Bar        AuthorsBar
+	Added      AuthorsAdded
+	AddItem    AuthorsAddItem
+	RemoveItem AuthorsRemoveItem
+}
+
+type Book struct {
+	ID  int64
+	Foo BooksFoo
+}
diff --git a/internal/endtoend/testdata/enum_column/mysql/go/query.sql.go b/internal/endtoend/testdata/enum_column/mysql/go/query.sql.go
new file mode 100644
index 000000000..fc2414463
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/mysql/go/query.sql.go
@@ -0,0 +1,71 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const listAuthors = `-- name: ListAuthors :many
+SELECT id, foo, bar, added, add_item, remove_item 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.Foo,
+			&i.Bar,
+			&i.Added,
+			&i.AddItem,
+			&i.RemoveItem,
+		); 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 listBooks = `-- name: ListBooks :many
+SELECT id, foo FROM books
+`
+
+func (q *Queries) ListBooks(ctx context.Context) ([]Book, error) {
+	rows, err := q.db.QueryContext(ctx, listBooks)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []Book
+	for rows.Next() {
+		var i Book
+		if err := rows.Scan(&i.ID, &i.Foo); 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/enum_column/mysql/query.sql b/internal/endtoend/testdata/enum_column/mysql/query.sql
new file mode 100644
index 000000000..893743b53
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/mysql/query.sql
@@ -0,0 +1,5 @@
+/* name: ListAuthors :many */
+SELECT * FROM authors;
+
+/* name: ListBooks :many */
+SELECT * FROM books;
diff --git a/internal/endtoend/testdata/enum_column/mysql/schema.sql b/internal/endtoend/testdata/enum_column/mysql/schema.sql
new file mode 100644
index 000000000..82771c195
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/mysql/schema.sql
@@ -0,0 +1,39 @@
+CREATE TABLE authors (
+  id          BIGINT PRIMARY KEY,
+  foo         ENUM("ok") DEFAULT "ok" NOT NULL,
+  renamed     ENUM("ok") DEFAULT "ok" NOT NULL,
+  removed     ENUM("ok") DEFAULT "ok" NOT NULL,
+  add_item    ENUM("ok") DEFAULT "ok" NOT NULL,
+  remove_item ENUM("ok", "removed") DEFAULT "ok" NOT NULL
+);
+
+CREATE TABLE renamed (
+  id       BIGINT PRIMARY KEY,
+  foo      ENUM("ok") DEFAULT "ok" NOT NULL
+);
+
+CREATE TABLE removed (
+  id       BIGINT PRIMARY KEY,
+  foo      ENUM("ok") DEFAULT "ok" NOT NULL
+);
+
+/* Rename column */
+ALTER TABLE authors RENAME COLUMN renamed TO bar;
+
+/* Drop column */
+ALTER TABLE authors DROP COLUMN removed;
+
+/* Add column */
+ALTER TABLE authors ADD COLUMN added ENUM("ok") DEFAULT "ok" NOT NULL;
+
+/* Add enum values */
+ALTER TABLE authors MODIFY add_item ENUM("ok", "added") DEFAULT "ok" NOT NULL;
+
+/* Remove enum values */
+ALTER TABLE authors MODIFY remove_item ENUM("ok") DEFAULT "ok" NOT NULL;
+
+/* Drop table */
+DROP TABLE removed;
+
+/* Rename table */
+ALTER TABLE renamed RENAME TO books;
diff --git a/internal/endtoend/testdata/enum_column/mysql/sqlc.yaml b/internal/endtoend/testdata/enum_column/mysql/sqlc.yaml
new file mode 100644
index 000000000..b843ef55e
--- /dev/null
+++ b/internal/endtoend/testdata/enum_column/mysql/sqlc.yaml
@@ -0,0 +1,9 @@
+version: "2"
+sql:
+  - engine: "mysql"
+    schema: "schema.sql"
+    queries: "query.sql"
+    gen:
+      go:
+        package: "querytest"
+        out: "go"
diff --git a/internal/endtoend/testdata/func_return_table/issue.md b/internal/endtoend/testdata/func_return_table/issue.md
new file mode 100644
index 000000000..119a3cd98
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/issue.md
@@ -0,0 +1,1 @@
+https://github.com/sqlc-dev/sqlc/issues/1322
diff --git a/internal/endtoend/testdata/func_return_table/postgresql/pgx/exec.json b/internal/endtoend/testdata/func_return_table/postgresql/pgx/exec.json
new file mode 100644
index 000000000..ee1b7ecd9
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/postgresql/pgx/exec.json
@@ -0,0 +1,3 @@
+{
+  "contexts": ["managed-db"]
+}
diff --git a/internal/endtoend/testdata/func_return_table/postgresql/pgx/go/db.go b/internal/endtoend/testdata/func_return_table/postgresql/pgx/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/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/func_return_table/postgresql/pgx/go/models.go b/internal/endtoend/testdata/func_return_table/postgresql/pgx/go/models.go
new file mode 100644
index 000000000..2b46ef008
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/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 Account struct {
+	ID       int32
+	Username string
+	Password string
+}
diff --git a/internal/endtoend/testdata/func_return_table/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/func_return_table/postgresql/pgx/go/query.sql.go
new file mode 100644
index 000000000..04ee7b02f
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/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 foo = `-- name: Foo :one
+SELECT register_account FROM register_account('a', 'b')
+`
+
+func (q *Queries) Foo(ctx context.Context) (pgtype.Int4, error) {
+	row := q.db.QueryRow(ctx, foo)
+	var register_account pgtype.Int4
+	err := row.Scan(&register_account)
+	return register_account, err
+}
diff --git a/internal/endtoend/testdata/func_return_table/postgresql/pgx/query.sql b/internal/endtoend/testdata/func_return_table/postgresql/pgx/query.sql
new file mode 100644
index 000000000..8a3db0f6d
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/postgresql/pgx/query.sql
@@ -0,0 +1,2 @@
+-- name: Foo :one
+SELECT * FROM register_account('a', 'b');
diff --git a/internal/endtoend/testdata/func_return_table/postgresql/pgx/schema.sql b/internal/endtoend/testdata/func_return_table/postgresql/pgx/schema.sql
new file mode 100644
index 000000000..e9ebf5e42
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/postgresql/pgx/schema.sql
@@ -0,0 +1,27 @@
+CREATE TABLE accounts (
+  id         INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+  username   TEXT NOT NULL UNIQUE,
+  password   TEXT NOT NULL
+);
+
+-- this is a useless and horrifying function cause we don't hash
+-- the password, this is just to repro the bug in sqlc
+CREATE OR REPLACE FUNCTION register_account(
+    _username TEXT,
+    _password VARCHAR(70)
+)
+RETURNS TABLE (
+    account_id   INTEGER
+)
+AS $$
+BEGIN
+  INSERT INTO accounts (username, password)
+       VALUES (
+         _username,
+         _password
+       )
+    RETURNING id INTO account_id;
+
+  RETURN NEXT;
+END;
+$$ LANGUAGE plpgsql;
diff --git a/internal/endtoend/testdata/func_return_table/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/func_return_table/postgresql/pgx/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/func_return_table/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/invalid_queries_foo/pgx/v4/stderr.txt b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt
index 6b0840fc3..06ec54327 100644
--- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt
+++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt
@@ -1,5 +1,5 @@
 # package querytest
-query.sql:1:1: invalid query comment: -- name: ListFoos
+query.sql:1:1: missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: -- 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
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 6b0840fc3..06ec54327 100644
--- a/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt
+++ b/internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt
@@ -1,5 +1,5 @@
 # package querytest
-query.sql:1:1: invalid query comment: -- name: ListFoos
+query.sql:1:1: missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: -- 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
diff --git a/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt b/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt
index 6b0840fc3..06ec54327 100644
--- a/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt
+++ b/internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt
@@ -1,5 +1,5 @@
 # package querytest
-query.sql:1:1: invalid query comment: -- name: ListFoos
+query.sql:1:1: missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: -- 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
diff --git a/internal/endtoend/testdata/join_using/issue.md b/internal/endtoend/testdata/join_using/issue.md
new file mode 100644
index 000000000..29861d966
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/issue.md
@@ -0,0 +1,1 @@
+https://github.com/sqlc-dev/sqlc/issues/1425
diff --git a/internal/endtoend/testdata/join_using/postgresql/pgx/exec.json b/internal/endtoend/testdata/join_using/postgresql/pgx/exec.json
new file mode 100644
index 000000000..ee1b7ecd9
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/postgresql/pgx/exec.json
@@ -0,0 +1,3 @@
+{
+  "contexts": ["managed-db"]
+}
diff --git a/internal/endtoend/testdata/join_using/postgresql/pgx/go/db.go b/internal/endtoend/testdata/join_using/postgresql/pgx/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/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/join_using/postgresql/pgx/go/models.go b/internal/endtoend/testdata/join_using/postgresql/pgx/go/models.go
new file mode 100644
index 000000000..4e0fc50bf
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/postgresql/pgx/go/models.go
@@ -0,0 +1,15 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import ()
+
+type T1 struct {
+	Fk int32
+}
+
+type T2 struct {
+	Fk int32
+}
diff --git a/internal/endtoend/testdata/join_using/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/join_using/postgresql/pgx/go/query.sql.go
new file mode 100644
index 000000000..1d32bfe90
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/postgresql/pgx/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"
+
+	"github.com/jackc/pgx/v5/pgtype"
+)
+
+const selectJoinUsing = `-- name: SelectJoinUsing :many
+select t1.fk, sum(t2.fk) from t1 join t2 using (fk) group by fk
+`
+
+type SelectJoinUsingRow struct {
+	Fk  int32
+	Sum pgtype.Int8
+}
+
+func (q *Queries) SelectJoinUsing(ctx context.Context) ([]SelectJoinUsingRow, error) {
+	rows, err := q.db.Query(ctx, selectJoinUsing)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []SelectJoinUsingRow
+	for rows.Next() {
+		var i SelectJoinUsingRow
+		if err := rows.Scan(&i.Fk, &i.Sum); 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/join_using/postgresql/pgx/query.sql b/internal/endtoend/testdata/join_using/postgresql/pgx/query.sql
new file mode 100644
index 000000000..67a732e02
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/postgresql/pgx/query.sql
@@ -0,0 +1,2 @@
+-- name: SelectJoinUsing :many
+select t1.fk, sum(t2.fk) from t1 join t2 using (fk) group by fk;
diff --git a/internal/endtoend/testdata/join_using/postgresql/pgx/schema.sql b/internal/endtoend/testdata/join_using/postgresql/pgx/schema.sql
new file mode 100644
index 000000000..1e7b5a851
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/postgresql/pgx/schema.sql
@@ -0,0 +1,6 @@
+create table t1 (
+        fk integer not null unique
+);
+create table t2 (
+        fk integer not null references t1(fk)
+);
diff --git a/internal/endtoend/testdata/join_using/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/join_using/postgresql/pgx/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/join_using/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/params_go_keywords/issue.md b/internal/endtoend/testdata/params_go_keywords/issue.md
new file mode 100644
index 000000000..f87f5c14c
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/issue.md
@@ -0,0 +1,1 @@
+# TODO
\ No newline at end of file
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/go/db.go b/internal/endtoend/testdata/params_go_keywords/postgresql/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/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/params_go_keywords/postgresql/go/models.go b/internal/endtoend/testdata/params_go_keywords/postgresql/go/models.go
new file mode 100644
index 000000000..e857924a3
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/go/models.go
@@ -0,0 +1,37 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import (
+	"github.com/jackc/pgx/v5/pgtype"
+)
+
+type GoKeyword struct {
+	Break       pgtype.Text
+	Default     pgtype.Text
+	Func        pgtype.Text
+	Interface   pgtype.Text
+	Select      pgtype.Text
+	Case        pgtype.Text
+	Defer       pgtype.Text
+	Go          pgtype.Text
+	Map         pgtype.Text
+	Struct      pgtype.Text
+	Chan        pgtype.Text
+	Else        pgtype.Text
+	Goto        pgtype.Text
+	Package     pgtype.Text
+	Switch      pgtype.Text
+	Const       pgtype.Text
+	Fallthrough pgtype.Text
+	If          pgtype.Text
+	Range       pgtype.Text
+	Type        pgtype.Text
+	Continue    pgtype.Text
+	For         pgtype.Text
+	Import      pgtype.Text
+	Return      pgtype.Text
+	Var         pgtype.Text
+}
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go b/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go
new file mode 100644
index 000000000..430bc74a6
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/go/query.sql.go
@@ -0,0 +1,512 @@
+// 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 keywordBreak = `-- name: KeywordBreak :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordBreak(ctx context.Context, break_ string) error {
+	_, err := q.db.Exec(ctx, keywordBreak, break_)
+	return err
+}
+
+const keywordCase = `-- name: KeywordCase :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordCase(ctx context.Context, case_ string) error {
+	_, err := q.db.Exec(ctx, keywordCase, case_)
+	return err
+}
+
+const keywordChan = `-- name: KeywordChan :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordChan(ctx context.Context, chan_ string) error {
+	_, err := q.db.Exec(ctx, keywordChan, chan_)
+	return err
+}
+
+const keywordConst = `-- name: KeywordConst :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordConst(ctx context.Context, const_ string) error {
+	_, err := q.db.Exec(ctx, keywordConst, const_)
+	return err
+}
+
+const keywordContinue = `-- name: KeywordContinue :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordContinue(ctx context.Context, continue_ string) error {
+	_, err := q.db.Exec(ctx, keywordContinue, continue_)
+	return err
+}
+
+const keywordDefault = `-- name: KeywordDefault :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordDefault(ctx context.Context, default_ string) error {
+	_, err := q.db.Exec(ctx, keywordDefault, default_)
+	return err
+}
+
+const keywordDefer = `-- name: KeywordDefer :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordDefer(ctx context.Context, defer_ string) error {
+	_, err := q.db.Exec(ctx, keywordDefer, defer_)
+	return err
+}
+
+const keywordElse = `-- name: KeywordElse :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordElse(ctx context.Context, else_ string) error {
+	_, err := q.db.Exec(ctx, keywordElse, else_)
+	return err
+}
+
+const keywordFallthrough = `-- name: KeywordFallthrough :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordFallthrough(ctx context.Context, fallthrough_ string) error {
+	_, err := q.db.Exec(ctx, keywordFallthrough, fallthrough_)
+	return err
+}
+
+const keywordFor = `-- name: KeywordFor :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordFor(ctx context.Context, for_ string) error {
+	_, err := q.db.Exec(ctx, keywordFor, for_)
+	return err
+}
+
+const keywordFunc = `-- name: KeywordFunc :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordFunc(ctx context.Context, func_ string) error {
+	_, err := q.db.Exec(ctx, keywordFunc, func_)
+	return err
+}
+
+const keywordGo = `-- name: KeywordGo :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordGo(ctx context.Context, go_ string) error {
+	_, err := q.db.Exec(ctx, keywordGo, go_)
+	return err
+}
+
+const keywordGoto = `-- name: KeywordGoto :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordGoto(ctx context.Context, goto_ string) error {
+	_, err := q.db.Exec(ctx, keywordGoto, goto_)
+	return err
+}
+
+const keywordIf = `-- name: KeywordIf :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordIf(ctx context.Context, if_ string) error {
+	_, err := q.db.Exec(ctx, keywordIf, if_)
+	return err
+}
+
+const keywordImport = `-- name: KeywordImport :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordImport(ctx context.Context, import_ string) error {
+	_, err := q.db.Exec(ctx, keywordImport, import_)
+	return err
+}
+
+const keywordInterface = `-- name: KeywordInterface :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordInterface(ctx context.Context, interface_ string) error {
+	_, err := q.db.Exec(ctx, keywordInterface, interface_)
+	return err
+}
+
+const keywordMap = `-- name: KeywordMap :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordMap(ctx context.Context, map_ string) error {
+	_, err := q.db.Exec(ctx, keywordMap, map_)
+	return err
+}
+
+const keywordPackage = `-- name: KeywordPackage :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordPackage(ctx context.Context, package_ string) error {
+	_, err := q.db.Exec(ctx, keywordPackage, package_)
+	return err
+}
+
+const keywordRange = `-- name: KeywordRange :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordRange(ctx context.Context, range_ string) error {
+	_, err := q.db.Exec(ctx, keywordRange, range_)
+	return err
+}
+
+const keywordReturn = `-- name: KeywordReturn :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordReturn(ctx context.Context, return_ string) error {
+	_, err := q.db.Exec(ctx, keywordReturn, return_)
+	return err
+}
+
+const keywordSelect = `-- name: KeywordSelect :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordSelect(ctx context.Context, select_ string) error {
+	_, err := q.db.Exec(ctx, keywordSelect, select_)
+	return err
+}
+
+const keywordStruct = `-- name: KeywordStruct :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordStruct(ctx context.Context, struct_ string) error {
+	_, err := q.db.Exec(ctx, keywordStruct, struct_)
+	return err
+}
+
+const keywordSwitch = `-- name: KeywordSwitch :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordSwitch(ctx context.Context, switch_ string) error {
+	_, err := q.db.Exec(ctx, keywordSwitch, switch_)
+	return err
+}
+
+const keywordType = `-- name: KeywordType :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordType(ctx context.Context, type_ string) error {
+	_, err := q.db.Exec(ctx, keywordType, type_)
+	return err
+}
+
+const keywordVar = `-- name: KeywordVar :exec
+SELECT $1::text
+`
+
+func (q *Queries) KeywordVar(ctx context.Context, var_ string) error {
+	_, err := q.db.Exec(ctx, keywordVar, var_)
+	return err
+}
+
+const selectBreak = `-- name: SelectBreak :one
+SELECT "break" FROM go_keywords
+`
+
+func (q *Queries) SelectBreak(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectBreak)
+	var break_ pgtype.Text
+	err := row.Scan(&break_)
+	return break_, err
+}
+
+const selectCase = `-- name: SelectCase :one
+SELECT "case" FROM go_keywords
+`
+
+func (q *Queries) SelectCase(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectCase)
+	var case_ pgtype.Text
+	err := row.Scan(&case_)
+	return case_, err
+}
+
+const selectChan = `-- name: SelectChan :one
+SELECT "chan" FROM go_keywords
+`
+
+func (q *Queries) SelectChan(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectChan)
+	var chan_ pgtype.Text
+	err := row.Scan(&chan_)
+	return chan_, err
+}
+
+const selectConst = `-- name: SelectConst :one
+SELECT "const" FROM go_keywords
+`
+
+func (q *Queries) SelectConst(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectConst)
+	var const_ pgtype.Text
+	err := row.Scan(&const_)
+	return const_, err
+}
+
+const selectContinue = `-- name: SelectContinue :one
+SELECT "continue" FROM go_keywords
+`
+
+func (q *Queries) SelectContinue(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectContinue)
+	var continue_ pgtype.Text
+	err := row.Scan(&continue_)
+	return continue_, err
+}
+
+const selectDefault = `-- name: SelectDefault :one
+SELECT "default" FROM go_keywords
+`
+
+func (q *Queries) SelectDefault(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectDefault)
+	var default_ pgtype.Text
+	err := row.Scan(&default_)
+	return default_, err
+}
+
+const selectDefer = `-- name: SelectDefer :one
+SELECT "defer" FROM go_keywords
+`
+
+func (q *Queries) SelectDefer(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectDefer)
+	var defer_ pgtype.Text
+	err := row.Scan(&defer_)
+	return defer_, err
+}
+
+const selectElse = `-- name: SelectElse :one
+SELECT "else" FROM go_keywords
+`
+
+func (q *Queries) SelectElse(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectElse)
+	var else_ pgtype.Text
+	err := row.Scan(&else_)
+	return else_, err
+}
+
+const selectFallthrough = `-- name: SelectFallthrough :one
+SELECT "fallthrough" FROM go_keywords
+`
+
+func (q *Queries) SelectFallthrough(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectFallthrough)
+	var fallthrough_ pgtype.Text
+	err := row.Scan(&fallthrough_)
+	return fallthrough_, err
+}
+
+const selectFor = `-- name: SelectFor :one
+SELECT "for" FROM go_keywords
+`
+
+func (q *Queries) SelectFor(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectFor)
+	var for_ pgtype.Text
+	err := row.Scan(&for_)
+	return for_, err
+}
+
+const selectFunc = `-- name: SelectFunc :one
+SELECT "func" FROM go_keywords
+`
+
+func (q *Queries) SelectFunc(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectFunc)
+	var func_ pgtype.Text
+	err := row.Scan(&func_)
+	return func_, err
+}
+
+const selectGo = `-- name: SelectGo :one
+SELECT "go" FROM go_keywords
+`
+
+func (q *Queries) SelectGo(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectGo)
+	var go_ pgtype.Text
+	err := row.Scan(&go_)
+	return go_, err
+}
+
+const selectGoto = `-- name: SelectGoto :one
+SELECT "goto" FROM go_keywords
+`
+
+func (q *Queries) SelectGoto(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectGoto)
+	var goto_ pgtype.Text
+	err := row.Scan(&goto_)
+	return goto_, err
+}
+
+const selectIf = `-- name: SelectIf :one
+SELECT "if" FROM go_keywords
+`
+
+func (q *Queries) SelectIf(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectIf)
+	var if_ pgtype.Text
+	err := row.Scan(&if_)
+	return if_, err
+}
+
+const selectImport = `-- name: SelectImport :one
+SELECT "import" FROM go_keywords
+`
+
+func (q *Queries) SelectImport(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectImport)
+	var import_ pgtype.Text
+	err := row.Scan(&import_)
+	return import_, err
+}
+
+const selectInterface = `-- name: SelectInterface :one
+SELECT "interface" FROM go_keywords
+`
+
+func (q *Queries) SelectInterface(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectInterface)
+	var interface_ pgtype.Text
+	err := row.Scan(&interface_)
+	return interface_, err
+}
+
+const selectMap = `-- name: SelectMap :one
+SELECT "map" FROM go_keywords
+`
+
+func (q *Queries) SelectMap(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectMap)
+	var map_ pgtype.Text
+	err := row.Scan(&map_)
+	return map_, err
+}
+
+const selectPackage = `-- name: SelectPackage :one
+SELECT "package" FROM go_keywords
+`
+
+func (q *Queries) SelectPackage(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectPackage)
+	var package_ pgtype.Text
+	err := row.Scan(&package_)
+	return package_, err
+}
+
+const selectRange = `-- name: SelectRange :one
+SELECT "range" FROM go_keywords
+`
+
+func (q *Queries) SelectRange(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectRange)
+	var range_ pgtype.Text
+	err := row.Scan(&range_)
+	return range_, err
+}
+
+const selectReturn = `-- name: SelectReturn :one
+SELECT "return" FROM go_keywords
+`
+
+func (q *Queries) SelectReturn(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectReturn)
+	var return_ pgtype.Text
+	err := row.Scan(&return_)
+	return return_, err
+}
+
+const selectSelect = `-- name: SelectSelect :one
+SELECT "select" FROM go_keywords
+`
+
+func (q *Queries) SelectSelect(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectSelect)
+	var select_ pgtype.Text
+	err := row.Scan(&select_)
+	return select_, err
+}
+
+const selectStruct = `-- name: SelectStruct :one
+SELECT "struct" FROM go_keywords
+`
+
+func (q *Queries) SelectStruct(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectStruct)
+	var struct_ pgtype.Text
+	err := row.Scan(&struct_)
+	return struct_, err
+}
+
+const selectSwitch = `-- name: SelectSwitch :one
+SELECT "switch" FROM go_keywords
+`
+
+func (q *Queries) SelectSwitch(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectSwitch)
+	var switch_ pgtype.Text
+	err := row.Scan(&switch_)
+	return switch_, err
+}
+
+const selectType = `-- name: SelectType :one
+SELECT "type" FROM go_keywords
+`
+
+func (q *Queries) SelectType(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectType)
+	var type_ pgtype.Text
+	err := row.Scan(&type_)
+	return type_, err
+}
+
+const selectVar = `-- name: SelectVar :one
+SELECT "var" FROM go_keywords
+`
+
+func (q *Queries) SelectVar(ctx context.Context) (pgtype.Text, error) {
+	row := q.db.QueryRow(ctx, selectVar)
+	var var_ pgtype.Text
+	err := row.Scan(&var_)
+	return var_, err
+}
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql b/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql
new file mode 100644
index 000000000..70796e4e3
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/query.sql
@@ -0,0 +1,149 @@
+-- name: KeywordBreak :exec
+SELECT sqlc.arg('break')::text;
+
+-- name: KeywordDefault :exec
+SELECT sqlc.arg('default')::text;
+
+-- name: KeywordFunc :exec
+SELECT sqlc.arg('func')::text;
+
+-- name: KeywordInterface :exec
+SELECT sqlc.arg('interface')::text;
+
+-- name: KeywordSelect :exec
+SELECT sqlc.arg('select')::text;
+
+-- name: KeywordCase :exec
+SELECT sqlc.arg('case')::text;
+
+-- name: KeywordDefer :exec
+SELECT sqlc.arg('defer')::text;
+
+-- name: KeywordGo :exec
+SELECT sqlc.arg('go')::text;
+
+-- name: KeywordMap :exec
+SELECT sqlc.arg('map')::text;
+
+-- name: KeywordStruct :exec
+SELECT sqlc.arg('struct')::text;
+
+-- name: KeywordChan :exec
+SELECT sqlc.arg('chan')::text;
+
+-- name: KeywordElse :exec
+SELECT sqlc.arg('else')::text;
+
+-- name: KeywordGoto :exec
+SELECT sqlc.arg('goto')::text;
+
+-- name: KeywordPackage :exec
+SELECT sqlc.arg('package')::text;
+
+-- name: KeywordSwitch :exec
+SELECT sqlc.arg('switch')::text;
+
+-- name: KeywordConst :exec
+SELECT sqlc.arg('const')::text;
+
+-- name: KeywordFallthrough :exec
+SELECT sqlc.arg('fallthrough')::text;
+
+-- name: KeywordIf :exec
+SELECT sqlc.arg('if')::text;
+
+-- name: KeywordRange :exec
+SELECT sqlc.arg('range')::text;
+
+-- name: KeywordType :exec
+SELECT sqlc.arg('type')::text;
+
+-- name: KeywordContinue :exec
+SELECT sqlc.arg('continue')::text;
+
+-- name: KeywordFor :exec
+SELECT sqlc.arg('for')::text;
+
+-- name: KeywordImport :exec
+SELECT sqlc.arg('import')::text;
+
+-- name: KeywordReturn :exec
+SELECT sqlc.arg('return')::text;
+
+-- name: KeywordVar :exec
+SELECT sqlc.arg('var')::text;
+
+-- name: SelectBreak :one
+SELECT "break" FROM go_keywords;
+
+-- name: SelectDefault :one
+SELECT "default" FROM go_keywords;
+
+-- name: SelectFunc :one
+SELECT "func" FROM go_keywords;
+
+-- name: SelectInterface :one
+SELECT "interface" FROM go_keywords;
+
+-- name: SelectSelect :one
+SELECT "select" FROM go_keywords;
+
+-- name: SelectCase :one
+SELECT "case" FROM go_keywords;
+
+-- name: SelectDefer :one
+SELECT "defer" FROM go_keywords;
+
+-- name: SelectGo :one
+SELECT "go" FROM go_keywords;
+
+-- name: SelectMap :one
+SELECT "map" FROM go_keywords;
+
+-- name: SelectStruct :one
+SELECT "struct" FROM go_keywords;
+
+-- name: SelectChan :one
+SELECT "chan" FROM go_keywords;
+
+-- name: SelectElse :one
+SELECT "else" FROM go_keywords;
+
+-- name: SelectGoto :one
+SELECT "goto" FROM go_keywords;
+
+-- name: SelectPackage :one
+SELECT "package" FROM go_keywords;
+
+-- name: SelectSwitch :one
+SELECT "switch" FROM go_keywords;
+
+-- name: SelectConst :one
+SELECT "const" FROM go_keywords;
+
+-- name: SelectFallthrough :one
+SELECT "fallthrough" FROM go_keywords;
+
+-- name: SelectIf :one
+SELECT "if" FROM go_keywords;
+
+-- name: SelectRange :one
+SELECT "range" FROM go_keywords;
+
+-- name: SelectType :one
+SELECT "type" FROM go_keywords;
+
+-- name: SelectContinue :one
+SELECT "continue" FROM go_keywords;
+
+-- name: SelectFor :one
+SELECT "for" FROM go_keywords;
+
+-- name: SelectImport :one
+SELECT "import" FROM go_keywords;
+
+-- name: SelectReturn :one
+SELECT "return" FROM go_keywords;
+
+-- name: SelectVar :one
+SELECT "var" FROM go_keywords;
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql b/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql
new file mode 100644
index 000000000..11a04beef
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/schema.sql
@@ -0,0 +1,27 @@
+CREATE TABLE go_keywords (
+    "break" TEXT,
+    "default" TEXT,
+    "func" TEXT,
+    "interface" TEXT,
+    "select" TEXT,
+    "case" TEXT,
+    "defer" TEXT,
+    "go" TEXT,
+    "map" TEXT,
+    "struct" TEXT,
+    "chan" TEXT,
+    "else" TEXT,
+    "goto" TEXT,
+    "package" TEXT,
+    "switch" TEXT,
+    "const" TEXT,
+    "fallthrough" TEXT,
+    "if" TEXT,
+    "range" TEXT,
+    "type" TEXT,
+    "continue" TEXT,
+    "for" TEXT,
+    "import" TEXT,
+    "return" TEXT,
+    "var" TEXT
+);
diff --git a/internal/endtoend/testdata/params_go_keywords/postgresql/sqlc.yaml b/internal/endtoend/testdata/params_go_keywords/postgresql/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/params_go_keywords/postgresql/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/process_plugin_sqlc_gen_json/gen/codegen.json b/internal/endtoend/testdata/process_plugin_sqlc_gen_json/gen/codegen.json
index fcfbff009..fcbceb288 100644
--- a/internal/endtoend/testdata/process_plugin_sqlc_gen_json/gen/codegen.json
+++ b/internal/endtoend/testdata/process_plugin_sqlc_gen_json/gen/codegen.json
@@ -13,7 +13,12 @@
     "codegen": {
       "out": "gen",
       "plugin": "jsonb",
-      "options": "eyJmaWxlbmFtZSI6ImNvZGVnZW4uanNvbiIsImluZGVudCI6IiAgIn0="
+      "options": "eyJmaWxlbmFtZSI6ImNvZGVnZW4uanNvbiIsImluZGVudCI6IiAgIn0=",
+      "env": [],
+      "process": {
+        "cmd": "sqlc-gen-json"
+      },
+      "wasm": null
     }
   },
   "catalog": {
diff --git a/internal/engine/sqlite/catalog_test.go b/internal/engine/sqlite/catalog_test.go
index 3c3028fcc..bf6dcd831 100644
--- a/internal/engine/sqlite/catalog_test.go
+++ b/internal/engine/sqlite/catalog_test.go
@@ -260,7 +260,7 @@ func TestUpdate(t *testing.T) {
 				}
 			}
 
-			if diff := cmp.Diff(e, c, cmpopts.EquateEmpty()); diff != "" {
+			if diff := cmp.Diff(e, c, cmpopts.EquateEmpty(), cmpopts.IgnoreUnexported(catalog.Column{})); diff != "" {
 				t.Log(test.stmt)
 				t.Errorf("catalog mismatch:\n%s", diff)
 			}
diff --git a/internal/metadata/meta_test.go b/internal/metadata/meta_test.go
index cbfcb6fba..3c2be6d6d 100644
--- a/internal/metadata/meta_test.go
+++ b/internal/metadata/meta_test.go
@@ -32,34 +32,108 @@ func TestParseQueryNameAndType(t *testing.T) {
 		}
 	}
 
-	query := `-- name: CreateFoo :one`
-	queryName, queryType, err := ParseQueryNameAndType(query, CommentSyntax{Dash: true})
-	if err != nil {
-		t.Errorf("expected valid metadata: %q", query)
-	}
-	if queryName != "CreateFoo" {
-		t.Errorf("incorrect queryName parsed: %q", query)
-	}
-	if queryType != CmdOne {
-		t.Errorf("incorrect queryType parsed: %q", query)
+	for query, cs := range map[string]CommentSyntax{
+		`-- name: CreateFoo :one`:    {Dash: true},
+		`# name: CreateFoo :one`:     {Hash: true},
+		`/* name: CreateFoo :one */`: {SlashStar: true},
+	} {
+		queryName, queryCmd, err := ParseQueryNameAndType(query, cs)
+		if err != nil {
+			t.Errorf("expected valid metadata: %q", query)
+		}
+		if queryName != "CreateFoo" {
+			t.Errorf("incorrect queryName parsed: (%q) %q", queryName, query)
+		}
+		if queryCmd != CmdOne {
+			t.Errorf("incorrect queryCmd parsed: (%q) %q", queryCmd, query)
+		}
 	}
 
 }
 
+func TestParseQueryParams(t *testing.T) {
+	for _, comments := range [][]string{
+		{
+			" name: CreateFoo :one",
+			" @param foo_id UUID",
+		},
+		{
+			" name: CreateFoo :one ",
+			" @param foo_id UUID ",
+		},
+		{
+			" name: CreateFoo :one",
+			"@param foo_id UUID",
+			" invalid",
+		},
+		{
+			" name: CreateFoo :one",
+			" @invalid",
+			" @param foo_id UUID",
+		},
+		{
+			" name: GetFoos :many ",
+			" @param foo_id UUID ",
+			" @param @invalid UUID ",
+		},
+	} {
+		params, _, err := ParseParamsAndFlags(comments)
+		if err != nil {
+			t.Errorf("expected comments to parse, got err: %s", err)
+		}
+
+		pt, ok := params["foo_id"]
+		if !ok {
+			t.Errorf("expected param not found")
+		}
+
+		if pt != "UUID" {
+			t.Error("unexpected param metadata:", pt)
+		}
+
+		_, ok = params["invalid"]
+		if ok {
+			t.Errorf("unexpected param found")
+		}
+	}
+}
+
 func TestParseQueryFlags(t *testing.T) {
 	for _, comments := range [][]string{
 		{
-			"-- name: CreateFoo :one",
-			"-- @flag-foo",
+			" name: CreateFoo :one",
+			" @flag-foo",
+		},
+		{
+			" name: CreateFoo :one ",
+			"@flag-foo ",
+		},
+		{
+			" name: CreateFoo :one",
+			" @flag-foo @flag-bar",
+		},
+		{
+			" name: GetFoos :many",
+			" @param @flag-bar UUID",
+			" @flag-foo",
+		},
+		{
+			" name: GetFoos :many",
+			" @flag-foo",
+			" @param @flag-bar UUID",
 		},
 	} {
-		flags, err := ParseQueryFlags(comments)
+		_, flags, err := ParseParamsAndFlags(comments)
 		if err != nil {
-			t.Errorf("expected query flags to parse, got error: %s", err)
+			t.Errorf("expected comments to parse, got err: %s", err)
 		}
 
 		if !flags["@flag-foo"] {
 			t.Errorf("expected flag not found")
 		}
+
+		if flags["@flag-bar"] {
+			t.Errorf("unexpected flag found")
+		}
 	}
-}
\ No newline at end of file
+}