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

[Bug] [SQLite] White space at the end of the SQL string makes execute() throw "Sqlite3 connector: Cannot execute multi-statements" #585

Closed
margaretselzer opened this issue Jul 25, 2024 · 2 comments

Comments

@margaretselzer
Copy link
Contributor

Hi Roland,

You said to keep them coming, so here is another one. :)

You added a check in sqlite3/connection.h in the prepare_statement function that compares the end of the provided statement with the end of the uncompiledTail returned by sqlite3_prepare_v2(). I did not check what this function does, but apparently it stops processing the string when only white-space is left. This makes this newly introduced check fail if there is white space on the end of the string. And a white space comes there easily when one executes an arbitrary SQL statement, especially if the statement is defined as a raw string. E.g.:

std::string myStatement = 
            R"(CREATE TABLE "tblParams" (
            "id"   INTEGER NOT NULL CHECK("id" BETWEEN 0 AND 65535) UNIQUE,
            "paramType"    INTEGER NOT NULL CHECK("paramType" BETWEEN 0 AND 65535),
            "name" TEXT NOT NULL CHECK(length("name") <= (48 - 1)),
            "value"        TEXT NOT NULL CHECK(length("value") <= (256 - 1)),
            PRIMARY KEY("name"));
            )");

Here is my very lazy fix to the issue if you wanted to be lazy as well:

      inline detail::prepared_statement_handle_t prepare_statement(std::unique_ptr<connection_handle>& handle,
                                                                   const std::string& orig_statement)
      {
        auto trimTrailingWhitespace = [](const std::string& str) {
            auto end = std::find_if(str.rbegin(), str.rend(), [](unsigned char ch) {
                return !std::isspace(ch);
            }).base();
            return std::string(str.begin(), end);
        };

        std::string statement = trimTrailingWhitespace(orig_statement);
        // Rest of the function unchanged....

Best,
Marcell

P.S.: I ran into this now when I was finishing a big piece of work and re-ran all my unit tests. For a moment I got really-really desperate as there was no way for me to see what I fucked up. Luckily git came to the rescue and after stepping one commit back in my repo the culprit revealed itself. Sanity preserved! :)

@rbock
Copy link
Owner

rbock commented Jul 26, 2024

Yet another nice find!
And I am glad you remain sane :-)

I uploaded a fix (loosely based on your idea), PTAL.

@margaretselzer
Copy link
Contributor Author

Looks good, leaner than my lazy fix. :)

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

2 participants