Skip to content

Commit 8ff4c0f

Browse files
committed
Add Oracle integration tests.
1 parent 72f4767 commit 8ff4c0f

18 files changed

+610
-420
lines changed

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<jsqlparser>5.0</jsqlparser>
3939
<mysql-connector-java>9.1.0</mysql-connector-java>
4040
<postgresql>42.7.4</postgresql>
41+
<oracle>23.7.0.25.01</oracle>
4142
<springdata.commons>4.0.0-SEARCH-RESULT-SNAPSHOT</springdata.commons>
4243
<vavr>0.10.3</vavr>
4344

@@ -120,6 +121,19 @@
120121
</includes>
121122
</configuration>
122123
</execution>
124+
<execution>
125+
<id>oracle-test</id>
126+
<phase>test</phase>
127+
<goals>
128+
<goal>test</goal>
129+
</goals>
130+
<configuration>
131+
<includes>
132+
<include>**/Oracle*IntegrationTests.java
133+
</include>
134+
</includes>
135+
</configuration>
136+
</execution>
123137
</executions>
124138
</plugin>
125139
</plugins>

spring-data-jpa/pom.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,28 @@
167167
<scope>test</scope>
168168
</dependency>
169169

170+
<!-- Oracle testing support -->
171+
172+
<dependency>
173+
<groupId>com.oracle.database.jdbc</groupId>
174+
<artifactId>ojdbc17</artifactId>
175+
<version>${oracle}</version>
176+
<scope>test</scope>
177+
</dependency>
178+
179+
<dependency>
180+
<groupId>com.oracle.database.jdbc</groupId>
181+
<artifactId>ucp17</artifactId>
182+
<version>${oracle}</version>
183+
<scope>test</scope>
184+
</dependency>
185+
186+
<dependency>
187+
<groupId>org.testcontainers</groupId>
188+
<artifactId>oracle-free</artifactId>
189+
<scope>test</scope>
190+
</dependency>
191+
170192
<dependency>
171193
<groupId>io.vavr</groupId>
172194
<artifactId>vavr</artifactId>
@@ -331,6 +353,7 @@
331353
<exclude>**/EclipseLink*</exclude>
332354
<exclude>**/MySql*</exclude>
333355
<exclude>**/Postgres*</exclude>
356+
<exclude>**/Oracle*</exclude>
334357
</excludes>
335358
<argLine>
336359
-Xmx4G

spring-data-jpa/src/main/java/org/springframework/data/jpa/convert/VectorConverters.java

Lines changed: 0 additions & 61 deletions
This file was deleted.

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@
3737

3838
import org.jspecify.annotations.Nullable;
3939

40+
import org.springframework.dao.InvalidDataAccessApiUsageException;
4041
import org.springframework.data.domain.Range;
4142
import org.springframework.data.domain.Score;
4243
import org.springframework.data.domain.ScoringFunction;
4344
import org.springframework.data.domain.Sort;
4445
import org.springframework.data.domain.VectorScoringFunctions;
45-
46-
import org.springframework.data.domain.Sort;
4746
import org.springframework.data.jpa.domain.JpaSort;
4847
import org.springframework.data.jpa.repository.query.JpqlQueryBuilder.ParameterPlaceholder;
4948
import org.springframework.data.jpa.repository.query.ParameterBinding.PartTreeParameterBinding;
@@ -71,7 +70,8 @@
7170
* @author Christoph Strobl
7271
* @author Jinmyeong Kim
7372
*/
74-
public class JpaQueryCreator extends AbstractQueryCreator<String, JpqlQueryBuilder.Predicate> implements JpqlQueryCreator {
73+
public class JpaQueryCreator extends AbstractQueryCreator<String, JpqlQueryBuilder.Predicate>
74+
implements JpqlQueryCreator {
7575

7676
private static final Map<ScoringFunction, DistanceFunction> DISTANCE_FUNCTIONS = Map.of(VectorScoringFunctions.COSINE,
7777
new DistanceFunction("cosine_distance", Sort.Direction.ASC), //
@@ -111,13 +111,12 @@ public JpaQueryCreator(PartTree tree, ReturnedType type, ParameterMetadataProvid
111111
}
112112

113113
public JpaQueryCreator(PartTree tree, ReturnedType type, ParameterMetadataProvider provider,
114-
JpqlQueryTemplates templates,
115-
Metamodel metamodel) {
114+
JpqlQueryTemplates templates, Metamodel metamodel) {
116115
this(tree, false, type, provider, templates, metamodel);
117116
}
118117

119118
public JpaQueryCreator(PartTree tree, boolean searchQuery, ReturnedType type, ParameterMetadataProvider provider,
120-
JpqlQueryTemplates templates, Metamodel metamodel) {
119+
JpqlQueryTemplates templates, Metamodel metamodel) {
121120

122121
super(tree);
123122

@@ -488,11 +487,10 @@ public JpqlQueryBuilder.Predicate build() {
488487
PartTreeParameterBinding parameter = provider.next(part, String.class);
489488
JpqlQueryBuilder.Expression parameterExpression = potentiallyIgnoreCase(part.getProperty(),
490489
placeholder(parameter));
490+
491491
// Predicate like = builder.like(propertyExpression, parameterExpression, escape.getEscapeCharacter());
492492
String escapeChar = Character.toString(escape.getEscapeCharacter());
493-
return
494-
495-
type.equals(NOT_LIKE) || type.equals(NOT_CONTAINING)
493+
return type.equals(NOT_LIKE) || type.equals(NOT_CONTAINING)
496494
? whereIgnoreCase.notLike(parameterExpression, escapeChar)
497495
: whereIgnoreCase.like(parameterExpression, escapeChar);
498496
case TRUE:
@@ -519,15 +517,14 @@ public JpqlQueryBuilder.Predicate build() {
519517

520518
where = JpqlQueryBuilder.where(entity, property);
521519
return type.equals(IS_NOT_EMPTY) ? where.isNotEmpty() : where.isEmpty();
522-
523520
case WITHIN:
524521
case NEAR:
525522
PartTreeParameterBinding vector = provider.next(part);
526523
PartTreeParameterBinding within = provider.next(part);
527524

528525
if (within.getValue() instanceof Range<?> r) {
529526

530-
Range<Score> range = (Range<Score>) within.getValue();
527+
Range<Score> range = (Range<Score>) r;
531528

532529
if (range.getUpperBound().isBounded() || range.getUpperBound().isBounded()) {
533530

@@ -573,6 +570,8 @@ public JpqlQueryBuilder.Predicate build() {
573570
return getUpperPredicate(true, distance, distanceValue);
574571
}
575572

573+
throw new InvalidDataAccessApiUsageException(
574+
"Near/Within keywords must be used with a Score or Range<Score> type");
576575
default:
577576
throw new IllegalArgumentException("Unsupported keyword " + type);
578577
}

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterMetadataProvider.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ public class ParameterMetadataProvider {
7878
* @param escape must not be {@literal null}.
7979
* @param templates must not be {@literal null}.
8080
*/
81-
public ParameterMetadataProvider(JpaParametersParameterAccessor accessor,
82-
EscapeCharacter escape, JpqlQueryTemplates templates) {
81+
public ParameterMetadataProvider(JpaParametersParameterAccessor accessor, EscapeCharacter escape,
82+
JpqlQueryTemplates templates) {
8383
this(accessor.iterator(), accessor, accessor.getParameters(), escape, templates);
8484
}
8585

@@ -91,8 +91,7 @@ public ParameterMetadataProvider(JpaParametersParameterAccessor accessor,
9191
* @param escape must not be {@literal null}.
9292
* @param templates must not be {@literal null}.
9393
*/
94-
public ParameterMetadataProvider(JpaParameters parameters, EscapeCharacter escape,
95-
JpqlQueryTemplates templates) {
94+
public ParameterMetadataProvider(JpaParameters parameters, EscapeCharacter escape, JpqlQueryTemplates templates) {
9695
this(null, null, parameters, escape, templates);
9796
}
9897

@@ -106,8 +105,8 @@ public ParameterMetadataProvider(JpaParameters parameters, EscapeCharacter escap
106105
* @param templates must not be {@literal null}.
107106
*/
108107
private ParameterMetadataProvider(@Nullable Iterator<Object> bindableParameterValues,
109-
@Nullable JpaParametersParameterAccessor accessor, JpaParameters parameters,
110-
EscapeCharacter escape, JpqlQueryTemplates templates) {
108+
@Nullable JpaParametersParameterAccessor accessor, JpaParameters parameters, EscapeCharacter escape,
109+
JpqlQueryTemplates templates) {
111110
Assert.notNull(parameters, "Parameters must not be null");
112111
Assert.notNull(escape, "EscapeCharacter must not be null");
113112
Assert.notNull(templates, "JpqlQueryTemplates must not be null");
@@ -196,14 +195,16 @@ private <T> PartTreeParameterBinding next(Part part, Class<T> type, Parameter pa
196195
int currentPosition = ++position;
197196
int currentBindMarker = ++bindMarker;
198197

199-
BindingIdentifier bindingIdentifier = parameter.getName().map(it -> BindingIdentifier.of(it, currentPosition))
198+
BindingIdentifier bindingIdentifier = parameter.getName().map(it -> BindingIdentifier.of(it, currentBindMarker))
199+
.orElseGet(() -> BindingIdentifier.of(currentBindMarker));
200+
201+
BindingIdentifier origin = parameter.getName().map(it -> BindingIdentifier.of(it, currentPosition))
200202
.orElseGet(() -> BindingIdentifier.of(currentPosition));
201203

202204
/* identifier refers to bindable parameters, not _all_ parameters index */
203-
MethodInvocationArgument methodParameter = ParameterOrigin.ofParameter(BindingIdentifier.of(currentPosition));
204-
PartTreeParameterBinding binding = new PartTreeParameterBinding(BindingIdentifier.of(currentBindMarker),
205-
methodParameter, reifiedType,
206-
part, value, templates, escape);
205+
MethodInvocationArgument methodParameter = ParameterOrigin.ofParameter(origin);
206+
PartTreeParameterBinding binding = new PartTreeParameterBinding(bindingIdentifier,
207+
methodParameter, reifiedType, part, value, templates, escape);
207208

208209
// PartTreeParameterBinding is more expressive than a potential ParameterBinding for Vector.
209210
bindings.add(binding);
@@ -284,7 +285,7 @@ RangeParameterBinding lower(PartTreeParameterBinding within, SimilarityNormalize
284285

285286
BindingIdentifier identifier = within.getIdentifier();
286287
RangeParameterBinding rangeBinding = new RangeParameterBinding(
287-
identifier.mapName(name -> name + "_upper").withPosition(bindMarker), within.getOrigin(), true, normalizer);
288+
identifier.mapName(name -> name + "_lower").withPosition(bindMarker), within.getOrigin(), true, normalizer);
288289
bindings.add(rangeBinding);
289290

290291
return rangeBinding;

0 commit comments

Comments
 (0)