All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.army.criteria.impl.PostgreNestedJoins Maven / Gradle / Ivy

There is a newer version: 0.6.6
Show newest version
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 valueOperator, Function function, String keyName) { return this.repeatable(valueOperator.apply(function.apply(keyName))); } @Override public final RR ifRepeatable(Supplier supplier) { final Expression expression; if ((expression = supplier.get()) != null) { this.repeatable(expression); } return (RR) this; } @Override public final RR ifRepeatable(Function valueOperator, Supplier supplier) { final E seedValue; if ((seedValue = supplier.get()) != null) { this.repeatable(valueOperator.apply(seedValue)); } return (RR) this; } @Override public final RR ifRepeatable(Function valueOperator, Function function, String keyName) { final Object seedValue; if ((seedValue = function.apply(keyName)) != null) { this.repeatable(valueOperator.apply(seedValue)); } return (RR) this; } @Override public final _Expression sampleMethod() { return this.sampleMethod; } @Override public final _Expression seed() { return this.seed; } }//NestedTableBlock private static final class NestedTableJoinBlock extends NestedTableBlock< I, PostgreStatement._NestedRepeatableJoinClause, PostgreStatement._PostgreNestedJoinClause> implements PostgreStatement._NestedTableSampleJoinSpec, PostgreStatement._NestedRepeatableJoinClause { private NestedTableJoinBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, TableMeta table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); } }//NestedTableJoinBlock private static final class NestedTableCrossBlock extends NestedTableBlock< I, PostgreStatement._NestedRepeatableCrossClause, PostgreStatement._NestedJoinSpec> implements PostgreStatement._NestedTableSampleCrossSpec, PostgreStatement._NestedRepeatableCrossClause { private NestedTableCrossBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, TableMeta table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); } }//NestedTableCrossBlock private static final class NestedTableOnBlock extends NestedTableBlock< I, PostgreStatement._NestedRepeatableOnClause, PostgreStatement._NestedOnSpec> implements PostgreStatement._NestedTableSampleOnSpec, PostgreStatement._NestedRepeatableOnClause { private NestedTableOnBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, TableMeta table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); } }//NestedTableOnBlock @SuppressWarnings("unchecked") private static abstract class NestedDerivedBlock extends PostgreNestedBlock implements Statement._OptionalParensStringClause, _ModifierTabularBlock, _AliasDerivedBlock { private List columnAliasList; private _SelectionMap selectionMap; private NestedDerivedBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, DerivedTable table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); this.selectionMap = (_DerivedTable) table; } @Override public final R parens(String first, String... rest) { return this.onColumnAlias(ArrayUtils.unmodifiableListOf(first, rest)); } @Override public final R parens(Consumer> consumer) { return this.onColumnAlias(CriteriaUtils.stringList(this.context, true, consumer)); } @Override public final R ifParens(Consumer> consumer) { return this.onColumnAlias(CriteriaUtils.stringList(this.context, false, consumer)); } @Override public final Selection refSelection(String name) { if (this.columnAliasList == null) { this.columnAliasList = Collections.emptyList(); } return this.selectionMap.refSelection(name); } @Override public final List refAllSelection() { if (this.columnAliasList == null) { this.columnAliasList = Collections.emptyList(); } return this.selectionMap.refAllSelection(); } @Override public final List columnAliasList() { List list = this.columnAliasList; if (list == null) { list = Collections.emptyList(); this.columnAliasList = list; } return list; } private R onColumnAlias(final List columnAliasList) { if (this.columnAliasList != null) { throw ContextStack.clearStackAnd(_Exceptions::castCriteriaApi); } this.columnAliasList = columnAliasList; this.selectionMap = CriteriaUtils.createAliasSelectionMap(columnAliasList, ((_DerivedTable) this.tabularItem).refAllSelection(), this.alias); return (R) this; } }//NestedDerivedBlock private static final class NestedDerivedJoinBlock extends NestedDerivedBlock> implements PostgreStatement._NestedParensJoinSpec { private NestedDerivedJoinBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, DerivedTable table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); } }//NestedDerivedJoinBlock private static final class NestedDerivedCrossBlock extends NestedDerivedBlock> implements PostgreStatement._NestedParensCrossSpec { private NestedDerivedCrossBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, DerivedTable table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); } }//NestedDerivedCrossBlock private static final class NestedDerivedOnBlock extends NestedDerivedBlock> implements PostgreStatement._NestedParensOnSpec { private NestedDerivedOnBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable SQLWords modifier, DerivedTable table, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, table, alias, ender); } }//NestedDerivedOnBlock private static final class NestedDoneFuncBlock extends PostgreNestedBlock implements _DoneFuncBlock { private final List<_FunctionField> fieldList; private final Map fieldMap; private NestedDoneFuncBlock(CriteriaContext context, Consumer<_TabularBlock> blockConsumer, _JoinType joinType, @Nullable Statement.DerivedModifier modifier, PostgreUtils.DoneFunc func, String alias, Supplier ender) { super(context, blockConsumer, joinType, modifier, func.funcItem, alias, ender); this.fieldList = func.fieldList; this.fieldMap = func.fieldMap; } @Override public Selection refSelection(String name) { return this.fieldMap.get(name); } @Override public List refAllSelection() { return this.fieldList; } @Override public List<_FunctionField> fieldList() { return this.fieldList; } }//NestedDoneFuncBlock }