Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit abff006

Browse files
committedMar 16, 2025·
DATAJDBC-1953 Introduced DialectCriteriaCondition
Signed-off-by: mipo256 <[email protected]>
1 parent f3dc789 commit abff006

File tree

7 files changed

+264
-35
lines changed

7 files changed

+264
-35
lines changed
 

‎spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/CriteriaUnitTests.java

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.assertj.core.api.SoftAssertions;
2424
import org.junit.jupiter.api.Test;
2525

26+
import org.springframework.data.relational.core.dialect.condition.Postgres;
2627
import org.springframework.data.relational.core.query.Criteria;
2728
import org.springframework.data.relational.core.sql.SqlIdentifier;
2829

‎spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/OracleDialect.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* An SQL dialect for Oracle.
2929
*
3030
* @author Jens Schauder
31-
* @author Mikahil Polivakha
31+
* @author Mikhail Polivakha
3232
* @since 2.1
3333
*/
3434
public class OracleDialect extends AnsiDialect {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.springframework.data.relational.core.dialect.condition;
2+
3+
import org.springframework.data.relational.core.query.Criteria;
4+
5+
/**
6+
* This interface represents dialect specific conditions used in WHERE causes built by {@link Criteria}.
7+
*
8+
* @author Mikhail Polivakha
9+
*/
10+
public interface DialectCriteriaCondition {
11+
12+
/**
13+
* Render a vendor-specific part of the SQL condition.
14+
*
15+
* @return the rendered part of the SQL statement
16+
*/
17+
String render();
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package org.springframework.data.relational.core.dialect.condition;
2+
3+
import org.springframework.data.relational.core.dialect.PostgresDialect;
4+
5+
/**
6+
* {@link DialectCriteriaCondition DialectCriteriaConditions} that are specific to {@link PostgresDialect PostgreSQL Dialect}
7+
*
8+
* @author Mikhail Polivakha
9+
*/
10+
public class Postgres {
11+
12+
/**
13+
* Creates a condition that checks that the assumed column of an {@link java.sql.Array} type
14+
* contains an array of any values
15+
*
16+
* @param values array that assumed column should contain
17+
* @return crafted {@link DialectCriteriaCondition}
18+
*/
19+
public static DialectCriteriaCondition arrayContains(Object... values) {
20+
return () -> "@> ARRAY[%s]".formatted(toLiterals(false, values));
21+
}
22+
23+
/**
24+
* Creates a condition that checks that the assumed column of an {@link java.sql.Array} type
25+
* contains an array of {@link String} values.
26+
*
27+
* @param values array of {@link String String} that assumed column should contain
28+
* @return crafted {@link DialectCriteriaCondition}
29+
*/
30+
public static DialectCriteriaCondition arrayContains(String... values) {
31+
return () -> "@> ARRAY[%s]::text[]".formatted(toLiterals(true, values));
32+
}
33+
34+
/**
35+
* Creates a condition that checks that the assumed column of an {@link java.sql.Array} type
36+
* contains an array of a single {@link String} value.
37+
*
38+
* @param value array of {@link String String} that assumed value should contain
39+
* @return crafted {@link DialectCriteriaCondition}
40+
*/
41+
public static DialectCriteriaCondition arrayContains(String value) {
42+
return arrayContains(new String[]{value});
43+
}
44+
45+
@SafeVarargs
46+
private static <T> String toLiterals(boolean quoted, T... values) {
47+
StringBuilder result = new StringBuilder();
48+
for (int i = 0; i < values.length; i++) {
49+
T value = values[i];
50+
51+
if (value != null) {
52+
if (quoted) {
53+
result.append('\'').append(value).append('\'');
54+
} else {
55+
result.append(value);
56+
}
57+
} else {
58+
result.append("NULL");
59+
}
60+
61+
if (i != values.length - 1) {
62+
result.append(",");
63+
}
64+
}
65+
return result.toString();
66+
}
67+
}

‎spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java

+99-34
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.StringJoiner;
2626

2727
import org.springframework.dao.InvalidDataAccessApiUsageException;
28+
import org.springframework.data.relational.core.dialect.condition.DialectCriteriaCondition;
2829
import org.springframework.data.relational.core.sql.IdentifierProcessing;
2930
import org.springframework.data.relational.core.sql.SqlIdentifier;
3031
import org.springframework.data.util.Pair;
@@ -53,11 +54,12 @@
5354
* @author Oliver Drotbohm
5455
* @author Roman Chigvintsev
5556
* @author Jens Schauder
57+
* @author Mikhail Polivakha
5658
* @since 2.0
5759
*/
5860
public class Criteria implements CriteriaDefinition {
5961

60-
static final Criteria EMPTY = new Criteria(SqlIdentifier.EMPTY, Comparator.INITIAL, null);
62+
static final Criteria EMPTY = new Criteria(SqlIdentifier.EMPTY, Comparator.INITIAL, null, null);
6163

6264
private final @Nullable Criteria previous;
6365
private final Combinator combinator;
@@ -68,17 +70,25 @@ public class Criteria implements CriteriaDefinition {
6870
private final @Nullable Object value;
6971
private final boolean ignoreCase;
7072

71-
private Criteria(SqlIdentifier column, Comparator comparator, @Nullable Object value) {
72-
this(null, Combinator.INITIAL, Collections.emptyList(), column, comparator, value, false);
73+
private final DialectCriteriaCondition dialectCriteriaCondition;
74+
75+
private Criteria(SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value, DialectCriteriaCondition dialectCriteriaCondition) {
76+
this(null, Combinator.INITIAL, Collections.emptyList(), column, comparator, value, false, dialectCriteriaCondition);
7377
}
7478

7579
private Criteria(@Nullable Criteria previous, Combinator combinator, List<CriteriaDefinition> group,
76-
@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value) {
77-
this(previous, combinator, group, column, comparator, value, false);
80+
@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value, DialectCriteriaCondition dialectCriteriaCondition) {
81+
this(previous, combinator, group, column, comparator, value, false, dialectCriteriaCondition);
7882
}
7983

8084
private Criteria(@Nullable Criteria previous, Combinator combinator, List<CriteriaDefinition> group,
81-
@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value, boolean ignoreCase) {
85+
@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value, boolean ignoreCase,
86+
@Nullable DialectCriteriaCondition dialectCriteriaCondition) {
87+
88+
Assert.state(
89+
(dialectCriteriaCondition != null && comparator == null) || (dialectCriteriaCondition == null && comparator != null),
90+
"Either DialectCriteriaCondition or Comparator should be specified for this criteria, but not both"
91+
);
8292

8393
this.previous = previous;
8494
this.combinator = previous != null && previous.isEmpty() ? Combinator.INITIAL : combinator;
@@ -87,6 +97,7 @@ private Criteria(@Nullable Criteria previous, Combinator combinator, List<Criter
8797
this.comparator = comparator;
8898
this.value = value;
8999
this.ignoreCase = ignoreCase;
100+
this.dialectCriteriaCondition = dialectCriteriaCondition;
90101
}
91102

92103
private Criteria(@Nullable Criteria previous, Combinator combinator, List<CriteriaDefinition> group) {
@@ -98,6 +109,7 @@ private Criteria(@Nullable Criteria previous, Combinator combinator, List<Criter
98109
this.comparator = null;
99110
this.value = null;
100111
this.ignoreCase = false;
112+
this.dialectCriteriaCondition = null;
101113
}
102114

103115
/**
@@ -169,8 +181,8 @@ public CriteriaStep and(String column) {
169181
SqlIdentifier identifier = SqlIdentifier.unquoted(column);
170182
return new DefaultCriteriaStep(identifier) {
171183
@Override
172-
protected Criteria createCriteria(Comparator comparator, @Nullable Object value) {
173-
return new Criteria(Criteria.this, Combinator.AND, Collections.emptyList(), identifier, comparator, value);
184+
protected Criteria createCriteria(Comparator comparator, @Nullable Object value, DialectCriteriaCondition dialectCriteriaCondition) {
185+
return new Criteria(Criteria.this, Combinator.AND, Collections.emptyList(), identifier, comparator, value, dialectCriteriaCondition);
174186
}
175187
};
176188
}
@@ -216,8 +228,8 @@ public CriteriaStep or(String column) {
216228
SqlIdentifier identifier = SqlIdentifier.unquoted(column);
217229
return new DefaultCriteriaStep(identifier) {
218230
@Override
219-
protected Criteria createCriteria(Comparator comparator, @Nullable Object value) {
220-
return new Criteria(Criteria.this, Combinator.OR, Collections.emptyList(), identifier, comparator, value);
231+
protected Criteria createCriteria(Comparator comparator, @Nullable Object value, DialectCriteriaCondition dialectCriteriaCondition) {
232+
return new Criteria(Criteria.this, Combinator.OR, Collections.emptyList(), identifier, comparator, value, dialectCriteriaCondition);
221233
}
222234
};
223235
}
@@ -259,7 +271,7 @@ public Criteria or(List<? extends CriteriaDefinition> criteria) {
259271
*/
260272
public Criteria ignoreCase(boolean ignoreCase) {
261273
if (this.ignoreCase != ignoreCase) {
262-
return new Criteria(previous, combinator, group, column, comparator, value, ignoreCase);
274+
return new Criteria(previous, combinator, group, column, comparator, value, ignoreCase, dialectCriteriaCondition);
263275
}
264276
return this;
265277
}
@@ -328,18 +340,25 @@ private boolean doIsEmpty() {
328340
/**
329341
* @return {@literal true} if this {@link Criteria} is empty.
330342
*/
343+
@Override
331344
public boolean isGroup() {
332345
return !this.group.isEmpty();
333346
}
334347

335348
/**
336349
* @return {@link Combinator} to combine this criteria with a previous one.
337350
*/
351+
@Override
338352
public Combinator getCombinator() {
339353
return combinator;
340354
}
341355

342-
@Override
356+
@Override
357+
public DialectCriteriaCondition getDialectCriteriaCondition() {
358+
return dialectCriteriaCondition;
359+
}
360+
361+
@Override
343362
public List<CriteriaDefinition> getGroup() {
344363
return group;
345364
}
@@ -476,8 +495,16 @@ private void render(CriteriaDefinition criteria, StringBuilder stringBuilder) {
476495
return;
477496
}
478497

479-
stringBuilder.append(criteria.getColumn().toSql(IdentifierProcessing.NONE)).append(' ')
480-
.append(criteria.getComparator().getComparator());
498+
stringBuilder.append(criteria.getColumn().toSql(IdentifierProcessing.NONE)).append(' ');
499+
500+
DialectCriteriaCondition dialectCriteriaCondition = criteria.getDialectCriteriaCondition();
501+
502+
if (dialectCriteriaCondition != null) {
503+
stringBuilder.append(dialectCriteriaCondition.render());
504+
return;
505+
}
506+
507+
stringBuilder.append(criteria.getComparator().getComparator());
481508

482509
switch (criteria.getComparator()) {
483510
case BETWEEN:
@@ -653,6 +680,39 @@ public interface CriteriaStep {
653680
* @return a new {@link Criteria} object
654681
*/
655682
Criteria isFalse();
683+
684+
/**
685+
* Creates a {@link Criteria} using custom {@link DialectCriteriaCondition}. This API primarily exists
686+
* to handle conditions in WHERE clause that are specific to particular RDBMS vendor.
687+
* <p>
688+
* There are some predefined vendor-specific conditions in the {@link org.springframework.data.relational.core.dialect.condition}
689+
* package. For instance, an example of usage is:
690+
* <p>
691+
* <pre class="code">
692+
* Criteria criteria = Criteria
693+
* .where("tags")
694+
* .satisfies(Postgres.arrayContains("computers", "electronics"))
695+
* </pre>
696+
*
697+
* This will yield the following SQL:
698+
* <p>
699+
* <pre class="code">
700+
* tags @> ARRAY['computers','electronics']::text[]
701+
* </pre>
702+
*
703+
* In the sample above, the assumption is that the 'tags' column is of an 'ARRAY TEXT' or 'ARRAY VARCHAR' PostgreSQL type.
704+
* <p>
705+
* If there is no appropriate {@link DialectCriteriaCondition} built-in, please, consider to file an issue, and in the meantime,
706+
* consider to write your own {@link DialectCriteriaCondition}, like this (case insensitive regexp-match in PostgreSQL):
707+
* <p>
708+
* <pre class="code">
709+
*
710+
* </pre>
711+
*
712+
* @see org.springframework.data.relational.core.dialect.condition.Postgres
713+
* @return a new {@link Criteria} object
714+
*/
715+
Criteria satisfies(DialectCriteriaCondition condition);
656716
}
657717

658718
/**
@@ -671,15 +731,15 @@ public Criteria is(Object value) {
671731

672732
Assert.notNull(value, "Value must not be null");
673733

674-
return createCriteria(Comparator.EQ, value);
734+
return createCriteria(Comparator.EQ, value, null);
675735
}
676736

677737
@Override
678738
public Criteria not(Object value) {
679739

680740
Assert.notNull(value, "Value must not be null");
681741

682-
return createCriteria(Comparator.NEQ, value);
742+
return createCriteria(Comparator.NEQ, value, null);
683743
}
684744

685745
@Override
@@ -693,7 +753,7 @@ public Criteria in(Object... values) {
693753
"You can only pass in one argument of type " + values[1].getClass().getName());
694754
}
695755

696-
return createCriteria(Comparator.IN, Arrays.asList(values));
756+
return createCriteria(Comparator.IN, Arrays.asList(values), null);
697757
}
698758

699759
@Override
@@ -702,7 +762,7 @@ public Criteria in(Collection<?> values) {
702762
Assert.notNull(values, "Values must not be null");
703763
Assert.noNullElements(values.toArray(), "Values must not contain a null value");
704764

705-
return createCriteria(Comparator.IN, values);
765+
return createCriteria(Comparator.IN, values, null);
706766
}
707767

708768
@Override
@@ -716,7 +776,7 @@ public Criteria notIn(Object... values) {
716776
"You can only pass in one argument of type " + values[1].getClass().getName());
717777
}
718778

719-
return createCriteria(Comparator.NOT_IN, Arrays.asList(values));
779+
return createCriteria(Comparator.NOT_IN, Arrays.asList(values), null);
720780
}
721781

722782
@Override
@@ -725,7 +785,7 @@ public Criteria notIn(Collection<?> values) {
725785
Assert.notNull(values, "Values must not be null");
726786
Assert.noNullElements(values.toArray(), "Values must not contain a null value");
727787

728-
return createCriteria(Comparator.NOT_IN, values);
788+
return createCriteria(Comparator.NOT_IN, values, null);
729789
}
730790

731791
@Override
@@ -734,7 +794,7 @@ public Criteria between(Object begin, Object end) {
734794
Assert.notNull(begin, "Begin value must not be null");
735795
Assert.notNull(end, "End value must not be null");
736796

737-
return createCriteria(Comparator.BETWEEN, Pair.of(begin, end));
797+
return createCriteria(Comparator.BETWEEN, Pair.of(begin, end), null);
738798
}
739799

740800
@Override
@@ -743,77 +803,82 @@ public Criteria notBetween(Object begin, Object end) {
743803
Assert.notNull(begin, "Begin value must not be null");
744804
Assert.notNull(end, "End value must not be null");
745805

746-
return createCriteria(Comparator.NOT_BETWEEN, Pair.of(begin, end));
806+
return createCriteria(Comparator.NOT_BETWEEN, Pair.of(begin, end), null);
747807
}
748808

749809
@Override
750810
public Criteria lessThan(Object value) {
751811

752812
Assert.notNull(value, "Value must not be null");
753813

754-
return createCriteria(Comparator.LT, value);
814+
return createCriteria(Comparator.LT, value, null);
755815
}
756816

757817
@Override
758818
public Criteria lessThanOrEquals(Object value) {
759819

760820
Assert.notNull(value, "Value must not be null");
761821

762-
return createCriteria(Comparator.LTE, value);
822+
return createCriteria(Comparator.LTE, value, null);
763823
}
764824

765825
@Override
766826
public Criteria greaterThan(Object value) {
767827

768828
Assert.notNull(value, "Value must not be null");
769829

770-
return createCriteria(Comparator.GT, value);
830+
return createCriteria(Comparator.GT, value, null);
771831
}
772832

773833
@Override
774834
public Criteria greaterThanOrEquals(Object value) {
775835

776836
Assert.notNull(value, "Value must not be null");
777837

778-
return createCriteria(Comparator.GTE, value);
838+
return createCriteria(Comparator.GTE, value, null);
779839
}
780840

781841
@Override
782842
public Criteria like(Object value) {
783843

784844
Assert.notNull(value, "Value must not be null");
785845

786-
return createCriteria(Comparator.LIKE, value);
846+
return createCriteria(Comparator.LIKE, value, null);
787847
}
788848

789849
@Override
790850
public Criteria notLike(Object value) {
791851
Assert.notNull(value, "Value must not be null");
792-
return createCriteria(Comparator.NOT_LIKE, value);
852+
return createCriteria(Comparator.NOT_LIKE, value, null);
793853
}
794854

795855
@Override
796856
public Criteria isNull() {
797-
return createCriteria(Comparator.IS_NULL, null);
857+
return createCriteria(Comparator.IS_NULL, null, null);
798858
}
799859

800860
@Override
801861
public Criteria isNotNull() {
802-
return createCriteria(Comparator.IS_NOT_NULL, null);
862+
return createCriteria(Comparator.IS_NOT_NULL, null, null);
803863
}
804864

805865
@Override
806866
public Criteria isTrue() {
807-
return createCriteria(Comparator.IS_TRUE, true);
867+
return createCriteria(Comparator.IS_TRUE, true, null);
808868
}
809869

810870
@Override
811871
public Criteria isFalse() {
812-
return createCriteria(Comparator.IS_FALSE, false);
872+
return createCriteria(Comparator.IS_FALSE, false, null);
813873
}
814874

815-
protected Criteria createCriteria(Comparator comparator, @Nullable Object value) {
816-
return new Criteria(this.property, comparator, value);
875+
@Override
876+
public Criteria satisfies(DialectCriteriaCondition condition) {
877+
return createCriteria(null, null, condition);
878+
}
879+
880+
protected Criteria createCriteria(@Nullable Comparator comparator, @Nullable Object value, DialectCriteriaCondition dialectCriteriaCondition) {
881+
return new Criteria(this.property, comparator, value, dialectCriteriaCondition);
817882
}
818883
}
819884
}

‎spring-data-relational/src/main/java/org/springframework/data/relational/core/query/CriteriaDefinition.java

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Arrays;
1919
import java.util.List;
2020

21+
import org.springframework.data.relational.core.dialect.condition.DialectCriteriaCondition;
2122
import org.springframework.data.relational.core.sql.SqlIdentifier;
2223
import org.springframework.lang.Nullable;
2324
import org.springframework.util.Assert;
@@ -28,6 +29,7 @@
2829
*
2930
* @author Mark Paluch
3031
* @author Jens Schauder
32+
* @author Mikhail Polivakha
3133
* @since 2.0
3234
*/
3335
public interface CriteriaDefinition {
@@ -133,6 +135,12 @@ static CriteriaDefinition from(List<? extends CriteriaDefinition> criteria) {
133135
*/
134136
Combinator getCombinator();
135137

138+
/**
139+
* @return {@link DialectCriteriaCondition} used in this criteria
140+
*/
141+
@Nullable
142+
DialectCriteriaCondition getDialectCriteriaCondition();
143+
136144
enum Combinator {
137145
INITIAL, AND, OR;
138146
}

‎spring-data-relational/src/test/java/org/springframework/data/relational/core/query/CriteriaUnitTests.java

+70
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Arrays;
2323

2424
import org.junit.jupiter.api.Test;
25+
import org.springframework.data.relational.core.dialect.condition.Postgres;
2526
import org.springframework.data.relational.core.sql.SqlIdentifier;
2627

2728
/**
@@ -30,6 +31,7 @@
3031
* @author Mark Paluch
3132
* @author Jens Schauder
3233
* @author Roman Chigvintsev
34+
* @author Mikhail Polivakha
3335
*/
3436
class CriteriaUnitTests {
3537

@@ -95,6 +97,27 @@ void andChainedCriteria() {
9597
assertThat(criteria.getValue()).isEqualTo("bar");
9698
}
9799

100+
@Test // DATAJDBC-513
101+
void andChainedCriteriaWithDialectCriteriaCondition() {
102+
103+
Criteria criteria = where("foo").is("bar").and("baz").satisfies(Postgres.arrayContains("first", "second"));
104+
105+
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("baz"));
106+
assertThat(criteria.getComparator()).isNull();
107+
assertThat(criteria.getValue()).isNull();
108+
assertThat(criteria.getPrevious()).isNotNull();
109+
assertThat(criteria.getDialectCriteriaCondition()).isNotNull();
110+
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.AND);
111+
112+
criteria = criteria.getPrevious();
113+
114+
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
115+
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
116+
assertThat(criteria.getValue()).isEqualTo("bar");
117+
118+
criteria.toString().equals("foo = 'bar' AND baz @> ARRAY['first','second']::text[]");
119+
}
120+
98121
@Test // DATAJDBC-513
99122
void andGroupedCriteria() {
100123

@@ -116,6 +139,27 @@ void andGroupedCriteria() {
116139
assertThat(grouped).hasToString("foo = 'bar' AND (foo = 'baz' OR bar IS NOT NULL)");
117140
}
118141

142+
@Test // DATAJDBC-1953
143+
void andGroupedCriteriaWithDialectCriteriaCondition() {
144+
145+
Criteria grouped = where("foo").is("bar").and(where("foo").is("baz").or("bar").satisfies(Postgres.arrayContains("electronics")));
146+
Criteria criteria = grouped;
147+
148+
assertThat(criteria.isGroup()).isTrue();
149+
assertThat(criteria.getGroup()).hasSize(1);
150+
assertThat(criteria.getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.unquoted("bar"));
151+
assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.AND);
152+
153+
criteria = criteria.getPrevious();
154+
155+
assertThat(criteria).isNotNull();
156+
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
157+
assertThat(criteria.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
158+
assertThat(criteria.getValue()).isEqualTo("bar");
159+
160+
assertThat(grouped).hasToString("foo = 'bar' AND (foo = 'baz' OR bar @> ARRAY['electronics']::text[])");
161+
}
162+
119163
@Test // DATAJDBC-513
120164
void orChainedCriteria() {
121165

@@ -179,6 +223,32 @@ void shouldBuildNotEqualsCriteria() {
179223
assertThat(criteria.getValue()).isEqualTo("bar");
180224
}
181225

226+
@Test // DATAJDBC-1953
227+
void shouldBuildSimplePredefinedDialectCriteriaCondition() {
228+
229+
Criteria criteria = where("foo").satisfies(Postgres.arrayContains(1, 2, 3));
230+
231+
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
232+
assertThat(criteria.getComparator()).isNull();
233+
assertThat(criteria.getDialectCriteriaCondition()).isNotNull();
234+
assertThat(criteria.getValue()).isNull();
235+
236+
assertThat(criteria.toString()).isEqualTo("foo @> ARRAY[1,2,3]");
237+
}
238+
239+
@Test // DATAJDBC-1953
240+
void shouldBuildSimpleCustomDialectCriteriaCondition() {
241+
242+
Criteria criteria = where("foo").satisfies(() -> "~* '*.example.*'");
243+
244+
assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
245+
assertThat(criteria.getComparator()).isNull();
246+
assertThat(criteria.getDialectCriteriaCondition()).isNotNull();
247+
assertThat(criteria.getValue()).isNull();
248+
249+
assertThat(criteria.toString()).isEqualTo("foo ~* '*.example.*'");
250+
}
251+
182252
@Test // DATAJDBC-513
183253
void shouldBuildInCriteria() {
184254

0 commit comments

Comments
 (0)
Please sign in to comment.