comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/meta/CompiledStatement.java @ 972:0c8aca463bd4

Added caching support for the static part of the datacage. flys-artifacts/trunk@2398 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 22 Jul 2011 16:55:36 +0000
parents 2c8fc60125b9
children c30ada285d45
comparison
equal deleted inserted replaced
971:d0c9a5f32c30 972:0c8aca463bd4
3 import java.util.regex.Pattern; 3 import java.util.regex.Pattern;
4 import java.util.regex.Matcher; 4 import java.util.regex.Matcher;
5 5
6 import java.util.List; 6 import java.util.List;
7 import java.util.Map; 7 import java.util.Map;
8 import java.util.HashMap; 8 import java.util.TreeMap;
9 import java.util.ArrayList; 9 import java.util.ArrayList;
10 10
11 import java.sql.PreparedStatement; 11 import java.sql.PreparedStatement;
12 import java.sql.SQLException; 12 import java.sql.SQLException;
13 import java.sql.Connection; 13 import java.sql.Connection;
14 import java.sql.ResultSet; 14 import java.sql.ResultSet;
15 15
16 import net.sf.ehcache.Cache;
17 import net.sf.ehcache.Element;
18
19 import de.intevation.flys.artifacts.cache.CacheFactory;
20
16 public class CompiledStatement 21 public class CompiledStatement
17 { 22 {
23 public static final String DATACAGE_DB_CACHE =
24 "datacage.db";
25
18 public static final Pattern VAR = 26 public static final Pattern VAR =
19 Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); 27 Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}");
20 28
21 protected String original; 29 protected String original;
22 protected String statement; 30 protected String statement;
23 31
24 protected Map<String, List<Integer>> positions; 32 protected Map<String, List<Integer>> positions;
25 33
26 protected PreparedStatement preparedStatement; 34 protected PreparedStatement preparedStatement;
27 35
36 protected int numVars;
37
28 public CompiledStatement() { 38 public CompiledStatement() {
29 } 39 }
30 40
31 public CompiledStatement(String original) { 41 public CompiledStatement(String original) {
32 this.original = original; 42 this.original = original;
33 positions = new HashMap<String, List<Integer>>(); 43 // TreeMap to ensure order
44 positions = new TreeMap<String, List<Integer>>();
34 compile(); 45 compile();
35 } 46 }
36 47
37 protected void compile() { 48 protected void compile() {
38 49
39 StringBuffer sb = new StringBuffer(); 50 StringBuffer sb = new StringBuffer();
40 51
41 Matcher m = VAR.matcher(original); 52 Matcher m = VAR.matcher(original);
42 53
43 int index = 1; 54 int index = 0;
44 55
45 while (m.find()) { 56 while (m.find()) {
46 String key = m.group(1); 57 String key = m.group(1);
47 List<Integer> indices = positions.get(key); 58 List<Integer> indices = positions.get(key);
48 if (indices == null) { 59 if (indices == null) {
54 ++index; 65 ++index;
55 } 66 }
56 67
57 m.appendTail(sb); 68 m.appendTail(sb);
58 69
70 numVars = index;
71
59 statement = sb.toString(); 72 statement = sb.toString();
60 } 73 }
61 74
62 public String getStatement() { 75 public String getStatement() {
63 return statement; 76 return statement;
64 } 77 }
65 78
66 public ResultData execute(Connection connection, StackFrames frames) 79 protected ResultData executeCached(
80 Cache cache,
81 Connection connection,
82 StackFrames frames
83 )
84 throws SQLException
85 {
86 Object [] values = new Object[numVars];
87
88 StringBuilder sb = new StringBuilder(original);
89
90 for (Map.Entry<String, List<Integer>> entry: positions.entrySet()) {
91 String key = entry.getKey();
92 Object value = frames.get(key);
93 sb.append(';').append(key).append(':').append(value);
94 for (Integer index: entry.getValue()) {
95 values[index] = value;
96 }
97 }
98
99 // XXX: Maybe too many collisions?
100 // String key = original + Arrays.hashCode(values);
101 String key = sb.toString();
102
103 Element element = cache.get(key);
104
105 if (element != null) {
106 return (ResultData)element.getValue();
107 }
108
109 if (preparedStatement == null) {
110 preparedStatement = connection.prepareStatement(statement);
111 }
112
113 for (int i = 0; i < values.length; ++i) {
114 preparedStatement.setObject(i+1, values[i]);
115 }
116
117 ResultData data;
118
119 ResultSet result = preparedStatement.executeQuery();
120 try {
121 data = new ResultData(preparedStatement.getMetaData())
122 .addAll(result);
123 }
124 finally {
125 result.close();
126 }
127
128 element = new Element(key, data);
129 cache.put(element);
130
131 return data;
132 }
133
134 protected ResultData executeUncached(
135 Connection connection,
136 StackFrames frames
137 )
67 throws SQLException 138 throws SQLException
68 { 139 {
69 if (preparedStatement == null) { 140 if (preparedStatement == null) {
70 preparedStatement = connection.prepareStatement(statement); 141 preparedStatement = connection.prepareStatement(statement);
71 } 142 }
72 143
73 for (Map.Entry<String, List<Integer>> entry: positions.entrySet()) { 144 for (Map.Entry<String, List<Integer>> entry: positions.entrySet()) {
74 Object value = frames.get(entry.getKey()); 145 Object value = frames.get(entry.getKey());
75 for (Integer index: entry.getValue()) { 146 for (Integer index: entry.getValue()) {
76 preparedStatement.setObject(index, value); 147 preparedStatement.setObject(index+1, value);
77 } 148 }
78 } 149 }
79 150
80 ResultSet result = preparedStatement.executeQuery(); 151 ResultSet result = preparedStatement.executeQuery();
81 try { 152 try {
83 .addAll(result); 154 .addAll(result);
84 } 155 }
85 finally { 156 finally {
86 result.close(); 157 result.close();
87 } 158 }
159 }
160
161 public ResultData execute(Connection connection, StackFrames frames)
162 throws SQLException
163 {
164 Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE);
165
166 return cache != null
167 ? executeCached(cache, connection, frames)
168 : executeUncached(connection, frames);
88 } 169 }
89 170
90 public void close() { 171 public void close() {
91 if (preparedStatement != null) { 172 if (preparedStatement != null) {
92 try { 173 try {

http://dive4elements.wald.intevation.org