Implement BLOB reading for sqlite#4994
Conversation
8d1cc15 to
90e35aa
Compare
diesel/src/sqlite/connection/mod.rs
Outdated
| NonZeroI64::new(self.raw_connection.last_insert_rowid()) | ||
| } | ||
|
|
||
| pub fn get_blob<'conn, 'query, U>(&'conn self, primary_key: i64) -> Result<sqlite_blob::SqliteBlob<'conn>, Error> |
There was a problem hiding this comment.
Documentation missing here, yes.
This patch implements BLOB reading via the sqlite3_blob_read() API. Co-authored-by: Marcel Müller <neikos@neikos.email> Signed-off-by: Marcel Müller <neikos@neikos.email> Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
90e35aa to
ebed4d6
Compare
|
Thanks for working on this. I (or someone else) will try to have a look at the implementation in the next days/weeks. cc @LucaCappelletti94 as he has done quite a lot of Sqlite api additions in the last weeks and might also help here |
|
One thing I'd like to mention wrt. Blobs in SQLITE and the current interface is that one cannot hold Blobs while executing any other command. This is fine and the easiest way from a technical standpoint. However I feel it does preclude from more interesting applications like having proper-streaming or similar backed by a sqlite database. The docs seem fairly clear on this:
As well as in
This means that the lifetime of a Blob is tied to a database, but not in a way that Rust can properly check. The current interface also means that users cannot move a blob handle from where it was created (due to blob being bound to the lifetime of the connection). As far as I can tell it is safe to not have the lifetime. However, this would introduce the hazard of panicking when dropping the SQLite connection while having any blobs open (as it would return SQLITE_BUSY on close). None of these are real 'problems' IMO, just decisions to be made one way or another. I believe a potential path forward could be something akin to a |
weiznich
left a comment
There was a problem hiding this comment.
Thanks for working on this. Overall this looks like a good start already. I've left a bunch of comments around the API design I would like to discuss and potentially address before merging.
I still need to look a the tests to decide if we want to add more cases.
Finally I think that's a feature that deserves a changelog entry, so please at it to the top level Changelog.md file.
| } | ||
| } | ||
|
|
||
| impl SqliteBlob<'_> { |
There was a problem hiding this comment.
We likely also want to implement Write?
That doesn't necessarily need to be done in this pr, but the design should allow it.
There was a problem hiding this comment.
Yes, I would like to include that later down the road!
| table_name.as_c_str().as_ptr(), | ||
| column_name.as_c_str().as_ptr(), | ||
| pkey, | ||
| 0, |
There was a problem hiding this comment.
We need a parameter to control this flag. Maybe even as compile time flag (generic parameter?)
Otherwise an enum could also be fine. For now that could just have a read variant and be marked as #[non_exhaustive]
There was a problem hiding this comment.
I see what you mean here. If you don't mind, I would include Write functionality in this very same PR later down the road and do that bit of refactoring for a generic parameter (or something like that) then.
But first I would like to get the Read functionality in a shape that's ACK'd by you or other diesel maintainers!
There was a problem hiding this comment.
It's fine to also postpone the write functionality to a later PR.
This comment was mostly about API design.
|
I pushed a fixup to address a number of your review points, where I did not have any questions! Also included some |
| NonZeroI64::new(self.raw_connection.last_insert_rowid()) | ||
| } | ||
|
|
||
| pub fn get_blob<'conn, 'query, U>( |
There was a problem hiding this comment.
Undocumented public method, maybe a documentation with doctests would be nice to have?
weiznich
left a comment
There was a problem hiding this comment.
Thanks for the update and sorry for taking that long to review it :(
The API design now mostly looks good to me, beside the minor note about close. I would be happy to merge this with the remaining minor things resolved, a bit of documentation + a changelog entry added.
| ffi::code_to_str(err_code) | ||
| } | ||
|
|
||
| #[doc(hidden)] |
There was a problem hiding this comment.
Minor nit: I usually put these traits in a local mod private {} and then reexport them as crate local via pub(crate) use self::private::HasDatabaseAndTableName; in the parent scope. That ensures that they are really not usable by downstream crates.
| table_name.as_c_str().as_ptr(), | ||
| column_name.as_c_str().as_ptr(), | ||
| pkey, | ||
| 0, |
There was a problem hiding this comment.
It's fine to also postpone the write functionality to a later PR.
This comment was mostly about API design.
| /// Using the handle after calling this function is an error if not otherwise stated. | ||
| pub fn close(&mut self) -> Result<(), crate::result::Error> { |
There was a problem hiding this comment.
Maybe rather expose this publically as consuming method (so pub fn clone(self)) and only internally have a fn close_intern(&mut self) method that can be shared between Drop and this function?
Seems like an easy way to remove this potential error path
This patch implements BLOB reading via the sqlite3_blob_read() API.
--
We (@weiznich and I) talked about this on mastodon.
This is a first proposal to see what you think of it.
This patch would not have been possible without the tremendous help from @TheNeikos who is mentioned as a co-author in the patch. Thank you very much for your help ❤️