Question

I'm developing from Mac OS X a java application that uses a SQLite database using JDBC driver.

The code works perfectly fine on the mac, but I can't use batch inserts using PreparedStatements on my Windows box.

EDIT: this also doesn't work with simple Statements that contains a single INSERT INTO instructions (CREATE TABLE works fine).

My code is basically:

Table creation:

    final String sql = "CREATE VIRTUAL TABLE " + TABLE_NAME + " USING fts3("
            + KEY_NOM + ", "
            + KEY_PRENOM + ", "
            + KEY_ADRESSE + ", "
            + KEY_ADRESSE2 + ", "
            + KEY_ADRESSE3 + ");";

    try {
        final Statement s = mConnection.createStatement();
        s.execute(sql);
    } catch (final SQLException e) {
        L.e("Unable to create table: "+sql+"! "+e);
    }

PreparedStatement creation:

    String sql =
            "INSERT INTO "+TABLE_NAME
                    +" ("
                    + KEY_NOM + ", "
                    + KEY_PRENOM + ", "
                    + KEY_ADRESSE + ", "
                    + KEY_ADRESSE2 + ", "
                    + KEY_ADRESSE3 + ") "
                    + " VALUES (?, ?, ?, ?, ?)";

    mConnection.setAutoCommit(false);
    final PreparedStatement prep = mConnection.prepareStatement(sql);

Then there is a loop that parses a CSV file, and at each line the following code is called:

        int i = 1;
        prep.setString(i++, ""+lawyer.nom);
        prep.setString(i++, ""+lawyer.prenom);
        prep.setString(i++, ""+lawyer.adresse);
        prep.setString(i++, ""+lawyer.adresse2);
        prep.setString(i++, ""+lawyer.adresse3);
        prep.addBatch();

When the parsing of the CSV file is over, the following is executed:

        final int[] res = prep.executeBatch();
        mConnection.setAutoCommit(true);
        for (int r: res) {
            if (r != 1) {
                L.e("Error adding entry!");
            }
        }

When I call mConnection.setAutoCommit(true);, the INSERTs statements are executed when it raises the following exception:

java.sql.SQLException: SQL logic error or missing database
at org.sqlite.DB.throwex(DB.java:288)
at org.sqlite.DB.exec(DB.java:68)
at org.sqlite.Conn.setAutoCommit(Conn.java:166)

Tested environments:

  • MacBookAir - Mac OS 10.6 - x64 - Java 1.6.31 - works fine (my development station)
  • Laptop - Windows 7 - x64 - Java 1.6.30 - works fine
  • MacBook - Mac OS 10.5 - x64 - Java 1.6.26 - works fine
  • Desktop - Windows Vista - x86 - Java 1.? - doesn't work
  • Server - Windows Server 2003 - unknown arch, x86 guessed - Java 1.7 - doesn't work
  • Desktop - Windows Seven - x86 - Java 1.7 - doesn't work
  • Desktop - Windows XP - x86 - Java 1.6.31 - doesn't work

It seems that only x64 hosts can make this to work. The following jars are used:

  • swt : included the x64 version on x64 hosts, and x86 version on x86 hosts
  • sqlitejdbc-v056: apparently this is x86 and x64 compatible
  • opencsv: this doesn't contain native code
  • iText-2.1.7 and iTextRTF: this doesn't contain native code

So maybe the JDBC SQLite driver isn't fully x86-compatible. I'll try to investigate more.

Was it helpful?

Solution

TL;DR:
my SQLite JDBC driver was using native code and was not fully compatible with 32 bits processors.

Two possible fixes:

  • Use Xerial, a native SQLite JDBC driver that works fine on both Mac OS X 64 bits and Windows 32 bits
  • Use a pure java implementation fixed the issue, at the cost of performance.

Explanation:

I've spent the past 3 days banging my head to the wall with an SQLite exception saying "SQL logic error or missing database". I won't comment on the exception text that includes two possible, different errors without saying which could be the cause. I won't comment either on the fact that none of the two errors mentioned in the exception text was the cause of the issue.

Facts:

  • SQLite exception stating "SQL logic error or missing database"
  • Using jsqlitejdbc v056
  • The driver is able to create tables
  • The driver is able to select information from tables
  • The database file is not corrupted, ie. it is possible to open it with a sqlite client and insert data to the tables
  • The driver is unable to insert data into tables

What solved my issue is replace sqlitejdbc-v056.jar which contains native code by sqlitejdbc-v056-pure.jar which is a pure-java implementation.

I hope that all the users that had this issue will be able to quickly see this, and not lose 3 days on this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top