changeset 973:c30ada285d45

Reuse the compiled statements in meta data service. flys-artifacts/trunk@2399 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sat, 23 Jul 2011 18:47:08 +0000
parents 0c8aca463bd4
children 30c85cb33a50
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/Builder.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java
diffstat 3 files changed, 167 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- 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 <sascha.teichmann@intevation.de>
+
+	* 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 <sascha.teichmann@intevation.de>
 
 	* doc/conf/cache.xml: Added configuration for static datacage db access.
--- 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<String, CompiledStatement> compiledStatements;
+
 
     public class BuildHelper
     {
-        protected Node                           output;
-        protected Document                       owner;
-        protected StackFrames                    frames;
-        protected Connection                     connection;
-        protected Map<String, CompiledStatement> statements;
+        protected Node                                    output;
+        protected Document                                owner;
+        protected StackFrames                             frames;
+        protected Connection                              connection;
+        protected Map<String, CompiledStatement.Instance> statements;
 
         public BuildHelper(
             Node                output,
@@ -60,7 +62,7 @@
             this.output     = output;
             this.connection = connection;
             frames          = new StackFrames(parameters);
-            statements      = new HashMap<String, CompiledStatement>();
+            statements      = new HashMap<String, CompiledStatement.Instance>();
             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<String, CompiledStatement>();
     }
 
     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<Node> 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(" ");
     }
--- 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<String, List<Integer>> 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<String, List<Integer>> 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<String, List<Integer>> 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<String, List<Integer>> 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<String, List<Integer>> 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 :

http://dive4elements.wald.intevation.org