Merge branch '6.2.x'
This commit is contained in:
commit
4f38c5bdfa
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -49,6 +49,7 @@ import org.springframework.util.Assert;
|
|||
* @author Juergen Hoeller
|
||||
* @author Mark Paluch
|
||||
* @author Anton Naydenov
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
abstract class NamedParameterUtils {
|
||||
|
@ -512,69 +513,17 @@ abstract class NamedParameterUtils {
|
|||
|
||||
private final BindParameterSource parameterSource;
|
||||
|
||||
|
||||
ExpandedQuery(String expandedSql, NamedParameters parameters, BindParameterSource parameterSource) {
|
||||
this.expandedSql = expandedSql;
|
||||
this.parameters = parameters;
|
||||
this.parameterSource = parameterSource;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void bind(BindTarget target, String identifier, Parameter parameter) {
|
||||
List<BindMarker> bindMarkers = getBindMarkers(identifier);
|
||||
if (bindMarkers == null) {
|
||||
target.bind(identifier, parameter);
|
||||
return;
|
||||
}
|
||||
if (parameter.getValue() instanceof Collection collection) {
|
||||
Iterator<Object> iterator = collection.iterator();
|
||||
Iterator<BindMarker> markers = bindMarkers.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Object valueToBind = iterator.next();
|
||||
if (valueToBind instanceof Object[] objects) {
|
||||
for (Object object : objects) {
|
||||
bind(target, markers, object);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bind(target, markers, valueToBind);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (BindMarker bindMarker : bindMarkers) {
|
||||
bindMarker.bind(target, parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(BindTarget target, Iterator<BindMarker> markers, Object valueToBind) {
|
||||
Assert.isTrue(markers.hasNext(), () -> String.format(
|
||||
"No bind marker for value [%s] in SQL [%s]. Check that the query was expanded using the same arguments.",
|
||||
valueToBind, toQuery()));
|
||||
markers.next().bind(target, valueToBind);
|
||||
}
|
||||
|
||||
public void bindNull(BindTarget target, String identifier, Parameter parameter) {
|
||||
List<BindMarker> bindMarkers = getBindMarkers(identifier);
|
||||
if (bindMarkers == null) {
|
||||
target.bind(identifier, parameter);
|
||||
return;
|
||||
}
|
||||
for (BindMarker bindMarker : bindMarkers) {
|
||||
bindMarker.bind(target, parameter);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable List<BindMarker> getBindMarkers(String identifier) {
|
||||
List<NamedParameters.NamedParameter> parameters = this.parameters.getMarker(identifier);
|
||||
if (parameters == null) {
|
||||
return null;
|
||||
}
|
||||
List<BindMarker> markers = new ArrayList<>();
|
||||
for (NamedParameters.NamedParameter parameter : parameters) {
|
||||
markers.addAll(parameter.placeholders);
|
||||
}
|
||||
return markers;
|
||||
@Override
|
||||
public String toQuery() {
|
||||
return this.expandedSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -595,10 +544,67 @@ abstract class NamedParameterUtils {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toQuery() {
|
||||
return this.expandedSql;
|
||||
private void bindNull(BindTarget target, String identifier, Parameter parameter) {
|
||||
List<List<BindMarker>> bindMarkers = getBindMarkers(identifier);
|
||||
if (bindMarkers == null) {
|
||||
target.bind(identifier, parameter);
|
||||
return;
|
||||
}
|
||||
for (List<BindMarker> outer : bindMarkers) {
|
||||
for (BindMarker bindMarker : outer) {
|
||||
bindMarker.bind(target, parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(BindTarget target, String identifier, Parameter parameter) {
|
||||
List<List<BindMarker>> bindMarkers = getBindMarkers(identifier);
|
||||
if (bindMarkers == null) {
|
||||
target.bind(identifier, parameter);
|
||||
return;
|
||||
}
|
||||
|
||||
for (List<BindMarker> outer : bindMarkers) {
|
||||
if (parameter.getValue() instanceof Collection<?> collection) {
|
||||
Iterator<BindMarker> markers = outer.iterator();
|
||||
for (Object valueToBind : collection) {
|
||||
if (valueToBind instanceof Object[] objects) {
|
||||
for (Object object : objects) {
|
||||
bind(target, markers, object);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bind(target, markers, valueToBind);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (BindMarker bindMarker : outer) {
|
||||
bindMarker.bind(target, parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bind(BindTarget target, Iterator<BindMarker> markers, Object valueToBind) {
|
||||
Assert.isTrue(markers.hasNext(), () -> String.format(
|
||||
"No bind marker for value [%s] in SQL [%s]. Check that the query was expanded using the same arguments.",
|
||||
valueToBind, toQuery()));
|
||||
markers.next().bind(target, valueToBind);
|
||||
}
|
||||
|
||||
private @Nullable List<List<BindMarker>> getBindMarkers(String identifier) {
|
||||
List<NamedParameters.NamedParameter> parameters = this.parameters.getMarker(identifier);
|
||||
if (parameters == null) {
|
||||
return null;
|
||||
}
|
||||
List<List<BindMarker>> markers = new ArrayList<>();
|
||||
for (NamedParameters.NamedParameter parameter : parameters) {
|
||||
markers.add(new ArrayList<>(parameter.placeholders));
|
||||
}
|
||||
return markers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -19,8 +19,9 @@ package org.springframework.r2dbc.core.binding;
|
|||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
|
||||
/**
|
||||
* Anonymous, index-based bind marker using a static placeholder.
|
||||
* Instances are bound by the ordinal position ordered by the appearance of
|
||||
* Anonymous, index-based bind markers that use a static placeholder.
|
||||
*
|
||||
* <p>Instances are bound by the ordinal position ordered by the appearance of
|
||||
* the placeholder. This implementation creates indexed bind markers using
|
||||
* an anonymous placeholder that correlates with an index.
|
||||
*
|
||||
|
@ -46,7 +47,7 @@ class AnonymousBindMarkers implements BindMarkers {
|
|||
|
||||
|
||||
/**
|
||||
* Create a new {@link AnonymousBindMarkers} instance given {@code placeholder}.
|
||||
* Create a new {@link AnonymousBindMarkers} instance for the given {@code placeholder}.
|
||||
* @param placeholder parameter bind marker
|
||||
*/
|
||||
AnonymousBindMarkers(String placeholder) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -20,7 +20,8 @@ import io.r2dbc.spi.Statement;
|
|||
|
||||
/**
|
||||
* A bind marker represents a single bindable parameter within a query.
|
||||
* Bind markers are dialect-specific and provide a
|
||||
*
|
||||
* <p>Bind markers are dialect-specific and provide a
|
||||
* {@link #getPlaceholder() placeholder} that is used in the actual query.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
|
@ -37,7 +38,8 @@ public interface BindMarker {
|
|||
String getPlaceholder();
|
||||
|
||||
/**
|
||||
* Bind the given {@code value} to the {@link Statement} using the underlying binding strategy.
|
||||
* Bind the given {@code value} to the {@link Statement} using the underlying
|
||||
* binding strategy.
|
||||
* @param bindTarget the target to bind the value to
|
||||
* @param value the actual value (must not be {@code null};
|
||||
* use {@link #bindNull(BindTarget, Class)} for {@code null} values)
|
||||
|
@ -46,7 +48,8 @@ public interface BindMarker {
|
|||
void bind(BindTarget bindTarget, Object value);
|
||||
|
||||
/**
|
||||
* Bind a {@code null} value to the {@link Statement} using the underlying binding strategy.
|
||||
* Bind a {@code null} value to the {@link Statement} using the underlying
|
||||
* binding strategy.
|
||||
* @param bindTarget the target to bind the value to
|
||||
* @param valueType the value type (must not be {@code null})
|
||||
* @see Statement#bindNull
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -20,10 +20,10 @@ package org.springframework.r2dbc.core.binding;
|
|||
* Bind markers represent placeholders in SQL queries for substitution
|
||||
* for an actual parameter. Using bind markers allows creating safe queries
|
||||
* so query strings are not required to contain escaped values but rather
|
||||
* the driver encodes parameter in the appropriate representation.
|
||||
* the driver encodes the parameter in the appropriate representation.
|
||||
*
|
||||
* <p>{@link BindMarkers} is stateful and can be only used for a single binding
|
||||
* pass of one or more parameters. It maintains bind indexes/bind parameter names.
|
||||
* pass of one or more parameters. It maintains bind indexes or bind parameter names.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 5.3
|
||||
|
@ -41,7 +41,7 @@ public interface BindMarkers {
|
|||
|
||||
/**
|
||||
* Create a new {@link BindMarker} that accepts a {@code hint}.
|
||||
* Implementations are allowed to consider/ignore/filter
|
||||
* <p>Implementations are allowed to consider/ignore/filter
|
||||
* the name hint to create more expressive bind markers.
|
||||
* @param hint an optional name hint that can be used as part of the bind marker
|
||||
* @return a new {@link BindMarker}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -30,8 +30,8 @@ import org.springframework.util.LinkedCaseInsensitiveMap;
|
|||
|
||||
/**
|
||||
* Resolves a {@link BindMarkersFactory} from a {@link ConnectionFactory} using
|
||||
* {@link BindMarkerFactoryProvider}. Dialect resolution uses Spring's
|
||||
* {@link SpringFactoriesLoader spring.factories} to determine available extensions.
|
||||
* a {@link BindMarkerFactoryProvider}. Dialect resolution uses Spring's
|
||||
* {@link SpringFactoriesLoader spring.factories} file to determine available extensions.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 5.3
|
||||
|
@ -45,8 +45,8 @@ public final class BindMarkersFactoryResolver {
|
|||
|
||||
|
||||
/**
|
||||
* Retrieve a {@link BindMarkersFactory} by inspecting {@link ConnectionFactory}
|
||||
* and its metadata.
|
||||
* Retrieve a {@link BindMarkersFactory} by inspecting the supplied
|
||||
* {@link ConnectionFactory} and its metadata.
|
||||
* @param connectionFactory the connection factory to inspect
|
||||
* @return the resolved {@link BindMarkersFactory}
|
||||
* @throws NoBindMarkersFactoryException if no {@link BindMarkersFactory} can be resolved
|
||||
|
@ -69,18 +69,21 @@ public final class BindMarkersFactoryResolver {
|
|||
|
||||
|
||||
/**
|
||||
* SPI to extend Spring's default R2DBC BindMarkersFactory discovery mechanism.
|
||||
* Implementations of this interface are discovered through Spring's
|
||||
* SPI to extend Spring's default R2DBC {@link BindMarkersFactory} discovery
|
||||
* mechanism.
|
||||
*
|
||||
* <p>Implementations of this interface are discovered through Spring's
|
||||
* {@link SpringFactoriesLoader} mechanism.
|
||||
*
|
||||
* @see SpringFactoriesLoader
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface BindMarkerFactoryProvider {
|
||||
|
||||
/**
|
||||
* Return a {@link BindMarkersFactory} for a {@link ConnectionFactory}.
|
||||
* @param connectionFactory the connection factory to be used with the {@link BindMarkersFactory}
|
||||
* @return the {@link BindMarkersFactory} if the {@link BindMarkerFactoryProvider}
|
||||
* Return a {@link BindMarkersFactory} for the given {@link ConnectionFactory}.
|
||||
* @param connectionFactory the connection factory to be used with the {@code BindMarkersFactory}
|
||||
* @return the {@code BindMarkersFactory} if this {@code BindMarkerFactoryProvider}
|
||||
* can provide a bind marker factory object, otherwise {@code null}
|
||||
*/
|
||||
@Nullable BindMarkersFactory getBindMarkers(ConnectionFactory connectionFactory);
|
||||
|
@ -88,7 +91,7 @@ public final class BindMarkersFactoryResolver {
|
|||
|
||||
|
||||
/**
|
||||
* Exception thrown when {@link BindMarkersFactoryResolver} cannot resolve a
|
||||
* Exception thrown when a {@link BindMarkersFactoryResolver} cannot resolve a
|
||||
* {@link BindMarkersFactory}.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
@ -105,8 +108,11 @@ public final class BindMarkersFactoryResolver {
|
|||
|
||||
|
||||
/**
|
||||
* Built-in bind maker factories. Used typically as last {@link BindMarkerFactoryProvider}
|
||||
* when other providers register with a higher precedence.
|
||||
* Built-in bind marker factories.
|
||||
*
|
||||
* <p>Typically used as the last {@link BindMarkerFactoryProvider} when other
|
||||
* providers are registered with a higher precedence.
|
||||
*
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
@ -19,7 +19,7 @@ package org.springframework.r2dbc.core.binding;
|
|||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
|
||||
/**
|
||||
* Index-based bind marker. This implementation creates indexed bind
|
||||
* Index-based bind markers. This implementation creates indexed bind
|
||||
* markers using a numeric index and an optional prefix for bind markers
|
||||
* to be represented within the query string.
|
||||
*
|
||||
|
@ -43,14 +43,15 @@ class IndexedBindMarkers implements BindMarkers {
|
|||
|
||||
|
||||
/**
|
||||
* Create a new {@link IndexedBindMarker} instance given {@code prefix} and {@code beginWith}.
|
||||
* @param prefix bind parameter prefix
|
||||
* @param beginWith the first index to use
|
||||
* Create a new {@link IndexedBindMarker} instance for the given {@code prefix}
|
||||
* and {@code beginWith} value.
|
||||
* @param prefix the bind parameter prefix
|
||||
* @param beginIndex the first index to use
|
||||
*/
|
||||
IndexedBindMarkers(String prefix, int beginWith) {
|
||||
IndexedBindMarkers(String prefix, int beginIndex) {
|
||||
this.counter = 0;
|
||||
this.prefix = prefix;
|
||||
this.offset = beginWith;
|
||||
this.offset = beginIndex;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,15 +21,12 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import io.r2dbc.spi.Parameters;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import org.springframework.r2dbc.core.binding.BindMarkersFactory;
|
||||
import org.springframework.r2dbc.core.binding.BindTarget;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -320,34 +317,17 @@ class NamedParameterUtilsTests {
|
|||
assertThat(operation.toQuery())
|
||||
.isEqualTo("SELECT * FROM person where name = $1 or lastname = $1");
|
||||
|
||||
Map<Integer, Object> bindings = new HashMap<>();
|
||||
TrackingBindTarget trackingBindTarget = new TrackingBindTarget();
|
||||
|
||||
operation.bindTo(new BindTarget() {
|
||||
@Override
|
||||
public void bind(String identifier, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bind(int index, Object value) {
|
||||
bindings.put(index, value);
|
||||
}
|
||||
@Override
|
||||
public void bindNull(String identifier, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bindNull(int index, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
operation.bindTo(trackingBindTarget);
|
||||
|
||||
assertThat(bindings)
|
||||
assertThat(trackingBindTarget.bindings)
|
||||
.hasSize(1)
|
||||
.containsEntry(0, Parameters.in("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleEqualCollectionParameterReferencesForIndexedMarkersBindsValueOnce() {
|
||||
void multipleEqualCollectionParameterReferencesForIndexedMarkersBindsValuesOnce() {
|
||||
String sql = "SELECT * FROM person where name IN (:ids) or lastname IN (:ids)";
|
||||
|
||||
MapBindParameterSource source = new MapBindParameterSource(Map.of("ids",
|
||||
|
@ -357,71 +337,39 @@ class NamedParameterUtilsTests {
|
|||
assertThat(operation.toQuery())
|
||||
.isEqualTo("SELECT * FROM person where name IN ($1, $2, $3) or lastname IN ($1, $2, $3)");
|
||||
|
||||
MultiValueMap<Integer, Object> bindings = new LinkedMultiValueMap<>();
|
||||
TrackingBindTarget trackingBindTarget = new TrackingBindTarget();
|
||||
|
||||
operation.bindTo(new BindTarget() {
|
||||
@Override
|
||||
public void bind(String identifier, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bind(int index, Object value) {
|
||||
bindings.add(index, value);
|
||||
}
|
||||
@Override
|
||||
public void bindNull(String identifier, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bindNull(int index, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
operation.bindTo(trackingBindTarget);
|
||||
|
||||
assertThat(bindings)
|
||||
assertThat(trackingBindTarget.bindings)
|
||||
.hasSize(3)
|
||||
.containsEntry(0, List.of("foo"))
|
||||
.containsEntry(1, List.of("bar"))
|
||||
.containsEntry(2, List.of("baz"));
|
||||
.containsEntry(0, "foo")
|
||||
.containsEntry(1, "bar")
|
||||
.containsEntry(2, "baz");
|
||||
}
|
||||
|
||||
@Test // gh-34768
|
||||
@Disabled("Disabled until gh-34768 is addressed")
|
||||
void multipleEqualCollectionParameterReferencesForAnonymousMarkersBindsValueTwice() {
|
||||
void multipleEqualCollectionParameterReferencesForAnonymousMarkersBindsValuesTwice() {
|
||||
String sql = "SELECT * FROM fund_info WHERE fund_code IN (:fundCodes) OR fund_code IN (:fundCodes)";
|
||||
|
||||
MapBindParameterSource source = new MapBindParameterSource(Map.of("fundCodes", Parameters.in(List.of("foo"))));
|
||||
MapBindParameterSource source = new MapBindParameterSource(Map.of("fundCodes", Parameters.in(List.of("foo", "bar", "baz"))));
|
||||
PreparedOperation<String> operation = NamedParameterUtils.substituteNamedParameters(sql, ANONYMOUS_MARKERS, source);
|
||||
|
||||
assertThat(operation.toQuery())
|
||||
.isEqualTo("SELECT * FROM fund_info WHERE fund_code IN (?) OR fund_code IN (?)");
|
||||
.isEqualTo("SELECT * FROM fund_info WHERE fund_code IN (?, ?, ?) OR fund_code IN (?, ?, ?)");
|
||||
|
||||
Map<Integer, Object> bindings = new HashMap<>();
|
||||
TrackingBindTarget trackingBindTarget = new TrackingBindTarget();
|
||||
|
||||
operation.bindTo(new BindTarget() {
|
||||
@Override
|
||||
public void bind(String identifier, Object value) {}
|
||||
operation.bindTo(trackingBindTarget);
|
||||
|
||||
@Override
|
||||
public void bind(int index, Object value) {
|
||||
bindings.put(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindNull(String identifier, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindNull(int index, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(bindings)
|
||||
.hasSize(2)
|
||||
assertThat(trackingBindTarget.bindings)
|
||||
.hasSize(6)
|
||||
.containsEntry(0, "foo")
|
||||
.containsEntry(1, "foo");
|
||||
.containsEntry(1, "bar")
|
||||
.containsEntry(2, "baz")
|
||||
.containsEntry(3, "foo")
|
||||
.containsEntry(4, "bar")
|
||||
.containsEntry(5, "baz");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -434,28 +382,11 @@ class NamedParameterUtilsTests {
|
|||
assertThat(operation.toQuery())
|
||||
.isEqualTo("SELECT * FROM person where name = ? or lastname = ?");
|
||||
|
||||
Map<Integer, Object> bindings = new HashMap<>();
|
||||
TrackingBindTarget trackingBindTarget = new TrackingBindTarget();
|
||||
|
||||
operation.bindTo(new BindTarget() {
|
||||
@Override
|
||||
public void bind(String identifier, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bind(int index, Object value) {
|
||||
bindings.put(index, value);
|
||||
}
|
||||
@Override
|
||||
public void bindNull(String identifier, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bindNull(int index, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
operation.bindTo(trackingBindTarget);
|
||||
|
||||
assertThat(bindings)
|
||||
assertThat(trackingBindTarget.bindings)
|
||||
.hasSize(2)
|
||||
.containsEntry(0, Parameters.in("foo"))
|
||||
.containsEntry(1, Parameters.in("foo"));
|
||||
|
@ -471,28 +402,11 @@ class NamedParameterUtilsTests {
|
|||
assertThat(operation.toQuery())
|
||||
.isEqualTo("SELECT * FROM person where name = $1 or lastname = $1");
|
||||
|
||||
Map<Integer, Object> bindings = new HashMap<>();
|
||||
TrackingBindTarget trackingBindTarget = new TrackingBindTarget();
|
||||
|
||||
operation.bindTo(new BindTarget() {
|
||||
@Override
|
||||
public void bind(String identifier, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bind(int index, Object value) {
|
||||
bindings.put(index, value);
|
||||
}
|
||||
@Override
|
||||
public void bindNull(String identifier, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void bindNull(int index, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
operation.bindTo(trackingBindTarget);
|
||||
|
||||
assertThat(bindings)
|
||||
assertThat(trackingBindTarget.bindings)
|
||||
.hasSize(1)
|
||||
.containsEntry(0, Parameters.in(String.class));
|
||||
}
|
||||
|
@ -508,4 +422,28 @@ class NamedParameterUtilsTests {
|
|||
new MapBindParameterSource()).toQuery();
|
||||
}
|
||||
|
||||
|
||||
private static class TrackingBindTarget implements BindTarget {
|
||||
|
||||
final Map<Integer, Object> bindings = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void bind(String identifier, Object value) {}
|
||||
|
||||
@Override
|
||||
public void bind(int index, Object value) {
|
||||
this.bindings.put(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindNull(String identifier, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindNull(int index, Class<?> type) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue