DATAJDBC-410 - Properly render NOT IN clauses.
See also: https://github.com/spring-projects/spring-data-r2dbc/issues/177 Original pull request: #167.
This commit is contained in:
committed by
Mark Paluch
parent
045c894d2e
commit
85bf1e6dc7
@@ -193,6 +193,26 @@ public class Column extends AbstractSegment implements Expression, Named {
|
||||
return Conditions.in(this, subselect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code not} {@link In} {@link Condition} given right {@link Expression}s.
|
||||
*
|
||||
* @param expression right side of the comparison.
|
||||
* @return the {@link In} condition.
|
||||
*/
|
||||
public In notIn(Expression... expression) {
|
||||
return Conditions.notIn(this, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code not} {@link In} {@link Condition} given a subselects.
|
||||
*
|
||||
* @param subselect right side of the comparison.
|
||||
* @return the {@link In} condition.
|
||||
*/
|
||||
public In notIn(Select subselect) {
|
||||
return Conditions.notIn(this, subselect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code IS NULL} condition.
|
||||
*
|
||||
|
||||
@@ -192,6 +192,66 @@ public abstract class Conditions {
|
||||
return in(column, new SubselectExpression(subselect));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code NOT IN} {@link Condition clause}.
|
||||
*
|
||||
* @param columnOrExpression left side of the comparison.
|
||||
* @param arg IN argument.
|
||||
* @return the {@link In} condition.
|
||||
*/
|
||||
public static In notIn(Expression columnOrExpression, Expression arg) {
|
||||
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(arg, "Expression argument must not be null");
|
||||
|
||||
return In.create(columnOrExpression, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code NOT IN} {@link Condition} given left and right {@link Expression}s.
|
||||
*
|
||||
* @param columnOrExpression left hand side of the {@link Condition} must not be {@literal null}.
|
||||
* @param expressions right hand side (collection {@link Expression}) must not be {@literal null}.
|
||||
* @return the {@link In} {@link Condition}.
|
||||
*/
|
||||
public static Condition notIn(Expression columnOrExpression, Collection<? extends Expression> expressions) {
|
||||
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(expressions, "Expression argument must not be null");
|
||||
|
||||
return In.createNotIn(columnOrExpression, new ArrayList<>(expressions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code NOT IN} {@link Condition} given left and right {@link Expression}s.
|
||||
*
|
||||
* @param columnOrExpression left hand side of the {@link Condition} must not be {@literal null}.
|
||||
* @param expressions right hand side (collection {@link Expression}) must not be {@literal null}.
|
||||
* @return the {@link In} {@link Condition}.
|
||||
*/
|
||||
public static In notIn(Expression columnOrExpression, Expression... expressions) {
|
||||
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(expressions, "Expression argument must not be null");
|
||||
|
||||
return In.createNotIn(columnOrExpression, Arrays.asList(expressions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code NOT IN} {@link Condition clause} for a {@link Select subselect}.
|
||||
*
|
||||
* @param column the column to compare.
|
||||
* @param subselect the subselect.
|
||||
* @return the {@link In} condition.
|
||||
*/
|
||||
public static In notIn(Column column, Select subselect) {
|
||||
|
||||
Assert.notNull(column, "Column must not be null");
|
||||
Assert.notNull(subselect, "Subselect must not be null");
|
||||
|
||||
return notIn(column, new SubselectExpression(subselect));
|
||||
}
|
||||
|
||||
static class ConstantCondition extends AbstractSegment implements Condition {
|
||||
|
||||
private final String condition;
|
||||
|
||||
@@ -34,13 +34,15 @@ public class In extends AbstractSegment implements Condition {
|
||||
|
||||
private final Expression left;
|
||||
private final Collection<Expression> expressions;
|
||||
private final boolean notIn;
|
||||
|
||||
private In(Expression left, Collection<Expression> expressions) {
|
||||
private In(Expression left, Collection<Expression> expressions, boolean notIn) {
|
||||
|
||||
super(toArray(left, expressions));
|
||||
|
||||
this.left = left;
|
||||
this.expressions = expressions;
|
||||
this.notIn = notIn;
|
||||
}
|
||||
|
||||
private static Segment[] toArray(Expression expression, Collection<Expression> expressions) {
|
||||
@@ -69,7 +71,7 @@ public class In extends AbstractSegment implements Condition {
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(arg, "Expression argument must not be null");
|
||||
|
||||
return new In(columnOrExpression, Collections.singletonList(arg));
|
||||
return new In(columnOrExpression, Collections.singletonList(arg), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +86,7 @@ public class In extends AbstractSegment implements Condition {
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(expressions, "Expression argument must not be null");
|
||||
|
||||
return new In(columnOrExpression, new ArrayList<>(expressions));
|
||||
return new In(columnOrExpression, new ArrayList<>(expressions), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +101,58 @@ public class In extends AbstractSegment implements Condition {
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(expressions, "Expression argument must not be null");
|
||||
|
||||
return new In(columnOrExpression, Arrays.asList(expressions));
|
||||
return new In(columnOrExpression, Arrays.asList(expressions), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link In} {@link Condition} given left and right {@link Expression}s.
|
||||
*
|
||||
* @param columnOrExpression left hand side of the {@link Condition} must not be {@literal null}.
|
||||
* @param arg right hand side (collection {@link Expression}) must not be {@literal null}.
|
||||
* @return the {@link In} {@link Condition}.
|
||||
*/
|
||||
public static In createNotIn(Expression columnOrExpression, Expression arg) {
|
||||
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(arg, "Expression argument must not be null");
|
||||
|
||||
return new In(columnOrExpression, Collections.singletonList(arg), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link In} {@link Condition} given left and right {@link Expression}s.
|
||||
*
|
||||
* @param columnOrExpression left hand side of the {@link Condition} must not be {@literal null}.
|
||||
* @param expressions right hand side (collection {@link Expression}) must not be {@literal null}.
|
||||
* @return the {@link In} {@link Condition}.
|
||||
*/
|
||||
public static In createNotIn(Expression columnOrExpression, Collection<? extends Expression> expressions) {
|
||||
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(expressions, "Expression argument must not be null");
|
||||
|
||||
return new In(columnOrExpression, new ArrayList<>(expressions), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link In} {@link Condition} given left and right {@link Expression}s.
|
||||
*
|
||||
* @param columnOrExpression left hand side of the {@link Condition} must not be {@literal null}.
|
||||
* @param expressions right hand side (collection {@link Expression}) must not be {@literal null}.
|
||||
* @return the {@link In} {@link Condition}.
|
||||
*/
|
||||
public static In createNotIn(Expression columnOrExpression, Expression... expressions) {
|
||||
|
||||
Assert.notNull(columnOrExpression, "Comparison column or expression must not be null");
|
||||
Assert.notNull(expressions, "Expression argument must not be null");
|
||||
|
||||
return new In(columnOrExpression, Arrays.asList(expressions), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Condition not() {
|
||||
|
||||
return new In(left, expressions, !notIn);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -108,6 +161,10 @@ public class In extends AbstractSegment implements Condition {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return left + " IN (" + StringUtils.collectionToDelimitedString(expressions, ", ") + ")";
|
||||
return left + (notIn ? " NOT" : "") + " IN (" + StringUtils.collectionToDelimitedString(expressions, ", ") + ")";
|
||||
}
|
||||
|
||||
public boolean isNotIn() {
|
||||
return notIn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class InVisitor extends TypedSingleConditionRenderSupport<In> {
|
||||
private final RenderTarget target;
|
||||
private final StringBuilder part = new StringBuilder();
|
||||
private boolean needsComma = false;
|
||||
private boolean notIn = false;
|
||||
|
||||
InVisitor(RenderContext context, RenderTarget target) {
|
||||
super(context);
|
||||
@@ -52,6 +53,9 @@ class InVisitor extends TypedSingleConditionRenderSupport<In> {
|
||||
|
||||
if (part.length() == 0) {
|
||||
part.append(renderedPart);
|
||||
if (notIn) {
|
||||
part.append(" NOT");
|
||||
}
|
||||
part.append(" IN (");
|
||||
} else {
|
||||
part.append(renderedPart);
|
||||
@@ -62,6 +66,14 @@ class InVisitor extends TypedSingleConditionRenderSupport<In> {
|
||||
return super.leaveNested(segment);
|
||||
}
|
||||
|
||||
@Override
|
||||
Delegation enterMatched(In segment) {
|
||||
|
||||
notIn = segment.isNotIn();
|
||||
|
||||
return super.enterMatched(segment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#leaveMatched(org.springframework.data.relational.core.sql.Visitable)
|
||||
|
||||
@@ -126,4 +126,16 @@ public class ConditionRendererUnitTests {
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left IS NOT NULL");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-410
|
||||
public void shouldRenderNotIn() {
|
||||
|
||||
String sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.in(right).not()).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left NOT IN (my_table.right)");
|
||||
|
||||
sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.notIn(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left NOT IN (my_table.right)");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user