[#2665] Implement SPI for RenderContext and BindContext listening to
allow for custom SQL transformation * Added tests for IN predicate * Added tests for EXISTS predicate
This commit is contained in:
parent
1a5d8e13c3
commit
a79b7bfeb0
@ -69,7 +69,7 @@ public enum Clause {
|
||||
/**
|
||||
* A complete table reference.
|
||||
* <p>
|
||||
* This "clause" surrounds a complete table reference as it can be encountered
|
||||
* This clause surrounds a complete table reference as it can be encountered
|
||||
* in
|
||||
* <ul>
|
||||
* <li> {@link #SELECT_FROM}</li>
|
||||
@ -119,31 +119,128 @@ public enum Clause {
|
||||
// Clauses used in a any type of statement to model condition references
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A condition expression.
|
||||
*/
|
||||
CONDITION,
|
||||
|
||||
/**
|
||||
* A <code>NULL</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds a {@link #FIELD}.
|
||||
*/
|
||||
CONDITION_IS_NULL,
|
||||
|
||||
/**
|
||||
* A <code>NOT NULL</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds a {@link #FIELD}.
|
||||
*/
|
||||
CONDITION_IS_NOT_NULL,
|
||||
|
||||
// TODO: Should operators be distinguished?
|
||||
// - LIKE predicate
|
||||
// - Subselect predicates
|
||||
// - RVE predicates
|
||||
// - Quantified predicates
|
||||
CONDITION_COMPARISON,
|
||||
|
||||
/**
|
||||
* A <code>BEWEEN</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds three {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_BETWEEN,
|
||||
|
||||
/**
|
||||
* A <code>BEWEEN SYMMETRIC</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds three {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_BETWEEN_SYMMETRIC,
|
||||
|
||||
/**
|
||||
* A <code>NOT BEWEEN</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds three {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_NOT_BETWEEN,
|
||||
|
||||
/**
|
||||
* A <code>NOT BEWEEN SYMMETRIC</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds three {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_NOT_BETWEEN_SYMMETRIC,
|
||||
|
||||
/**
|
||||
* A <code>DISTINCT</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds two {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_IS_DISTINCT,
|
||||
|
||||
/**
|
||||
* A <code>NOT DISTINCT</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds two {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_IS_NOT_DISTINCT,
|
||||
|
||||
/**
|
||||
* An <code>OVERLAPS</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds two {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_OVERLAPS,
|
||||
|
||||
/**
|
||||
* A combined condition using <code>AND</code>.
|
||||
* <p>
|
||||
* This clause surrounds several {@link #CONDITION} clauses.
|
||||
*/
|
||||
CONDITION_AND,
|
||||
|
||||
/**
|
||||
* A combined condition using <code>OR</code>.
|
||||
* <p>
|
||||
* This clause surrounds several {@link #CONDITION} clauses.
|
||||
*/
|
||||
CONDITION_OR,
|
||||
|
||||
/**
|
||||
* A <code>NOT</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds a {@link #CONDITION} clause.
|
||||
*/
|
||||
CONDITION_NOT,
|
||||
|
||||
/**
|
||||
* An <code>IN</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds two or more {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_IN,
|
||||
|
||||
/**
|
||||
* A <code>NOT IN</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds two or more {@link #FIELD} clauses.
|
||||
*/
|
||||
CONDITION_NOT_IN,
|
||||
|
||||
/**
|
||||
* An <code>EXISTS</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds a {@link #SELECT} clause.
|
||||
*/
|
||||
CONDITION_EXISTS,
|
||||
|
||||
/**
|
||||
* A <code>NOT EXISTS</code> condition.
|
||||
* <p>
|
||||
* This clause surrounds a {@link #SELECT} clause.
|
||||
*/
|
||||
CONDITION_NOT_EXISTS,
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -153,7 +250,7 @@ public enum Clause {
|
||||
/**
|
||||
* A complete <code>SELECT</code> statement or a subselect.
|
||||
* <p>
|
||||
* This "clause" surrounds a complete <code>SELECT</code> statement, a
|
||||
* This clause surrounds a complete <code>SELECT</code> statement, a
|
||||
* subselect, or a set operation, such as
|
||||
* <ul>
|
||||
* <li> {@link #SELECT_UNION}</li>
|
||||
@ -301,7 +398,7 @@ public enum Clause {
|
||||
* This clause surrounds
|
||||
* <ul>
|
||||
* <li>the <code>RETURNING</code> keyword</li>
|
||||
* <li>several {@link #FIELD} "clauses"</li>
|
||||
* <li>several {@link #FIELD} clauses</li>
|
||||
* </ul>
|
||||
*/
|
||||
UPDATE_RETURNING,
|
||||
|
||||
@ -45,7 +45,6 @@ import org.jooq.Configuration;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Param;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.QueryPartInternal;
|
||||
import org.jooq.RenderContext;
|
||||
import org.jooq.conf.ParamType;
|
||||
|
||||
@ -100,10 +99,8 @@ abstract class AbstractDelegatingQuery<Q extends Query> extends AbstractQueryPar
|
||||
|
||||
@Override
|
||||
public final Clause[] clauses(Context<?> ctx) {
|
||||
if (delegate instanceof QueryPartInternal) {
|
||||
return ((QueryPartInternal) delegate).clauses(null);
|
||||
}
|
||||
|
||||
// Delegate queries don't emit clauses themselves.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ class SQLQuery extends AbstractQuery {
|
||||
@Override
|
||||
public final Clause[] clauses(Context<?> ctx) {
|
||||
if (delegate instanceof QueryPartInternal) {
|
||||
return ((QueryPartInternal) delegate).clauses(null);
|
||||
return ((QueryPartInternal) delegate).clauses(ctx);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@ -84,7 +84,7 @@ class SQLResultQuery extends AbstractResultQuery<Record> {
|
||||
@Override
|
||||
public final Clause[] clauses(Context<?> ctx) {
|
||||
if (delegate instanceof QueryPartInternal) {
|
||||
return ((QueryPartInternal) delegate).clauses(null);
|
||||
return ((QueryPartInternal) delegate).clauses(ctx);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@ -43,15 +43,27 @@ import static org.jooq.Clause.CONDITION_AND;
|
||||
import static org.jooq.Clause.CONDITION_BETWEEN;
|
||||
import static org.jooq.Clause.CONDITION_BETWEEN_SYMMETRIC;
|
||||
import static org.jooq.Clause.CONDITION_COMPARISON;
|
||||
import static org.jooq.Clause.CONDITION_EXISTS;
|
||||
import static org.jooq.Clause.CONDITION_IN;
|
||||
import static org.jooq.Clause.CONDITION_IS_NOT_NULL;
|
||||
import static org.jooq.Clause.CONDITION_IS_NULL;
|
||||
import static org.jooq.Clause.CONDITION_NOT_BETWEEN;
|
||||
import static org.jooq.Clause.CONDITION_NOT_BETWEEN_SYMMETRIC;
|
||||
import static org.jooq.Clause.CONDITION_NOT_EXISTS;
|
||||
import static org.jooq.Clause.CONDITION_NOT_IN;
|
||||
import static org.jooq.Clause.CONDITION_OR;
|
||||
import static org.jooq.Clause.FIELD;
|
||||
import static org.jooq.Clause.FIELD_REFERENCE;
|
||||
import static org.jooq.Clause.FIELD_ROW;
|
||||
import static org.jooq.Clause.FIELD_VALUE;
|
||||
import static org.jooq.Clause.SELECT;
|
||||
import static org.jooq.Clause.SELECT_CONNECT_BY;
|
||||
import static org.jooq.Clause.SELECT_FROM;
|
||||
import static org.jooq.Clause.SELECT_GROUP_BY;
|
||||
import static org.jooq.Clause.SELECT_HAVING;
|
||||
import static org.jooq.Clause.SELECT_ORDER_BY;
|
||||
import static org.jooq.Clause.SELECT_SELECT;
|
||||
import static org.jooq.Clause.SELECT_START_WITH;
|
||||
import static org.jooq.Clause.SELECT_WHERE;
|
||||
import static org.jooq.Clause.TABLE;
|
||||
import static org.jooq.Clause.TABLE_REFERENCE;
|
||||
@ -62,8 +74,11 @@ import static org.jooq.Clause.UPDATE_SET_ASSIGNMENT;
|
||||
import static org.jooq.Clause.UPDATE_UPDATE;
|
||||
import static org.jooq.Clause.UPDATE_WHERE;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.impl.DSL.exists;
|
||||
import static org.jooq.impl.DSL.notExists;
|
||||
import static org.jooq.impl.DSL.row;
|
||||
import static org.jooq.impl.DSL.select;
|
||||
import static org.jooq.impl.DSL.selectOne;
|
||||
import static org.jooq.impl.DSL.using;
|
||||
import static org.jooq.impl.DSL.val;
|
||||
import static org.jooq.impl.DefaultVisitListenerProvider.providers;
|
||||
@ -377,6 +392,86 @@ public class VisitContextTest extends AbstractTest {
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CONDITION_IN() {
|
||||
ctx.render(FIELD_ID1.in(1, 2));
|
||||
|
||||
assertEvents(asList(
|
||||
asList(CONDITION),
|
||||
asList(CONDITION, CONDITION_IN),
|
||||
asList(CONDITION, CONDITION_IN, FIELD),
|
||||
asList(CONDITION, CONDITION_IN, FIELD, FIELD_REFERENCE),
|
||||
asList(CONDITION, CONDITION_IN, FIELD),
|
||||
asList(CONDITION, CONDITION_IN, FIELD, FIELD_VALUE),
|
||||
asList(CONDITION, CONDITION_IN, FIELD),
|
||||
asList(CONDITION, CONDITION_IN, FIELD, FIELD_VALUE)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CONDITION_NOT_IN() {
|
||||
ctx.render(FIELD_ID1.notIn(1, 2));
|
||||
|
||||
assertEvents(asList(
|
||||
asList(CONDITION),
|
||||
asList(CONDITION, CONDITION_NOT_IN),
|
||||
asList(CONDITION, CONDITION_NOT_IN, FIELD),
|
||||
asList(CONDITION, CONDITION_NOT_IN, FIELD, FIELD_REFERENCE),
|
||||
asList(CONDITION, CONDITION_NOT_IN, FIELD),
|
||||
asList(CONDITION, CONDITION_NOT_IN, FIELD, FIELD_VALUE),
|
||||
asList(CONDITION, CONDITION_NOT_IN, FIELD),
|
||||
asList(CONDITION, CONDITION_NOT_IN, FIELD, FIELD_VALUE)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CONDITION_EXISTS() {
|
||||
|
||||
// Omit "dual" with Postgres
|
||||
ctx.configuration().set(POSTGRES);
|
||||
ctx.render(exists(selectOne()));
|
||||
|
||||
assertEvents(asList(
|
||||
asList(CONDITION),
|
||||
asList(CONDITION, CONDITION_EXISTS),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_SELECT),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_SELECT, FIELD),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_FROM),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_WHERE),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_START_WITH),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_CONNECT_BY),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_GROUP_BY),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_HAVING),
|
||||
asList(CONDITION, CONDITION_EXISTS, SELECT, SELECT_ORDER_BY)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CONDITION_NOT_EXISTS() {
|
||||
|
||||
// Omit "dual" with Postgres
|
||||
ctx.configuration().set(POSTGRES);
|
||||
ctx.render(notExists(selectOne()));
|
||||
|
||||
assertEvents(asList(
|
||||
asList(CONDITION),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_SELECT),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_SELECT, FIELD),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_FROM),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_WHERE),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_START_WITH),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_CONNECT_BY),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_GROUP_BY),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_HAVING),
|
||||
asList(CONDITION, CONDITION_NOT_EXISTS, SELECT, SELECT_ORDER_BY)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CONDITION_BETWEEN() {
|
||||
ctx.render(FIELD_ID1.between(1).and(2));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user