# HG changeset patch # User Sascha L. Teichmann # Date 1311446828 0 # Node ID c30ada285d4516fe7eb47f4164cdf35a1ca690d1 # Parent 0c8aca463bd4a491a1d732d2acff5ec6e05869a9 Reuse the compiled statements in meta data service. flys-artifacts/trunk@2399 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 0c8aca463bd4 -r c30ada285d45 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Fri Jul 22 16:55:36 2011 +0000 +++ b/flys-artifacts/ChangeLog Sat Jul 23 18:47:08 2011 +0000 @@ -1,3 +1,13 @@ +2011-07-21 Sascha L. Teichmann + + * src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java: + Moved connection specific into inner class. The enables the reuse of the + compiled statement. + + * src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java: The + SQL statements are now only compiled once at creation time of the builder. + Each connection now reuses them. + 2011-07-21 Sascha L. Teichmann * doc/conf/cache.xml: Added configuration for static datacage db access. diff -r 0c8aca463bd4 -r c30ada285d45 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java Fri Jul 22 16:55:36 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java Sat Jul 23 18:47:08 2011 +0000 @@ -43,14 +43,16 @@ protected Document template; + protected Map compiledStatements; + public class BuildHelper { - protected Node output; - protected Document owner; - protected StackFrames frames; - protected Connection connection; - protected Map statements; + protected Node output; + protected Document owner; + protected StackFrames frames; + protected Connection connection; + protected Map statements; public BuildHelper( Node output, @@ -60,7 +62,7 @@ this.output = output; this.connection = connection; frames = new StackFrames(parameters); - statements = new HashMap(); + statements = new HashMap(); owner = getOwnerDocument(output); } @@ -71,13 +73,17 @@ } } finally { - for (CompiledStatement cs: statements.values()) { - cs.close(); - } - statements.clear(); + closeStatements(); } } + protected void closeStatements() { + for (CompiledStatement.Instance csi: statements.values()) { + csi.close(); + } + statements.clear(); + } + protected void context(Node parent, Element current) throws SQLException { @@ -107,20 +113,15 @@ String stmntText = stmntNode.item(0).getTextContent(); - if (stmntText == null - || (stmntText = trimStatement(stmntText)).length() == 0) { - log.warn("dc:context: no sql statement found -> ignored"); - return; + CompiledStatement.Instance csi = statements.get(stmntText); + + if (csi == null) { + CompiledStatement cs = compiledStatements.get(stmntText); + csi = cs.new Instance(); + statements.put(stmntText, csi); } - CompiledStatement cs = statements.get(stmntText); - - if (cs == null) { - cs = new CompiledStatement(stmntText); - statements.put(stmntText, cs); - } - - ResultData rd = cs.execute(connection, frames); + ResultData rd = csi.execute(connection, frames); String [] columns = rd.getColumnLabels(); @@ -387,10 +388,32 @@ public Builder() { + compiledStatements = new HashMap(); } public Builder(Document template) { + this(); this.template = template; + compileStatements(); + } + + protected void compileStatements() { + + NodeList nodes = template.getElementsByTagNameNS( + DC_NAMESPACE_URI, "statement"); + + for (int i = 0, N = nodes.getLength(); i < N; ++i) { + Element stmntElement = (Element)nodes.item(i); + String stmnt = trimStatement(stmntElement.getTextContent()); + if (stmnt == null || stmnt.length() == 0) { + throw new IllegalArgumentException("found empty statement"); + } + CompiledStatement cs = new CompiledStatement(stmnt); + // for faster lookup store a shortend string into the template + stmnt = "s" + i; + stmntElement.setTextContent(stmnt); + compiledStatements.put(stmnt, cs); + } } protected static List rootsToList(NodeList roots) { @@ -411,6 +434,7 @@ } protected static final String trimStatement(String stmnt) { + if (stmnt == null) return null; //XXX: Maybe a bit to radical for multiline strings? return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); } diff -r 0c8aca463bd4 -r c30ada285d45 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java Fri Jul 22 16:55:36 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java Sat Jul 23 18:47:08 2011 +0000 @@ -31,9 +31,118 @@ protected Map> positions; - protected PreparedStatement preparedStatement; + protected int numVars; - protected int numVars; + public class Instance { + + protected PreparedStatement preparedStatement; + + public Instance() { + } + + protected ResultData executeCached( + Cache cache, + Connection connection, + StackFrames frames + ) + throws SQLException + { + Object [] values = new Object[numVars]; + + StringBuilder sb = new StringBuilder(original); + + for (Map.Entry> entry: positions.entrySet()) { + String key = entry.getKey(); + Object value = frames.get(key); + sb.append(';').append(key).append(':').append(value); + for (Integer index: entry.getValue()) { + values[index] = value; + } + } + + // XXX: Maybe too many collisions? + // String key = original + Arrays.hashCode(values); + String key = sb.toString(); + + Element element = cache.get(key); + + if (element != null) { + return (ResultData)element.getValue(); + } + + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (int i = 0; i < values.length; ++i) { + preparedStatement.setObject(i+1, values[i]); + } + + ResultData data; + + ResultSet result = preparedStatement.executeQuery(); + try { + data = new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + + element = new Element(key, data); + cache.put(element); + + return data; + } + + protected ResultData executeUncached( + Connection connection, + StackFrames frames + ) + throws SQLException + { + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (Map.Entry> entry: positions.entrySet()) { + Object value = frames.get(entry.getKey()); + for (Integer index: entry.getValue()) { + preparedStatement.setObject(index+1, value); + } + } + + ResultSet result = preparedStatement.executeQuery(); + try { + return new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + } + + public ResultData execute(Connection connection, StackFrames frames) + throws SQLException + { + Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); + + return cache != null + ? executeCached(cache, connection, frames) + : executeUncached(connection, frames); + } + + public void close() { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } + catch (SQLException sqle) { + } + preparedStatement = null; + } + } + } // class Instance public CompiledStatement() { } @@ -75,108 +184,5 @@ public String getStatement() { return statement; } - - protected ResultData executeCached( - Cache cache, - Connection connection, - StackFrames frames - ) - throws SQLException - { - Object [] values = new Object[numVars]; - - StringBuilder sb = new StringBuilder(original); - - for (Map.Entry> entry: positions.entrySet()) { - String key = entry.getKey(); - Object value = frames.get(key); - sb.append(';').append(key).append(':').append(value); - for (Integer index: entry.getValue()) { - values[index] = value; - } - } - - // XXX: Maybe too many collisions? - // String key = original + Arrays.hashCode(values); - String key = sb.toString(); - - Element element = cache.get(key); - - if (element != null) { - return (ResultData)element.getValue(); - } - - if (preparedStatement == null) { - preparedStatement = connection.prepareStatement(statement); - } - - for (int i = 0; i < values.length; ++i) { - preparedStatement.setObject(i+1, values[i]); - } - - ResultData data; - - ResultSet result = preparedStatement.executeQuery(); - try { - data = new ResultData(preparedStatement.getMetaData()) - .addAll(result); - } - finally { - result.close(); - } - - element = new Element(key, data); - cache.put(element); - - return data; - } - - protected ResultData executeUncached( - Connection connection, - StackFrames frames - ) - throws SQLException - { - if (preparedStatement == null) { - preparedStatement = connection.prepareStatement(statement); - } - - for (Map.Entry> entry: positions.entrySet()) { - Object value = frames.get(entry.getKey()); - for (Integer index: entry.getValue()) { - preparedStatement.setObject(index+1, value); - } - } - - ResultSet result = preparedStatement.executeQuery(); - try { - return new ResultData(preparedStatement.getMetaData()) - .addAll(result); - } - finally { - result.close(); - } - } - - public ResultData execute(Connection connection, StackFrames frames) - throws SQLException - { - Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); - - return cache != null - ? executeCached(cache, connection, frames) - : executeUncached(connection, frames); - } - - public void close() { - if (preparedStatement != null) { - try { - preparedStatement.close(); - } - catch (SQLException sqle) { - } - preparedStatement = null; - } - } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :