[jOOQ/jOOQ#14573] Add Settings.returnDefaultOnUpdatableRecord and Settings.returnComputedOnUpdatableRecord
This commit is contained in:
parent
e14ebc33d8
commit
b7a392066f
@ -383,6 +383,10 @@ public class Settings
|
||||
@XmlElement(defaultValue = "true")
|
||||
protected Boolean returnIdentityOnUpdatableRecord = true;
|
||||
@XmlElement(defaultValue = "false")
|
||||
protected Boolean returnDefaultOnUpdatableRecord = false;
|
||||
@XmlElement(defaultValue = "false")
|
||||
protected Boolean returnComputedOnUpdatableRecord = false;
|
||||
@XmlElement(defaultValue = "false")
|
||||
protected Boolean returnAllOnUpdatableRecord = false;
|
||||
@XmlElement(defaultValue = "true")
|
||||
protected Boolean returnRecordToPojo = true;
|
||||
@ -4612,6 +4616,54 @@ public class Settings
|
||||
this.returnIdentityOnUpdatableRecord = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether calls to store(), insert() and update() should return values for columns that are {@link org.jooq.DataType#defaulted()}.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public Boolean isReturnDefaultOnUpdatableRecord() {
|
||||
return returnDefaultOnUpdatableRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the returnDefaultOnUpdatableRecord property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public void setReturnDefaultOnUpdatableRecord(Boolean value) {
|
||||
this.returnDefaultOnUpdatableRecord = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether calls to store(), insert() and update() should return values for columns that are {@link org.jooq.DataType#computed()}.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public Boolean isReturnComputedOnUpdatableRecord() {
|
||||
return returnComputedOnUpdatableRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the returnComputedOnUpdatableRecord property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public void setReturnComputedOnUpdatableRecord(Boolean value) {
|
||||
this.returnComputedOnUpdatableRecord = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether calls to store(), insert() and update() should return all columns, not just identity columns.
|
||||
* <p>
|
||||
@ -6840,6 +6892,16 @@ public class Settings
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withReturnDefaultOnUpdatableRecord(Boolean value) {
|
||||
setReturnDefaultOnUpdatableRecord(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withReturnComputedOnUpdatableRecord(Boolean value) {
|
||||
setReturnComputedOnUpdatableRecord(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withReturnAllOnUpdatableRecord(Boolean value) {
|
||||
setReturnAllOnUpdatableRecord(value);
|
||||
return this;
|
||||
@ -7473,6 +7535,8 @@ public class Settings
|
||||
builder.append("fetchWarnings", fetchWarnings);
|
||||
builder.append("fetchServerOutputSize", fetchServerOutputSize);
|
||||
builder.append("returnIdentityOnUpdatableRecord", returnIdentityOnUpdatableRecord);
|
||||
builder.append("returnDefaultOnUpdatableRecord", returnDefaultOnUpdatableRecord);
|
||||
builder.append("returnComputedOnUpdatableRecord", returnComputedOnUpdatableRecord);
|
||||
builder.append("returnAllOnUpdatableRecord", returnAllOnUpdatableRecord);
|
||||
builder.append("returnRecordToPojo", returnRecordToPojo);
|
||||
builder.append("mapJPAAnnotations", mapJPAAnnotations);
|
||||
@ -8938,6 +9002,24 @@ public class Settings
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (returnDefaultOnUpdatableRecord == null) {
|
||||
if (other.returnDefaultOnUpdatableRecord!= null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!returnDefaultOnUpdatableRecord.equals(other.returnDefaultOnUpdatableRecord)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (returnComputedOnUpdatableRecord == null) {
|
||||
if (other.returnComputedOnUpdatableRecord!= null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!returnComputedOnUpdatableRecord.equals(other.returnComputedOnUpdatableRecord)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (returnAllOnUpdatableRecord == null) {
|
||||
if (other.returnAllOnUpdatableRecord!= null) {
|
||||
return false;
|
||||
@ -9621,6 +9703,8 @@ public class Settings
|
||||
result = ((prime*result)+((fetchWarnings == null)? 0 :fetchWarnings.hashCode()));
|
||||
result = ((prime*result)+((fetchServerOutputSize == null)? 0 :fetchServerOutputSize.hashCode()));
|
||||
result = ((prime*result)+((returnIdentityOnUpdatableRecord == null)? 0 :returnIdentityOnUpdatableRecord.hashCode()));
|
||||
result = ((prime*result)+((returnDefaultOnUpdatableRecord == null)? 0 :returnDefaultOnUpdatableRecord.hashCode()));
|
||||
result = ((prime*result)+((returnComputedOnUpdatableRecord == null)? 0 :returnComputedOnUpdatableRecord.hashCode()));
|
||||
result = ((prime*result)+((returnAllOnUpdatableRecord == null)? 0 :returnAllOnUpdatableRecord.hashCode()));
|
||||
result = ((prime*result)+((returnRecordToPojo == null)? 0 :returnRecordToPojo.hashCode()));
|
||||
result = ((prime*result)+((mapJPAAnnotations == null)? 0 :mapJPAAnnotations.hashCode()));
|
||||
|
||||
@ -37,6 +37,8 @@
|
||||
*/
|
||||
package org.jooq.conf;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static org.jooq.conf.FetchIntermediateResult.WHEN_EXECUTE_LISTENERS_PRESENT;
|
||||
import static org.jooq.conf.FetchIntermediateResult.WHEN_RESULT_REQUESTED;
|
||||
import static org.jooq.conf.ParamType.INDEXED;
|
||||
@ -54,6 +56,7 @@ import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.StringUtils;
|
||||
import org.jooq.util.jaxb.tools.MiniJAXB;
|
||||
@ -465,4 +468,15 @@ public final class SettingsTools {
|
||||
? settings.getFetchServerOutputSize()
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether any value should be returned on an {@link UpdatableRecord}
|
||||
* operation.
|
||||
*/
|
||||
public static final boolean returnAnyOnUpdatableRecord(Settings settings) {
|
||||
return !FALSE.equals(settings.isReturnIdentityOnUpdatableRecord())
|
||||
|| TRUE.equals(settings.isReturnAllOnUpdatableRecord())
|
||||
|| TRUE.equals(settings.isReturnDefaultOnUpdatableRecord())
|
||||
|| TRUE.equals(settings.isReturnComputedOnUpdatableRecord());
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +95,10 @@ final class BatchCRUD extends AbstractBatch {
|
||||
// [#1529] Avoid DEBUG logging of single INSERT / UPDATE statements
|
||||
.withExecuteLogging(false)
|
||||
|
||||
// [#3327] [#11509] We can't return generated keys from batches (yet)
|
||||
// [#3327] [#11509] [#14573] We can't return generated keys from batches (yet)
|
||||
.withReturnAllOnUpdatableRecord(false)
|
||||
.withReturnDefaultOnUpdatableRecord(false)
|
||||
.withReturnComputedOnUpdatableRecord(false)
|
||||
.withReturnIdentityOnUpdatableRecord(false);
|
||||
|
||||
return local;
|
||||
|
||||
@ -69,6 +69,7 @@ import org.jooq.TableField;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.SettingsTools;
|
||||
|
||||
/**
|
||||
* A common base implementation for generated {@link DAO}.
|
||||
@ -198,8 +199,7 @@ public abstract class DAOImpl<R extends UpdatableRecord<R>, P, T> implements DAO
|
||||
if (objects.size() > 1)
|
||||
|
||||
// [#2536] [#3327] We cannot batch UPDATE RETURNING calls yet
|
||||
if (!FALSE.equals(settings().isReturnRecordToPojo()) &&
|
||||
TRUE.equals(settings().isReturnAllOnUpdatableRecord()))
|
||||
if (returnAnyOnUpdatableRecord())
|
||||
for (R record : records(objects, true))
|
||||
record.update();
|
||||
else
|
||||
@ -228,8 +228,7 @@ public abstract class DAOImpl<R extends UpdatableRecord<R>, P, T> implements DAO
|
||||
if (objects.size() > 1)
|
||||
|
||||
// [#2536] [#3327] We cannot batch MERGE RETURNING calls yet
|
||||
if (!FALSE.equals(settings().isReturnRecordToPojo()) &&
|
||||
TRUE.equals(settings().isReturnAllOnUpdatableRecord()))
|
||||
if (returnAnyOnUpdatableRecord())
|
||||
for (R record : records(objects, false))
|
||||
record.merge();
|
||||
else
|
||||
@ -258,8 +257,7 @@ public abstract class DAOImpl<R extends UpdatableRecord<R>, P, T> implements DAO
|
||||
if (objects.size() > 1)
|
||||
|
||||
// [#2536] [#3327] We cannot batch DELETE RETURNING calls yet
|
||||
if (!FALSE.equals(settings().isReturnRecordToPojo()) &&
|
||||
TRUE.equals(settings().isReturnAllOnUpdatableRecord()))
|
||||
if (returnAnyOnUpdatableRecord())
|
||||
for (R record : records(objects, true))
|
||||
record.delete();
|
||||
else
|
||||
@ -510,4 +508,9 @@ public abstract class DAOImpl<R extends UpdatableRecord<R>, P, T> implements DAO
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private final boolean returnAnyOnUpdatableRecord() {
|
||||
return !FALSE.equals(settings().isReturnRecordToPojo())
|
||||
&& SettingsTools.returnAnyOnUpdatableRecord(settings());
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,6 +49,7 @@ import static org.jooq.SQLDialect.MARIADB;
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.conf.SettingsTools.returnAnyOnUpdatableRecord;
|
||||
import static org.jooq.conf.SettingsTools.updatablePrimaryKeys;
|
||||
import static org.jooq.conf.WriteIfReadonly.IGNORE;
|
||||
import static org.jooq.conf.WriteIfReadonly.THROW;
|
||||
@ -59,6 +60,8 @@ import static org.jooq.impl.Tools.EMPTY_FIELD;
|
||||
import static org.jooq.impl.Tools.collect;
|
||||
import static org.jooq.impl.Tools.filter;
|
||||
import static org.jooq.impl.Tools.indexOrFail;
|
||||
import static org.jooq.impl.Tools.isEmpty;
|
||||
import static org.jooq.impl.Tools.let;
|
||||
import static org.jooq.impl.Tools.settings;
|
||||
import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
|
||||
@ -90,6 +93,7 @@ import org.jooq.UniqueKey;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.Update;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.SettingsTools;
|
||||
import org.jooq.conf.WriteIfReadonly;
|
||||
import org.jooq.exception.DataTypeException;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
@ -208,7 +212,7 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractQualified
|
||||
}
|
||||
|
||||
final void getReturningIfNeeded(StoreQuery<R> query, Collection<Field<?>> key) {
|
||||
if (key != null && !key.isEmpty()) {
|
||||
if (!isEmpty(key)) {
|
||||
R record = query.getReturnedRecord();
|
||||
|
||||
if (record != null) {
|
||||
@ -223,7 +227,7 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractQualified
|
||||
|
||||
// [#1859] In some databases, not all fields can be fetched via getGeneratedKeys()
|
||||
Configuration c = configuration();
|
||||
if (TRUE.equals(c.settings().isReturnAllOnUpdatableRecord())
|
||||
if (returnAnyOnUpdatableRecord(c.settings())
|
||||
|
||||
// [#11620] Refresh only if the RETURNING clause didn't run
|
||||
// E.g. in MySQL when there was no identity column
|
||||
@ -243,21 +247,12 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractQualified
|
||||
final Collection<Field<?>> setReturningIfNeeded(StoreQuery<R> query) {
|
||||
Collection<Field<?>> key = null;
|
||||
|
||||
if (configuration() != null)
|
||||
if (configuration() != null && returnAnyOnUpdatableRecord(configuration().settings())) {
|
||||
key = getReturning(query);
|
||||
|
||||
// [#7966] Allow users to turning off the returning clause entirely
|
||||
if (!FALSE.equals(configuration().settings().isReturnIdentityOnUpdatableRecord()))
|
||||
|
||||
// [#1859] Return also non-key columns
|
||||
if (TRUE.equals(configuration().settings().isReturnAllOnUpdatableRecord()))
|
||||
key = Arrays.asList(fields());
|
||||
|
||||
// [#5940] Getting the primary key mostly doesn't make sense on UPDATE statements
|
||||
else if (query instanceof InsertQuery || updatablePrimaryKeys(settings(this)))
|
||||
key = getReturning();
|
||||
|
||||
if (key != null)
|
||||
query.setReturning(key);
|
||||
if (!isEmpty(key))
|
||||
query.setReturning(key);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
@ -430,16 +425,35 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractQualified
|
||||
|| getTable().getRecordVersion() != null && isUpdateRecordVersion();
|
||||
}
|
||||
|
||||
final Collection<Field<?>> getReturning() {
|
||||
final Collection<Field<?>> getReturning(StoreQuery<R> query) {
|
||||
Settings s = configuration().settings();
|
||||
|
||||
// [#1859] Returning all columns if requested explicitly
|
||||
if (TRUE.equals(s.isReturnAllOnUpdatableRecord()))
|
||||
return asList(fields());
|
||||
|
||||
Collection<Field<?>> result = new LinkedHashSet<>();
|
||||
|
||||
Identity<R, ?> identity = getTable().getIdentity();
|
||||
if (identity != null)
|
||||
result.add(identity.getField());
|
||||
// [#7966] Allow users to turning off the returning clause entirely
|
||||
if (!FALSE.equals(s.isReturnIdentityOnUpdatableRecord())
|
||||
|
||||
UniqueKey<?> key = getPrimaryKey();
|
||||
if (key != null)
|
||||
result.addAll(key.getFields());
|
||||
// [#5940] Getting the primary key mostly doesn't make sense on UPDATE statements
|
||||
&& (query instanceof InsertQuery || updatablePrimaryKeys(s))
|
||||
) {
|
||||
let(getTable().getIdentity(), i -> result.add(i.getField()));
|
||||
let(getPrimaryKey(), k -> result.addAll(k.getFields()));
|
||||
}
|
||||
|
||||
// [#14573] Return also non-key columns
|
||||
if (TRUE.equals(s.isReturnDefaultOnUpdatableRecord()))
|
||||
for (Field<?> f : fields())
|
||||
if (f.getDataType().defaulted())
|
||||
result.add(f);
|
||||
|
||||
if (TRUE.equals(s.isReturnComputedOnUpdatableRecord()))
|
||||
for (Field<?> f : fields())
|
||||
if (f.getDataType().computed())
|
||||
result.add(f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2175,8 +2175,10 @@ final class Tools {
|
||||
return t == null ? s.get() : t;
|
||||
}
|
||||
|
||||
static final <T> T let(T t, Consumer<? super T> consumer) {
|
||||
consumer.accept(t);
|
||||
static final <T> T let(@Nullable T t, Consumer<? super @NotNull T> consumer) {
|
||||
if (t != null)
|
||||
consumer.accept(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@ -1305,6 +1305,14 @@ UpdatableRecord.store() and UpdatableRecord.update().]]></jxb:javadoc></jxb:prop
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether calls to store(), insert() and update() should return the identity column.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="returnDefaultOnUpdatableRecord" type="boolean" minOccurs="0" maxOccurs="1" default="false">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether calls to store(), insert() and update() should return values for columns that are {@link org.jooq.DataType#defaulted()}.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="returnComputedOnUpdatableRecord" type="boolean" minOccurs="0" maxOccurs="1" default="false">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether calls to store(), insert() and update() should return values for columns that are {@link org.jooq.DataType#computed()}.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="returnAllOnUpdatableRecord" type="boolean" minOccurs="0" maxOccurs="1" default="false">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether calls to store(), insert() and update() should return all columns, not just identity columns.
|
||||
<p>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user