Skip to content

Commit

Permalink
[#7460] SEEK without WHERE produces excess 1 = 1 predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaseder committed May 3, 2018
1 parent fe213c3 commit 89adb16
Showing 1 changed file with 59 additions and 47 deletions.
106 changes: 59 additions & 47 deletions jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java
Expand Up @@ -1040,7 +1040,12 @@ private final void toSQLReference0(Context<?> context, Field<?>[] originalFields
boolean wrapQueryExpressionBodyInDerivedTable = false;


wrapQueryExpressionInDerivedTable = false
wrapQueryExpressionInDerivedTable =

// [#6380] SEEK BEFORE with LIMIT requires two applications of ORDER BY:
// - A reversed ordering in a derived table
// - The desired ordering in the outer table
seekBefore && getLimit().isApplicable()



Expand Down Expand Up @@ -1256,27 +1261,28 @@ else if (context.subquery() && dialect == H2 && context.data(DATA_ROW_VALUE_EXPR
// WHERE clause
// ------------
context.start(SELECT_WHERE);
ConditionProviderImpl where = getWhere();

if (TRUE.equals(context.data().get(DataKey.DATA_SELECT_NO_DATA)))
context.formatSeparator()
.visit(K_WHERE)
.sql(' ')
.visit(falseCondition());
else if (!getWhere().hasWhere() && semiAntiJoinPredicates == null)
else if (!where.hasWhere() && semiAntiJoinPredicates == null)
;
else {
ConditionProviderImpl where = new ConditionProviderImpl();
ConditionProviderImpl actual = new ConditionProviderImpl();

if (semiAntiJoinPredicates != null)
where.addConditions(semiAntiJoinPredicates);
actual.addConditions(semiAntiJoinPredicates);

if (getWhere().hasWhere())
where.addConditions(getWhere());
if (where.hasWhere())
actual.addConditions(where);

context.formatSeparator()
.visit(K_WHERE)
.sql(' ')
.visit(where);
.visit(actual);
}

context.end(SELECT_WHERE);
Expand Down Expand Up @@ -1922,57 +1928,63 @@ final void setGrouping() {
grouping = true;
}

@SuppressWarnings({ "rawtypes", "unchecked" })
final ConditionProviderImpl getWhere() {
if (getOrderBy().isEmpty() || getSeek().isEmpty()) {
if (getOrderBy().isEmpty() || getSeek().isEmpty())
return condition;
}
else {
SortFieldList o = getOrderBy();
Condition c = null;

// [#2786] TODO: Check if NULLS FIRST | NULLS LAST clauses are
// contained in the SortFieldList, in case of which, the below
// predicates will become a lot more complicated.
if (o.nulls()) {}

// If we have uniform sorting, more efficient row value expression
// predicates can be applied, which can be heavily optimised on some
// databases.
if (o.size() > 1 && o.uniform()) {
if (o.get(0).getOrder() != DESC ^ seekBefore)
c = row(o.fields()).gt(row(getSeek()));
else
c = row(o.fields()).lt(row(getSeek()));
}

// With alternating sorting, the SEEK clause has to be explicitly
// phrased for each ORDER BY field.
else {
ConditionProviderImpl or = new ConditionProviderImpl();
ConditionProviderImpl result = new ConditionProviderImpl();

for (int i = 0; i < o.size(); i++) {
ConditionProviderImpl and = new ConditionProviderImpl();
if (condition.hasWhere())
result.addConditions(condition.getWhere());

for (int j = 0; j < i; j++)
and.addConditions(((Field) ((SortFieldImpl<?>) o.get(j)).getField()).eq(getSeek().get(j)));
result.addConditions(getSeekCondition());
return result;
}

SortFieldImpl<?> s = (SortFieldImpl<?>) o.get(i);
if (s.getOrder() != DESC ^ seekBefore)
and.addConditions(((Field) s.getField()).gt(getSeek().get(i)));
else
and.addConditions(((Field) s.getField()).lt(getSeek().get(i)));
@SuppressWarnings({ "rawtypes", "unchecked" })
final Condition getSeekCondition() {
SortFieldList o = getOrderBy();
Condition c = null;

// [#2786] TODO: Check if NULLS FIRST | NULLS LAST clauses are
// contained in the SortFieldList, in case of which, the below
// predicates will become a lot more complicated.
if (o.nulls()) {}

// If we have uniform sorting, more efficient row value expression
// predicates can be applied, which can be heavily optimised on some
// databases.
if (o.size() > 1 && o.uniform()) {
if (o.get(0).getOrder() != DESC ^ seekBefore)
c = row(o.fields()).gt(row(getSeek()));
else
c = row(o.fields()).lt(row(getSeek()));
}

or.addConditions(OR, and);
}
// With alternating sorting, the SEEK clause has to be explicitly
// phrased for each ORDER BY field.
else {
ConditionProviderImpl or = new ConditionProviderImpl();

for (int i = 0; i < o.size(); i++) {
ConditionProviderImpl and = new ConditionProviderImpl();

c = or;
for (int j = 0; j < i; j++)
and.addConditions(((Field) ((SortFieldImpl<?>) o.get(j)).getField()).eq(getSeek().get(j)));

SortFieldImpl<?> s = (SortFieldImpl<?>) o.get(i);
if (s.getOrder() != DESC ^ seekBefore)
and.addConditions(((Field) s.getField()).gt(getSeek().get(i)));
else
and.addConditions(((Field) s.getField()).lt(getSeek().get(i)));

or.addConditions(OR, and);
}

ConditionProviderImpl result = new ConditionProviderImpl();
result.addConditions(condition, c);
return result;
c = or;
}

return c;
}

final ConditionProviderImpl getConnectBy() {
Expand Down

0 comments on commit 89adb16

Please sign in to comment.