[jOOQ/jOOQ#6639] Cache TableRecord Constructor in TableImpl for use in
Tools.recordFactory()
This commit is contained in:
parent
ba1b9d96b7
commit
8899b97f11
@ -259,7 +259,7 @@ implements
|
||||
}
|
||||
|
||||
Field<?>[] fields = getFields(() -> ctx.resultSet().getMetaData());
|
||||
cursor = new CursorImpl<>(ctx, listener, fields, intern.internIndexes(fields), keepStatement(), keepResultSet(), getRecordType(), SettingsTools.getMaxRows(maxRows, ctx.settings()), autoclosing);
|
||||
cursor = new CursorImpl<>(ctx, listener, fields, intern.internIndexes(fields), keepStatement(), keepResultSet(), getTable(), getRecordType(), SettingsTools.getMaxRows(maxRows, ctx.settings()), autoclosing);
|
||||
|
||||
if (!lazy) {
|
||||
result = cursor.fetch();
|
||||
@ -342,15 +342,24 @@ implements
|
||||
return results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Table<? extends R> getTable() {
|
||||
if (coerceTable != null)
|
||||
return (Table<? extends R>) coerceTable;
|
||||
else
|
||||
return getTable0();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final Class<? extends R> getRecordType() {
|
||||
if (coerceTable != null)
|
||||
return (Class<? extends R>) coerceTable.getRecordType();
|
||||
|
||||
return getRecordType0();
|
||||
else
|
||||
return getRecordType0();
|
||||
}
|
||||
|
||||
abstract Table<? extends R> getTable0();
|
||||
abstract Class<? extends R> getRecordType0();
|
||||
|
||||
@Override
|
||||
|
||||
@ -84,6 +84,7 @@ import org.jooq.Field;
|
||||
// ...
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.exception.ControlFlowSignal;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.jdbc.JDBC41ResultSet;
|
||||
@ -112,15 +113,15 @@ final class CursorImpl<R extends Record> extends AbstractCursor<R> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
CursorImpl(ExecuteContext ctx, ExecuteListener listener, Field<?>[] fields, int[] internIndexes, boolean keepStatement, boolean keepResultSet) {
|
||||
this(ctx, listener, fields, internIndexes, keepStatement, keepResultSet, (Class<? extends R>) RecordImplN.class, 0, true);
|
||||
this(ctx, listener, fields, internIndexes, keepStatement, keepResultSet, null, (Class<? extends R>) RecordImplN.class, 0, true);
|
||||
}
|
||||
|
||||
CursorImpl(ExecuteContext ctx, ExecuteListener listener, Field<?>[] fields, int[] internIndexes, boolean keepStatement, boolean keepResultSet, Class<? extends R> type, int maxRows, boolean autoclosing) {
|
||||
CursorImpl(ExecuteContext ctx, ExecuteListener listener, Field<?>[] fields, int[] internIndexes, boolean keepStatement, boolean keepResultSet, Table<? extends R> table, Class<? extends R> type, int maxRows, boolean autoclosing) {
|
||||
super(ctx.configuration(), (AbstractRow<R>) Tools.row0(fields));
|
||||
|
||||
this.ctx = ctx;
|
||||
this.listener = (listener != null ? listener : ExecuteListeners.getAndStart(ctx));
|
||||
this.factory = recordFactory(type, this.fields);
|
||||
this.factory = recordFactory(table, type, this.fields);
|
||||
this.keepStatement = keepStatement;
|
||||
this.keepResultSet = keepResultSet;
|
||||
this.rs = new CursorResultSet();
|
||||
|
||||
@ -46,6 +46,7 @@ import org.jooq.Context;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.impl.QOM.UEmpty;
|
||||
import org.jooq.impl.QOM.UTransient;
|
||||
|
||||
@ -68,6 +69,11 @@ final class FetchCount extends AbstractResultQuery<Record1<Integer>> implements
|
||||
ctx.visit(select(count).from(new AliasedSelect<>(query, true, true, false).as("t")));
|
||||
}
|
||||
|
||||
@Override
|
||||
final Table<? extends Record1<Integer>> getTable0() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public final Class<? extends Record1<Integer>> getRecordType0() {
|
||||
|
||||
@ -350,7 +350,7 @@ final class R2DBC {
|
||||
// TODO: This call is duplicated from CursorImpl and related classes.
|
||||
// Refactor this call to make sure code is re-used, especially when
|
||||
// ExecuteListener lifecycle management is implemented
|
||||
RecordDelegate<AbstractRecord> delegate = Tools.newRecord(true, recordFactory((Class<AbstractRecord>) query.getRecordType(), (AbstractRow<AbstractRecord>) Tools.row0(fields)), query.configuration());
|
||||
RecordDelegate<AbstractRecord> delegate = Tools.newRecord(true, recordFactory(null, (Class<AbstractRecord>) query.getRecordType(), (AbstractRow<AbstractRecord>) Tools.row0(fields)), query.configuration());
|
||||
|
||||
// TODO: What data to pass here?
|
||||
DefaultBindingGetResultSetContext<?> ctx = new DefaultBindingGetResultSetContext(
|
||||
|
||||
@ -51,7 +51,9 @@ import org.jooq.Field;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.QueryPartInternal;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.SQL;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.impl.QOM.UEmpty;
|
||||
import org.jooq.impl.QOM.UEmptyQuery;
|
||||
|
||||
@ -97,6 +99,11 @@ final class SQLResultQuery extends AbstractResultQuery<Record> implements UEmpty
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
final Table<? extends Record1<Integer>> getTable0() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Class<? extends Record> getRecordType0() {
|
||||
return RecordImplN.class;
|
||||
|
||||
@ -318,6 +318,7 @@ import org.jooq.TableLike;
|
||||
import org.jooq.TableOnStep;
|
||||
import org.jooq.TableOptionalOnStep;
|
||||
import org.jooq.TablePartitionByStep;
|
||||
import org.jooq.TableRecord;
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
@ -4332,6 +4333,14 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
final Table<? extends R> getTable0() {
|
||||
return getFrom().size() == 1 && TableRecord.class.isAssignableFrom(getRecordType0())
|
||||
? (Table<? extends R>) getFrom().get(0)
|
||||
: null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
final Class<? extends R> getRecordType0() {
|
||||
|
||||
@ -65,6 +65,7 @@ import static org.jooq.impl.Tools.unwrap;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_RENDER_IMPLICIT_JOIN;
|
||||
import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
@ -92,6 +93,7 @@ import org.jooq.TableOptions;
|
||||
import org.jooq.impl.QOM.JoinHint;
|
||||
import org.jooq.impl.QOM.UEmpty;
|
||||
import org.jooq.tools.StringUtils;
|
||||
import org.jooq.tools.reflect.Reflect;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -561,6 +563,21 @@ implements
|
||||
return (Class<? extends R>) RecordImplN.class;
|
||||
}
|
||||
|
||||
private transient Constructor<? extends R> recordConstructor;
|
||||
|
||||
final Constructor<? extends R> getRecordConstructor() {
|
||||
if (recordConstructor == null) {
|
||||
try {
|
||||
recordConstructor = Reflect.accessible(getRecordType().getDeclaredConstructor());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Could not access record constructor", e);
|
||||
}
|
||||
}
|
||||
|
||||
return recordConstructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean declaresTables() {
|
||||
return true;
|
||||
|
||||
@ -1375,14 +1375,22 @@ final class Tools {
|
||||
* Create a new {@link Table} or {@link UDT} record.
|
||||
*/
|
||||
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, RecordQualifier<R> type, Configuration configuration) {
|
||||
return newRecord(fetched, type.getRecordType(), (AbstractRow<R>) type.fieldsRow(), configuration);
|
||||
return newRecord(
|
||||
fetched,
|
||||
recordFactory(
|
||||
type,
|
||||
type.getRecordType(),
|
||||
(AbstractRow<R>) type.fieldsRow()
|
||||
),
|
||||
configuration
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new record.
|
||||
*/
|
||||
static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, Class<? extends R> type, AbstractRow<? extends R> fields, Configuration configuration) {
|
||||
return newRecord(fetched, recordFactory(type, fields), configuration);
|
||||
return newRecord(fetched, recordFactory(null, type, fields), configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1471,7 +1479,11 @@ final class Tools {
|
||||
* Create a new record factory.
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
static final <R extends Record> Supplier<R> recordFactory(Class<? extends R> type, AbstractRow<? extends R> row) {
|
||||
static final <R extends Record> Supplier<R> recordFactory(
|
||||
RecordQualifier<? extends R> qualifier,
|
||||
Class<? extends R> type,
|
||||
AbstractRow<? extends R> row
|
||||
) {
|
||||
|
||||
// An ad-hoc type resulting from a JOIN or arbitrary SELECT
|
||||
if (type == AbstractRecord.class || type == Record.class || InternalRecord.class.isAssignableFrom(type)) {
|
||||
@ -1512,7 +1524,9 @@ final class Tools {
|
||||
try {
|
||||
|
||||
// [#919] Allow for accessing non-public constructors
|
||||
final Constructor<? extends R> constructor = Reflect.accessible(type.getDeclaredConstructor());
|
||||
final Constructor<? extends R> constructor = qualifier instanceof TableImpl<? extends R> t
|
||||
? t.getRecordConstructor()
|
||||
: Reflect.accessible(type.getDeclaredConstructor());
|
||||
|
||||
return () -> {
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user