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

Check for multiple statements in prepare #1147

Open
thomcc opened this issue Mar 27, 2022 · 9 comments
Open

Check for multiple statements in prepare #1147

thomcc opened this issue Mar 27, 2022 · 9 comments

Comments

@thomcc
Copy link
Member

thomcc commented Mar 27, 2022

Consider checking by default if someone does something like conn.prepare("<stmt 1>; <stmt 2>"). This will silently only run stmt 1, which is probably not what the user wants.

Right now, I believe we have some tail checking here, but I think it's only under extra-check feature. It also might be disabled then too. I think we should probably check this always, since I don't see a case where anybody wouldn't want this detected.

@gwenn
Copy link
Collaborator

gwenn commented Mar 27, 2022

You may have false positive with some trailing comments "SELECT 1; /comments/;"

@thomcc
Copy link
Member Author

thomcc commented Mar 27, 2022

Yeah. I think that's probably fine.

@jvasile
Copy link

jvasile commented Apr 26, 2022

I ran into this issue in my own code and worked up a crate to quickly split strings containing multiple sqlite statements and also to tell me when I'm dealing with multiple sql statements. It's standalone functionality, so I put it in its own crate, but I could easily turn it into a PR.

sql_split is O(n) to split, where n is the length of the string. It also has a short-circuiting func, is_multiple, that just tells you if you're dealing with a multi-statement string.

If this is useful to rusqlite, I'd be happy to turn it into a PR.

@gwenn
Copy link
Collaborator

gwenn commented Apr 26, 2022

@thomcc
Copy link
Member Author

thomcc commented Apr 26, 2022

I think we should take the current approach, where we used the tail returned by SQLite. This has downsides, but is much less error-prone than trying to parse it ourselves IMO.

@jvasile
Copy link

jvasile commented Apr 26, 2022

Yes, that's right. I thought it could be done simply, but after chasing down a bunch of edge cases and handling virtual tables, I think this "simple" bit of code will quickly get hairier than its worth.

@d-bucur
Copy link

d-bucur commented Sep 9, 2023

Would also be great if there was an equivalent method for multiple statements, like there is for execute_batch. The only way to do that currently is to manually format the string and send it to execute_batch

@gwenn
Copy link
Collaborator

gwenn commented Sep 12, 2023

We should be able to check at compile time that only a single statement is provided with sqlite3-parser if the SQL is a static string.

@gwenn
Copy link
Collaborator

gwenn commented Feb 19, 2024

There is a new single! macro here.
But it cannot be used inside rusqlite existing method.
For example, it cannot work if put inside Connection::execute method.
I can work only if used like this:

let changes = conn.execute(single!("DELETE FROM my_table WHERE col = ?"), ...)?;

which is not user-friendly...
Do you know how to make it nicer (without duplicating rusqlite public API) ?

Edit: I am going to try conditional attribute-like macro => doesn't work

    #[inline]
    #[cfg_attr(feature = "rusqlite-macros", single())]
    pub fn execute<P: Params>(&self, sql: &str, params: P) -> Result<usize> {

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

No branches or pull requests

4 participants