All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.d3x.core.db.DatabaseExecute Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2018-2019 D3X Systems - All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.d3x.core.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;

import com.d3x.core.util.IO;
import com.d3x.core.util.Option;

/**
 * A database operation to implement a JDBC Statement.execute() operation
 *
 * @author Xavier Witdouck
 */
public class DatabaseExecute extends DatabaseOperation {

    /**
     * Constructor
     * @param db    the database reference
     * @param sql   the sql for this operation
     */
    DatabaseExecute(Database db, String sql) {
        super(db);
        this.sql(sql);
    }


    /**
     * Applies this database execute operation
     * @return  optional record count for operation
     * @throws DatabaseException    if this operation fails
     */
    public Option apply() throws DatabaseException {
        return apply((Multiple)null);
    }


    /**
     * Applies this database execute operation
     * @return  optional record count for operation
     * @throws DatabaseException    if this operation fails
     */
    public Option apply(Single handler) throws DatabaseException {
        return apply((idx, rs) -> handler.accept(rs));
    }


    /**
     * Applies this database execute operation
     * @param handler       the consumer to receive one or more result sets
     * @return              the optional record count for operation
     * @throws DatabaseException    if this operation fails
     */
    public Option apply(Multiple handler) throws DatabaseException {
        Connection conn = null;
        PreparedStatement stmt = null;
        var args = getArgs();
        var sql = DatabaseUtils.loadSql(getSql().get());
        try {
            conn = getDb().getConnection();
            stmt = DatabaseMapping.bindArgs(conn.prepareStatement(sql), args);
            stmt.setQueryTimeout((int) getTimeout().orElse(Duration.ofSeconds(30)).toSeconds());
            stmt.setFetchSize(getFetchSize().orElse(0));
            stmt.setMaxRows(this.getLimit().orElse(0));
            var results = stmt.execute();
            if (results && handler != null) {
                var count = new AtomicInteger();
                var rs = stmt.getResultSet();
                handler.accept(0, rs);
                IO.close(rs);
                while (stmt.getMoreResults()) {
                    rs = stmt.getResultSet();
                    handler.accept(count.incrementAndGet(), rs);
                    IO.close(rs);
                }
            }
            var records = stmt.getUpdateCount();
            return records < 0 ? Option.empty() : Option.of(records);
        } catch (RuntimeException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new DatabaseException("Failed to execute sql: " + sql, ex);
        } finally {
            IO.close(stmt, conn);
        }
    }


    /**
     * An interface to a handler that accepts a single result set
     */
    public interface Single {

        /**
         * Called to process the result set from a execute() call
         * @param rs    the result set
         * @throws SQLException if SQL exception
         */
        void accept(ResultSet rs) throws SQLException;
    }


    /**
     * An interface to a handler that accepts multiple results sets
     */
    public interface Multiple {

        /**
         * Called to process one result set from a execute() call
         * @param index the index of result set, 0 for first one
         * @param rs    the result set
         * @throws SQLException if SQL exception
         */
        void accept(int index, ResultSet rs) throws SQLException;
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy