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

fix(sqlite): allow queries without arguments to be persistent #1159

Closed
wants to merge 1 commit into from
Closed

fix(sqlite): allow queries without arguments to be persistent #1159

wants to merge 1 commit into from

Conversation

link2xt
Copy link
Contributor

@link2xt link2xt commented Apr 8, 2021

No description provided.

@link2xt
Copy link
Contributor Author

link2xt commented Apr 8, 2021

The problem is that sqlx forces statements without arguments to be non-persistent. Because of this there is currently no way to make all the queries persistent except by adding arguments to all of them artificially.

This is actually a workaround for deltachat/deltachat-ios#1129 It's likely caused by sqlx finalizing the query too early. It's hard to prove that query is not finalized by the time sqlite3_step is executed because StatementHandle accesses raw sqlite statements via C pointer but does not actually own it and VirtualStatement can be dropped independently, causing the statement to be finalized. Making all statements persistent ensures that they are only finalized when they are evicted from the cache, and this happens after executing 100 other different queries by default, so it's unlikely that they are freed too early. Fixing the original problem would be nice, but I don't see the reason not to allow statements without arguments to be cached anyway and it was unexpected to see them evicted immediately despite not setting .persistent(false) explicitly.

@link2xt link2xt marked this pull request as draft April 8, 2021 19:16
@link2xt link2xt marked this pull request as ready for review April 8, 2021 19:40
@mehcode
Copy link
Member

mehcode commented Apr 9, 2021

So this is actually largely intentional. Any query built from sqlx::query( ... ) ( or that family of functions ) is by-default persistent.

The "low level" execution APIs intentionally do not touch the statement cache.

In other words,

// persistent
sqlx::query("SELECT 10").execute(&mut conn).await?;

// not persistent
conn.execute("SELECT 10").await?;

@link2xt
Copy link
Contributor Author

link2xt commented Apr 9, 2021

So this is actually largely intentional. Any query built from sqlx::query( ... ) ( or that family of functions ) is by-default persistent.

Is it documented somewhere? It then makes sense to add one non-persistent statement like this to the test and close this PR without merging.

@r10s tests this workaround on iOS now, if it works we can just wrap every query in deltachat-core-rust in sqlx::query.

The real bug is that sqlite driver does not guarantee that sqlite3_step-ped statements are not finalized prior to that, because StatementWorker only gets a StatementHandle which does not actually own the statement and VirtualStatement can be dropped asynchronously. Making all queries persistent is a workaround, but not a fix anyway.

@link2xt
Copy link
Contributor Author

link2xt commented Apr 10, 2021

I opened #1165 as a replacement of this PR.

@link2xt link2xt closed this Apr 10, 2021
@link2xt link2xt deleted the sqlite-arguments-persist branch April 10, 2021 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants