Skip to content

Commit 6491e86

Browse files
ipirogetiennehomer
authored andcommitted
Extract methodes implementing IN clause in gridsuite-computation (#4)
* Extract methodes implementing IN clause in gridsuite-computation Signed-off-by: Igor PIROG <[email protected]> * Code indentation Signed-off-by: Igor PIROG <[email protected]> * Generalize use of IN clause Signed-off-by: Igor PIROG <[email protected]> * It seems there are misuses of EQUALS operator with a list of parameters :/ Signed-off-by: Igor PIROG <[email protected]> * Fixed NOT_EQUAL implementation Signed-off-by: Igor PIROG <[email protected]> * Remove useless annotation @slf4j Signed-off-by: Igor PIROG <[email protected]> --------- Signed-off-by: Igor PIROG <[email protected]> Co-authored-by: Etienne Homer <[email protected]>
1 parent f3bfd75 commit 6491e86

File tree

2 files changed

+29
-30
lines changed

2 files changed

+29
-30
lines changed

src/main/java/org/gridsuite/computation/utils/SpecificationUtils.java

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
* @author Kevin Le Saulnier <[email protected]>
2727
*/
2828
public final class SpecificationUtils {
29-
/**
30-
* Maximum values per IN clause chunk to avoid StackOverflow exceptions.
31-
* Current value (500) is a safe default but can be changed
32-
*/
33-
public static final int MAX_IN_CLAUSE_SIZE = 500;
3429

3530
public static final String FIELD_SEPARATOR = ".";
3631

32+
/**
33+
Prefer less than 1000 for Oracle DB / good compromise for Postgres
34+
*/
35+
public static final int MAX_IN_CLAUSE_SIZE = 10000;
36+
3737
// Utility class, so no constructor
3838
private SpecificationUtils() { }
3939

@@ -51,6 +51,11 @@ public static <X> Specification<X> notEqual(String field, String value) {
5151
return (root, cq, cb) -> cb.notEqual(getColumnPath(root, field), value);
5252
}
5353

54+
public static <X> Specification<X> in(String field, List<String> values) {
55+
return (root, cq, cb) ->
56+
cb.upper(getColumnPath(root, field).as(String.class)).in(values);
57+
}
58+
5459
public static <X> Specification<X> contains(String field, String value) {
5560
return (root, cq, cb) -> cb.like(cb.upper(getColumnPath(root, field).as(String.class)), "%" + EscapeCharacter.DEFAULT.escape(value).toUpperCase() + "%", EscapeCharacter.DEFAULT.getEscapeCharacter());
5661
}
@@ -135,15 +140,22 @@ private static <X> Specification<X> appendTextFilterToSpecification(Specificatio
135140
// implicitly an IN resourceFilter type because only IN may have value lists as filter value
136141
List<String> inValues = valueList.stream()
137142
.map(Object::toString)
143+
.map(String::toUpperCase)
138144
.toList();
139145
completedSpecification = completedSpecification.and(
146+
resourceFilter.type() == ResourceFilterDTO.Type.NOT_EQUAL ?
147+
not(generateInSpecification(resourceFilter.column(), inValues)) :
140148
generateInSpecification(resourceFilter.column(), inValues)
141149
);
142150
} else if (resourceFilter.value() == null) {
143151
// if the value is null, we build an impossible specification (trick to remove later on ?)
144152
completedSpecification = completedSpecification.and(not(completedSpecification));
145153
} else {
146-
completedSpecification = completedSpecification.and(equals(resourceFilter.column(), resourceFilter.value().toString()));
154+
completedSpecification = completedSpecification.and(
155+
resourceFilter.type() == ResourceFilterDTO.Type.NOT_EQUAL ?
156+
notEqual(resourceFilter.column(), resourceFilter.value().toString()) :
157+
equals(resourceFilter.column(), resourceFilter.value().toString())
158+
);
147159
}
148160
}
149161
case CONTAINS -> {
@@ -176,32 +188,17 @@ private static <X> Specification<X> appendTextFilterToSpecification(Specificatio
176188
* @return a specification for the IN clause
177189
*/
178190
private static <X> Specification<X> generateInSpecification(String column, List<String> inPossibleValues) {
179-
180-
if (inPossibleValues.size() > MAX_IN_CLAUSE_SIZE) {
181-
// there are too many values for only one call to anyOf() : it might cause a StackOverflow
182-
// => the specification is divided into several specifications which have an OR between them :
183-
List<List<String>> chunksOfInValues = Lists.partition(inPossibleValues, MAX_IN_CLAUSE_SIZE);
184-
Specification<X> containerSpec = null;
185-
for (List<String> chunk : chunksOfInValues) {
186-
Specification<X> multiOrEqualSpec = anyOf(
187-
chunk
188-
.stream()
189-
.map(value -> SpecificationUtils.<X>equals(column, value))
190-
.toList()
191-
);
192-
if (containerSpec == null) {
193-
containerSpec = multiOrEqualSpec;
194-
} else {
195-
containerSpec = containerSpec.or(multiOrEqualSpec);
196-
}
191+
List<List<String>> chunksOfInValues = Lists.partition(inPossibleValues, MAX_IN_CLAUSE_SIZE);
192+
Specification<X> containerSpec = null;
193+
for (List<String> chunk : chunksOfInValues) {
194+
Specification<X> multiOrEqualSpec = Specification.anyOf(in(column, chunk));
195+
if (containerSpec == null) {
196+
containerSpec = multiOrEqualSpec;
197+
} else {
198+
containerSpec = containerSpec.or(multiOrEqualSpec);
197199
}
198-
return containerSpec;
199200
}
200-
return anyOf(inPossibleValues
201-
.stream()
202-
.map(value -> SpecificationUtils.<X>equals(column, value))
203-
.toList()
204-
);
201+
return containerSpec;
205202
}
206203

207204
@NotNull

src/test/java/org/gridsuite/computation/specification/CommonSpecificationBuilderTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ void testBuildSpecification() {
7979
// test data
8080
List<ResourceFilterDTO> resourceFilters = List.of(
8181
new ResourceFilterDTO(TEXT, EQUALS, "dummyColumnValue", "dummyColumn"),
82+
new ResourceFilterDTO(TEXT, NOT_EQUAL, "dummyColumnValue", "dummyColumn"),
83+
new ResourceFilterDTO(TEXT, NOT_EQUAL, List.of("dummyColumnValue", "otherDummyColumnValue"), "dummyColumn"),
8284
new ResourceFilterDTO(TEXT, STARTS_WITH, "dum", "dummyColumn"),
8385
new ResourceFilterDTO(TEXT, IN, List.of("dummyColumnValue", "otherDummyColumnValue"), "dummyColumn"),
8486
new ResourceFilterDTO(TEXT, IN, tooManyInValues, "dummyColumn"),

0 commit comments

Comments
 (0)