com.google.sitebricks.persist.sql.Sql Maven / Gradle / Ivy
package com.google.sitebricks.persist.sql;
import com.google.common.collect.ImmutableMap;
import org.slf4j.LoggerFactory;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A simplified API to execute SQL statements against. This is what the
* EntityStore itself uses to manage the SQL interface. Use this as a low-level,
* implementation-specific API, as needed.
*
* @author [email protected] (Dhanji R. Prasanna)
*/
public class Sql {
static final Pattern NAMED_ARG_PATTERN = Pattern.compile("(@[\\w_]+)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private final Connection connection;
public Sql(Connection connection) {
this.connection = connection;
}
public void execute(String sql) {
query(sql);
}
public void execute(String sql, Map params) {
query(sql, params);
}
public ResultSet query(String sql) {
return query(sql, ImmutableMap.of());
}
public ResultSet query(String sql, Map params) {
try {
Matcher matcher = Sql.NAMED_ARG_PATTERN.matcher(sql);
Map positionalParams = toPositionalMap(params, matcher);
matcher.reset();
sql = matcher.replaceAll("?");
PreparedStatement statement = connection.prepareStatement(sql);
for (int i = 1; i <= positionalParams.size(); i++) {
statement.setObject(i, positionalParams.get(i));
}
if (statement.execute())
return statement.getResultSet();
else {
statement.close();
return null;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Map toPositionalMap(Map params, Matcher matcher) {
boolean find = matcher.find();
Map positionalParams = new HashMap();
int index = 1;
while (find) {
Object value = params.get(matcher.group().substring(1));
if (value == null) {
throw new IllegalArgumentException("Named parameter map for SQL statement did" +
" not contain required parameter: " + matcher.group());
}
positionalParams.put(index, value);
find = matcher.find(matcher.end());
index++;
}
return positionalParams;
}
public boolean tableExists(String name) {
try {
boolean exists = connection.getMetaData().getTables(null, null, name, null).next();
// Try upper-case object name in case there is some provider-specific weirdness.
if (!exists)
return connection.getMetaData().getTables(null, null, name.toUpperCase(), null).next();
else
return exists;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public List