KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > jdbc > SqlExecutor


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package scriptella.jdbc;
17
18 import scriptella.core.EtlCancelledException;
19 import scriptella.spi.AbstractConnection;
20 import scriptella.spi.ParametersCallback;
21 import scriptella.spi.QueryCallback;
22 import scriptella.spi.Resource;
23 import scriptella.util.StringUtils;
24
25 import java.io.Closeable JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.Reader JavaDoc;
28 import java.io.StringReader JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.sql.SQLWarning JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.logging.Level JavaDoc;
34 import java.util.logging.Logger JavaDoc;
35
36
37 /**
38  * SQL statements executor.
39  *
40  * @author Fyodor Kupolov
41  * @version 1.0
42  */

43 class SqlExecutor extends SqlParserBase implements Closeable JavaDoc {
44     private static final Logger JavaDoc LOG = Logger.getLogger(SqlExecutor.class.getName());
45     protected final Resource resource;
46     protected final JdbcConnection connection;
47     protected final JdbcTypesConverter converter;
48     protected final StatementCache cache;
49     private QueryCallback callback;
50     private ParametersCallback paramsCallback;
51     private List JavaDoc<Object JavaDoc> params = new ArrayList JavaDoc<Object JavaDoc>();
52     private int updateCount;//number of updated rows
53
private final AbstractConnection.StatementCounter counter;
54     private SqlTokenizer cachedTokenizer;
55
56     public SqlExecutor(final Resource resource, final JdbcConnection connection) {
57         this.resource = resource;
58         this.connection = connection;
59         converter = new JdbcTypesConverter();
60         cache = new StatementCache(connection.getNativeConnection(), connection.statementCacheSize);
61         counter = connection.getStatementCounter();
62     }
63
64     final void execute(final ParametersCallback parametersCallback) {
65         execute(parametersCallback, null);
66     }
67
68     final void execute(final ParametersCallback parametersCallback, final QueryCallback queryCallback) {
69         paramsCallback = parametersCallback;
70         callback = queryCallback;
71         updateCount = 0;
72         SqlTokenizer tok = cachedTokenizer;
73         boolean cache = false;
74         if (tok==null) { //If not cached
75
try {
76                 final Reader JavaDoc reader = resource.open();
77                 tok = new SqlReaderTokenizer(reader, connection.separator,
78                         connection.separatorSingleLine, connection.keepformat);
79                 cache = reader instanceof StringReader JavaDoc;
80                 if (cache) { //If resource is a String - allow caching
81
tok = new CachedSqlTokenizer(tok);
82                 }
83             } catch (IOException JavaDoc e) {
84                 throw new JdbcException("Failed to open resource", e);
85             }
86         }
87         parse(tok);
88         //We should remember cached tokenizer only if all statements were parsed
89
//i.e. no errors occured
90
if (cache) {
91             cachedTokenizer=tok;
92         }
93         
94
95     }
96
97     int getUpdateCount() {
98         return updateCount;
99     }
100
101
102     @Override JavaDoc
103     protected String JavaDoc handleParameter(final String JavaDoc name,
104                                      final boolean expression, boolean jdbcParam) {
105         Object JavaDoc p;
106
107         if (expression) {
108             p = connection.getParametersParser().evaluate(name, paramsCallback);
109         } else {
110             p = paramsCallback.getParameter(name);
111         }
112
113         if (jdbcParam) { //if insert as prepared stmt parameter
114
params.add(p);
115             return "?";
116         } else { //otherwise return string representation.
117
//todo we need to defines rules for toString transformations
118
return p == null ? super.handleParameter(name, expression, jdbcParam) : p.toString();
119         }
120     }
121
122     @Override JavaDoc
123     public void statementParsed(final String JavaDoc sql) {
124         EtlCancelledException.checkEtlCancelled();
125         StatementWrapper sw = null;
126         try {
127             sw = cache.prepare(sql, params, converter);
128             int updatedRows = -1;
129             if (callback != null) {
130                 sw.query(callback, paramsCallback);
131             } else {
132                 updatedRows = sw.update();
133             }
134             logExecutedStatement(sql, params, updatedRows);
135         } catch (SQLException JavaDoc e) {
136             throw new JdbcException("Unable to execute statement", e, sql, params);
137         } catch (JdbcException e) {
138             //if ProviderException has no SQL - attach it
139
if (e.getErrorStatement() == null) {
140                 e.setErrorStatement(sql, params);
141             }
142             throw e; //rethrow
143
} finally {
144             params.clear();
145             if (sw != null) {
146                 cache.releaseStatement(sw);
147             }
148         }
149
150     }
151
152     private void logExecutedStatement(final String JavaDoc sql, final List JavaDoc<?> parameters, final int updateCount) {
153         counter.statements++;
154         if (updateCount > 0) {
155             this.updateCount += updateCount;
156         }
157         SQLWarning JavaDoc warnings = null;
158         try {
159             warnings = connection.getNativeConnection().getWarnings();
160         } catch (Exception JavaDoc e) {
161             LOG.log(Level.WARNING, "Failed to obtain SQL warnings", e);
162
163         }
164         Level JavaDoc level = warnings == null ? Level.FINE : Level.INFO;
165         if (warnings != null) { //If warnings present - use INFO priority
166
level = Level.INFO;
167         }
168
169         if (LOG.isLoggable(level)) {
170             StringBuilder JavaDoc sb = new StringBuilder JavaDoc(" Executed statement ");
171             sb.append(StringUtils.consoleFormat(sql));
172             if (!parameters.isEmpty()) {
173                 sb.append(", Parameters: ").append(parameters);
174             }
175             if (updateCount >= 0) {
176                 sb.append(". Update count: ").append(updateCount);
177             }
178             if (warnings != null) { //Iterate warnings
179
sb.append(". SQL Warnings:");
180                 do {
181                     sb.append("\n * ").append(warnings);
182                     warnings = warnings.getNextWarning();
183                 } while (warnings != null);
184                 try {
185                     connection.getNativeConnection().clearWarnings();
186                 } catch (Exception JavaDoc e) { //catch everything because drivers may violate rules and throw any exception
187
LOG.log(Level.WARNING, "Failed to clear SQL warnings", e);
188                 }
189             }
190
191             LOG.log(level, sb.toString());
192         }
193     }
194
195
196     public void close() {
197         cache.close();
198     }
199 }
200
Popular Tags