[#7459] SEEK with UNION doesn't work correctly

This commit is contained in:
lukaseder 2018-05-03 14:02:53 +02:00
parent b75e9e9384
commit 91d9331778

View File

@ -1038,6 +1038,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// synthetic parentheses
boolean wrapQueryExpressionInDerivedTable;
boolean wrapQueryExpressionBodyInDerivedTable = false;
boolean applySeekOnDerivedTable = applySeekOnDerivedTable(context);
wrapQueryExpressionInDerivedTable = false
@ -1072,28 +1073,34 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// [#7459] In the presence of UNIONs and other set operations, the SEEK
// predicate must be applied on a derived table, not on the individual subqueries
wrapQueryExpressionBodyInDerivedTable |= applySeekOnDerivedTable;
if (wrapQueryExpressionBodyInDerivedTable) {
context.visit(K_SELECT).sql(' ');
context.formatIndentStart()
.formatNewLine()
.sql("t.*");
if (alternativeFields != null && originalFields.length < alternativeFields.length)
context.sql(", ")
.formatSeparator()
.declareFields(true)
.visit(alternativeFields[alternativeFields.length - 1])
.declareFields(false);
context.formatIndentEnd()
.formatSeparator()
.visit(K_FROM).sql(" (")
.formatIndentStart()
.formatNewLine();
}
// [#1658] jOOQ applies left-associativity to set operators. In order to enforce that across
// all databases, we need to wrap relevant subqueries in parentheses.
@ -1424,12 +1431,22 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
context.data().remove(DATA_NESTED_SET_OPERATIONS);
}
if (wrapQueryExpressionBodyInDerivedTable) {
context.formatIndentEnd()
.formatNewLine()
.sql(") t");
if (applySeekOnDerivedTable) {
boolean qualify = context.qualify();
context.formatSeparator()
.visit(K_WHERE)
.sql(' ')
.qualify(false)
.visit(getSeekCondition())
.qualify(qualify);
}
}
// ORDER BY clause for UNION
// -------------------------
@ -1527,6 +1544,10 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
ctx.visit(actualLimit);
}
private final boolean applySeekOnDerivedTable(Context<?> ctx) {
return !getSeek().isEmpty() && !getOrderBy().isEmpty() && !unionOp.isEmpty();
}
private final boolean wrapQueryExpressionBodyInDerivedTable(Context<?> ctx) {
return true
@ -1924,7 +1945,13 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
}
final ConditionProviderImpl getWhere() {
if (getOrderBy().isEmpty() || getSeek().isEmpty())
// Do not apply SEEK predicates in the WHERE clause, if:
// - There is no ORDER BY clause (SEEK is non-deterministic)
// - There is no SEEK clause (obvious case)
// - There are unions (union is nested in derived table
// and SEEK predicate is applied outside). See [#7459]
if (getOrderBy().isEmpty() || getSeek().isEmpty() || unionOp.size() > 0)
return condition;
ConditionProviderImpl result = new ConditionProviderImpl();