Repository: sqlc-dev/sqlc
Pull request #2743 (2023-09-19 10:31:10)

build(deps): bump google.golang.org/grpc from 1.57.0 to 1.58.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.57.0 to 1.58.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p>
<blockquote>
<h2>Release 1.58.1</h2>
<h1>Bug Fixes</h1>
<ul>
<li>grpc: fix a bug that was decrementing active RPC count too early for streaming RPCs; leading to channel moving to IDLE even though it had open streams</li>
<li>grpc: fix a bug where transports were not being closed upon channel entering IDLE</li>
</ul>
<h2>Release 1.58.0</h2>
<h1>API Changes</h1>
<p>See <a href="https://redirect.github.com/grpc/grpc-go/issues/6472">#6472</a> for details about these changes.</p>
<ul>
<li>balancer: add <code>StateListener</code> to <code>NewSubConnOptions</code> for <code>SubConn</code> state updates and deprecate <code>Balancer.UpdateSubConnState</code> (<a href="https://redirect.github.com/grpc/grpc-go/issues/6481">#6481</a>)
<ul>
<li><code>UpdateSubConnState</code> will be deleted in the future.</li>
</ul>
</li>
<li>balancer: add <code>SubConn.Shutdown</code> and deprecate <code>Balancer.RemoveSubConn</code> (<a href="https://redirect.github.com/grpc/grpc-go/issues/6493">#6493</a>)
<ul>
<li><code>RemoveSubConn</code> will be deleted in the future.</li>
</ul>
</li>
<li>resolver: remove deprecated <code>AddressType</code> (<a href="https://redirect.github.com/grpc/grpc-go/issues/6451">#6451</a>)
<ul>
<li>This was previously used as a signal to enable the &quot;grpclb&quot; load balancing policy, and to pass LB addresses to the policy.  Instead, <code>balancer/grpclb/state.Set()</code> should be used to add these addresses to the name resolver's output.  The built-in &quot;dns&quot; name resolver already does this.</li>
</ul>
</li>
<li>resolver: add new field <code>Endpoints</code> to <code>State</code> and deprecate <code>Addresses</code> (<a href="https://redirect.github.com/grpc/grpc-go/issues/6471">#6471</a>)
<ul>
<li><code>Addresses</code> will be deleted in the future.</li>
</ul>
</li>
</ul>
<h1>New Features</h1>
<ul>
<li>balancer/leastrequest: Add experimental support for least request LB policy and least request configured as a custom xDS policy (<a href="https://redirect.github.com/grpc/grpc-go/issues/6510">#6510</a>, <a href="https://redirect.github.com/grpc/grpc-go/issues/6517">#6517</a>)
<ul>
<li>Set <code>GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST=true</code> to enable</li>
</ul>
</li>
<li>stats: Add an RPC event for blocking caused by the LB policy's picker (<a href="https://redirect.github.com/grpc/grpc-go/issues/6422">#6422</a>)</li>
</ul>
<h1>Bug Fixes</h1>
<ul>
<li>clusterresolver: fix deadlock when dns resolver responds inline with update or error at build time (<a href="https://redirect.github.com/grpc/grpc-go/issues/6563">#6563</a>)</li>
<li>grpc: fix a bug where the channel could erroneously report <code>TRANSIENT_FAILURE</code> when actually moving to <code>IDLE</code> (<a href="https://redirect.github.com/grpc/grpc-go/issues/6497">#6497</a>)</li>
<li>balancergroup: do not cache closed sub-balancers by default; affects <code>rls</code>, <code>weightedtarget</code> and <code>clustermanager</code> LB policies (<a href="https://redirect.github.com/grpc/grpc-go/issues/6523">#6523</a>)</li>
<li>client: fix a bug that prevented detection of RPC status in trailers-only RPC responses when using <code>ClientStream.Header()</code>, and prevented retry of the RPC (<a href="https://redirect.github.com/grpc/grpc-go/issues/6557">#6557</a>)</li>
</ul>
<h1>Performance Improvements</h1>
<ul>
<li>client &amp; server: Add experimental <code>[With]SharedWriteBuffer</code> to improve performance by reducing allocations when sending RPC messages. (Disabled by default.) (<a href="https://redirect.github.com/grpc/grpc-go/issues/6309">#6309</a>)
<ul>
<li>Special Thanks: <a href="https://github.com/s-matyukevich"><code>@​s-matyukevich</code></a></li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/grpc/grpc-go/commit/62726d4336c675cb45b65cded43838a85f1cbc25"><code>62726d4</code></a> update version to 1.58.1 (<a href="https://redirect.github.com/grpc/grpc-go/issues/6629">#6629</a>)</li>
<li><a href="https://github.com/grpc/grpc-go/commit/fa6d9abecbece2f326e7d91084bf3654bb87a42d"><code>fa6d9ab</code></a> cherry-pick 6610 and 6620 (<a href="https://redirect.github.com/grpc/grpc-go/issues/6627">#6627</a>)</li>
<li><a href="https://github.com/grpc/grpc-go/commit/467fbf2a55aaae1e88ca313a7e0571f88c910cb6"><code>467fbf2</code></a> Change version to 1.58.1-dev (<a href="https://redirect.github.com/grpc/grpc-go/issues/6580">#6580</a>)</li>
<li><a href="https://github.com/grpc/grpc-go/commit/c2b0797a5353b29ca02869629c83151c980a6e31"><code>c2b0797</code></a> Change version to 1.58.0 (<a href="https://redirect.github.com/grpc/grpc-go/issues/6579">#6579</a>)</li>
<li><a href="https://github.com/grpc/grpc-go/commit/0467e471c2da6b87363c7ca5e2acbbaf40fb7189"><code>0467e47</code></a> balancer/leastrequest: Cache atomic load and also add concurrent rpc test (<a href="https://redirect.github.com/grpc/grpc-go/issues/6">#6</a>...</li>
<li><a href="https://github.com/grpc/grpc-go/commit/5d1c0ae143ba03cfe6116d899762d9f6dfb50a71"><code>5d1c0ae</code></a> leastrequest: fix data race in leastrequest picker (<a href="https://redirect.github.com/grpc/grpc-go/issues/6606">#6606</a>)</li>
<li><a href="https://github.com/grpc/grpc-go/commit/e26457d0c976a5669aea35e3f97889c576324983"><code>e26457d</code></a> stream: swallow Header errors as we used to; RecvMsg can still return it (<a href="https://redirect.github.com/grpc/grpc-go/issues/6591">#6591</a>)</li>
<li><a href="https://github.com/grpc/grpc-go/commit/4c9777ceff549b54cf37acc64504a10f786c58e2"><code>4c9777c</code></a> clusterresolver: fix deadlock when dns resolver responds inline with update o...</li>
<li><a href="https://github.com/grpc/grpc-go/commit/81b9df233eb48a223f6915be450a34d4ab4b0760"><code>81b9df2</code></a> idle: move idleness manager to separate package and ~13s of tests into it (<a href="https://redirect.github.com/grpc/grpc-go/issues/6">#6</a>...</li>
<li><a href="https://github.com/grpc/grpc-go/commit/7d35b8ece0131eb23b5069de26ca067fd76e4da2"><code>7d35b8e</code></a> test: speed up TestServiceConfigTimeoutTD from 1.8s to 0.03s (<a href="https://redirect.github.com/grpc/grpc-go/issues/6571">#6571</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/grpc/grpc-go/compare/v1.57.0...v1.58.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.57.0&new-version=1.58.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3706e74b6..6fe347097 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -76,6 +76,8 @@ jobs:
         MYSQL_HOST: localhost
         MYSQL_PORT: ${{ job.services.mysql.ports['3306'] }}
         MYSQL_ROOT_PASSWORD: mysecretpassword
+        CI_SQLC_PROJECT_ID: ${{ secrets.CI_SQLC_PROJECT_ID }}
+        CI_SQLC_AUTH_TOKEN: ${{ secrets.CI_SQLC_AUTH_TOKEN }}
 
     - name: build internal/endtoend
       run: go build ./...
diff --git a/go.mod b/go.mod
index 18da48b61..02122b31f 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
 	github.com/spf13/pflag v1.0.5
 	github.com/xeipuuv/gojsonschema v1.2.0
 	golang.org/x/sync v0.3.0
-	google.golang.org/grpc v1.57.0
+	google.golang.org/grpc v1.58.1
 	google.golang.org/protobuf v1.31.0
 	gopkg.in/yaml.v3 v3.0.1
 )
@@ -56,10 +56,10 @@ require (
 	go.uber.org/atomic v1.11.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.25.0 // indirect
-	golang.org/x/crypto v0.9.0 // indirect
+	golang.org/x/crypto v0.11.0 // indirect
 	golang.org/x/exp v0.0.0-20230724220655-d98519c11495 // indirect
-	golang.org/x/net v0.10.0 // indirect
-	golang.org/x/sys v0.8.0 // indirect
+	golang.org/x/net v0.12.0 // indirect
+	golang.org/x/sys v0.10.0 // indirect
 	golang.org/x/text v0.12.0 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 3aa6805e2..a8a27a1ff 100644
--- a/go.sum
+++ b/go.sum
@@ -227,8 +227,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 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/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
 golang.org/x/exp v0.0.0-20230724220655-d98519c11495 h1:zKGKw2WlGb8oPoRGqQ2PT8g2YoCN1w/YbbQjHXCdUWE=
 golang.org/x/exp v0.0.0-20230724220655-d98519c11495/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -242,8 +242,8 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
+golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
@@ -263,8 +263,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -299,8 +299,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I=
-google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
-google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
+google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58=
+google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/internal/quickdb/region.go b/internal/quickdb/region.go
new file mode 100644
index 000000000..bc03e3b3f
--- /dev/null
+++ b/internal/quickdb/region.go
@@ -0,0 +1,19 @@
+package quickdb
+
+import (
+	"net/http"
+	"sync"
+)
+
+var region string
+var once sync.Once
+
+func GetClosestRegion() string {
+	once.Do(func() {
+		resp, err := http.Get("https://debug.fly.dev")
+		if err == nil {
+			region = resp.Header.Get("Fly-Region")
+		}
+	})
+	return region
+}
diff --git a/internal/quickdb/rpc.go b/internal/quickdb/rpc.go
new file mode 100644
index 000000000..c1f9ffd4c
--- /dev/null
+++ b/internal/quickdb/rpc.go
@@ -0,0 +1,57 @@
+package quickdb
+
+import (
+	"crypto/tls"
+	"os"
+
+	"github.com/riza-io/grpc-go/credentials/basic"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
+
+	"github.com/sqlc-dev/sqlc/internal/config"
+	pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1"
+)
+
+const defaultHostname = "grpc.sqlc.dev"
+
+func NewClientFromConfig(cloudConfig config.Cloud) (pb.QuickClient, error) {
+	projectID := cloudConfig.Project
+	authToken := os.Getenv("SQLC_AUTH_TOKEN")
+	return NewClient(projectID, authToken, WithHost(cloudConfig.Hostname))
+}
+
+type options struct {
+	hostname string
+}
+
+type Option func(*options)
+
+func WithHost(host string) Option {
+	return func(o *options) {
+		o.hostname = host
+	}
+}
+
+func NewClient(project, token string, opts ...Option) (pb.QuickClient, error) {
+	var o options
+	for _, apply := range opts {
+		apply(&o)
+	}
+
+	dialOpts := []grpc.DialOption{
+		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
+		grpc.WithPerRPCCredentials(basic.NewPerRPCCredentials(project, token)),
+	}
+
+	hostname := o.hostname
+	if hostname == "" {
+		hostname = defaultHostname
+	}
+
+	conn, err := grpc.Dial(hostname+":443", dialOpts...)
+	if err != nil {
+		return nil, err
+	}
+
+	return pb.NewQuickClient(conn), nil
+}
diff --git a/internal/quickdb/v1/quickdb.pb.go b/internal/quickdb/v1/quickdb.pb.go
new file mode 100755
index 000000000..7bdec9974
--- /dev/null
+++ b/internal/quickdb/v1/quickdb.pb.go
@@ -0,0 +1,507 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.30.0
+// 	protoc        v3.21.7
+// source: proto/quickdb/v1/quickdb.proto
+
+package v1
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	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 CreateEphemeralDatabaseRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Region     string   `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"`
+	Engine     string   `protobuf:"bytes,2,opt,name=engine,proto3" json:"engine,omitempty"`
+	ServerId   string   `protobuf:"bytes,3,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"`
+	Migrations []string `protobuf:"bytes,4,rep,name=migrations,proto3" json:"migrations,omitempty"`
+}
+
+func (x *CreateEphemeralDatabaseRequest) Reset() {
+	*x = CreateEphemeralDatabaseRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_proto_quickdb_v1_quickdb_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CreateEphemeralDatabaseRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateEphemeralDatabaseRequest) ProtoMessage() {}
+
+func (x *CreateEphemeralDatabaseRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_proto_quickdb_v1_quickdb_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 CreateEphemeralDatabaseRequest.ProtoReflect.Descriptor instead.
+func (*CreateEphemeralDatabaseRequest) Descriptor() ([]byte, []int) {
+	return file_proto_quickdb_v1_quickdb_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateEphemeralDatabaseRequest) GetRegion() string {
+	if x != nil {
+		return x.Region
+	}
+	return ""
+}
+
+func (x *CreateEphemeralDatabaseRequest) GetEngine() string {
+	if x != nil {
+		return x.Engine
+	}
+	return ""
+}
+
+func (x *CreateEphemeralDatabaseRequest) GetServerId() string {
+	if x != nil {
+		return x.ServerId
+	}
+	return ""
+}
+
+func (x *CreateEphemeralDatabaseRequest) GetMigrations() []string {
+	if x != nil {
+		return x.Migrations
+	}
+	return nil
+}
+
+type CreateEphemeralDatabaseResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	DatabaseId string `protobuf:"bytes,1,opt,name=database_id,json=databaseId,proto3" json:"database_id,omitempty"`
+	Uri        string `protobuf:"bytes,2,opt,name=uri,proto3" json:"uri,omitempty"`
+}
+
+func (x *CreateEphemeralDatabaseResponse) Reset() {
+	*x = CreateEphemeralDatabaseResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_proto_quickdb_v1_quickdb_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CreateEphemeralDatabaseResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateEphemeralDatabaseResponse) ProtoMessage() {}
+
+func (x *CreateEphemeralDatabaseResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_proto_quickdb_v1_quickdb_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 CreateEphemeralDatabaseResponse.ProtoReflect.Descriptor instead.
+func (*CreateEphemeralDatabaseResponse) Descriptor() ([]byte, []int) {
+	return file_proto_quickdb_v1_quickdb_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateEphemeralDatabaseResponse) GetDatabaseId() string {
+	if x != nil {
+		return x.DatabaseId
+	}
+	return ""
+}
+
+func (x *CreateEphemeralDatabaseResponse) GetUri() string {
+	if x != nil {
+		return x.Uri
+	}
+	return ""
+}
+
+type DropEphemeralDatabaseRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	DatabaseId string `protobuf:"bytes,1,opt,name=database_id,json=databaseId,proto3" json:"database_id,omitempty"`
+}
+
+func (x *DropEphemeralDatabaseRequest) Reset() {
+	*x = DropEphemeralDatabaseRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_proto_quickdb_v1_quickdb_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *DropEphemeralDatabaseRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DropEphemeralDatabaseRequest) ProtoMessage() {}
+
+func (x *DropEphemeralDatabaseRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_proto_quickdb_v1_quickdb_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 DropEphemeralDatabaseRequest.ProtoReflect.Descriptor instead.
+func (*DropEphemeralDatabaseRequest) Descriptor() ([]byte, []int) {
+	return file_proto_quickdb_v1_quickdb_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *DropEphemeralDatabaseRequest) GetDatabaseId() string {
+	if x != nil {
+		return x.DatabaseId
+	}
+	return ""
+}
+
+type DropEphemeralDatabaseResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *DropEphemeralDatabaseResponse) Reset() {
+	*x = DropEphemeralDatabaseResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_proto_quickdb_v1_quickdb_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *DropEphemeralDatabaseResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DropEphemeralDatabaseResponse) ProtoMessage() {}
+
+func (x *DropEphemeralDatabaseResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_proto_quickdb_v1_quickdb_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 DropEphemeralDatabaseResponse.ProtoReflect.Descriptor instead.
+func (*DropEphemeralDatabaseResponse) Descriptor() ([]byte, []int) {
+	return file_proto_quickdb_v1_quickdb_proto_rawDescGZIP(), []int{3}
+}
+
+var File_proto_quickdb_v1_quickdb_proto protoreflect.FileDescriptor
+
+var file_proto_quickdb_v1_quickdb_proto_rawDesc = []byte{
+	0x0a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x64, 0x62, 0x2f,
+	0x76, 0x31, 0x2f, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x64, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x12, 0x1a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x73, 0x71, 0x6c, 0x63, 0x2e, 0x64, 0x65,
+	0x76, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x22, 0x8d, 0x01, 0x0a,
+	0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c,
+	0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x67, 0x69, 0x6e,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x12,
+	0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a,
+	0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09,
+	0x52, 0x0a, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x54, 0x0a, 0x1f,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x44,
+	0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x49, 0x64,
+	0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,
+	0x72, 0x69, 0x22, 0x3f, 0x0a, 0x1c, 0x44, 0x72, 0x6f, 0x70, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65,
+	0x72, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73,
+	0x65, 0x49, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x44, 0x72, 0x6f, 0x70, 0x45, 0x70, 0x68, 0x65, 0x6d,
+	0x65, 0x72, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x32, 0xab, 0x02, 0x0a, 0x05, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x12, 0x92,
+	0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72,
+	0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x3a, 0x2e, 0x72, 0x65, 0x6d,
+	0x6f, 0x74, 0x65, 0x2e, 0x73, 0x71, 0x6c, 0x63, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x71, 0x75, 0x69,
+	0x63, 0x6b, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x70,
+	0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e,
+	0x73, 0x71, 0x6c, 0x63, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x64, 0x62,
+	0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65,
+	0x72, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x15, 0x44, 0x72, 0x6f, 0x70, 0x45, 0x70, 0x68, 0x65,
+	0x6d, 0x65, 0x72, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x38, 0x2e,
+	0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x73, 0x71, 0x6c, 0x63, 0x2e, 0x64, 0x65, 0x76, 0x2e,
+	0x71, 0x75, 0x69, 0x63, 0x6b, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x45,
+	0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65,
+	0x2e, 0x73, 0x71, 0x6c, 0x63, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x64,
+	0x62, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x45, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72,
+	0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_proto_quickdb_v1_quickdb_proto_rawDescOnce sync.Once
+	file_proto_quickdb_v1_quickdb_proto_rawDescData = file_proto_quickdb_v1_quickdb_proto_rawDesc
+)
+
+func file_proto_quickdb_v1_quickdb_proto_rawDescGZIP() []byte {
+	file_proto_quickdb_v1_quickdb_proto_rawDescOnce.Do(func() {
+		file_proto_quickdb_v1_quickdb_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_quickdb_v1_quickdb_proto_rawDescData)
+	})
+	return file_proto_quickdb_v1_quickdb_proto_rawDescData
+}
+
+var file_proto_quickdb_v1_quickdb_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_proto_quickdb_v1_quickdb_proto_goTypes = []interface{}{
+	(*CreateEphemeralDatabaseRequest)(nil),  // 0: remote.sqlc.dev.quickdb.v1.CreateEphemeralDatabaseRequest
+	(*CreateEphemeralDatabaseResponse)(nil), // 1: remote.sqlc.dev.quickdb.v1.CreateEphemeralDatabaseResponse
+	(*DropEphemeralDatabaseRequest)(nil),    // 2: remote.sqlc.dev.quickdb.v1.DropEphemeralDatabaseRequest
+	(*DropEphemeralDatabaseResponse)(nil),   // 3: remote.sqlc.dev.quickdb.v1.DropEphemeralDatabaseResponse
+}
+var file_proto_quickdb_v1_quickdb_proto_depIdxs = []int32{
+	0, // 0: remote.sqlc.dev.quickdb.v1.Quick.CreateEphemeralDatabase:input_type -> remote.sqlc.dev.quickdb.v1.CreateEphemeralDatabaseRequest
+	2, // 1: remote.sqlc.dev.quickdb.v1.Quick.DropEphemeralDatabase:input_type -> remote.sqlc.dev.quickdb.v1.DropEphemeralDatabaseRequest
+	1, // 2: remote.sqlc.dev.quickdb.v1.Quick.CreateEphemeralDatabase:output_type -> remote.sqlc.dev.quickdb.v1.CreateEphemeralDatabaseResponse
+	3, // 3: remote.sqlc.dev.quickdb.v1.Quick.DropEphemeralDatabase:output_type -> remote.sqlc.dev.quickdb.v1.DropEphemeralDatabaseResponse
+	2, // [2:4] is the sub-list for method output_type
+	0, // [0:2] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_proto_quickdb_v1_quickdb_proto_init() }
+func file_proto_quickdb_v1_quickdb_proto_init() {
+	if File_proto_quickdb_v1_quickdb_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_proto_quickdb_v1_quickdb_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreateEphemeralDatabaseRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_proto_quickdb_v1_quickdb_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreateEphemeralDatabaseResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_proto_quickdb_v1_quickdb_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DropEphemeralDatabaseRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_proto_quickdb_v1_quickdb_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DropEphemeralDatabaseResponse); 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_proto_quickdb_v1_quickdb_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   4,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_proto_quickdb_v1_quickdb_proto_goTypes,
+		DependencyIndexes: file_proto_quickdb_v1_quickdb_proto_depIdxs,
+		MessageInfos:      file_proto_quickdb_v1_quickdb_proto_msgTypes,
+	}.Build()
+	File_proto_quickdb_v1_quickdb_proto = out.File
+	file_proto_quickdb_v1_quickdb_proto_rawDesc = nil
+	file_proto_quickdb_v1_quickdb_proto_goTypes = nil
+	file_proto_quickdb_v1_quickdb_proto_depIdxs = nil
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConnInterface
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion6
+
+// QuickClient is the client API for Quick service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type QuickClient interface {
+	CreateEphemeralDatabase(ctx context.Context, in *CreateEphemeralDatabaseRequest, opts ...grpc.CallOption) (*CreateEphemeralDatabaseResponse, error)
+	DropEphemeralDatabase(ctx context.Context, in *DropEphemeralDatabaseRequest, opts ...grpc.CallOption) (*DropEphemeralDatabaseResponse, error)
+}
+
+type quickClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewQuickClient(cc grpc.ClientConnInterface) QuickClient {
+	return &quickClient{cc}
+}
+
+func (c *quickClient) CreateEphemeralDatabase(ctx context.Context, in *CreateEphemeralDatabaseRequest, opts ...grpc.CallOption) (*CreateEphemeralDatabaseResponse, error) {
+	out := new(CreateEphemeralDatabaseResponse)
+	err := c.cc.Invoke(ctx, "/remote.sqlc.dev.quickdb.v1.Quick/CreateEphemeralDatabase", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *quickClient) DropEphemeralDatabase(ctx context.Context, in *DropEphemeralDatabaseRequest, opts ...grpc.CallOption) (*DropEphemeralDatabaseResponse, error) {
+	out := new(DropEphemeralDatabaseResponse)
+	err := c.cc.Invoke(ctx, "/remote.sqlc.dev.quickdb.v1.Quick/DropEphemeralDatabase", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// QuickServer is the server API for Quick service.
+type QuickServer interface {
+	CreateEphemeralDatabase(context.Context, *CreateEphemeralDatabaseRequest) (*CreateEphemeralDatabaseResponse, error)
+	DropEphemeralDatabase(context.Context, *DropEphemeralDatabaseRequest) (*DropEphemeralDatabaseResponse, error)
+}
+
+// UnimplementedQuickServer can be embedded to have forward compatible implementations.
+type UnimplementedQuickServer struct {
+}
+
+func (*UnimplementedQuickServer) CreateEphemeralDatabase(context.Context, *CreateEphemeralDatabaseRequest) (*CreateEphemeralDatabaseResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method CreateEphemeralDatabase not implemented")
+}
+func (*UnimplementedQuickServer) DropEphemeralDatabase(context.Context, *DropEphemeralDatabaseRequest) (*DropEphemeralDatabaseResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method DropEphemeralDatabase not implemented")
+}
+
+func RegisterQuickServer(s *grpc.Server, srv QuickServer) {
+	s.RegisterService(&_Quick_serviceDesc, srv)
+}
+
+func _Quick_CreateEphemeralDatabase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(CreateEphemeralDatabaseRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QuickServer).CreateEphemeralDatabase(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/remote.sqlc.dev.quickdb.v1.Quick/CreateEphemeralDatabase",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QuickServer).CreateEphemeralDatabase(ctx, req.(*CreateEphemeralDatabaseRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Quick_DropEphemeralDatabase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DropEphemeralDatabaseRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(QuickServer).DropEphemeralDatabase(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/remote.sqlc.dev.quickdb.v1.Quick/DropEphemeralDatabase",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(QuickServer).DropEphemeralDatabase(ctx, req.(*DropEphemeralDatabaseRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _Quick_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "remote.sqlc.dev.quickdb.v1.Quick",
+	HandlerType: (*QuickServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "CreateEphemeralDatabase",
+			Handler:    _Quick_CreateEphemeralDatabase_Handler,
+		},
+		{
+			MethodName: "DropEphemeralDatabase",
+			Handler:    _Quick_DropEphemeralDatabase_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "proto/quickdb/v1/quickdb.proto",
+}


Test patch:
diff --git a/examples/authors/postgresql/db_test.go b/examples/authors/postgresql/db_test.go
index 150c11861..d2df436ae 100644
--- a/examples/authors/postgresql/db_test.go
+++ b/examples/authors/postgresql/db_test.go
@@ -8,25 +8,31 @@ import (
 	"database/sql"
 	"testing"
 
-	"github.com/sqlc-dev/sqlc/internal/sqltest"
+	_ "github.com/lib/pq"
+
+	"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
 )
 
 func TestAuthors(t *testing.T) {
-	sdb, cleanup := sqltest.PostgreSQL(t, []string{"schema.sql"})
-	defer cleanup()
+	uri := hosted.PostgreSQL(t, []string{"schema.sql"})
+	db, err := sql.Open("postgres", uri)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer db.Close()
 
 	ctx := context.Background()
-	db := New(sdb)
+	q := New(db)
 
 	// list all authors
-	authors, err := db.ListAuthors(ctx)
+	authors, err := q.ListAuthors(ctx)
 	if err != nil {
 		t.Fatal(err)
 	}
 	t.Log(authors)
 
 	// create an author
-	insertedAuthor, err := db.CreateAuthor(ctx, CreateAuthorParams{
+	insertedAuthor, err := q.CreateAuthor(ctx, CreateAuthorParams{
 		Name: "Brian Kernighan",
 		Bio:  sql.NullString{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true},
 	})
@@ -36,7 +42,7 @@ func TestAuthors(t *testing.T) {
 	t.Log(insertedAuthor)
 
 	// get the author we just inserted
-	fetchedAuthor, err := db.GetAuthor(ctx, insertedAuthor.ID)
+	fetchedAuthor, err := q.GetAuthor(ctx, insertedAuthor.ID)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/examples/batch/postgresql/db_test.go b/examples/batch/postgresql/db_test.go
index 9395e4c20..fd3ce4e72 100644
--- a/examples/batch/postgresql/db_test.go
+++ b/examples/batch/postgresql/db_test.go
@@ -8,14 +8,21 @@ import (
 	"testing"
 	"time"
 
-	"github.com/sqlc-dev/sqlc/internal/sqltest"
+	"github.com/jackc/pgx/v4"
+	"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
 )
 
 func TestBatchBooks(t *testing.T) {
-	db, cleanup := sqltest.PostgreSQLPgx(t, []string{"schema.sql"})
-	defer cleanup()
+	uri := hosted.PostgreSQL(t, []string{"schema.sql"})
 
 	ctx := context.Background()
+
+	db, err := pgx.Connect(ctx, uri)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer db.Close(ctx)
+
 	dq := New(db)
 
 	// create an author
diff --git a/examples/booktest/postgresql/db_test.go b/examples/booktest/postgresql/db_test.go
index 440198d0e..9716f5684 100644
--- a/examples/booktest/postgresql/db_test.go
+++ b/examples/booktest/postgresql/db_test.go
@@ -5,15 +5,22 @@ package booktest
 
 import (
 	"context"
+	"database/sql"
 	"testing"
 	"time"
 
-	"github.com/sqlc-dev/sqlc/internal/sqltest"
+	_ "github.com/lib/pq"
+
+	"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
 )
 
 func TestBooks(t *testing.T) {
-	db, cleanup := sqltest.PostgreSQL(t, []string{"schema.sql"})
-	defer cleanup()
+	uri := hosted.PostgreSQL(t, []string{"schema.sql"})
+	db, err := sql.Open("postgres", uri)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer db.Close()
 
 	ctx := context.Background()
 	dq := New(db)
diff --git a/examples/ondeck/postgresql/db_test.go b/examples/ondeck/postgresql/db_test.go
index fd16a4948..c4e4ce8bb 100644
--- a/examples/ondeck/postgresql/db_test.go
+++ b/examples/ondeck/postgresql/db_test.go
@@ -5,11 +5,13 @@ package ondeck
 
 import (
 	"context"
+	"database/sql"
 	"testing"
 
-	"github.com/sqlc-dev/sqlc/internal/sqltest"
-
 	"github.com/google/go-cmp/cmp"
+	_ "github.com/lib/pq"
+
+	"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
 )
 
 func runOnDeckQueries(t *testing.T, q *Queries) {
@@ -124,10 +126,14 @@ func runOnDeckQueries(t *testing.T, q *Queries) {
 func TestPrepared(t *testing.T) {
 	t.Parallel()
 
-	sdb, cleanup := sqltest.PostgreSQL(t, []string{"schema"})
-	defer cleanup()
+	uri := hosted.PostgreSQL(t, []string{"schema"})
+	db, err := sql.Open("postgres", uri)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer db.Close()
 
-	q, err := Prepare(context.Background(), sdb)
+	q, err := Prepare(context.Background(), db)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -138,8 +144,12 @@ func TestPrepared(t *testing.T) {
 func TestQueries(t *testing.T) {
 	t.Parallel()
 
-	sdb, cleanup := sqltest.PostgreSQL(t, []string{"schema"})
-	defer cleanup()
+	uri := hosted.PostgreSQL(t, []string{"schema"})
+	db, err := sql.Open("postgres", uri)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer db.Close()
 
-	runOnDeckQueries(t, New(sdb))
+	runOnDeckQueries(t, New(db))
 }
diff --git a/internal/endtoend/ddl_test.go b/internal/endtoend/ddl_test.go
new file mode 100644
index 000000000..123a503ce
--- /dev/null
+++ b/internal/endtoend/ddl_test.go
@@ -0,0 +1,134 @@
+package main
+
+import (
+	"context"
+	"fmt"
+	"io/fs"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+
+	"github.com/jackc/pgx/v5"
+
+	"github.com/sqlc-dev/sqlc/internal/config"
+	"github.com/sqlc-dev/sqlc/internal/migrations"
+	"github.com/sqlc-dev/sqlc/internal/quickdb"
+	pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1"
+	"github.com/sqlc-dev/sqlc/internal/sql/sqlpath"
+)
+
+func TestValidSchema(t *testing.T) {
+	ctx := context.Background()
+
+	projectID := os.Getenv("CI_SQLC_PROJECT_ID")
+	authToken := os.Getenv("CI_SQLC_AUTH_TOKEN")
+
+	if projectID == "" || authToken == "" {
+		if os.Getenv("CI") == "" {
+			t.Skip("skiping ddl tests outside of CI")
+		} else {
+			t.Fatal("missing project id and auth token")
+		}
+	}
+
+	client, err := quickdb.NewClient(projectID, authToken)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	files := []string{}
+
+	// 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 filepath.Base(path) == "sqlc.json" || filepath.Base(path) == "sqlc.yaml" {
+			stderr := filepath.Join(filepath.Dir(path), "stderr.txt")
+			if _, err := os.Stat(stderr); !os.IsNotExist(err) {
+				return nil
+			}
+			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
+		rd, err := os.Open(file)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		conf, err := config.ParseConfig(rd)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		for j, pkg := range conf.SQL {
+			j, pkg := j, pkg
+			if pkg.Engine != config.EnginePostgreSQL {
+				continue
+			}
+			t.Run(fmt.Sprintf("endtoend-%s-%d", file, j), func(t *testing.T) {
+				t.Parallel()
+
+				if strings.Contains(file, "pg_dump") {
+					t.Skip("loading pg_dump not supported")
+				}
+
+				var schema []string
+				for _, path := range pkg.Schema {
+					schema = append(schema, filepath.Join(filepath.Dir(file), path))
+				}
+
+				files, err := sqlpath.Glob(schema)
+				if err != nil {
+					t.Fatal(err)
+				}
+
+				var sqls []string
+				for _, f := range files {
+					contents, err := os.ReadFile(f)
+					if err != nil {
+						t.Fatalf("%s: %s", f, err)
+					}
+					// TODO: Split schema into separate files
+					before, _, _ := strings.Cut(string(contents), "-- name:")
+					before, _, _ = strings.Cut(before, "/* name:")
+					// Support loading pg_dump SQL files
+					before = strings.ReplaceAll(before, "CREATE SCHEMA public;", "CREATE SCHEMA IF NOT EXISTS public;")
+					sqls = append(sqls, migrations.RemoveRollbackStatements(before))
+				}
+
+				resp, err := client.CreateEphemeralDatabase(ctx, &pb.CreateEphemeralDatabaseRequest{
+					Engine:     "postgresql",
+					Region:     quickdb.GetClosestRegion(),
+					Migrations: sqls,
+				})
+				if err != nil {
+					t.Fatalf("region %s: %s", quickdb.GetClosestRegion(), err)
+				}
+
+				t.Cleanup(func() {
+					_, err = client.DropEphemeralDatabase(ctx, &pb.DropEphemeralDatabaseRequest{
+						DatabaseId: resp.DatabaseId,
+					})
+					if err != nil {
+						t.Fatal(err)
+					}
+				})
+
+				conn, err := pgx.Connect(ctx, resp.Uri)
+				if err != nil {
+					t.Fatalf("connect %s: %s", resp.Uri, err)
+				}
+				defer conn.Close(ctx)
+			})
+		}
+	}
+}
diff --git a/internal/sqltest/hosted/db.go b/internal/sqltest/hosted/db.go
new file mode 100644
index 000000000..4d2fe8dc8
--- /dev/null
+++ b/internal/sqltest/hosted/db.go
@@ -0,0 +1,78 @@
+package hosted
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"sync"
+	"testing"
+
+	"github.com/sqlc-dev/sqlc/internal/quickdb"
+	pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1"
+	"github.com/sqlc-dev/sqlc/internal/sql/sqlpath"
+)
+
+var client pb.QuickClient
+var once sync.Once
+
+func initClient() error {
+	projectID := os.Getenv("CI_SQLC_PROJECT_ID")
+	authToken := os.Getenv("CI_SQLC_AUTH_TOKEN")
+	if projectID == "" || authToken == "" {
+		return fmt.Errorf("missing project id or auth token")
+	}
+	c, err := quickdb.NewClient(projectID, authToken)
+	if err != nil {
+		return err
+	}
+	client = c
+	return nil
+}
+
+func PostgreSQL(t *testing.T, migrations []string) string {
+	ctx := context.Background()
+	t.Helper()
+
+	once.Do(func() {
+		if err := initClient(); err != nil {
+			t.Fatal(err)
+		}
+	})
+
+	if client == nil {
+		t.Fatalf("client init failed")
+	}
+
+	var seed []string
+	files, err := sqlpath.Glob(migrations)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, f := range files {
+		blob, err := os.ReadFile(f)
+		if err != nil {
+			t.Fatal(err)
+		}
+		seed = append(seed, string(blob))
+	}
+
+	resp, err := client.CreateEphemeralDatabase(ctx, &pb.CreateEphemeralDatabaseRequest{
+		Engine:     "postgresql",
+		Region:     quickdb.GetClosestRegion(),
+		Migrations: seed,
+	})
+	if err != nil {
+		t.Fatalf("region %s: %s", quickdb.GetClosestRegion(), err)
+	}
+
+	t.Cleanup(func() {
+		_, err = client.DropEphemeralDatabase(ctx, &pb.DropEphemeralDatabaseRequest{
+			DatabaseId: resp.DatabaseId,
+		})
+		if err != nil {
+			t.Fatal(err)
+		}
+	})
+
+	return resp.Uri
+}