getGeneratedKeys() come back
prrvchr opened this issue · 8 comments
Hi all,
It seems that you are determined not to implement the getGeneratedKeys() method.
I don't really understand what prevents this from happening.
If you want to use mass inserts with the command INSERT INTO mytable (Col1, Col2) VALUES (data1, data2), (data1, data2), ...
this is the only method that allows you to recover the primary keys generated automatically in a single pass.
Thanks for your help.
there is no such support in SQLite to retrieve multiple generated values. You can use a RETURNING
clause if you want to get multiple IDs.
Hi gotson,
This is what I understood, but I will have to do this transparently since my end user is LibreOffice Base and he only knows getGeneratedKeys() (in fact it follows the JDBC API)
So as I am obliged to follow the API that Base uses, here is what I am preparing to do:
- when calling executeUpdate() if the option is set to
java.statement.RETURN_GENERATED_KEYS
I add (if the SQL command starts withINSERT
) theRETURNING *
clause. I keep in cache the resultset that this command will return and returns 0 (or the number of lines affected if possible). - When calling the getGeneratedKeys() method I deliver the cached resultset.
If this works, wouldn't it be smarter to integrate this into sqlite-jdbc to make the use of its API fully compatible?
If this works, wouldn't it be smarter to integrate this into sqlite-jdbc to make the use of its API fully compatible?
feel free to send a PR
Here is a possible implementation of getGeneratedKeys().
I was not able to test because I cannot compile, but I am ready to test if I have an archive available.
Can anyone give me instructions on how to compile?
Thanks.
Well I have a version which integrates the modifications and which remains to be tested. For now everything is working fine...
I understand that editing the SQL commands in the sqlite-jdbc driver may seem a bit messy, but in fact I am convinced that this is the right way to do it because:
- It makes the driver fully compatible with JDBC.
- Normally we are able to obtain the desired columns in response to an insert, I have not yet tested...
- This does not prevent the old way of working (select last_insert_id) which by the way was already doing a bit of the same thing.
- Although this correction seems a bit simplistic, I think this will prove particularly robust, especially if we follow the JDBC specifications to the letter (a single SQL command per call to executeUpdate(), etc...)
- And the icing on the cake: this will allow massive insert (1000 records per two SQL commands is possible while the old implementation required 2000 SQL queries).
The archive if you want to test: sqlite-jdbc-3.45.1.2-SNAPSHOT.jar
Well, I produced a version that allows you to follow the JDBC specifications to the letter, but @gotson doesn't seem ready to integrate it.
I believe that it refuses to modify the SQL requests that the driver processes even though this is the only way to follow the JDBC specifications. It's a shame.
For the moment a version is available on my fork of sqlite-jdbc.
I have just updated sqlite-jdbc-3.45.1.3-SNAPSHOT.jar to comply with JDBC 4.1, namely:
- The
java.sql.DatabaseMetaData.supportsGetGeneratedKeys()
method answerstrue
. - The
java.sql.DatabaseMetaData.generatedKeyAlwaysReturned()
method answerstrue
. - The
java.sql.Statement.executeUpdate(String sql, int autoGeneratedKeys)
method works as follows:- If autoGeneratedKeys is equal to
java.sql.Statement.RETURN_GENERATED_KEYS
and the SQL command begins withINSERT
orREPLACE
and it only includes one SQL command then the records affected by the SQL command will be accessible by thejava.sql.Statement.getGeneratedKeys()
method (all columns in the table will be returned). - Otherwise the SQL command will be executed without influencing the operation of
getGenerateKeys()
which allows you to interweave queries before having to retrieve the records usinggetGeneratedKeys()
...
- If autoGeneratedKeys is equal to
- The
java.sql.Statement.executeLargeUpdate(String sql, int autoGeneratedKeys)
method works like the previous one... - The
java.sql.Statement.executeUpdate(String sql, String[] columnNames)
method allows you to get only the requested columnNames ingetGeneratedKeys()
. - The
java.sql.Statement.executeLargeUpdate(String sql, String[] columnNames)
method works like the previous one... - The
java.sql.Statement.executeUpdate(String sql, int[] columnIndex)
method is not supported. - The
java.sql.Statement.executeLargeUpdate(String sql, int[] columnIndex)
method is not supported. - The
java.sql.Statement.execute(String sql, int autoGeneratedKeys)
method is not supported (you need to useexecuteUpdate()
thengetGenratedKeys()
methods). - The
java.sql.Statement.execute(String sql, String[] columnNames)
method is not supported (you need to useexecuteUpdate()
thengetGenratedKeys()
methods). - The
java.sql.Statement.execute(String sql, int[] columnIndex)
method is not supported. - The
java.sql.Connection.prepareStatement(String sql, int autoGeneratedKeys)
method work same asexecuteUpdate(String sql, int autoGeneratedKeys)
concerning the use ofgetGeneratedKeys()
which must however be accessed after each call to theexecuteUpdate()
orexecuteLargeUpdate()
method. - The
java.sql.Connection.prepareStatement(String sql, String[] columnNames)
method work same asexecuteUpdate(String sql, String[] columnNames)
concerning the use ofgetGeneratedKeys()
which must however be accessed after each call to theexecuteUpdate()
orexecuteLargeUpdate()
method. - The
java.sql.Connection.prepareStatement(String sql, int[] columnIndex)
method is not supported.
I would like to point out to you that the new operating mode of this driver is not at all the same as that used in the gotson driver. It probably requires rewriting your programs but it follows JDBC 4.1 specifications.
And finally I hope that @gotson will change his mind about integrating this PR because I don't really want to maintain sqlite-jdbc...