From b729a58a07a8b4b20e664e208a52c9b95f8e417f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Sat, 11 May 2013 12:45:36 +0200 Subject: [PATCH] [#2265] Added prototype implementation for Record.delete() --- .../test/_/testcases/KeepResultSetTests.java | 54 ++++++++++++++---- .../src/org/jooq/test/jOOQAbstractTest.java | 4 +- jOOQ/src/main/java/org/jooq/Record.java | 2 + .../main/java/org/jooq/UpdatableRecord.java | 1 + .../java/org/jooq/impl/AbstractRecord.java | 56 ++++++++++++++----- .../org/jooq/impl/UpdatableRecordImpl.java | 49 ++++++++-------- 6 files changed, 115 insertions(+), 51 deletions(-) diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/KeepResultSetTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/KeepResultSetTests.java index ede4058730..d93a01e6bb 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/KeepResultSetTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/KeepResultSetTests.java @@ -53,7 +53,9 @@ import java.util.Collections; import org.jooq.Cursor; import org.jooq.DSLContext; +import org.jooq.Delete; import org.jooq.ExecuteContext; +import org.jooq.Query; import org.jooq.Record; import org.jooq.Record1; import org.jooq.Record2; @@ -100,21 +102,31 @@ extends BaseTestSELECT statement is * issued after a call to {@link Record#refresh()}. */ - private static class NoSelectAfterRefreshListener extends DefaultExecuteListener { + private static class NoStatementAfterCRUDListener extends DefaultExecuteListener { /** * Default UID */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; + + private final Class type; + private final String crudMethod; + + NoStatementAfterCRUDListener(Class type, String crudMethod) { + this.type = type; + this.crudMethod = crudMethod; + } @Override public void start(ExecuteContext ctx) { super.start(ctx); - if (ctx.query() instanceof Select) { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (e.getMethodName().equals("refresh")) { - fail("Record.refresh() should not execute any queries"); + if (ctx.query() != null) { + if (type.isAssignableFrom(ctx.query().getClass())) { + for (StackTraceElement e : Thread.currentThread().getStackTrace()) { + if (e.getMethodName().equals(crudMethod)) { + fail("Record." + crudMethod + "() should not execute any " + type.getName() + " queries"); + } } } } @@ -140,7 +152,7 @@ extends BaseTest b1 = create.selectFrom(TBook()).fetch(); assertNull(b1.resultSet()); @@ -194,7 +206,7 @@ extends BaseTest b2 = create.selectFrom(TBook()).keepResultSet(KEEP_AFTER_FETCH).fetch(); B r = b2.get(0); assertNotNull(b2.resultSet()); @@ -259,7 +271,7 @@ extends BaseTest books = @@ -297,7 +309,7 @@ extends BaseTest books = create.selectFrom(TBook()) @@ -337,7 +349,7 @@ extends BaseTest books = + create.selectFrom(TBook()) + .orderBy(TBook_ID()) + .keepResultSet(UPDATE_ON_CHANGE) + .fetch(); + + B b2 = books.get(1); + assertEquals(1, b2.delete()); + ResultSet rs = b2.resultSet(); + rs.beforeFirst(); + assertTrue(rs.next()); + assertTrue(rs.next()); + assertTrue(rs.next()); + assertFalse(rs.next()); + + System.out.println(books); } /* diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index e43a4c5d1c..b5c1621492 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -2241,8 +2241,8 @@ public abstract class jOOQAbstractTest< } @Test - public void testKeepRSWithUpdateOnChangeRemove() throws Exception { - new KeepResultSetTests(this).testKeepRSWithUpdateOnChangeRemove(); + public void testKeepRSWithUpdateOnChangeDelete() throws Exception { + new KeepResultSetTests(this).testKeepRSWithUpdateOnChangeDelete(); } @Test diff --git a/jOOQ/src/main/java/org/jooq/Record.java b/jOOQ/src/main/java/org/jooq/Record.java index 6120e9514f..c65a0cae36 100644 --- a/jOOQ/src/main/java/org/jooq/Record.java +++ b/jOOQ/src/main/java/org/jooq/Record.java @@ -1042,6 +1042,8 @@ public interface Record extends Attachable, Comparable { // Methods related to the underlying ResultSet (if applicable) // ------------------------------------------------------------------------- + int delete() throws DataAccessException; + /** * Refresh this record from the database. *

diff --git a/jOOQ/src/main/java/org/jooq/UpdatableRecord.java b/jOOQ/src/main/java/org/jooq/UpdatableRecord.java index a23ab7600a..fa2a1c7a57 100644 --- a/jOOQ/src/main/java/org/jooq/UpdatableRecord.java +++ b/jOOQ/src/main/java/org/jooq/UpdatableRecord.java @@ -298,6 +298,7 @@ public interface UpdatableRecord> extends TableReco * @throws DataChangedException If optimistic locking is enabled and the * record has already been changed/deleted in the database */ + @Override int delete() throws DataAccessException, DataChangedException; /** diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java index 1bbb092496..ce5d2fa1cf 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java @@ -66,6 +66,7 @@ import org.jooq.UniqueKey; import org.jooq.exception.DataAccessException; import org.jooq.exception.InvalidResultException; import org.jooq.exception.MappingException; +import org.jooq.impl.CursorImpl.CursorResultSet; import org.jooq.tools.Convert; import org.jooq.tools.JooqLogger; @@ -86,7 +87,7 @@ abstract class AbstractRecord extends AbstractStore implements Record { final RowImpl fields; final Value[] values; transient KeepResultSetMode keepResultSetMode; - transient ResultSet rs; + transient CursorResultSet rs; transient int rsIndex; AbstractRecord(Collection> fields) { @@ -699,6 +700,28 @@ abstract class AbstractRecord extends AbstractStore implements Record { // XXX: Methods related to the underlying ResultSet (if applicable) // ------------------------------------------------------------------------- + /** + * {@inheritDoc} + *

+ * Subclasses may override this + */ + @Override + public int delete() { + checkRsAvailable("Cannot delete record. No ResultSet available"); + + try { + + // [#2265] TODO: This code is prototypical. + rs.absolute(rsIndex - 1); + rs.deleteRow(); + + return 1; + } + catch (SQLException e) { + throw translate("Cannot delete record", e); + } + } + @Override public final void refresh() { refresh(fields.fields.fields); @@ -710,22 +733,25 @@ abstract class AbstractRecord extends AbstractStore implements Record { * Subclasses may override this */ @Override - public void refresh(Field... f) throws DataAccessException { - if (rs != null) { - try { + public void refresh(Field... f) { + checkRsAvailable("Cannot refresh record. No ResultSet available"); - // [#2265] TODO: This code is prototypical. fetchLazy() is not - // the best way to fetch a record - rs.absolute(rsIndex - 1); - AbstractRecord record = (AbstractRecord) create().fetchLazy(rs).fetchOne(); - setValues(f, record); - } - catch (SQLException e) { - throw translate("Cannot refresh record", e); - } + try { + + // [#2265] TODO: This code is prototypical. fetchLazy() is not + // the best way to fetch a record + rs.absolute(rsIndex - 1); + AbstractRecord record = (AbstractRecord) create().fetchLazy(rs).fetchOne(); + setValues(f, record); } - else { - throw new DataAccessException("Cannot refresh record. No ResultSet available"); + catch (SQLException e) { + throw translate("Cannot refresh record", e); + } + } + + private final void checkRsAvailable(String message) { + if (rs == null) { + throw new DataAccessException(message); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java index 7dc295179e..13b132534c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java @@ -302,35 +302,40 @@ public class UpdatableRecordImpl> extends TableReco @Override public final int delete() { - TableField[] keys = getPrimaryKey().getFieldsArray(); + if (rs != null) { + return super.delete(); + } + else { + TableField[] keys = getPrimaryKey().getFieldsArray(); - try { - DeleteQuery delete1 = create().deleteQuery(getTable()); - Utils.addConditions(delete1, this, keys); + try { + DeleteQuery delete1 = create().deleteQuery(getTable()); + Utils.addConditions(delete1, this, keys); - if (isExecuteWithOptimisticLocking()) { + if (isExecuteWithOptimisticLocking()) { - // [#1596] Add additional conditions for version and/or timestamp columns - if (isTimestampOrVersionAvailable()) { - addConditionForVersionAndTimestamp(delete1); + // [#1596] Add additional conditions for version and/or timestamp columns + if (isTimestampOrVersionAvailable()) { + addConditionForVersionAndTimestamp(delete1); + } + + // [#1547] Try fetching the Record again first, and compare this + // Record's original values with the ones in the database + else { + checkIfChanged(keys); + } } - // [#1547] Try fetching the Record again first, and compare this - // Record's original values with the ones in the database - else { - checkIfChanged(keys); - } + int result = delete1.execute(); + checkIfChanged(result, null, null); + return result; } - int result = delete1.execute(); - checkIfChanged(result, null, null); - return result; - } - - // [#673] If store() is called after delete(), a new INSERT should - // be executed and the record should be recreated - finally { - changed(true); + // [#673] If store() is called after delete(), a new INSERT should + // be executed and the record should be recreated + finally { + changed(true); + } } }