[jOOQ/jOOQ#13843] Cannot use Table as SelectField from derived table
where nesting records is supported natively
This commit is contained in:
parent
58a9029b20
commit
596b5d5394
@ -65,11 +65,17 @@ import org.jooq.Fields;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Row;
|
||||
import org.jooq.SelectField;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
abstract class AbstractRowAsField<R extends Record> extends AbstractField<R> {
|
||||
abstract class AbstractRowAsField<R extends Record>
|
||||
extends
|
||||
AbstractField<R>
|
||||
implements
|
||||
AutoAlias<SelectField<R>>
|
||||
{
|
||||
|
||||
AbstractRowAsField(Name name, DataType<R> type) {
|
||||
super(name, type);
|
||||
@ -222,6 +228,22 @@ abstract class AbstractRowAsField<R extends Record> extends AbstractField<R> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SelectField<R> autoAlias(Context<?> ctx) {
|
||||
|
||||
// [#13843] Re-aliasing only applies if at least ROW() projection is supported natively
|
||||
if (RowAsField.NO_NATIVE_SUPPORT.contains(ctx.dialect()))
|
||||
return this;
|
||||
|
||||
// [#13843] Within MULTISET(), re-aliasing isn't required, while it leads to new edge cases
|
||||
else if (forceMultisetContent(ctx, () -> getDataType().getRow().size() > 1))
|
||||
return this;
|
||||
|
||||
// [#13843] With native support, re-alias the table as field projection
|
||||
else
|
||||
return new FieldAlias<>(this, getUnqualifiedName());
|
||||
}
|
||||
|
||||
private static final Field<?> alias(Context<?> ctx, Name alias, Field<?> field) {
|
||||
return ctx.declareFields() ? field.as(alias) : field;
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
package org.jooq.impl;
|
||||
|
||||
import org.jooq.Context;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.QueryPartInternal;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Table;
|
||||
@ -48,11 +49,11 @@ import org.jooq.Table;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
interface AutoAliasTable<R extends Record> extends Table<R>, QueryPartInternal {
|
||||
interface AutoAlias<Q extends QueryPart> extends QueryPartInternal {
|
||||
|
||||
/**
|
||||
* Create the aliased table expression or <code>null</code> if no auto-alias
|
||||
* is required.
|
||||
*/
|
||||
Table<R> autoAlias(Context<?> ctx);
|
||||
Q autoAlias(Context<?> ctx);
|
||||
}
|
||||
@ -49,7 +49,13 @@ import org.jooq.QueryPart;
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
final class Coerce<T> extends AbstractField<T> implements QOM.Coerce<T> {
|
||||
final class Coerce<T>
|
||||
extends
|
||||
AbstractField<T>
|
||||
implements
|
||||
AutoAlias<Field<T>>,
|
||||
QOM.Coerce<T>
|
||||
{
|
||||
|
||||
final AbstractField<?> field;
|
||||
|
||||
@ -118,6 +124,15 @@ final class Coerce<T> extends AbstractField<T> implements QOM.Coerce<T> {
|
||||
return field.generatesCast();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final Field<T> autoAlias(Context<?> ctx) {
|
||||
if (field instanceof AutoAlias)
|
||||
return ((AutoAlias<Field<T>>) field).autoAlias(ctx).coerce(getDataType());
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Query Object Model
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -82,7 +82,7 @@ final class DataChangeDeltaTable<R extends Record>
|
||||
extends
|
||||
AbstractTable<R>
|
||||
implements
|
||||
AutoAliasTable<R>,
|
||||
AutoAlias<Table<R>>,
|
||||
QOM.DataChangeDeltaTable<R>
|
||||
{
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ final class GenerateSeries
|
||||
extends
|
||||
AbstractTable<Record1<Integer>>
|
||||
implements
|
||||
AutoAliasTable<Record1<Integer>>,
|
||||
AutoAlias<Table<Record1<Integer>>>,
|
||||
QOM.GenerateSeries<Integer>
|
||||
{
|
||||
|
||||
|
||||
@ -74,15 +74,26 @@ final class SelectFieldList<F extends SelectFieldOrAsterisk> extends QueryPartLi
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void acceptElement(Context<?> ctx, F part) {
|
||||
|
||||
// [#4727] Various SelectFieldList references containing Table<?> cannot
|
||||
// resolve the instance in time for the rendering, e.g. RETURNING
|
||||
if (part instanceof AbstractTable<?> t)
|
||||
ctx.visit(t.tf());
|
||||
acceptElement0(ctx, (F) t.tf());
|
||||
else if (part instanceof AbstractRow<?> r)
|
||||
ctx.visit(r.rf());
|
||||
acceptElement0(ctx, (F) r.rf());
|
||||
else
|
||||
acceptElement0(ctx, part);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void acceptElement0(Context<?> ctx, F part) {
|
||||
F alternative;
|
||||
|
||||
if (ctx.declareFields() && part instanceof AutoAlias && (alternative = ((AutoAlias<F>) part).autoAlias(ctx)) != null)
|
||||
super.acceptElement(ctx, alternative);
|
||||
else
|
||||
super.acceptElement(ctx, part);
|
||||
}
|
||||
|
||||
@ -82,11 +82,12 @@ final class TableList extends QueryPartList<Table<?>> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void acceptElement(Context<?> ctx, Table<?> part) {
|
||||
Table<?> alternative;
|
||||
|
||||
if (ctx.declareTables() && part instanceof AutoAliasTable && (alternative = ((AutoAliasTable<?>) part).autoAlias(ctx)) != null)
|
||||
if (ctx.declareTables() && part instanceof AutoAlias && (alternative = ((AutoAlias<Table<?>>) part).autoAlias(ctx)) != null)
|
||||
super.acceptElement(ctx, alternative);
|
||||
else
|
||||
super.acceptElement(ctx, part);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user