package org.jooq.impl;
import static org.jooq.Clause.CONDITION;
import static org.jooq.Clause.CONDITION_COMPARISON;
import static org.jooq.Comparator.EQUALS;
import static org.jooq.Comparator.GREATER;
import static org.jooq.Comparator.GREATER_OR_EQUAL;
import static org.jooq.Comparator.LESS;
import static org.jooq.Comparator.LESS_OR_EQUAL;
import static org.jooq.Comparator.NOT_EQUALS;
import static org.jooq.SQLDialect.CUBRID;
import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.impl.Keywords.K_NOT;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jooq.Clause;
import org.jooq.Comparator;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.Field;
import org.jooq.QueryPartInternal;
import org.jooq.Row;
import org.jooq.SQLDialect;
@SuppressWarnings({ "unchecked", "rawtypes" })
final class RowCondition extends AbstractCondition {
private static final long serialVersionUID = -1806139685201770706L;
private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON };
private static final Set<SQLDialect> EMULATE_EQ_AND_NE = SQLDialect.supportedBy(DERBY, FIREBIRD);
private static final Set<SQLDialect> EMULATE_RANGES = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD);
private final Row left;
private final Row right;
private final Comparator comparator;
private final boolean forceEmulation;
RowCondition(Row left, Row right, Comparator comparator) {
this(left, right, comparator, false);
}
RowCondition(Row left, Row right, Comparator comparator, boolean forceEmulation) {
this.left = left;
this.right = right;
this.comparator = comparator;
this.forceEmulation = forceEmulation;
}
@Override
public final void accept(Context<?> ctx) {
ctx.visit(delegate(ctx.configuration()));
}
@Override
public final Clause[] clauses(Context<?> ctx) {
return null;
}
private final QueryPartInternal delegate(Configuration configuration) {
if ((comparator == EQUALS || comparator == NOT_EQUALS) &&
(forceEmulation || EMULATE_EQ_AND_NE.contains(configuration.dialect()))) {
Field<?>[] leftFields = left.fields();
Field<?>[] rightFields = right.fields();
List<Condition> conditions = new ArrayList<>(leftFields.length);
for (int i = 0; i < leftFields.length; i++)
conditions.add(leftFields[i].equal((Field) rightFields[i]));
Condition result = DSL.and(conditions);
if (comparator == NOT_EQUALS)
result = result.not();
return (QueryPartInternal) result;
}
else if ((comparator == GREATER || comparator == GREATER_OR_EQUAL || comparator == LESS || comparator == LESS_OR_EQUAL) &&
(forceEmulation || EMULATE_RANGES.contains(configuration.dialect()))) {
Comparator order
= (comparator == GREATER) ? GREATER
: (comparator == GREATER_OR_EQUAL) ? GREATER
: (comparator == LESS) ? LESS
: (comparator == LESS_OR_EQUAL) ? LESS
: null;
Comparator factoredOrder
= (comparator == GREATER) ? GREATER_OR_EQUAL
: (comparator == GREATER_OR_EQUAL) ? GREATER_OR_EQUAL
: (comparator == LESS) ? LESS_OR_EQUAL
: (comparator == LESS_OR_EQUAL) ? LESS_OR_EQUAL
: null;
boolean equal
= (comparator == GREATER_OR_EQUAL)
||(comparator == LESS_OR_EQUAL);
Field<?>[] leftFields = left.fields();
Field<?>[] rightFields = right.fields();
List<Condition> outer = new ArrayList<>(1 + leftFields.length);
for (int i = 0; i < leftFields.length; i++) {
List<Condition> inner = new ArrayList<>(1 + i);
for (int j = 0; j < i; j++)
inner.add(leftFields[j].equal((Field) rightFields[j]));
inner.add(leftFields[i].compare(
equal && i == leftFields.length - 1 ? comparator : order,
(Field) rightFields[i])
);
outer.add(DSL.and(inner));
}
Condition result = DSL.or(outer);
if (leftFields.length > 1)
result = leftFields[0].compare(factoredOrder, (Field) rightFields[0]).and(result);
return (QueryPartInternal) result;
}
else {
return new Native();
}
}
private class Native extends AbstractCondition {
private static final long serialVersionUID = -2977241780111574353L;
@Override
public final void accept(Context<?> ctx) {
{
boolean extraParentheses = false
;
ctx.visit(left)
.sql(' ')
.sql(comparator.toSQL())
.sql(' ')
.sql(extraParentheses ? "(" : "")
.visit(right)
.sql(extraParentheses ? ")" : "");
}
}
@Override
public final Clause[] clauses(Context<?> ctx) {
return CLAUSES;
}
}
}