Thread: Problem with executeBatch and "A result was returned when none was expected"
I've been trying to batch create a bunch of records using stored procedures and the executeBatch() method (so I can get back the generated PKID's) with no luck. I've tried PostgreSQL 8.4.2 with the 8.4-701.jar and 8.4-702.jar on OS X, PostgreSQL 9.0.3 with the latest 9.0 JAR on both OS X and Ubuntu Linux, all under JDK 1.6, and all with the same results. When I try to call executeBatch, I get a BatchUpdateException with the message: "A result was returned when none was expected".
Here's my simple example that I whittled down from my larger application:
import java.sql.*;
public class Check {
public static void main(String[] args) throws Exception {
try {
Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection(
"jdbc:postgresql://localhost/mydb", "postgres", null);
con.setAutoCommit(false);
"INSERT INTO users (email,password,login) VALUES (?,?,?)",
Statement.RETURN_GENERATED_KEYS);
stmt.setObject(1, "myemail@gmail.com");
stmt.setObject(2, "test");
stmt.setObject(3, "sbowman");
stmt.addBatch();
stmt.executeBatch();
System.out.println("Got " + stmt.getGeneratedKeys());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
System.out.println(e.getMessage());
System.out.println(e.getNextException().getMessage());
}
}
}
This always, in all settings described above, returns (raised from the stmt.executeBatch() line):
Batch entry 0 INSERT INTO users (email,password,login) VALUES ('myemail@gmail.com','test','sbowman') RETURNING * was aborted. Call getNextException to see the cause.
A result was returned when none was expected.
Here's the stacktrace:
java.sql.BatchUpdateException: Batch entry 0 INSERT INTO users (email,password,login) VALUES ('myemail@gmail.com','test','sbowman') RETURNING * was aborted. Call getNextException to see the cause.
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2586)
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleResultRows(AbstractJdbc2Statement.java:2550)
at org.postgresql.core.v3.QueryExecutorImpl$1.handleResultRows(QueryExecutorImpl.java:437)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1747)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:407)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2725)
at Check.main(Check.java:21)
I think my code is correct. If I modify the above code to use a MySQL database instead of a PostgreSQL database, everything works fine and I do get the PKID's generated by the database back.
I was under the impression that getGeneratedKeys() was now working, since 8.4-701.jar, but for the life of me I can't figure out how.
If I skip using the batch methods and insert user records one at a time, calling "stmt.execute()", then the getGeneratedKeys() call returns a ResultSet with the generated ID in it. So execute() works, but executeBatch() doesn't.
Any suggestions or pointing out my code flaws would be most appreciated. Or does executeBatch just not work? I've been battling this issue most of the day and I'm just about at my wits' end. Should I just give up and switch to calling execute() one at a time? Seems far less efficient, but at least it seems to work.
Thanks,
Sean
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Dave Cramer
Date:
Sean, Apparently the only database it works for is mysql. It certainly works for single prepared statements. Dave On Wed, Mar 16, 2011 at 5:14 AM, Sean Bowman <pico303@gmail.com> wrote: > I've been trying to batch create a bunch of records using stored procedures > and the executeBatch() method (so I can get back the generated PKID's) with > no luck. I've tried PostgreSQL 8.4.2 with the 8.4-701.jar and 8.4-702.jar > on OS X, PostgreSQL 9.0.3 with the latest 9.0 JAR on both OS X and Ubuntu > Linux, all under JDK 1.6, and all with the same results. When I try to call > executeBatch, I get a BatchUpdateException with the message: "A result was > returned when none was expected". > Here's my simple example that I whittled down from my larger application: > import java.sql.*; > public class Check { > public static void main(String[] args) throws Exception { > try { > Class.forName("org.postgresql.Driver"); > Connection con = DriverManager.getConnection( > "jdbc:postgresql://localhost/mydb", "postgres", null); > con.setAutoCommit(false); > PreparedStatement stmt = con.prepareStatement( > "INSERT INTO users (email,password,login) VALUES > (?,?,?)", > Statement.RETURN_GENERATED_KEYS); > stmt.setObject(1, "myemail@gmail.com"); > stmt.setObject(2, "test"); > stmt.setObject(3, "sbowman"); > stmt.addBatch(); > stmt.executeBatch(); > System.out.println("Got " + stmt.getGeneratedKeys()); > } catch (ClassNotFoundException e) { > e.printStackTrace(); > } catch (SQLException e) { > System.out.println(e.getMessage()); > System.out.println(e.getNextException().getMessage()); > } > } > } > This always, in all settings described above, returns (raised from the > stmt.executeBatch() line): > Batch entry 0 INSERT INTO users (email,password,login) VALUES > ('myemail@gmail.com','test','sbowman') RETURNING * was aborted. Call > getNextException to see the cause. > A result was returned when none was expected. > Here's the stacktrace: > java.sql.BatchUpdateException: Batch entry 0 INSERT INTO users > (email,password,login) VALUES ('myemail@gmail.com','test','sbowman') > RETURNING * was aborted. Call getNextException to see the cause. > at > org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2586) > at > org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleResultRows(AbstractJdbc2Statement.java:2550) > at > org.postgresql.core.v3.QueryExecutorImpl$1.handleResultRows(QueryExecutorImpl.java:437) > at > org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1747) > at > org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:407) > at > org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2725) > at Check.main(Check.java:21) > I think my code is correct. If I modify the above code to use a MySQL > database instead of a PostgreSQL database, everything works fine and I do > get the PKID's generated by the database back. > I was under the impression that getGeneratedKeys() was now working, since > 8.4-701.jar, but for the life of me I can't figure out how. > If I skip using the batch methods and insert user records one at a time, > calling "stmt.execute()", then the getGeneratedKeys() call returns a > ResultSet with the generated ID in it. So execute() works, but > executeBatch() doesn't. > Any suggestions or pointing out my code flaws would be most appreciated. Or > does executeBatch just not work? I've been battling this issue most of the > day and I'm just about at my wits' end. Should I just give up and switch to > calling execute() one at a time? Seems far less efficient, but at least it > seems to work. > Thanks, > Sean >
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Oliver Jowett
Date:
On 16 March 2011 22:14, Sean Bowman <pico303@gmail.com> wrote: > Any suggestions or pointing out my code flaws would be most appreciated. Or > does executeBatch just not work? I've been battling this issue most of the > day and I'm just about at my wits' end. Should I just give up and switch to > calling execute() one at a time? Seems far less efficient, but at least it > seems to work. You are correct, generated keys don't work with executeBatch() yet. (There was another thread about this a couple of days ago) Oliver
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Dave Cramer
Date:
On Wed, Mar 16, 2011 at 5:59 AM, Oliver Jowett <oliver@opencloud.com> wrote: > On 16 March 2011 22:14, Sean Bowman <pico303@gmail.com> wrote: > >> Any suggestions or pointing out my code flaws would be most appreciated. Or >> does executeBatch just not work? I've been battling this issue most of the >> day and I'm just about at my wits' end. Should I just give up and switch to >> calling execute() one at a time? Seems far less efficient, but at least it >> seems to work. There are some what more efficient ways to do this, such as incrementing the sequence by the number of keys you need. Dave
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Sean Bowman
Date:
Thanks for the quick response. I'll switch it around to execute() each prepared statement individually, and accumulate the generated ID's. On 3/16/11 4:04 AM, "Dave Cramer" <pg@fastcrypt.com> wrote: >Sean, > >Apparently the only database it works for is mysql. It certainly works >for single prepared statements. > >Dave > >On Wed, Mar 16, 2011 at 5:14 AM, Sean Bowman <pico303@gmail.com> wrote: >> I've been trying to batch create a bunch of records using stored >>procedures >> and the executeBatch() method (so I can get back the generated PKID's) >>with >> no luck. I've tried PostgreSQL 8.4.2 with the 8.4-701.jar and >>8.4-702.jar >> on OS X, PostgreSQL 9.0.3 with the latest 9.0 JAR on both OS X and >>Ubuntu >> Linux, all under JDK 1.6, and all with the same results. When I try to >>call >> executeBatch, I get a BatchUpdateException with the message: "A result >>was >> returned when none was expected". >> Here's my simple example that I whittled down from my larger >>application: >> import java.sql.*; >> public class Check { >> public static void main(String[] args) throws Exception { >> try { >> Class.forName("org.postgresql.Driver"); >> Connection con = DriverManager.getConnection( >> "jdbc:postgresql://localhost/mydb", "postgres", >>null); >> con.setAutoCommit(false); >> PreparedStatement stmt = con.prepareStatement( >> "INSERT INTO users (email,password,login) VALUES >> (?,?,?)", >> Statement.RETURN_GENERATED_KEYS); >> stmt.setObject(1, "myemail@gmail.com"); >> stmt.setObject(2, "test"); >> stmt.setObject(3, "sbowman"); >> stmt.addBatch(); >> stmt.executeBatch(); >> System.out.println("Got " + stmt.getGeneratedKeys()); >> } catch (ClassNotFoundException e) { >> e.printStackTrace(); >> } catch (SQLException e) { >> System.out.println(e.getMessage()); >> System.out.println(e.getNextException().getMessage()); >> } >> } >> } >> This always, in all settings described above, returns (raised from the >> stmt.executeBatch() line): >> Batch entry 0 INSERT INTO users (email,password,login) VALUES >> ('myemail@gmail.com','test','sbowman') RETURNING * was aborted. Call >> getNextException to see the cause. >> A result was returned when none was expected. >> Here's the stacktrace: >> java.sql.BatchUpdateException: Batch entry 0 INSERT INTO users >> (email,password,login) VALUES ('myemail@gmail.com','test','sbowman') >> RETURNING * was aborted. Call getNextException to see the cause. >> at >> >>org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleErro >>r(AbstractJdbc2Statement.java:2586) >> at >> >>org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleResu >>ltRows(AbstractJdbc2Statement.java:2550) >> at >> >>org.postgresql.core.v3.QueryExecutorImpl$1.handleResultRows(QueryExecutor >>Impl.java:437) >> at >> >>org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl >>.java:1747) >> at >> >>org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:4 >>07) >> at >> >>org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Sta >>tement.java:2725) >> at Check.main(Check.java:21) >> I think my code is correct. If I modify the above code to use a MySQL >> database instead of a PostgreSQL database, everything works fine and I >>do >> get the PKID's generated by the database back. >> I was under the impression that getGeneratedKeys() was now working, >>since >> 8.4-701.jar, but for the life of me I can't figure out how. >> If I skip using the batch methods and insert user records one at a time, >> calling "stmt.execute()", then the getGeneratedKeys() call returns a >> ResultSet with the generated ID in it. So execute() works, but >> executeBatch() doesn't. >> Any suggestions or pointing out my code flaws would be most >>appreciated. Or >> does executeBatch just not work? I've been battling this issue most of >>the >> day and I'm just about at my wits' end. Should I just give up and >>switch to >> calling execute() one at a time? Seems far less efficient, but at >>least it >> seems to work. >> Thanks, >> Sean >>
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Sean Bowman
Date:
I'm actually using UUID's, so it's even easier. I was just hoping to let the database routines do the UUID generation, but I can do that on the Java side instead. On 3/16/11 4:10 AM, "Dave Cramer" <pg@fastcrypt.com> wrote: >On Wed, Mar 16, 2011 at 5:59 AM, Oliver Jowett <oliver@opencloud.com> >wrote: >> On 16 March 2011 22:14, Sean Bowman <pico303@gmail.com> wrote: >> >>> Any suggestions or pointing out my code flaws would be most >>>appreciated. Or >>> does executeBatch just not work? I've been battling this issue most >>>of the >>> day and I'm just about at my wits' end. Should I just give up and >>>switch to >>> calling execute() one at a time? Seems far less efficient, but at >>>least it >>> seems to work. >There are some what more efficient ways to do this, such as >incrementing the sequence by the number of keys you need. > >Dave
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Dave Cramer
Date:
So looking at the code if you add RETURN_GENERATED_KEYS to the statement it returns all of the columns. That's rather ugly. Is there a way to determine just the generated keys ? Dave
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Vitalii Tymchyshyn
Date:
16.03.11 12:40, Dave Cramer написав(ла):
Best regards, Vitalii Tymchyshyn
AFAIR it was a long discussion on what is "generated". E.g. is calculated default value (CURRENT TIMESTAMP) generated? Constant default value? So, the driver now either returns all or you can pass columns you require by yourself with "boolean execute(String sql, String[] columnNames)".So looking at the code if you add RETURN_GENERATED_KEYS to the statement it returns all of the columns. That's rather ugly. Is there a way to determine just the generated keys ?
Best regards, Vitalii Tymchyshyn
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Dave Cramer
Date:
On Wed, Mar 16, 2011 at 6:43 AM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote: > 16.03.11 12:40, Dave Cramer написав(ла): > > So looking at the code if you add RETURN_GENERATED_KEYS to the > statement it returns all of the columns. That's rather ugly. Is there > a way to determine just the generated keys ? > > AFAIR it was a long discussion on what is "generated". E.g. is calculated > default value (CURRENT TIMESTAMP) generated? Constant default value? So, the > driver now either returns all or you can pass columns you require by > yourself with "boolean execute(String sql, String[] columnNames)". > So ideally we need some backend support here. The backend can certainly figure out what was the result of a default column. Dave
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Vitalii Tymchyshyn
Date:
16.03.11 12:57, Dave Cramer написав(ла): > On Wed, Mar 16, 2011 at 6:43 AM, Vitalii Tymchyshyn<tivv00@gmail.com> wrote: >> 16.03.11 12:40, Dave Cramer написав(ла): >> >> AFAIR it was a long discussion on what is "generated". E.g. is calculated >> default value (CURRENT TIMESTAMP) generated? Constant default value? So, the >> driver now either returns all or you can pass columns you require by >> yourself with "boolean execute(String sql, String[] columnNames)". >> > So ideally we need some backend support here. The backend can > certainly figure out what was the result of a default column. The question AFAIK is not technical, there's simply no strict definition of "generated". And no public consensus on it. Best regards, Vitalii Tymchyshyn
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Dave Cramer
Date:
On Wed, Mar 16, 2011 at 7:04 AM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote: > 16.03.11 12:57, Dave Cramer написав(ла): >> >> On Wed, Mar 16, 2011 at 6:43 AM, Vitalii Tymchyshyn<tivv00@gmail.com> >> wrote: >>> >>> 16.03.11 12:40, Dave Cramer написав(ла): >>> >>> AFAIR it was a long discussion on what is "generated". E.g. is calculated >>> default value (CURRENT TIMESTAMP) generated? Constant default value? So, >>> the >>> driver now either returns all or you can pass columns you require by >>> yourself with "boolean execute(String sql, String[] columnNames)". >>> >> So ideally we need some backend support here. The backend can >> certainly figure out what was the result of a default column. > > The question AFAIK is not technical, there's simply no strict definition of > "generated". And no public consensus on it. Yes, this is a typical problem with JDBC.
Oliver Jowett wrote: > Sean Bowman wrote: >> I've been trying to batch create a bunch of records using stored procedures and >> the executeBatch() method (so I can get back the generated PKID's) with no luck. ... >> When I try to call executeBatch, I get a BatchUpdateException with the message: >> "A result was returned when none was expected". This is the documented result when a statement tries to create a result set: "Throws BatchUpdateException (a subclass of SQLException) if one of the commands sent to the database fails to execute properly or attempts to return a result set." ... >> Any suggestions or pointing out my code flaws would be most appreciated. Or >> does executeBatch just not work? I've been battling this issue most of the >> day and I'm just about at my wits' end. Should I just give up and switch to >> calling execute() one at a time? Seems far less efficient, but at least it >> seems to work. > > You are correct, generated keys don't work with executeBatch() yet. > (There was another thread about this a couple of days ago) How would you retrieve the result if 'executeBatch()' did what you're asking? There's nothing in the documentation for 'Statement#getGeneratedKeys()' that indicates a need for a 'RETURNING' clause in the 'INSERT'. As near as I can tell from the API docs, the behavior you experienced is required. Postgres tells us about RETURNING that: "If the INSERT command contains a RETURNING clause, the result will be similar to that of a SELECT statement containing the columns and values defined in the RETURNING list, computed over the row(s) inserted by the command." http://www.postgresql.org/docs/9.0/interactive/sql-insert.html A SELECT would return a 'ResultSet' through JDBC, thus the API requires your statement to throw the exception that you got. -- Lew Honi soit qui mal y pense.
Please stop top-posting. Sean Bowman wrote: > Thanks for the quick response. I'll switch it around to execute() each > prepared statement individually, and accumulate the generated ID's [sic]. Why don't you try it batched without the RETURNING clause, and use 'getGeneratedKeys()' as the docs suggest? -- Lew Honi soit qui mal y pense.
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Oliver Jowett
Date:
On 19 March 2011 11:49, Lew <noone@lewscanon.com> wrote: > Sean Bowman wrote: >> >> Thanks for the quick response. I'll switch it around to execute() each >> prepared statement individually, and accumulate the generated ID's [sic]. > > Why don't you try it batched without the RETURNING clause, and use > 'getGeneratedKeys()' as the docs suggest? There *is* no RETURNING clause in the application's original query (see the code in the OP), that clause is being added by the driver to implement Statement.RETURN_GENERATED_KEYS. Merely requesting generated keys shouldn't really make executeBatch() explode like this - the app is executing bare INSERTs as far as it knows. We could definitely do better here. Oliver
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Oliver Jowett
Date:
On 19 March 2011 11:47, Lew <noone@lewscanon.com> wrote: > Oliver Jowett wrote: > This is the documented result when a statement tries to create a result set: > "Throws BatchUpdateException (a subclass of SQLException) if one of the > commands sent to the database fails to execute properly or attempts to > return a result set." However, the query that the app provided was just a simple INSERT, which does not return a result set, so this isn't really relevant here. If the driver decides to transform the query, it's also responsible for cleaning the mess up afterwards! >> You are correct, generated keys don't work with executeBatch() yet. >> (There was another thread about this a couple of days ago) > > How would you retrieve the result if 'executeBatch()' did what you're > asking? Via getGeneratedKeys(). The driver already knows that it added the RETURNING clause to implement Statement.RETURN_GENERATED_KEYS, and it deals with the eventual resultset in the simple query execution path (so that it looks to the caller as if the original query executed with no RETURNING clause). The missing piece is equivalent code for the batch execution path. Oliver
Re: Problem with executeBatch and "A result was returned when none was expected"
From
Sean Bowman
Date:
SQL databases won't return any data that was created without the RETURNING clause. Also, if you read the original post, you'd see the RETURNING clause gets appended and does just fine when not in batch mode. But that all said, individual SQL execute() statements are fine for the near future. I'll worry about performance when we've got a million customers. On 3/19/11 2:46 AM, "Oliver Jowett" <oliver@opencloud.com> wrote: >There *is* no RETURNING clause in the application's original query >(see the code in the OP), that clause is being added by the driver to >implement Statement.RETURN_GENERATED_KEYS.