1.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java Mon Mar 04 17:06:42 2019 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,192 +0,0 @@
1.4 -/**
1.5 - * SQL-DK
1.6 - * Copyright © 2013 František Kučera (frantovo.cz)
1.7 - *
1.8 - * This program is free software: you can redistribute it and/or modify
1.9 - * it under the terms of the GNU General Public License as published by
1.10 - * the Free Software Foundation, either version 3 of the License, or
1.11 - * (at your option) any later version.
1.12 - *
1.13 - * This program is distributed in the hope that it will be useful,
1.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.16 - * GNU General Public License for more details.
1.17 - *
1.18 - * You should have received a copy of the GNU General Public License
1.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
1.20 - */
1.21 -package info.globalcode.sql.dk;
1.22 -
1.23 -import static info.globalcode.sql.dk.jmx.ConnectionManagement.incrementCounter;
1.24 -import static info.globalcode.sql.dk.jmx.ConnectionManagement.resetCounter;
1.25 -import info.globalcode.sql.dk.batch.Batch;
1.26 -import info.globalcode.sql.dk.batch.BatchException;
1.27 -import info.globalcode.sql.dk.configuration.DatabaseDefinition;
1.28 -import info.globalcode.sql.dk.configuration.Loader;
1.29 -import info.globalcode.sql.dk.configuration.Properties;
1.30 -import info.globalcode.sql.dk.formatting.ColumnsHeader;
1.31 -import info.globalcode.sql.dk.formatting.Formatter;
1.32 -import info.globalcode.sql.dk.jmx.ConnectionManagement;
1.33 -import info.globalcode.sql.dk.jmx.ConnectionManagement.COUNTER;
1.34 -import java.sql.Connection;
1.35 -import java.sql.PreparedStatement;
1.36 -import java.sql.ResultSet;
1.37 -import java.sql.SQLException;
1.38 -import java.sql.SQLWarning;
1.39 -import java.util.logging.Level;
1.40 -import java.util.logging.Logger;
1.41 -
1.42 -/**
1.43 - * Represents connected database. Is derived from {@linkplain DatabaseDefinition}.
1.44 - * Wraps {@linkplain Connection}.
1.45 - *
1.46 - * Is responsible for executing {@linkplain SQLCommand} and passing results to the
1.47 - * {@linkplain Formatter}.
1.48 - *
1.49 - * @author Ing. František Kučera (frantovo.cz)
1.50 - */
1.51 -public class DatabaseConnection implements AutoCloseable {
1.52 -
1.53 - private static final Logger log = Logger.getLogger(DatabaseConnection.class.getName());
1.54 - public static final String JDBC_PROPERTY_USER = "user";
1.55 - public static final String JDBC_PROPERTY_PASSWORD = "password";
1.56 - private final DatabaseDefinition databaseDefinition;
1.57 - private final Connection connection;
1.58 - private final Properties properties;
1.59 - /**
1.60 - * Could be null = JMX is disabled → must check, see functions in
1.61 - * {@linkplain ConnectionManagement}
1.62 - */
1.63 - private final ConnectionManagement connectionMBean;
1.64 -
1.65 - /**
1.66 - *
1.67 - * @param databaseDefinition DB url, name, password etc.
1.68 - * @param properties additional properties from CLI
1.69 - * @param connectionMBean JMX management bean | null = disabled JMX reporting
1.70 - * @throws SQLException
1.71 - */
1.72 - public DatabaseConnection(DatabaseDefinition databaseDefinition, Properties properties, ConnectionManagement connectionMBean) throws SQLException {
1.73 - this.databaseDefinition = databaseDefinition;
1.74 - this.properties = properties;
1.75 - this.connectionMBean = connectionMBean;
1.76 - this.connection = Loader.jdbcConnect(databaseDefinition, properties);
1.77 - }
1.78 -
1.79 - public void executeQuery(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
1.80 - formatter.writeStartBatch();
1.81 - formatter.writeStartDatabase(databaseDefinition);
1.82 - formatter.writeStartStatement();
1.83 - formatter.writeQuery(sqlCommand.getQuery());
1.84 - formatter.writeParameters(sqlCommand.getParameters());
1.85 - processCommand(sqlCommand, formatter);
1.86 - formatter.writeEndStatement();
1.87 - formatter.writeEndDatabase();
1.88 - formatter.writeEndBatch();
1.89 - }
1.90 -
1.91 - public void executeBatch(Batch batch, Formatter formatter) throws SQLException, BatchException {
1.92 - formatter.writeStartBatch();
1.93 - formatter.writeStartDatabase(databaseDefinition);
1.94 - while (batch.hasNext()) {
1.95 - SQLCommand sqlCommand = batch.next();
1.96 - formatter.writeStartStatement();
1.97 - formatter.writeQuery(sqlCommand.getQuery());
1.98 - formatter.writeParameters(sqlCommand.getParameters());
1.99 - processCommand(sqlCommand, formatter);
1.100 - formatter.writeEndStatement();
1.101 - }
1.102 - formatter.writeEndDatabase();
1.103 - formatter.writeEndBatch();
1.104 - }
1.105 -
1.106 - private void processCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
1.107 - incrementCounter(connectionMBean, COUNTER.COMMAND);
1.108 - resetCounter(connectionMBean, COUNTER.RECORD_CURRENT);
1.109 -
1.110 - try (PreparedStatement ps = sqlCommand.prepareStatement(connection)) {
1.111 - log.log(Level.FINE, "Statement prepared");
1.112 - sqlCommand.parametrize(ps);
1.113 -
1.114 - boolean isRS = ps.execute();
1.115 - log.log(Level.FINE, "Statement executed");
1.116 - if (isRS) {
1.117 - try (ResultSet rs = ps.getResultSet()) {
1.118 - processResultSet(rs, formatter);
1.119 - }
1.120 - } else {
1.121 - processUpdateResult(ps, formatter);
1.122 - }
1.123 - logWarnings(ps);
1.124 -
1.125 - while (ps.getMoreResults() || ps.getUpdateCount() > -1) {
1.126 - ResultSet rs = ps.getResultSet();
1.127 - if (rs == null) {
1.128 - processUpdateResult(ps, formatter);
1.129 - } else {
1.130 - processResultSet(rs, formatter);
1.131 - rs.close();
1.132 - }
1.133 - logWarnings(ps);
1.134 - }
1.135 - }
1.136 - }
1.137 -
1.138 - private void processUpdateResult(PreparedStatement ps, Formatter formatter) throws SQLException {
1.139 - formatter.writeUpdatesResult(ps.getUpdateCount());
1.140 - }
1.141 -
1.142 - private void processResultSet(ResultSet rs, Formatter formatter) throws SQLException {
1.143 - formatter.writeStartResultSet(new ColumnsHeader(rs.getMetaData()));
1.144 -
1.145 - int columnCount = rs.getMetaData().getColumnCount();
1.146 -
1.147 - while (rs.next()) {
1.148 - incrementCounter(connectionMBean, COUNTER.RECORD_CURRENT);
1.149 - incrementCounter(connectionMBean, COUNTER.RECORD_TOTAL);
1.150 -
1.151 - formatter.writeStartRow();
1.152 -
1.153 - for (int i = 1; i <= columnCount; i++) {
1.154 - formatter.writeColumnValue(rs.getObject(i));
1.155 - }
1.156 -
1.157 - formatter.writeEndRow();
1.158 - }
1.159 -
1.160 - formatter.writeEndResultSet();
1.161 - }
1.162 -
1.163 - private void logWarnings(PreparedStatement ps) throws SQLException {
1.164 - SQLWarning w = ps.getWarnings();
1.165 - while (w != null) {
1.166 - log.log(Level.WARNING, "SQL: {0}", w.getLocalizedMessage());
1.167 - w = w.getNextWarning();
1.168 - }
1.169 - ps.clearWarnings();
1.170 - }
1.171 -
1.172 - /**
1.173 - * Tests if this connection is live.
1.174 - *
1.175 - * @return true if test was successful
1.176 - * @throws SQLException if test fails
1.177 - */
1.178 - public boolean test() throws SQLException {
1.179 - connection.getAutoCommit();
1.180 - return true;
1.181 - }
1.182 -
1.183 - public String getProductName() throws SQLException {
1.184 - return connection.getMetaData().getDatabaseProductName();
1.185 - }
1.186 -
1.187 - public String getProductVersion() throws SQLException {
1.188 - return connection.getMetaData().getDatabaseProductVersion();
1.189 - }
1.190 -
1.191 - @Override
1.192 - public void close() throws SQLException {
1.193 - connection.close();
1.194 - }
1.195 -}