diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java index 307db5b650..1c863144cb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java @@ -52,37 +52,54 @@ import static org.jooq.impl.Keywords.K_WHEN; import static org.jooq.impl.Names.NQ_CASE; import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_CASE_ELSE_NULL; -import java.util.ArrayList; import java.util.List; import org.jooq.CaseConditionStep; import org.jooq.Condition; import org.jooq.Context; +import org.jooq.DataType; import org.jooq.Field; +import org.jooq.Function2; // ... +import org.jooq.QueryPart; import org.jooq.Record1; // ... import org.jooq.Select; -import org.jooq.impl.QOM.UNotYetImplemented; +// ... +import org.jooq.impl.QOM.CaseSearched; +import org.jooq.impl.QOM.UTuple2; +import org.jooq.impl.QOM.UnmodifiableList; /** * @author Lukas Eder */ -final class CaseConditionStepImpl extends AbstractField implements CaseConditionStep, UNotYetImplemented { +final class CaseConditionStepImpl +extends + AbstractField +implements + CaseConditionStep, + QOM.CaseSearched +{ - private final List conditions; - private final List> results; - private Field else_; + private final List>> when; + private Field else_; + + CaseConditionStepImpl(DataType type) { + super(NQ_CASE, type); + + this.when = new QueryPartList<>(); + } CaseConditionStepImpl(Condition condition, Field result) { - super(NQ_CASE, result.getDataType()); - - this.conditions = new ArrayList<>(); - this.results = new ArrayList<>(); + this(result.getDataType()); when(condition, result); } + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + @Override public final CaseConditionStep when(Condition condition, T result) { return when(condition, Tools.field(result)); @@ -90,9 +107,7 @@ final class CaseConditionStepImpl extends AbstractField implements CaseCon @Override public final CaseConditionStep when(Condition condition, Field result) { - conditions.add(condition); - results.add(result); - + when.add(QOM.tuple(condition, result)); return this; } @@ -200,11 +215,6 @@ final class CaseConditionStepImpl extends AbstractField implements CaseCon - - - - - @@ -215,9 +225,8 @@ final class CaseConditionStepImpl extends AbstractField implements CaseCon ctx.visit(K_CASE) .formatIndentStart(); - int size = conditions.size(); - for (int i = 0; i < size; i++) { - Condition c = conditions.get(i); + for (UTuple2> e : when) { + Condition c = e.$part1(); @@ -236,7 +245,7 @@ final class CaseConditionStepImpl extends AbstractField implements CaseCon ctx.formatSeparator() .visit(K_WHEN).sql(' ').visit(c).sql(' ') - .visit(K_THEN).sql(' ').visit(results.get(i)); + .visit(K_THEN).sql(' ').visit(e.$part2()); } if (else_ != null) @@ -250,4 +259,54 @@ final class CaseConditionStepImpl extends AbstractField implements CaseCon .formatSeparator() .visit(K_END); } + + // ------------------------------------------------------------------------- + // XXX: Query Object Model + // ------------------------------------------------------------------------- + + @Override + public final Function2>>, ? super Field, ? extends CaseSearched> $constructor() { + return (w, e) -> { + CaseConditionStepImpl r = new CaseConditionStepImpl<>(getDataType()); + w.forEach(t -> r.when(t.$part1(), t.$part2())); + r.else_(e); + return r; + }; + } + + @Override + public final UnmodifiableList>> $arg1() { + return QOM.unmodifiable(when); + } + + @Override + public final CaseSearched $arg1(UnmodifiableList>> w) { + return $constructor().apply(w, $else()); + } + + @Override + public final Field $arg2() { + return else_; + } + + @Override + public final CaseSearched $arg2(Field e) { + return $constructor().apply($when(), e); + } + + @Override + public final R $traverse(Traverser traverser) { + return QOM.traverse(traverser, this, $when(), $else()); + } + + @Override + public final QueryPart $replace(Replacer replacer) { + return QOM.replace( + this, + $when(), + $else(), + (w, e) -> $constructor().apply(w, e), + replacer + ); + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java index e7b736b18b..b9734c4645 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java @@ -39,7 +39,6 @@ package org.jooq.impl; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Map.Entry; import org.jooq.CaseValueStep; import org.jooq.CaseWhenStep; diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java index 4aa95700ed..7829910b2e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java @@ -62,6 +62,9 @@ import org.jooq.Field; // ... import org.jooq.impl.QOM.UNotYetImplemented; +/** + * @author Lukas Eder + */ final class CaseWhenStepImpl extends AbstractField implements CaseWhenStep, UNotYetImplemented { private final Field value; diff --git a/jOOQ/src/main/java/org/jooq/impl/QOM.java b/jOOQ/src/main/java/org/jooq/impl/QOM.java index 06b7adbb64..5b09c78de0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QOM.java +++ b/jOOQ/src/main/java/org/jooq/impl/QOM.java @@ -218,6 +218,18 @@ public final class QOM { // minimal example. Without the qualification, the types cannot be found // despite being imported + public sealed interface UTuple2 + extends + org.jooq.QueryPart + permits + UTupleImpl2 + { + @NotNull Q1 $part1(); + @NotNull UTuple2 $part1(Q1 newPart1); + @NotNull Q2 $part2(); + @NotNull UTuple2 $part2(Q2 newPart2); + } + /** * An unmodifiable {@link Collection} of {@link QueryPart} elements. */ @@ -965,6 +977,30 @@ public final class QOM { Coalesce*/ {} + public /*sealed*/ interface CaseSimple + extends + Field, + UOperator3, UnmodifiableList, Field>>, Field, CaseSimple> + { + @NotNull default Field $value() { return $arg1(); } + @NotNull default CaseSimple $value(Field value) { return $arg1(value); } + @NotNull default UnmodifiableList, Field>> $when() { return $arg2(); } + @NotNull default CaseSimple $when(UnmodifiableList, Field>> when) { return $arg2(when); } + @Nullable default Field $else() { return $arg3(); } + @NotNull default CaseSimple $else(Field else_) { return $arg3(else_); } + } + + public /*sealed*/ interface CaseSearched + extends + Field, + UOperator2>>, Field, CaseSearched> + { + @NotNull default UnmodifiableList>> $when() { return $arg1(); } + @NotNull default CaseSearched $when(UnmodifiableList>> when) { return $arg1(when); } + @Nullable default Field $else() { return $arg2(); } + @NotNull default CaseSearched $else(Field else_) { return $arg2(else_); } + } + public /*sealed*/ interface Concat extends Field, @@ -7727,4 +7763,9 @@ public final class QOM { else return new QueryPartList<>(unmodifiableCollection(collection)); } + + @Internal + public static final UTuple2 tuple(Q1 q1, Q2 q2) { + return new UTupleImpl2<>(q1, q2); + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/UTupleImpl2.java b/jOOQ/src/main/java/org/jooq/impl/UTupleImpl2.java new file mode 100644 index 0000000000..5588f25be4 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/UTupleImpl2.java @@ -0,0 +1,117 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: https://www.jooq.org/legal/licensing + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import org.jooq.Context; +import org.jooq.QueryPart; +// ... +// ... +import org.jooq.impl.QOM.UTuple2; + +/** + * A generic tuple of degree 2, which acts as a {@link QueryPart} for traversal, + * replacement, etc. + * + * @author Lukas Eder + */ +final class UTupleImpl2 +extends + AbstractQueryPart +implements + UTuple2 +{ + + private final Q1 part1; + private final Q2 part2; + + UTupleImpl2(Q1 part1, Q2 part2) { + this.part1 = part1; + this.part2 = part2; + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + public final void accept(Context ctx) { + + // This is unlikely to be called directly: + ctx.sql('(').visit(part1).sql(", ").visit(part2).sql(')'); + } + + // ------------------------------------------------------------------------- + // XXX: Query Object Model + // ------------------------------------------------------------------------- + + @Override + public final Q1 $part1() { + return part1; + } + + @Override + public final Q2 $part2() { + return part2; + } + + @Override + public final UTuple2 $part1(Q1 newPart1) { + return new UTupleImpl2<>(newPart1, part2); + } + + @Override + public final UTuple2 $part2(Q2 newPart2) { + return new UTupleImpl2<>(part1, newPart2); + } + + @Override + public final R $traverse(Traverser traverser) { + return QOM.traverse(traverser, this, $part1(), $part2()); + } + + @Override + public final QueryPart $replace(Replacer replacer) { + return QOM.replace( + this, + $part1(), + $part2(), + (p1, p2) -> new UTupleImpl2<>(p1, p2), + replacer + ); + } +}