"The given constant tells the driver whether it should make
auto-generated keys available for retrieval. This parameter is ignored
if the SQL statement is not an INSERT statement, or an SQL statement
able to return auto-generated keys (the list of such statements is
vendor-specific). "
Here's a simple test class to demonstrate this problem:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class PostgrePrepareStatementTest {
public static void main(String[] args) throws
InstantiationException, IllegalAccessException, ClassNotFoundException,
SQLException {
Class.forName("org.postgresql.Driver").newInstance();
String url = "jdbc:postgresql://localhost:5432/testdb";
Connection conn = DriverManager.getConnection(url, "user",
"password");
PreparedStatement pStmt = conn.prepareStatement("select * from
test_table", Statement.RETURN_GENERATED_KEYS);
System.out.println(pStmt.toString());
pStmt.execute();
}
}
When run this prints "select * from test_table RETURNING *" - which is
invalid - and an exception is thrown:
Exception in thread "main" org.postgresql.util.PSQLException: ERROR:
syntax error at or near "RETURNING"
Position: 26
at
org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2062)
at
org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1795)
at
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:479)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:367)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:360)
at
com.smilehouse.PostgrePrepareStatementTest.main(PostgrePrepareStatementTest.java:17)
I have tested this with driver version 8.4-701 (both JDBC3 and JDBC4).
The PostgreSQL version was 8.4.
-Heikki Hiltunen
--
Sent via pgsql-jdbc mailing list (pgsql...@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-jdbc
Yeah, the driver just blindly tacks a " RETURNING *" to the end of the
SQL string if you specify RETURN_GENERATED_KEYS. I'm tempted to do
something like this:
*** AbstractJdbc3Connection.java 23 Dec 2009 10:28:40 +0200 1.21
--- AbstractJdbc3Connection.java 23 Apr 2010 18:49:44 +0300
***************
*** 359,364 ****
--- 359,381 ----
throws SQLException
{
checkClosed();
+
+ /*
+ * We implement fetching auto-generated keys by tacking a
+ * " RETURNING *" to the end of the string. Don't try to do that
+ * with other statements than INSERT/UPDATE/DELETE.
+ *
+ * XXX this gets fooled by comments at the beginning of the SQL string
+ */
+ if (autoGeneratedKeys != Statement.NO_GENERATED_KEYS)
+ {
+ String trimmedSql = sql.trim();
+ if (!trimmedSql.regionMatches(true, 0, "INSERT", 0, 6) &&
+ !trimmedSql.regionMatches(true, 0, "UPDATE", 0, 6) &&
+ !trimmedSql.regionMatches(true, 0, "DELETE", 0, 6))
+ autoGeneratedKeys = Statement.NO_GENERATED_KEYS;
+ }
+
if (autoGeneratedKeys != Statement.NO_GENERATED_KEYS)
sql = AbstractJdbc3Statement.addReturning(this, sql, new
String[]{"*"}, false);
But that's not very bullet-proof, and will fail to detect the statement
as an INSERT if it e.g begins with a comment. We could add a mini-parser
to detect comments too, but it's not a very robust approach.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com