io.vertx.oracleclient.impl.commands.OraclePreparedBatchQuery Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2023 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.oracleclient.impl.commands;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.impl.ContextInternal;
import io.vertx.oracleclient.OraclePrepareOptions;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.Tuple;
import io.vertx.sqlclient.impl.QueryResultHandler;
import io.vertx.sqlclient.impl.TupleInternal;
import io.vertx.sqlclient.impl.command.ExtendedQueryCommand;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OraclePreparedStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Flow;
import java.util.stream.Collector;
import static io.vertx.oracleclient.impl.FailureUtil.sanitize;
public class OraclePreparedBatchQuery extends OracleQueryCommand {
private final String sql;
private final List listParams;
private final QueryResultHandler resultHandler;
public OraclePreparedBatchQuery(OracleConnection oracleConnection, ContextInternal connectionContext, ExtendedQueryCommand cmd, Collector collector) {
super(oracleConnection, connectionContext, collector);
sql = cmd.sql();
listParams = cmd.paramsList();
resultHandler = cmd.resultHandler();
}
@Override
protected OraclePrepareOptions prepareOptions() {
return null;
}
@Override
protected boolean returnAutoGeneratedKeys(Connection conn, OraclePrepareOptions options) {
return false;
}
@Override
protected String query() {
return sql;
}
@Override
protected void fillStatement(PreparedStatement ps, Connection conn) throws SQLException {
for (Tuple params : listParams) {
for (int i = 0; i < params.size(); i++) {
// we must convert types (to comply to JDBC)
Object value = adaptType(conn, params.getValue(i));
ps.setObject(i + 1, value);
}
ps.addBatch();
}
}
@Override
protected Future doExecute(OraclePreparedStatement ps, boolean returnAutoGeneratedKeys) {
return executeBlocking(ps::executeBatchAsyncOracle)
.compose(pub -> collect(pub))
.map(list -> {
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i).intValue();
}
return res;
})
.compose(returnedBatchResult -> executeBlocking(() -> decode(ps, returnedBatchResult, returnAutoGeneratedKeys)))
.map(oracleResponse -> {
oracleResponse.handle(resultHandler);
return false;
});
}
private Future> collect(Flow.Publisher publisher) {
Promise> promise = connectionContext.promise();
publisher.subscribe(new Flow.Subscriber<>() {
final List list = Collections.synchronizedList(new ArrayList<>());
@Override
public void onSubscribe(Flow.Subscription subscription) {
subscription.request(Long.MAX_VALUE);
}
@Override
public void onNext(T item) {
list.add(item);
}
@Override
public void onError(Throwable throwable) {
promise.fail(sanitize(throwable));
}
@Override
public void onComplete() {
promise.complete(list);
}
});
return promise.future();
}
}