Skip to content
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

support unnamed statements #1067

Closed
wants to merge 3 commits into from
Closed

support unnamed statements #1067

wants to merge 3 commits into from

Conversation

devsnek
Copy link

@devsnek devsnek commented Sep 25, 2023

Refs: #1017
Refs: #1044

This PR implements unnamed statements when querying the database. This is not a performance optimization. The library still uses a "prepared" statement in order to parse the columns and types of queries, so round trips are not reduced (although we don't need to send an additional query to clean up the named prepared statement, which is nice). The reason for this change is to enable queries against pgbouncer instances which are running in transaction or statement pooling modes. A named prepared statement cannot be used in these modes, because the connection may be swapped from under you between preparing the statement and using it.

I found this helpful in understanding what was going on while I was debugging this problem: https://jpcamara.com/2023/04/12/pgbouncer-is-useful.html#prepared-statements

While writing this I also changed the "unexpected message" errors to help me debug, but I can remove that from this PR if you feel it is out of scope.

@sfackler
Copy link
Owner

This will break pipelined queries.

@devsnek
Copy link
Author

devsnek commented Sep 25, 2023

@sfackler Can you elaborate on this? My understanding is the parse/bind/execute is sent as a single unit, and would therefore be unaffected by pipelining?

@sfackler
Copy link
Owner

Oh wait, the same query is prepared both at preparation time and at each use? I guess that works but it feels like an pretty janky setup, and defeats the purpose of statement preparation.

IMO, if you're running pgbouncer in transaction mode you should just make sure you scope your statements within the transaction that uses them. If you're using it in statement mode, either don't, or deal with simple_query.

@devsnek
Copy link
Author

devsnek commented Sep 25, 2023

Yeah the prepare flow is only for this library to get a handle on those types that it expects. It is definitely not ideal BUT it is not worse than the current implementation of doing a named prepare for every query. I don't think I agree that simple_query is an acceptable solution as you have to go back to worrying about sql injection. It also doesn't return something that works with the To/FromSql traits, which is a huge usability problem 😬

@sfackler
Copy link
Owner

It is definitely not ideal BUT it is not worse than the current implementation of doing a named prepare for every query.

It is worse - it means you cannot avoid preparing frequently-executed queries on every execution.

@devsnek
Copy link
Author

devsnek commented Sep 26, 2023

it means you cannot avoid preparing frequently-executed queries on every execution.

To be clear:

let statement = client.prepare("...").await?;
client.query(statement, &[]).await?;
client.query("...", &[]).await?;

The first example is not changed at all by this PR. The second example behaves almost the identically, except that it uses an unnamed statement instead of a named statement. No additional network calls or round trips are introduced in either case by this PR. This matches how other postgres libraries (including libpq) generally behave.

@devsnek
Copy link
Author

devsnek commented Sep 28, 2023

@sfackler any chance of this getting merged? I really don't want to have to maintain a fork of this library... If you're still against this for some reason, maybe it could be behind a cargo feature?

@fbjork
Copy link

fbjork commented Oct 5, 2023

@sfackler We would love to see this one merged too as we're about to launch the Postgres connector at Grafbase.

@janpio
Copy link

janpio commented Oct 6, 2023

We at @prisma would also be very interested in this.

Right now, we do a weird dance of wrapping all queries in transactions, and each time deallocating the named prepared statements when talking to a PgBouncer instance in transaction mode - which adds up to 3 additional roundtrips for 1 query and has an obvious very bad effect on our performance.

With unnamed (but still prepared) statements we could probably avoid this.

@pimeys
Copy link

pimeys commented Oct 12, 2023

It would be extra cool to get this merged... Now, again, needing to use a fork of this crate for a production system.

@devsnek
Copy link
Author

devsnek commented Nov 1, 2023

@sfackler any word here?

@devsnek
Copy link
Author

devsnek commented Nov 14, 2023

@sfackler anything? should i just close this? i really don't want to fork...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants