-
-
Notifications
You must be signed in to change notification settings - Fork 481
Should Statement be a token? #346
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
Comments
cc @jwilm |
Hmm, portals still imply a need for internal mutability :( |
We can drop impl<'a> Transaction<'a> {
pub fn bind(&mut self, statement: &Statement, params: &[&ToSql]) -> Result<Portal> { ... }
pub fn query_portal(&mut self, portal: &Portal, rows: u32) -> Result<Rows> { ... }
} The portal will be automatically closed when the active transaction/savepoint closes and we lose the static prohibition of that similarly to statements after the connection closes. |
Have you put any thought into having I'm thinking about this purely from the non-tokio perspective; I haven't really thought about that side of the library at all. |
Rc doesn't really work since you wouldn't be able to save the statements across use of a pooled connection due to the lack of a Send bound. |
Ah right, connection poolers.. I don't see the cons to your approach as particularly negative. The overloading approach makes sense and aligns with my own thoughts about it.
Panicking seems strong. A globally unique statement name seems like a nice solution. |
There's also the possibility that if someone puts a connection pooler between this library and the server that the statement wouldn't be on the same connection anyhow. |
Quite like the API proposed; I think the static-checking advantages of One comment on LazyRows: I personally feel it repeats the functionality of "DECLARE CURSOR" and "FETCH" commands already provided by postgresql (and already working nicely via rust-postgres). Also, the concern of reading a large number of rows is a sync-only concern, as tokio-postgres anyway makes it a Stream. Are portals also aimed at the same use-case as LazyRows only? |
You can achieve the same thing via SQL-level cursors for sure. LazyRows doesn't use that, but rather a feature of the postgres protocol that should I think be a bit more efficient network transfer-wise.
Portals are a bit more powerful than that - you have control over when you want more rows to be sent. That means if you for example don't know how many rows you'll need to you can just stop receiving them with a portal rather than having to read and discard them all with a normal query. |
Nice! Would you say it has lesser round-trips? With CURSOR + FETCH, we have about n+1 round-trips, if I want to read the total output in n chunks.
Ah, I see: even with tokio-postgres, a long query can not be aborted midway without reading all the data the server is sending. I didn't realize that. |
This is now implemented on the master branch. |
A statement is currently modeled as a type that borrows the connection and has methods defined to query/execute it. This is conceptually nice, but has a few issues in practice:
prepare_cached
method, but if that doesn't work for your use case you have to write unsafe code to package the statement alongside its connection.&self
and connection to have an internalRefCell
. This means that we have to dynamically check that the connection/transaction you're using is the "active" one.An alternate approach is for statement to be a "token" which does not borrow the connection. It has no methods defined on itself, but is instead provided to methods on the connection for use. It holds onto a channel sender and on drop enqueues itself for cleanup. The connection periodically checks the cleanup list and closes all dead statements. This is the approach taken in tokio-postgres.
A high level API sketch:
RefCell
inside ofConnection
.prepare_cached
can go away since you can save off statements how you see fit. r2d2-postgres will need to have some logic to allow you to attach statements to the pooled connection probably.Connection::query
andConnection::execute
methods get a bit longer. We could overload a single set of methods with a trait bound that takes both query strings and statements?The text was updated successfully, but these errors were encountered: