#73 - Introduce BindTarget.

We now apply bindings to a BindTarget that can be overridden without the need to implement all Statement methods.

PreparedOperation no longer has a direct dependency on R2DBC Statement.

Original pull request: #82.
This commit is contained in:
Mark Paluch
2019-05-06 13:43:42 +02:00
parent 02e0cb5026
commit 88945d7d71
25 changed files with 389 additions and 653 deletions

View File

@@ -18,10 +18,10 @@ package org.springframework.data.r2dbc.dialect;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import io.r2dbc.spi.Statement;
import org.junit.Test;
import org.springframework.data.r2dbc.domain.BindTarget;
/**
* Unit tests for {@link AnonymousBindMarkers}.
*
@@ -44,17 +44,17 @@ public class AnonymousBindMarkersUnitTests {
@Test // gh-75
public void shouldBindByIndex() {
Statement statement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindMarkers bindMarkers = BindMarkersFactory.anonymous("?").create();
BindMarker first = bindMarkers.next();
BindMarker second = bindMarkers.next();
second.bind(statement, "foo");
first.bindNull(statement, Object.class);
second.bind(bindTarget, "foo");
first.bindNull(bindTarget, Object.class);
verify(statement).bindNull(0, Object.class);
verify(statement).bind(1, "foo");
verify(bindTarget).bindNull(0, Object.class);
verify(bindTarget).bind(1, "foo");
}
}

View File

@@ -3,10 +3,10 @@ package org.springframework.data.r2dbc.dialect;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import io.r2dbc.spi.Statement;
import org.junit.Test;
import org.springframework.data.r2dbc.domain.BindTarget;
/**
* Unit tests for {@link IndexedBindMarkers}.
*
@@ -29,20 +29,20 @@ public class IndexedBindMarkersUnitTests {
@Test // gh-15
public void shouldCreateNewBindMarkersWithOffset() {
Statement statement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindMarkers bindMarkers = BindMarkersFactory.indexed("$", 1).create();
BindMarker first = bindMarkers.next();
first.bind(statement, "foo");
first.bind(bindTarget, "foo");
BindMarker second = bindMarkers.next();
second.bind(statement, "bar");
second.bind(bindTarget, "bar");
assertThat(first.getPlaceholder()).isEqualTo("$1");
assertThat(second.getPlaceholder()).isEqualTo("$2");
verify(statement).bind(0, "foo");
verify(statement).bind(1, "bar");
verify(bindTarget).bind(0, "foo");
verify(bindTarget).bind(1, "bar");
}
@Test // gh-15
@@ -65,28 +65,28 @@ public class IndexedBindMarkersUnitTests {
@Test // gh-15
public void bindValueShouldBindByIndex() {
Statement statement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindMarkers bindMarkers = BindMarkersFactory.indexed("$", 0).create();
bindMarkers.next().bind(statement, "foo");
bindMarkers.next().bind(statement, "bar");
bindMarkers.next().bind(bindTarget, "foo");
bindMarkers.next().bind(bindTarget, "bar");
verify(statement).bind(0, "foo");
verify(statement).bind(1, "bar");
verify(bindTarget).bind(0, "foo");
verify(bindTarget).bind(1, "bar");
}
@Test // gh-15
public void bindNullShouldBindByIndex() {
Statement statement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindMarkers bindMarkers = BindMarkersFactory.indexed("$", 0).create();
bindMarkers.next(); // ignore
bindMarkers.next().bindNull(statement, Integer.class);
bindMarkers.next().bindNull(bindTarget, Integer.class);
verify(statement).bindNull(1, Integer.class);
verify(bindTarget).bindNull(1, Integer.class);
}
}

View File

@@ -3,10 +3,10 @@ package org.springframework.data.r2dbc.dialect;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import io.r2dbc.spi.Statement;
import org.junit.Test;
import org.springframework.data.r2dbc.domain.BindTarget;
/**
* Unit tests for {@link NamedBindMarkers}.
*
@@ -85,27 +85,27 @@ public class NamedBindMarkersUnitTests {
@Test // gh-15
public void bindValueShouldBindByName() {
Statement statement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindMarkers bindMarkers = BindMarkersFactory.named("@", "p", 32).create();
bindMarkers.next().bind(statement, "foo");
bindMarkers.next().bind(statement, "bar");
bindMarkers.next().bind(bindTarget, "foo");
bindMarkers.next().bind(bindTarget, "bar");
verify(statement).bind("p0", "foo");
verify(statement).bind("p1", "bar");
verify(bindTarget).bind("p0", "foo");
verify(bindTarget).bind("p1", "bar");
}
@Test // gh-15
public void bindNullShouldBindByName() {
Statement statement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindMarkers bindMarkers = BindMarkersFactory.named("@", "p", 32).create();
bindMarkers.next(); // ignore
bindMarkers.next().bindNull(statement, Integer.class);
bindMarkers.next().bindNull(bindTarget, Integer.class);
verify(statement).bindNull("p1", Integer.class);
verify(bindTarget).bindNull("p1", Integer.class);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.data.r2dbc.function;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import io.r2dbc.spi.Statement;
import java.util.Arrays;
import java.util.HashMap;
import org.junit.Test;
import org.springframework.data.r2dbc.dialect.BindMarkersFactory;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.dialect.SqlServerDialect;
import org.springframework.data.r2dbc.domain.BindTarget;
/**
* Unit tests for {@link NamedParameterUtils}.
@@ -94,15 +94,15 @@ public class NamedParameterUtilsUnitTests {
namedParams.addValue("a",
Arrays.asList(new Object[] { "Walter", "Heisenberg" }, new Object[] { "Walt Jr.", "Flynn" }));
Statement mockStatement = mock(Statement.class);
BindTarget bindTarget = mock(BindTarget.class);
BindableOperation operation = NamedParameterUtils.substituteNamedParameters("xxx :a", BIND_MARKERS, namedParams);
operation.bind(mockStatement, "a", namedParams.getValue("a"));
operation.bind(bindTarget, "a", namedParams.getValue("a"));
verify(mockStatement).bind(0, "Walter");
verify(mockStatement).bind(1, "Heisenberg");
verify(mockStatement).bind(2, "Walt Jr.");
verify(mockStatement).bind(3, "Flynn");
verify(bindTarget).bind(0, "Walter");
verify(bindTarget).bind(1, "Heisenberg");
verify(bindTarget).bind(2, "Walt Jr.");
verify(bindTarget).bind(3, "Flynn");
}
@Test // gh-23

View File

@@ -24,9 +24,11 @@ import io.r2dbc.spi.Statement;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.domain.PreparedOperation;
import org.springframework.data.r2dbc.domain.SettableValue;
import org.springframework.data.relational.core.dialect.RenderContextFactory;
import org.springframework.data.relational.core.sql.Delete;
@@ -49,7 +51,8 @@ public class StatementFactoryUnitTests {
Statement statementMock = mock(Statement.class);
Connection connectionMock = mock(Connection.class);
{
@Before
public void before() {
when(connectionMock.createStatement(anyString())).thenReturn(statementMock);
}
@@ -61,7 +64,7 @@ public class StatementFactoryUnitTests {
assertThat(select.getSource()).isInstanceOf(Select.class);
assertThat(select.toQuery()).isEqualTo("SELECT foo.bar, foo.baz FROM foo");
select.createBoundStatement(connectionMock);
createBoundStatement(select, connectionMock);
verifyZeroInteractions(statementMock);
}
@@ -76,7 +79,7 @@ public class StatementFactoryUnitTests {
assertThat(select.getSource()).isInstanceOf(Select.class);
assertThat(select.toQuery()).isEqualTo("SELECT foo.bar, foo.baz FROM foo WHERE foo.doe = $1");
select.createBoundStatement(connectionMock);
createBoundStatement(select, connectionMock);
verify(statementMock).bind(0, "John");
verifyNoMoreInteractions(statementMock);
@@ -93,7 +96,7 @@ public class StatementFactoryUnitTests {
assertThat(select.getSource()).isInstanceOf(Select.class);
assertThat(select.toQuery()).isEqualTo("SELECT foo.bar, foo.baz FROM foo WHERE foo.doe = $1 AND foo.baz = $2");
select.createBoundStatement(connectionMock);
createBoundStatement(select, connectionMock);
verify(statementMock).bind(0, "John");
verify(statementMock).bind(1, "Jake");
@@ -110,7 +113,7 @@ public class StatementFactoryUnitTests {
assertThat(select.getSource()).isInstanceOf(Select.class);
assertThat(select.toQuery()).isEqualTo("SELECT foo.bar, foo.baz FROM foo WHERE foo.doe IS NULL");
select.createBoundStatement(connectionMock);
createBoundStatement(select, connectionMock);
verifyZeroInteractions(statementMock);
}
@@ -124,7 +127,7 @@ public class StatementFactoryUnitTests {
assertThat(select.getSource()).isInstanceOf(Select.class);
assertThat(select.toQuery()).isEqualTo("SELECT foo.bar, foo.baz FROM foo WHERE foo.doe IN ($1, $2)");
select.createBoundStatement(connectionMock);
createBoundStatement(select, connectionMock);
verify(statementMock).bind(0, "John");
verify(statementMock).bind(1, "Jake");
verifyNoMoreInteractions(statementMock);
@@ -147,9 +150,8 @@ public class StatementFactoryUnitTests {
assertThat(insert.getSource()).isInstanceOf(Insert.class);
assertThat(insert.toQuery()).isEqualTo("INSERT INTO foo (bar) VALUES ($1)");
insert.createBoundStatement(connectionMock);
createBoundStatement(insert, connectionMock);
verify(statementMock).bind(0, "Foo");
verify(statementMock).returnGeneratedValues(any(String[].class));
verifyNoMoreInteractions(statementMock);
}
@@ -170,7 +172,7 @@ public class StatementFactoryUnitTests {
assertThat(update.getSource()).isInstanceOf(Update.class);
assertThat(update.toQuery()).isEqualTo("UPDATE foo SET bar = $1");
update.createBoundStatement(connectionMock);
createBoundStatement(update, connectionMock);
verify(statementMock).bind(0, "Foo");
verifyNoMoreInteractions(statementMock);
}
@@ -185,7 +187,7 @@ public class StatementFactoryUnitTests {
assertThat(update.getSource()).isInstanceOf(Update.class);
assertThat(update.toQuery()).isEqualTo("UPDATE foo SET bar = $1");
update.createBoundStatement(connectionMock);
createBoundStatement(update, connectionMock);
verify(statementMock).bindNull(0, String.class);
verifyNoMoreInteractions(statementMock);
@@ -202,7 +204,7 @@ public class StatementFactoryUnitTests {
assertThat(update.getSource()).isInstanceOf(Update.class);
assertThat(update.toQuery()).isEqualTo("UPDATE foo SET bar = $1 WHERE foo.baz = $2");
update.createBoundStatement(connectionMock);
createBoundStatement(update, connectionMock);
verify(statementMock).bind(0, "Foo");
verify(statementMock).bind(1, "Baz");
verifyNoMoreInteractions(statementMock);
@@ -218,7 +220,7 @@ public class StatementFactoryUnitTests {
assertThat(delete.getSource()).isInstanceOf(Delete.class);
assertThat(delete.toQuery()).isEqualTo("DELETE FROM foo WHERE foo.doe = $1");
delete.createBoundStatement(connectionMock);
createBoundStatement(delete, connectionMock);
verify(statementMock).bind(0, "John");
verifyNoMoreInteractions(statementMock);
}
@@ -234,7 +236,7 @@ public class StatementFactoryUnitTests {
assertThat(delete.getSource()).isInstanceOf(Delete.class);
assertThat(delete.toQuery()).isEqualTo("DELETE FROM foo WHERE foo.doe = $1 AND foo.baz = $2");
delete.createBoundStatement(connectionMock);
createBoundStatement(delete, connectionMock);
verify(statementMock).bind(0, "John");
verify(statementMock).bind(1, "Jake");
verifyNoMoreInteractions(statementMock);
@@ -250,7 +252,13 @@ public class StatementFactoryUnitTests {
assertThat(delete.getSource()).isInstanceOf(Delete.class);
assertThat(delete.toQuery()).isEqualTo("DELETE FROM foo WHERE foo.doe IS NULL");
delete.createBoundStatement(connectionMock);
createBoundStatement(delete, connectionMock);
verifyZeroInteractions(statementMock);
}
void createBoundStatement(PreparedOperation<?> operation, Connection connection) {
Statement statement = connection.createStatement(operation.toQuery());
operation.bindTo(new DefaultDatabaseClient.StatementWrapper(statement));
}
}