DATAJDBC-513 - Polishing.
Add Criteria.toString and Update.toString.
This commit is contained in:
@@ -18,9 +18,13 @@ package org.springframework.data.relational.core.query;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.relational.core.sql.IdentifierProcessing;
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -370,6 +374,128 @@ public class Criteria implements CriteriaDefinition {
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
if (isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
unroll(this, builder);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void unroll(CriteriaDefinition criteria, StringBuilder stringBuilder) {
|
||||
|
||||
CriteriaDefinition current = criteria;
|
||||
|
||||
// reverse unroll criteria chain
|
||||
Map<CriteriaDefinition, CriteriaDefinition> forwardChain = new HashMap<>();
|
||||
|
||||
while (current.hasPrevious()) {
|
||||
forwardChain.put(current.getPrevious(), current);
|
||||
current = current.getPrevious();
|
||||
}
|
||||
|
||||
// perform the actual mapping
|
||||
render(current, stringBuilder);
|
||||
while (forwardChain.containsKey(current)) {
|
||||
|
||||
CriteriaDefinition criterion = forwardChain.get(current);
|
||||
|
||||
if (criterion.getCombinator() != Combinator.INITIAL) {
|
||||
stringBuilder.append(' ').append(criterion.getCombinator().name()).append(' ');
|
||||
}
|
||||
|
||||
render(criterion, stringBuilder);
|
||||
|
||||
current = criterion;
|
||||
}
|
||||
}
|
||||
|
||||
private void unrollGroup(List<? extends CriteriaDefinition> criteria, StringBuilder stringBuilder) {
|
||||
|
||||
stringBuilder.append("(");
|
||||
|
||||
boolean first = true;
|
||||
for (CriteriaDefinition criterion : criteria) {
|
||||
|
||||
if (criterion.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
Combinator combinator = criterion.getCombinator() == Combinator.INITIAL ? Combinator.AND
|
||||
: criterion.getCombinator();
|
||||
stringBuilder.append(' ').append(combinator.name()).append(' ');
|
||||
}
|
||||
|
||||
unroll(criterion, stringBuilder);
|
||||
first = false;
|
||||
}
|
||||
|
||||
stringBuilder.append(")");
|
||||
}
|
||||
|
||||
private void render(CriteriaDefinition criteria, StringBuilder stringBuilder) {
|
||||
|
||||
if (criteria.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (criteria.isGroup()) {
|
||||
unrollGroup(criteria.getGroup(), stringBuilder);
|
||||
return;
|
||||
}
|
||||
|
||||
stringBuilder.append(criteria.getColumn().toSql(IdentifierProcessing.NONE)).append(' ')
|
||||
.append(criteria.getComparator().getComparator());
|
||||
|
||||
switch (criteria.getComparator()) {
|
||||
case BETWEEN:
|
||||
case NOT_BETWEEN:
|
||||
Pair<Object, Object> pair = (Pair<Object, Object>) criteria.getValue();
|
||||
stringBuilder.append(' ').append(pair.getFirst()).append(" AND ").append(pair.getSecond());
|
||||
break;
|
||||
|
||||
case IS_NULL:
|
||||
case IS_NOT_NULL:
|
||||
case IS_TRUE:
|
||||
case IS_FALSE:
|
||||
break;
|
||||
|
||||
case IN:
|
||||
case NOT_IN:
|
||||
stringBuilder.append(" (").append(renderValue(criteria.getValue())).append(')');
|
||||
break;
|
||||
|
||||
default:
|
||||
stringBuilder.append(' ').append(renderValue(criteria.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private static String renderValue(@Nullable Object value) {
|
||||
|
||||
if (value instanceof Number) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Collection) {
|
||||
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
((Collection<?>) value).forEach(o -> joiner.add(renderValue(o)));
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
return String.format("'%s'", value);
|
||||
}
|
||||
|
||||
return "null";
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface declaring terminal builder methods to build a {@link Criteria}.
|
||||
*/
|
||||
|
||||
@@ -135,6 +135,18 @@ public interface CriteriaDefinition {
|
||||
}
|
||||
|
||||
enum Comparator {
|
||||
INITIAL, EQ, NEQ, BETWEEN, NOT_BETWEEN, LT, LTE, GT, GTE, IS_NULL, IS_NOT_NULL, LIKE, NOT_LIKE, NOT_IN, IN, IS_TRUE, IS_FALSE
|
||||
INITIAL(""), EQ("="), NEQ("!="), BETWEEN("BETWEEN"), NOT_BETWEEN("NOT BETWEEN"), LT("<"), LTE("<="), GT(">"), GTE(
|
||||
">="), IS_NULL("IS NULL"), IS_NOT_NULL("IS NOT NULL"), LIKE(
|
||||
"LIKE"), NOT_LIKE("NOT LIKE"), NOT_IN("NOT IN"), IN("IN"), IS_TRUE("IS TRUE"), IS_FALSE("IS FALSE");
|
||||
|
||||
private final String comparator;
|
||||
|
||||
Comparator(String comparator) {
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
public String getComparator() {
|
||||
return comparator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ package org.springframework.data.relational.core.query;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.springframework.data.relational.core.sql.IdentifierProcessing;
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -105,4 +107,21 @@ public class Update {
|
||||
|
||||
return new Update(updates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
if (getAssignments().isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
|
||||
getAssignments().forEach((column, o) -> {
|
||||
joiner.add(
|
||||
String.format("%s = %s", column.toSql(IdentifierProcessing.NONE), o instanceof Number ? o : "'" + o + "'"));
|
||||
});
|
||||
|
||||
return "SET " + joiner.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public class CriteriaUnitTests {
|
||||
assertThat(criteria.isGroup()).isTrue();
|
||||
assertThat(criteria.getGroup()).containsExactly(nested1, nested2);
|
||||
assertThat(criteria.getPrevious()).isEqualTo(Criteria.empty());
|
||||
assertThat(criteria).hasToString("(foo IS NOT NULL AND foo IS NULL)");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
@@ -52,7 +53,7 @@ public class CriteriaUnitTests {
|
||||
Criteria nested = where("foo").is("bar").and("baz").isNotNull();
|
||||
Criteria criteria = Criteria.from(nested);
|
||||
|
||||
assertThat(criteria).isSameAs(nested);
|
||||
assertThat(criteria).isSameAs(nested).hasToString("foo = 'bar' AND baz IS NOT NULL");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
@@ -98,11 +99,12 @@ public class CriteriaUnitTests {
|
||||
@Test // DATAJDBC-513
|
||||
public void andGroupedCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").is("bar").and(where("foo").is("baz"));
|
||||
Criteria grouped = where("foo").is("bar").and(where("foo").is("baz").or("bar").isNotNull());
|
||||
Criteria criteria = grouped;
|
||||
|
||||
assertThat(criteria.isGroup()).isTrue();
|
||||
assertThat(criteria.getGroup()).hasSize(1);
|
||||
assertThat(criteria.getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.unquoted("bar"));
|
||||
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.AND);
|
||||
|
||||
criteria = criteria.getPrevious();
|
||||
@@ -111,6 +113,8 @@ public class CriteriaUnitTests {
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
|
||||
assertThat(grouped).hasToString("foo = 'bar' AND (foo = 'baz' OR bar IS NOT NULL)");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
@@ -184,6 +188,7 @@ public class CriteriaUnitTests {
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IN);
|
||||
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
|
||||
assertThat(criteria).hasToString("foo IN ('bar', 'baz')");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.query;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Update}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class UpdateUnitTests {
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldRenderUpdateToString() {
|
||||
|
||||
assertThat(Update.update("foo", "baz").set("bar", 42)).hasToString("SET foo = 'baz', bar = 42");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user