/*
* Copyright 2007 - 2017 the original author or authors.
*
* 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 net.sf.jailer.ui.databrowser;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sf.jailer.configuration.DBMS;
import net.sf.jailer.database.Session;
import net.sf.jailer.datamodel.Column;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.util.CellContentConverter;
import net.sf.jailer.util.Quoting;
import net.sf.jailer.util.SqlUtil;
/**
* Builder for Insert/Delete/Update statements.
*
* @author Ralf Wisser
*/
public class SQLDMLBuilder {
/**
* Build Update statements.
*
* @param table the table
* @param rows rows
* @param session current DB session
* @return update statements for rows
*/
public static String buildUpdate(Table table, List<Row> rows, Session session) {
StringBuilder sb = new StringBuilder();
for (Row row: unique(rows)) {
sb.append(buildUpdate(table, row, false, session)).append(";" + LF + LF);
}
return sb.toString();
}
/**
* Build Update statements.
*
* @param table the table
* @param row row to be updated
* @param session current DB session
* @return update statement for row
*/
public static String buildUpdate(Table table, Row row, boolean withComments, Session session) {
Quoting quoting;
try {
quoting = new Quoting(session);
} catch (SQLException e) {
throw new RuntimeException(e);
}
String sql = "Update " + table.getName() + " " + LF + "Set ";
boolean f = true;
int i = 0;
CellContentConverter cellContentConverter = new CellContentConverter(null, session, session.dbms);
for (Column column : table.getColumns()) {
String value = getSQLLiteral(row.values[i++], cellContentConverter);
if (value == null) {
continue;
}
if (column.isVirtualOrBlocked(session)) {
continue;
}
String name = quoting.requote(column.name);
sql += (f? "" : ", " + LF + " ") + name + " = " + value + comment(withComments, column, false);
f = false;
}
sql += " " + LF + "Where " + SqlUtil.replaceAliases(row.rowId, null, null);
return sql;
}
private static String comment(boolean withComments, Column column, boolean withName) {
if (withComments) {
return " /* " + (withName? column.toSQL(null) : (column.toSQL(null).substring(column.name.length())).trim()) + " */";
}
return "";
}
/**
* Build Insert statements.
*
* @param table the table
* @param rows rows
* @param session current DB session
* @return insert statements for rows
*/
public static String buildInsert(Table table, List<Row> rows, Session session) {
StringBuilder sb = new StringBuilder();
for (Row row: unique(rows)) {
sb.append(buildInsert(table, row, false, session)).append(";" + LF + LF);
}
return sb.toString();
}
/**
* Build Insert statements.
*
* @param table the table
* @param row row to be updated
* @param session current DB session
* @return update statement for row
*/
public static String buildInsert(Table table, Row row, boolean withComments, Session session) {
Quoting quoting;
try {
quoting = new Quoting(session);
} catch (SQLException e) {
throw new RuntimeException(e);
}
String sql = "Insert into " + table.getName() + " (" + LF + " ";
String values = "";
boolean f = true;
int i = 0;
CellContentConverter cellContentConverter = new CellContentConverter(null, session, session.dbms);
for (Column column : table.getColumns()) {
String value = getSQLLiteral(row.values[i++], cellContentConverter);
if (value == null) {
continue;
}
if (column.isVirtualOrBlocked(session)) {
continue;
}
String name = quoting.requote(column.name);
sql += (f? "" : ", " + LF + " ") + name + comment(withComments, column, false);
values += (f? "" : ", " + LF + " ") + value + comment(withComments, column, true);
f = false;
}
sql += ") " + LF + "Values (" + LF + " " + values + ")";
return sql;
}
/**
* Build Delete statements.
*
* @param table the table
* @param row row to be updated
* @param session current DB session
* @return update statement for row
*/
public static String buildDelete(Table table, Row row, boolean withComments, Session session) {
String sql = "Delete from " + table.getName() + " Where " + SqlUtil.replaceAliases(row.rowId, null, null);
return sql;
}
/**
* Build Delete statements.
*
* @param table the table
* @param rows rows
* @param session current DB session
* @return delete statements for rows
*/
public static String buildDelete(Table table, List<Row> rows, Session session) {
StringBuilder sb = new StringBuilder();
for (Row row: unique(rows)) {
sb.append(buildDelete(table, row, false, session)).append(";" + LF + "");
}
return sb.toString();
}
/**
* Removes all duplicates out of a list of rows.
*
* @param rows list of rows
* @return list of rows without duplicates
*/
private static List<Row> unique(List<Row> rows) {
List<Row> result = new ArrayList<Row>();
Set<String> ids = new HashSet<String>();
for (Row row: rows) {
if (row.rowId.length() == 0 || !ids.contains(row.rowId)) {
ids.add(row.rowId);
result.add(row);
}
}
return result;
}
/**
* Gets SQL literal for a given object. Returns <code>null</code> if the object cannot be converted into a SQL literal (LOBs).
*
* @param value the value
* @param cellContentConverter
* @return SQL literal or <code>null</code>
*/
private static String getSQLLiteral(Object value, CellContentConverter cellContentConverter) {
if (value instanceof LobValue) {
return null;
}
return cellContentConverter.toSql(value);
}
private static final String LF = System.getProperty("line.separator", "\n");
}