chore(db): Swap lib/pq for jackc/pgx/v5#259
Open
Amund211 wants to merge 2 commits into
Open
Conversation
lib/pq is in maintenance mode and the community has consolidated on pgx.
Switch the database/sql driver name from "postgres" to "pgx" via the
pgx/v5/stdlib side-effect import and replace every pq.QuoteIdentifier
call site with pgx.Identifier{...}.Sanitize(). Also rename the CloudSQL
DSN keyword from "database" to "dbname" since pgx's libpq-style parser
does not accept the pq-only alias.
The golang-migrate database/postgres driver still pulls lib/pq in as an
indirect dep; a follow-up will move migrations onto database/pgx/v5 to
drop it entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch the migrate driver from database/postgres to database/pgx/v5 and inject search_path via a one-off *sql.DB built with stdlib.OpenDB(*connConfig) where RuntimeParams["search_path"] is set to the target schema. Every connection in that pool gets search_path as a startup parameter, so migrate's WithInstance driver finds the right schema regardless of which conn it borrows. The schema name is run through pgx.Identifier.Sanitize() before being stuffed into the runtime param: Postgres parses each entry of search_path as a SQL identifier, so unquoted names get lower-cased and reject hyphens — without the quoting, mixed-case test schemas like find_milestone_Single_milestone_reached silently resolved to a non-existent schema and unqualified DDL failed with SQLSTATE 3F000. NewDatabaseMigrator now takes a connection string instead of an *sqlx.DB, mirroring how it builds its own short-lived pool. NewCloudsqlPostgresDatabase had only one caller and was redundant once ConnectionString was extracted; removed. lib/pq is no longer reachable from flashlight's binary or tests — it remains in go.sum only because jmoiron/sqlx's own test suite imports it, which the Go module graph keeps even though we never compile it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR migrates the project’s PostgreSQL integration from lib/pq to jackc/pgx/v5, including updating identifier quoting and switching migrations to use the golang-migrate pgx/v5 database driver with schema-scoped connections.
Changes:
- Switched
database/sqldriver from"postgres"(lib/pq) to"pgx"(pgx stdlib) and replacedpq.QuoteIdentifierusages withpgx.Identifier{...}.Sanitize(). - Updated Cloud SQL DSN keyword
database=→dbname=for pgx compatibility. - Reworked migrations to run via
database/pgx/v5using a per-schemasearch_pathstartup parameter on a temporary*sql.DB.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| main.go | Uses a shared connection string for both repository DB creation and migrator initialization. |
| internal/adapters/userrepository/postgres.go | Replaces schema identifier quoting with pgx sanitizer. |
| internal/adapters/userrepository/postgres_test.go | Updates schema DDL/search_path quoting and migrator construction API. |
| internal/adapters/playerrepository/repository.go | Updates SET search_path quoting to pgx sanitizer. |
| internal/adapters/playerrepository/repository_test.go | Updates schema setup/search_path quoting and migrator construction API. |
| internal/adapters/database/postgres.go | Switches sql driver to pgx, introduces ConnectionString, and adds schema-scoped DB helper for migrations. |
| internal/adapters/database/postgres_test.go | Updates tests to connect using the pgx driver name. |
| internal/adapters/database/migrator.go | Switches migrate DB driver from postgres to pgx/v5 and uses schema-scoped DB instances. |
| internal/adapters/database/migrator_test.go | Updates migration test setup to use pgx/v5 migrate driver and schema-scoped DB helper. |
| internal/adapters/database/cloudsql.go | Updates DSN to use dbname= instead of database=. |
| internal/adapters/accountrepository/postgres.go | Replaces schema identifier quoting with pgx sanitizer. |
| internal/adapters/accountrepository/postgres_test.go | Updates schema setup/search_path quoting and migrator construction API. |
| go.mod | Adds pgx/v5 and moves lib/pq to indirect dependency. |
| go.sum | Adds checksums for pgx and related indirect dependencies. |
| connConfig.RuntimeParams["search_path"] = pgx.Identifier{schemaName}.Sanitize() | ||
|
|
||
| return db, nil | ||
| return stdlib.OpenDB(*connConfig), nil |
| @@ -28,32 +28,30 @@ func TestMigrator(t *testing.T) { | |||
| db, err := NewPostgresDatabase(LocalConnectionString) | |||
| require.NoError(t, err) | |||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two commits:
9459243Swap lib/pq for jackc/pgx/v5 as the sql driver.database/sqldriver name"postgres"→"pgx"via_ "github.com/jackc/pgx/v5/stdlib". Everypq.QuoteIdentifier(...)call becomespgx.Identifier{...}.Sanitize(). CloudSQL DSN keyworddatabase=→dbname=(pgx doesn't accept the pq-only alias).37abad5Run migrations viadatabase/pgx/v5with per-schema DSN. Migrations now run through a one-off*sql.DBbuilt bystdlib.OpenDB(*cfg)whereRuntimeParams["search_path"]is set to the target schema.NewDatabaseMigratortakes a connection string instead of an*sqlx.DB.NewCloudsqlPostgresDatabaselost its only caller and was removed;ConnectionString(conf)was extracted.Why
lib/pqis in maintenance mode — README and issue #1010 explicitly point users at pgx. flashlight's direct usage was limited topq.QuoteIdentifier, so the swap is minimal-risk.Caveats / things a reviewer should know
pgx.Identifier{name}.Sanitize()is the canonical pgx-native identifier quoter (pgx.Identifier []stringwith aSanitize()method). Multi-part identifiers like{"schema","table"}produce"schema"."table". Same semantics as the oldpq.QuoteIdentifierfor single names.database=is pq-only. pgx's libpq-style parser usesdbname=(matches PostgreSQL's own keyword set). The CloudSQL helper was changed.database/pgx/v5only exposesWithInstance(*sql.DB)— noWithConnection(*sql.Conn). So per-schemasearch_pathcan't ride on a single borrowed conn anymore; it has to be a property of every conn in the pool, which is why the throwaway DB /RuntimeParamsapproach.search_pathmust be quoted insideRuntimeParams. First implementation set it to the bare schema name. Postgres parses each comma-separated entry ofsearch_pathas a SQL identifier — unquoted names get lower-cased and reject-. Test schemas likefind_milestone_Single_milestone_reachedandfind_milestone_Milestones_skipped_-_final_reachedsilently resolved to a non-existent schema; unqualified DDL then failed with SQLSTATE 3F000 ("no schema has been selected to create in"), whileSHOW search_pathhappily echoed the raw value back. Wrapping the value inpgx.Identifier{...}.Sanitize()fixes it. There's a comment onopenSchemaScopedDBexplaining this.migrate.NewWithInstanceis"pgx5", not"pgx"or"postgres"— that's whatdatabase/pgx/v5registers itself as.lib/pqis still ingo.sumas// indirect, but only becausejmoiron/sqlx's own test suite imports it (flashlight → sqlx → sqlx.test → lib/pq). It is never compiled into flashlight's binary or its tests. Fully removing it would require dropping sqlx itself; out of scope here.cache_statementwhich is incompatible with PgBouncer transaction/statement pooling on older PgBouncer (< 1.21). flashlight talks to Cloud SQL directly over Unix socket — no PgBouncer in the path — so the default is fine. If that changes, append?default_query_exec_mode=execto the DSN.Test plan
go build ./...go vet ./...go test ./...— all 19 packages pass, including the four Postgres-backed integration suites (accountrepository,database,playerrepository,userrepository) that exercise schema creation, migrations, and per-schema search_path under the new driver.🤖 Generated with Claude Code