-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pgx: Make it actually use pgx #593
Conversation
Pull Request Test Coverage Report for Build 482
💛 - Coveralls |
database/pgx/pgx.go
Outdated
return px, nil | ||
} | ||
|
||
func WithPgxInstance(ctx context.Context, conn *pgx.Conn, config *Config) (database.Driver, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to WithConnection()
and return (*Postgres, error)
so you don't need to perform type assertions.
Also, do a compile time type check at the package level: var _ database.Driver = (*Postgres)(nil) // explicit compile time type check
database/pgx/pgx.go
Outdated
// Locking and unlocking need to use the same connection | ||
conn *sql.Conn | ||
db *sql.DB | ||
db *pgx.Conn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not keep the existing names? e.g.
type Postgres struct {
conn *pgx.Conn
db *sqll.DB
}
Calling the connection db
and the DB stdlib
is confusing.
database/pgx/pgx.go
Outdated
dbErr := p.db.Close() | ||
if connErr != nil || dbErr != nil { | ||
return fmt.Errorf("conn: %v, db: %v", connErr, dbErr) | ||
if p.stdlib != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll need to revisit this once the fields are renamed. The current field names make this logic hard to follow.
The pgx.Conn
should be closed first and only released if the stdlib was used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm under the impression that if we got it from AquireConn we're just "borowing" it from the sql.DB, so we shouldn't be closing it, but passing it back to the sql.DB instance with ReleaseConn, which is why I did it this way.
AcquireConn acquires a *pgx.Conn from database/sql connection pool. It must be released with ReleaseConn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh, that makes sense. e.g. if the connection is create/acquired via AcquireConn()
, it should be returned/released via ReleaseConn()
and not close. Similarly, database.sql.Conn.Raw()
doesn't close connections and releases it when finished.
Thanks for the PR! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing the PR feedback!
} | ||
|
||
dbErr := p.conn.Close(context.Background()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 3 cases Close()
needs to handle:
- Created with
Open()
p.db
andp.conn
are both non-nil
- should release the connection and close the DB
- Created with
WithInstance()
p.db
andp.conn
are both non-nil
- Should release the connection but leave the DB open for the caller of
WithInstance()
to close. However, this isn't the current behavior which is to closep.db
, and existing clients may expect the current behavior, so let's leave it as is. e.g. close bothp.db
and releasep.conn
.
- Created with
WithConnection()
p.db
isnil
andp.conn
is non-nil
- Should leave the connection for the caller of
WithConnection()
to release the connection.
Per this comment, I think we should be releasing connection and never closing it
@@ -56,8 +58,9 @@ type Config struct { | |||
} | |||
|
|||
type Postgres struct { | |||
// Locking and unlocking need to use the same connection | |||
conn *sql.Conn | |||
conn *pgx.Conn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just realized that changing this a from a *sql.Conn
to a *pgx.Conn
will make it harder to factor out common db driver logic between the pgx and postgres drivers...
I don't see any direct pgx functionality being used in this PR. Are there any plans to do so?
Can we go back to using *sql.Conn
? We can use Raw()
or Conn()
to get the underlying *pgx.Conn
if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The benefit of using the pgx.Conn over sql.Conn is you can get a pgx.Conn from a sql.DB -- but you can't get a sql.DB from a pgx.Conn. This is the issue I was running into with a program of mine that uses pgx directly, for some speed benefits and some benefits around de/serialisation that can't be done through database/sql
That said, lib/pg
's README states that it's in maintenance mode, and to use pgx instead, and I'm not aware of any other popular postgres go libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can a pgx.Conn
be converted to a sql.Conn
? I didn't see a way in the docs. In your project(s) can you get a sql.Conn
even though you're using pgx?
That said,
lib/pg
's README states that it's in maintenance mode, and to use pgx instead, and I'm not aware of any other popular postgres go libraries.
migrate
needs to continue supporting lib/pq
since there are still active users even though it's in maintenance mode. There isn't much of a difference between the pgx and postgres drivers (diff the source code to see for yourself how trivial the differences are) and contributors shouldn't need to update both drivers when making changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only way I could find to get a sql.Conn/DB in my program would be to open a separate connection using sql.Open instead of just passing in the pgx.Conn my program already created to do it's database operations, which just doesn't feel that clean to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave the pgx db driver as is for now until we have a usecase for using pgx.Conn
directly. Hopefully, we'll have the postgres and pgx db drivers refactored by then... Thanks again for the PR!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't stdlib.OpenDB()
create a new connection instead of using the existing one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but if a user who's using pgx.Conn
everywhere else wants to call this library then they have to do that anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a db driver is created with an existing connection, the user's expectation is for that connection to be used by migrate
but managed by the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see your point there.
I guess my qualm is just that, without this PR, pgx users that weren't otherwise using the stdlib compatibility layer need to import it and then open a connection with it themselves in ordert to pass it to NewWithDatabaseInstance
. And if you're not using the WithDatabaseIstance
entrypoint then it's still an awkward way in as afaict the URL-style connstrings aren't compatible due to migrate
looking for a pgx://
scheme instead of postgres://
, which pgx itself doesn't do. If you're already bought in to pgx and try to pick up migrate
, it's tricky to figure out how to get the puzzle pieces to slot together. I think pushing for a unified pgx/pq driver that uses the sql.DB
interface will leave that usecase unserved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh. Just ran into this ourselves. We're using pgx/v5 without the stdlib compat layer, and it seems like migrate doesn't really support using an existing pgx connection.
Not a deal breaker, but it would have been nice not having to duplicate a bunch of connection setup/handling code, just for the brief migrate connection. 😉
FYI - pgx release 5.5 has added |
This modifies the pgx driver to actually use pgx directly, and adds a
WithPgxInstance
function, which will let people who are using the pgx driver directly run migrations using the package as a library.