sqlite-jdbc icon indicating copy to clipboard operation
sqlite-jdbc copied to clipboard

SQLException when calling setReadOnly

Open Synesso opened this issue 8 years ago • 6 comments

This is an unresolved bug (2014) migrated from bitbucket. I did not find it in github issues and it is still a problem.


Since version 3.7.15-M1, we see the following exception:

Exception in thread "main" java.sql.SQLException: Cannot change read-only flag after establishing a connection. Use SQLiteConfig#setReadOnly and QLiteConfig.createConnection().
at org.sqlite.SQLiteConnection.setReadOnly(SQLiteConnection.java:447)
at org.apache.commons.dbcp.DelegatingConnection.setReadOnly(DelegatingConnection.java:377)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setReadOnly(PoolingDataSource.java:338)
at scalikejdbc.DBConnection$class.readOnlySession(DB.scala:138)
at scalikejdbc.DB.readOnlySession(DB.scala:498)
...

Such behaviour differs from other JDBC drivers.

see also: http://stackoverflow.com/questions/23390278/scalikejdbc-sqlite-cannot-change-read-only-flag-after-establishing-a-connecti

Synesso avatar Aug 07 '17 06:08 Synesso

It seems PRAGMA query_only may be used.

gwenn avatar Aug 11 '17 19:08 gwenn

Any plans to address this in the near future? :)

spaudanjo avatar Dec 10 '17 16:12 spaudanjo

We hit this as well with HikariCP. HikariCP is explicitly setting readOnly to a value which it chooses, which may differ from the setting of the underlying DataSource. The solution was to tell HikariCP to leave it alone, in our case, by setting HCP's readOnly flag to the same as that of SQLite.

There is an argument to say that the result of an "advisory" (doc: "hint") call to sqlite should not be fatal. However, the doc on setReadOnly permits exceptions to be thrown under somewhat loosely defined circumstances ("if a database error occurs").

No strong conclusion about validity.

shevek avatar Feb 22 '18 00:02 shevek

I ran into this at work, and the query_only pragma didn't work for me, I suppose because it interferes with prepared statements. (I couldn't set parameters since there were two statements in the string.) This workaround seems OK, though:

        PoolProperties props = new PoolProperties();
        props.setDriverClassName("org.sqlite.JDBC");
        props.setUrl("jdbc:sqlite:...");

        Properties extraProps = new Properties();
        extraProps.setProperty("open_mode", SQLiteOpenMode.READONLY.flag + "");
        props.setDbProperties(extraProps);
        // This line can be left in or removed; it no longer causes a problem
        // as long as the open_mode code is present.
        props.setDefaultReadOnly(true);

        return new DataSource(props);

timmc-bcov avatar Aug 16 '19 13:08 timmc-bcov

This also worked (in 3.28.0), and was considerably simpler:

String path = ...
SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(true);
return DriverManager.getConnection("jdbc:sqlite:" + path, config.toProperties());

timmc-bcov avatar Sep 14 '19 22:09 timmc-bcov

Would be fixed by #432 i suppose

gotson avatar Jul 29 '22 05:07 gotson