Repository: supabase/cli
Pull request #2021 (2024-03-06 15:23:20)

feat: use binary protocol when connecting to remote
## What kind of change does this PR introduce?

Bug fix

## What is the new behavior?

Binary protocol supports [pipeline mode](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html) with performance gains for large batch of statements. This is a good idea now because we support seeding the remote database and most requests are routed through IPv4 connection pool.

## Additional context

Add any other context or screenshots.


coveralls: ## Pull Request Test Coverage Report for [Build 8174987577](https://coveralls.io/builds/66121153)


### Details

* **64** of **94**   **(68.09%)**  changed or added relevant lines in **9** files are covered.
* **9** unchanged lines in **3** files lost coverage.
* Overall coverage decreased (**-0.01%**) to **58.864%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [internal/db/remote/commit/commit.go](https://coveralls.io/builds/66121153/source?filename=internal%2Fdb%2Fremote%2Fcommit%2Fcommit.go#L43) | 0 | 3 | 0.0%
| [internal/migration/repair/repair.go](https://coveralls.io/builds/66121153/source?filename=internal%2Fmigration%2Frepair%2Frepair.go#L172) | 24 | 30 | 80.0%
| [internal/db/remote/changes/changes.go](https://coveralls.io/builds/66121153/source?filename=internal%2Fdb%2Fremote%2Fchanges%2Fchanges.go#L37) | 0 | 10 | 0.0%
| [internal/testing/pgtest/mock.go](https://coveralls.io/builds/66121153/source?filename=internal%2Ftesting%2Fpgtest%2Fmock.go#L94) | 21 | 32 | 65.63%
<!-- | **Total:** | **64** | **94** | **68.09%** | -->

|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [internal/db/reset/reset.go](https://coveralls.io/builds/66121153/source?filename=internal%2Fdb%2Freset%2Freset.go#L298) | 2 | 58.18% |
| [internal/migration/list/list.go](https://coveralls.io/builds/66121153/source?filename=internal%2Fmigration%2Flist%2Flist.go#L63) | 2 | 95.08% |
| [internal/gen/keys/keys.go](https://coveralls.io/builds/66121153/source?filename=internal%2Fgen%2Fkeys%2Fkeys.go#L101) | 5 | 11.76% |
<!-- | **Total:** | **9** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/66121153/badge)](https://coveralls.io/builds/66121153) |
| :-- | --: |
| Change from base [Build 8170096106](https://coveralls.io/builds/66112721): |  -0.01% |
| Covered Lines: | 6209 |
| Relevant Lines: | 10548 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/internal/db/remote/changes/changes.go b/internal/db/remote/changes/changes.go
index 14cd4275..b6d77f37 100644
--- a/internal/db/remote/changes/changes.go
+++ b/internal/db/remote/changes/changes.go
@@ -2,6 +2,7 @@ package changes
 
 import (
 	"context"
+	"io"
 
 	"github.com/jackc/pgconn"
 	"github.com/spf13/afero"
@@ -33,23 +34,24 @@ func Run(ctx context.Context, schema []string, config pgconn.Config, fsys afero.
 
 func run(p utils.Program, ctx context.Context, schema []string, config pgconn.Config, fsys afero.Fs) (err error) {
 	// 1. Assert `supabase/migrations` and `schema_migrations` are in sync.
-	{
-		p.Send(utils.StatusMsg("Connecting to remote database..."))
-		conn, err := utils.ConnectRemotePostgres(ctx, config)
+	w := utils.StatusWriter{Program: p}
+	if len(schema) == 0 {
+		schema, err = loadSchema(ctx, config, w)
 		if err != nil {
 			return err
 		}
-		defer conn.Close(context.Background())
-		if len(schema) == 0 {
-			schema, err = diff.LoadUserSchemas(ctx, conn)
-			if err != nil {
-				return err
-			}
-		}
 	}
 
-	w := utils.StatusWriter{Program: p}
 	// 2. Diff remote db (source) & shadow db (target) and print it.
 	output, err = diff.DiffDatabase(ctx, schema, config, w, fsys, diff.DiffSchemaMigra)
 	return err
 }
+
+func loadSchema(ctx context.Context, config pgconn.Config, w io.Writer) ([]string, error) {
+	conn, err := utils.ConnectByConfigStream(ctx, config, w)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close(context.Background())
+	return diff.LoadUserSchemas(ctx, conn)
+}
diff --git a/internal/db/remote/commit/commit.go b/internal/db/remote/commit/commit.go
index e0ddf365..17188edb 100644
--- a/internal/db/remote/commit/commit.go
+++ b/internal/db/remote/commit/commit.go
@@ -8,7 +8,6 @@ import (
 	"path/filepath"
 
 	"github.com/jackc/pgconn"
-	"github.com/jackc/pgerrcode"
 	"github.com/jackc/pgx/v4"
 	"github.com/spf13/afero"
 	"github.com/supabase/cli/internal/db/diff"
@@ -41,8 +40,8 @@ func Run(ctx context.Context, schema []string, config pgconn.Config, fsys afero.
 
 func run(p utils.Program, ctx context.Context, schema []string, config pgconn.Config, fsys afero.Fs) error {
 	// 1. Assert `supabase/migrations` and `schema_migrations` are in sync.
-	p.Send(utils.StatusMsg("Connecting to remote database..."))
-	conn, err := utils.ConnectRemotePostgres(ctx, config)
+	w := utils.StatusWriter{Program: p}
+	conn, err := utils.ConnectByConfigStream(ctx, config, w)
 	if err != nil {
 		return err
 	}
@@ -92,10 +91,7 @@ func fetchRemote(p utils.Program, ctx context.Context, schema []string, timestam
 func assertRemoteInSync(ctx context.Context, conn *pgx.Conn, fsys afero.Fs) error {
 	remoteMigrations, err := list.LoadRemoteMigrations(ctx, conn)
 	if err != nil {
-		var pgErr *pgconn.PgError
-		if !errors.As(err, &pgErr) || pgErr.Code != pgerrcode.UndefinedTable {
-			return err
-		}
+		return err
 	}
 	localMigrations, err := list.LoadLocalMigrations(fsys)
 	if err != nil {
diff --git a/internal/db/reset/reset.go b/internal/db/reset/reset.go
index f4498752..27ccd3d9 100644
--- a/internal/db/reset/reset.go
+++ b/internal/db/reset/reset.go
@@ -259,7 +259,7 @@ func WaitForServiceReady(ctx context.Context, started []string) error {
 
 func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
 	fmt.Fprintln(os.Stderr, "Resetting remote database"+toLogMessage(version))
-	conn, err := utils.ConnectRemotePostgres(ctx, config, options...)
+	conn, err := utils.ConnectByConfigStream(ctx, config, io.Discard, options...)
 	if err != nil {
 		return err
 	}
diff --git a/internal/link/link.go b/internal/link/link.go
index 6bb9e342..45ca362e 100644
--- a/internal/link/link.go
+++ b/internal/link/link.go
@@ -177,7 +177,7 @@ func linkStorageVersion(ctx context.Context, projectRef string, fsys afero.Fs) e
 }
 
 func linkDatabase(ctx context.Context, config pgconn.Config, options ...func(*pgx.ConnConfig)) error {
-	conn, err := utils.ConnectRemotePostgres(ctx, config, options...)
+	conn, err := utils.ConnectByConfig(ctx, config, options...)
 	if err != nil {
 		return err
 	}
diff --git a/internal/migration/list/list.go b/internal/migration/list/list.go
index d14c0ec3..844c6041 100644
--- a/internal/migration/list/list.go
+++ b/internal/migration/list/list.go
@@ -46,13 +46,20 @@ func loadRemoteVersions(ctx context.Context, config pgconn.Config, options ...fu
 }
 
 func LoadRemoteMigrations(ctx context.Context, conn *pgx.Conn) ([]string, error) {
-	rows, err := conn.Query(ctx, LIST_MIGRATION_VERSION)
+	versions, err := listMigrationVersions(ctx, conn)
 	if err != nil {
 		var pgErr *pgconn.PgError
 		if errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UndefinedTable {
 			// If migration history table is undefined, the remote project has no migrations
 			return nil, nil
 		}
+	}
+	return versions, err
+}
+
+func listMigrationVersions(ctx context.Context, conn *pgx.Conn) ([]string, error) {
+	rows, err := conn.Query(ctx, LIST_MIGRATION_VERSION)
+	if err != nil {
 		return nil, errors.Errorf("failed to query rows: %w", err)
 	}
 	return pgxv5.CollectStrings(rows)
diff --git a/internal/migration/repair/repair.go b/internal/migration/repair/repair.go
index e81aa71a..36b7e8cd 100644
--- a/internal/migration/repair/repair.go
+++ b/internal/migration/repair/repair.go
@@ -88,24 +88,6 @@ func UpdateMigrationTable(ctx context.Context, conn *pgx.Conn, version []string,
 	return nil
 }
 
-func InsertVersionSQL(batch *pgconn.Batch, version, name string, stats []string) {
-	encoded := []byte{'{'}
-	for i, line := range stats {
-		if i > 0 {
-			encoded = append(encoded, ',')
-		}
-		encoded = append(encoded, pgtype.QuoteArrayElementIfNeeded(line)...)
-	}
-	encoded = append(encoded, '}')
-	batch.ExecParams(
-		history.INSERT_MIGRATION_VERSION,
-		[][]byte{[]byte(version), []byte(name), encoded},
-		[]uint32{pgtype.TextOID, pgtype.TextOID, pgtype.TextArrayOID},
-		[]int16{pgtype.TextFormatCode, pgtype.TextFormatCode, pgtype.TextFormatCode},
-		nil,
-	)
-}
-
 func GetMigrationFile(version string, fsys afero.Fs) (string, error) {
 	path := filepath.Join(utils.MigrationsDir, version+"_*.sql")
 	matches, err := afero.Glob(fsys, path)
@@ -175,7 +157,9 @@ func (m *MigrationFile) ExecBatch(ctx context.Context, conn *pgx.Conn) error {
 	}
 	// Insert into migration history
 	if len(m.Version) > 0 {
-		InsertVersionSQL(batch, m.Version, m.Name, m.Lines)
+		if err := m.insertVersionSQL(conn, batch); err != nil {
+			return err
+		}
 	}
 	// ExecBatch is implicitly transactional
 	if result, err := conn.PgConn().ExecBatch(ctx, batch).ReadAll(); err != nil {
@@ -190,6 +174,35 @@ func (m *MigrationFile) ExecBatch(ctx context.Context, conn *pgx.Conn) error {
 	return nil
 }
 
+func (m *MigrationFile) insertVersionSQL(conn *pgx.Conn, batch *pgconn.Batch) error {
+	value := pgtype.TextArray{}
+	if err := value.Set(m.Lines); err != nil {
+		return errors.Errorf("failed to set text array: %w", err)
+	}
+	ci := conn.ConnInfo()
+	var err error
+	var encoded []byte
+	var valueFormat int16
+	if conn.Config().PreferSimpleProtocol {
+		encoded, err = value.EncodeText(ci, encoded)
+		valueFormat = pgtype.TextFormatCode
+	} else {
+		encoded, err = value.EncodeBinary(ci, encoded)
+		valueFormat = pgtype.BinaryFormatCode
+	}
+	if err != nil {
+		return errors.Errorf("failed to encode binary: %w", err)
+	}
+	batch.ExecParams(
+		history.INSERT_MIGRATION_VERSION,
+		[][]byte{[]byte(m.Version), []byte(m.Name), encoded},
+		[]uint32{pgtype.TextOID, pgtype.TextOID, pgtype.TextArrayOID},
+		[]int16{pgtype.TextFormatCode, pgtype.TextFormatCode, valueFormat},
+		nil,
+	)
+	return nil
+}
+
 func (m *MigrationFile) ExecBatchWithCache(ctx context.Context, conn *pgx.Conn) error {
 	// Data statements don't mutate schemas, safe to use statement cache
 	batch := pgx.Batch{}
diff --git a/internal/utils/connect.go b/internal/utils/connect.go
index 5f738928..a12ceb57 100644
--- a/internal/utils/connect.go
+++ b/internal/utils/connect.go
@@ -41,24 +41,6 @@ func ToPostgresURL(config pgconn.Config) string {
 	)
 }
 
-// Connnect to remote Postgres with optimised settings. The caller is responsible for closing the connection returned.
-func ConnectRemotePostgres(ctx context.Context, config pgconn.Config, options ...func(*pgx.ConnConfig)) (*pgx.Conn, error) {
-	// Simple protocol is preferred over pgx default Parse -> Bind flow because
-	//   1. Using a single command for each query reduces RTT over an Internet connection.
-	//   2. Performance gains from using the alternate binary protocol is negligible because
-	//      we are only selecting from migrations table. Large reads are handled by PostgREST.
-	//   3. Any prepared statements are cleared server side upon closing the TCP connection.
-	//      Since CLI workloads are one-off scripts, we don't use connection pooling and hence
-	//      don't benefit from per connection server side cache.
-	opts := append(options, func(cc *pgx.ConnConfig) {
-		cc.PreferSimpleProtocol = true
-		if DNSResolver.Value == DNS_OVER_HTTPS {
-			cc.LookupFunc = FallbackLookupIP
-		}
-	})
-	return ConnectByUrl(ctx, ToPostgresURL(config), opts...)
-}
-
 func GetPoolerConfig(projectRef string) *pgconn.Config {
 	logger := getDebugLogger()
 	if len(Config.Db.Pooler.ConnectionString) == 0 {
@@ -74,9 +56,11 @@ func GetPoolerConfig(projectRef string) *pgconn.Config {
 		fmt.Fprintln(logger, "Failed to parse pooler URL:", poolerUrl)
 		return nil
 	}
+	if poolerConfig.RuntimeParams == nil {
+		poolerConfig.RuntimeParams = make(map[string]string)
+	}
 	// Verify that the pooler username matches the database host being connected to
-	_, ref, found := strings.Cut(poolerConfig.User, ".")
-	if !found {
+	if _, ref, found := strings.Cut(poolerConfig.User, "."); !found {
 		for _, option := range strings.Split(poolerConfig.RuntimeParams["options"], ",") {
 			key, value, found := strings.Cut(option, "=")
 			if found && key == "reference" && value != projectRef {
@@ -94,6 +78,12 @@ func GetPoolerConfig(projectRef string) *pgconn.Config {
 		return nil
 	}
 	fmt.Fprintln(logger, "Using connection pooler:", poolerUrl)
+	// Supavisor transaction mode does not support prepared statement
+	if poolerConfig.Port == 6543 {
+		if _, ok := poolerConfig.RuntimeParams["statement_cache_mode"]; !ok {
+			poolerConfig.RuntimeParams["statement_cache_mode"] = "describe"
+		}
+	}
 	return poolerConfig
 }
 
@@ -157,13 +147,22 @@ func ConnectByUrl(ctx context.Context, url string, options ...func(*pgx.ConnConf
 	return conn, nil
 }
 
-func ConnectByConfig(ctx context.Context, config pgconn.Config, options ...func(*pgx.ConnConfig)) (*pgx.Conn, error) {
+func ConnectByConfigStream(ctx context.Context, config pgconn.Config, w io.Writer, options ...func(*pgx.ConnConfig)) (*pgx.Conn, error) {
 	if IsLocalDatabase(config) {
-		fmt.Fprintln(os.Stderr, "Connecting to local database...")
+		fmt.Fprintln(w, "Connecting to local database...")
 		return ConnectLocalPostgres(ctx, config, options...)
 	}
-	fmt.Fprintln(os.Stderr, "Connecting to remote database...")
-	return ConnectRemotePostgres(ctx, config, options...)
+	fmt.Fprintln(w, "Connecting to remote database...")
+	opts := append(options, func(cc *pgx.ConnConfig) {
+		if DNSResolver.Value == DNS_OVER_HTTPS {
+			cc.LookupFunc = FallbackLookupIP
+		}
+	})
+	return ConnectByUrl(ctx, ToPostgresURL(config), opts...)
+}
+
+func ConnectByConfig(ctx context.Context, config pgconn.Config, options ...func(*pgx.ConnConfig)) (*pgx.Conn, error) {
+	return ConnectByConfigStream(ctx, config, os.Stderr, options...)
 }
 
 func IsLocalDatabase(config pgconn.Config) bool {


Test patch:
diff --git a/internal/db/diff/diff_test.go b/internal/db/diff/diff_test.go
index 557e1f9f..00d019d4 100644
--- a/internal/db/diff/diff_test.go
+++ b/internal/db/diff/diff_test.go
@@ -3,12 +3,10 @@ package diff
 import (
 	"context"
 	"errors"
-	"fmt"
 	"io"
 	"net/http"
 	"os"
 	"path/filepath"
-	"strings"
 	"testing"
 	"time"
 
@@ -36,6 +34,33 @@ var dbConfig = pgconn.Config{
 	Database: "postgres",
 }
 
+var escapedSchemas = []string{
+	"auth",
+	"pgbouncer",
+	"realtime",
+	`\_realtime`,
+	"storage",
+	`\_analytics`,
+	`supabase\_functions`,
+	`supabase\_migrations`,
+	`information\_schema`,
+	`pg\_%`,
+	"cron",
+	"graphql",
+	`graphql\_public`,
+	"net",
+	"pgsodium",
+	`pgsodium\_masks`,
+	"pgtle",
+	"repack",
+	"tiger",
+	`tiger\_data`,
+	`timescaledb\_%`,
+	`\_timescaledb\_%`,
+	"topology",
+	"vault",
+}
+
 func TestRun(t *testing.T) {
 	t.Run("runs migra diff", func(t *testing.T) {
 		// Setup in-memory fs
@@ -102,7 +127,7 @@ func TestRun(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(reset.LIST_SCHEMAS, "$1", `('{auth,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","supabase\\_migrations","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}')`)).
+		conn.Query(reset.LIST_SCHEMAS, escapedSchemas).
 			ReplyError(pgerrcode.DuplicateTable, `relation "test" already exists`)
 		// Run test
 		err := Run(context.Background(), []string{}, "", dbConfig, DiffSchemaMigra, fsys, conn.Intercept)
@@ -152,7 +177,7 @@ func TestMigrateShadow(t *testing.T) {
 		pgtest.MockMigrationHistory(conn)
 		conn.Query(sql).
 			Reply("CREATE SCHEMA").
-			Query(history.INSERT_MIGRATION_VERSION, "0", "test", fmt.Sprintf("{%s}", sql)).
+			Query(history.INSERT_MIGRATION_VERSION, "0", "test", []string{sql}).
 			Reply("INSERT 0 1")
 		// Run test
 		err := MigrateShadowDatabase(context.Background(), "test-shadow-db", fsys, conn.Intercept)
@@ -317,7 +342,7 @@ At statement 0: create schema public`)
 		pgtest.MockMigrationHistory(conn)
 		conn.Query(sql).
 			Reply("CREATE SCHEMA").
-			Query(history.INSERT_MIGRATION_VERSION, "0", "test", fmt.Sprintf("{%s}", sql)).
+			Query(history.INSERT_MIGRATION_VERSION, "0", "test", []string{sql}).
 			Reply("INSERT 0 1")
 		// Run test
 		diff, err := DiffDatabase(context.Background(), []string{"public"}, dbConfig, io.Discard, fsys, DiffSchemaMigra, conn.Intercept)
@@ -332,11 +357,11 @@ func TestUserSchema(t *testing.T) {
 	// Setup mock postgres
 	conn := pgtest.NewConn()
 	defer conn.Close(t)
-	conn.Query(strings.ReplaceAll(reset.LIST_SCHEMAS, "$1", `('{auth,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","supabase\\_migrations","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}')`)).
+	conn.Query(reset.LIST_SCHEMAS, escapedSchemas).
 		Reply("SELECT 1", []interface{}{"test"})
 	// Connect to mock
 	ctx := context.Background()
-	mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+	mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 	require.NoError(t, err)
 	defer mock.Close(ctx)
 	// Run test
diff --git a/internal/db/lint/lint_test.go b/internal/db/lint/lint_test.go
index 3bb9f876..7b6359f6 100644
--- a/internal/db/lint/lint_test.go
+++ b/internal/db/lint/lint_test.go
@@ -123,7 +123,7 @@ func TestLintDatabase(t *testing.T) {
 			Query("rollback").Reply("ROLLBACK")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectLocalPostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -169,7 +169,7 @@ func TestLintDatabase(t *testing.T) {
 			Query("rollback").Reply("ROLLBACK")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectLocalPostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -189,7 +189,7 @@ func TestLintDatabase(t *testing.T) {
 			Query("rollback").Reply("ROLLBACK")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectLocalPostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -209,7 +209,7 @@ func TestLintDatabase(t *testing.T) {
 			Query("rollback").Reply("ROLLBACK")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectLocalPostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
diff --git a/internal/db/pull/pull_test.go b/internal/db/pull/pull_test.go
index ff5cbead..62c49ff9 100644
--- a/internal/db/pull/pull_test.go
+++ b/internal/db/pull/pull_test.go
@@ -6,7 +6,6 @@ import (
 	"net/http"
 	"os"
 	"path/filepath"
-	"strings"
 	"testing"
 
 	"github.com/jackc/pgconn"
@@ -31,6 +30,33 @@ var dbConfig = pgconn.Config{
 	Database: "postgres",
 }
 
+var escapedSchemas = []string{
+	"auth",
+	"pgbouncer",
+	"realtime",
+	`\_realtime`,
+	"storage",
+	`\_analytics`,
+	`supabase\_functions`,
+	`supabase\_migrations`,
+	`information\_schema`,
+	`pg\_%`,
+	"cron",
+	"graphql",
+	`graphql\_public`,
+	"net",
+	"pgsodium",
+	`pgsodium\_masks`,
+	"pgtle",
+	"repack",
+	"tiger",
+	`tiger\_data`,
+	`timescaledb\_%`,
+	`\_timescaledb\_%`,
+	"topology",
+	"vault",
+}
+
 func TestPullCommand(t *testing.T) {
 	t.Run("throws error on missing docker", func(t *testing.T) {
 		// Setup in-memory fs
@@ -144,7 +170,7 @@ func TestPullSchema(t *testing.T) {
 			Reply("SELECT 0")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -169,11 +195,11 @@ func TestPullSchema(t *testing.T) {
 		defer conn.Close(t)
 		conn.Query(list.LIST_MIGRATION_VERSION).
 			Reply("SELECT 1", []interface{}{"0"}).
-			Query(strings.ReplaceAll(reset.LIST_SCHEMAS, "$1", `('{auth,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","supabase\\_migrations","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}')`)).
+			Query(reset.LIST_SCHEMAS, escapedSchemas).
 			ReplyError(pgerrcode.DuplicateTable, `relation "test" already exists`)
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -202,7 +228,7 @@ func TestPullSchema(t *testing.T) {
 			Reply("SELECT 1", []interface{}{"0"})
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -226,7 +252,7 @@ func TestSyncRemote(t *testing.T) {
 			Reply("SELECT 0")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -248,7 +274,7 @@ func TestSyncRemote(t *testing.T) {
 			Reply("SELECT 0")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -270,7 +296,7 @@ func TestSyncRemote(t *testing.T) {
 			Reply("SELECT 1", []interface{}{"20220727064247"})
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
@@ -290,7 +316,7 @@ func TestSyncRemote(t *testing.T) {
 			Reply("SELECT 0")
 		// Connect to mock
 		ctx := context.Background()
-		mock, err := utils.ConnectRemotePostgres(ctx, dbConfig, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
diff --git a/internal/db/push/push_test.go b/internal/db/push/push_test.go
index 710771db..11f16782 100644
--- a/internal/db/push/push_test.go
+++ b/internal/db/push/push_test.go
@@ -95,7 +95,7 @@ func TestMigrationPush(t *testing.T) {
 		conn.Query(list.LIST_MIGRATION_VERSION).
 			Reply("SELECT 0")
 		pgtest.MockMigrationHistory(conn)
-		conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", "{}").
+		conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", nil).
 			ReplyError(pgerrcode.NotNullViolation, `null value in column "version" of relation "schema_migrations"`)
 		// Run test
 		err := Run(context.Background(), false, false, false, false, dbConfig, fsys, conn.Intercept)
diff --git a/internal/db/reset/reset_test.go b/internal/db/reset/reset_test.go
index fdf89354..3b91a344 100644
--- a/internal/db/reset/reset_test.go
+++ b/internal/db/reset/reset_test.go
@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"io"
 	"net/http"
-	"strings"
 	"testing"
 	"time"
 
@@ -293,6 +292,34 @@ func TestRestartDatabase(t *testing.T) {
 	})
 }
 
+var escapedSchemas = []string{
+	"public",
+	"auth",
+	"extensions",
+	"pgbouncer",
+	"realtime",
+	`\_realtime`,
+	"storage",
+	`\_analytics`,
+	`supabase\_functions`,
+	`information\_schema`,
+	`pg\_%`,
+	"cron",
+	"graphql",
+	`graphql\_public`,
+	"net",
+	"pgsodium",
+	`pgsodium\_masks`,
+	"pgtle",
+	"repack",
+	"tiger",
+	`tiger\_data`,
+	`timescaledb\_%`,
+	`\_timescaledb\_%`,
+	"topology",
+	"vault",
+}
+
 func TestResetRemote(t *testing.T) {
 	dbConfig := pgconn.Config{
 		Host:     "db.supabase.co",
@@ -308,7 +335,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", `('{public,auth,extensions,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}')`)).
+		conn.Query(LIST_SCHEMAS, escapedSchemas).
 			Reply("SELECT 1", []interface{}{"private"}).
 			Query("DROP SCHEMA IF EXISTS private CASCADE").
 			Reply("DROP SCHEMA").
@@ -335,7 +362,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", `('{public,auth,extensions,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}')`)).
+		conn.Query(LIST_SCHEMAS, escapedSchemas).
 			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation information_schema")
 		// Run test
 		err := resetRemote(context.Background(), "", dbConfig, fsys, conn.Intercept)
@@ -349,7 +376,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", `('{public,auth,extensions,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}')`)).
+		conn.Query(LIST_SCHEMAS, escapedSchemas).
 			Reply("SELECT 0").
 			Query(dropObjects).
 			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation supabase_migrations")
diff --git a/internal/migration/apply/apply_test.go b/internal/migration/apply/apply_test.go
index d0419bbf..af124c2c 100644
--- a/internal/migration/apply/apply_test.go
+++ b/internal/migration/apply/apply_test.go
@@ -2,7 +2,6 @@ package apply
 
 import (
 	"context"
-	"fmt"
 	"os"
 	"path/filepath"
 	"testing"
@@ -31,7 +30,7 @@ func TestMigrateDatabase(t *testing.T) {
 		pgtest.MockMigrationHistory(conn)
 		conn.Query(sql).
 			Reply("CREATE SCHEMA").
-			Query(history.INSERT_MIGRATION_VERSION, "0", "test", fmt.Sprintf("{%s}", sql)).
+			Query(history.INSERT_MIGRATION_VERSION, "0", "test", []string{sql}).
 			Reply("INSERT 0 1")
 		// Connect to mock
 		ctx := context.Background()
diff --git a/internal/migration/repair/repair_test.go b/internal/migration/repair/repair_test.go
index 2d586bbd..af97ea33 100644
--- a/internal/migration/repair/repair_test.go
+++ b/internal/migration/repair/repair_test.go
@@ -10,6 +10,7 @@ import (
 
 	"github.com/jackc/pgconn"
 	"github.com/jackc/pgerrcode"
+	"github.com/jackc/pgx/v4"
 	"github.com/spf13/afero"
 	"github.com/spf13/viper"
 	"github.com/stretchr/testify/assert"
@@ -33,12 +34,12 @@ func TestRepairCommand(t *testing.T) {
 		// Setup in-memory fs
 		fsys := afero.NewMemMapFs()
 		path := filepath.Join(utils.MigrationsDir, "0_test.sql")
-		require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0644))
+		require.NoError(t, afero.WriteFile(fsys, path, []byte("select 1"), 0644))
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
 		pgtest.MockMigrationHistory(conn)
-		conn.Query("INSERT INTO supabase_migrations.schema_migrations(version, name, statements) VALUES(('0'), ('test'), (null))").
+		conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", []string{"select 1"}).
 			Reply("INSERT 0 1")
 		// Run test
 		err := Run(context.Background(), dbConfig, []string{"0"}, Applied, fsys, conn.Intercept)
@@ -53,7 +54,7 @@ func TestRepairCommand(t *testing.T) {
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
 		pgtest.MockMigrationHistory(conn)
-		conn.Query("DELETE FROM supabase_migrations.schema_migrations WHERE version = ANY(('{0}'))").
+		conn.Query(history.DELETE_MIGRATION_VERSION, []string{"0"}).
 			Reply("DELETE 1")
 		// Run test
 		err := Run(context.Background(), dbConfig, []string{"0"}, Reverted, fsys, conn.Intercept)
@@ -79,7 +80,7 @@ func TestRepairCommand(t *testing.T) {
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
 		pgtest.MockMigrationHistory(conn)
-		conn.Query("INSERT INTO supabase_migrations.schema_migrations(version, name, statements) VALUES(('0'), ('test'), (null))").
+		conn.Query(history.INSERT_MIGRATION_VERSION, "0", "test", nil).
 			ReplyError(pgerrcode.DuplicateObject, `relation "supabase_migrations.schema_migrations" does not exist`)
 		// Run test
 		err := Run(context.Background(), dbConfig, []string{"0"}, Applied, fsys, conn.Intercept)
@@ -117,6 +118,29 @@ func TestMigrationFile(t *testing.T) {
 		assert.Nil(t, migration)
 	})
 
+	t.Run("encodes statements in binary format", func(t *testing.T) {
+		migration := MigrationFile{
+			Lines:   []string{"create schema public"},
+			Version: "0",
+		}
+		// Setup mock postgres
+		conn := pgtest.NewConn()
+		defer conn.Close(t)
+		conn.Query(migration.Lines[0]).
+			Reply("CREATE SCHEMA").
+			Query(history.INSERT_MIGRATION_VERSION, "0", "", migration.Lines).
+			Reply("INSERT 0 1")
+		// Connect to mock
+		ctx := context.Background()
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
+		require.NoError(t, err)
+		defer mock.Close(ctx)
+		// Run test
+		err = migration.ExecBatch(context.Background(), mock)
+		// Check error
+		assert.NoError(t, err)
+	})
+
 	t.Run("throws error on insert failure", func(t *testing.T) {
 		migration := MigrationFile{
 			Lines:   []string{"create schema public"},
@@ -129,9 +153,11 @@ func TestMigrationFile(t *testing.T) {
 			ReplyError(pgerrcode.DuplicateSchema, `schema "public" already exists`).
 			Query(history.INSERT_MIGRATION_VERSION, "0", "", fmt.Sprintf("{%s}", migration.Lines[0])).
 			Reply("INSERT 0 1")
-		// Connect to mock
+		// Connect to mock via text protocol
 		ctx := context.Background()
-		mock, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{Port: 5432}, conn.Intercept)
+		mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept, func(cc *pgx.ConnConfig) {
+			cc.PreferSimpleProtocol = true
+		})
 		require.NoError(t, err)
 		defer mock.Close(ctx)
 		// Run test
diff --git a/internal/migration/squash/squash_test.go b/internal/migration/squash/squash_test.go
index 115f4020..f7326dff 100644
--- a/internal/migration/squash/squash_test.go
+++ b/internal/migration/squash/squash_test.go
@@ -11,6 +11,7 @@ import (
 
 	"github.com/jackc/pgconn"
 	"github.com/jackc/pgerrcode"
+	"github.com/jackc/pgx/v4"
 	"github.com/spf13/afero"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -62,9 +63,9 @@ func TestSquashCommand(t *testing.T) {
 		pgtest.MockMigrationHistory(conn)
 		conn.Query(sql).
 			Reply("CREATE SCHEMA").
-			Query(history.INSERT_MIGRATION_VERSION, "0", "init", fmt.Sprintf("{%s}", sql)).
+			Query(history.INSERT_MIGRATION_VERSION, "0", "init", []string{sql}).
 			Reply("INSERT 0 1").
-			Query(history.INSERT_MIGRATION_VERSION, "1", "target", "{}").
+			Query(history.INSERT_MIGRATION_VERSION, "1", "target", nil).
 			Reply("INSERT 0 1")
 		// Run test
 		err := Run(context.Background(), "", pgconn.Config{
@@ -96,7 +97,9 @@ func TestSquashCommand(t *testing.T) {
 		conn.Query(fmt.Sprintf("DELETE FROM supabase_migrations.schema_migrations WHERE version <= ('0');INSERT INTO supabase_migrations.schema_migrations(version, name, statements) VALUES(('0'), ('init'), ('{%s}'))", sql)).
 			Reply("INSERT 0 1")
 		// Run test
-		err := Run(context.Background(), "0", dbConfig, fsys, conn.Intercept)
+		err := Run(context.Background(), "0", dbConfig, fsys, conn.Intercept, func(cc *pgx.ConnConfig) {
+			cc.PreferSimpleProtocol = true
+		})
 		// Check error
 		assert.NoError(t, err)
 		match, err := afero.FileContainsBytes(fsys, path, []byte(sql))
@@ -230,7 +233,7 @@ func TestSquashMigrations(t *testing.T) {
 		pgtest.MockMigrationHistory(conn)
 		conn.Query(sql).
 			Reply("CREATE SCHEMA").
-			Query(history.INSERT_MIGRATION_VERSION, "0", "init", fmt.Sprintf("{%s}", sql)).
+			Query(history.INSERT_MIGRATION_VERSION, "0", "init", []string{sql}).
 			Reply("INSERT 0 1")
 		// Run test
 		err := squashMigrations(context.Background(), []string{filepath.Base(path)}, afero.NewReadOnlyFs(fsys), conn.Intercept)
@@ -258,7 +261,9 @@ func TestBaselineMigration(t *testing.T) {
 		conn.Query(fmt.Sprintf("DELETE FROM supabase_migrations.schema_migrations WHERE version <= ('0');INSERT INTO supabase_migrations.schema_migrations(version, name, statements) VALUES(('0'), ('init'), ('{%s}'))", sql)).
 			Reply("INSERT 0 1")
 		// Run test
-		err := baselineMigrations(context.Background(), dbConfig, "", fsys, conn.Intercept)
+		err := baselineMigrations(context.Background(), dbConfig, "", fsys, conn.Intercept, func(cc *pgx.ConnConfig) {
+			cc.PreferSimpleProtocol = true
+		})
 		// Check error
 		assert.NoError(t, err)
 	})
@@ -284,7 +289,9 @@ func TestBaselineMigration(t *testing.T) {
 		conn.Query(fmt.Sprintf("DELETE FROM supabase_migrations.schema_migrations WHERE version <= ('%[1]s');INSERT INTO supabase_migrations.schema_migrations(version, name, statements) VALUES(('%[1]s'), ('init'), (null))", "0")).
 			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation supabase_migrations")
 		// Run test
-		err := baselineMigrations(context.Background(), dbConfig, "0", fsys, conn.Intercept)
+		err := baselineMigrations(context.Background(), dbConfig, "0", fsys, conn.Intercept, func(cc *pgx.ConnConfig) {
+			cc.PreferSimpleProtocol = true
+		})
 		// Check error
 		assert.ErrorContains(t, err, `ERROR: permission denied for relation supabase_migrations (SQLSTATE 42501)`)
 	})
diff --git a/internal/testing/pgtest/mock.go b/internal/testing/pgtest/mock.go
index b389959a..eda0376c 100644
--- a/internal/testing/pgtest/mock.go
+++ b/internal/testing/pgtest/mock.go
@@ -15,8 +15,6 @@ import (
 	"google.golang.org/grpc/test/bufconn"
 )
 
-var ci = pgtype.NewConnInfo()
-
 type MockConn struct {
 	// Duplex server listener backed by in-memory buffer
 	server *bufconn.Listener
@@ -78,22 +76,42 @@ func (r *MockConn) Query(sql string, args ...interface{}) *MockConn {
 	var oids []uint32
 	var params [][]byte
 	for _, v := range args {
-		if dt, ok := ci.DataTypeForValue(v); ok {
-			if err := dt.Value.Set(v); err != nil {
-				continue
-			}
-			value, err := (dt.Value).(pgtype.TextEncoder).EncodeText(ci, []byte{})
-			if err != nil {
-				continue
-			}
+		if value, oid := r.encodeValueArg(v); oid > 0 {
 			params = append(params, value)
-			oids = append(oids, dt.OID)
+			oids = append(oids, oid)
 		}
 	}
 	r.script.Steps = append(r.script.Steps, ExpectQuery(sql, params, oids))
 	return r
 }
 
+func (r *MockConn) encodeValueArg(v interface{}) (value []byte, oid uint32) {
+	if v == nil {
+		return nil, pgtype.TextArrayOID
+	}
+	dt, ok := ci.DataTypeForValue(v)
+	if !ok {
+		r.errChan <- fmt.Errorf("no suitable type for arg: %v", v)
+		return nil, 0
+	}
+	if err := dt.Value.Set(v); err != nil {
+		r.errChan <- fmt.Errorf("failed to set value: %w", err)
+		return nil, 0
+	}
+	var err error
+	switch dt.OID {
+	case pgtype.TextArrayOID:
+		value, err = (dt.Value).(pgtype.BinaryEncoder).EncodeBinary(ci, []byte{})
+	default:
+		value, err = (dt.Value).(pgtype.TextEncoder).EncodeText(ci, []byte{})
+	}
+	if err != nil {
+		r.errChan <- fmt.Errorf("failed to encode arg: %w", err)
+		return nil, 0
+	}
+	return value, dt.OID
+}
+
 func getDataTypeSize(v interface{}) int16 {
 	t := reflect.TypeOf(v)
 	k := t.Kind()
@@ -107,9 +125,9 @@ func (r *MockConn) lastQuery() *extendedQueryStep {
 	return r.script.Steps[len(r.script.Steps)-1].(*extendedQueryStep)
 }
 
-// Adds a server reply using text protocol format.
+// Adds a server reply using binary or text protocol format.
 //
-// TODO: support binary protocol
+// TODO: support prepared statements when using binary protocol
 func (r *MockConn) Reply(tag string, rows ...[]interface{}) *MockConn {
 	q := r.lastQuery()
 	// Add field description
@@ -119,6 +137,7 @@ func (r *MockConn) Reply(tag string, rows ...[]interface{}) *MockConn {
 			name := fmt.Sprintf("c_%02d", i)
 			if dt, ok := ci.DataTypeForValue(v); ok {
 				size := getDataTypeSize(v)
+				format := ci.ParamFormatCodeForOID(dt.OID)
 				desc.Fields = append(desc.Fields, pgproto3.FieldDescription{
 					Name:                 []byte(name),
 					TableOID:             17131,
@@ -126,7 +145,7 @@ func (r *MockConn) Reply(tag string, rows ...[]interface{}) *MockConn {
 					DataTypeOID:          dt.OID,
 					DataTypeSize:         size,
 					TypeModifier:         -1,
-					Format:               pgtype.TextFormatCode,
+					Format:               format,
 				})
 			}
 		}
@@ -139,13 +158,8 @@ func (r *MockConn) Reply(tag string, rows ...[]interface{}) *MockConn {
 	for _, data := range rows {
 		var dr pgproto3.DataRow
 		for _, v := range data {
-			if dt, ok := ci.DataTypeForValue(v); ok {
-				if err := dt.Value.Set(v); err != nil {
-					continue
-				}
-				if value, err := (dt.Value).(pgtype.TextEncoder).EncodeText(ci, []byte{}); err == nil {
-					dr.Values = append(dr.Values, value)
-				}
+			if value, oid := r.encodeValueArg(v); oid > 0 {
+				dr.Values = append(dr.Values, value)
 			}
 		}
 		q.reply.Steps = append(q.reply.Steps, pgmock.SendMessage(&dr))
@@ -180,10 +194,10 @@ func (r *MockConn) ReplyError(code, message string) *MockConn {
 
 func (r *MockConn) Close(t *testing.T) {
 	if err := <-r.errChan; err != nil {
-		t.Fatalf("failed to close %v", err)
+		t.Fatalf("failed to close: %v", err)
 	}
 	if err := r.server.Close(); err != nil {
-		t.Fatalf("failed to close %v", err)
+		t.Fatalf("failed to close: %v", err)
 	}
 }
 
diff --git a/internal/testing/pgtest/step.go b/internal/testing/pgtest/step.go
index 9dd7fd39..86e136ee 100644
--- a/internal/testing/pgtest/step.go
+++ b/internal/testing/pgtest/step.go
@@ -9,6 +9,8 @@ import (
 	"github.com/jackc/pgtype"
 )
 
+var ci = pgtype.NewConnInfo()
+
 type extendedQueryStep struct {
 	sql    string
 	params [][]byte
@@ -51,8 +53,8 @@ func (e *extendedQueryStep) Step(backend *pgproto3.Backend) error {
 
 	if m, ok := msg.(*pgproto3.Bind); ok {
 		var codes []int16
-		for range e.oids {
-			codes = append(codes, pgtype.TextFormatCode)
+		for _, oid := range e.oids {
+			codes = append(codes, ci.ParamFormatCodeForOID(oid))
 		}
 		want := &pgproto3.Bind{
 			ParameterFormatCodes: codes,
diff --git a/internal/utils/connect_test.go b/internal/utils/connect_test.go
index 3f5ccec9..92b77ff1 100644
--- a/internal/utils/connect_test.go
+++ b/internal/utils/connect_test.go
@@ -29,7 +29,7 @@ const (
 	PG15_POOLER_URL = "postgres://postgres.zupyfdrjfhbeevcogohz:[YOUR-PASSWORD]@fly-0-sin.pooler.supabase.com:6543/postgres"
 )
 
-func TestConnectRemotePostgres(t *testing.T) {
+func TestConnectByConfig(t *testing.T) {
 	t.Run("connects to remote postgres with DoH", func(t *testing.T) {
 		Config.Db.Pooler.ConnectionString = ""
 		DNSResolver.Value = DNS_OVER_HTTPS
@@ -56,7 +56,7 @@ func TestConnectRemotePostgres(t *testing.T) {
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
 		// Run test
-		c, err := ConnectRemotePostgres(context.Background(), dbConfig, conn.Intercept)
+		c, err := ConnectByConfig(context.Background(), dbConfig, conn.Intercept)
 		require.NoError(t, err)
 		defer c.Close(context.Background())
 		assert.NoError(t, err)
@@ -71,7 +71,7 @@ func TestConnectRemotePostgres(t *testing.T) {
 		config := *dbConfig.Copy()
 		config.Host = "localhost"
 		config.Password = "pass word"
-		c, err := ConnectRemotePostgres(context.Background(), config, conn.Intercept)
+		c, err := ConnectByConfig(context.Background(), config, conn.Intercept)
 		require.NoError(t, err)
 		defer c.Close(context.Background())
 		assert.Equal(t, config.Password, c.Config().Password)
@@ -84,7 +84,7 @@ func TestConnectRemotePostgres(t *testing.T) {
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
 		// Run test
-		c, err := ConnectRemotePostgres(context.Background(), dbConfig, conn.Intercept)
+		c, err := ConnectByConfig(context.Background(), dbConfig, conn.Intercept)
 		// Check error
 		require.NoError(t, err)
 		defer c.Close(context.Background())
@@ -108,7 +108,7 @@ func TestConnectRemotePostgres(t *testing.T) {
 			MatchHeader("accept", "application/dns-json").
 			ReplyError(&net.OpError{Op: "dial", Err: netErr})
 		// Run test
-		_, err := ConnectRemotePostgres(context.Background(), dbConfig)
+		_, err := ConnectByConfig(context.Background(), dbConfig)
 		// Check error
 		require.ErrorIs(t, err, netErr)
 		assert.Empty(t, apitest.ListUnmatchedRequests())