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

SQLException: The prepared statement has been finalized #731

Open
bajinsheng opened this issue May 10, 2022 · 5 comments
Open

SQLException: The prepared statement has been finalized #731

bajinsheng opened this issue May 10, 2022 · 5 comments
Labels
waiting for feedback Waiting for a feedback from the issue creator

Comments

@bajinsheng
Copy link

bajinsheng commented May 10, 2022

Hi, when I execute the query ";" in the JDBC and get the "The prepared statement has been finalized" error, but there is no error when I execute the query ";" in the cli.

Reproducible test case:

...
Connection connection = connection = DriverManager.getConnection("jdbc:sqlite:sample.db");
Statement statement = connection.createStatement();
statement.executeUpdate(";");
...

The stack trace:

java.lang.AssertionError: ;
        at Sample.Main(Sample.java:17)
Caused by: java.sql.SQLException: The prepared statement has been finalized
        at org.sqlite.core.NativeDB.throwex(NativeDB.java:406)
        at org.sqlite.core.NativeDB.step(Native Method)
        at org.sqlite.core.DB.execute(DB.java:962)
        at org.sqlite.core.CoreStatement.exec(CoreStatement.java:74)
        at org.sqlite.jdbc3.JDBC3Statement.execute(JDBC3Statement.java:41)

SQLite3 JDBC version:
3.36.0.3

Is it expected?

@gotson
Copy link
Collaborator

gotson commented Jul 27, 2022

I'm wondering why you would execute a single command containing only ; though.

@gotson gotson added the waiting for feedback Waiting for a feedback from the issue creator label Jul 27, 2022
@bajinsheng
Copy link
Author

It may be randomly generated by my application when converting external data to SQL query.

@gotson
Copy link
Collaborator

gotson commented Aug 1, 2022

I just tried the following:

@Test
    public void issue731() throws Exception {
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        stmt.executeUpdate(";");
        stmt.close();
        conn.close();
    }

And i don't get any exception.

Can you try with the latest snapshot version to confirm on your side?

@pyckle
Copy link
Contributor

pyckle commented Aug 3, 2022

@bajinsheng - I think you made a mistake in your test case that fails - I think you intended to call executeQuery(), not executeUpdate(). executeQuery() is a noop. See: https://www.sqlite.org/c3ref/exec.html

I think the bug here is that we throw the wrong error from the wrong place.

Internally, sqlite3 gives us a null pointer from sqlite3_prepare_v2 (https://www.sqlite.org/draft/c3ref/prepare.html) when we create this query.

Oddly enough, I don't get an error from the return code from this function. I don't see that the sqlite3 documentation defines the return code for this scenario, but it's definitely possible that I am missing something.

From the docs:

*ppStmt is left pointing to a compiled prepared statement that can be executed using sqlite3_step(). If there is an error, *ppStmt is set to NULL. If the input text contains no SQL (if the input is an empty string or a comment) then *ppStmt is set to NULL. The calling procedure is responsible for deleting the compiled SQL statement using sqlite3_finalize() after it has finished with it. ppStmt may not be NULL.

Anyways, the exception is thrown because the pointer is set to null with a successful return code. When we try to use it, we check whether it's null first, and throw the already closed exception if it is.

@gotson - I think the issue here is that we should be checking for null in the prepared statement made with sqlite3_prepare_v2. If it is null, we should throw an SQLException that ";" is an invalid query, rather than bombing later. Alternatively we could return a empty ResultSet. What do you think? I haven't seen anything within the JDBC spec for what to do when a noop query is run.

@gotson
Copy link
Collaborator

gotson commented Aug 4, 2022

@pyckle i was thinking that in doubt we should check what's the behaviour with another JDBC driver, maybe the PostgreSQL one. What do you think?

I know SQLite itself is usually following the PG implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for feedback Waiting for a feedback from the issue creator
Projects
None yet
Development

No branches or pull requests

3 participants