[jOOQ/jOOQ#16310] Wrong SQL generated when nesting predicates on subqueries projecting embeddables within MULTISET
This commit is contained in:
parent
118cce19f2
commit
bd88ac10eb
@ -54,6 +54,8 @@ import static org.jooq.impl.Tools.EMPTY_CLAUSE;
|
||||
import static org.jooq.impl.Tools.EMPTY_QUERYPART;
|
||||
import static org.jooq.impl.Tools.lazy;
|
||||
import static org.jooq.impl.Tools.traverseJoins;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONDITION;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONTENT;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_NESTED_SET_OPERATIONS;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_OMIT_CLAUSE_EVENT_EMISSION;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_RENDER_IMPLICIT_JOIN;
|
||||
@ -106,6 +108,7 @@ import org.jooq.conf.SettingsTools;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.QOM.UEmpty;
|
||||
import org.jooq.impl.Tools.BooleanDataKey;
|
||||
import org.jooq.impl.Tools.DataKey;
|
||||
|
||||
|
||||
@ -263,7 +266,24 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
|
||||
|
||||
@Override
|
||||
public final C visit(Condition part) {
|
||||
return visit((QueryPart) part);
|
||||
|
||||
// [#16310] The MULTISET content flag needs to be reset for any non
|
||||
// multiset projection context. For example, in any Condition.
|
||||
// While Conditions can be projected, they're projecting a BOOLEAN,
|
||||
// not nested records or collections
|
||||
if (TRUE.equals(data(DATA_MULTISET_CONTENT))) {
|
||||
try {
|
||||
data(DATA_MULTISET_CONTENT, false);
|
||||
visit((QueryPart) part);
|
||||
}
|
||||
finally {
|
||||
data(DATA_MULTISET_CONTENT, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
visit((QueryPart) part);
|
||||
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -42,10 +42,11 @@ import static org.jooq.impl.DSL.selectCount;
|
||||
import static org.jooq.impl.Keywords.K_IS_NOT_NULL;
|
||||
import static org.jooq.impl.SubqueryCharacteristics.PREDICAND;
|
||||
import static org.jooq.impl.Tools.allNotNull;
|
||||
import static org.jooq.impl.Tools.exactlyOne;
|
||||
import static org.jooq.impl.Tools.flattenCollection;
|
||||
import static org.jooq.impl.Tools.visitSubquery;
|
||||
|
||||
import org.jooq.Clause;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Function1;
|
||||
import org.jooq.Select;
|
||||
@ -78,7 +79,8 @@ final class SelectIsNotNull extends AbstractCondition implements QOM.SelectIsNot
|
||||
if (SelectIsNull.EMULATE_NULL_QUERY.contains(ctx.dialect())) {
|
||||
|
||||
// [#11011] Avoid the RVE IS NULL emulation for queries of degree 1
|
||||
if (select.getSelect().size() == 1) {
|
||||
// [#16319] Flatten embeddables to find collection size
|
||||
if (exactlyOne(flattenCollection(select.getSelect()))) {
|
||||
acceptStandard(ctx);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -73,6 +73,8 @@ import static org.jooq.impl.DSL.selectCount;
|
||||
import static org.jooq.impl.Keywords.K_IS_NULL;
|
||||
import static org.jooq.impl.SubqueryCharacteristics.PREDICAND;
|
||||
import static org.jooq.impl.Tools.allNull;
|
||||
import static org.jooq.impl.Tools.exactlyOne;
|
||||
import static org.jooq.impl.Tools.flattenCollection;
|
||||
import static org.jooq.impl.Tools.visitSubquery;
|
||||
|
||||
import java.util.Set;
|
||||
@ -113,7 +115,8 @@ final class SelectIsNull extends AbstractCondition implements QOM.SelectIsNull {
|
||||
if (EMULATE_NULL_QUERY.contains(ctx.dialect())) {
|
||||
|
||||
// [#11011] Avoid the RVE IS NULL emulation for queries of degree 1
|
||||
if (select.getSelect().size() == 1) {
|
||||
// [#16319] Flatten embeddables to find collection size
|
||||
if (exactlyOne(flattenCollection(select.getSelect()))) {
|
||||
acceptStandard(ctx);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -6691,6 +6691,20 @@ final class Tools {
|
||||
return !i.hasNext();
|
||||
}
|
||||
|
||||
static final boolean exactlyOne(Iterable<?> it) {
|
||||
if (it == null)
|
||||
return false;
|
||||
else if (it instanceof Collection<?> c)
|
||||
return c.size() == 1;
|
||||
|
||||
Iterator<?> i = it.iterator();
|
||||
return i.hasNext() && true_(i.next()) && !i.hasNext();
|
||||
}
|
||||
|
||||
static final boolean true_(Object o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static final boolean isNotEmpty(Object[] array) {
|
||||
return !isEmpty(array);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user