DATAJDBC-513 - Introduce Query, Criteria and Update Objects for Spring Data Relational.
This commit is contained in:
@@ -0,0 +1,695 @@
|
||||
/*
|
||||
* Copyright 2019-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 java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Central class for creating queries. It follows a fluent API style so that you can easily chain together multiple
|
||||
* criteria. Static import of the {@code Criteria.property(…)} method will improve readability as in
|
||||
* {@code where(property(…).is(…)}.
|
||||
* <p>
|
||||
* The Criteria API supports composition with a {@link #empty() NULL object} and a {@link #from(List) static factory
|
||||
* method}. Example usage:
|
||||
*
|
||||
* <pre class="code">
|
||||
* Criteria.from(Criteria.where("name").is("Foo"), Criteria.from(Criteria.where("age").greaterThan(42)));
|
||||
* </pre>
|
||||
*
|
||||
* rendering:
|
||||
*
|
||||
* <pre class="code">
|
||||
* WHERE name = 'Foo' AND age > 42
|
||||
* </pre>
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Oliver Drotbohm
|
||||
* @author Roman Chigvintsev
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Criteria implements CriteriaDefinition {
|
||||
|
||||
static final Criteria EMPTY = new Criteria(SqlIdentifier.EMPTY, Comparator.INITIAL, null);
|
||||
|
||||
private final @Nullable Criteria previous;
|
||||
private final Combinator combinator;
|
||||
private final List<Criteria> group;
|
||||
|
||||
private final @Nullable SqlIdentifier column;
|
||||
private final @Nullable Comparator comparator;
|
||||
private final @Nullable Object value;
|
||||
private final boolean ignoreCase;
|
||||
|
||||
private Criteria(SqlIdentifier column, Comparator comparator, @Nullable Object value) {
|
||||
this(null, Combinator.INITIAL, Collections.emptyList(), column, comparator, value, false);
|
||||
}
|
||||
|
||||
private Criteria(@Nullable Criteria previous, Combinator combinator, List<Criteria> group,
|
||||
@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value) {
|
||||
this(previous, combinator, group, column, comparator, value, false);
|
||||
}
|
||||
|
||||
private Criteria(@Nullable Criteria previous, Combinator combinator, List<Criteria> group,
|
||||
@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value, boolean ignoreCase) {
|
||||
|
||||
this.previous = previous;
|
||||
this.combinator = previous != null && previous.isEmpty() ? Combinator.INITIAL : combinator;
|
||||
this.group = group;
|
||||
this.column = column;
|
||||
this.comparator = comparator;
|
||||
this.value = value;
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
private Criteria(@Nullable Criteria previous, Combinator combinator, List<Criteria> group) {
|
||||
|
||||
this.previous = previous;
|
||||
this.combinator = previous != null && previous.isEmpty() ? Combinator.INITIAL : combinator;
|
||||
this.group = group;
|
||||
this.column = null;
|
||||
this.comparator = null;
|
||||
this.value = null;
|
||||
this.ignoreCase = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Static factory method to create an empty Criteria.
|
||||
*
|
||||
* @return an empty {@link Criteria}.
|
||||
*/
|
||||
public static Criteria empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link List Criterias}.
|
||||
*
|
||||
* @return new {@link Criteria}.
|
||||
*/
|
||||
public static Criteria from(Criteria... criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null");
|
||||
Assert.noNullElements(criteria, "Criteria must not contain null elements");
|
||||
|
||||
return from(Arrays.asList(criteria));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link List Criterias}.
|
||||
*
|
||||
* @return new {@link Criteria}.
|
||||
*/
|
||||
public static Criteria from(List<Criteria> criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null");
|
||||
Assert.noNullElements(criteria, "Criteria must not contain null elements");
|
||||
|
||||
if (criteria.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
if (criteria.size() == 1) {
|
||||
return criteria.get(0);
|
||||
}
|
||||
|
||||
return EMPTY.and(criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method to create a Criteria using the provided {@code column} name.
|
||||
*
|
||||
* @param column Must not be {@literal null} or empty.
|
||||
* @return a new {@link CriteriaStep} object to complete the first {@link Criteria}.
|
||||
*/
|
||||
public static CriteriaStep where(String column) {
|
||||
|
||||
Assert.hasText(column, "Column name must not be null or empty!");
|
||||
|
||||
return new DefaultCriteriaStep(SqlIdentifier.unquoted(column));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it with {@code AND} using the provided {@code column} name.
|
||||
*
|
||||
* @param column Must not be {@literal null} or empty.
|
||||
* @return a new {@link CriteriaStep} object to complete the next {@link Criteria}.
|
||||
*/
|
||||
public CriteriaStep and(String column) {
|
||||
|
||||
Assert.hasText(column, "Column name must not be null or empty!");
|
||||
|
||||
SqlIdentifier identifier = SqlIdentifier.unquoted(column);
|
||||
return new DefaultCriteriaStep(identifier) {
|
||||
@Override
|
||||
protected Criteria createCriteria(Comparator comparator, Object value) {
|
||||
return new Criteria(Criteria.this, Combinator.AND, Collections.emptyList(), identifier, comparator, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link Criteria} group.
|
||||
*
|
||||
* @param criteria criteria object.
|
||||
* @return a new {@link Criteria} object.
|
||||
* @since 1.1
|
||||
*/
|
||||
public Criteria and(Criteria criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null!");
|
||||
|
||||
return and(Collections.singletonList(criteria));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link Criteria} group.
|
||||
*
|
||||
* @param criteria criteria objects.
|
||||
* @return a new {@link Criteria} object.
|
||||
* @since 1.1
|
||||
*/
|
||||
public Criteria and(List<Criteria> criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null!");
|
||||
|
||||
return new Criteria(Criteria.this, Combinator.AND, criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it with {@code OR} using the provided {@code column} name.
|
||||
*
|
||||
* @param column Must not be {@literal null} or empty.
|
||||
* @return a new {@link CriteriaStep} object to complete the next {@link Criteria}.
|
||||
*/
|
||||
public CriteriaStep or(String column) {
|
||||
|
||||
Assert.hasText(column, "Column name must not be null or empty!");
|
||||
|
||||
SqlIdentifier identifier = SqlIdentifier.unquoted(column);
|
||||
return new DefaultCriteriaStep(identifier) {
|
||||
@Override
|
||||
protected Criteria createCriteria(Comparator comparator, Object value) {
|
||||
return new Criteria(Criteria.this, Combinator.OR, Collections.emptyList(), identifier, comparator, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code OR} using the provided {@link Criteria} group.
|
||||
*
|
||||
* @param criteria criteria object.
|
||||
* @return a new {@link Criteria} object.
|
||||
* @since 1.1
|
||||
*/
|
||||
public Criteria or(Criteria criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null!");
|
||||
|
||||
return or(Collections.singletonList(criteria));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code OR} using the provided {@link Criteria} group.
|
||||
*
|
||||
* @param criteria criteria object.
|
||||
* @return a new {@link Criteria} object.
|
||||
* @since 1.1
|
||||
*/
|
||||
public Criteria or(List<Criteria> criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null!");
|
||||
|
||||
return new Criteria(Criteria.this, Combinator.OR, criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Criteria} with the given "ignore case" flag.
|
||||
*
|
||||
* @param ignoreCase {@literal true} if comparison should be done in case-insensitive way
|
||||
* @return a new {@link Criteria} object
|
||||
*/
|
||||
public Criteria ignoreCase(boolean ignoreCase) {
|
||||
if (this.ignoreCase != ignoreCase) {
|
||||
return new Criteria(previous, combinator, group, column, comparator, value, ignoreCase);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the previous {@link Criteria} object. Can be {@literal null} if there is no previous {@link Criteria}.
|
||||
* @see #hasPrevious()
|
||||
*/
|
||||
@Nullable
|
||||
public Criteria getPrevious() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this {@link Criteria} has a previous one.
|
||||
*/
|
||||
public boolean hasPrevious() {
|
||||
return previous != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this {@link Criteria} is empty.
|
||||
* @since 1.1
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
|
||||
if (!doIsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Criteria parent = this.previous;
|
||||
|
||||
while (parent != null) {
|
||||
|
||||
if (!parent.doIsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parent = parent.previous;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean doIsEmpty() {
|
||||
|
||||
if (this.comparator == Comparator.INITIAL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.column != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Criteria criteria : group) {
|
||||
|
||||
if (!criteria.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this {@link Criteria} is empty.
|
||||
*/
|
||||
public boolean isGroup() {
|
||||
return !this.group.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Combinator} to combine this criteria with a previous one.
|
||||
*/
|
||||
public Combinator getCombinator() {
|
||||
return combinator;
|
||||
}
|
||||
|
||||
public List<Criteria> getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the column/property name.
|
||||
*/
|
||||
@Nullable
|
||||
public SqlIdentifier getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Comparator}.
|
||||
*/
|
||||
@Nullable
|
||||
public Comparator getComparator() {
|
||||
return comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the comparison value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether comparison should be done in case-insensitive way.
|
||||
*
|
||||
* @return {@literal true} if comparison should be done in case-insensitive way
|
||||
*/
|
||||
@Override
|
||||
public boolean isIgnoreCase() {
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface declaring terminal builder methods to build a {@link Criteria}.
|
||||
*/
|
||||
public interface CriteriaStep {
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using equality.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria is(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using equality (is not).
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria not(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code IN}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
Criteria in(Object... values);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code IN}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
Criteria in(Collection<?> values);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code NOT IN}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
Criteria notIn(Object... values);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code NOT IN}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
Criteria notIn(Collection<?> values);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using less-than ({@literal <}).
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria lessThan(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using less-than or equal to ({@literal <=}).
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria lessThanOrEquals(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using greater-than({@literal >}).
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria greaterThan(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using greater-than or equal to ({@literal >=}).
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria greaterThanOrEquals(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code LIKE}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
*/
|
||||
Criteria like(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code NOT LIKE}.
|
||||
*
|
||||
* @param value must not be {@literal null}
|
||||
* @return a new {@link Criteria} object
|
||||
*/
|
||||
Criteria notLike(Object value);
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code IS NULL}.
|
||||
*/
|
||||
Criteria isNull();
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code IS NOT NULL}.
|
||||
*/
|
||||
Criteria isNotNull();
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code IS TRUE}.
|
||||
*
|
||||
* @return a new {@link Criteria} object
|
||||
*/
|
||||
Criteria isTrue();
|
||||
|
||||
/**
|
||||
* Creates a {@link Criteria} using {@code IS FALSE}.
|
||||
*
|
||||
* @return a new {@link Criteria} object
|
||||
*/
|
||||
Criteria isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default {@link CriteriaStep} implementation.
|
||||
*/
|
||||
static class DefaultCriteriaStep implements CriteriaStep {
|
||||
|
||||
private final SqlIdentifier property;
|
||||
|
||||
DefaultCriteriaStep(SqlIdentifier property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#is(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria is(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.EQ, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#not(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria not(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.NEQ, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#in(java.lang.Object[])
|
||||
*/
|
||||
@Override
|
||||
public Criteria in(Object... values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
Assert.noNullElements(values, "Values must not contain a null value!");
|
||||
|
||||
if (values.length > 1 && values[1] instanceof Collection) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"You can only pass in one argument of type " + values[1].getClass().getName());
|
||||
}
|
||||
|
||||
return createCriteria(Comparator.IN, Arrays.asList(values));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#in(java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public Criteria in(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
Assert.noNullElements(values.toArray(), "Values must not contain a null value!");
|
||||
|
||||
return createCriteria(Comparator.IN, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#notIn(java.lang.Object[])
|
||||
*/
|
||||
@Override
|
||||
public Criteria notIn(Object... values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
Assert.noNullElements(values, "Values must not contain a null value!");
|
||||
|
||||
if (values.length > 1 && values[1] instanceof Collection) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"You can only pass in one argument of type " + values[1].getClass().getName());
|
||||
}
|
||||
|
||||
return createCriteria(Comparator.NOT_IN, Arrays.asList(values));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#notIn(java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public Criteria notIn(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
Assert.noNullElements(values.toArray(), "Values must not contain a null value!");
|
||||
|
||||
return createCriteria(Comparator.NOT_IN, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#lessThan(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria lessThan(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.LT, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#lessThanOrEquals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria lessThanOrEquals(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.LTE, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#greaterThan(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria greaterThan(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.GT, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#greaterThanOrEquals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria greaterThanOrEquals(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.GTE, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#like(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria like(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return createCriteria(Comparator.LIKE, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#notLike(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Criteria notLike(Object value) {
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return createCriteria(Comparator.NOT_LIKE, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#isNull()
|
||||
*/
|
||||
@Override
|
||||
public Criteria isNull() {
|
||||
return createCriteria(Comparator.IS_NULL, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#isNotNull()
|
||||
*/
|
||||
@Override
|
||||
public Criteria isNotNull() {
|
||||
return createCriteria(Comparator.IS_NOT_NULL, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#isTrue()
|
||||
*/
|
||||
@Override
|
||||
public Criteria isTrue() {
|
||||
return createCriteria(Comparator.IS_TRUE, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.function.query.Criteria.CriteriaStep#isFalse()
|
||||
*/
|
||||
@Override
|
||||
public Criteria isFalse() {
|
||||
return createCriteria(Comparator.IS_FALSE, null);
|
||||
}
|
||||
|
||||
protected Criteria createCriteria(Comparator comparator, Object value) {
|
||||
return new Criteria(this.property, comparator, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Interface defining a criteria definition object. A criteria definition may chain multiple predicates and may also
|
||||
* represent a group of nested criteria objects.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface CriteriaDefinition {
|
||||
|
||||
/**
|
||||
* Static factory method to create an empty Criteria.
|
||||
*
|
||||
* @return an empty {@link Criteria}.
|
||||
*/
|
||||
static CriteriaDefinition empty() {
|
||||
return Criteria.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link List Criterias}.
|
||||
*
|
||||
* @return new {@link Criteria}.
|
||||
*/
|
||||
static CriteriaDefinition from(Criteria... criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null");
|
||||
Assert.noNullElements(criteria, "Criteria must not contain null elements");
|
||||
|
||||
return from(Arrays.asList(criteria));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link List Criterias}.
|
||||
*
|
||||
* @return new {@link Criteria}.
|
||||
* @since 1.1
|
||||
*/
|
||||
static CriteriaDefinition from(List<Criteria> criteria) {
|
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null");
|
||||
Assert.noNullElements(criteria, "Criteria must not contain null elements");
|
||||
|
||||
if (criteria.isEmpty()) {
|
||||
return Criteria.EMPTY;
|
||||
}
|
||||
|
||||
if (criteria.size() == 1) {
|
||||
return criteria.get(0);
|
||||
}
|
||||
|
||||
return Criteria.EMPTY.and(criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this {@link Criteria} is empty.
|
||||
*/
|
||||
boolean isGroup();
|
||||
|
||||
List<? extends CriteriaDefinition> getGroup();
|
||||
|
||||
/**
|
||||
* @return the column/property name.
|
||||
*/
|
||||
@Nullable
|
||||
SqlIdentifier getColumn();
|
||||
|
||||
/**
|
||||
* @return {@link Criteria.Comparator}.
|
||||
*/
|
||||
@Nullable
|
||||
Comparator getComparator();
|
||||
|
||||
/**
|
||||
* @return the comparison value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
Object getValue();
|
||||
|
||||
/**
|
||||
* Checks whether comparison should be done in case-insensitive way.
|
||||
*
|
||||
* @return {@literal true} if comparison should be done in case-insensitive way
|
||||
*/
|
||||
boolean isIgnoreCase();
|
||||
|
||||
/**
|
||||
* @return the previous {@link CriteriaDefinition} object. Can be {@literal null} if there is no previous
|
||||
* {@link CriteriaDefinition}.
|
||||
* @see #hasPrevious()
|
||||
*/
|
||||
@Nullable
|
||||
CriteriaDefinition getPrevious();
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this {@link Criteria} has a previous one.
|
||||
*/
|
||||
boolean hasPrevious();
|
||||
|
||||
/**
|
||||
* @return {@literal true} if this {@link Criteria} is empty.
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* @return {@link Combinator} to combine this criteria with a previous one.
|
||||
*/
|
||||
Combinator getCombinator();
|
||||
|
||||
enum Combinator {
|
||||
INITIAL, AND, OR;
|
||||
}
|
||||
|
||||
enum Comparator {
|
||||
INITIAL, EQ, NEQ, LT, LTE, GT, GTE, IS_NULL, IS_NOT_NULL, LIKE, NOT_LIKE, NOT_IN, IN, IS_TRUE, IS_FALSE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Query object representing {@link Criteria}, columns, {@link Sort}, and limit/offset for a SQL query. {@link Query} is
|
||||
* created with a fluent API creating immutable objects.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
* @see Criteria
|
||||
* @see Sort
|
||||
* @see Pageable
|
||||
*/
|
||||
public class Query {
|
||||
|
||||
private final @Nullable CriteriaDefinition criteria;
|
||||
|
||||
private final List<SqlIdentifier> columns;
|
||||
private final Sort sort;
|
||||
private final int limit;
|
||||
private final long offset;
|
||||
|
||||
/**
|
||||
* Static factory method to create a {@link Query} using the provided {@link CriteriaDefinition}.
|
||||
*
|
||||
* @param criteria must not be {@literal null}.
|
||||
* @return a new {@link Query} for the given {@link Criteria}.
|
||||
*/
|
||||
public static Query query(CriteriaDefinition criteria) {
|
||||
return new Query(criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Query} using the given {@link Criteria}.
|
||||
*
|
||||
* @param criteria must not be {@literal null}.
|
||||
*/
|
||||
private Query(@Nullable CriteriaDefinition criteria) {
|
||||
this(criteria, Collections.emptyList(), Sort.unsorted(), -1, -1);
|
||||
}
|
||||
|
||||
private Query(@Nullable CriteriaDefinition criteria, List<SqlIdentifier> columns, Sort sort, int limit, long offset) {
|
||||
|
||||
this.criteria = criteria;
|
||||
this.columns = columns;
|
||||
this.sort = sort;
|
||||
this.limit = limit;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty {@link Query}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Query empty() {
|
||||
return new Query(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to the query.
|
||||
*
|
||||
* @param columns
|
||||
* @return a new {@link Query} object containing the former settings with {@code columns} applied.
|
||||
*/
|
||||
public Query columns(String... columns) {
|
||||
|
||||
Assert.notNull(columns, "Columns must not be null");
|
||||
|
||||
return withColumns(Arrays.stream(columns).map(SqlIdentifier::unquoted).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to the query.
|
||||
*
|
||||
* @param columns
|
||||
* @return a new {@link Query} object containing the former settings with {@code columns} applied.
|
||||
*/
|
||||
public Query columns(Collection<String> columns) {
|
||||
|
||||
Assert.notNull(columns, "Columns must not be null");
|
||||
|
||||
return withColumns(columns.stream().map(SqlIdentifier::unquoted).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to the query.
|
||||
*
|
||||
* @param columns
|
||||
* @return a new {@link Query} object containing the former settings with {@code columns} applied.
|
||||
* @since 1.1
|
||||
*/
|
||||
public Query columns(SqlIdentifier... columns) {
|
||||
|
||||
Assert.notNull(columns, "Columns must not be null");
|
||||
|
||||
return withColumns(Arrays.asList(columns));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to the query.
|
||||
*
|
||||
* @param columns
|
||||
* @return a new {@link Query} object containing the former settings with {@code columns} applied.
|
||||
*/
|
||||
private Query withColumns(Collection<SqlIdentifier> columns) {
|
||||
|
||||
Assert.notNull(columns, "Columns must not be null");
|
||||
|
||||
List<SqlIdentifier> newColumns = new ArrayList<>(this.columns);
|
||||
newColumns.addAll(columns);
|
||||
return new Query(this.criteria, newColumns, this.sort, this.limit, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number of rows to skip before returning results.
|
||||
*
|
||||
* @param offset
|
||||
* @return a new {@link Query} object containing the former settings with {@code offset} applied.
|
||||
*/
|
||||
public Query offset(long offset) {
|
||||
return new Query(this.criteria, this.columns, this.sort, this.limit, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of returned documents to {@code limit}.
|
||||
*
|
||||
* @param limit
|
||||
* @return a new {@link Query} object containing the former settings with {@code limit} applied.
|
||||
*/
|
||||
public Query limit(int limit) {
|
||||
return new Query(this.criteria, this.columns, this.sort, limit, this.offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given pagination information on the {@link Query} instance. Will transparently set {@code offset} and
|
||||
* {@code limit} as well as applying the {@link Sort} instance defined with the {@link Pageable}.
|
||||
*
|
||||
* @param pageable
|
||||
* @return a new {@link Query} object containing the former settings with {@link Pageable} applied.
|
||||
*/
|
||||
public Query with(Pageable pageable) {
|
||||
|
||||
if (pageable.isUnpaged()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
assertNoCaseSort(pageable.getSort());
|
||||
|
||||
return new Query(this.criteria, this.columns, this.sort.and(sort), pageable.getPageSize(), pageable.getOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link Sort} to the {@link Query} instance.
|
||||
*
|
||||
* @param sort
|
||||
* @return a new {@link Query} object containing the former settings with {@link Sort} applied.
|
||||
*/
|
||||
public Query sort(Sort sort) {
|
||||
|
||||
Assert.notNull(sort, "Sort must not be null!");
|
||||
|
||||
if (sort.isUnsorted()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
assertNoCaseSort(sort);
|
||||
|
||||
return new Query(this.criteria, this.columns, this.sort.and(sort), this.limit, this.offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link Criteria} to be applied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Optional<CriteriaDefinition> getCriteria() {
|
||||
return Optional.ofNullable(this.criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the columns that this query should project.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<SqlIdentifier> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@literal true} if the {@link Query} has a sort parameter.
|
||||
*
|
||||
* @return {@literal true} if sorted.
|
||||
* @see Sort#isSorted()
|
||||
*/
|
||||
public boolean isSorted() {
|
||||
return sort.isSorted();
|
||||
}
|
||||
|
||||
public Sort getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of rows to skip.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long getOffset() {
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of rows to be return.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLimit() {
|
||||
return this.limit;
|
||||
}
|
||||
|
||||
private static void assertNoCaseSort(Sort sort) {
|
||||
|
||||
for (Sort.Order order : sort) {
|
||||
if (order.isIgnoreCase()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Given sort contained an Order for %s with ignore case;" + "Ignore case sorting is not supported",
|
||||
order.getProperty()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2019-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 java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Class to easily construct SQL update assignments.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Oliver Drotbohm
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Update {
|
||||
|
||||
private static final Update EMPTY = new Update(Collections.emptyMap());
|
||||
|
||||
private final Map<SqlIdentifier, Object> columnsToUpdate;
|
||||
|
||||
private Update(Map<SqlIdentifier, Object> columnsToUpdate) {
|
||||
this.columnsToUpdate = columnsToUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method to create an {@link Update} from {@code assignments}.
|
||||
*
|
||||
* @param assignments must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static Update from(Map<SqlIdentifier, Object> assignments) {
|
||||
return new Update(new LinkedHashMap<>(assignments));
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method to create an {@link Update} using the provided column.
|
||||
*
|
||||
* @param column must not be {@literal null}.
|
||||
* @param value can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static Update update(String column, @Nullable Object value) {
|
||||
return EMPTY.set(column, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a column by assigning a value.
|
||||
*
|
||||
* @param column must not be {@literal null}.
|
||||
* @param value can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public Update set(String column, @Nullable Object value) {
|
||||
|
||||
Assert.hasText(column, "Column for update must not be null or blank");
|
||||
|
||||
return addMultiFieldOperation(SqlIdentifier.unquoted(column), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a column by assigning a value.
|
||||
*
|
||||
* @param column must not be {@literal null}.
|
||||
* @param value can be {@literal null}.
|
||||
* @return
|
||||
* @since 1.1
|
||||
*/
|
||||
public Update set(SqlIdentifier column, @Nullable Object value) {
|
||||
return addMultiFieldOperation(column, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all assignments.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<SqlIdentifier, Object> getAssignments() {
|
||||
return Collections.unmodifiableMap(this.columnsToUpdate);
|
||||
}
|
||||
|
||||
private Update addMultiFieldOperation(SqlIdentifier key, @Nullable Object value) {
|
||||
|
||||
Assert.notNull(key, "Column for update must not be null");
|
||||
|
||||
Map<SqlIdentifier, Object> updates = new LinkedHashMap<>(this.columnsToUpdate);
|
||||
updates.put(key, value);
|
||||
|
||||
return new Update(updates);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Query and update support.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
@org.springframework.lang.NonNullFields
|
||||
package org.springframework.data.relational.core.query;
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CriteriaTests {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright 2019-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 static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.SoftAssertions.*;
|
||||
import static org.springframework.data.relational.core.query.Criteria.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.relational.core.sql.SqlIdentifier;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Criteria}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
* @author Roman Chigvintsev
|
||||
*/
|
||||
public class CriteriaUnitTests {
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void fromCriteria() {
|
||||
|
||||
Criteria nested1 = where("foo").isNotNull();
|
||||
Criteria nested2 = where("foo").isNull();
|
||||
Criteria criteria = Criteria.from(nested1, nested2);
|
||||
|
||||
assertThat(criteria.isGroup()).isTrue();
|
||||
assertThat(criteria.getGroup()).containsExactly(nested1, nested2);
|
||||
assertThat(criteria.getPrevious()).isEqualTo(Criteria.empty());
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void fromCriteriaOptimized() {
|
||||
|
||||
Criteria nested = where("foo").is("bar").and("baz").isNotNull();
|
||||
Criteria criteria = Criteria.from(nested);
|
||||
|
||||
assertThat(criteria).isSameAs(nested);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void isEmpty() {
|
||||
|
||||
assertSoftly(softly -> {
|
||||
|
||||
Criteria empty = empty();
|
||||
Criteria notEmpty = where("foo").is("bar");
|
||||
|
||||
assertThat(empty.isEmpty()).isTrue();
|
||||
assertThat(notEmpty.isEmpty()).isFalse();
|
||||
|
||||
assertThat(Criteria.from(notEmpty).isEmpty()).isFalse();
|
||||
assertThat(Criteria.from(notEmpty, notEmpty).isEmpty()).isFalse();
|
||||
|
||||
assertThat(Criteria.from(empty).isEmpty()).isTrue();
|
||||
assertThat(Criteria.from(empty, empty).isEmpty()).isTrue();
|
||||
|
||||
assertThat(Criteria.from(empty, notEmpty).isEmpty()).isFalse();
|
||||
assertThat(Criteria.from(notEmpty, empty).isEmpty()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void andChainedCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").is("bar").and("baz").isNotNull();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("baz"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IS_NOT_NULL);
|
||||
assertThat(criteria.getValue()).isNull();
|
||||
assertThat(criteria.getPrevious()).isNotNull();
|
||||
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.AND);
|
||||
|
||||
criteria = criteria.getPrevious();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void andGroupedCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").is("bar").and(where("foo").is("baz"));
|
||||
|
||||
assertThat(criteria.isGroup()).isTrue();
|
||||
assertThat(criteria.getGroup()).hasSize(1);
|
||||
assertThat(criteria.getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.AND);
|
||||
|
||||
criteria = criteria.getPrevious();
|
||||
|
||||
assertThat(criteria).isNotNull();
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void orChainedCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").is("bar").or("baz").isNotNull();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("baz"));
|
||||
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.OR);
|
||||
|
||||
criteria = criteria.getPrevious();
|
||||
|
||||
assertThat(criteria).isNotNull();
|
||||
assertThat(criteria.getPrevious()).isNull();
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void orGroupedCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").is("bar").or(where("foo").is("baz"));
|
||||
|
||||
assertThat(criteria.isGroup()).isTrue();
|
||||
assertThat(criteria.getGroup()).hasSize(1);
|
||||
assertThat(criteria.getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.OR);
|
||||
|
||||
criteria = criteria.getPrevious();
|
||||
|
||||
assertThat(criteria).isNotNull();
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildEqualsCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").is("bar");
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBuildEqualsIgnoreCaseCriteria() {
|
||||
Criteria criteria = where("foo").is("bar").ignoreCase(true);
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
assertThat(criteria.isIgnoreCase()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildNotEqualsCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").not("bar");
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.NEQ);
|
||||
assertThat(criteria.getValue()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildInCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").in("bar", "baz");
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IN);
|
||||
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildNotInCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").notIn("bar", "baz");
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.NOT_IN);
|
||||
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildGtCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").greaterThan(1);
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.GT);
|
||||
assertThat(criteria.getValue()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildGteCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").greaterThanOrEquals(1);
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.GTE);
|
||||
assertThat(criteria.getValue()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildLtCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").lessThan(1);
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.LT);
|
||||
assertThat(criteria.getValue()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildLteCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").lessThanOrEquals(1);
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.LTE);
|
||||
assertThat(criteria.getValue()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildLikeCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").like("hello%");
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.LIKE);
|
||||
assertThat(criteria.getValue()).isEqualTo("hello%");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBuildNotLikeCriteria() {
|
||||
Criteria criteria = where("foo").notLike("hello%");
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.NOT_LIKE);
|
||||
assertThat(criteria.getValue()).isEqualTo("hello%");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildIsNullCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").isNull();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IS_NULL);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildIsNotNullCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").isNotNull();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IS_NOT_NULL);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildIsTrueCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").isTrue();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IS_TRUE);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-513
|
||||
public void shouldBuildIsFalseCriteria() {
|
||||
|
||||
Criteria criteria = where("foo").isFalse();
|
||||
|
||||
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
|
||||
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.IS_FALSE);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user