/*
* Copyright (c) 2013 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.io.jdbc;
import java.net.URI;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import javax.annotation.Nullable;
import eu.esdihumboldt.hale.common.core.io.project.ProjectInfoService;
import eu.esdihumboldt.hale.common.core.io.project.ProjectVariableReplacer;
import eu.esdihumboldt.hale.common.core.service.ServiceProvider;
import eu.esdihumboldt.hale.io.jdbc.extension.JDBCSchemaReaderAdvisor;
/**
* JDBC utility methods.
*
* @author Kai Schwierczek
* @author Simon Templer
*/
public class JDBCUtil {
/**
* Removes one pair of leading/trailing quotes ("x" or 'x' or `x` becomes
* x).
*
* @param s the string to remove quotes from
* @return the string with one pair of quotes less if possible
*/
public static String unquote(String s) {
if (s == null) {
return null;
}
char startChar = s.charAt(0);
char endChar = s.charAt(s.length() - 1);
if ((startChar == '\'' || startChar == '"' || startChar == '`') && startChar == endChar)
return s.substring(1, s.length() - 1);
else
return s;
}
/**
* Adds a pair of quotes ("x") if no quotes (" or ') are present.
*
* @param s the string to quote
* @return the quoted string
*/
public static String quote(String s) {
if (s == null) {
return null;
}
char startChar = s.charAt(0);
char endChar = s.charAt(s.length() - 1);
if ((startChar == '\'' || startChar == '"') && startChar == endChar)
return s; // already quoted
else
return '"' + s + '"';
}
/**
* Determine the identifier quote string for a given JDBC connection.
*
* @param connection the JDBC connection
* @return the quote string
*/
public static String determineQuoteString(Connection connection) {
String quotes = "\"";
try {
quotes = connection.getMetaData().getIdentifierQuoteString();
if (quotes.trim().isEmpty()) {
quotes = "";
}
} catch (SQLException e) {
// can't do anything about that
}
return quotes;
}
/**
* Determine the namespace for a JDBC source-
*
* @param jdbcURI the JDBC connection URI
* @param advisor the schema reader advisor, if applicable
* @return the namespace
*/
public static String determineNamespace(URI jdbcURI,
@Nullable JDBCSchemaReaderAdvisor advisor) {
URI specificURI;
try {
specificURI = URI.create(jdbcURI.getRawSchemeSpecificPart());
} catch (Exception e) {
specificURI = jdbcURI;
}
StringBuilder ns = new StringBuilder();
if (specificURI.getScheme() != null) {
if (!specificURI.getScheme().equals("jdbc")) {
ns.append("jdbc:");
}
ns.append(specificURI.getScheme());
}
if (specificURI.getPath() != null) {
String path = null;
if (advisor != null) {
path = advisor.adaptPathForNamespace(specificURI.getPath());
}
else {
// default handling
path = specificURI.getPath();
if (path.startsWith("/")) {
path = path.substring(1);
}
}
if (path != null && !path.isEmpty()) {
if (ns.length() > 0) {
ns.append(':');
}
ns.append(path);
}
}
String overallNamespace = ns.toString();
if (overallNamespace == null) {
overallNamespace = "";
}
return overallNamespace;
}
/**
* Replace variables in an SQL query.
*
* @param query the query
* @param services the service provider
* @return the query with variables replaced
*/
public static String replaceVariables(String query, ServiceProvider services) {
if (services != null) {
ProjectInfoService projectInfo = services.getService(ProjectInfoService.class);
ProjectVariableReplacer replacer = new ProjectVariableReplacer(projectInfo);
return replacer.replaceVariables(query, true);
}
return query;
}
/**
* Create a statement for a default read-only iteration query.
*
* @param connection the JDBC connection
* @param fetchSize the batch fetch size, should be greater than zero
* @return the statement
* @throws SQLException if the statement cannot be created
*/
public static Statement createReadStatement(Connection connection, int fetchSize)
throws SQLException {
Statement st;
try {
st = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
} catch (SQLFeatureNotSupportedException e) {
// Oracle Database supports only HOLD_CURSORS_OVER_COMMIT
st = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
}
st.setFetchSize(fetchSize);
return st;
}
}