io.army.criteria.impl.PostgreNestedJoins Maven / Gradle / Ivy
package io.army.criteria.impl;
import io.army.criteria.*;
import io.army.criteria.impl.inner.*;
import io.army.criteria.impl.inner.postgre._PostgreTableBlock;
import io.army.criteria.postgre.PostgreCrosses;
import io.army.criteria.postgre.PostgreJoins;
import io.army.criteria.postgre.PostgreStatement;
import javax.annotation.Nullable;
import io.army.mapping.MappingType;
import io.army.meta.TableMeta;
import io.army.util.ArrayUtils;
import io.army.util._Exceptions;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
*
* This class hold the implementation of Postgre nested join.
*
* @since 1.0
*/
final class PostgreNestedJoins extends JoinableClause.NestedLeftParenClause<
I,
PostgreStatement._NestedTableSampleJoinSpec,
Statement._AsClause>,
PostgreStatement._PostgreNestedJoinClause,
PostgreStatement._FuncColumnDefinitionAsClause>>
implements PostgreStatement._NestedLeftParenSpec {
static PostgreStatement._NestedLeftParenSpec nestedItem(
CriteriaContext context, _JoinType joinType, BiFunction<_JoinType, _NestedItems, I> function) {
return new PostgreNestedJoins<>(context, joinType, function);
}
private PostgreNestedJoins(CriteriaContext context, _JoinType joinType,
BiFunction<_JoinType, _NestedItems, I> function) {
super(context, joinType, function);
}
@Override
public PostgreStatement._PostgreNestedJoinClause leftParen(
Function>, PostgreStatement._PostgreNestedJoinClause> function) {
return function.apply(new PostgreNestedJoins<>(this.context, _JoinType.NONE, this::nestedNestedJoinEnd));
}
@Override
boolean isIllegalTableModifier(@Nullable Query.TableModifier modifier) {
return CriteriaUtils.isIllegalOnly(modifier);
}
@Override
boolean isIllegalDerivedModifier(@Nullable Query.DerivedModifier modifier) {
return CriteriaUtils.isIllegalLateral(modifier);
}
@Override
PostgreStatement._NestedTableSampleJoinSpec onLeftTable(
@Nullable Query.TableModifier modifier, TableMeta> table, String tableAlias) {
final NestedTableJoinBlock block;
block = new NestedTableJoinBlock<>(this.context, this::onAddTabularBlock, _JoinType.NONE, modifier, table, tableAlias,
this::thisNestedJoinEnd);
this.onAddTabularBlock(block);
return block;
}
@Override
Statement._AsClause> onLeftDerived(
@Nullable Query.DerivedModifier modifier, DerivedTable table) {
return alias -> {
final NestedDerivedJoinBlock block;
block = new NestedDerivedJoinBlock<>(this.context, this::onAddTabularBlock, _JoinType.NONE, modifier,
table, alias, this::thisNestedJoinEnd);
this.onAddTabularBlock(block);
return block;
};
}
@Override
PostgreStatement._PostgreNestedJoinClause onLeftCte(_Cte cteItem, String alias) {
final PostgreNestedBlock block;
block = new PostgreNestedBlock<>(this.context, this::onAddTabularBlock, _JoinType.NONE, null,
cteItem, alias, this::thisNestedJoinEnd);
this.onAddTabularBlock(block);
return block;
}
@Override
PostgreStatement._FuncColumnDefinitionAsClause> onLeftUndoneFunc(
final @Nullable Statement.DerivedModifier modifier, final UndoneFunction func) {
return alias -> {
final Function> function;
function = doneFunc -> {
NestedDoneFuncBlock block;
block = new NestedDoneFuncBlock<>(this.context, this::onAddTabularBlock, _JoinType.NONE, modifier,
doneFunc, alias, this::thisNestedJoinEnd);
this.onAddTabularBlock(block);
return block;
};
return PostgreUtils.undoneFunc(func, function);
};
}
private PostgreStatement._PostgreNestedJoinClause nestedNestedJoinEnd(final _JoinType joinType,
final _NestedItems nestedItems) {
if (joinType != _JoinType.NONE) {
throw _Exceptions.unexpectedEnum(joinType);
}
final PostgreNestedBlock clause;
clause = new PostgreNestedBlock<>(this.context, this::onAddTabularBlock, joinType, null, nestedItems, "",
this::thisNestedJoinEnd);
this.onAddTabularBlock(clause);
return clause;
}
private static class PostgreNestedBlock extends JoinableClause.NestedJoinableBlock<
PostgreStatement._NestedTableSampleCrossSpec,
Statement._AsClause>,
PostgreStatement._NestedJoinSpec,
PostgreStatement._FuncColumnDefinitionAsClause>,
PostgreStatement._NestedTableSampleOnSpec,
Statement._AsClause>,
PostgreStatement._NestedOnSpec,
PostgreStatement._FuncColumnDefinitionAsClause>,
PostgreStatement._NestedJoinSpec>
implements PostgreStatement._NestedOnSpec {
private final Supplier ender;
private PostgreNestedBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType,
@Nullable SQLWords modifier, TabularItem tabularItem, String alias,
Supplier ender) {
super(context, blockConsumer, joinType, modifier, tabularItem, alias);
this.ender = ender;
}
@Override
public final PostgreStatement._NestedJoinSpec crossJoin(Function>, PostgreStatement._NestedJoinSpec> function) {
return function.apply(new PostgreNestedJoins<>(this.context, _JoinType.CROSS_JOIN, this::crossNestedEnd));
}
@Override
public final PostgreStatement._NestedOnSpec leftJoin(Function>, PostgreStatement._NestedOnSpec> function) {
return function.apply(new PostgreNestedJoins<>(this.context, _JoinType.LEFT_JOIN, this::joinNestedEnd));
}
@Override
public final PostgreStatement._NestedOnSpec join(Function>, PostgreStatement._NestedOnSpec> function) {
return function.apply(new PostgreNestedJoins<>(this.context, _JoinType.JOIN, this::joinNestedEnd));
}
@Override
public final PostgreStatement._NestedOnSpec rightJoin(Function>, PostgreStatement._NestedOnSpec> function) {
return function.apply(new PostgreNestedJoins<>(this.context, _JoinType.RIGHT_JOIN, this::joinNestedEnd));
}
@Override
public final PostgreStatement._NestedOnSpec fullJoin(Function>, PostgreStatement._NestedOnSpec> function) {
return function.apply(new PostgreNestedJoins<>(this.context, _JoinType.FULL_JOIN, this::joinNestedEnd));
}
@Override
public final PostgreStatement._NestedJoinSpec ifLeftJoin(Consumer consumer) {
consumer.accept(PostgreDynamicJoins.joinBuilder(this.context, _JoinType.LEFT_JOIN, this.blockConsumer));
return this;
}
@Override
public final PostgreStatement._NestedJoinSpec ifJoin(Consumer consumer) {
consumer.accept(PostgreDynamicJoins.joinBuilder(this.context, _JoinType.JOIN, this.blockConsumer));
return this;
}
@Override
public final PostgreStatement._NestedJoinSpec ifRightJoin(Consumer consumer) {
consumer.accept(PostgreDynamicJoins.joinBuilder(this.context, _JoinType.RIGHT_JOIN, this.blockConsumer));
return this;
}
@Override
public final PostgreStatement._NestedJoinSpec ifFullJoin(Consumer consumer) {
consumer.accept(PostgreDynamicJoins.joinBuilder(this.context, _JoinType.FULL_JOIN, this.blockConsumer));
return this;
}
@Override
public final PostgreStatement._NestedJoinSpec ifCrossJoin(Consumer consumer) {
consumer.accept(PostgreDynamicJoins.crossBuilder(this.context, this.blockConsumer));
return this;
}
@Override
public final I rightParen() {
return this.ender.get();
}
@Override
boolean isIllegalTableModifier(@Nullable Query.TableModifier modifier) {
return CriteriaUtils.isIllegalOnly(modifier);
}
@Override
boolean isIllegalDerivedModifier(@Nullable Query.DerivedModifier modifier) {
return CriteriaUtils.isIllegalLateral(modifier);
}
@Override
final PostgreStatement._NestedTableSampleCrossSpec onFromTable(_JoinType joinType,
@Nullable Query.TableModifier modifier,
TableMeta> table, String alias) {
final NestedTableCrossBlock block;
block = new NestedTableCrossBlock<>(this.context, this.blockConsumer, joinType, modifier, table, alias,
this.ender);
this.blockConsumer.accept(block);
return block;
}
@Override
final Statement._AsClause> onFromDerived(
_JoinType joinType, @Nullable Query.DerivedModifier modifier, DerivedTable table) {
return alias -> {
final NestedDerivedCrossBlock block;
block = new NestedDerivedCrossBlock<>(this.context, this.blockConsumer, joinType, modifier, table,
alias, this.ender);
this.blockConsumer.accept(block);
return block;
};
}
@Override
final PostgreStatement._FuncColumnDefinitionAsClause> onFromUndoneFunc(
final _JoinType joinType, final @Nullable Statement.DerivedModifier modifier,
final UndoneFunction func) {
return alias -> {
final Function> function;
function = doneFunc -> {
final NestedDoneFuncBlock block;
block = new NestedDoneFuncBlock<>(this.context, this.blockConsumer, joinType, modifier,
doneFunc, alias, this.ender);
this.blockConsumer.accept(block);
return block;
};
return PostgreUtils.undoneFunc(func, function);
};
}
@Override
final PostgreStatement._NestedJoinSpec onFromCte(_JoinType joinType,
@Nullable Query.DerivedModifier modifier,
_Cte cteItem, String alias) {
final PostgreNestedBlock block;
block = new PostgreNestedBlock<>(this.context, this.blockConsumer, joinType, modifier, cteItem, alias,
this.ender);
this.blockConsumer.accept(block);
return block;
}
@Override
final PostgreStatement._NestedTableSampleOnSpec onJoinTable(_JoinType joinType,
@Nullable Query.TableModifier modifier,
TableMeta> table, String alias) {
final NestedTableOnBlock block;
block = new NestedTableOnBlock<>(this.context, this.blockConsumer, joinType, modifier, table, alias,
this.ender);
this.blockConsumer.accept(block);
return block;
}
@Override
final Statement._AsClause> onJoinDerived(
_JoinType joinType, @Nullable Query.DerivedModifier modifier, DerivedTable table) {
return alias -> {
final NestedDerivedOnBlock block;
block = new NestedDerivedOnBlock<>(this.context, this.blockConsumer, joinType, modifier, table,
alias, this.ender);
this.blockConsumer.accept(block);
return block;
};
}
@Override
final PostgreStatement._NestedOnSpec onJoinCte(_JoinType joinType,
@Nullable Query.DerivedModifier modifier,
_Cte cteItem, String alias) {
final PostgreNestedBlock block;
block = new PostgreNestedBlock<>(this.context, this.blockConsumer, joinType, modifier, cteItem, alias,
this.ender);
this.blockConsumer.accept(block);
return block;
}
@Override
final PostgreStatement._FuncColumnDefinitionAsClause> onJoinUndoneFunc(
final _JoinType joinType, final @Nullable Statement.DerivedModifier modifier,
final UndoneFunction func) {
return alias -> {
final Function> function;
function = doneFunc -> {
final NestedDoneFuncBlock block;
block = new NestedDoneFuncBlock<>(this.context, this.blockConsumer, joinType, modifier,
doneFunc, alias, this.ender);
this.blockConsumer.accept(block);
return block;
};
return PostgreUtils.undoneFunc(func, function);
};
}
/**
* @see #leftJoin(Function)
* @see #join(Function)
* @see #rightJoin(Function)
* @see #fullJoin(Function)
*/
private PostgreStatement._NestedOnSpec joinNestedEnd(final _JoinType joinType,
final _NestedItems nestedItems) {
final PostgreNestedBlock block;
block = new PostgreNestedBlock<>(this.context, this.blockConsumer, joinType, null, nestedItems, "",
this.ender);
this.blockConsumer.accept(block);
return block;
}
/**
* @see #crossJoin(Function)
*/
private PostgreStatement._NestedJoinSpec crossNestedEnd(final _JoinType joinType, final _NestedItems items) {
assert joinType == _JoinType.CROSS_JOIN;
final PostgreNestedBlock block;
block = new PostgreNestedBlock<>(this.context, this.blockConsumer, _JoinType.CROSS_JOIN, null, items, "",
this.ender);
this.blockConsumer.accept(block);
return block;
}
}//PostgreNestedBlock
@SuppressWarnings("unchecked")
private static abstract class NestedTableBlock extends PostgreNestedBlock
implements PostgreStatement._TableSampleClause,
PostgreStatement._RepeatableClause,
_PostgreTableBlock {
private ArmyExpression sampleMethod;
private ArmyExpression seed;
private NestedTableBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType,
@Nullable SQLWords modifier, TableMeta> table, String alias,
Supplier ender) {
super(context, blockConsumer, joinType, modifier, table, alias, ender);
}
@Override
public final TR tableSample(final @Nullable Expression method) {
if (this.sampleMethod != null) {
throw ContextStack.castCriteriaApi(this.context);
} else if (method == null) {
throw ContextStack.nullPointer(this.context);
}
this.sampleMethod = (ArmyExpression) method;
return (TR) this;
}
@Override
public final TR tableSample(BiFunction, Expression, Expression> method,
BiFunction valueOperator, Expression argument) {
return this.tableSample(method.apply(valueOperator, argument));
}
@Override
public final TR tableSample(BiFunction, T, Expression> method,
BiFunction valueOperator, Supplier supplier) {
return this.tableSample(method.apply(valueOperator, supplier.get()));
}
@Override
public final TR tableSample(BiFunction, Object, Expression> method,
BiFunction valueOperator, Function function,
String keyName) {
return this.tableSample(method.apply(valueOperator, function.apply(keyName)));
}
@Override
public final TR ifTableSample(Supplier supplier) {
final Expression expression;
expression = supplier.get();
if (expression != null) {
this.tableSample(expression);
}
return (TR) this;
}
@Override
public final TR ifTableSample(BiFunction, T, Expression> method,
BiFunction valueOperator, Supplier supplier) {
final T argument;
argument = supplier.get();
if (argument != null) {
this.tableSample(method.apply(valueOperator, argument));
}
return (TR) this;
}
@Override
public final TR ifTableSample(BiFunction, Object, Expression> method,
BiFunction valueOperator, Function function,
String keyName) {
final Object argument;
argument = function.apply(keyName);
if (argument != null) {
this.tableSample(method.apply(valueOperator, argument));
}
return (TR) this;
}
@Override
public final RR repeatable(final @Nullable Expression seed) {
if (seed == null) {
throw ContextStack.nullPointer(this.context);
}
this.seed = (ArmyExpression) seed;
return (RR) this;
}
@Override
public final RR repeatable(Supplier supplier) {
return this.repeatable(supplier.get());
}
@Override
public final RR repeatable(Function valueOperator, Number seedValue) {
return this.repeatable(valueOperator.apply(seedValue));
}
@Override
public final RR repeatable(Function valueOperator, Supplier supplier) {
return this.repeatable(valueOperator.apply(supplier.get()));
}
@Override
public final RR repeatable(Function