Skip to content

Commit 4d37910

Browse files
toverdijkmp911de
authored andcommitted
Replaced stream() calls with for loops Added validation of binding in PostgresqlStatement.add() - failed unit test for PostgresqlTestKit.prepareStatementWithIncompleteBatchFails().
[#468]
1 parent ea12998 commit 4d37910

File tree

3 files changed

+56
-33
lines changed

3 files changed

+56
-33
lines changed

src/main/java/io/r2dbc/postgresql/PostgresqlStatement.java

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import io.r2dbc.postgresql.util.GeneratedValuesUtils;
3232
import io.r2dbc.postgresql.util.Operators;
3333
import io.r2dbc.postgresql.util.sql.BasicPostgresqlSqlLexer;
34-
import io.r2dbc.postgresql.util.sql.TokenType;
3534
import io.r2dbc.postgresql.util.sql.TokenizedSql;
3635
import io.r2dbc.spi.Statement;
3736
import reactor.core.publisher.Flux;
@@ -52,7 +51,7 @@
5251
import static io.r2dbc.postgresql.util.PredicateUtils.or;
5352

5453
/**
55-
* {@link Statement} using the <a href="https://www.postgresql.org/docs/current/static/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY">Extended Query Flow</a>.
54+
* {@link Statement}.
5655
*/
5756
final class PostgresqlStatement implements io.r2dbc.postgresql.api.PostgresqlStatement {
5857

@@ -85,6 +84,10 @@ final class PostgresqlStatement implements io.r2dbc.postgresql.api.PostgresqlSta
8584

8685
@Override
8786
public PostgresqlStatement add() {
87+
Binding binding = bindings.peekLast();
88+
if (binding != null) {
89+
binding.validate();
90+
}
8891
this.bindings.add(new Binding(tokenizedSql.getParameterCount()));
8992
return this;
9093
}
@@ -99,7 +102,7 @@ public PostgresqlStatement bind(int index, Object value) {
99102
Assert.requireNonNull(value, "value must not be null");
100103

101104
BindingLogger.logBind(this.connectionContext, index, value);
102-
getCurrentOrNewBinding().add(index, this.resources.getCodecs().encode(value));
105+
getCurrentOrFirstBinding().add(index, this.resources.getCodecs().encode(value));
103106
return this;
104107
}
105108

@@ -112,17 +115,17 @@ public PostgresqlStatement bindNull(String identifier, Class<?> type) {
112115
public PostgresqlStatement bindNull(int index, Class<?> type) {
113116
Assert.requireNonNull(type, "type must not be null");
114117

115-
if(index >= tokenizedSql.getParameterCount()){
118+
if (index >= tokenizedSql.getParameterCount()) {
116119
throw new UnsupportedOperationException(String.format("Cannot bind parameter %d, statement has %d parameters", index, this.tokenizedSql.getParameterCount()));
117120
}
118121

119122
BindingLogger.logBindNull(this.connectionContext, index, type);
120-
getCurrentOrNewBinding().add(index, this.resources.getCodecs().encodeNull(type));
123+
getCurrentOrFirstBinding().add(index, this.resources.getCodecs().encodeNull(type));
121124
return this;
122125
}
123126

124127
@Nonnull
125-
private Binding getCurrentOrNewBinding() {
128+
private Binding getCurrentOrFirstBinding() {
126129
Binding binding = bindings.peekLast();
127130
if (binding == null) {
128131
Binding newBinding = new Binding(tokenizedSql.getParameterCount());
@@ -145,20 +148,12 @@ public Flux<io.r2dbc.postgresql.api.PostgresqlResult> execute() {
145148
public PostgresqlStatement returnGeneratedValues(String... columns) {
146149
Assert.requireNonNull(columns, "columns must not be null");
147150

148-
boolean hasReturning = this.tokenizedSql.getStatements().stream()
149-
.flatMap(s -> s.getTokens().stream())
150-
.anyMatch(token -> (token.getType() == TokenType.DEFAULT)
151-
&& (token.getValue().equalsIgnoreCase("RETURNING")));
151+
boolean hasReturning = this.tokenizedSql.hasDefaultTokenValue("RETURNING");
152152
if (hasReturning) {
153153
throw new IllegalStateException("Statement already includes RETURNING clause");
154154
}
155-
boolean isSupporting = this.tokenizedSql.getStatements().stream()
156-
.flatMap(s -> s.getTokens().stream())
157-
.anyMatch(e -> e.getType() == TokenType.DEFAULT
158-
&& (e.getValue().equalsIgnoreCase("DELETE")
159-
|| e.getValue().equalsIgnoreCase("INSERT")
160-
|| e.getValue().equalsIgnoreCase("UPDATE")));
161155

156+
boolean isSupporting = this.tokenizedSql.hasDefaultTokenValue("DELETE", "INSERT", "UPDATE");
162157
if (!isSupporting) {
163158
throw new IllegalStateException("Statement is not a DELETE, INSERT, or UPDATE command");
164159
}
@@ -185,13 +180,13 @@ public String toString() {
185180
}
186181

187182
Binding getCurrentBinding() {
188-
return getCurrentOrNewBinding();
183+
return getCurrentOrFirstBinding();
189184
}
190185

191186
private int getIdentifierIndex(String identifier) {
192187
Assert.requireNonNull(identifier, "identifier must not be null");
193188
Assert.requireType(identifier, String.class, "identifier must be a String");
194-
if(!identifier.startsWith("$")){
189+
if (!identifier.startsWith("$")) {
195190
throw new NoSuchElementException(String.format("\"%s\" is not a valid identifier", identifier));
196191
}
197192
try {

src/main/java/io/r2dbc/postgresql/util/sql/TokenizedSql.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public TokenizedSql(String sql, List<TokenizedStatement> statements) {
3232
this.sql = sql;
3333
this.statements = statements;
3434
this.statementCount = statements.size();
35-
this.parameterCount = statements.stream().mapToInt(TokenizedStatement::getParameterCount).sum();
35+
this.parameterCount = getParameterCount(statements);
3636
}
3737

3838
public List<TokenizedStatement> getStatements() {
@@ -51,4 +51,27 @@ public String getSql() {
5151
return sql;
5252
}
5353

54+
private static int getParameterCount(List<TokenizedStatement> statements) {
55+
int sum = 0;
56+
for (TokenizedStatement statement : statements){
57+
sum += statement.getParameterCount();
58+
}
59+
return sum;
60+
}
61+
62+
public boolean hasDefaultTokenValue(String... tokenValues) {
63+
for (TokenizedStatement statement : statements) {
64+
for (Token token : statement.getTokens()) {
65+
if (token.getType() == TokenType.DEFAULT) {
66+
for (String value : tokenValues) {
67+
if (token.getValue().equalsIgnoreCase(value)) {
68+
return true;
69+
}
70+
}
71+
}
72+
}
73+
}
74+
return false;
75+
}
76+
5477
}

src/main/java/io/r2dbc/postgresql/util/sql/TokenizedStatement.java

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
package io.r2dbc.postgresql.util.sql;
1818

19+
import java.util.HashSet;
1920
import java.util.List;
21+
import java.util.Set;
22+
import java.util.TreeSet;
2023
import java.util.stream.Collectors;
2124

2225
public class TokenizedStatement {
@@ -77,26 +80,28 @@ public String toString() {
7780
}
7881

7982
private static int readParameterCount(List<Token> tokens) {
80-
List<Integer> parameterTokens = tokens.stream()
81-
.filter(t -> t.getType() == TokenType.PARAMETER)
82-
.map(t -> {
83-
try {
84-
return Integer.parseInt(t.getValue().substring(1));
85-
} catch (NumberFormatException | IndexOutOfBoundsException e) {
86-
throw new IllegalArgumentException("Illegal parameter token: " + t.getValue());
87-
}
88-
})
89-
.distinct()
90-
.sorted()
91-
.collect(Collectors.toList());
83+
Set<Integer> parameters = new TreeSet<>();
84+
85+
for (Token token : tokens) {
86+
if (token.getType() != TokenType.PARAMETER) {
87+
continue;
88+
}
89+
try {
90+
int i = Integer.parseInt(token.getValue().substring(1));
91+
parameters.add(i);
92+
} catch (NumberFormatException | IndexOutOfBoundsException e) {
93+
throw new IllegalArgumentException("Illegal parameter token: " + token.getValue());
94+
}
95+
}
96+
9297
int current = 1;
93-
for (Integer i : parameterTokens) {
98+
for (Integer i : parameters) {
9499
if (i != current) {
95100
throw new IllegalArgumentException("Missing parameter number $" + i);
96101
}
97102
current++;
98103
}
99-
return parameterTokens.size();
104+
return parameters.size();
100105
}
101106

102107
}

0 commit comments

Comments
 (0)