implement LoadQuery for batch insert statements for sqlite connection#4616
Conversation
…qliteConnection` This implementation allows running insert statements with returning clause.
…5` as it requires returning clause support
|
Thanks for opening this PR. There seems to be still a failing CI job here: https://github.com/diesel-rs/diesel/actions/runs/15237082999/job/42852408104?pr=4616. I did not look into the details yet, but that's something that needs to be addressed.
I would suggest to return a "private" wrapper type that implements
That would be required. |
|
Thank you for your feedback.
For some reason, the same code causes
I was hoping to use an already defined iterator instead of defining a new one, such as the I will try to write some tests. Until completing all the tasks, I think converting this PR to draft might be the best. |
I'm not sure if it's related to 1.82. It might also be due to building with
If |
I just checked this issue by compiling this PR with a few rust releases with
Nice, I will check whether |
|
I did a quick search which rustc change did introduce that changed behavior just to make sure that this is not by accident and that pointed to rust-lang/rust#130654, which seems to be reasonable. So I suggest to just bump the minimal supported rust version to 1.84. That needs to be done here, here and here. |
…on for all ContainsDefaultableValue values
…qliteConnection` where query contains defaultable value.
…d-query-for-sqlite-batch-insert
…use with sqlite connection when the values contains defaultable value
While this code compiles fine with Rust 1.87, it does not compile with 1.84. It looks like trait bounds are being improved with newer version of Rust compiler.
…` implementations
|
I believe this PR is ready for the review :). I would like to thank you for all your guidance and feedback. |
weiznich
left a comment
There was a problem hiding this comment.
Thanks for the update. This looks already really good in terms of implementation.
I added another bunch of mostly minor comments about some details that need to be adjusted. As soon as those are fixed, this should be fine to be merged.
| .collect::<Vec<_>>(); | ||
|
|
||
| Ok(Box::new(results.into_iter())) |
There was a problem hiding this comment.
Would it be possible to skip the collect here and return the iterator directly?
There was a problem hiding this comment.
We might also want to mention the new feature in the Changelog 😉
diesel/src/query_builder/insert_statement/insert_with_default_for_sqlite.rs
Show resolved
Hide resolved
| .next() | ||
| .ok_or(crate::result::Error::NotFound)?; | ||
|
|
||
| results.push(result); |
There was a problem hiding this comment.
We also want to unwrap the inner result to stop the transaction from being comited in the error test. We likely want to have a test case for this (Just insert a reasonable item + a duplicated item and make sure that none are in the database)
| results.push(result); | |
| results.push(Ok(result?)); |
(If we would like to be even more correct: We should roll back the transaction for anything but deserialization errors to perfectly mirror the batch variant)
There is a test for batch inserts without returning here:
diesel/diesel_tests/tests/insert.rs
Line 821 in efcb1e7
Otherwise it sounds like a good idea to quickly go over the tests cfg out for sqlite in that file and check which ones can now be enabled.
There was a problem hiding this comment.
Thank you for pointing this out. I updated code to bubble up errors earlier other than deserialization one as you said. And added a few case to test this. Please do not hesitate to suggest any other improvement for both code and tests (current implementation does a match on the result but there might be a better way to do it).
| .next() | ||
| .ok_or(crate::result::Error::NotFound)?; | ||
|
|
||
| results.push(result); |
diesel/src/query_builder/insert_statement/insert_with_default_for_sqlite.rs
Show resolved
Hide resolved
diesel/src/query_builder/insert_statement/insert_with_default_for_sqlite.rs
Show resolved
Hide resolved
| }; | ||
|
|
||
| Ok(crate::query_dsl::load_dsl::LoadIter { | ||
| cursor: <_ as crate::connection::LoadConnection<B>>::load(conn, query)?, |
There was a problem hiding this comment.
Indeed 😃 , but I found another way to run the query, which eliminated using LoadIter explicitly. I reverted changes related to making LoadIter pub(crate).
…to ensure no rows are inserted
weiznich
left a comment
There was a problem hiding this comment.
Looks good now, thanks for updating.
(I just pushed a changelog entry, otherwise this is now ready to be merged)
This is a draft PR requesting for comments. It allows running insert statements with returning clause for sqlite connection. There are a few remaining tasks, which needs a little bit guidance, to consider this PR as ready:
internal_load(instead of currently used boxed iteration).LoadQueryforYescase which requires running multiple insert statements. I can implement this ifNocase looks good.Consider using a generic connection with backendIt looks like trait bounds resolution is being improved with newer version of Rust compiler. In the future, it might be possible to use a generic connection bounded bySqlite(similar toExecuteDslimplementation). I tried to do this but it caused conflicting implementation error.Sqlitebackend. For now, we can continue using directlySqliteConnection.conflicting implementationerror. Check this and this messages for more informationWith this PR, following example should compile successfully: