Skip to content

Commit

Permalink
add support for using jackc/pgx as a driver (#122)
Browse files Browse the repository at this point in the history
This patch updates `pggen` to support using `jackc/pgx` as
a database driver. `lib/pq` has entered maintenance mode, and
`jackc/pgx` is the recommended replacement. I still cannot
recommend using `jackc/pgx` as a driver at this time because it
has [a bug][1] that prevents `pggen` from gracefully handling
schema changes.

Most of the changes involve tweaking our scanners to be able
to consume both the data that `lib/pq` and `jackc/pgx` pass
down.

For the moment, the generated code still depends on `lib/pq`
because we need to be able to use `lib/pq.Array` to scan arrays
of values. Once `jackc/pgx` becomes the recommended driver, we
will switch to using whatever the equivalent of `lib/pq.Array`
is for `jackc/pgx` (or roll our own). We will not drop support
for using `lib/pq` as a driver (likely not ever, but certainly
not without a major version bump).

This bumps our go versions, including the msgv. We need to bump
the msgv because jackc/pgx does not support go 1.11.

Closes #119

[1]: jackc/pgx#841
  • Loading branch information
ethanpailes authored Oct 5, 2020
1 parent 6abe0df commit 051c9f6
Show file tree
Hide file tree
Showing 23 changed files with 425 additions and 112 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.14-alpine
FROM golang:1.15-alpine

# we need postgresql-client so we can set up our database with psql
# for testing and `go` uses `git` to fetch deps for us. musl-dev
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.msgv
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This docker file is for running tests against the earliest support go
# version.
#
FROM golang:1.11-alpine
FROM golang:1.13-alpine

# we need postgresql-client so we can set up our database with psql
# for testing and `go` uses `git` to fetch deps for us. musl-dev
Expand Down
16 changes: 16 additions & 0 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,22 @@ CI checks a bit, but hopefully this is made up for by the fact that the `docker-
file in the repo root makes debugging CI jobs easier. We maintain two different compose files
so that we can share the source between the host and the container during local development.

## Testing Non-Default Drivers

`pggen` supports using both `github.com/lib/pq` and `github.com/jackc/pgx/stdlib` as
database drivers. For the moment `lib/pq` is recommended because `jackc/pgx` contains
a [nasty bug](https://github.com/jackc/pgx/issues/841) that prevents our test suite
from passing fully. Going forward we do want to switch to recommending `jackc/pgx`,
as it is more actively maintained than `lib/pq`.

The example tests all use the recommended driver (`lib/pq`) for testing to keep the example code
simple. The main test suite `cmd/pggen/test` is parameterized over the driver though. It
allows you to you set the driver name via the `DB_DRIVER` environment variable. You can
either set this variable to `postgres` (to use `lib/pq`) or `pgx` (to use
`github.com/jackc/pgx/stdlib`).

The `tools/test.bash` script runs the test suite both ways.

# Philosophy

Certain aspects of the style in which `pggen` is developed are intentionally divergent
Expand Down
3 changes: 2 additions & 1 deletion cmd/pggen/test/overrides_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ func TestOverriddenGetTimes(t *testing.T) {
res, err := overriddenPgClient.GetTimes(ctx)
chkErr(t, err)

if res[0].TsFieldNotNull.String() != "1999-01-08 04:05:06 +0000 +0000" {
tsStr := res[0].TsFieldNotNull.String()
if !(tsStr == "1999-01-08 04:05:06 +0000 +0000" || tsStr == "1999-01-08 04:05:06 +0000 UTC") {
t.Fatalf("bad ts field: '%s'", res[0].TsFieldNotNull.String())
}

Expand Down
16 changes: 10 additions & 6 deletions cmd/pggen/test/prepared_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package test

import (
"encoding/json"
"math"
"reflect"
"regexp"
"testing"
Expand Down Expand Up @@ -96,18 +97,21 @@ func TestSelectTime(t *testing.T) {
chkErr(t, err)

ti := times[0]
if ti.TsField.String() != "1999-01-08 04:05:06 +0000 +0000" {
timeStr := ti.TsField.String()
if !(timeStr == "1999-01-08 04:05:06 +0000 +0000" || timeStr == "1999-01-08 04:05:06 +0000 UTC") {
t.Fatalf("0: tsfield (actual = '%s')", ti.TsField.String())
}
if ti.TsFieldNotNull.String() != "1999-01-08 04:05:06 +0000 +0000" {
timeStr = ti.TsFieldNotNull.String()
if !(timeStr == "1999-01-08 04:05:06 +0000 +0000" || timeStr == "1999-01-08 04:05:06 +0000 UTC") {
t.Fatalf("0: tsfieldnn (actual = '%s'", ti.TsFieldNotNull.String())
}

ti = times[1]
if ti.TsField != nil {
t.Fatalf("1: tsfield unexpectedly valid")
}
if ti.TsFieldNotNull.String() != "1999-01-08 04:05:06 +0000 +0000" {
timeStr = ti.TsFieldNotNull.String()
if !(timeStr == "1999-01-08 04:05:06 +0000 +0000" || timeStr == "1999-01-08 04:05:06 +0000 UTC") {
t.Fatalf("1: tsfieldnn (actual = '%s')", ti.TsFieldNotNull.String())
}
// TODO: there is something weird going on with time marshalling. It
Expand Down Expand Up @@ -190,14 +194,14 @@ func TestSelectNumbers(t *testing.T) {
t.Fatalf("%d: numeric prec scale mismatch", i)
}

if (i == 0 && !reflect.DeepEqual(n.RealField, &n2d3)) ||
!reflect.DeepEqual(n.RealFieldNotNull, &n2d3) {
if (i == 0 && math.Abs(*n.RealField-n2d3) > 0.001) ||
math.Abs(*n.RealFieldNotNull-n2d3) > 0.001 {
t.Fatalf("%d: real mismatch", i)
}

if (i == 0 && !reflect.DeepEqual(n.DoubleField, &n9d3)) ||
!reflect.DeepEqual(n.DoubleFieldNotNull, &n9d3) {
t.Fatalf("%d: real mismatch", i)
t.Fatalf("%d: double mismatch", i)
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion cmd/pggen/test/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package test

import (
"database/sql"
"os"
"reflect"
"sort"
"testing"
Expand Down Expand Up @@ -1118,6 +1119,12 @@ func TestNotFoundList(t *testing.T) {
}

func TestDroppingColumnOnTheFly(t *testing.T) {
if os.Getenv("DB_DRIVER") == "pgx" {
// disable this test for jackc/pgx
// TODO: re-enable once https://github.com/jackc/pgx/issues/841 is resolved
return
}

// make sure we always start in a consistant state
_, err := pgClient.Handle().ExecContext(ctx, `
DROP TABLE drop_cols;
Expand All @@ -1144,6 +1151,8 @@ func TestDroppingColumnOnTheFly(t *testing.T) {

// load the record again
dc, err := pgClient.GetDropCol(ctx, id)
// NOTE: error actually occurs in github.com/jackc/pgx/v4/stdlib.(*Conn).QueryContex
// when scanning the very first row.
chkErr(t, err)

if dc.F1 != 0 {
Expand All @@ -1154,7 +1163,7 @@ func TestDroppingColumnOnTheFly(t *testing.T) {
t.Fatalf("expected F2 to be 2, was %d", dc.F2)
}

// pull the rug out from under us
// replace the old column
_, err = pgClient.Handle().ExecContext(ctx, `ALTER TABLE drop_cols ADD COLUMN f1 int NOT NULL DEFAULT 1`)
chkErr(t, err)
}
8 changes: 7 additions & 1 deletion cmd/pggen/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"encoding/json"
_ "github.com/jackc/pgx/v4/stdlib" // load driver
"log"
"os"
"os/exec"
Expand Down Expand Up @@ -31,7 +32,12 @@ func init() {
log.Fatalf("no DB_URL in the environment")
}

db, err := sql.Open("postgres", dbURL)
dbDriver, inEnv := os.LookupEnv("DB_DRIVER")
if !inEnv || dbDriver == "" {
dbDriver = "postgres" // default to using lib/pq
}

db, err := sql.Open(dbDriver, dbURL)
if err != nil {
log.Fatal(err)
}
Expand Down
46 changes: 23 additions & 23 deletions examples/extending_models/models/models.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 21 additions & 6 deletions examples/extending_models/models/pggen_prelude.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 21 additions & 6 deletions examples/id_in_set/models/pggen_prelude.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 21 additions & 6 deletions examples/include_specs/models/pggen_prelude.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 051c9f6

Please sign in to comment.