/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.tools.data.partitioning.sql.builder.exporter;
import com.liferay.portal.tools.data.partitioning.sql.builder.exporter.context.ExportContext;
import com.liferay.portal.tools.data.partitioning.sql.builder.internal.exporter.ExportProcess;
import com.liferay.portal.tools.data.partitioning.sql.builder.internal.exporter.SQLBuilder;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Manuel de la Peña
*/
public abstract class BaseDataPartitioningExporter
implements DataPartitioningExporter, DBExporter, DBProvider {
public BaseDataPartitioningExporter() {
_sqlBuilder = new InsertSQLBuilder();
}
public BaseDataPartitioningExporter(SQLBuilder sqlBuilder) {
_sqlBuilder = sqlBuilder;
}
@Override
public void export(ExportContext exportContext) {
initializeDatabase(exportContext.getProperties());
ExportProcess exportProcess = new ExportProcess(this);
try {
exportProcess.export(exportContext);
}
catch (IOException ioe) {
_logger.error("Unable to export", ioe);
}
}
@Override
public List<String> getControlTableNames(ExportContext exportContext) {
return getTableNames(getControlTableNamesSQL(exportContext));
}
@Override
public DataSource getDataSource() {
return _dataSource;
}
@Override
public int getFetchSize() {
return 0;
}
@Override
public String getOutputFileExtension() {
return ".sql";
}
@Override
public List<String> getPartitionedTableNames(ExportContext exportContext) {
return getTableNames(getPartitionedTableNamesSQL(exportContext));
}
@Override
public void write(
long companyId, String tableName, OutputStream outputStream) {
DataSource dataSource = getDataSource();
String sql = "select * from " + tableName;
if (companyId > 0) {
sql += " where companyId = ?";
}
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = buildPreparedStatement(
connection, sql, companyId);
ResultSet resultSet = preparedStatement.executeQuery()) {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
while (resultSet.next()) {
String[] fields = new String[columnCount];
for (int i = 0; i < columnCount; i++) {
fields[i] = _sqlBuilder.buildField(
resultSet.getObject(i + 1));
}
String insertSQL = _sqlBuilder.buildInsert(tableName, fields);
outputStream.write(insertSQL.getBytes());
}
}
catch (IOException | SQLException e) {
_logger.error(
"Unable to generate insert SQL statements for table " +
tableName,
e);
}
}
@Override
public void write(String tableName, OutputStream outputStream) {
write(0, tableName, outputStream);
}
@Override
public void writeDelete(
long companyId, String tableName, OutputStream outputStream) {
DataSource dataSource = getDataSource();
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = buildPreparedStatement(
connection,
"select count(1) from " + tableName + " where companyId = ?",
companyId);
ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next() && (resultSet.getInt(1) > 0)) {
String deleteSQL =
"delete from " + tableName + " where companyId = " +
companyId + ";\n";
outputStream.write(deleteSQL.getBytes());
}
}
catch (IOException | SQLException e) {
_logger.error(
"Unable to generate delete SQL statements for table " +
tableName,
e);
}
}
protected PreparedStatement buildPreparedStatement(
Connection connection, String sql, long companyId)
throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement(
sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
preparedStatement.setFetchSize(getFetchSize());
if (companyId > 0) {
preparedStatement.setLong(1, companyId);
}
return preparedStatement;
}
protected abstract String getControlTableNamesSQL(
ExportContext exportContext);
protected abstract String getPartitionedTableNamesSQL(
ExportContext exportContext);
protected List<String> getTableNames(String sql) {
List<String> tableNames = new ArrayList<>();
DataSource dataSource = getDataSource();
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
sql);
ResultSet resultSet = preparedStatement.executeQuery()) {
while (resultSet.next()) {
tableNames.add(resultSet.getString(getTableNameFieldName()));
}
}
catch (SQLException sqle) {
_logger.error(
"Unable to get table names using SQL query: " + sql, sqle);
}
return tableNames;
}
protected void initializeDatabase(Properties properties) {
HikariConfig hikariConfig = new HikariConfig(properties);
_dataSource = new HikariDataSource(hikariConfig);
}
private static final Logger _logger = LoggerFactory.getLogger(
BaseDataPartitioningExporter.class);
private DataSource _dataSource;
private final SQLBuilder _sqlBuilder;
}