Skip to content

Commit af38817

Browse files
author
Tomáš Kraus
committed
Issue helidon-io#8613 - Consider missing named parameters values in the parameters Map as null
Signed-off-by: Tomáš Kraus <tomas.kraus@oracle.com>
1 parent 0041016 commit af38817

10 files changed

Lines changed: 102 additions & 35 deletions

File tree

dbclient/dbclient/src/main/java/io/helidon/dbclient/DbClientBuilderBase.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@ public abstract class DbClientBuilderBase<T extends DbClientBuilderBase<T>>
3939
private String url;
4040
private String username;
4141
private String password;
42+
private boolean missingMapParametersAsNull;
4243
private DbStatements statements;
4344
private MapperManager mapperManager;
4445
private DbMapperManager dbMapperManager;
@@ -49,6 +50,7 @@ public abstract class DbClientBuilderBase<T extends DbClientBuilderBase<T>>
4950
*/
5051
protected DbClientBuilderBase() {
5152
this.clientServices = new LinkedList<>();
53+
this.missingMapParametersAsNull = false;
5254
}
5355

5456
@Override
@@ -71,6 +73,7 @@ public DbClient build() {
7173

7274
@Override
7375
public T config(Config config) {
76+
config.get("missing-map-parameters-as-null").as(Boolean.class).ifPresent(this::missingMapParametersAsNull);
7477
config.get("statements").map(DbStatements::create).ifPresent(this::statements);
7578
return identity();
7679
}
@@ -93,6 +96,12 @@ public T password(String password) {
9396
return identity();
9497
}
9598

99+
@Override
100+
public T missingMapParametersAsNull(boolean missingMapParametersAsNull) {
101+
this.missingMapParametersAsNull = missingMapParametersAsNull;
102+
return identity();
103+
}
104+
96105
@Override
97106
public T statements(DbStatements statements) {
98107
this.statements = statements;
@@ -185,6 +194,17 @@ public String password() {
185194
return password;
186195
}
187196

197+
/**
198+
* Configured missing values in named parameters {@link java.util.Map} handling.
199+
*
200+
* @return when set to {@code true}, named parameters value missing in the {@code Map} is considered
201+
* as {@code null}, when set to {@code false}, any parameter value missing in the {@code Map}
202+
* will cause an exception.
203+
*/
204+
public boolean missingMapParametersAsNull() {
205+
return missingMapParametersAsNull;
206+
}
207+
188208
/**
189209
* Get configured statements to be used by database provider.
190210
*

dbclient/dbclient/src/main/java/io/helidon/dbclient/DbClientContext.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2020, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ public class DbClientContext implements DbContext {
2929
private final DbMapperManager dbMapperManager;
3030
private final MapperManager mapperManager;
3131
private final List<DbClientService> clientServices;
32+
private final boolean missingMapParametersAsNull;
3233
private final DbStatements statements;
3334
private final String dbType;
3435

@@ -42,10 +43,16 @@ protected DbClientContext(
4243
this.dbMapperManager = builder.dbMapperManager;
4344
this.mapperManager = builder.mapperManager;
4445
this.clientServices = builder.clientServices;
46+
this.missingMapParametersAsNull = builder.missingMapParametersAsNull;
4547
this.statements = builder.statements;
4648
this.dbType = builder.dbType;
4749
}
4850

51+
@Override
52+
public boolean missingMapParametersAsNull() {
53+
return missingMapParametersAsNull;
54+
}
55+
4956
@Override
5057
public DbStatements statements() {
5158
return statements;
@@ -107,13 +114,15 @@ public abstract static class BuilderBase<B extends BuilderBase<B, T>, T extends
107114
private DbMapperManager dbMapperManager;
108115
private MapperManager mapperManager;
109116
private List<DbClientService> clientServices = List.of();
117+
private boolean missingMapParametersAsNull;
110118
private DbStatements statements;
111119
private String dbType;
112120

113121
/**
114122
* Creates an instance of base builder for {@link DbClientContext}.
115123
*/
116124
protected BuilderBase() {
125+
this.missingMapParametersAsNull = false;
117126
}
118127

119128
/**
@@ -149,6 +158,20 @@ public B clientServices(List<DbClientService> clientServices) {
149158
return identity();
150159
}
151160

161+
/**
162+
* Missing values in named parameters {@link java.util.Map} are considered as null values.
163+
* When set to {@code true}, named parameters value missing in the {@code Map} is considered
164+
* as {@code null}. When set to {@code false}, any parameter value missing in the {@code Map}
165+
* will cause an exception.
166+
* @param missingMapParametersAsNull whether missing values in named parameters {@code Map}
167+
* are considered as null values
168+
* @return updated builder instance
169+
*/
170+
public B missingMapParametersAsNull(boolean missingMapParametersAsNull) {
171+
this.missingMapParametersAsNull = missingMapParametersAsNull;
172+
return identity();
173+
}
174+
152175
/**
153176
* Configure the db statements to use.
154177
*

dbclient/dbclient/src/main/java/io/helidon/dbclient/DbContext.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,15 @@
2424
*/
2525
public interface DbContext {
2626

27+
/**
28+
* Configured missing values in named parameters {@link java.util.Map} handling.
29+
*
30+
* @return when set to {@code true}, named parameters value missing in the {@code Map} is considered
31+
* as {@code null}, when set to {@code false}, any parameter value missing in the {@code Map}
32+
* will cause an exception.
33+
*/
34+
boolean missingMapParametersAsNull();
35+
2736
/**
2837
* Configured statements.
2938
*

dbclient/dbclient/src/main/java/io/helidon/dbclient/DbExecuteContext.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,6 +58,11 @@ public String statement() {
5858
return statement;
5959
}
6060

61+
@Override
62+
public boolean missingMapParametersAsNull() {
63+
return clientContext.missingMapParametersAsNull();
64+
}
65+
6166
@Override
6267
public DbStatements statements() {
6368
return clientContext.statements();

dbclient/dbclient/src/main/java/io/helidon/dbclient/spi/DbClientBuilder.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2019, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -64,6 +64,17 @@ public interface DbClientBuilder<T extends DbClientBuilder<T>> extends Builder<T
6464
*/
6565
T password(String password);
6666

67+
/**
68+
* Missing values in named parameters {@link java.util.Map} are considered as null values.
69+
* When set to {@code true}, named parameters value missing in the {@code Map} is considered
70+
* as {@code null}. When set to {@code false}, any parameter value missing in the {@code Map}
71+
* will cause an exception.
72+
* @param missingMapParametersAsNull whether missing values in named parameters {@code Map}
73+
* are considered as null values
74+
* @return updated builder instance
75+
*/
76+
T missingMapParametersAsNull(boolean missingMapParametersAsNull);
77+
6778
/**
6879
* Statements to use either from configuration
6980
* or manually configured.

dbclient/jdbc/src/main/java/io/helidon/dbclient/jdbc/JdbcClient.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class JdbcClient extends DbClientBase implements DbClient {
3636
*/
3737
JdbcClient(JdbcClientBuilder builder) {
3838
super(JdbcClientContext.jdbcBuilder()
39+
.missingMapParametersAsNull(builder.missingMapParametersAsNull())
3940
.statements(builder.statements())
4041
.dbMapperManager(builder.dbMapperManager())
4142
.mapperManager(builder.mapperManager())

dbclient/jdbc/src/main/java/io/helidon/dbclient/jdbc/JdbcStatement.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,13 @@ private PreparedStatement prepareNamedStatement(String stmtName, String stmt, Ma
152152
setParameter(preparedStatement, i, value);
153153
i++;
154154
} else {
155-
throw new DbClientException(namedStatementErrorMessage(namesOrder, parameters));
155+
if (context().missingMapParametersAsNull()) {
156+
LOGGER.log(Level.TRACE, String.format("Mapped parameter %d: %s -> null", i, name));
157+
setParameter(preparedStatement, i, null);
158+
i++;
159+
} else {
160+
throw new DbClientException(namedStatementErrorMessage(namesOrder, parameters));
161+
}
156162
}
157163
}
158164
return preparedStatement;

tests/integration/dbclient/common/src/main/java/io/helidon/tests/integration/dbclient/common/tests/QueryStatementIT.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2019, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,9 @@
2929
import org.junit.jupiter.api.extension.ExtendWith;
3030

3131
import static io.helidon.tests.integration.dbclient.common.utils.VerifyData.verifyPokemonsIdRange;
32+
import static org.hamcrest.MatcherAssert.assertThat;
33+
import static org.hamcrest.Matchers.hasSize;
34+
import static org.hamcrest.Matchers.notNullValue;
3235

3336
/**
3437
* Test DbStatementQuery methods.
@@ -87,6 +90,19 @@ public void testQueryMapParams() {
8790
verifyPokemonsIdRange(rows, 1, 7);
8891
}
8992

93+
@Test
94+
public void testQueryMapMissingParams() {
95+
Map<String, Integer> params = new HashMap<>(2);
96+
params.put("id", 1);
97+
Stream<DbRow> rows = dbClient.execute()
98+
.createNamedQuery("select-pokemons-idname-named-arg")
99+
.params(params)
100+
.execute();
101+
assertThat(rows, notNullValue());
102+
List<DbRow> rowsList = rows.toList();
103+
assertThat(rowsList, hasSize(0));
104+
}
105+
90106
/**
91107
* Verify {@code addParam(Object parameter)} parameters setting method.
92108
*/

tests/integration/dbclient/h2/pom.xml

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,27 +129,6 @@
129129
<include>io.helidon.tests.integration.dbclient.common.tests.*IT</include>
130130
</includes>
131131
</configuration>
132-
<executions>
133-
<execution>
134-
<id>test</id>
135-
<phase>integration-test</phase>
136-
<goals>
137-
<goal>integration-test</goal>
138-
</goals>
139-
</execution>
140-
</executions>
141-
</plugin>
142-
<!--plugin>
143-
<groupId>org.apache.maven.plugins</groupId>
144-
<artifactId>maven-failsafe-plugin</artifactId>
145-
<configuration>
146-
<redirectTestOutputToFile>${maven.test.redirectTestOutputToFile}</redirectTestOutputToFile>
147-
<parallel>methods</parallel>
148-
<threadCount>10</threadCount>
149-
<systemPropertyVariables>
150-
<junit.jupiter.extensions.autodetection.enabled>true</junit.jupiter.extensions.autodetection.enabled>
151-
</systemPropertyVariables>
152-
</configuration>
153132
<executions>
154133
<execution>
155134
<id>test</id>
@@ -158,14 +137,9 @@
158137
<goal>integration-test</goal>
159138
<goal>verify</goal>
160139
</goals>
161-
<configuration>
162-
<includes>
163-
<include>**/*SuiteIT</include>
164-
</includes>
165-
</configuration>
166140
</execution>
167141
</executions>
168-
</plugin-->
142+
</plugin>
169143
</plugins>
170144
</build>
171145
</project>

tests/integration/dbclient/h2/src/test/resources/h2.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2019, 2023 Oracle and/or its affiliates.
2+
# Copyright (c) 2019, 2024 Oracle and/or its affiliates.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ db:
1919
port: 9092
2020
password: "password"
2121
database: "test"
22+
missing-map-parameters-as-null: true
2223
connection:
2324
url: jdbc:h2:tcp://${db.host}:${db.port}/${db.database};DATABASE_TO_UPPER=FALSE
2425
health-check:
@@ -56,6 +57,7 @@ db:
5657
select-pokemons-idrng-named-arg: "SELECT id, name FROM Pokemons WHERE id > :idmin AND id < :idmax"
5758
select-pokemons-idrng-order-arg: "SELECT id, name FROM Pokemons WHERE id > ? AND id < ?"
5859
select-pokemons-error-arg: "SELECT id, name FROM Pokemons WHERE id > :id AND name = ?"
60+
select-pokemons-idname-named-arg: "SELECT id, name FROM Pokemons WHERE name=:name AND id=:id"
5961

6062
test:
6163
ping-dml: false

0 commit comments

Comments
 (0)