[jOOQ/jOOQ#13640] Implement QOM.CaseSearched

This commit is contained in:
Lukas Eder 2022-10-27 15:24:18 +02:00
parent bfb1f8533c
commit cdc57e4e12
5 changed files with 242 additions and 23 deletions

View File

@ -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<T> extends AbstractField<T> implements CaseConditionStep<T>, UNotYetImplemented {
final class CaseConditionStepImpl<T>
extends
AbstractField<T>
implements
CaseConditionStep<T>,
QOM.CaseSearched<T>
{
private final List<Condition> conditions;
private final List<Field<T>> results;
private Field<T> else_;
private final List<UTuple2<Condition, Field<T>>> when;
private Field<T> else_;
CaseConditionStepImpl(DataType<T> type) {
super(NQ_CASE, type);
this.when = new QueryPartList<>();
}
CaseConditionStepImpl(Condition condition, Field<T> 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<T> when(Condition condition, T result) {
return when(condition, Tools.field(result));
@ -90,9 +107,7 @@ final class CaseConditionStepImpl<T> extends AbstractField<T> implements CaseCon
@Override
public final CaseConditionStep<T> when(Condition condition, Field<T> result) {
conditions.add(condition);
results.add(result);
when.add(QOM.tuple(condition, result));
return this;
}
@ -200,11 +215,6 @@ final class CaseConditionStepImpl<T> extends AbstractField<T> implements CaseCon
@ -215,9 +225,8 @@ final class CaseConditionStepImpl<T> extends AbstractField<T> 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<Condition, Field<T>> e : when) {
Condition c = e.$part1();
@ -236,7 +245,7 @@ final class CaseConditionStepImpl<T> extends AbstractField<T> 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<T> extends AbstractField<T> implements CaseCon
.formatSeparator()
.visit(K_END);
}
// -------------------------------------------------------------------------
// XXX: Query Object Model
// -------------------------------------------------------------------------
@Override
public final Function2<? super UnmodifiableList<? extends UTuple2<Condition, Field<T>>>, ? super Field<T>, ? extends CaseSearched<T>> $constructor() {
return (w, e) -> {
CaseConditionStepImpl<T> r = new CaseConditionStepImpl<>(getDataType());
w.forEach(t -> r.when(t.$part1(), t.$part2()));
r.else_(e);
return r;
};
}
@Override
public final UnmodifiableList<? extends UTuple2<Condition, Field<T>>> $arg1() {
return QOM.unmodifiable(when);
}
@Override
public final CaseSearched<T> $arg1(UnmodifiableList<? extends UTuple2<Condition, Field<T>>> w) {
return $constructor().apply(w, $else());
}
@Override
public final Field<T> $arg2() {
return else_;
}
@Override
public final CaseSearched<T> $arg2(Field<T> e) {
return $constructor().apply($when(), e);
}
@Override
public final <R> R $traverse(Traverser<?, R> 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
);
}
}

View File

@ -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;

View File

@ -62,6 +62,9 @@ import org.jooq.Field;
// ...
import org.jooq.impl.QOM.UNotYetImplemented;
/**
* @author Lukas Eder
*/
final class CaseWhenStepImpl<V, T> extends AbstractField<T> implements CaseWhenStep<V, T>, UNotYetImplemented {
private final Field<V> value;

View File

@ -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<Q1 extends org.jooq.QueryPart, Q2 extends org.jooq.QueryPart>
extends
org.jooq.QueryPart
permits
UTupleImpl2
{
@NotNull Q1 $part1();
@NotNull UTuple2<Q1, Q2> $part1(Q1 newPart1);
@NotNull Q2 $part2();
@NotNull UTuple2<Q1, Q2> $part2(Q2 newPart2);
}
/**
* An unmodifiable {@link Collection} of {@link QueryPart} elements.
*/
@ -965,6 +977,30 @@ public final class QOM {
Coalesce*/
{}
public /*sealed*/ interface CaseSimple<V, T>
extends
Field<T>,
UOperator3<Field<V>, UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>>, Field<T>, CaseSimple<V, T>>
{
@NotNull default Field<V> $value() { return $arg1(); }
@NotNull default CaseSimple<V, T> $value(Field<V> value) { return $arg1(value); }
@NotNull default UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>> $when() { return $arg2(); }
@NotNull default CaseSimple<V, T> $when(UnmodifiableList<? extends UTuple2<Field<V>, Field<T>>> when) { return $arg2(when); }
@Nullable default Field<T> $else() { return $arg3(); }
@NotNull default CaseSimple<V, T> $else(Field<T> else_) { return $arg3(else_); }
}
public /*sealed*/ interface CaseSearched<T>
extends
Field<T>,
UOperator2<UnmodifiableList<? extends UTuple2<Condition, Field<T>>>, Field<T>, CaseSearched<T>>
{
@NotNull default UnmodifiableList<? extends UTuple2<Condition, Field<T>>> $when() { return $arg1(); }
@NotNull default CaseSearched<T> $when(UnmodifiableList<? extends UTuple2<Condition, Field<T>>> when) { return $arg1(when); }
@Nullable default Field<T> $else() { return $arg2(); }
@NotNull default CaseSearched<T> $else(Field<T> else_) { return $arg2(else_); }
}
public /*sealed*/ interface Concat
extends
Field<String>,
@ -7727,4 +7763,9 @@ public final class QOM {
else
return new QueryPartList<>(unmodifiableCollection(collection));
}
@Internal
public static final <Q1 extends QueryPart, Q2 extends QueryPart> UTuple2<Q1, Q2> tuple(Q1 q1, Q2 q2) {
return new UTupleImpl2<>(q1, q2);
}
}

View File

@ -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<Q1 extends QueryPart, Q2 extends QueryPart>
extends
AbstractQueryPart
implements
UTuple2<Q1, Q2>
{
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<Q1, Q2> $part1(Q1 newPart1) {
return new UTupleImpl2<>(newPart1, part2);
}
@Override
public final UTuple2<Q1, Q2> $part2(Q2 newPart2) {
return new UTupleImpl2<>(part1, newPart2);
}
@Override
public final <R> R $traverse(Traverser<?, R> 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
);
}
}