From d3ea56750ea5dd524a758eda40714540bfed3fd2 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Sat, 28 Sep 2013 11:35:11 +0200 Subject: [PATCH] [#2764] Let CRUD operations be able to perform UPDATEs on primary keys --- .../org/jooq/test/_/testcases/CRUDTests.java | 67 +++++++ .../src/org/jooq/test/jOOQAbstractTest.java | 5 + jOOQ/pom.xml | 2 +- .../java/org/jooq/conf/SettingsTools.java | 8 + .../java/org/jooq/impl/AbstractRecord.java | 7 + .../org/jooq/impl/UpdatableRecordImpl.java | 25 ++- jOOQ/src/main/java/org/jooq/impl/Utils.java | 34 +++- jOOQ/src/main/resources/xjb/binding.xjb | 4 +- .../main/resources/xsd/jooq-runtime-3.2.0.xsd | 182 ++++++++++++++++++ 9 files changed, 321 insertions(+), 13 deletions(-) create mode 100644 jOOQ/src/main/resources/xsd/jooq-runtime-3.2.0.xsd diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java index 5231664c61..4bf4368e0d 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/CRUDTests.java @@ -35,6 +35,7 @@ */ package org.jooq.test._.testcases; +import static java.util.Arrays.asList; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; @@ -776,4 +777,70 @@ extends BaseTestsrc/main/resources/xsd src/main/resources/xjb - jooq-runtime-3.1.0.xsd + jooq-runtime-3.2.0.xsd org.jooq.conf diff --git a/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java b/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java index 8db3a11ef2..b553291a75 100644 --- a/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java +++ b/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java @@ -39,6 +39,7 @@ import static org.jooq.conf.ParamType.INDEXED; import static org.jooq.conf.ParamType.INLINED; import static org.jooq.conf.StatementType.PREPARED_STATEMENT; import static org.jooq.conf.StatementType.STATIC_STATEMENT; +import static org.jooq.tools.StringUtils.defaultIfNull; import java.io.File; import java.io.InputStream; @@ -138,6 +139,13 @@ public final class SettingsTools { return getStatementType(settings) == STATIC_STATEMENT; } + /** + * Whether primary keys should be updatable. + */ + public static final boolean updatablePrimaryKeys(Settings settings) { + return defaultIfNull(settings.isUpdatablePrimaryKeys(), false); + } + /** * Lazy access to {@link RenderMapping}. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java index 87db5b5c06..9cc22f6792 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java @@ -37,11 +37,13 @@ package org.jooq.impl; import static java.util.Arrays.asList; +import static org.jooq.conf.SettingsTools.updatablePrimaryKeys; import static org.jooq.impl.Utils.getAnnotatedGetter; import static org.jooq.impl.Utils.getAnnotatedMembers; import static org.jooq.impl.Utils.getMatchingGetter; import static org.jooq.impl.Utils.getMatchingMembers; import static org.jooq.impl.Utils.hasColumnAnnotations; +import static org.jooq.impl.Utils.settings; import java.lang.reflect.Method; import java.sql.ResultSet; @@ -294,6 +296,11 @@ abstract class AbstractRecord extends AbstractStore implements Record { val.setValue(value); } + // [#2764] Users may override updatability of primary key values + else if (updatablePrimaryKeys(settings(this))) { + val.setValue(value); + } + // [#979] If the primary key is being changed, all other fields' flags // need to be set to true for in case this record is stored again, an // INSERT statement will thus be issued diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java index e75a3cd9c8..91d8f4ffc6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdatableRecordImpl.java @@ -36,12 +36,14 @@ package org.jooq.impl; import static java.lang.Boolean.TRUE; +import static org.jooq.conf.SettingsTools.updatablePrimaryKeys; import static org.jooq.impl.RecordDelegate.delegate; import static org.jooq.impl.RecordDelegate.RecordLifecycleType.DELETE; import static org.jooq.impl.RecordDelegate.RecordLifecycleType.INSERT; import static org.jooq.impl.RecordDelegate.RecordLifecycleType.REFRESH; import static org.jooq.impl.RecordDelegate.RecordLifecycleType.STORE; import static org.jooq.impl.RecordDelegate.RecordLifecycleType.UPDATE; +import static org.jooq.impl.Utils.settings; import java.math.BigInteger; import java.sql.Timestamp; @@ -146,16 +148,27 @@ public class UpdatableRecordImpl> extends TableReco for (TableField field : keys) { - // If any primary key value is null or changed, execute an insert - if (getValue(field) == null || getValue0(field).isChanged()) { - executeUpdate = false; - break; + // [#2764] If primary key values are allowed to be changed, + // inserting is only possible without prior loading of pk values + if (updatablePrimaryKeys(settings(this))) { + if (original(field) == null) { + executeUpdate = false; + break; + } } - // If primary key values are unchanged, updates are possible + // [#2764] Primary key value changes are interpreted as record copies else { - executeUpdate = true; + + // If any primary key value is null or changed, execute an insert + if (getValue(field) == null || getValue0(field).isChanged()) { + executeUpdate = false; + break; + } } + + // Otherwise, updates are possible + executeUpdate = true; } int result = 0; diff --git a/jOOQ/src/main/java/org/jooq/impl/Utils.java b/jOOQ/src/main/java/org/jooq/impl/Utils.java index f31d359bba..b03e16a93f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Utils.java +++ b/jOOQ/src/main/java/org/jooq/impl/Utils.java @@ -39,6 +39,7 @@ import static java.lang.Boolean.FALSE; import static org.jooq.SQLDialect.CUBRID; import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.conf.ParamType.INLINED; +import static org.jooq.conf.SettingsTools.updatablePrimaryKeys; import static org.jooq.impl.DSL.escape; import static org.jooq.impl.DSL.getDataType; import static org.jooq.impl.DSL.nullSafe; @@ -345,18 +346,36 @@ final class Utils { * Get an attachable's configuration or a new {@link DefaultConfiguration} * if null. */ - static Configuration configuration(AttachableInternal attachable) { - return configuration(attachable.configuration()); + static Configuration configuration(Attachable attachable) { + return configuration(attachable instanceof AttachableInternal + ? ((AttachableInternal) attachable).configuration() + : null); } /** - * Get an configuration or a new {@link DefaultConfiguration} if + * Get a configuration or a new {@link DefaultConfiguration} if * null. */ static Configuration configuration(Configuration configuration) { return configuration != null ? configuration : new DefaultConfiguration(); } + /** + * Get a configuration's settings or default settings if the configuration + * is null. + */ + static Settings settings(Attachable attachable) { + return configuration(attachable).settings(); + } + + /** + * Get a configuration's settings or default settings if the configuration + * is null. + */ + static Settings settings(Configuration configuration) { + return configuration(configuration).settings(); + } + private static final boolean attachRecords(Configuration configuration) { if (configuration != null) { Settings settings = configuration.settings(); @@ -1292,7 +1311,14 @@ final class Utils { */ @SuppressWarnings("deprecation") static final void addCondition(org.jooq.ConditionProvider provider, Record record, Field field) { - provider.addConditions(field.equal(record.getValue(field))); + + // [#2764] If primary keys are allowed to be changed, the + if (updatablePrimaryKeys(settings(record))) { + provider.addConditions(field.equal(record.original(field))); + } + else { + provider.addConditions(field.equal(record.getValue(field))); + } } // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/resources/xjb/binding.xjb b/jOOQ/src/main/resources/xjb/binding.xjb index b389034a65..b9a86e5963 100644 --- a/jOOQ/src/main/resources/xjb/binding.xjb +++ b/jOOQ/src/main/resources/xjb/binding.xjb @@ -12,12 +12,12 @@ - + - + org.jooq.conf.SettingsBase java.lang.Cloneable diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.2.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.2.0.xsd new file mode 100644 index 0000000000..5833f09cad --- /dev/null +++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.2.0.xsd @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file