Skip to content

Commit 071f159

Browse files
authored
Support OraclePrepareOptions config from JSON (#1099)
This allows to create generic PrepareOptions with Oracle specific data in JSON. Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
1 parent 0db0b36 commit 071f159

File tree

8 files changed

+240
-100
lines changed

8 files changed

+240
-100
lines changed

vertx-oracle-client/src/main/java/io/vertx/oracleclient/OraclePrepareOptions.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
/*
2+
* Copyright (c) 2011-2021 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
112
package io.vertx.oracleclient;
213

314
import io.vertx.codegen.annotations.DataObject;
@@ -17,14 +28,34 @@ public OraclePrepareOptions() {
1728
}
1829

1930
public OraclePrepareOptions(OraclePrepareOptions options) {
31+
super(options);
2032
this.autoGeneratedKeys = options.autoGeneratedKeys;
2133
this.autoGeneratedKeysIndexes = options.autoGeneratedKeysIndexes != null ? options.autoGeneratedKeysIndexes.copy() : null;
2234
}
2335

2436
public OraclePrepareOptions(JsonObject json) {
37+
super(json);
2538
OraclePrepareOptionsConverter.fromJson(json, this);
2639
}
2740

41+
/**
42+
* Creates a new instance of {@link OraclePrepareOptions} from the provided {@link PrepareOptions}.
43+
*
44+
* @param prepareOptions an instance of {@link PrepareOptions}
45+
* @return a copy of {@code prepareOptions} or {@code null} if {@code prepareOptions} is {@code null}
46+
*/
47+
public static OraclePrepareOptions createFrom(PrepareOptions prepareOptions) {
48+
OraclePrepareOptions oraclePrepareOptions;
49+
if (prepareOptions == null) {
50+
oraclePrepareOptions = null;
51+
} else if (prepareOptions instanceof OraclePrepareOptions) {
52+
oraclePrepareOptions = new OraclePrepareOptions((OraclePrepareOptions) prepareOptions);
53+
} else {
54+
oraclePrepareOptions = new OraclePrepareOptions(prepareOptions.toJson());
55+
}
56+
return oraclePrepareOptions;
57+
}
58+
2859
public boolean isAutoGeneratedKeys() {
2960
return autoGeneratedKeys;
3061
}
@@ -42,4 +73,19 @@ public OraclePrepareOptions setAutoGeneratedKeysIndexes(JsonArray autoGeneratedK
4273
this.autoGeneratedKeysIndexes = autoGeneratedKeysIndexes;
4374
return this;
4475
}
76+
77+
@Override
78+
public JsonObject toJson() {
79+
JsonObject jsonObject = new JsonObject();
80+
OraclePrepareOptionsConverter.toJson(this, jsonObject);
81+
return jsonObject;
82+
}
83+
84+
@Override
85+
public String toString() {
86+
return "OraclePrepareOptions{" +
87+
"autoGeneratedKeys=" + autoGeneratedKeys +
88+
", autoGeneratedKeysIndexes=" + autoGeneratedKeysIndexes +
89+
'}';
90+
}
4591
}

vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/CommandHandler.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ private <R> Future<Boolean> handle(io.vertx.sqlclient.impl.command.SimpleQueryCo
109109
}
110110

111111
private Future<PreparedStatement> handle(io.vertx.sqlclient.impl.command.PrepareStatementCommand command) {
112-
OraclePrepareOptions options = command.options() instanceof OraclePrepareOptions ? (OraclePrepareOptions) command.options() : null;
113-
PrepareStatementCommand action = new PrepareStatementCommand(options, command.sql());
112+
PrepareStatementCommand action = new PrepareStatementCommand(OraclePrepareOptions.createFrom(command.options()), command.sql());
114113
return action.execute(connection, context);
115114
}
116115

vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/commands/OracleCursorQueryCommand.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import io.vertx.oracleclient.OraclePrepareOptions;
1616
import io.vertx.oracleclient.impl.Helper;
1717
import io.vertx.oracleclient.impl.RowReader;
18-
import io.vertx.sqlclient.PrepareOptions;
1918
import io.vertx.sqlclient.Tuple;
2019
import io.vertx.sqlclient.impl.command.ExtendedQueryCommand;
2120
import oracle.jdbc.OraclePreparedStatement;
@@ -39,8 +38,7 @@ public OracleCursorQueryCommand(ExtendedQueryCommand<R> command, Tuple params) {
3938

4039
@Override
4140
protected OraclePrepareOptions prepareOptions() {
42-
PrepareOptions prepareOptions = command.options();
43-
return prepareOptions instanceof OraclePrepareOptions ? (OraclePrepareOptions) prepareOptions : null;
41+
return OraclePrepareOptions.createFrom(command.options());
4442
}
4543

4644
@Override

vertx-oracle-client/src/main/java/io/vertx/oracleclient/impl/commands/OraclePreparedQuery.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import io.vertx.core.impl.ContextInternal;
1515
import io.vertx.oracleclient.OraclePrepareOptions;
1616
import io.vertx.oracleclient.impl.Helper;
17-
import io.vertx.sqlclient.PrepareOptions;
1817
import io.vertx.sqlclient.Row;
1918
import io.vertx.sqlclient.Tuple;
2019
import io.vertx.sqlclient.impl.command.ExtendedQueryCommand;
@@ -40,8 +39,7 @@ public OraclePreparedQuery(ExtendedQueryCommand<R> query, Collector<Row, C, R> c
4039

4140
@Override
4241
protected OraclePrepareOptions prepareOptions() {
43-
PrepareOptions prepareOptions = query.options();
44-
return prepareOptions instanceof OraclePrepareOptions ? (OraclePrepareOptions) prepareOptions : null;
42+
return OraclePrepareOptions.createFrom(query.options());
4543
}
4644

4745
@Override
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2011-2021 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
12+
package io.vertx.oracleclient.test;
13+
14+
import io.vertx.core.AsyncResult;
15+
import io.vertx.core.Future;
16+
import io.vertx.core.Handler;
17+
import io.vertx.sqlclient.SqlClient;
18+
19+
import java.util.function.Function;
20+
21+
public class OracleGeneratedKeysPooledTest extends OracleGeneratedKeysTestBase {
22+
23+
@Override
24+
protected <T> void withSqlClient(Function<SqlClient, Future<T>> function, Handler<AsyncResult<T>> handler) {
25+
function.apply(pool).onComplete(handler);
26+
}
27+
}

vertx-oracle-client/src/test/java/io/vertx/oracleclient/test/OracleGeneratedKeysTest.java

Lines changed: 9 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -11,99 +11,17 @@
1111

1212
package io.vertx.oracleclient.test;
1313

14-
import io.vertx.core.json.JsonArray;
15-
import io.vertx.ext.unit.TestContext;
16-
import io.vertx.ext.unit.junit.VertxUnitRunner;
17-
import io.vertx.oracleclient.OracleClient;
18-
import io.vertx.oracleclient.OraclePool;
19-
import io.vertx.oracleclient.OraclePrepareOptions;
20-
import io.vertx.oracleclient.test.junit.OracleRule;
21-
import io.vertx.sqlclient.PoolOptions;
22-
import io.vertx.sqlclient.Row;
23-
import io.vertx.sqlclient.Tuple;
24-
import org.junit.After;
25-
import org.junit.Before;
26-
import org.junit.ClassRule;
27-
import org.junit.Test;
28-
import org.junit.runner.RunWith;
14+
import io.vertx.core.AsyncResult;
15+
import io.vertx.core.Future;
16+
import io.vertx.core.Handler;
17+
import io.vertx.sqlclient.SqlClient;
2918

30-
import java.math.BigInteger;
31-
import java.util.function.Consumer;
32-
import java.util.function.Supplier;
19+
import java.util.function.Function;
3320

34-
import static org.hamcrest.CoreMatchers.instanceOf;
35-
import static org.hamcrest.CoreMatchers.is;
36-
import static org.hamcrest.MatcherAssert.assertThat;
37-
import static org.junit.Assert.assertEquals;
38-
import static org.junit.Assert.assertNotNull;
21+
public class OracleGeneratedKeysTest extends OracleGeneratedKeysTestBase {
3922

40-
@RunWith(VertxUnitRunner.class)
41-
public class OracleGeneratedKeysTest extends OracleTestBase {
42-
43-
private static final String DROP = "DROP TABLE EntityWithIdentity";
44-
private static final String CREATE = "CREATE TABLE EntityWithIdentity\n" +
45-
"(\n" +
46-
" id NUMBER(19, 0) GENERATED AS IDENTITY,\n" +
47-
" name VARCHAR2(255 CHAR),\n" +
48-
" position NUMBER(10, 0),\n" +
49-
" PRIMARY KEY (id)\n" +
50-
")";
51-
private static final String INSERT = "INSERT INTO EntityWithIdentity (name, position) VALUES (?, ?)";
52-
53-
@ClassRule
54-
public static OracleRule oracle = OracleRule.SHARED_INSTANCE;
55-
56-
OraclePool pool;
57-
58-
@Before
59-
public void setUp(TestContext ctx) throws Exception {
60-
pool = OraclePool.pool(vertx, oracle.options(), new PoolOptions());
61-
pool.withConnection(conn -> {
62-
return conn.query(DROP).execute()
63-
.otherwiseEmpty()
64-
.compose(v -> conn.query(CREATE).execute());
65-
}, ctx.asyncAssertSuccess());
66-
}
67-
68-
@Test
69-
public void shouldRetrieveRowId(TestContext ctx) {
70-
doTest(ctx, () -> {
71-
return null;
72-
}, generated -> verifyGenerated(generated, "ROWID", byte[].class));
73-
}
74-
75-
@Test
76-
public void shouldRetrieveGeneratedKeyByName(TestContext ctx) {
77-
doTest(ctx, () -> {
78-
return new OraclePrepareOptions()
79-
.setAutoGeneratedKeysIndexes(new JsonArray().add("id"));
80-
}, generated -> verifyGenerated(generated, "ID", BigInteger.class));
81-
}
82-
83-
@Test
84-
public void shouldRetrieveGeneratedKeyByIndex(TestContext ctx) {
85-
doTest(ctx, () -> {
86-
return new OraclePrepareOptions()
87-
.setAutoGeneratedKeysIndexes(new JsonArray().add(1));
88-
}, generated -> verifyGenerated(generated, "ID", BigInteger.class));
89-
}
90-
91-
private void doTest(TestContext ctx, Supplier<OraclePrepareOptions> supplier, Consumer<Row> checks) {
92-
pool.withConnection(conn -> {
93-
return conn.preparedQuery(INSERT, supplier.get()).execute(Tuple.of("john", 3));
94-
}, ctx.asyncAssertSuccess(rows -> ctx.verify(v -> {
95-
checks.accept(rows.property(OracleClient.GENERATED_KEYS));
96-
})));
97-
}
98-
99-
private void verifyGenerated(Row generated, String expectedColumnName, Class<?> expectedClass) {
100-
assertNotNull(generated);
101-
assertEquals(expectedColumnName, generated.getColumnName(0));
102-
assertThat(generated.getValue(expectedColumnName), is(instanceOf(expectedClass)));
103-
}
104-
105-
@After
106-
public void tearDown(TestContext ctx) throws Exception {
107-
pool.close(ctx.asyncAssertSuccess());
23+
@Override
24+
protected <T> void withSqlClient(Function<SqlClient, Future<T>> function, Handler<AsyncResult<T>> handler) {
25+
pool.withConnection(function::apply, handler);
10826
}
10927
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2011-2021 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
12+
package io.vertx.oracleclient.test;
13+
14+
import io.vertx.core.AsyncResult;
15+
import io.vertx.core.Future;
16+
import io.vertx.core.Handler;
17+
import io.vertx.core.json.JsonArray;
18+
import io.vertx.ext.unit.TestContext;
19+
import io.vertx.ext.unit.junit.VertxUnitRunner;
20+
import io.vertx.oracleclient.OracleClient;
21+
import io.vertx.oracleclient.OraclePool;
22+
import io.vertx.oracleclient.OraclePrepareOptions;
23+
import io.vertx.oracleclient.test.junit.OracleRule;
24+
import io.vertx.sqlclient.*;
25+
import org.junit.After;
26+
import org.junit.Before;
27+
import org.junit.ClassRule;
28+
import org.junit.Test;
29+
import org.junit.runner.RunWith;
30+
31+
import java.math.BigInteger;
32+
import java.util.function.Consumer;
33+
import java.util.function.Function;
34+
import java.util.function.Supplier;
35+
36+
import static org.hamcrest.CoreMatchers.instanceOf;
37+
import static org.hamcrest.CoreMatchers.is;
38+
import static org.hamcrest.MatcherAssert.assertThat;
39+
import static org.junit.Assert.assertEquals;
40+
import static org.junit.Assert.assertNotNull;
41+
42+
@RunWith(VertxUnitRunner.class)
43+
public abstract class OracleGeneratedKeysTestBase extends OracleTestBase {
44+
45+
private static final String DROP = "DROP TABLE EntityWithIdentity";
46+
private static final String CREATE = "CREATE TABLE EntityWithIdentity\n" +
47+
"(\n" +
48+
" id NUMBER(19, 0) GENERATED AS IDENTITY,\n" +
49+
" name VARCHAR2(255 CHAR),\n" +
50+
" position NUMBER(10, 0),\n" +
51+
" PRIMARY KEY (id)\n" +
52+
")";
53+
private static final String INSERT = "INSERT INTO EntityWithIdentity (name, position) VALUES (?, ?)";
54+
55+
@ClassRule
56+
public static OracleRule oracle = OracleRule.SHARED_INSTANCE;
57+
58+
protected OraclePool pool;
59+
60+
@Before
61+
public void setUp(TestContext ctx) throws Exception {
62+
pool = OraclePool.pool(vertx, oracle.options(), new PoolOptions());
63+
pool.withConnection(conn -> {
64+
return conn.query(DROP).execute()
65+
.otherwiseEmpty()
66+
.compose(v -> conn.query(CREATE).execute());
67+
}, ctx.asyncAssertSuccess());
68+
}
69+
70+
@Test
71+
public void shouldRetrieveRowId(TestContext ctx) {
72+
doTest(ctx, () -> {
73+
return null;
74+
}, generated -> verifyGenerated(generated, "ROWID", byte[].class));
75+
}
76+
77+
@Test
78+
public void shouldRetrieveGeneratedKeyByName(TestContext ctx) {
79+
doTest(ctx, () -> {
80+
return new OraclePrepareOptions()
81+
.setAutoGeneratedKeysIndexes(new JsonArray().add("id"));
82+
}, generated -> verifyGenerated(generated, "ID", BigInteger.class));
83+
}
84+
85+
@Test
86+
public void shouldRetrieveGeneratedKeyByIndex(TestContext ctx) {
87+
doTest(ctx, () -> {
88+
return new OraclePrepareOptions()
89+
.setAutoGeneratedKeysIndexes(new JsonArray().add(1));
90+
}, generated -> verifyGenerated(generated, "ID", BigInteger.class));
91+
}
92+
93+
private void doTest(TestContext ctx, Supplier<OraclePrepareOptions> supplier, Consumer<Row> checks) {
94+
OraclePrepareOptions options = supplier.get();
95+
withSqlClient(client -> {
96+
return client.preparedQuery(INSERT, options).execute(Tuple.of("bar", 4));
97+
}, ctx.asyncAssertSuccess(rows -> ctx.verify(v -> {
98+
checks.accept(rows.property(OracleClient.GENERATED_KEYS));
99+
})));
100+
if (options != null) {
101+
withSqlClient(client -> {
102+
return client.preparedQuery(INSERT, new PrepareOptions(options.toJson())).execute(Tuple.of("foo", 3));
103+
}, ctx.asyncAssertSuccess(rows -> ctx.verify(v -> {
104+
checks.accept(rows.property(OracleClient.GENERATED_KEYS));
105+
})));
106+
}
107+
}
108+
109+
protected abstract <T> void withSqlClient(Function<SqlClient, Future<T>> function, Handler<AsyncResult<T>> handler);
110+
111+
private void verifyGenerated(Row generated, String expectedColumnName, Class<?> expectedClass) {
112+
assertNotNull(generated);
113+
assertEquals(expectedColumnName, generated.getColumnName(0));
114+
assertThat(generated.getValue(expectedColumnName), is(instanceOf(expectedClass)));
115+
}
116+
117+
@After
118+
public void tearDown(TestContext ctx) throws Exception {
119+
pool.close(ctx.asyncAssertSuccess());
120+
}
121+
}

0 commit comments

Comments
 (0)