sascha@372: package de.intevation.flys.artifacts.services.meta; sascha@372: sascha@372: import java.util.regex.Pattern; sascha@372: import java.util.regex.Matcher; sascha@372: sascha@372: import java.util.List; sascha@372: import java.util.Map; sascha@972: import java.util.TreeMap; sascha@372: import java.util.ArrayList; sascha@372: sascha@372: import java.sql.PreparedStatement; sascha@372: import java.sql.SQLException; sascha@372: import java.sql.Connection; sascha@372: import java.sql.ResultSet; sascha@372: sascha@972: import net.sf.ehcache.Cache; sascha@972: import net.sf.ehcache.Element; sascha@972: sascha@972: import de.intevation.flys.artifacts.cache.CacheFactory; sascha@972: sascha@372: public class CompiledStatement sascha@372: { sascha@972: public static final String DATACAGE_DB_CACHE = sascha@972: "datacage.db"; sascha@972: sascha@969: public static final Pattern VAR = sascha@969: Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); sascha@372: sascha@372: protected String original; sascha@372: protected String statement; sascha@372: sascha@372: protected Map> positions; sascha@372: sascha@973: protected int numVars; sascha@372: sascha@973: public class Instance { sascha@973: sascha@973: protected PreparedStatement preparedStatement; sascha@973: sascha@973: public Instance() { sascha@973: } sascha@973: sascha@973: protected ResultData executeCached( sascha@973: Cache cache, sascha@973: Connection connection, sascha@973: StackFrames frames sascha@973: ) sascha@973: throws SQLException sascha@973: { sascha@973: Object [] values = new Object[numVars]; sascha@973: sascha@973: StringBuilder sb = new StringBuilder(original); sascha@973: sascha@973: for (Map.Entry> entry: positions.entrySet()) { sascha@973: String key = entry.getKey(); sascha@973: Object value = frames.get(key); sascha@973: sb.append(';').append(key).append(':').append(value); sascha@973: for (Integer index: entry.getValue()) { sascha@973: values[index] = value; sascha@973: } sascha@973: } sascha@973: sascha@973: // XXX: Maybe too many collisions? sascha@973: // String key = original + Arrays.hashCode(values); sascha@973: String key = sb.toString(); sascha@973: sascha@973: Element element = cache.get(key); sascha@973: sascha@973: if (element != null) { sascha@973: return (ResultData)element.getValue(); sascha@973: } sascha@973: sascha@973: if (preparedStatement == null) { sascha@973: preparedStatement = connection.prepareStatement(statement); sascha@973: } sascha@973: sascha@973: for (int i = 0; i < values.length; ++i) { sascha@973: preparedStatement.setObject(i+1, values[i]); sascha@973: } sascha@973: sascha@973: ResultData data; sascha@973: sascha@973: ResultSet result = preparedStatement.executeQuery(); sascha@973: try { sascha@973: data = new ResultData(preparedStatement.getMetaData()) sascha@973: .addAll(result); sascha@973: } sascha@973: finally { sascha@973: result.close(); sascha@973: } sascha@973: sascha@973: element = new Element(key, data); sascha@973: cache.put(element); sascha@973: sascha@973: return data; sascha@973: } sascha@973: sascha@973: protected ResultData executeUncached( sascha@973: Connection connection, sascha@973: StackFrames frames sascha@973: ) sascha@973: throws SQLException sascha@973: { sascha@973: if (preparedStatement == null) { sascha@973: preparedStatement = connection.prepareStatement(statement); sascha@973: } sascha@973: sascha@973: for (Map.Entry> entry: positions.entrySet()) { sascha@973: Object value = frames.get(entry.getKey()); sascha@973: for (Integer index: entry.getValue()) { sascha@973: preparedStatement.setObject(index+1, value); sascha@973: } sascha@973: } sascha@973: sascha@973: ResultSet result = preparedStatement.executeQuery(); sascha@973: try { sascha@973: return new ResultData(preparedStatement.getMetaData()) sascha@973: .addAll(result); sascha@973: } sascha@973: finally { sascha@973: result.close(); sascha@973: } sascha@973: } sascha@973: sascha@973: public ResultData execute(Connection connection, StackFrames frames) sascha@973: throws SQLException sascha@973: { sascha@973: Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); sascha@973: sascha@973: return cache != null sascha@973: ? executeCached(cache, connection, frames) sascha@973: : executeUncached(connection, frames); sascha@973: } sascha@973: sascha@973: public void close() { sascha@973: if (preparedStatement != null) { sascha@973: try { sascha@973: preparedStatement.close(); sascha@973: } sascha@973: catch (SQLException sqle) { sascha@973: } sascha@973: preparedStatement = null; sascha@973: } sascha@973: } sascha@973: } // class Instance sascha@972: sascha@372: public CompiledStatement() { sascha@372: } sascha@372: sascha@372: public CompiledStatement(String original) { sascha@372: this.original = original; sascha@972: // TreeMap to ensure order sascha@972: positions = new TreeMap>(); sascha@372: compile(); sascha@372: } sascha@372: sascha@372: protected void compile() { sascha@372: sascha@372: StringBuffer sb = new StringBuffer(); sascha@372: sascha@372: Matcher m = VAR.matcher(original); sascha@372: sascha@972: int index = 0; sascha@372: sascha@372: while (m.find()) { sascha@372: String key = m.group(1); sascha@372: List indices = positions.get(key); sascha@372: if (indices == null) { sascha@372: indices = new ArrayList(); sascha@372: positions.put(key, indices); sascha@372: } sascha@372: indices.add(index); sascha@372: m.appendReplacement(sb, "?"); sascha@372: ++index; sascha@372: } sascha@372: sascha@372: m.appendTail(sb); sascha@372: sascha@972: numVars = index; sascha@972: sascha@372: statement = sb.toString(); sascha@372: } sascha@372: sascha@372: public String getStatement() { sascha@372: return statement; sascha@372: } sascha@372: } sascha@372: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :