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

com.landawn.abacus.util.JdbcUtil Maven / Gradle / Ivy

There is a newer version: 1.8.1
Show newest version
/*
 * Copyright (c) 2015, Haiyang Li.
 * 
 * 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.landawn.abacus.util;

import static com.landawn.abacus.core.AbacusConfiguration.DataSourceConfiguration.DRIVER;
import static com.landawn.abacus.core.AbacusConfiguration.DataSourceConfiguration.PASSWORD;
import static com.landawn.abacus.core.AbacusConfiguration.DataSourceConfiguration.URL;
import static com.landawn.abacus.core.AbacusConfiguration.DataSourceConfiguration.USER;
import static com.landawn.abacus.util.IOUtil.DEFAULT_QUEUE_SIZE_FOR_ROW_PARSER;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import javax.xml.parsers.DocumentBuilder;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.landawn.abacus.DataSet;
import com.landawn.abacus.DataSource;
import com.landawn.abacus.DataSourceManager;
import com.landawn.abacus.DataSourceSelector;
import com.landawn.abacus.IsolationLevel;
import com.landawn.abacus.SliceSelector;
import com.landawn.abacus.core.AbacusConfiguration;
import com.landawn.abacus.core.AbacusConfiguration.DataSourceConfiguration;
import com.landawn.abacus.core.AbacusConfiguration.DataSourceManagerConfiguration;
import com.landawn.abacus.core.RowDataSet;
import com.landawn.abacus.core.sql.dataSource.NonSliceSelector;
import com.landawn.abacus.core.sql.dataSource.SQLDataSource;
import com.landawn.abacus.core.sql.dataSource.SQLDataSourceManager;
import com.landawn.abacus.core.sql.dataSource.SimpleSourceSelector;
import com.landawn.abacus.dataChannel.DataChannel;
import com.landawn.abacus.dataChannel.StatementDataChannel;
import com.landawn.abacus.exception.AbacusException;
import com.landawn.abacus.exception.ParseException;
import com.landawn.abacus.exception.UncheckedIOException;
import com.landawn.abacus.exception.UncheckedSQLException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.util.SQLExecutor.JdbcSettings;
import com.landawn.abacus.util.stream.Stream;

/**
 *
 * @since 0.8
 * 
 * @author Haiyang Li
 * 
 * @see http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html
 * @see http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html
 * @see http://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html
 * @see http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
 */
public final class JdbcUtil {
    private static final Logger logger = LoggerFactory.getLogger(JdbcUtil.class);

    // ...
    private static final String CURRENT_DIR_PATH = "./";

    private static final Try.BiConsumer DEFAULT_STMT_SETTER = new Try.BiConsumer() {
        @Override
        public void accept(PreparedStatement stmt, Object[] parameters) throws SQLException {
            for (int i = 0, len = parameters.length; i < len; i++) {
                stmt.setObject(i + 1, parameters[i]);
            }
        }
    };

    private static final Set sqlStateForTableNotExists = new HashSet<>();

    static {
        sqlStateForTableNotExists.add("42S02"); // for MySQL.
        sqlStateForTableNotExists.add("42P01"); // for PostgreSQL.
        sqlStateForTableNotExists.add("42501"); // for HSQLDB.
    }

    private JdbcUtil() {
        // singleton
    }

    public static DBVersion getDBVersion(final Connection conn) throws UncheckedSQLException {
        try {
            String dbProudctName = conn.getMetaData().getDatabaseProductName();
            String dbProudctVersion = conn.getMetaData().getDatabaseProductVersion();

            DBVersion dbVersion = DBVersion.OTHERS;

            String upperCaseProductName = dbProudctName.toUpperCase();
            if (upperCaseProductName.contains("H2")) {
                dbVersion = DBVersion.H2;
            } else if (upperCaseProductName.contains("HSQL")) {
                dbVersion = DBVersion.HSQLDB;
            } else if (upperCaseProductName.contains("MYSQL")) {
                if (dbProudctVersion.startsWith("5.5")) {
                    dbVersion = DBVersion.MYSQL_5_5;
                } else if (dbProudctVersion.startsWith("5.6")) {
                    dbVersion = DBVersion.MYSQL_5_6;
                } else if (dbProudctVersion.startsWith("5.7")) {
                    dbVersion = DBVersion.MYSQL_5_7;
                } else if (dbProudctVersion.startsWith("5.8")) {
                    dbVersion = DBVersion.MYSQL_5_8;
                } else if (dbProudctVersion.startsWith("5.9")) {
                    dbVersion = DBVersion.MYSQL_5_9;
                } else if (dbProudctVersion.startsWith("6")) {
                    dbVersion = DBVersion.MYSQL_6;
                } else if (dbProudctVersion.startsWith("7")) {
                    dbVersion = DBVersion.MYSQL_7;
                } else {
                    dbVersion = DBVersion.MYSQL_OTHERS;
                }
            } else if (upperCaseProductName.contains("POSTGRESQL")) {
                if (dbProudctVersion.startsWith("9.2")) {
                    dbVersion = DBVersion.POSTGRESQL_9_2;
                } else if (dbProudctVersion.startsWith("9.3")) {
                    dbVersion = DBVersion.POSTGRESQL_9_3;
                } else if (dbProudctVersion.startsWith("9.4")) {
                    dbVersion = DBVersion.POSTGRESQL_9_4;
                } else if (dbProudctVersion.startsWith("9.5")) {
                    dbVersion = DBVersion.POSTGRESQL_9_5;
                } else if (dbProudctVersion.startsWith("10")) {
                    dbVersion = DBVersion.POSTGRESQL_10;
                } else {
                    dbVersion = DBVersion.POSTGRESQL_OTHERS;
                }
            } else if (upperCaseProductName.contains("ORACLE")) {
                dbVersion = DBVersion.ORACLE;
            } else if (upperCaseProductName.contains("DB2")) {
                dbVersion = DBVersion.DB2;
            } else if (upperCaseProductName.contains("SQL SERVER")) {
                dbVersion = DBVersion.SQL_SERVER;
            }

            return dbVersion;
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        }
    }

    /**
     * 
     * @param dataSourceXmlFile
     * @return DataSourceManager
     * 
     * @see DataSource.xsd
     */
    public static DataSourceManager createDataSourceManager(final String dataSourceXmlFile) throws UncheckedIOException, UncheckedSQLException {
        InputStream is = null;
        try {
            is = new FileInputStream(Configuration.findFile(dataSourceXmlFile));
            return createDataSourceManager(is, dataSourceXmlFile);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        } finally {
            IOUtil.close(is);
        }

    }

    /**
     * 
     * @param dataSourceXmlInputStream
     * @return DataSourceManager
     * 
     * @see DataSource.xsd
     */
    public static DataSourceManager createDataSourceManager(final InputStream dataSourceXmlInputStream) throws UncheckedIOException, UncheckedSQLException {
        return createDataSourceManager(dataSourceXmlInputStream, CURRENT_DIR_PATH);
    }

    private static DataSourceManager createDataSourceManager(final InputStream dataSourceXmlInputStream, final String dataSourceXmlFile)
            throws UncheckedIOException, UncheckedSQLException {
        DocumentBuilder domParser = XMLUtil.createDOMParser();
        Document doc = null;

        try {
            doc = domParser.parse(dataSourceXmlInputStream);

            Element rootElement = doc.getDocumentElement();

            final Map props = new HashMap<>();
            List propertiesElementList = XMLUtil.getElementsByTagName(rootElement, AbacusConfiguration.PROPERTIES);

            if (N.notNullOrEmpty(propertiesElementList)) {
                for (Element propertiesElement : propertiesElementList) {
                    File resourcePropertiesFile = Configuration.findFileByFile(new File(dataSourceXmlFile),
                            propertiesElement.getAttribute(AbacusConfiguration.RESOURCE));
                    java.util.Properties properties = new java.util.Properties();
                    InputStream is = null;

                    try {
                        is = new FileInputStream(resourcePropertiesFile);

                        if (resourcePropertiesFile.getName().endsWith(".xml")) {
                            properties.loadFromXML(is);
                        } else {
                            properties.load(is);
                        }
                    } finally {
                        IOUtil.close(is);
                    }

                    for (Object key : properties.keySet()) {
                        props.put((String) key, (String) properties.get(key));
                    }
                }
            }

            String nodeName = rootElement.getNodeName();
            if (nodeName.equals(DataSourceManagerConfiguration.DATA_SOURCE_MANAGER)) {
                DataSourceManagerConfiguration config = new DataSourceManagerConfiguration(rootElement, props);
                return new SQLDataSourceManager(config);
            } else if (nodeName.equals(DataSourceConfiguration.DATA_SOURCE)) {
                DataSourceConfiguration config = new DataSourceConfiguration(rootElement, props);
                return new SimpleDataSourceManager(new SQLDataSource(config));
            } else {
                throw new AbacusException("Unknown xml format with root element: " + nodeName);
            }
        } catch (SAXException e) {
            throw new ParseException(e);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static DataSource createDataSource(final String dataSourceFile) throws UncheckedIOException, UncheckedSQLException {
        InputStream is = null;
        try {
            is = new FileInputStream(Configuration.findFile(dataSourceFile));
            return createDataSource(is, dataSourceFile);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        } finally {
            IOUtil.close(is);
        }
    }

    public static DataSource createDataSource(final InputStream dataSourceInputStream) throws UncheckedIOException, UncheckedSQLException {
        return createDataSource(dataSourceInputStream, CURRENT_DIR_PATH);
    }

    private static DataSource createDataSource(final InputStream dataSourceInputStream, final String dataSourceFile)
            throws UncheckedIOException, UncheckedSQLException {
        final String dataSourceString = IOUtil.readString(dataSourceInputStream);

        if (CURRENT_DIR_PATH.equals(dataSourceFile) || dataSourceFile.endsWith(".xml")) {
            try {
                return createDataSourceManager(new ByteArrayInputStream(dataSourceString.getBytes())).getPrimaryDataSource();
            } catch (ParseException e) {
                // ignore.
            } catch (UncheckedIOException e) {
                // ignore.
            }
        }

        final Map newProps = new HashMap<>();
        final java.util.Properties properties = new java.util.Properties();

        try {
            properties.load(new ByteArrayInputStream(dataSourceString.getBytes()));

            Object value = null;

            for (Object key : properties.keySet()) {
                value = properties.get(key);
                newProps.put(key.toString().trim(), value.toString().trim());
            }

        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }

        return new SQLDataSource(newProps);
    }

    public static DataSource createDataSource(final String url, final String user, final String password) throws UncheckedSQLException {
        return createDataSource(getDriverClasssByUrl(url), url, user, password);
    }

    public static DataSource createDataSource(final String driver, final String url, final String user, final String password) throws UncheckedSQLException {
        final Class driverClass = ClassUtil.forClass(driver);

        return createDataSource(driverClass, url, user, password);
    }

    public static DataSource createDataSource(final Class driverClass, final String url, final String user, final String password)
            throws UncheckedSQLException {
        final Map props = new HashMap<>();

        props.put(DRIVER, driverClass.getCanonicalName());
        props.put(URL, url);
        props.put(USER, user);
        props.put(PASSWORD, password);

        return createDataSource(props);
    }

    /**
     * 
     * @param props refer to Connection.xsd for the supported properties.
     * @return
     */
    public static DataSource createDataSource(final Map props) throws UncheckedSQLException {
        final String driver = (String) props.get(DRIVER);

        if (N.isNullOrEmpty(driver)) {
            final String url = (String) props.get(URL);

            if (N.isNullOrEmpty(url)) {
                throw new IllegalArgumentException("Url is not specified");
            }

            final Map tmp = new HashMap<>(props);

            tmp.put(DRIVER, getDriverClasssByUrl(url).getCanonicalName());

            return new SQLDataSource(tmp);
        } else {
            return new SQLDataSource(props);
        }
    }

    public static DataSource wrap(final javax.sql.DataSource sqlDataSource) {
        return sqlDataSource instanceof DataSource ? ((DataSource) sqlDataSource) : new SimpleDataSource(sqlDataSource);
    }

    public static Connection createConnection(final String url, final String user, final String password) throws UncheckedSQLException {
        return createConnection(getDriverClasssByUrl(url), url, user, password);
    }

    private static Class getDriverClasssByUrl(final String url) {
        Class driverClass = null;
        // jdbc:mysql://localhost:3306/abacustest
        if (url.indexOf("mysql") > 0 || StringUtil.indexOfIgnoreCase(url, "mysql") > 0) {
            driverClass = ClassUtil.forClass("com.mysql.jdbc.Driver");
            // jdbc:postgresql://localhost:5432/abacustest
        } else if (url.indexOf("postgresql") > 0 || StringUtil.indexOfIgnoreCase(url, "postgresql") > 0) {
            driverClass = ClassUtil.forClass("org.postgresql.Driver");
            // jdbc:h2:hsql://:/
        } else if (url.indexOf("h2") > 0 || StringUtil.indexOfIgnoreCase(url, "h2") > 0) {
            driverClass = ClassUtil.forClass("org.h2.Driver");
            // jdbc:hsqldb:hsql://localhost/abacustest
        } else if (url.indexOf("hsqldb") > 0 || StringUtil.indexOfIgnoreCase(url, "hsqldb") > 0) {
            driverClass = ClassUtil.forClass("org.hsqldb.jdbc.JDBCDriver");
            // jdbc.url=jdbc:oracle:thin:@localhost:1521:abacustest
        } else if (url.indexOf("oracle") > 0 || StringUtil.indexOfIgnoreCase(url, "oracle") > 0) {
            driverClass = ClassUtil.forClass("oracle.jdbc.driver.OracleDriver");
            // jdbc.url=jdbc:sqlserver://localhost:1433;Database=abacustest
        } else if (url.indexOf("sqlserver") > 0 || StringUtil.indexOfIgnoreCase(url, "sqlserver") > 0) {
            driverClass = ClassUtil.forClass("com.microsoft.sqlserver.jdbc.SQLServerDrive");
            // jdbc:db2://localhost:50000/abacustest
        } else if (url.indexOf("db2") > 0 || StringUtil.indexOfIgnoreCase(url, "db2") > 0) {
            driverClass = ClassUtil.forClass("com.ibm.db2.jcc.DB2Driver");
        } else {
            throw new UncheckedSQLException(
                    "Can not identity the driver class by url: " + url + ". Only mysql, postgresql, hsqldb, sqlserver, oracle and db2 are supported currently");
        }
        return driverClass;
    }

    public static Connection createConnection(final String driverClass, final String url, final String user, final String password)
            throws UncheckedSQLException {
        Class cls = ClassUtil.forClass(driverClass);
        return createConnection(cls, url, user, password);
    }

    public static Connection createConnection(final Class driverClass, final String url, final String user, final String password)
            throws UncheckedSQLException {
        try {
            DriverManager.registerDriver(N.newInstance(driverClass));

            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new UncheckedSQLException("Failed to close create connection", e);
        }
    }

    public static void close(final ResultSet rs) throws UncheckedSQLException {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new UncheckedSQLException(e);
            }
        }
    }

    public static void close(final ResultSet rs, final boolean closeStatement) throws UncheckedSQLException {
        close(rs, closeStatement, false);
    }

    /**
     * 
     * @param rs
     * @param closeStatement 
     * @param closeConnection
     * @throws IllegalArgumentException if {@code closeStatement = false} while {@code closeConnection = true}.
     * @throws UncheckedSQLException
     */
    public static void close(final ResultSet rs, final boolean closeStatement, final boolean closeConnection)
            throws IllegalArgumentException, UncheckedSQLException {
        if (closeConnection && closeStatement == false) {
            throw new IllegalArgumentException("'closeStatement' can't be false while 'closeConnection' is true");
        }

        if (rs == null) {
            return;
        }

        Connection conn = null;
        Statement stmt = null;

        try {
            if (closeStatement || closeConnection) {
                stmt = rs.getStatement();
            }

            if (closeConnection && stmt != null) {
                conn = stmt.getConnection();
            }
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        } finally {
            close(rs, stmt, conn);
        }
    }

    public static void close(final Statement stmt) throws UncheckedSQLException {
        if (stmt != null) {
            try {
                if (stmt instanceof PreparedStatement) {
                    try {
                        ((PreparedStatement) stmt).clearParameters();
                    } catch (SQLException e) {
                        logger.error("Failed to clear parameters", e);
                    }
                }

                stmt.close();
            } catch (SQLException e) {
                throw new UncheckedSQLException(e);
            }
        }
    }

    public static void close(final Connection conn) throws UncheckedSQLException {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new UncheckedSQLException(e);
            }
        }
    }

    public static void close(final ResultSet rs, final Statement stmt) throws UncheckedSQLException {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        } finally {
            try {
                if (stmt != null) {
                    if (stmt instanceof PreparedStatement) {
                        try {
                            ((PreparedStatement) stmt).clearParameters();
                        } catch (SQLException e) {
                            logger.error("Failed to clear parameters", e);
                        }
                    }
                    stmt.close();
                }
            } catch (SQLException e) {
                throw new UncheckedSQLException(e);
            }
        }
    }

    public static void close(final Statement stmt, final Connection conn) throws UncheckedSQLException {
        try {
            if (stmt != null) {
                if (stmt instanceof PreparedStatement) {
                    try {
                        ((PreparedStatement) stmt).clearParameters();
                    } catch (SQLException e) {
                        logger.error("Failed to clear parameters", e);
                    }
                }
                stmt.close();
            }
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        } finally {
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                throw new UncheckedSQLException(e);
            }
        }
    }

    public static void close(final ResultSet rs, final Statement stmt, final Connection conn) throws UncheckedSQLException {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        } finally {
            try {
                if (stmt != null) {
                    if (stmt instanceof PreparedStatement) {
                        try {
                            ((PreparedStatement) stmt).clearParameters();
                        } catch (SQLException e) {
                            logger.error("Failed to clear parameters", e);
                        }
                    }
                    stmt.close();
                }
            } catch (SQLException e) {
                throw new UncheckedSQLException(e);
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    throw new UncheckedSQLException(e);
                }
            }
        }
    }

    /**
     * Unconditionally close an ResultSet.
     * 

* Equivalent to {@link ResultSet#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param rs */ public static void closeQuietly(final ResultSet rs) { closeQuietly(rs, null, null); } public static void closeQuietly(final ResultSet rs, final boolean closeStatement) throws UncheckedSQLException { closeQuietly(rs, closeStatement, false); } /** * * @param rs * @param closeStatement * @param closeConnection * @throws IllegalArgumentException if {@code closeStatement = false} while {@code closeConnection = true}. */ public static void closeQuietly(final ResultSet rs, final boolean closeStatement, final boolean closeConnection) throws IllegalArgumentException { if (closeConnection && closeStatement == false) { throw new IllegalArgumentException("'closeStatement' can't be false while 'closeConnection' is true"); } if (rs == null) { return; } Connection conn = null; Statement stmt = null; try { if (closeStatement || closeConnection) { stmt = rs.getStatement(); } if (closeConnection && stmt != null) { conn = stmt.getConnection(); } } catch (SQLException e) { logger.error("Failed to get Statement or Connection by ResultSet", e); } finally { closeQuietly(rs, stmt, conn); } } /** * Unconditionally close an Statement. *

* Equivalent to {@link Statement#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param stmt */ public static void closeQuietly(final Statement stmt) { closeQuietly(null, stmt, null); } /** * Unconditionally close an Connection. *

* Equivalent to {@link Connection#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param conn */ public static void closeQuietly(final Connection conn) { closeQuietly(null, null, conn); } /** * Unconditionally close the ResultSet, Statement. *

* Equivalent to {@link ResultSet#close()}, {@link Statement#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param rs * @param stmt */ public static void closeQuietly(final ResultSet rs, final Statement stmt) { closeQuietly(rs, stmt, null); } /** * Unconditionally close the Statement, Connection. *

* Equivalent to {@link Statement#close()}, {@link Connection#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param stmt * @param conn */ public static void closeQuietly(final Statement stmt, final Connection conn) { closeQuietly(null, stmt, conn); } /** * Unconditionally close the ResultSet, Statement, Connection. *

* Equivalent to {@link ResultSet#close()}, {@link Statement#close()}, {@link Connection#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param rs * @param stmt * @param conn */ public static void closeQuietly(final ResultSet rs, final Statement stmt, final Connection conn) { if (rs != null) { try { rs.close(); } catch (Throwable e) { logger.error("Failed to close ResultSet", e); } } if (stmt != null) { if (stmt instanceof PreparedStatement) { try { ((PreparedStatement) stmt).clearParameters(); } catch (Throwable e) { logger.error("Failed to clear parameters", e); } } try { stmt.close(); } catch (Throwable e) { logger.error("Failed to close Statement", e); } } if (conn != null) { try { conn.close(); } catch (Throwable e) { logger.error("Failed to close Connection", e); } } } public static SQLTransaction beginTransaction(final Connection conn, final IsolationLevel isolationLevel) throws UncheckedSQLException { if (isolationLevel == null) { throw new IllegalArgumentException("The parameter isolationLevel can't be null"); } return new SQLTransaction(conn, isolationLevel); } @SafeVarargs public static PreparedStatement prepareStatement(final Connection conn, final String sql, final Object... parameters) throws SQLException { final NamedSQL namedSQL = NamedSQL.parse(sql); final PreparedStatement stmt = conn.prepareStatement(namedSQL.getPureSQL()); if (N.notNullOrEmpty(parameters)) { SQLExecutor.DEFAULT_STATEMENT_SETTER.setParameters(namedSQL, stmt, parameters); } return stmt; } @SafeVarargs public static CallableStatement prepareCall(final Connection conn, final String sql, final Object... parameters) throws SQLException { final NamedSQL namedSQL = NamedSQL.parse(sql); final CallableStatement stmt = conn.prepareCall(namedSQL.getPureSQL()); if (N.notNullOrEmpty(parameters)) { SQLExecutor.DEFAULT_STATEMENT_SETTER.setParameters(namedSQL, stmt, parameters); } return stmt; } public static PreparedStatement batchPrepareStatement(final Connection conn, final String sql, final List parametersList) throws SQLException { final NamedSQL namedSQL = NamedSQL.parse(sql); final PreparedStatement stmt = conn.prepareStatement(namedSQL.getPureSQL()); for (Object parameters : parametersList) { SQLExecutor.DEFAULT_STATEMENT_SETTER.setParameters(namedSQL, stmt, parameters); stmt.addBatch(); } return stmt; } public static CallableStatement batchPrepareCall(final Connection conn, final String sql, final List parametersList) throws SQLException { final NamedSQL namedSQL = NamedSQL.parse(sql); final CallableStatement stmt = conn.prepareCall(namedSQL.getPureSQL()); for (Object parameters : parametersList) { SQLExecutor.DEFAULT_STATEMENT_SETTER.setParameters(namedSQL, stmt, parameters); stmt.addBatch(); } return stmt; } @SafeVarargs public static DataSet executeQuery(final Connection conn, final String sql, final Object... parameters) throws UncheckedSQLException { PreparedStatement stmt = null; ResultSet rs = null; try { stmt = prepareStatement(conn, sql, parameters); rs = stmt.executeQuery(); return extractData(rs); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(rs, stmt); } } public static DataSet executeQuery(final PreparedStatement stmt) throws UncheckedSQLException { ResultSet rs = null; try { rs = stmt.executeQuery(); return extractData(rs); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(rs); } } @SafeVarargs public static int executeUpdate(final Connection conn, final String sql, final Object... parameters) throws UncheckedSQLException { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, sql, parameters); return stmt.executeUpdate(); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(stmt); } } public static int executeUpdate(final PreparedStatement stmt) throws UncheckedSQLException { try { return stmt.executeUpdate(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } /** * * @param conn * @param sql * @param parametersListList * @return * @throws UncheckedSQLException */ public static int executeBatchUpdate(final Connection conn, final String sql, final List parametersListList) throws UncheckedSQLException { return executeBatchUpdate(conn, sql, parametersListList, JdbcSettings.DEFAULT_BATCH_SIZE); } /** * * @param conn * @param sql * @param parametersListList * @param batchSize. * @return * @throws UncheckedSQLException */ public static int executeBatchUpdate(final Connection conn, final String sql, final List parametersListList, final int batchSize) throws UncheckedSQLException { N.checkArgNotNull(conn); N.checkArgNotNull(sql); N.checkArgument(batchSize > 0, "'batchSize' can't be 0 or negative"); if (N.isNullOrEmpty(parametersListList)) { return 0; } final NamedSQL namedSQL = NamedSQL.parse(sql); PreparedStatement stmt = null; try { stmt = conn.prepareStatement(namedSQL.getPureSQL()); int res = 0; int idx = 0; for (Object parameters : parametersListList) { SQLExecutor.DEFAULT_STATEMENT_SETTER.setParameters(namedSQL, stmt, parameters); stmt.addBatch(); if (++idx % batchSize == 0) { res += stmt.executeUpdate(); stmt.clearBatch(); } } if (idx % batchSize != 0) { res += stmt.executeUpdate(); stmt.clearBatch(); } return res; } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.close(stmt); } } @SafeVarargs public static boolean execute(final Connection conn, final String sql, final Object... parameters) throws UncheckedSQLException { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, sql, parameters); return stmt.execute(); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(stmt); } } public static boolean execute(final PreparedStatement stmt) throws UncheckedSQLException { try { return stmt.execute(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } /** * * @param rs * @param n the count of row to move ahead. * @throws UncheckedSQLException */ public static void skip(final ResultSet rs, int n) throws UncheckedSQLException { skip(rs, (long) n); } /** * * @param rs * @param n the count of row to move ahead. * @throws UncheckedSQLException * @see {@link ResultSet#absolute(int)} */ public static void skip(final ResultSet rs, long n) throws UncheckedSQLException { // N.checkArgument(offset >= 0, "'offset' can't be negative: %s", offset); // // if (offset == 0) { // return; // } if (n <= 0) { return; } else if (n == 1) { try { rs.next(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } else if (n <= Integer.MAX_VALUE) { try { if (n > Integer.MAX_VALUE - rs.getRow()) { try { while (n-- > 0L && rs.next()) { } } catch (SQLException e) { throw new UncheckedSQLException(e); } } else { rs.absolute((int) n + rs.getRow()); } } catch (SQLException e) { try { while (n-- > 0L && rs.next()) { } } catch (SQLException e1) { throw new UncheckedSQLException(e); } } } else { try { while (n-- > 0L && rs.next()) { } } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * * @param rs * @throws UncheckedSQLException */ public static RowIterator iterate(final ResultSet rs) throws UncheckedSQLException { return new RowIterator(rs, false, false); } /** * * @param rs * @return * @throws UncheckedSQLException */ public static DataSet extractData(final ResultSet rs) throws UncheckedSQLException { return extractData(rs, false); } public static DataSet extractData(final ResultSet rs, final boolean closeResultSet) throws UncheckedSQLException { return extractData(rs, 0, Integer.MAX_VALUE, closeResultSet); } public static DataSet extractData(final ResultSet rs, final int offset, final int count) throws UncheckedSQLException { return extractData(rs, offset, count, false); } public static DataSet extractData(final ResultSet rs, final int offset, final int count, final boolean closeResultSet) throws UncheckedSQLException { return extractData(rs, offset, count, Fn.alwaysTrue(), closeResultSet); } public static DataSet extractData(final ResultSet rs, int offset, int count, final Try.Predicate filter, final boolean closeResultSet) throws UncheckedSQLException, E { try { // TODO [performance improvement]. it will improve performance a lot if MetaData is cached. final ResultSetMetaData metaData = rs.getMetaData(); final int columnCount = metaData.getColumnCount(); final List columnNameList = new ArrayList<>(columnCount); final List> columnList = new ArrayList<>(columnCount); for (int i = 0; i < columnCount;) { columnNameList.add(metaData.getColumnLabel(++i)); columnList.add(new ArrayList<>()); } JdbcUtil.skip(rs, offset); final Object[] row = new Object[columnCount]; while (count > 0 && rs.next()) { for (int i = 0; i < columnCount;) { row[i] = rs.getObject(++i); } if (filter == null || filter.test(row)) { for (int i = 0; i < columnCount; i++) { columnList.get(i).add(row[i]); } count--; } } // return new RowDataSet(null, entityClass, columnNameList, columnList); return new RowDataSet(columnNameList, columnList); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { if (closeResultSet) { closeQuietly(rs); } } } /** * Don’t close the specified Connection before the returned {@code Stream} is consumed/collected/terminated. * * @param conn * @param sql * @param parameters * @return * @throws UncheckedSQLException */ @SafeVarargs public static Try> stream(final Connection conn, final String sql, final Object... parameters) throws UncheckedSQLException { return stream2(null, conn, sql, parameters); } /** * Don’t close the specified Connection before the returned {@code Stream} is consumed/collected/terminated. * * @param targetType {@code Map} or {@code Entity} class with getter/setter methods. * @param conn * @param sql * @param parameters * @return * @throws UncheckedSQLException */ @SafeVarargs public static Try> stream(final Class targetType, final Connection conn, final String sql, final Object... parameters) throws UncheckedSQLException { N.checkArgNotNull(targetType); return stream2(targetType, conn, sql, parameters); } @SafeVarargs private static Try> stream2(final Class targetType, final Connection conn, final String sql, final Object... parameters) throws UncheckedSQLException { PreparedStatement stmt = null; ResultSet rs = null; boolean isOK = false; try { stmt = JdbcUtil.prepareStatement(conn, sql, parameters); rs = stmt.executeQuery(); final PreparedStatement _stmt = stmt; final ResultSet _rs = rs; @SuppressWarnings("unchecked") final Try> res = (targetType == null ? (Stream) Stream.of(rs) : Stream.of(targetType, rs)).onClose(new Runnable() { @Override public void run() { JdbcUtil.closeQuietly(_rs, _stmt); } }).tried(); isOK = true; return res; } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { if (!isOK) { JdbcUtil.closeQuietly(rs, stmt); } } } /** * Don’t close the specified statement before the returned {@code Stream} is consumed/collected/terminated. * * @param stmt * @return * @throws UncheckedSQLException */ public static Try> stream(final PreparedStatement stmt) throws UncheckedSQLException { return stream2(null, stmt); } /** * Don’t close the specified statement before the returned {@code Stream} is consumed/collected/terminated. * * @param targetType {@code Map} or {@code Entity} class with getter/setter methods. * @param stmt * @return * @throws UncheckedSQLException */ public static Try> stream(final Class targetType, final PreparedStatement stmt) throws UncheckedSQLException { N.checkArgNotNull(targetType); return stream2(targetType, stmt); } private static Try> stream2(final Class targetType, final PreparedStatement stmt) throws UncheckedSQLException { ResultSet rs = null; boolean isOK = false; try { rs = stmt.executeQuery(); final ResultSet _rs = rs; @SuppressWarnings("unchecked") final Try> res = (targetType == null ? (Stream) Stream.of(rs) : Stream.of(targetType, rs)).onClose(new Runnable() { @Override public void run() { JdbcUtil.closeQuietly(_rs); } }).tried(); isOK = true; return res; } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { if (!isOK) { JdbcUtil.closeQuietly(rs); } } } /** * Imports the data from DataSet to database. * * @param dataset * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *


        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Connection conn, final String insertSQL) throws UncheckedSQLException { return importData(dataset, dataset.columnNameList(), conn, insertSQL); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final Connection conn, final String insertSQL) throws UncheckedSQLException { return importData(dataset, selectColumnNames, 0, dataset.size(), conn, insertSQL); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param offset * @param count * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final int offset, final int count, final Connection conn, final String insertSQL) throws UncheckedSQLException { return importData(dataset, selectColumnNames, offset, count, conn, insertSQL, 200, 0); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param offset * @param count * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param batchSize * @param batchInterval * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final int offset, final int count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval) throws UncheckedSQLException { return importData(dataset, selectColumnNames, offset, count, Fn.alwaysTrue(), conn, insertSQL, batchSize, batchInterval); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param offset * @param count * @param filter * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param batchSize * @param batchInterval * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final int offset, final int count, final Try.Predicate filter, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(dataset, selectColumnNames, offset, count, filter, stmt, batchSize, batchInterval); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } /** * Imports the data from DataSet to database. * * @param dataset * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final Connection conn, final String insertSQL, final Map columnTypeMap) throws UncheckedSQLException { return importData(dataset, 0, dataset.size(), conn, insertSQL, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final int offset, final int count, final Connection conn, final String insertSQL, final Map columnTypeMap) throws UncheckedSQLException { return importData(dataset, offset, count, conn, insertSQL, 200, 0, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param batchSize * @param batchInterval * @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final int offset, final int count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Map columnTypeMap) throws UncheckedSQLException { return importData(dataset, offset, count, Fn.alwaysTrue(), conn, insertSQL, batchSize, batchInterval, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param filter * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param batchSize * @param batchInterval * @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final int offset, final int count, final Try.Predicate filter, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Map columnTypeMap) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(dataset, offset, count, filter, stmt, batchSize, batchInterval, columnTypeMap); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } /** * Imports the data from DataSet to database. * * @param dataset * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param stmtSetter * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Connection conn, final String insertSQL, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return importData(dataset, 0, dataset.size(), conn, insertSQL, stmtSetter); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param stmtSetter * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final int offset, final int count, final Connection conn, final String insertSQL, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return importData(dataset, offset, count, conn, insertSQL, 200, 0, stmtSetter); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param batchSize * @param batchInterval * @param stmtSetter * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final int offset, final int count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return importData(dataset, offset, count, Fn.alwaysTrue(), conn, insertSQL, batchSize, batchInterval, stmtSetter); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param filter * @param conn * @param insertSQL the column order in the sql must be consistent with the column order in the DataSet. Here is sample about how to create the sql: *

        List columnNameList = new ArrayList<>(dataset.columnNameList());
        columnNameList.retainAll(yourSelectColumnNames);        
        String sql = RE.insert(columnNameList).into(tableName).sql();  
     * 
* @param batchSize * @param batchInterval * @param stmtSetter * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final int offset, final int count, final Try.Predicate filter, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(dataset, offset, count, filter, stmt, batchSize, batchInterval, stmtSetter); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } /** * Imports the data from DataSet to database. * * @param dataset * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final PreparedStatement stmt) throws UncheckedSQLException { return importData(dataset, dataset.columnNameList(), stmt); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final PreparedStatement stmt) throws UncheckedSQLException { return importData(dataset, selectColumnNames, 0, dataset.size(), stmt); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final int offset, final int count, final PreparedStatement stmt) throws UncheckedSQLException { return importData(dataset, selectColumnNames, offset, count, stmt, 200, 0); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final int offset, final int count, final PreparedStatement stmt, final int batchSize, final int batchInterval) throws UncheckedSQLException { return importData(dataset, selectColumnNames, offset, count, Fn.alwaysTrue(), stmt, batchSize, batchInterval); } /** * Imports the data from DataSet to database. * * @param dataset * @param selectColumnNames * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param batchSize * @param batchInterval * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final Collection selectColumnNames, final int offset, final int count, final Try.Predicate filter, final PreparedStatement stmt, final int batchSize, final int batchInterval) throws UncheckedSQLException, E { final Type objType = N.typeOf(Object.class); final Map> columnTypeMap = new HashMap<>(); for (String propName : selectColumnNames) { columnTypeMap.put(propName, objType); } return importData(dataset, offset, count, filter, stmt, batchSize, batchInterval, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final PreparedStatement stmt, final Map columnTypeMap) throws UncheckedSQLException { return importData(dataset, 0, dataset.size(), stmt, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final int offset, final int count, final PreparedStatement stmt, final Map columnTypeMap) throws UncheckedSQLException { return importData(dataset, offset, count, stmt, 200, 0, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param columnTypeMap * @param filter * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final int offset, final int count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Map columnTypeMap) throws UncheckedSQLException { return importData(dataset, offset, count, Fn.alwaysTrue(), stmt, batchSize, batchInterval, columnTypeMap); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param filter * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param batchSize * @param batchInterval * @param columnTypeMap * @return * @throws UncheckedSQLException */ @SuppressWarnings("rawtypes") public static int importData(final DataSet dataset, final int offset, final int count, final Try.Predicate filter, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Map columnTypeMap) throws UncheckedSQLException, E { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can't be negative", offset, count); N.checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); int result = 0; try { final int columnCount = columnTypeMap.size(); final List columnNameList = dataset.columnNameList(); final int[] columnIndexes = new int[columnCount]; final Type[] columnTypes = new Type[columnCount]; final Set columnNameSet = new HashSet<>(columnCount); int idx = 0; for (String columnName : columnNameList) { if (columnTypeMap.containsKey(columnName)) { columnIndexes[idx] = dataset.getColumnIndex(columnName); columnTypes[idx] = columnTypeMap.get(columnName); columnNameSet.add(columnName); idx++; } } if (columnNameSet.size() != columnTypeMap.size()) { final List keys = new ArrayList<>(columnTypeMap.keySet()); keys.removeAll(columnNameSet); throw new AbacusException(keys + " are not included in titles: " + N.toString(columnNameList)); } final DataChannel dc = new StatementDataChannel(stmt); final Object[] row = filter == null ? null : new Object[columnCount]; for (int i = offset, size = dataset.size(); result < count && i < size; i++) { dataset.absolute(i); if (filter == null) { for (int j = 0; j < columnCount; j++) { columnTypes[j].set(dc, j, dataset.get(columnIndexes[j])); } } else { for (int j = 0; j < columnCount; j++) { row[j] = dataset.get(columnIndexes[j]); } if (filter.test(row) == false) { continue; } for (int j = 0; j < columnCount; j++) { columnTypes[j].set(dc, j, row[j]); } } stmt.addBatch(); if ((++result % batchSize) == 0) { stmt.executeBatch(); stmt.clearBatch(); if (batchInterval > 0) { N.sleep(batchInterval); } } } if ((result % batchSize) > 0) { stmt.executeBatch(); stmt.clearBatch(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } return result; } public static int importData(final DataSet dataset, final PreparedStatement stmt, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return importData(dataset, 0, dataset.size(), stmt, stmtSetter); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final int offset, final int count, final PreparedStatement stmt, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return importData(dataset, offset, count, stmt, 200, 0, stmtSetter); } /** * Imports the data from DataSet to database. * * @param dataset * @param columnTypeMap * @param offset * @param count * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param filter * @param stmtSetter * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final int offset, final int count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return importData(dataset, offset, count, Fn.alwaysTrue(), stmt, batchSize, batchInterval, stmtSetter); } /** * Imports the data from DataSet to database. * * @param dataset * @param offset * @param count * @param filter * @param stmt the column order in the sql must be consistent with the column order in the DataSet. * @param batchSize * @param batchInterval * @param stmtSetter * @param columnTypeMap * @return * @throws UncheckedSQLException */ public static int importData(final DataSet dataset, final int offset, final int count, final Try.Predicate filter, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws UncheckedSQLException, E { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can't be negative", offset, count); N.checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); final int columnCount = dataset.columnNameList().size(); final Object[] row = new Object[columnCount]; int result = 0; try { for (int i = offset, size = dataset.size(); result < count && i < size; i++) { dataset.absolute(i); for (int j = 0; j < columnCount; j++) { row[j] = dataset.get(j); } if (filter != null && filter.test(row) == false) { continue; } stmtSetter.accept(stmt, row); stmt.addBatch(); if ((++result % batchSize) == 0) { stmt.executeBatch(); stmt.clearBatch(); if (batchInterval > 0) { N.sleep(batchInterval); } } } if ((result % batchSize) > 0) { stmt.executeBatch(); stmt.clearBatch(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } return result; } public static long importData(final File file, final Connection conn, final String insertSQL, final Try.Function func) throws UncheckedSQLException, E { return importData(file, 0, Long.MAX_VALUE, conn, insertSQL, 200, 0, func); } public static long importData(final File file, final long offset, final long count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(file, offset, count, stmt, batchSize, batchInterval, func); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } public static long importData(final File file, final PreparedStatement stmt, final Try.Function func) throws UncheckedSQLException, E { return importData(file, 0, Long.MAX_VALUE, stmt, 200, 0, func); } /** * Imports the data from file to database. * * @param file * @param offset * @param count * @param stmt * @param batchSize * @param batchInterval * @param func convert line to the parameters for record insert. Returns a null array to skip the line. * @return * @throws UncheckedSQLException */ public static long importData(final File file, final long offset, final long count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { Reader reader = null; try { reader = new FileReader(file); return importData(reader, offset, count, stmt, batchSize, batchInterval, func); } catch (IOException e) { throw new UncheckedIOException(e); } finally { IOUtil.close(reader); } } public static long importData(final InputStream is, final Connection conn, final String insertSQL, final Try.Function func) throws UncheckedSQLException, E { return importData(is, 0, Long.MAX_VALUE, conn, insertSQL, 200, 0, func); } public static long importData(final InputStream is, final long offset, final long count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(is, offset, count, stmt, batchSize, batchInterval, func); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } public static long importData(final InputStream is, final PreparedStatement stmt, final Try.Function func) throws E { return importData(is, 0, Long.MAX_VALUE, stmt, 200, 0, func); } /** * Imports the data from file to database. * * @param is * @param offset * @param count * @param stmt * @param batchSize * @param batchInterval * @param func convert line to the parameters for record insert. Returns a null array to skip the line. * @return * @throws UncheckedSQLException */ public static long importData(final InputStream is, final long offset, final long count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { final Reader reader = new InputStreamReader(is); return importData(reader, offset, count, stmt, batchSize, batchInterval, func); } public static long importData(final Reader reader, final Connection conn, final String insertSQL, final Try.Function func) throws UncheckedSQLException, E { return importData(reader, 0, Long.MAX_VALUE, conn, insertSQL, 200, 0, func); } public static long importData(final Reader reader, final long offset, final long count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(reader, offset, count, stmt, batchSize, batchInterval, func); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } public static long importData(final Reader reader, final PreparedStatement stmt, final Try.Function func) throws E { return importData(reader, 0, Long.MAX_VALUE, stmt, 200, 0, func); } /** * Imports the data from file to database. * * @param reader * @param offset * @param count * @param stmt * @param batchSize * @param batchInterval * @param func convert line to the parameters for record insert. Returns a null array to skip the line. * @return * @throws UncheckedSQLException */ public static long importData(final Reader reader, long offset, final long count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can't be negative", offset, count); N.checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); long result = 0; final BufferedReader br = ObjectFactory.createBufferedReader(reader); try { while (offset-- > 0 && br.readLine() != null) { } String line = null; Object[] row = null; while (result < count && (line = br.readLine()) != null) { row = func.apply(line); if (row == null) { continue; } for (int i = 0, len = row.length; i < len; i++) { stmt.setObject(i + 1, row[i]); } stmt.addBatch(); if ((++result % batchSize) == 0) { stmt.executeBatch(); stmt.clearBatch(); if (batchInterval > 0) { N.sleep(batchInterval); } } } if ((result % batchSize) > 0) { stmt.executeBatch(); stmt.clearBatch(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(br); } return result; } public static long importData(final Iterator iter, final Connection conn, final String insertSQL, final Try.Function func) throws UncheckedSQLException, E { return importData(iter, 0, Long.MAX_VALUE, conn, insertSQL, 200, 0, func); } public static long importData(final Iterator iter, final long offset, final long count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(iter, offset, count, stmt, batchSize, batchInterval, func); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } public static long importData(final Iterator iter, final PreparedStatement stmt, final Try.Function func) throws E { return importData(iter, 0, Long.MAX_VALUE, stmt, 200, 0, func); } /** * Imports the data from Iterator to database. * * @param iter * @param offset * @param count * @param stmt * @param batchSize * @param batchInterval * @param func convert element to the parameters for record insert. Returns a null array to skip the line. * @return * @throws UncheckedSQLException */ public static long importData(final Iterator iter, long offset, final long count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.Function func) throws UncheckedSQLException, E { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can't be negative", offset, count); N.checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); long result = 0; try { while (offset-- > 0 && iter.hasNext()) { iter.next(); } Object[] row = null; while (result < count && iter.hasNext()) { row = func.apply(iter.next()); if (row == null) { continue; } for (int i = 0, len = row.length; i < len; i++) { stmt.setObject(i + 1, row[i]); } stmt.addBatch(); if ((++result % batchSize) == 0) { stmt.executeBatch(); stmt.clearBatch(); if (batchInterval > 0) { N.sleep(batchInterval); } } } if ((result % batchSize) > 0) { stmt.executeBatch(); stmt.clearBatch(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } return result; } public static long importData(final Iterator iter, final Connection conn, final String insertSQL, final Try.BiConsumer stmtSetter) { return importData(iter, 0, Long.MAX_VALUE, conn, insertSQL, 200, 0, stmtSetter); } public static long importData(final Iterator iter, final long offset, final long count, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) { return importData(iter, offset, count, Fn.alwaysTrue(), conn, insertSQL, batchSize, batchInterval, stmtSetter); } /** * * @param iter * @param offset * @param count * @param filter * @param conn * @param insertSQL * @param batchSize * @param batchInterval * @param stmtSetter * @return * @throws UncheckedSQLException */ public static long importData(final Iterator iter, final long offset, final long count, final Try.Predicate filter, final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws UncheckedSQLException, E { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, insertSQL); return importData(iter, offset, count, filter, stmt, batchSize, batchInterval, stmtSetter); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { JdbcUtil.closeQuietly(stmt); } } public static long importData(final Iterator iter, final PreparedStatement stmt, final Try.BiConsumer stmtSetter) { return importData(iter, 0, Long.MAX_VALUE, stmt, 200, 0, stmtSetter); } public static long importData(final Iterator iter, long offset, final long count, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) { return importData(iter, offset, count, Fn.alwaysTrue(), stmt, batchSize, batchInterval, stmtSetter); } /** * Imports the data from Iterator to database. * * @param iter * @param offset * @param count * @param filter * @param stmt * @param batchSize * @param batchInterval * @param stmtSetter * @return * @throws UncheckedSQLException */ public static long importData(final Iterator iter, long offset, final long count, final Try.Predicate filter, final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws UncheckedSQLException, E { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can't be negative", offset, count); N.checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); long result = 0; try { while (offset-- > 0 && iter.hasNext()) { iter.next(); } T next = null; while (result < count && iter.hasNext()) { next = iter.next(); if (filter != null && filter.test(next) == false) { continue; } stmtSetter.accept(stmt, next); stmt.addBatch(); if ((++result % batchSize) == 0) { stmt.executeBatch(); stmt.clearBatch(); if (batchInterval > 0) { N.sleep(batchInterval); } } } if ((result % batchSize) > 0) { stmt.executeBatch(); stmt.clearBatch(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } return result; } public static void parse(final Connection conn, final String sql, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(conn, sql, rowParser, Fn.emptyAction()); } public static void parse(final Connection conn, final String sql, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { parse(conn, sql, 0, Long.MAX_VALUE, rowParser, onComplete); } public static void parse(final Connection conn, final String sql, final long offset, final long count, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(conn, sql, offset, count, rowParser, Fn.emptyAction()); } public static void parse(final Connection conn, final String sql, final long offset, final long count, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { parse(conn, sql, offset, count, 0, 0, rowParser, onComplete); } public static void parse(final Connection conn, final String sql, final long offset, final long count, final int processThreadNum, final int queueSize, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(conn, sql, offset, count, processThreadNum, queueSize, rowParser, Fn.emptyAction()); } /** * Parse the ResultSet obtained by executing query with the specified Connection and sql. * * @param conn * @param sql * @param offset * @param count * @param processThreadNum new threads started to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param rowParser * @param onComplete * @throws UncheckedSQLException */ public static void parse(final Connection conn, final String sql, final long offset, final long count, final int processThreadNum, final int queueSize, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { PreparedStatement stmt = null; try { stmt = prepareStatement(conn, sql); stmt.setFetchSize(200); parse(stmt, offset, count, processThreadNum, queueSize, rowParser, onComplete); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(stmt); } } public static void parse(final PreparedStatement stmt, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(stmt, rowParser, Fn.emptyAction()); } public static void parse(final PreparedStatement stmt, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { parse(stmt, 0, Long.MAX_VALUE, rowParser, onComplete); } public static void parse(final PreparedStatement stmt, final long offset, final long count, final Try.Consumer rowParser) throws E { parse(stmt, offset, count, rowParser, Fn.emptyAction()); } public static void parse(final PreparedStatement stmt, final long offset, final long count, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { parse(stmt, offset, count, 0, 0, rowParser, onComplete); } public static void parse(final PreparedStatement stmt, final long offset, final long count, final int processThreadNum, final int queueSize, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(stmt, offset, count, processThreadNum, queueSize, rowParser, Fn.emptyAction()); } /** * Parse the ResultSet obtained by executing query with the specified PreparedStatement. * * @param stmt * @param offset * @param count * @param processThreadNum new threads started to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param rowParser * @param onComplete * @throws UncheckedSQLException */ public static void parse(final PreparedStatement stmt, final long offset, final long count, final int processThreadNum, final int queueSize, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { ResultSet rs = null; try { rs = stmt.executeQuery(); parse(rs, offset, count, processThreadNum, queueSize, rowParser, onComplete); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(rs); } } public static void parse(final ResultSet rs, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(rs, rowParser, Fn.emptyAction()); } public static void parse(final ResultSet rs, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { parse(rs, 0, Long.MAX_VALUE, rowParser, onComplete); } public static void parse(final ResultSet rs, long offset, long count, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(rs, offset, count, rowParser, Fn.emptyAction()); } public static void parse(final ResultSet rs, long offset, long count, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { parse(rs, offset, count, 0, 0, rowParser, onComplete); } public static void parse(final ResultSet rs, long offset, long count, final int processThreadNum, final int queueSize, final Try.Consumer rowParser) throws UncheckedSQLException, E { parse(rs, offset, count, processThreadNum, queueSize, rowParser, Fn.emptyAction()); } /** * Parse the ResultSet. * * @param stmt * @param offset * @param count * @param processThreadNum new threads started to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param rowParser * @param onComplete * @throws UncheckedSQLException */ public static void parse(final ResultSet rs, long offset, long count, final int processThreadNum, final int queueSize, final Try.Consumer rowParser, final Try.Runnable onComplete) throws UncheckedSQLException, E, E2 { N.parse(new RowIterator(rs, false, false), offset, count, processThreadNum, queueSize, rowParser, onComplete); } public static long copy(final Connection sourceConn, final String selectSql, final Connection targetConn, final String insertSql) throws UncheckedSQLException { return copy(sourceConn, selectSql, 200, 0, Integer.MAX_VALUE, targetConn, insertSql, DEFAULT_STMT_SETTER, 200, 0, false); } /** * * @param sourceConn * @param selectSql * @param fetchSize * @param offset * @param count * @param targetConn * @param insertSql * @param stmtSetter * @param batchSize * @param batchInterval * @param inParallel do the read and write in separated threads. * @return * @throws UncheckedSQLException */ public static long copy(final Connection sourceConn, final String selectSql, final int fetchSize, final long offset, final long count, final Connection targetConn, final String insertSql, final Try.BiConsumer stmtSetter, final int batchSize, final int batchInterval, final boolean inParallel) throws UncheckedSQLException { PreparedStatement selectStmt = null; PreparedStatement insertStmt = null; int result = 0; try { insertStmt = targetConn.prepareStatement(insertSql); selectStmt = sourceConn.prepareStatement(selectSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); selectStmt.setFetchSize(fetchSize); copy(selectStmt, offset, count, insertStmt, stmtSetter, batchSize, batchInterval, inParallel); } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { closeQuietly(selectStmt); closeQuietly(insertStmt); } return result; } public static long copy(final PreparedStatement selectStmt, final PreparedStatement insertStmt, final Try.BiConsumer stmtSetter) throws UncheckedSQLException { return copy(selectStmt, 0, Integer.MAX_VALUE, insertStmt, stmtSetter, 200, 0, false); } /** * * @param selectStmt * @param offset * @param count * @param insertStmt * @param stmtSetter * @param batchSize * @param batchInterval * @param inParallel do the read and write in separated threads. * @return * @throws UncheckedSQLException */ public static long copy(final PreparedStatement selectStmt, final long offset, final long count, final PreparedStatement insertStmt, final Try.BiConsumer stmtSetter, final int batchSize, final int batchInterval, final boolean inParallel) throws UncheckedSQLException { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can't be negative", offset, count); N.checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); @SuppressWarnings("rawtypes") final Try.BiConsumer setter = (Try.BiConsumer) (stmtSetter == null ? DEFAULT_STMT_SETTER : stmtSetter); final AtomicLong result = new AtomicLong(); final Try.Consumer rowParser = new Try.Consumer() { @Override public void accept(Object[] row) { try { setter.accept(insertStmt, row); insertStmt.addBatch(); result.incrementAndGet(); if ((result.longValue() % batchSize) == 0) { insertStmt.executeBatch(); insertStmt.clearBatch(); if (batchInterval > 0) { N.sleep(batchInterval); } } } catch (SQLException e) { throw new UncheckedSQLException(e); } } }; final Try.Runnable onComplete = new Try.Runnable() { @Override public void run() { if ((result.longValue() % batchSize) > 0) { try { insertStmt.executeBatch(); insertStmt.clearBatch(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } } }; parse(selectStmt, offset, count, 0, inParallel ? DEFAULT_QUEUE_SIZE_FOR_ROW_PARSER : 0, rowParser, onComplete); return result.longValue(); } public static boolean doesTableExist(final Connection conn, final String tableName) { try { executeQuery(conn, "SELECT 1 FROM " + tableName + " WHERE 1 > 2"); return true; } catch (UncheckedSQLException e) { if (isTableNotExistsException(e)) { return false; } throw e; } } /** * Returns {@code true} if succeed to create table, otherwise {@code false} is returned. * * @param conn * @param tableName * @param schema * @return */ public static boolean createTableIfNotExists(final Connection conn, final String tableName, final String schema) { if (doesTableExist(conn, tableName)) { return false; } try { execute(conn, schema); return true; } catch (UncheckedSQLException e) { return false; } } /** * Returns {@code true} if succeed to drop table, otherwise {@code false} is returned. * * @param conn * @param tableName * @return */ public static boolean dropTableIfExists(final Connection conn, final String tableName) { try { if (doesTableExist(conn, tableName)) { execute(conn, "DROP TABLE " + tableName); return true; } } catch (UncheckedSQLException e) { // ignore. } return false; } /** * * @param conn * @param tableName * @return * @throws UncheckedSQLException */ public static List getColumnNameList(final Connection conn, final String tableName) throws UncheckedSQLException { DataSet dataSet = executeQuery(conn, "SELECT * FROM " + tableName + " WHERE 1 > 2"); List columnNameList = new ArrayList<>(dataSet.columnNameList().size()); for (String columName : dataSet.columnNameList()) { columnNameList.add(columName.intern()); } return columnNameList; } /** * * @param rs * @return * @throws UncheckedSQLException */ public static List getColumnLabelList(ResultSet rs) throws UncheckedSQLException { try { ResultSetMetaData metaData = rs.getMetaData(); final int columnCount = metaData.getColumnCount(); final List labelList = new ArrayList<>(columnCount); for (int i = 1, n = columnCount + 1; i < n; i++) { labelList.add(metaData.getColumnLabel(i)); } return labelList; } catch (SQLException e) { throw new UncheckedSQLException(e); } } static boolean isTableNotExistsException(final Throwable e) { if (e instanceof SQLException) { SQLException sqlException = (SQLException) e; if (sqlException.getSQLState() != null && sqlStateForTableNotExists.contains(sqlException.getSQLState())) { return true; } String msg = e.getMessage(); return N.notNullOrEmpty(msg) && (msg.contains("not exist") || msg.contains("doesn't exist") || msg.contains("not found")); } else if (e instanceof UncheckedSQLException) { UncheckedSQLException sqlException = (UncheckedSQLException) e; if (sqlException.getSQLState() != null && sqlStateForTableNotExists.contains(sqlException.getSQLState())) { return true; } String msg = e.getMessage(); return N.notNullOrEmpty(msg) && (msg.contains("not exist") || msg.contains("doesn't exist") || msg.contains("not found")); } return false; } static class SimpleDataSource implements DataSource { static final String PRIMARY = "primary"; private final javax.sql.DataSource sqlDataSource; private final Properties props = new Properties<>(); private final SliceSelector sliceSelector = new NonSliceSelector(); private final Method closeMethod; private boolean isClosed = false; public SimpleDataSource(final javax.sql.DataSource sqlDataSource) { this.sqlDataSource = sqlDataSource; Method method = null; try { method = ClassUtil.getDeclaredMethod(sqlDataSource.getClass(), "close"); } catch (Throwable e) { } closeMethod = method != null && Modifier.isPublic(method.getModifiers()) ? method : null; } @Override public Connection getConnection(final String username, final String password) throws SQLException { return sqlDataSource.getConnection(username, password); } @Override public PrintWriter getLogWriter() throws SQLException { return sqlDataSource.getLogWriter(); } @Override public void setLogWriter(final PrintWriter out) throws SQLException { sqlDataSource.setLogWriter(out); } @Override public void setLoginTimeout(final int seconds) throws SQLException { sqlDataSource.setLoginTimeout(seconds); } @Override public int getLoginTimeout() throws SQLException { return sqlDataSource.getLoginTimeout(); } @Override public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { return sqlDataSource.getParentLogger(); } @Override public T unwrap(final Class iface) throws SQLException { return sqlDataSource.unwrap(iface); } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return sqlDataSource.isWrapperFor(iface); } @Override public Connection getConnection() { try { return sqlDataSource.getConnection(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } @Override public Connection getReadOnlyConnection() { try { return sqlDataSource.getConnection(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } @Override public SliceSelector getSliceSelector() { return sliceSelector; } @Override public String getName() { return PRIMARY; } @Override public Properties getProperties() { return props; } @Override public int getMaxActive() { throw new UnsupportedOperationException(); } @Override public int getCurrentActive() { throw new UnsupportedOperationException(); } @Override public void close() { if (isClosed) { return; } if (closeMethod != null) { try { ClassUtil.invokeMethod(sqlDataSource, closeMethod); } catch (Throwable e) { // ignore. } } isClosed = true; } @Override public boolean isClosed() { return isClosed; } } static class SimpleDataSourceManager implements DataSourceManager { private final DataSource primaryDataSource; private final Map activeDataSources; private final Properties props = new Properties<>(); private final DataSourceSelector dataSourceSelector = new SimpleSourceSelector(); private boolean isClosed = false; public SimpleDataSourceManager(final DataSource ds) { this.primaryDataSource = ds; if (N.isNullOrEmpty(ds.getName())) { this.activeDataSources = N.asMap(SimpleDataSource.PRIMARY, ds); } else { this.activeDataSources = N.asMap(ds.getName(), ds); } } @Override public DataSource getPrimaryDataSource() { return primaryDataSource; } @Override public Map getActiveDataSources() { return activeDataSources; } @Override public DataSourceSelector getDataSourceSelector() { return dataSourceSelector; } @Override public Properties getProperties() { return props; } @Override public void close() { if (isClosed) { return; } primaryDataSource.close(); isClosed = true; } @Override public boolean isClosed() { return isClosed; } } }