[jOOQ/jOOQ#12425] Move NOT predicate to API generator
Fixed a regression in the lazy type lookup and nullability propagation
This commit is contained in:
parent
04f00df329
commit
6b42ede21e
@ -380,14 +380,14 @@ public interface Condition extends QueryPart {
|
||||
@Support
|
||||
Condition orNotExists(Select<?> select);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Invert this condition
|
||||
* <p>
|
||||
* This is the same as calling {@link DSL#not(Condition)}
|
||||
*
|
||||
* @return This condition, inverted
|
||||
* The <code>NOT</code> operator.
|
||||
*/
|
||||
@NotNull
|
||||
@Support
|
||||
Condition not();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -178,19 +178,24 @@ abstract class AbstractCondition extends AbstractQueryPart implements Condition
|
||||
return or(notExists(select));
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ Condition not() {
|
||||
return new NotCondition(this);
|
||||
}
|
||||
|
||||
static final Condition unwrapNot(Condition c, BiFunction<? super Condition, ? super Boolean, ? extends Condition> function) {
|
||||
boolean not = false;
|
||||
|
||||
while (c instanceof NotCondition) {
|
||||
c = ((NotCondition) c).condition;
|
||||
while (c instanceof Not) {
|
||||
c = ((Not) c).$arg1();
|
||||
not = !not;
|
||||
}
|
||||
|
||||
return function.apply(c, not);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final Condition not() {
|
||||
return DSL.not(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ abstract class AbstractField<T> extends AbstractTypedNamed<T> implements Field<T
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public final Condition isDistinctFrom(Field<T> arg2) {
|
||||
return new IsDistinctFrom(this, arg2);
|
||||
return new IsDistinctFrom(this, nullSafe(arg2, getDataType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -372,7 +372,7 @@ abstract class AbstractField<T> extends AbstractTypedNamed<T> implements Field<T
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public final Condition isNotDistinctFrom(Field<T> arg2) {
|
||||
return new IsNotDistinctFrom(this, arg2);
|
||||
return new IsNotDistinctFrom(this, nullSafe(arg2, getDataType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -462,7 +462,7 @@ abstract class AbstractField<T> extends AbstractTypedNamed<T> implements Field<T
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public final Field<T> mod(Field<? extends Number> arg2) {
|
||||
return new Mod(this, arg2);
|
||||
return new Mod(this, nullSafe(arg2, getDataType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -14555,7 +14555,7 @@ public class DSL {
|
||||
@NotNull
|
||||
@Support
|
||||
public static Condition unique(Select<?> query) {
|
||||
return new UniqueCondition(query, true);
|
||||
return new UniqueCondition(query);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -14566,18 +14566,7 @@ public class DSL {
|
||||
@NotNull
|
||||
@Support
|
||||
public static Condition notUnique(Select<?> query) {
|
||||
return new UniqueCondition(query, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invert a condition.
|
||||
* <p>
|
||||
* This is the same as calling {@link Condition#not()}
|
||||
*/
|
||||
@NotNull
|
||||
@Support
|
||||
public static Condition not(Condition condition) {
|
||||
return condition.not();
|
||||
return not(unique(query));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -15689,6 +15678,15 @@ public class DSL {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The <code>NOT</code> function.
|
||||
*/
|
||||
@NotNull
|
||||
@Support
|
||||
public static Condition not(Condition arg1) {
|
||||
return new Not(arg1);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Numeric functions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -74,8 +74,8 @@ extends
|
||||
Field<T> arg2
|
||||
) {
|
||||
|
||||
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
|
||||
this.arg2 = nullSafeNotNull(arg2, (DataType) OTHER);
|
||||
this.arg1 = nullableIf(true, Tools.nullSafe(arg1, arg2.getDataType()));
|
||||
this.arg2 = nullableIf(true, Tools.nullSafe(arg2, arg1.getDataType()));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -74,8 +74,8 @@ extends
|
||||
Field<T> arg2
|
||||
) {
|
||||
|
||||
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
|
||||
this.arg2 = nullSafeNotNull(arg2, (DataType) OTHER);
|
||||
this.arg1 = nullableIf(true, Tools.nullSafe(arg1, arg2.getDataType()));
|
||||
this.arg2 = nullableIf(true, Tools.nullSafe(arg2, arg1.getDataType()));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
131
jOOQ/src/main/java/org/jooq/impl/Not.java
Normal file
131
jOOQ/src/main/java/org/jooq/impl/Not.java
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.DSL.*;
|
||||
import static org.jooq.impl.Internal.*;
|
||||
import static org.jooq.impl.Keywords.*;
|
||||
import static org.jooq.impl.Names.*;
|
||||
import static org.jooq.impl.SQLDataType.*;
|
||||
import static org.jooq.impl.Tools.*;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.*;
|
||||
import static org.jooq.impl.Tools.DataExtendedKey.*;
|
||||
import static org.jooq.impl.Tools.DataKey.*;
|
||||
import static org.jooq.SQLDialect.*;
|
||||
|
||||
import org.jooq.*;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.conf.*;
|
||||
import org.jooq.impl.*;
|
||||
import org.jooq.tools.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>NOT</code> statement.
|
||||
*/
|
||||
@SuppressWarnings({ "unused" })
|
||||
final class Not
|
||||
extends
|
||||
AbstractCondition
|
||||
{
|
||||
|
||||
private final Condition arg1;
|
||||
|
||||
Not(
|
||||
Condition arg1
|
||||
) {
|
||||
|
||||
this.arg1 = arg1;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: QueryPart API
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
private static final Clause[] CLAUSES = { Clause.CONDITION, Clause.CONDITION_NOT };
|
||||
|
||||
@Override
|
||||
boolean isNullable() {
|
||||
return !(arg1 instanceof AbstractCondition) || ((AbstractCondition) arg1).isNullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
switch (ctx.family()) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
ctx.visit(K_NOT).sql(" (").visit(arg1).sql(')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Clause[] clauses(Context<?> ctx) {
|
||||
return CLAUSES;
|
||||
}
|
||||
|
||||
final Condition $arg1() {
|
||||
return arg1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// The Object API
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that instanceof Not) {
|
||||
return
|
||||
StringUtils.equals(arg1, ((Not) that).arg1)
|
||||
;
|
||||
}
|
||||
else
|
||||
return super.equals(that);
|
||||
}
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.Clause.CONDITION;
|
||||
import static org.jooq.Clause.CONDITION_NOT;
|
||||
import static org.jooq.impl.Keywords.K_NOT;
|
||||
|
||||
import org.jooq.Clause;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
|
||||
final class NotCondition extends AbstractCondition {
|
||||
|
||||
private static final Clause[] CLAUSES = { CONDITION, CONDITION_NOT };
|
||||
|
||||
final Condition condition;
|
||||
|
||||
NotCondition(Condition condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isNullable() {
|
||||
return !(condition instanceof AbstractCondition) || ((AbstractCondition) condition).isNullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
switch (ctx.family()) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
ctx.visit(K_NOT).sql(" (").visit(condition).sql(')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Clause[] clauses(Context<?> ctx) {
|
||||
return CLAUSES;
|
||||
}
|
||||
}
|
||||
@ -60,11 +60,9 @@ import org.jooq.Table;
|
||||
final class UniqueCondition extends AbstractCondition {
|
||||
|
||||
private final Select<?> query;
|
||||
private final boolean unique;
|
||||
|
||||
UniqueCondition(Select<?> query, boolean unique) {
|
||||
UniqueCondition(Select<?> query) {
|
||||
this.query = query;
|
||||
this.unique = unique;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,9 +74,6 @@ final class UniqueCondition extends AbstractCondition {
|
||||
public final void accept(Context<?> ctx) {
|
||||
switch (ctx.family()) {
|
||||
case H2:
|
||||
if (!unique)
|
||||
ctx.visit(K_NOT).sql(' ');
|
||||
|
||||
ctx.visit(K_UNIQUE).sql(' ');
|
||||
visitSubquery(ctx, query);
|
||||
break;
|
||||
@ -92,15 +87,9 @@ final class UniqueCondition extends AbstractCondition {
|
||||
.groupBy(queryFields)
|
||||
.having(count().gt(one()));
|
||||
|
||||
ctx.visit(unique ? notExists(subquery) : exists(subquery));
|
||||
// TODO: [#7362] [#10304] Find a better way to prevent double negation and unnecessary parentheses
|
||||
ctx.visit(notExists(subquery));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition not() {
|
||||
|
||||
// TODO: [#7362] [#10304] Find a better way to prevent double negation and unnecessary parentheses
|
||||
return unique ? new UniqueCondition(query, false) : super.not();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user