Repository: sqlc-dev/sqlc
Pull request #2889 (2023-10-19 22:53:21)

feat(analyzer): Cache query analysis
When using managed databases, cache the query analysis if the query, schema and configuration file hasn't change. Also take into account the version of sqlc.

Analysis can only be cached for managed databases as we can't know if a connected database has been changed.


Patch:
diff --git a/docs/reference/datatypes.md b/docs/reference/datatypes.md
index 80b35bbfe..542624a25 100644
--- a/docs/reference/datatypes.md
+++ b/docs/reference/datatypes.md
@@ -27,12 +27,16 @@ type Place struct {
 }
 ```
 
-## Dates and Time
+## Dates and times
 
-All PostgreSQL time and date types are returned as `time.Time` structs. For
+All date and time types are returned as `time.Time` structs. For
 null time or date values, the `NullTime` type from `database/sql` is used.
+
 The `pgx/v5` sql package uses the appropriate pgx types.
 
+For MySQL users relying on `github.com/go-sql-driver/mysql`, ensure that
+`parseTime=true` is added to your database connection string.
+
 ```sql
 CREATE TABLE authors (
   id         SERIAL    PRIMARY KEY,
diff --git a/docs/tutorials/getting-started-mysql.md b/docs/tutorials/getting-started-mysql.md
index 4fa55d713..7cf52972f 100644
--- a/docs/tutorials/getting-started-mysql.md
+++ b/docs/tutorials/getting-started-mysql.md
@@ -3,9 +3,16 @@
 This tutorial assumes that the latest version of sqlc is
 [installed](../overview/install.md) and ready to use.
 
+We'll generate Go code here, but other
+[language plugins](../reference/language-support.rst) are available. You'll
+naturally need the Go toolchain if you want to build and run a program with the
+code sqlc generates, but sqlc itself has no dependencies.
+
+## Setting up
+
 Create a new directory called `sqlc-tutorial` and open it up.
 
-Initialize a new Go module named `tutorial.sql.dev/app`
+Initialize a new Go module named `tutorial.sqlc.dev/app`
 
 ```shell
 go mod init tutorial.sqlc.dev/app
@@ -16,7 +23,7 @@ directory. In our new directory, create a file named `sqlc.yaml` with the
 following contents:
 
 ```yaml
-version: 2
+version: "2"
 sql:
   - engine: "mysql"
     queries: "query.sql"
@@ -27,8 +34,11 @@ sql:
         out: "tutorial"
 ```
 
-sqlc needs to know your database schema and queries. In the same directory,
-create a file named `schema.sql` with the following contents:
+## Schema and queries
+
+sqlc needs to know your database schema and queries in order to generate code.
+In the same directory, create a file named `schema.sql` with the following
+content:
 
 ```sql
 CREATE TABLE authors (
@@ -61,13 +71,17 @@ DELETE FROM authors
 WHERE id = ?;
 ```
 
-You are now ready to generate code. Run the `generate` command. You shouldn't see any errors or output.
+## Generating code
+
+You are now ready to generate code. You shouldn't see any output when you run
+the `generate` subcommand, unless something goes wrong:
 
 ```shell
 sqlc generate
 ```
 
-You should now have a `tutorial` package containing three files.
+You should now have a `tutorial` subdirectory with three files containing Go
+source code. These files comprise a Go package named `tutorial`:
 
 ```
 ├── go.mod
@@ -80,7 +94,10 @@ You should now have a `tutorial` package containing three files.
     └── query.sql.go
 ```
 
-You can use your newly generated queries in `app.go`.
+## Using generated code
+
+You can use your newly-generated `tutorial` package from any Go program.
+Create a file named `tutorial.go` and add the following contents:
 
 ```go
 package main
@@ -91,9 +108,9 @@ import (
 	"log"
 	"reflect"
 
-	"tutorial.sqlc.dev/app/tutorial"
-
 	_ "github.com/go-sql-driver/mysql"
+
+	"tutorial.sqlc.dev/app/tutorial"
 )
 
 func run() error {
@@ -146,17 +163,21 @@ func main() {
 }
 ```
 
-Before the code will compile, you'll need to add the Go MySQL driver.
+Before this code will compile you'll need to fetch the relevant MySQL driver:
 
-```
+```shell
 go get github.com/go-sql-driver/mysql
 go build ./...
 ```
 
-To make that possible, sqlc generates readable, **idiomatic** Go code that you
-otherwise would have had to write yourself. Take a look in `tutorial/query.sql.go`.
+The program should compile without errors. To make that possible, sqlc generates
+readable, **idiomatic** Go code that you otherwise would've had to write
+yourself. Take a look in `tutorial/query.sql.go`.
+
+Of course for this program to run successfully you'll need
+to compile after replacing the database connection parameters in the call to
+`sql.Open()` with the correct parameters for your database. And your
+database must have the `authors` table as defined in `schema.sql`.
 
-If your tables have columns with date or time types, sqlc expects these values
-to scan into `time.Time` structs. If you're using
-`github.com/go-sql-driver/mysql`, ensure that `parseTime=true` has been added to
-the connection string.
+You should now have a working program using sqlc's generated Go source code,
+and hopefully can see how you'd use sqlc in your own real-world applications.
diff --git a/docs/tutorials/getting-started-postgresql.md b/docs/tutorials/getting-started-postgresql.md
index 9f7d09a1a..d4898d203 100644
--- a/docs/tutorials/getting-started-postgresql.md
+++ b/docs/tutorials/getting-started-postgresql.md
@@ -3,9 +3,23 @@
 This tutorial assumes that the latest version of sqlc is
 [installed](../overview/install.md) and ready to use.
 
+We'll generate Go code here, but other
+[language plugins](../reference/language-support.rst) are available. You'll
+naturally need the Go toolchain if you want to build and run a program with the
+code sqlc generates, but sqlc itself has no dependencies.
+
+We'll also rely on sqlc's [managed databases](../howto/managed-databases.md),
+which require a sqlc Cloud project and auth token. You can get those from
+the [sqlc Cloud dashboard](https://dashboard.sqlc.dev/). Managed databases are
+an optional feature that improves sqlc's query analysis in many cases, but you
+can turn it off simply by removing the `cloud` and `database` sections of your
+configuration.
+
+## Setting up
+
 Create a new directory called `sqlc-tutorial` and open it up.
 
-Initialize a new Go module named `tutorial.sqlc.dev/app`
+Initialize a new Go module named `tutorial.sqlc.dev/app`:
 
 ```shell
 go mod init tutorial.sqlc.dev/app
@@ -17,16 +31,29 @@ following contents:
 
 ```yaml
 version: "2"
+cloud:
+  project: "<your project id>"
 sql:
   - engine: "postgresql"
     queries: "query.sql"
     schema: "schema.sql"
+    database:
+      managed: true
     gen:
       go:
         package: "tutorial"
         out: "tutorial"
+        sql_package: "pgx/v5"
+```
+
+And finally, set the `SQLC_AUTH_TOKEN` environment variable:
+
+```shell
+export SQLC_AUTH_TOKEN="<your sqlc auth token>"
 ```
 
+## Schema and queries
+
 sqlc needs to know your database schema and queries in order to generate code.
 In the same directory, create a file named `schema.sql` with the following
 content:
@@ -39,7 +66,7 @@ CREATE TABLE authors (
 );
 ```
 
-Next, create a `query.sql` file with the following four queries:
+Next, create a `query.sql` file with the following five queries:
 
 ```sql
 -- name: GetAuthor :one
@@ -58,23 +85,19 @@ INSERT INTO authors (
 )
 RETURNING *;
 
--- name: DeleteAuthor :exec
-DELETE FROM authors
-WHERE id = $1;
-```
-
-If you **do not** want your SQL `UPDATE` queries to return the updated record
-to the user, add this to `query.sql`:
-
-```sql
 -- name: UpdateAuthor :exec
 UPDATE authors
   set name = $2,
   bio = $3
 WHERE id = $1;
+
+-- name: DeleteAuthor :exec
+DELETE FROM authors
+WHERE id = $1;
 ```
 
-Otherwise, to return the updated record to the user, add this to `query.sql`:
+If you prefer, you can alter the `UpdateAuthor` query to return the updated
+record:
 
 ```sql
 -- name: UpdateAuthor :one
@@ -85,13 +108,17 @@ WHERE id = $1
 RETURNING *;
 ```
 
-You are now ready to generate code. You shouldn't see any errors or output.
+## Generating code
+
+You are now ready to generate code. You shouldn't see any output when you run
+the `generate` subcommand, unless something goes wrong:
 
 ```shell
 sqlc generate
 ```
 
-You should now have a `tutorial` package containing three files.
+You should now have a `tutorial` subdirectory with three files containing Go
+source code. These files comprise a Go package named `tutorial`:
 
 ```
 ├── go.mod
@@ -104,31 +131,35 @@ You should now have a `tutorial` package containing three files.
     └── query.sql.go
 ```
 
-You can use your newly generated queries in `app.go`.
+## Using generated code
+
+You can use your newly-generated `tutorial` package from any Go program.
+Create a file named `tutorial.go` and add the following contents:
 
 ```go
 package main
 
 import (
 	"context"
-	"database/sql"
 	"log"
 	"reflect"
 
-	"tutorial.sqlc.dev/app/tutorial"
+	"github.com/jackc/pgx/v5"
+	"github.com/jackc/pgx/v5/pgtype"
 
-	_ "github.com/lib/pq"
+	"tutorial.sqlc.dev/app/tutorial"
 )
 
 func run() error {
 	ctx := context.Background()
 
-	db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full")
+	conn, err := pgx.Connect(ctx, "user=pqgotest dbname=pqgotest sslmode=verify-full")
 	if err != nil {
 		return err
 	}
+	defer conn.Close(ctx)
 
-	queries := tutorial.New(db)
+	queries := tutorial.New(conn)
 
 	// list all authors
 	authors, err := queries.ListAuthors(ctx)
@@ -140,7 +171,7 @@ func run() error {
 	// create an author
 	insertedAuthor, err := queries.CreateAuthor(ctx, tutorial.CreateAuthorParams{
 		Name: "Brian Kernighan",
-		Bio:  sql.NullString{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true},
+		Bio:  pgtype.Text{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true},
 	})
 	if err != nil {
 		return err
@@ -165,13 +196,23 @@ func main() {
 }
 ```
 
-Before the code will compile, you'll need to add the Go PostgreSQL driver.
+Before this code will compile you'll need to fetch the relevant PostgreSQL
+driver. You can use `lib/pq` with the standard library's `database/sql`
+package, but in this tutorial we've used `pgx/v5`:
 
-```
-go get github.com/lib/pq
+```shell
+go get github.com/jackc/pgx/v5
 go build ./...
 ```
 
-sqlc generates readable, **idiomatic** Go code that you otherwise would have
-had to write yourself. Take a look in the `tutorial` package to see what code
-sqlc generated.
+The program should compile without errors. To make that possible, sqlc generates
+readable, **idiomatic** Go code that you otherwise would've had to write
+yourself. Take a look in `tutorial/query.sql.go`.
+
+Of course for this program to run successfully you'll need
+to compile after replacing the database connection parameters in the call to
+`pgx.Connect()` with the correct parameters for your database. And your
+database must have the `authors` table as defined in `schema.sql`.
+
+You should now have a working program using sqlc's generated Go source code,
+and hopefully can see how you'd use sqlc in your own real-world applications.
diff --git a/docs/tutorials/getting-started-sqlite.md b/docs/tutorials/getting-started-sqlite.md
index 28f0669ea..f855e41af 100644
--- a/docs/tutorials/getting-started-sqlite.md
+++ b/docs/tutorials/getting-started-sqlite.md
@@ -3,9 +3,16 @@
 This tutorial assumes that the latest version of sqlc is
 [installed](../overview/install.md) and ready to use.
 
+We'll generate Go code here, but other
+[language plugins](../reference/language-support.rst) are available. You'll
+naturally need the Go toolchain if you want to build and run a program with the
+code sqlc generates, but sqlc itself has no dependencies.
+
+## Setting up
+
 Create a new directory called `sqlc-tutorial` and open it up.
 
-Initialize a new Go module named `tutorial.sql.dev/app`
+Initialize a new Go module named `tutorial.sqlc.dev/app`
 
 ```shell
 go mod init tutorial.sqlc.dev/app
@@ -16,19 +23,22 @@ directory. In our new directory, create a file named `sqlc.yaml` with the
 following contents:
 
 ```yaml
-version: 2
+version: "2"
 sql:
   - engine: "sqlite"
-    schema: "schema.sql"
     queries: "query.sql"
+    schema: "schema.sql"
     gen:
       go:
         package: "tutorial"
         out: "tutorial"
 ```
 
-sqlc needs to know your database schema and queries. In the same directory,
-create a file named `schema.sql` with the following contents:
+## Schema and queries
+
+sqlc needs to know your database schema and queries in order to generate code.
+In the same directory, create a file named `schema.sql` with the following
+content:
 
 ```sql
 CREATE TABLE authors (
@@ -38,7 +48,7 @@ CREATE TABLE authors (
 );
 ```
 
-Next, create a `query.sql` file with the following four queries:
+Next, create a `query.sql` file with the following five queries:
 
 ```sql
 -- name: GetAuthor :one
@@ -57,22 +67,19 @@ INSERT INTO authors (
 )
 RETURNING *;
 
--- name: DeleteAuthor :exec
-DELETE FROM authors
-WHERE id = ?;
-```
-
-For SQL UPDATE if you do not want to return the updated record to the user, add this to the `query.sql` file:
-
-```sql
 -- name: UpdateAuthor :exec
 UPDATE authors
 set name = ?,
 bio = ?
 WHERE id = ?;
+
+-- name: DeleteAuthor :exec
+DELETE FROM authors
+WHERE id = ?;
 ```
 
-Otherwise, to return the updated record back to the user, add this to the `query.sql` file:
+If you prefer, you can alter the `UpdateAuthor` query to return the updated
+record:
 
 ```sql
 -- name: UpdateAuthor :one
@@ -83,13 +90,17 @@ WHERE id = ?
 RETURNING *;
 ```
 
-You are now ready to generate code. Run the `generate` command. You shouldn't see any errors or output.
+## Generating code
+
+You are now ready to generate code. You shouldn't see any output when you run
+the `generate` subcommand, unless something goes wrong:
 
 ```shell
 sqlc generate
 ```
 
-You should now have a `tutorial` package containing three files.
+You should now have a `tutorial` subdirectory with three files containing Go
+source code. These files comprise a Go package named `tutorial`:
 
 ```
 ├── go.mod
@@ -102,7 +113,10 @@ You should now have a `tutorial` package containing three files.
     └── query.sql.go
 ```
 
-You can use your newly generated queries in `app.go`.
+## Using generated code
+
+You can use your newly-generated `tutorial` package from any Go program.
+Create a file named `tutorial.go` and add the following contents:
 
 ```go
 package main
@@ -110,14 +124,13 @@ package main
 import (
 	"context"
 	"database/sql"
+	_ "embed"
 	"log"
 	"reflect"
 
-	"tutorial.sqlc.dev/app/tutorial"
-
-	_ "embed"
-
 	_ "github.com/mattn/go-sqlite3"
+
+	"tutorial.sqlc.dev/app/tutorial"
 )
 
 //go:embed schema.sql
@@ -173,12 +186,16 @@ func main() {
 }
 ```
 
-Before the code will compile, you'll need to add the Go SQLite driver.
+Before this code will compile you'll need to fetch the relevant SQLite driver:
 
-```
-go mod tidy
+```shell
+go get github.com/mattn/go-sqlite3
 go build ./...
 ```
 
-To make that possible, sqlc generates readable, **idiomatic** Go code that you
-otherwise would have had to write yourself. Take a look in `tutorial/query.sql.go`.
+The program should compile without errors, and run successfully. To make that
+possible, sqlc generates readable, **idiomatic** Go code that you
+otherwise would've had to write yourself. Take a look in `tutorial/query.sql.go`.
+
+You should now have a working program using sqlc's generated Go source code,
+and hopefully can see how you'd use sqlc in your own real-world applications.
diff --git a/internal/analysis/analysis.pb.go b/internal/analysis/analysis.pb.go
new file mode 100644
index 000000000..e039cd616
--- /dev/null
+++ b/internal/analysis/analysis.pb.go
@@ -0,0 +1,546 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.30.0
+// 	protoc        (unknown)
+// source: analysis/analysis.proto
+
+package analysis
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Identifier struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Catalog string `protobuf:"bytes,1,opt,name=catalog,proto3" json:"catalog,omitempty"`
+	Schema  string `protobuf:"bytes,2,opt,name=schema,proto3" json:"schema,omitempty"`
+	Name    string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *Identifier) Reset() {
+	*x = Identifier{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_analysis_analysis_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Identifier) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Identifier) ProtoMessage() {}
+
+func (x *Identifier) ProtoReflect() protoreflect.Message {
+	mi := &file_analysis_analysis_proto_msgTypes[0]
+	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 Identifier.ProtoReflect.Descriptor instead.
+func (*Identifier) Descriptor() ([]byte, []int) {
+	return file_analysis_analysis_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Identifier) GetCatalog() string {
+	if x != nil {
+		return x.Catalog
+	}
+	return ""
+}
+
+func (x *Identifier) GetSchema() string {
+	if x != nil {
+		return x.Schema
+	}
+	return ""
+}
+
+func (x *Identifier) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+type Column struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name         string      `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	OriginalName string      `protobuf:"bytes,2,opt,name=original_name,json=originalName,proto3" json:"original_name,omitempty"`
+	DataType     string      `protobuf:"bytes,3,opt,name=data_type,json=dataType,proto3" json:"data_type,omitempty"`
+	NotNull      bool        `protobuf:"varint,4,opt,name=not_null,json=notNull,proto3" json:"not_null,omitempty"`
+	Unsigned     bool        `protobuf:"varint,5,opt,name=unsigned,proto3" json:"unsigned,omitempty"`
+	IsArray      bool        `protobuf:"varint,6,opt,name=is_array,json=isArray,proto3" json:"is_array,omitempty"`
+	ArrayDims    int32       `protobuf:"varint,7,opt,name=array_dims,json=arrayDims,proto3" json:"array_dims,omitempty"`
+	Comment      string      `protobuf:"bytes,8,opt,name=comment,proto3" json:"comment,omitempty"`
+	Length       int32       `protobuf:"varint,9,opt,name=length,proto3" json:"length,omitempty"` // *int
+	IsNamedParam bool        `protobuf:"varint,10,opt,name=is_named_param,json=isNamedParam,proto3" json:"is_named_param,omitempty"`
+	IsFuncCall   bool        `protobuf:"varint,11,opt,name=is_func_call,json=isFuncCall,proto3" json:"is_func_call,omitempty"`
+	Scope        string      `protobuf:"bytes,12,opt,name=scope,proto3" json:"scope,omitempty"`
+	Table        *Identifier `protobuf:"bytes,13,opt,name=table,proto3" json:"table,omitempty"`
+	TableAlias   string      `protobuf:"bytes,14,opt,name=table_alias,json=tableAlias,proto3" json:"table_alias,omitempty"`
+	Type         *Identifier `protobuf:"bytes,15,opt,name=type,proto3" json:"type,omitempty"`
+	EmbedTable   *Identifier `protobuf:"bytes,16,opt,name=embed_table,json=embedTable,proto3" json:"embed_table,omitempty"`
+	IsSqlcSlice  bool        `protobuf:"varint,17,opt,name=is_sqlc_slice,json=isSqlcSlice,proto3" json:"is_sqlc_slice,omitempty"`
+}
+
+func (x *Column) Reset() {
+	*x = Column{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_analysis_analysis_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Column) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Column) ProtoMessage() {}
+
+func (x *Column) ProtoReflect() protoreflect.Message {
+	mi := &file_analysis_analysis_proto_msgTypes[1]
+	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 Column.ProtoReflect.Descriptor instead.
+func (*Column) Descriptor() ([]byte, []int) {
+	return file_analysis_analysis_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Column) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *Column) GetOriginalName() string {
+	if x != nil {
+		return x.OriginalName
+	}
+	return ""
+}
+
+func (x *Column) GetDataType() string {
+	if x != nil {
+		return x.DataType
+	}
+	return ""
+}
+
+func (x *Column) GetNotNull() bool {
+	if x != nil {
+		return x.NotNull
+	}
+	return false
+}
+
+func (x *Column) GetUnsigned() bool {
+	if x != nil {
+		return x.Unsigned
+	}
+	return false
+}
+
+func (x *Column) GetIsArray() bool {
+	if x != nil {
+		return x.IsArray
+	}
+	return false
+}
+
+func (x *Column) GetArrayDims() int32 {
+	if x != nil {
+		return x.ArrayDims
+	}
+	return 0
+}
+
+func (x *Column) GetComment() string {
+	if x != nil {
+		return x.Comment
+	}
+	return ""
+}
+
+func (x *Column) GetLength() int32 {
+	if x != nil {
+		return x.Length
+	}
+	return 0
+}
+
+func (x *Column) GetIsNamedParam() bool {
+	if x != nil {
+		return x.IsNamedParam
+	}
+	return false
+}
+
+func (x *Column) GetIsFuncCall() bool {
+	if x != nil {
+		return x.IsFuncCall
+	}
+	return false
+}
+
+func (x *Column) GetScope() string {
+	if x != nil {
+		return x.Scope
+	}
+	return ""
+}
+
+func (x *Column) GetTable() *Identifier {
+	if x != nil {
+		return x.Table
+	}
+	return nil
+}
+
+func (x *Column) GetTableAlias() string {
+	if x != nil {
+		return x.TableAlias
+	}
+	return ""
+}
+
+func (x *Column) GetType() *Identifier {
+	if x != nil {
+		return x.Type
+	}
+	return nil
+}
+
+func (x *Column) GetEmbedTable() *Identifier {
+	if x != nil {
+		return x.EmbedTable
+	}
+	return nil
+}
+
+func (x *Column) GetIsSqlcSlice() bool {
+	if x != nil {
+		return x.IsSqlcSlice
+	}
+	return false
+}
+
+type Parameter struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Number int32   `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+	Column *Column `protobuf:"bytes,2,opt,name=column,proto3" json:"column,omitempty"`
+}
+
+func (x *Parameter) Reset() {
+	*x = Parameter{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_analysis_analysis_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Parameter) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Parameter) ProtoMessage() {}
+
+func (x *Parameter) ProtoReflect() protoreflect.Message {
+	mi := &file_analysis_analysis_proto_msgTypes[2]
+	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 Parameter.ProtoReflect.Descriptor instead.
+func (*Parameter) Descriptor() ([]byte, []int) {
+	return file_analysis_analysis_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Parameter) GetNumber() int32 {
+	if x != nil {
+		return x.Number
+	}
+	return 0
+}
+
+func (x *Parameter) GetColumn() *Column {
+	if x != nil {
+		return x.Column
+	}
+	return nil
+}
+
+type Analysis struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Columns []*Column    `protobuf:"bytes,1,rep,name=columns,proto3" json:"columns,omitempty"`
+	Params  []*Parameter `protobuf:"bytes,2,rep,name=params,proto3" json:"params,omitempty"`
+}
+
+func (x *Analysis) Reset() {
+	*x = Analysis{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_analysis_analysis_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Analysis) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Analysis) ProtoMessage() {}
+
+func (x *Analysis) ProtoReflect() protoreflect.Message {
+	mi := &file_analysis_analysis_proto_msgTypes[3]
+	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 Analysis.ProtoReflect.Descriptor instead.
+func (*Analysis) Descriptor() ([]byte, []int) {
+	return file_analysis_analysis_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Analysis) GetColumns() []*Column {
+	if x != nil {
+		return x.Columns
+	}
+	return nil
+}
+
+func (x *Analysis) GetParams() []*Parameter {
+	if x != nil {
+		return x.Params
+	}
+	return nil
+}
+
+var File_analysis_analysis_proto protoreflect.FileDescriptor
+
+var file_analysis_analysis_proto_rawDesc = []byte{
+	0x0a, 0x17, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x2f, 0x61, 0x6e, 0x61, 0x6c, 0x79,
+	0x73, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x61, 0x6e, 0x61, 0x6c, 0x79,
+	0x73, 0x69, 0x73, 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, 0xb1, 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, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
+	0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f,
+	0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64,
+	0x61, 0x74, 0x61, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x74, 0x5f,
+	0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, 0x6f, 0x74, 0x4e,
+	0x75, 0x6c, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x12,
+	0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28,
+	0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x72,
+	0x72, 0x61, 0x79, 0x5f, 0x64, 0x69, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
+	0x61, 0x72, 0x72, 0x61, 0x79, 0x44, 0x69, 0x6d, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d,
+	0x6d, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d,
+	0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x09, 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, 0x0a, 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, 0x0b, 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, 0x0c, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x74, 0x61, 0x62,
+	0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79,
+	0x73, 0x69, 0x73, 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, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x62, 0x6c,
+	0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0f,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x2e,
+	0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
+	0x12, 0x35, 0x0a, 0x0b, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18,
+	0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73,
+	0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x65, 0x6d, 0x62,
+	0x65, 0x64, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x73, 0x71,
+	0x6c, 0x63, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
+	0x69, 0x73, 0x53, 0x71, 0x6c, 0x63, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x22, 0x4d, 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, 0x28, 0x0a, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x10, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x2e, 0x43, 0x6f, 0x6c, 0x75,
+	0x6d, 0x6e, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x63, 0x0a, 0x08, 0x41, 0x6e,
+	0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e,
+	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73,
+	0x69, 0x73, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x2e, 0x50, 0x61,
+	0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42,
+	0x89, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73,
+	0x42, 0x0d, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
+	0x01, 0x5a, 0x2a, 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, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0xa2, 0x02, 0x03,
+	0x41, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0xca, 0x02,
+	0x08, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0xe2, 0x02, 0x14, 0x41, 0x6e, 0x61, 0x6c,
+	0x79, 0x73, 0x69, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0xea, 0x02, 0x08, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
+}
+
+var (
+	file_analysis_analysis_proto_rawDescOnce sync.Once
+	file_analysis_analysis_proto_rawDescData = file_analysis_analysis_proto_rawDesc
+)
+
+func file_analysis_analysis_proto_rawDescGZIP() []byte {
+	file_analysis_analysis_proto_rawDescOnce.Do(func() {
+		file_analysis_analysis_proto_rawDescData = protoimpl.X.CompressGZIP(file_analysis_analysis_proto_rawDescData)
+	})
+	return file_analysis_analysis_proto_rawDescData
+}
+
+var file_analysis_analysis_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_analysis_analysis_proto_goTypes = []interface{}{
+	(*Identifier)(nil), // 0: analysis.Identifier
+	(*Column)(nil),     // 1: analysis.Column
+	(*Parameter)(nil),  // 2: analysis.Parameter
+	(*Analysis)(nil),   // 3: analysis.Analysis
+}
+var file_analysis_analysis_proto_depIdxs = []int32{
+	0, // 0: analysis.Column.table:type_name -> analysis.Identifier
+	0, // 1: analysis.Column.type:type_name -> analysis.Identifier
+	0, // 2: analysis.Column.embed_table:type_name -> analysis.Identifier
+	1, // 3: analysis.Parameter.column:type_name -> analysis.Column
+	1, // 4: analysis.Analysis.columns:type_name -> analysis.Column
+	2, // 5: analysis.Analysis.params:type_name -> analysis.Parameter
+	6, // [6:6] is the sub-list for method output_type
+	6, // [6:6] is the sub-list for method input_type
+	6, // [6:6] is the sub-list for extension type_name
+	6, // [6:6] is the sub-list for extension extendee
+	0, // [0:6] is the sub-list for field type_name
+}
+
+func init() { file_analysis_analysis_proto_init() }
+func file_analysis_analysis_proto_init() {
+	if File_analysis_analysis_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_analysis_analysis_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Identifier); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_analysis_analysis_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Column); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_analysis_analysis_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Parameter); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_analysis_analysis_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Analysis); 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{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_analysis_analysis_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   4,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_analysis_analysis_proto_goTypes,
+		DependencyIndexes: file_analysis_analysis_proto_depIdxs,
+		MessageInfos:      file_analysis_analysis_proto_msgTypes,
+	}.Build()
+	File_analysis_analysis_proto = out.File
+	file_analysis_analysis_proto_rawDesc = nil
+	file_analysis_analysis_proto_goTypes = nil
+	file_analysis_analysis_proto_depIdxs = nil
+}
diff --git a/internal/analysis/analysis_vtproto.pb.go b/internal/analysis/analysis_vtproto.pb.go
new file mode 100644
index 000000000..7aacb8635
--- /dev/null
+++ b/internal/analysis/analysis_vtproto.pb.go
@@ -0,0 +1,2078 @@
+// Code generated by protoc-gen-go-vtproto. DO NOT EDIT.
+// protoc-gen-go-vtproto version: v0.4.0
+// source: analysis/analysis.proto
+
+package analysis
+
+import (
+	fmt "fmt"
+	proto "google.golang.org/protobuf/proto"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	io "io"
+	bits "math/bits"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+func (m *Identifier) CloneVT() *Identifier {
+	if m == nil {
+		return (*Identifier)(nil)
+	}
+	r := &Identifier{
+		Catalog: m.Catalog,
+		Schema:  m.Schema,
+		Name:    m.Name,
+	}
+	if len(m.unknownFields) > 0 {
+		r.unknownFields = make([]byte, len(m.unknownFields))
+		copy(r.unknownFields, m.unknownFields)
+	}
+	return r
+}
+
+func (m *Identifier) CloneMessageVT() proto.Message {
+	return m.CloneVT()
+}
+
+func (m *Column) CloneVT() *Column {
+	if m == nil {
+		return (*Column)(nil)
+	}
+	r := &Column{
+		Name:         m.Name,
+		OriginalName: m.OriginalName,
+		DataType:     m.DataType,
+		NotNull:      m.NotNull,
+		Unsigned:     m.Unsigned,
+		IsArray:      m.IsArray,
+		ArrayDims:    m.ArrayDims,
+		Comment:      m.Comment,
+		Length:       m.Length,
+		IsNamedParam: m.IsNamedParam,
+		IsFuncCall:   m.IsFuncCall,
+		Scope:        m.Scope,
+		Table:        m.Table.CloneVT(),
+		TableAlias:   m.TableAlias,
+		Type:         m.Type.CloneVT(),
+		EmbedTable:   m.EmbedTable.CloneVT(),
+		IsSqlcSlice:  m.IsSqlcSlice,
+	}
+	if len(m.unknownFields) > 0 {
+		r.unknownFields = make([]byte, len(m.unknownFields))
+		copy(r.unknownFields, m.unknownFields)
+	}
+	return r
+}
+
+func (m *Column) CloneMessageVT() proto.Message {
+	return m.CloneVT()
+}
+
+func (m *Parameter) CloneVT() *Parameter {
+	if m == nil {
+		return (*Parameter)(nil)
+	}
+	r := &Parameter{
+		Number: m.Number,
+		Column: m.Column.CloneVT(),
+	}
+	if len(m.unknownFields) > 0 {
+		r.unknownFields = make([]byte, len(m.unknownFields))
+		copy(r.unknownFields, m.unknownFields)
+	}
+	return r
+}
+
+func (m *Parameter) CloneMessageVT() proto.Message {
+	return m.CloneVT()
+}
+
+func (m *Analysis) CloneVT() *Analysis {
+	if m == nil {
+		return (*Analysis)(nil)
+	}
+	r := &Analysis{}
+	if rhs := m.Columns; rhs != nil {
+		tmpContainer := make([]*Column, len(rhs))
+		for k, v := range rhs {
+			tmpContainer[k] = v.CloneVT()
+		}
+		r.Columns = tmpContainer
+	}
+	if rhs := m.Params; rhs != nil {
+		tmpContainer := make([]*Parameter, len(rhs))
+		for k, v := range rhs {
+			tmpContainer[k] = v.CloneVT()
+		}
+		r.Params = tmpContainer
+	}
+	if len(m.unknownFields) > 0 {
+		r.unknownFields = make([]byte, len(m.unknownFields))
+		copy(r.unknownFields, m.unknownFields)
+	}
+	return r
+}
+
+func (m *Analysis) CloneMessageVT() proto.Message {
+	return m.CloneVT()
+}
+
+func (this *Identifier) EqualVT(that *Identifier) bool {
+	if this == that {
+		return true
+	} else if this == nil || that == nil {
+		return false
+	}
+	if this.Catalog != that.Catalog {
+		return false
+	}
+	if this.Schema != that.Schema {
+		return false
+	}
+	if this.Name != that.Name {
+		return false
+	}
+	return string(this.unknownFields) == string(that.unknownFields)
+}
+
+func (this *Identifier) EqualMessageVT(thatMsg proto.Message) bool {
+	that, ok := thatMsg.(*Identifier)
+	if !ok {
+		return false
+	}
+	return this.EqualVT(that)
+}
+func (this *Column) EqualVT(that *Column) bool {
+	if this == that {
+		return true
+	} else if this == nil || that == nil {
+		return false
+	}
+	if this.Name != that.Name {
+		return false
+	}
+	if this.OriginalName != that.OriginalName {
+		return false
+	}
+	if this.DataType != that.DataType {
+		return false
+	}
+	if this.NotNull != that.NotNull {
+		return false
+	}
+	if this.Unsigned != that.Unsigned {
+		return false
+	}
+	if this.IsArray != that.IsArray {
+		return false
+	}
+	if this.ArrayDims != that.ArrayDims {
+		return false
+	}
+	if this.Comment != that.Comment {
+		return false
+	}
+	if this.Length != that.Length {
+		return false
+	}
+	if this.IsNamedParam != that.IsNamedParam {
+		return false
+	}
+	if this.IsFuncCall != that.IsFuncCall {
+		return false
+	}
+	if this.Scope != that.Scope {
+		return false
+	}
+	if !this.Table.EqualVT(that.Table) {
+		return false
+	}
+	if this.TableAlias != that.TableAlias {
+		return false
+	}
+	if !this.Type.EqualVT(that.Type) {
+		return false
+	}
+	if !this.EmbedTable.EqualVT(that.EmbedTable) {
+		return false
+	}
+	if this.IsSqlcSlice != that.IsSqlcSlice {
+		return false
+	}
+	return string(this.unknownFields) == string(that.unknownFields)
+}
+
+func (this *Column) EqualMessageVT(thatMsg proto.Message) bool {
+	that, ok := thatMsg.(*Column)
+	if !ok {
+		return false
+	}
+	return this.EqualVT(that)
+}
+func (this *Parameter) EqualVT(that *Parameter) bool {
+	if this == that {
+		return true
+	} else if this == nil || that == nil {
+		return false
+	}
+	if this.Number != that.Number {
+		return false
+	}
+	if !this.Column.EqualVT(that.Column) {
+		return false
+	}
+	return string(this.unknownFields) == string(that.unknownFields)
+}
+
+func (this *Parameter) EqualMessageVT(thatMsg proto.Message) bool {
+	that, ok := thatMsg.(*Parameter)
+	if !ok {
+		return false
+	}
+	return this.EqualVT(that)
+}
+func (this *Analysis) EqualVT(that *Analysis) bool {
+	if this == that {
+		return true
+	} else if this == nil || that == nil {
+		return false
+	}
+	if len(this.Columns) != len(that.Columns) {
+		return false
+	}
+	for i, vx := range this.Columns {
+		vy := that.Columns[i]
+		if p, q := vx, vy; p != q {
+			if p == nil {
+				p = &Column{}
+			}
+			if q == nil {
+				q = &Column{}
+			}
+			if !p.EqualVT(q) {
+				return false
+			}
+		}
+	}
+	if len(this.Params) != len(that.Params) {
+		return false
+	}
+	for i, vx := range this.Params {
+		vy := that.Params[i]
+		if p, q := vx, vy; p != q {
+			if p == nil {
+				p = &Parameter{}
+			}
+			if q == nil {
+				q = &Parameter{}
+			}
+			if !p.EqualVT(q) {
+				return false
+			}
+		}
+	}
+	return string(this.unknownFields) == string(that.unknownFields)
+}
+
+func (this *Analysis) EqualMessageVT(thatMsg proto.Message) bool {
+	that, ok := thatMsg.(*Analysis)
+	if !ok {
+		return false
+	}
+	return this.EqualVT(that)
+}
+func (m *Identifier) 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 *Identifier) MarshalToVT(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVT(dAtA[:size])
+}
+
+func (m *Identifier) 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.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.Schema) > 0 {
+		i -= len(m.Schema)
+		copy(dAtA[i:], m.Schema)
+		i = encodeVarint(dAtA, i, uint64(len(m.Schema)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Catalog) > 0 {
+		i -= len(m.Catalog)
+		copy(dAtA[i:], m.Catalog)
+		i = encodeVarint(dAtA, i, uint64(len(m.Catalog)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Column) 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 *Column) MarshalToVT(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVT(dAtA[:size])
+}
+
+func (m *Column) 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 m.IsSqlcSlice {
+		i--
+		if m.IsSqlcSlice {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x1
+		i--
+		dAtA[i] = 0x88
+	}
+	if m.EmbedTable != nil {
+		size, err := m.EmbedTable.MarshalToSizedBufferVT(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x1
+		i--
+		dAtA[i] = 0x82
+	}
+	if m.Type != nil {
+		size, err := m.Type.MarshalToSizedBufferVT(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x7a
+	}
+	if len(m.TableAlias) > 0 {
+		i -= len(m.TableAlias)
+		copy(dAtA[i:], m.TableAlias)
+		i = encodeVarint(dAtA, i, uint64(len(m.TableAlias)))
+		i--
+		dAtA[i] = 0x72
+	}
+	if m.Table != nil {
+		size, err := m.Table.MarshalToSizedBufferVT(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x6a
+	}
+	if len(m.Scope) > 0 {
+		i -= len(m.Scope)
+		copy(dAtA[i:], m.Scope)
+		i = encodeVarint(dAtA, i, uint64(len(m.Scope)))
+		i--
+		dAtA[i] = 0x62
+	}
+	if m.IsFuncCall {
+		i--
+		if m.IsFuncCall {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x58
+	}
+	if m.IsNamedParam {
+		i--
+		if m.IsNamedParam {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x50
+	}
+	if m.Length != 0 {
+		i = encodeVarint(dAtA, i, uint64(m.Length))
+		i--
+		dAtA[i] = 0x48
+	}
+	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] = 0x42
+	}
+	if m.ArrayDims != 0 {
+		i = encodeVarint(dAtA, i, uint64(m.ArrayDims))
+		i--
+		dAtA[i] = 0x38
+	}
+	if m.IsArray {
+		i--
+		if m.IsArray {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x30
+	}
+	if m.Unsigned {
+		i--
+		if m.Unsigned {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x28
+	}
+	if m.NotNull {
+		i--
+		if m.NotNull {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x20
+	}
+	if len(m.DataType) > 0 {
+		i -= len(m.DataType)
+		copy(dAtA[i:], m.DataType)
+		i = encodeVarint(dAtA, i, uint64(len(m.DataType)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.OriginalName) > 0 {
+		i -= len(m.OriginalName)
+		copy(dAtA[i:], m.OriginalName)
+		i = encodeVarint(dAtA, i, uint64(len(m.OriginalName)))
+		i--
+		dAtA[i] = 0x12
+	}
+	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] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Parameter) 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 *Parameter) MarshalToVT(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVT(dAtA[:size])
+}
+
+func (m *Parameter) 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 m.Column != nil {
+		size, err := m.Column.MarshalToSizedBufferVT(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Number != 0 {
+		i = encodeVarint(dAtA, i, uint64(m.Number))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Analysis) 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 *Analysis) MarshalToVT(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVT(dAtA[:size])
+}
+
+func (m *Analysis) 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.Params) > 0 {
+		for iNdEx := len(m.Params) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.Params[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if len(m.Columns) > 0 {
+		for iNdEx := len(m.Columns) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.Columns[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func encodeVarint(dAtA []byte, offset int, v uint64) int {
+	offset -= sov(v)
+	base := offset
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return base
+}
+func (m *Identifier) 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 *Identifier) MarshalToVTStrict(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
+}
+
+func (m *Identifier) 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.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.Schema) > 0 {
+		i -= len(m.Schema)
+		copy(dAtA[i:], m.Schema)
+		i = encodeVarint(dAtA, i, uint64(len(m.Schema)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Catalog) > 0 {
+		i -= len(m.Catalog)
+		copy(dAtA[i:], m.Catalog)
+		i = encodeVarint(dAtA, i, uint64(len(m.Catalog)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Column) 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 *Column) MarshalToVTStrict(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
+}
+
+func (m *Column) 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 m.IsSqlcSlice {
+		i--
+		if m.IsSqlcSlice {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x1
+		i--
+		dAtA[i] = 0x88
+	}
+	if m.EmbedTable != nil {
+		size, err := m.EmbedTable.MarshalToSizedBufferVTStrict(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x1
+		i--
+		dAtA[i] = 0x82
+	}
+	if m.Type != nil {
+		size, err := m.Type.MarshalToSizedBufferVTStrict(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x7a
+	}
+	if len(m.TableAlias) > 0 {
+		i -= len(m.TableAlias)
+		copy(dAtA[i:], m.TableAlias)
+		i = encodeVarint(dAtA, i, uint64(len(m.TableAlias)))
+		i--
+		dAtA[i] = 0x72
+	}
+	if m.Table != nil {
+		size, err := m.Table.MarshalToSizedBufferVTStrict(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x6a
+	}
+	if len(m.Scope) > 0 {
+		i -= len(m.Scope)
+		copy(dAtA[i:], m.Scope)
+		i = encodeVarint(dAtA, i, uint64(len(m.Scope)))
+		i--
+		dAtA[i] = 0x62
+	}
+	if m.IsFuncCall {
+		i--
+		if m.IsFuncCall {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x58
+	}
+	if m.IsNamedParam {
+		i--
+		if m.IsNamedParam {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x50
+	}
+	if m.Length != 0 {
+		i = encodeVarint(dAtA, i, uint64(m.Length))
+		i--
+		dAtA[i] = 0x48
+	}
+	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] = 0x42
+	}
+	if m.ArrayDims != 0 {
+		i = encodeVarint(dAtA, i, uint64(m.ArrayDims))
+		i--
+		dAtA[i] = 0x38
+	}
+	if m.IsArray {
+		i--
+		if m.IsArray {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x30
+	}
+	if m.Unsigned {
+		i--
+		if m.Unsigned {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x28
+	}
+	if m.NotNull {
+		i--
+		if m.NotNull {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x20
+	}
+	if len(m.DataType) > 0 {
+		i -= len(m.DataType)
+		copy(dAtA[i:], m.DataType)
+		i = encodeVarint(dAtA, i, uint64(len(m.DataType)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.OriginalName) > 0 {
+		i -= len(m.OriginalName)
+		copy(dAtA[i:], m.OriginalName)
+		i = encodeVarint(dAtA, i, uint64(len(m.OriginalName)))
+		i--
+		dAtA[i] = 0x12
+	}
+	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] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Parameter) 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 *Parameter) MarshalToVTStrict(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
+}
+
+func (m *Parameter) 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 m.Column != nil {
+		size, err := m.Column.MarshalToSizedBufferVTStrict(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarint(dAtA, i, uint64(size))
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Number != 0 {
+		i = encodeVarint(dAtA, i, uint64(m.Number))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Analysis) 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 *Analysis) MarshalToVTStrict(dAtA []byte) (int, error) {
+	size := m.SizeVT()
+	return m.MarshalToSizedBufferVTStrict(dAtA[:size])
+}
+
+func (m *Analysis) 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.Params) > 0 {
+		for iNdEx := len(m.Params) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.Params[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if len(m.Columns) > 0 {
+		for iNdEx := len(m.Columns) - 1; iNdEx >= 0; iNdEx-- {
+			size, err := m.Columns[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarint(dAtA, i, uint64(size))
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *Identifier) SizeVT() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Catalog)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	l = len(m.Schema)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	l = len(m.Name)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	n += len(m.unknownFields)
+	return n
+}
+
+func (m *Column) SizeVT() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Name)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	l = len(m.OriginalName)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	l = len(m.DataType)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	if m.NotNull {
+		n += 2
+	}
+	if m.Unsigned {
+		n += 2
+	}
+	if m.IsArray {
+		n += 2
+	}
+	if m.ArrayDims != 0 {
+		n += 1 + sov(uint64(m.ArrayDims))
+	}
+	l = len(m.Comment)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	if m.Length != 0 {
+		n += 1 + sov(uint64(m.Length))
+	}
+	if m.IsNamedParam {
+		n += 2
+	}
+	if m.IsFuncCall {
+		n += 2
+	}
+	l = len(m.Scope)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	if m.Table != nil {
+		l = m.Table.SizeVT()
+		n += 1 + l + sov(uint64(l))
+	}
+	l = len(m.TableAlias)
+	if l > 0 {
+		n += 1 + l + sov(uint64(l))
+	}
+	if m.Type != nil {
+		l = m.Type.SizeVT()
+		n += 1 + l + sov(uint64(l))
+	}
+	if m.EmbedTable != nil {
+		l = m.EmbedTable.SizeVT()
+		n += 2 + l + sov(uint64(l))
+	}
+	if m.IsSqlcSlice {
+		n += 3
+	}
+	n += len(m.unknownFields)
+	return n
+}
+
+func (m *Parameter) SizeVT() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Number != 0 {
+		n += 1 + sov(uint64(m.Number))
+	}
+	if m.Column != nil {
+		l = m.Column.SizeVT()
+		n += 1 + l + sov(uint64(l))
+	}
+	n += len(m.unknownFields)
+	return n
+}
+
+func (m *Analysis) SizeVT() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Columns) > 0 {
+		for _, e := range m.Columns {
+			l = e.SizeVT()
+			n += 1 + l + sov(uint64(l))
+		}
+	}
+	if len(m.Params) > 0 {
+		for _, e := range m.Params {
+			l = e.SizeVT()
+			n += 1 + l + sov(uint64(l))
+		}
+	}
+	n += len(m.unknownFields)
+	return n
+}
+
+func sov(x uint64) (n int) {
+	return (bits.Len64(x|1) + 6) / 7
+}
+func soz(x uint64) (n int) {
+	return sov(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Identifier) 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: Identifier: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Identifier: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Catalog", 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.Catalog = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Schema", 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.Schema = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", 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.Name = 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 *Column) 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: Column: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Column: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", 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.Name = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OriginalName", 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.OriginalName = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DataType", 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.DataType = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field NotNull", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.NotNull = bool(v != 0)
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Unsigned", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.Unsigned = bool(v != 0)
+		case 6:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IsArray", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.IsArray = bool(v != 0)
+		case 7:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ArrayDims", wireType)
+			}
+			m.ArrayDims = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.ArrayDims |= int32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 8:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Comment", 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.Comment = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 9:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Length", wireType)
+			}
+			m.Length = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Length |= int32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 10:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IsNamedParam", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.IsNamedParam = bool(v != 0)
+		case 11:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IsFuncCall", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.IsFuncCall = bool(v != 0)
+		case 12:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Scope", 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.Scope = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 13:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Table", 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.Table == nil {
+				m.Table = &Identifier{}
+			}
+			if err := m.Table.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 14:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TableAlias", 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.TableAlias = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 15:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", 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.Type == nil {
+				m.Type = &Identifier{}
+			}
+			if err := m.Type.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 16:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field EmbedTable", 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.EmbedTable == nil {
+				m.EmbedTable = &Identifier{}
+			}
+			if err := m.EmbedTable.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 17:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IsSqlcSlice", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.IsSqlcSlice = bool(v != 0)
+		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 *Parameter) 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: Parameter: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Parameter: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Number", wireType)
+			}
+			m.Number = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Number |= int32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Column", 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.Column == nil {
+				m.Column = &Column{}
+			}
+			if err := m.Column.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			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 *Analysis) 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: Analysis: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Analysis: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Columns", 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
+			}
+			m.Columns = append(m.Columns, &Column{})
+			if err := m.Columns[len(m.Columns)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Params", 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
+			}
+			m.Params = append(m.Params, &Parameter{})
+			if err := m.Params[len(m.Params)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			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 skip(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	depth := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflow
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+		case 1:
+			iNdEx += 8
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflow
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if length < 0 {
+				return 0, ErrInvalidLength
+			}
+			iNdEx += length
+		case 3:
+			depth++
+		case 4:
+			if depth == 0 {
+				return 0, ErrUnexpectedEndOfGroup
+			}
+			depth--
+		case 5:
+			iNdEx += 4
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+		if iNdEx < 0 {
+			return 0, ErrInvalidLength
+		}
+		if depth == 0 {
+			return iNdEx, nil
+		}
+	}
+	return 0, io.ErrUnexpectedEOF
+}
+
+var (
+	ErrInvalidLength        = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflow          = fmt.Errorf("proto: integer overflow")
+	ErrUnexpectedEndOfGroup = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/internal/analyzer/analyzer.go b/internal/analyzer/analyzer.go
index 4ad703482..85ae587b6 100644
--- a/internal/analyzer/analyzer.go
+++ b/internal/analyzer/analyzer.go
@@ -2,45 +2,115 @@ package analyzer
 
 import (
 	"context"
+	"encoding/json"
+	"fmt"
+	"hash/fnv"
+	"log/slog"
+	"os"
+	"path/filepath"
 
+	"google.golang.org/protobuf/proto"
+
+	"github.com/sqlc-dev/sqlc/internal/analysis"
+	"github.com/sqlc-dev/sqlc/internal/cache"
+	"github.com/sqlc-dev/sqlc/internal/config"
+	"github.com/sqlc-dev/sqlc/internal/info"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 	"github.com/sqlc-dev/sqlc/internal/sql/named"
 )
 
-type Column struct {
-	Name         string
-	OriginalName string
-	DataType     string
-	NotNull      bool
-	Unsigned     bool
-	IsArray      bool
-	ArrayDims    int
-	Comment      string
-	Length       *int
-	IsNamedParam bool
-	IsFuncCall   bool
-
-	// XXX: Figure out what PostgreSQL calls `foo.id`
-	Scope      string
-	Table      *ast.TableName
-	TableAlias string
-	Type       *ast.TypeName
-	EmbedTable *ast.TableName
-
-	IsSqlcSlice bool // is this sqlc.slice()
+type CachedAnalyzer struct {
+	a           Analyzer
+	config      config.Config
+	configBytes []byte
+	db          config.Database
+}
+
+func Cached(a Analyzer, c config.Config, db config.Database) *CachedAnalyzer {
+	return &CachedAnalyzer{
+		a:      a,
+		config: c,
+		db:     db,
+	}
 }
 
-type Parameter struct {
-	Number int
-	Column *Column
+// Create a new error here
+
+func (c *CachedAnalyzer) Analyze(ctx context.Context, n ast.Node, q string, schema []string, np *named.ParamSet) (*analysis.Analysis, error) {
+	result, rerun, err := c.analyze(ctx, n, q, schema, np)
+	if rerun {
+		if err != nil {
+			slog.Warn("first analysis failed with error", "err", err)
+		}
+		return c.a.Analyze(ctx, n, q, schema, np)
+	}
+	return result, err
+}
+
+func (c *CachedAnalyzer) analyze(ctx context.Context, n ast.Node, q string, schema []string, np *named.ParamSet) (*analysis.Analysis, bool, error) {
+	// Only cache queries for managed databases. We can't be certain the the
+	// database is in an unchanged state otherwise
+	if !c.db.Managed {
+		return nil, true, nil
+	}
+
+	dir, err := cache.AnalysisDir()
+	if err != nil {
+		return nil, true, err
+	}
+
+	if c.configBytes == nil {
+		c.configBytes, err = json.Marshal(c.config)
+		if err != nil {
+			return nil, true, err
+		}
+	}
+
+	// Calculate cache key
+	h := fnv.New64()
+	h.Write([]byte(info.Version))
+	h.Write(c.configBytes)
+	for _, m := range schema {
+		h.Write([]byte(m))
+	}
+	h.Write([]byte(q))
+
+	key := fmt.Sprintf("%x", h.Sum(nil))
+	path := filepath.Join(dir, key)
+	if _, err := os.Stat(path); err == nil {
+		contents, err := os.ReadFile(path)
+		if err != nil {
+			return nil, true, err
+		}
+		var a analysis.Analysis
+		if err := proto.Unmarshal(contents, &a); err != nil {
+			return nil, true, err
+		}
+		return &a, false, nil
+	}
+
+	result, err := c.a.Analyze(ctx, n, q, schema, np)
+
+	if err == nil {
+		contents, err := proto.Marshal(result)
+		if err != nil {
+			slog.Warn("unable to marshal analysis", "err", err)
+			return result, false, nil
+		}
+		if err := os.WriteFile(path, contents, 0644); err != nil {
+			slog.Warn("saving analysis to disk failed", "err", err)
+			return result, false, nil
+		}
+	}
+
+	return result, false, err
 }
 
-type Analysis struct {
-	Columns []Column
-	Params  []Parameter
+func (c *CachedAnalyzer) Close(ctx context.Context) error {
+	return c.a.Close(ctx)
 }
 
 type Analyzer interface {
-	Analyze(context.Context, ast.Node, string, []string, *named.ParamSet) (*Analysis, error)
+	Analyze(context.Context, ast.Node, string, []string, *named.ParamSet) (*analysis.Analysis, error)
 	Close(context.Context) error
 }
diff --git a/internal/cache/cache.go b/internal/cache/cache.go
new file mode 100644
index 000000000..a6978034a
--- /dev/null
+++ b/internal/cache/cache.go
@@ -0,0 +1,47 @@
+package cache
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+// The cache directory defaults to os.UserCacheDir(). This location can be
+// overridden by the SQLCCACHE environment variable.
+//
+// Currently the cache stores two types of data: plugins and query analysis
+func Dir() (string, error) {
+	cache := os.Getenv("SQLCCACHE")
+	if cache != "" {
+		return cache, nil
+	}
+	cacheHome, err := os.UserCacheDir()
+	if err != nil {
+		return "", err
+	}
+	return filepath.Join(cacheHome, "sqlc"), nil
+}
+
+func PluginsDir() (string, error) {
+	cacheRoot, err := Dir()
+	if err != nil {
+		return "", err
+	}
+	dir := filepath.Join(cacheRoot, "plugins")
+	if err := os.MkdirAll(dir, 0755); err != nil && !os.IsExist(err) {
+		return "", fmt.Errorf("failed to create %s directory: %w", dir, err)
+	}
+	return dir, nil
+}
+
+func AnalysisDir() (string, error) {
+	cacheRoot, err := Dir()
+	if err != nil {
+		return "", err
+	}
+	dir := filepath.Join(cacheRoot, "query_analysis")
+	if err := os.MkdirAll(dir, 0755); err != nil && !os.IsExist(err) {
+		return "", fmt.Errorf("failed to create %s directory: %w", dir, err)
+	}
+	return dir, nil
+}
diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go
index 381ec0ffe..11e3dc5b4 100644
--- a/internal/codegen/golang/imports.go
+++ b/internal/codegen/golang/imports.go
@@ -219,6 +219,10 @@ func buildImports(settings *plugin.Settings, options *opts, queries []Query, use
 	if uses("uuid.NullUUID") && !overrideNullUUID {
 		pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{}
 	}
+	_, overrideVector := overrideTypes["pgvector.Vector"]
+	if uses("pgvector.Vector") && !overrideVector {
+		pkg[ImportSpec{Path: "github.com/pgvector/pgvector-go"}] = struct{}{}
+	}
 
 	// Custom imports
 	for _, o := range settings.Overrides {
diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go
index 815befad3..54a7f02d4 100644
--- a/internal/codegen/golang/postgresql_type.go
+++ b/internal/codegen/golang/postgresql_type.go
@@ -537,6 +537,15 @@ func postgresType(req *plugin.CodeGenRequest, options *opts, col *plugin.Column)
 			return "pgtype.Polygon"
 		}
 
+	case "vector":
+		if driver == SQLDriverPGXV5 {
+			if emitPointersForNull {
+				return "*pgvector.Vector"
+			} else {
+				return "pgvector.Vector"
+			}
+		}
+
 	case "void":
 		// A void value can only be scanned into an empty interface.
 		return "interface{}"
diff --git a/internal/compiler/analyze.go b/internal/compiler/analyze.go
index 584042f97..82a67fb6f 100644
--- a/internal/compiler/analyze.go
+++ b/internal/compiler/analyze.go
@@ -3,7 +3,7 @@ package compiler
 import (
 	"sort"
 
-	"github.com/sqlc-dev/sqlc/internal/analyzer"
+	analyzer "github.com/sqlc-dev/sqlc/internal/analysis"
 	"github.com/sqlc-dev/sqlc/internal/config"
 	"github.com/sqlc-dev/sqlc/internal/source"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
@@ -13,15 +13,37 @@ import (
 )
 
 type analysis struct {
-	Table        *ast.TableName
-	Columns      []*Column
-	QueryCatalog *QueryCatalog
-	Parameters   []Parameter
-	Named        *named.ParamSet
-	Query        string
+	Table      *ast.TableName
+	Columns    []*Column
+	Parameters []Parameter
+	Named      *named.ParamSet
+	Query      string
 }
 
-func convertColumn(c analyzer.Column) *Column {
+func convertTableName(id *analyzer.Identifier) *ast.TableName {
+	if id == nil {
+		return nil
+	}
+	return &ast.TableName{
+		Catalog: id.Catalog,
+		Schema:  id.Schema,
+		Name:    id.Name,
+	}
+}
+
+func convertTypeName(id *analyzer.Identifier) *ast.TypeName {
+	if id == nil {
+		return nil
+	}
+	return &ast.TypeName{
+		Catalog: id.Catalog,
+		Schema:  id.Schema,
+		Name:    id.Name,
+	}
+}
+
+func convertColumn(c *analyzer.Column) *Column {
+	length := int(c.Length)
 	return &Column{
 		Name:         c.Name,
 		OriginalName: c.OriginalName,
@@ -29,16 +51,16 @@ func convertColumn(c analyzer.Column) *Column {
 		NotNull:      c.NotNull,
 		Unsigned:     c.Unsigned,
 		IsArray:      c.IsArray,
-		ArrayDims:    c.ArrayDims,
+		ArrayDims:    int(c.ArrayDims),
 		Comment:      c.Comment,
-		Length:       c.Length,
+		Length:       &length,
 		IsNamedParam: c.IsNamedParam,
 		IsFuncCall:   c.IsFuncCall,
 		Scope:        c.Scope,
-		Table:        c.Table,
+		Table:        convertTableName(c.Table),
 		TableAlias:   c.TableAlias,
-		Type:         c.Type,
-		EmbedTable:   c.EmbedTable,
+		Type:         convertTypeName(c.Type),
+		EmbedTable:   convertTableName(c.EmbedTable),
 		IsSqlcSlice:  c.IsSqlcSlice,
 	}
 }
@@ -51,8 +73,8 @@ func combineAnalysis(prev *analysis, a *analyzer.Analysis) *analysis {
 	var params []Parameter
 	for _, p := range a.Params {
 		params = append(params, Parameter{
-			Number: p.Number,
-			Column: convertColumn(*p.Column),
+			Number: int(p.Number),
+			Column: convertColumn(p.Column),
 		})
 	}
 	if len(prev.Columns) == len(cols) {
@@ -189,11 +211,10 @@ func (c *Compiler) _analyzeQuery(raw *ast.RawStmt, query string, failfast bool)
 	}
 
 	return &analysis{
-		Table:        table,
-		Columns:      cols,
-		Parameters:   params,
-		QueryCatalog: qc,
-		Query:        expanded,
-		Named:        namedParams,
+		Table:      table,
+		Columns:    cols,
+		Parameters: params,
+		Query:      expanded,
+		Named:      namedParams,
 	}, rerr
 }
diff --git a/internal/compiler/engine.go b/internal/compiler/engine.go
index bbef2f00d..e7e11152c 100644
--- a/internal/compiler/engine.go
+++ b/internal/compiler/engine.go
@@ -51,7 +51,11 @@ func NewCompiler(conf config.SQL, combo config.CombinedSettings) (*Compiler, err
 		c.catalog = postgresql.NewCatalog()
 		if conf.Database != nil {
 			if conf.Analyzer.Database == nil || *conf.Analyzer.Database {
-				c.analyzer = pganalyze.New(c.client, *conf.Database)
+				c.analyzer = analyzer.Cached(
+					pganalyze.New(c.client, *conf.Database),
+					combo.Global,
+					*conf.Database,
+				)
 			}
 		}
 	default:
diff --git a/internal/compiler/parse.go b/internal/compiler/parse.go
index 2cc575b4d..b47a72bee 100644
--- a/internal/compiler/parse.go
+++ b/internal/compiler/parse.go
@@ -70,7 +70,6 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
 
 	var anlys *analysis
 	if c.analyzer != nil {
-		// TODO: Handle panics
 		inference, _ := c.inferQuery(raw, rawSQL)
 		if inference == nil {
 			inference = &analysis{}
diff --git a/internal/engine/postgresql/analyzer/analyze.go b/internal/engine/postgresql/analyzer/analyze.go
index fe07b840e..9c1e77f65 100644
--- a/internal/engine/postgresql/analyzer/analyze.go
+++ b/internal/engine/postgresql/analyzer/analyze.go
@@ -11,7 +11,7 @@ import (
 	"github.com/jackc/pgx/v5/pgconn"
 	"github.com/jackc/pgx/v5/pgxpool"
 
-	core "github.com/sqlc-dev/sqlc/internal/analyzer"
+	core "github.com/sqlc-dev/sqlc/internal/analysis"
 	"github.com/sqlc-dev/sqlc/internal/config"
 	pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
@@ -250,14 +250,14 @@ func (a *Analyzer) Analyze(ctx context.Context, n ast.Node, query string, migrat
 			dt, isArray, _ := parseType(col.DataType)
 			notNull := col.NotNull
 			name := field.Name
-			result.Columns = append(result.Columns, core.Column{
+			result.Columns = append(result.Columns, &core.Column{
 				Name:         name,
 				OriginalName: field.Name,
 				DataType:     dt,
 				NotNull:      notNull,
 				IsArray:      isArray,
-				ArrayDims:    col.ArrayDims,
-				Table: &ast.TableName{
+				ArrayDims:    int32(col.ArrayDims),
+				Table: &core.Identifier{
 					Schema: tbl.SchemaName,
 					Name:   tbl.TableName,
 				},
@@ -271,13 +271,13 @@ func (a *Analyzer) Analyze(ctx context.Context, n ast.Node, query string, migrat
 			notNull := false
 			name := field.Name
 			dt, isArray, dims := parseType(dataType)
-			result.Columns = append(result.Columns, core.Column{
+			result.Columns = append(result.Columns, &core.Column{
 				Name:         name,
 				OriginalName: field.Name,
 				DataType:     dt,
 				NotNull:      notNull,
 				IsArray:      isArray,
-				ArrayDims:    dims,
+				ArrayDims:    int32(dims),
 			})
 		}
 	}
@@ -293,13 +293,13 @@ func (a *Analyzer) Analyze(ctx context.Context, n ast.Node, query string, migrat
 		if ps != nil {
 			name, _ = ps.NameFor(i + 1)
 		}
-		result.Params = append(result.Params, core.Parameter{
-			Number: i + 1,
+		result.Params = append(result.Params, &core.Parameter{
+			Number: int32(i + 1),
 			Column: &core.Column{
 				Name:      name,
 				DataType:  dt,
 				IsArray:   isArray,
-				ArrayDims: dims,
+				ArrayDims: int32(dims),
 				NotNull:   notNull,
 			},
 		})
diff --git a/internal/ext/wasm/wasm.go b/internal/ext/wasm/wasm.go
index 1a23b9c4b..a06d86796 100644
--- a/internal/ext/wasm/wasm.go
+++ b/internal/ext/wasm/wasm.go
@@ -20,6 +20,7 @@ import (
 	wasmtime "github.com/bytecodealliance/wasmtime-go/v13"
 	"golang.org/x/sync/singleflight"
 
+	"github.com/sqlc-dev/sqlc/internal/cache"
 	"github.com/sqlc-dev/sqlc/internal/info"
 	"github.com/sqlc-dev/sqlc/internal/plugin"
 )
@@ -76,16 +77,12 @@ func (r *Runner) loadSerializedModule(ctx context.Context, engine *wasmtime.Engi
 	if err != nil {
 		return nil, err
 	}
-	cacheRoot, err := cacheDir()
+	cacheDir, err := cache.PluginsDir()
 	if err != nil {
 		return nil, err
 	}
-	cache := filepath.Join(cacheRoot, "plugins")
-	if err := os.MkdirAll(cache, 0755); err != nil && !os.IsExist(err) {
-		return nil, fmt.Errorf("failed to create cache directory: %w", err)
-	}
 
-	pluginDir := filepath.Join(cache, expected)
+	pluginDir := filepath.Join(cacheDir, expected)
 	modName := fmt.Sprintf("plugin_%s_%s_%s.module", runtime.GOOS, runtime.GOARCH, wasmtimeVersion)
 	modPath := filepath.Join(pluginDir, modName)
 	_, staterr := os.Stat(modPath)
@@ -97,7 +94,7 @@ func (r *Runner) loadSerializedModule(ctx context.Context, engine *wasmtime.Engi
 		return data, nil
 	}
 
-	wmod, err := r.loadWASM(ctx, cache, expected)
+	wmod, err := r.loadWASM(ctx, cacheDir, expected)
 	if err != nil {
 		return nil, err
 	}
diff --git a/protos/analysis/analysis.proto b/protos/analysis/analysis.proto
new file mode 100644
index 000000000..39febb45c
--- /dev/null
+++ b/protos/analysis/analysis.proto
@@ -0,0 +1,41 @@
+syntax = "proto3";
+
+package analysis;
+
+option go_package = "github.com/sqlc-dev/sqlc/internal/analysis";
+
+message Identifier {
+	string catalog = 1;
+	string schema = 2;
+	string name = 3;
+}
+
+message Column {
+	string name = 1;
+	string original_name = 2;
+	string data_type = 3;
+	bool not_null = 4;
+	bool unsigned = 5;
+	bool is_array = 6;
+	int32 array_dims = 7;
+	string comment = 8;
+	int32 length = 9; // *int
+	bool is_named_param = 10;
+	bool is_func_call = 11;
+	string scope = 12;
+	Identifier table = 13;
+	string table_alias = 14;
+	Identifier type = 15;
+	Identifier embed_table = 16;
+	bool is_sqlc_slice = 17;
+}
+
+message Parameter {
+	int32 number = 1;
+	Column column = 2;
+}
+
+message Analysis {
+	repeated Column columns = 1;
+	repeated Parameter params = 2;
+}


Test patch:
diff --git a/internal/endtoend/ddl_test.go b/internal/endtoend/ddl_test.go
index 2ead5841c..c77389207 100644
--- a/internal/endtoend/ddl_test.go
+++ b/internal/endtoend/ddl_test.go
@@ -3,9 +3,9 @@ package main
 import (
 	"context"
 	"fmt"
-	"io/fs"
 	"os"
 	"path/filepath"
+	"slices"
 	"strings"
 	"testing"
 
@@ -32,28 +32,20 @@ func TestValidSchema(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	files := []string{}
+	for _, replay := range FindTests(t, "testdata", "managed-db") {
+		replay := replay // https://golang.org/doc/faq#closures_and_goroutines
 
-	// Find all tests that do not have a stderr.txt file
-	err = filepath.Walk("testdata", func(path string, info fs.FileInfo, err error) error {
-		if err != nil {
-			return err
+		if len(replay.Stderr) > 0 {
+			continue
 		}
-		if filepath.Base(path) == "sqlc.json" || filepath.Base(path) == "sqlc.yaml" || filepath.Base(path) == "sqlc.yml" {
-			stderr := filepath.Join(filepath.Dir(path), "stderr.txt")
-			if _, err := os.Stat(stderr); !os.IsNotExist(err) {
-				return nil
+
+		if replay.Exec != nil {
+			if !slices.Contains(replay.Exec.Contexts, "managed-db") {
+				continue
 			}
-			files = append(files, path)
 		}
-		return nil
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
 
-	for _, file := range files {
-		file := file // https://golang.org/doc/faq#closures_and_goroutines
+		file := filepath.Join(replay.Path, replay.ConfigName)
 		rd, err := os.Open(file)
 		if err != nil {
 			t.Fatal(err)
diff --git a/internal/endtoend/testdata/go.mod b/internal/endtoend/testdata/go.mod
index 535a3b8d2..e2a7ea704 100644
--- a/internal/endtoend/testdata/go.mod
+++ b/internal/endtoend/testdata/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853
 	github.com/jackc/pgtype v1.6.2
 	github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904
-	github.com/jackc/pgx/v5 v5.0.1
+	github.com/jackc/pgx/v5 v5.4.3
 	github.com/lib/pq v1.9.0
 	github.com/sqlc-dev/pqtype v0.2.0
 	github.com/sqlc-dev/sqlc-testdata v1.0.0
@@ -24,11 +24,12 @@ require (
 	github.com/jackc/pgio v1.0.0 // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
 	github.com/jackc/pgproto3/v2 v2.0.1 // indirect
-	github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
+	github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
+	github.com/pgvector/pgvector-go v0.1.1 // indirect
 	github.com/volatiletech/inflect v0.0.1 // indirect
 	github.com/volatiletech/randomize v0.0.1 // indirect
 	github.com/volatiletech/strmangle v0.0.1 // indirect
-	golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
-	golang.org/x/text v0.3.7 // indirect
-	golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
+	golang.org/x/crypto v0.9.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
+	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 )
diff --git a/internal/endtoend/testdata/go.sum b/internal/endtoend/testdata/go.sum
index a1cc05548..a5819e0a3 100644
--- a/internal/endtoend/testdata/go.sum
+++ b/internal/endtoend/testdata/go.sum
@@ -47,6 +47,8 @@ github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwX
 github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
 github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
 github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
 github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
 github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
 github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
@@ -64,6 +66,10 @@ github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904 h1:SdGWuGg+Cpxq6Z+A
 github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
 github.com/jackc/pgx/v5 v5.0.1 h1:JZu9othr7l8so2JMDAGeDUMXqERAuZpovyfl4H50tdg=
 github.com/jackc/pgx/v5 v5.0.1/go.mod h1:JBbvW3Hdw77jKl9uJrEDATUZIFM2VFPzRq4RWIhkF4o=
+github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
+github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
+github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
+github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
 github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
@@ -89,6 +95,8 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/pgvector/pgvector-go v0.1.1 h1:kqJigGctFnlWvskUiYIvJRNwUtQl/aMSUZVs0YWQe+g=
+github.com/pgvector/pgvector-go v0.1.1/go.mod h1:wLJgD/ODkdtd2LJK4l6evHXTuG+8PxymYAVomKHOWac=
 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -114,6 +122,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
 github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU=
 github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA=
@@ -140,6 +149,9 @@ golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
 golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -161,6 +173,10 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -173,6 +189,8 @@ golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
@@ -180,5 +198,6 @@ gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg=
 gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI=
 gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/db.go b/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/db.go
new file mode 100644
index 000000000..8a010ccc4
--- /dev/null
+++ b/internal/endtoend/testdata/pg_vector/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/pg_vector/postgresql/pgx/go/models.go b/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/models.go
new file mode 100644
index 000000000..23a8538ba
--- /dev/null
+++ b/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/models.go
@@ -0,0 +1,14 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+
+package querytest
+
+import (
+	"github.com/pgvector/pgvector-go"
+)
+
+type Item struct {
+	ID        int64
+	Embedding pgvector.Vector
+}
diff --git a/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/query.sql.go
new file mode 100644
index 000000000..44006cd19
--- /dev/null
+++ b/internal/endtoend/testdata/pg_vector/postgresql/pgx/go/query.sql.go
@@ -0,0 +1,48 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.22.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+
+	"github.com/pgvector/pgvector-go"
+)
+
+const insertVector = `-- name: InsertVector :exec
+INSERT INTO items (embedding) VALUES ($1)
+`
+
+func (q *Queries) InsertVector(ctx context.Context, embedding pgvector.Vector) error {
+	_, err := q.db.Exec(ctx, insertVector, embedding)
+	return err
+}
+
+const nearestNeighbor = `-- name: NearestNeighbor :many
+SELECT id, embedding
+FROM items
+ORDER BY embedding <-> $1
+LIMIT 5
+`
+
+func (q *Queries) NearestNeighbor(ctx context.Context, embedding pgvector.Vector) ([]Item, error) {
+	rows, err := q.db.Query(ctx, nearestNeighbor, embedding)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []Item
+	for rows.Next() {
+		var i Item
+		if err := rows.Scan(&i.ID, &i.Embedding); 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/pg_vector/postgresql/pgx/query.sql b/internal/endtoend/testdata/pg_vector/postgresql/pgx/query.sql
new file mode 100644
index 000000000..5bcc53958
--- /dev/null
+++ b/internal/endtoend/testdata/pg_vector/postgresql/pgx/query.sql
@@ -0,0 +1,8 @@
+-- name: InsertVector :exec
+INSERT INTO items (embedding) VALUES ($1);
+
+-- name: NearestNeighbor :many
+SELECT *
+FROM items
+ORDER BY embedding <-> $1
+LIMIT 5;
diff --git a/internal/endtoend/testdata/pg_vector/postgresql/pgx/schema.sql b/internal/endtoend/testdata/pg_vector/postgresql/pgx/schema.sql
new file mode 100644
index 000000000..a07840542
--- /dev/null
+++ b/internal/endtoend/testdata/pg_vector/postgresql/pgx/schema.sql
@@ -0,0 +1,3 @@
+CREATE EXTENSION IF NOT EXISTS "vector";
+
+CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
diff --git a/internal/endtoend/testdata/pg_vector/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/pg_vector/postgresql/pgx/sqlc.yaml
new file mode 100644
index 000000000..5dc63e3f9
--- /dev/null
+++ b/internal/endtoend/testdata/pg_vector/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"