package org.openlca.core.database.internal;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Writes the complete content of a database as insert statements to a SQL file.
*/
public class SQLScriptWriter {
private Connection con;
private BufferedWriter writer;
private Logger log = LoggerFactory.getLogger(getClass());
public void write(Connection con, File file) throws Exception {
setUp(con, file);
List<String> tables = getTables();
for (String table : tables) {
try (ResultSet rs = query("SHOW COLUMNS FROM " + table)) {
List<String> fields = new ArrayList<>();
while (rs.next()) {
fields.add(rs.getString(1));
}
exportTable(table, fields);
}
}
close();
}
private List<String> getTables() throws Exception, SQLException {
List<String> tables = new ArrayList<>();
try (ResultSet rs = query("SHOW TABLES")) {
while (rs.next()) {
String tableName = rs.getString(1).toLowerCase();
if (!"openlca_version".equalsIgnoreCase(tableName))
tables.add(tableName);
}
}
return tables;
}
private void setUp(Connection con, File file) throws IOException {
log.trace("set up writer for file {}", file);
this.con = con;
if (!file.exists())
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter wout = new OutputStreamWriter(fos, "UTF-8");
writer = new BufferedWriter(wout);
}
private void close() throws IOException, SQLException {
log.trace("close connection and file");
writer.flush();
writer.close();
con.close();
}
// cannot close statements => resultset will be closed too
private ResultSet query(String sql) throws Exception {
log.trace("execute query {}", sql);
Statement statement = con.createStatement();
return statement.executeQuery(sql);
}
private String getFieldLine(List<String> fields) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < fields.size(); i++) {
builder.append(fields.get(i));
if (i < fields.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
}
private void exportTable(String tableName, List<String> fields)
throws Exception {
log.trace("Export table {}", tableName);
try (ResultSet rs = query("SELECT * FROM " + tableName)) {
while (rs.next()) {
String valueLine = getValueLine(rs, fields);
writer.write("INSERT INTO ");
writer.write(tableName);
writer.write("(");
writer.write(getFieldLine(fields));
writer.write(") VALUES (");
writer.write(valueLine);
writer.write(");");
writer.newLine();
}
}
writer.newLine();
}
private String getValueLine(ResultSet rs, List<String> fields)
throws SQLException {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < fields.size(); i++) {
Object o = rs.getObject(fields.get(i));
if (o instanceof String || o instanceof Date) {
builder.append("'");
appendString(o.toString(), builder);
builder.append("'");
} else {
builder.append(o);
}
if (i < fields.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
}
private void appendString(String string, StringBuilder builder) {
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (c == '\'' || c == '\\') {
builder.append('\\');
}
builder.append(c);
}
}
}