[jOOQ/jOOQ#11788] Add QualifiedRecord and RecordQualifier to unify the Table|UDT and TableRecord|UDTRecord type hierarchy

This helps better implement Oracle %ROWTYPE support see [jOOQ/jOOQ#7863]
This commit is contained in:
Lukas Eder 2021-04-21 14:04:06 +02:00
parent fcc258bfe8
commit 1ab673fa9a
14 changed files with 347 additions and 230 deletions

View File

@ -0,0 +1,65 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import java.sql.SQLData;
import org.jetbrains.annotations.NotNull;
/**
* A record that has a {@link RecordQualifier} (a {@link UDTRecord} or a
* {@link TableRecord}).
*
* @author Lukas Eder
*/
public interface QualifiedRecord<R extends QualifiedRecord<R>> extends Record, SQLData {
/**
* Get the {@link UDT} or {@link Table} reference.
*/
@NotNull
RecordQualifier<R> getQualifier();
@NotNull
@Override
<T> R with(Field<T> field, T value);
@NotNull
@Override
<T, U> R with(Field<T> field, U value, Converter<? extends T, ? super U> converter);
}

View File

@ -0,0 +1,79 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A {@link UDT} or {@link Table}.
*
* @author Lukas Eder
*/
public interface RecordQualifier<R extends Record> extends Qualified, Fields {
/**
* Get the UDT package if this is a {@link UDT}, or <code>null</code> if it
* is not a UDT, or if it is a schema level UDT defined outside of a
* package.
*/
@Nullable
Package getPackage();
/**
* The record type produced by this {@link UDT} or {@link Table}.
*/
@NotNull
Class<? extends R> getRecordType();
/**
* The {@link UDT}'s or {@link Table}'s data type as known to the database.
*/
@NotNull
DataType<R> getDataType();
/**
* Create a new {@link Record} of this {@link UDT}'s or {@link Table}'s type.
*
* @see DSLContext#newRecord(Table)
*/
@NotNull
R newRecord();
}

View File

@ -123,7 +123,7 @@ import org.jetbrains.annotations.Nullable;
* @param <R> The record type associated with this table
* @author Lukas Eder
*/
public interface Table<R extends Record> extends TableLike<R>, Qualified {
public interface Table<R extends Record> extends TableLike<R>, RecordQualifier<R> {
/**
* Get the table type.
@ -143,27 +143,6 @@ public interface Table<R extends Record> extends TableLike<R>, Qualified {
@NotNull
RecordType<R> recordType();
/**
* The record type produced by this table.
*/
@NotNull
Class<? extends R> getRecordType();
/**
* The table's record type as a UDT data type, in case the underlying
* database supports table records as UDT records.
*/
@NotNull
DataType<R> getDataType();
/**
* Create a new {@link Record} of this table's type.
*
* @see DSLContext#newRecord(Table)
*/
@NotNull
R newRecord();
/**
* Retrieve the table's <code>IDENTITY</code> information, if available.
* <p>

View File

@ -51,7 +51,7 @@ import org.jetbrains.annotations.Nullable;
* @param <R> The record type
* @author Lukas Eder
*/
public interface TableRecord<R extends TableRecord<R>> extends Record {
public interface TableRecord<R extends TableRecord<R>> extends QualifiedRecord<R> {
/**
* The table from which this record was read.
@ -126,12 +126,4 @@ public interface TableRecord<R extends TableRecord<R>> extends Record {
@NotNull
@Support
<O extends UpdatableRecord<O>> Table<O> parent(ForeignKey<R, O> key);
@NotNull
@Override
<T> R with(Field<T> field, T value);
@NotNull
@Override
<T, U> R with(Field<T> field, U value, Converter<? extends T, ? super U> converter);
}

View File

@ -37,9 +37,6 @@
*/
package org.jooq;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* UDT definition.
* <p>
@ -49,33 +46,7 @@ import org.jetbrains.annotations.Nullable;
* @param <R> The record type
* @author Lukas Eder
*/
public interface UDT<R extends UDTRecord<R>> extends Fields, Qualified {
/**
* Get the UDT package.
*/
@Nullable
Package getPackage();
/**
* @return The record type produced by this table.
*/
@NotNull
Class<R> getRecordType();
/**
* Create a new {@link Record} of this UDT's type.
*
* @see DSLContext#newRecord(UDT)
*/
@NotNull
R newRecord();
/**
* The UDT's data type as known to the database.
*/
@NotNull
DataType<R> getDataType();
public interface UDT<R extends UDTRecord<R>> extends RecordQualifier<R> {
/**
* Whether this data type can be used from SQL statements.

View File

@ -37,8 +37,6 @@
*/
package org.jooq;
import java.sql.SQLData;
import org.jetbrains.annotations.NotNull;
/**
@ -47,7 +45,7 @@ import org.jetbrains.annotations.NotNull;
* @param <R> The record type
* @author Lukas Eder
*/
public interface UDTRecord<R extends UDTRecord<R>> extends Record, SQLData {
public interface UDTRecord<R extends UDTRecord<R>> extends QualifiedRecord<R> {
/**
* The UDT from which this record was read
@ -55,12 +53,4 @@ public interface UDTRecord<R extends UDTRecord<R>> extends Record, SQLData {
@NotNull
UDT<R> getUDT();
@NotNull
@Override
<T> R with(Field<T> field, T value);
@NotNull
@Override
<T, U> R with(Field<T> field, U value, Converter<? extends T, ? super U> converter);
}

View File

@ -0,0 +1,154 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import static org.jooq.impl.DefaultExecuteContext.localConfiguration;
import static org.jooq.impl.DefaultExecuteContext.localData;
import static org.jooq.impl.Tools.fieldsArray;
import static org.jooq.impl.Tools.row0;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
import java.util.Map;
import org.jooq.Configuration;
import org.jooq.Converter;
import org.jooq.Field;
import org.jooq.QualifiedRecord;
import org.jooq.Record;
import org.jooq.RecordQualifier;
import org.jooq.Row;
import org.jooq.UDT;
/**
* @author Lukas Eder
*/
abstract class AbstractQualifiedRecord<R extends QualifiedRecord<R>> extends AbstractRecord implements QualifiedRecord<R> {
/**
* Generated UID
*/
private static final long serialVersionUID = 6031695690614716816L;
private final RecordQualifier<R> qualifier;
public AbstractQualifiedRecord(RecordQualifier<R> qualifier) {
super((AbstractRow) qualifier.fieldsRow());
this.qualifier = qualifier;
}
// -------------------------------------------------------------------------
// XXX: QualifiedRecord API
// -------------------------------------------------------------------------
@Override
public final RecordQualifier<R> getQualifier() {
return qualifier;
}
@SuppressWarnings("unchecked")
@Override
public final <T> R with(Field<T> field, T value) {
return (R) super.with(field, value);
}
@SuppressWarnings("unchecked")
@Override
public final <T, U> R with(Field<T> field, U value, Converter<? extends T, ? super U> converter) {
return (R) super.with(field, value, converter);
}
/*
* Subclasses may override this method
*/
@Override
public Row fieldsRow() {
return fields;
}
/*
* Subclasses may override this method
*/
@Override
public Row valuesRow() {
return row0(fieldsArray(intoArray(), fields.fields.fields()));
}
// -------------------------------------------------------------------------
// XXX: SQLData API
// -------------------------------------------------------------------------
@Override
public final String getSQLTypeName() throws SQLException {
// [#1693] This needs to return the fully qualified SQL type name, in
// case the connected user is not the owner of the UDT
Configuration configuration = localConfiguration();
return Tools.getMappedUDTName(configuration, this);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final void readSQL(SQLInput stream, String typeName) throws SQLException {
Configuration configuration = localConfiguration();
Map<Object, Object> data = localData();
Field<?>[] f = getQualifier().fields();
for (int i = 0; i < f.length; i++) {
Field field = f[i];
DefaultBindingGetSQLInputContext out = new DefaultBindingGetSQLInputContext(configuration, data, stream);
field.getBinding().get(out);
set(i, field, out.value());
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final void writeSQL(SQLOutput stream) throws SQLException {
Configuration configuration = localConfiguration();
Map<Object, Object> data = localData();
Field<?>[] f = getQualifier().fields();
for (int i = 0; i < f.length; i++) {
Field field = f[i];
field.getBinding().set(new DefaultBindingSetSQLOutputContext(configuration, data, stream, get(i)));
}
}
}

View File

@ -90,6 +90,7 @@ import org.jooq.Index;
import org.jooq.JoinType;
// ...
import org.jooq.Name;
import org.jooq.Package;
// ...
// ...
// ...
@ -469,6 +470,11 @@ abstract class AbstractTable<R extends Record> extends AbstractNamed implements
return getSchema() == null ? null : getSchema().getCatalog();
}
@Override
public final Package getPackage() {
return null;
}
@Override
public /* non-final */ Schema getSchema() {
if (tableschema == null)

View File

@ -194,6 +194,7 @@ import org.jooq.JSON;
import org.jooq.JSONB;
import org.jooq.Param;
// ...
import org.jooq.QualifiedRecord;
import org.jooq.Record;
import org.jooq.RenderContext;
import org.jooq.Result;
@ -505,11 +506,11 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
@SuppressWarnings("unchecked")
static final Map<String, Class<?>> typeMap(Class<?> type, Configuration configuration, Map<String, Class<?>> result) {
try {
if (UDTRecord.class.isAssignableFrom(type)) {
Class<UDTRecord<?>> t = (Class<UDTRecord<?>>) type;
if (QualifiedRecord.class.isAssignableFrom(type)) {
Class<QualifiedRecord<?>> t = (Class<QualifiedRecord<?>>) type;
result.put(getMappedUDTName(configuration, t), t);
UDTRecord<?> r = t.newInstance();
for (Field<?> field : r.getUDT().fields())
QualifiedRecord<?> r = t.getConstructor().newInstance();
for (Field<?> field : r.getQualifier().fields())
typeMap(field.getType(), configuration, result);
}

View File

@ -51,9 +51,7 @@ import static org.jooq.conf.SettingsTools.updatablePrimaryKeys;
import static org.jooq.impl.RecordDelegate.delegate;
import static org.jooq.impl.RecordDelegate.RecordLifecycleType.INSERT;
import static org.jooq.impl.Tools.EMPTY_FIELD;
import static org.jooq.impl.Tools.fieldsArray;
import static org.jooq.impl.Tools.indexOrFail;
import static org.jooq.impl.Tools.row0;
import static org.jooq.impl.Tools.settings;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_OMIT_RETURNING_CLAUSE;
@ -65,7 +63,6 @@ import java.util.LinkedHashSet;
import java.util.Set;
import org.jooq.Configuration;
import org.jooq.Converter;
import org.jooq.DSLContext;
import org.jooq.DataType;
import org.jooq.Field;
@ -73,7 +70,6 @@ import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.InsertQuery;
import org.jooq.Record;
import org.jooq.Row;
import org.jooq.SQLDialect;
import org.jooq.StoreQuery;
import org.jooq.Table;
@ -91,7 +87,7 @@ import org.jooq.tools.JooqLogger;
* @author Lukas Eder
*/
@org.jooq.Internal
public class TableRecordImpl<R extends TableRecord<R>> extends AbstractRecord implements TableRecord<R> {
public class TableRecordImpl<R extends TableRecord<R>> extends AbstractQualifiedRecord<R> implements TableRecord<R> {
/**
* Generated UID
@ -100,45 +96,13 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractRecord im
private static final JooqLogger log = JooqLogger.getLogger(TableRecordImpl.class);
private static final Set<SQLDialect> REFRESH_GENERATED_KEYS = SQLDialect.supportedBy(DERBY, H2, MARIADB, MYSQL);
private final Table<R> table;
public TableRecordImpl(Table<R> table) {
super((AbstractRow) table.fieldsRow());
this.table = table;
}
@SuppressWarnings("unchecked")
@Override
public final <T> R with(Field<T> field, T value) {
return (R) super.with(field, value);
}
@SuppressWarnings("unchecked")
@Override
public final <T, U> R with(Field<T> field, U value, Converter<? extends T, ? super U> converter) {
return (R) super.with(field, value, converter);
super(table);
}
@Override
public final Table<R> getTable() {
return table;
}
/*
* Subclasses may override this method
*/
@Override
public Row fieldsRow() {
return fields;
}
/*
* Subclasses may override this method
*/
@Override
public Row valuesRow() {
return row0(fieldsArray(intoArray(), fields.fields.fields()));
return (Table<R>) getQualifier();
}
@SuppressWarnings("unchecked")

View File

@ -257,10 +257,12 @@ import org.jooq.OrderField;
import org.jooq.Param;
// ...
import org.jooq.QualifiedAsterisk;
import org.jooq.QualifiedRecord;
import org.jooq.Query;
import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.RecordQualifier;
import org.jooq.RecordType;
import org.jooq.RenderContext;
import org.jooq.RenderContext.CastMode;
@ -911,38 +913,30 @@ final class Tools {
}
/**
* Create a new record
* Create a new record.
*/
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, Class<R> type, AbstractRow fields) {
return newRecord(fetched, type, fields, null);
}
/**
* Create a new record
* Create a new {@link Table} or {@link UDT} record.
*/
@SuppressWarnings("unchecked")
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, Table<R> type, Configuration configuration) {
return (RecordDelegate<R>) newRecord(fetched, type.getRecordType(), (AbstractRow) type.fieldsRow(), configuration);
}
/**
* Create a new UDT record
*/
static final <R extends UDTRecord<R>> RecordDelegate<R> newRecord(boolean fetched, UDT<R> type) {
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, RecordQualifier<R> type) {
return newRecord(fetched, type, null);
}
/**
* Create a new UDT record
* Create a new {@link Table} or {@link UDT} record.
*/
static final <R extends UDTRecord<R>> RecordDelegate<R> newRecord(boolean fetched, UDT<R> type, Configuration configuration) {
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, RecordQualifier<R> type, Configuration configuration) {
return newRecord(fetched, type.getRecordType(), (AbstractRow) type.fieldsRow(), configuration);
}
/**
* Create a new record.
*/
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, Class<R> type, AbstractRow fields, Configuration configuration) {
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, Class<? extends R> type, AbstractRow fields, Configuration configuration) {
return newRecord(fetched, recordFactory(type, fields), configuration);
}
@ -1031,7 +1025,7 @@ final class Tools {
* Create a new record factory.
*/
@SuppressWarnings({ "unchecked" })
static final <R extends Record> Supplier<R> recordFactory(final Class<R> type, final AbstractRow row) {
static final <R extends Record> Supplier<R> recordFactory(Class<? extends R> type, AbstractRow row) {
// An ad-hoc type resulting from a JOIN or arbitrary SELECT
if (type == AbstractRecord.class || type == Record.class || InternalRecord.class.isAssignableFrom(type)) {
@ -1072,7 +1066,7 @@ final class Tools {
try {
// [#919] Allow for accessing non-public constructors
final Constructor<R> constructor = Reflect.accessible(type.getDeclaredConstructor());
final Constructor<? extends R> constructor = Reflect.accessible(type.getDeclaredConstructor());
return () -> {
try {
@ -2947,7 +2941,6 @@ final class Tools {
/**
* Map a {@link Catalog} according to the configured {@link org.jooq.SchemaMapping}
*/
@SuppressWarnings("deprecation")
static final Catalog getMappedCatalog(Configuration configuration, Catalog catalog) {
if (configuration != null) {
org.jooq.SchemaMapping mapping = configuration.schemaMapping();
@ -2962,7 +2955,6 @@ final class Tools {
/**
* Map a {@link Schema} according to the configured {@link org.jooq.SchemaMapping}
*/
@SuppressWarnings("deprecation")
static final Schema getMappedSchema(Configuration configuration, Schema schema) {
if (configuration != null) {
org.jooq.SchemaMapping mapping = configuration.schemaMapping();
@ -2977,7 +2969,6 @@ final class Tools {
/**
* Map a {@link Table} according to the configured {@link org.jooq.SchemaMapping}
*/
@SuppressWarnings("deprecation")
static final <R extends Record> Table<R> getMappedTable(Configuration configuration, Table<R> table) {
if (configuration != null) {
org.jooq.SchemaMapping mapping = configuration.schemaMapping();
@ -2990,18 +2981,20 @@ final class Tools {
}
/**
* Map an {@link ArrayRecord} according to the configured {@link org.jooq.SchemaMapping}
* Map an {@link UDTRecord} according to the configured
* {@link org.jooq.SchemaMapping}
*/
@SuppressWarnings("unchecked")
static final String getMappedUDTName(Configuration configuration, Class<? extends UDTRecord<?>> type) {
return getMappedUDTName(configuration, Tools.newRecord(false, (Class<UDTRecord<?>>) type).operate(null));
static final String getMappedUDTName(Configuration configuration, Class<? extends QualifiedRecord<?>> type) {
return getMappedUDTName(configuration, Tools.newRecord(false, (Class<QualifiedRecord<?>>) type).operate(null));
}
/**
* Map an {@link ArrayRecord} according to the configured {@link org.jooq.SchemaMapping}
* Map an {@link UDTRecord} according to the configured
* {@link org.jooq.SchemaMapping}
*/
static final String getMappedUDTName(Configuration configuration, UDTRecord<?> record) {
UDT<?> udt = record.getUDT();
static final String getMappedUDTName(Configuration configuration, QualifiedRecord<?> record) {
RecordQualifier<?> udt = record.getQualifier();
Schema mapped = getMappedSchema(configuration, udt.getSchema());
StringBuilder sb = new StringBuilder();
@ -3013,7 +3006,12 @@ final class Tools {
sb.append(record.getUDT().getName());
sb.append(record.getQualifier().getName());
return sb.toString();
}

View File

@ -51,8 +51,8 @@ final class UDTDataType<R extends UDTRecord<R>> extends DefaultDataType<R> {
*/
private static final long serialVersionUID = 3262508265391094581L;
@SuppressWarnings("unchecked")
UDTDataType(UDT<R> udt) {
super(SQLDialect.DEFAULT, udt.getRecordType(), Tools.asString(udt.getQualifiedName()));
super(SQLDialect.DEFAULT, (Class<R>) udt.getRecordType(), Tools.asString(udt.getQualifiedName()));
}
}

View File

@ -37,20 +37,6 @@
*/
package org.jooq.impl;
import static org.jooq.impl.DefaultExecuteContext.localConfiguration;
import static org.jooq.impl.DefaultExecuteContext.localData;
import static org.jooq.impl.Tools.fieldsArray;
import static org.jooq.impl.Tools.row0;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
import java.util.Map;
import org.jooq.Configuration;
import org.jooq.Converter;
import org.jooq.Field;
import org.jooq.Row;
import org.jooq.UDT;
import org.jooq.UDTRecord;
@ -62,88 +48,20 @@ import org.jooq.UDTRecord;
* @author Lukas Eder
*/
@org.jooq.Internal
public class UDTRecordImpl<R extends UDTRecord<R>> extends AbstractRecord implements UDTRecord<R> {
public class UDTRecordImpl<R extends UDTRecord<R>> extends AbstractQualifiedRecord<R> implements UDTRecord<R> {
/**
* Generated UID
*/
private static final long serialVersionUID = 5671315498175872799L;
private final UDT<R> udt;
public UDTRecordImpl(UDT<R> udt) {
super((AbstractRow) udt.fieldsRow());
this.udt = udt;
super(udt);
}
@Override
public final UDT<R> getUDT() {
return udt;
}
/*
* Subclasses may override this method
*/
@Override
public Row fieldsRow() {
return fields;
}
/*
* Subclasses may override this method
*/
@Override
public Row valuesRow() {
return row0(fieldsArray(intoArray(), fields.fields.fields()));
}
@Override
public final String getSQLTypeName() throws SQLException {
// [#1693] This needs to return the fully qualified SQL type name, in
// case the connected user is not the owner of the UDT
Configuration configuration = localConfiguration();
return Tools.getMappedUDTName(configuration, this);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final void readSQL(SQLInput stream, String typeName) throws SQLException {
Configuration configuration = localConfiguration();
Map<Object, Object> data = localData();
Field<?>[] f = getUDT().fields();
for (int i = 0; i < f.length; i++) {
Field field = f[i];
DefaultBindingGetSQLInputContext out = new DefaultBindingGetSQLInputContext(configuration, data, stream);
field.getBinding().get(out);
set(i, field, out.value());
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public final void writeSQL(SQLOutput stream) throws SQLException {
Configuration configuration = localConfiguration();
Map<Object, Object> data = localData();
Field<?>[] f = getUDT().fields();
for (int i = 0; i < f.length; i++) {
Field field = f[i];
field.getBinding().set(new DefaultBindingSetSQLOutputContext(configuration, data, stream, get(i)));
}
}
@SuppressWarnings("unchecked")
@Override
public final <T> R with(Field<T> field, T value) {
return (R) super.with(field, value);
}
@SuppressWarnings("unchecked")
@Override
public final <T, U> R with(Field<T> field, U value, Converter<? extends T, ? super U> converter) {
return (R) super.with(field, value, converter);
return (UDT<R>) getQualifier();
}
@Override

View File

@ -429,7 +429,7 @@ public class UpdatableRecordImpl<R extends UpdatableRecord<R>> extends TableReco
// [#3359] The "fetched" flag must be set to false to enforce INSERT statements on
// subsequent store() calls - when Settings.updatablePrimaryKeys is set.
return (R) Tools.newRecord(false, getTable(), configuration())
return Tools.newRecord(false, getTable(), configuration())
.operate(copy -> {
// Copy all fields. This marks them all as isChanged, which is important
@ -440,7 +440,7 @@ public class UpdatableRecordImpl<R extends UpdatableRecord<R>> extends TableReco
if (!key.contains(field))
copy.set((Field) field, get(field));
return (R) copy;
return copy;
});
}