From a8f2f494f569917bde8204f24e877e837fbfa203 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 29 Aug 2011 17:18:50 +0000 Subject: [PATCH] [#809] Add support for INSERT .. RETURNING for Sybase using SELECT @@identity --- .../java/org/jooq/impl/InsertQueryImpl.java | 85 ++++++++++++------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java index 699723f003..78fdc05fb1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java @@ -308,10 +308,13 @@ class InsertQueryImpl> extends AbstractStoreQuery im Connection connection = configuration.getConnection(); switch (configuration.getDialect()) { + // Some JDBC drivers do not support generated keys altogether case INGRES: - case SYBASE: - case SQLITE: { + case SQLITE: + + // Sybase will select @@identity after the INSERT + case SYBASE: { return super.prepare(configuration, sql); } @@ -341,7 +344,6 @@ class InsertQueryImpl> extends AbstractStoreQuery im } } - @SuppressWarnings("unchecked") @Override protected final int execute(Configuration configuration, PreparedStatement statement) throws SQLException { if (returning.isEmpty()) { @@ -355,11 +357,17 @@ class InsertQueryImpl> extends AbstractStoreQuery im // Some JDBC drivers do not support generated keys altogether case INGRES: - case SYBASE: case SQLITE: { return super.execute(configuration, statement); } + // Sybase can select @@identity after the insert + case SYBASE: { + result = statement.executeUpdate(); + selectReturning(configuration, create(configuration).lastID()); + return result; + } + // Some dialects can only retrieve "identity" (AUTO_INCREMENT) values // Additional values have to be fetched explicitly case DERBY: @@ -369,35 +377,8 @@ class InsertQueryImpl> extends AbstractStoreQuery im result = statement.executeUpdate(); rs = statement.getGeneratedKeys(); - if (rs.next() && getInto() instanceof UpdatableTable) { - UpdatableTable updatable = (UpdatableTable) getInto(); - - // This shouldn't be null, as relevant dialects should - // return empty generated keys ResultSet - if (updatable.getIdentity() != null) { - Field id = (Field) updatable.getIdentity().getField(); - Number value = id.getDataType().convert(rs.getObject(1)); - returned = JooqUtil.newRecord(updatable, configuration); - - // Only the IDENTITY value was requested. No need for an - // additional query - if (returning.size() == 1 && returning.get(0).equals(id)) { - ((AbstractRecord) returned).setValue(id, new Value(value)); - } - - // Other values are requested, too. Run another query - else { - Record record = - create(configuration).select(returning) - .from(updatable) - .where(id.equal(value)) - .fetchOne(); - - for (Field field : returning) { - setValue(record, field); - } - } - } + if (rs.next()) { + selectReturning(configuration, rs.getObject(1)); } return result; @@ -429,6 +410,44 @@ class InsertQueryImpl> extends AbstractStoreQuery im } } + /** + * Get the returning record in those dialects that do not support fetching + * arbitrary fields from JDBC's {@link Statement#getGeneratedKeys()} method. + */ + @SuppressWarnings("unchecked") + private void selectReturning(Configuration configuration, Object o) throws SQLException { + if (getInto() instanceof UpdatableTable) { + UpdatableTable updatable = (UpdatableTable) getInto(); + + // This shouldn't be null, as relevant dialects should + // return empty generated keys ResultSet + if (updatable.getIdentity() != null) { + Field id = (Field) updatable.getIdentity().getField(); + Number value = id.getDataType().convert(o); + returned = JooqUtil.newRecord(updatable, configuration); + + // Only the IDENTITY value was requested. No need for an + // additional query + if (returning.size() == 1 && returning.get(0).equals(id)) { + ((AbstractRecord) returned).setValue(id, new Value(value)); + } + + // Other values are requested, too. Run another query + else { + Record record = + create(configuration).select(returning) + .from(updatable) + .where(id.equal(value)) + .fetchOne(); + + for (Field field : returning) { + setValue(record, field); + } + } + } + } + } + /** * Generic type-safe utility method */