Skip to content

Commit

Permalink
[#6639] Cache TableRecord Constructor in TableImpl for use in
Browse files Browse the repository at this point in the history
Tools.recordFactory()
  • Loading branch information
lukaseder committed Feb 9, 2024
1 parent fac822c commit f0bb624
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 11 deletions.
15 changes: 12 additions & 3 deletions jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws
}

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();
Expand Down Expand Up @@ -342,15 +342,24 @@ public final Results fetchMany() {
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
Expand Down
7 changes: 4 additions & 3 deletions jOOQ/src/main/java/org/jooq/impl/CursorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
// ...
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;
Expand Down Expand Up @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions jOOQ/src/main/java/org/jooq/impl/FetchCount.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
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;

Expand All @@ -68,6 +69,11 @@ public final void accept(Context<?> ctx) {
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() {
Expand Down
2 changes: 1 addition & 1 deletion jOOQ/src/main/java/org/jooq/impl/R2DBC.java
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public final void onNext(Result r) {
// 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(
Expand Down
7 changes: 7 additions & 0 deletions jOOQ/src/main/java/org/jooq/impl/SQLResultQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@
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;

Expand Down Expand Up @@ -97,6 +99,11 @@ public final Clause[] clauses(Context<?> ctx) {
return null;
}

@Override
final Table<? extends Record1<Integer>> getTable0() {
return null;
}

@Override
public final Class<? extends Record> getRecordType0() {
return RecordImplN.class;
Expand Down
9 changes: 9 additions & 0 deletions jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@
import org.jooq.TableOnStep;
import org.jooq.TableOptionalOnStep;
import org.jooq.TablePartitionByStep;
import org.jooq.TableRecord;
// ...
// ...
// ...
Expand Down Expand Up @@ -4321,6 +4322,14 @@ private final boolean knownTableSource() {
);
}

@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() {
Expand Down
17 changes: 17 additions & 0 deletions jOOQ/src/main/java/org/jooq/impl/TableImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
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;
Expand Down Expand Up @@ -92,6 +93,7 @@
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;

Expand Down Expand Up @@ -561,6 +563,21 @@ public Class<? extends R> getRecordType() {
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;
Expand Down
22 changes: 18 additions & 4 deletions jOOQ/src/main/java/org/jooq/impl/Tools.java
Original file line number Diff line number Diff line change
Expand Up @@ -1369,14 +1369,22 @@ static final <R extends Record> RecordDelegate<R> newRecord(boolean fetched, Rec
* 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);
}

/**
Expand Down Expand Up @@ -1465,7 +1473,11 @@ static final Class<? extends AbstractRecord> recordType(int length) {
* 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)) {
Expand Down Expand Up @@ -1506,7 +1518,9 @@ static final <R extends Record> Supplier<R> recordFactory(Class<? extends R> typ
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 {
Expand Down

0 comments on commit f0bb624

Please sign in to comment.