KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > extractor > runtime > PreparedExtractorStatement


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 XQuark Group.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.extractor.runtime;
24
25 import java.io.InputStream JavaDoc;
26 import java.math.BigDecimal JavaDoc;
27 import java.sql.PreparedStatement JavaDoc;
28 import java.sql.ResultSet JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.util.*;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.xquark.extractor.ExtractorConnection;
35 import org.xquark.extractor.algebra.ExternalVariable;
36 import org.xquark.extractor.common.MessageLibrary;
37 import org.xquark.extractor.metadata.MetaDataManager;
38 import org.xquark.extractor.sql.PlaceHolderInfo;
39 import org.xquark.extractor.sql.RuntimeVarInfo;
40 import org.xquark.extractor.sql.StatementInfo;
41 import org.xquark.schema.Type;
42 import org.xquark.xml.xdbc.PreparedXMLStatement;
43 import org.xquark.xml.xdbc.XMLDBCException;
44 import org.xquark.xml.xdbc.XMLResultSet;
45 import org.xquark.xquery.parser.*;
46
47 /**
48  * Extractor XML/DBC prepared statement implementation. Based on the design
49  * of split compilation and execution processes in the superclass.
50  */

51 public class PreparedExtractorStatement extends ExtractorStatement implements PreparedXMLStatement {
52
53     private static Log log = LogFactory.getLog(PreparedExtractorStatement.class);
54
55     private static final byte PARAM_OBJECT = 0;
56     private static final byte PARAM_XML = 1;
57     private static final byte PARAM_DECIMAL = 2;
58     private static final byte PARAM_INPUTSTREAM = 3;
59     private static final byte PARAM_BYTES = 4;
60     private static final byte PARAM_BOOLEAN = 5;
61     private static final byte PARAM_DATE = 6;
62     private static final byte PARAM_DOUBLE = 7;
63     private static final byte PARAM_FLOAT = 8;
64     private static final byte PARAM_LONG = 9;
65     private static final byte PARAM_STRING = 10;
66     private static final byte PARAM_SEQUENCE = 11;
67
68     /* cacheable structures */
69     protected Query _query = null;
70
71     /* execution structures */
72     /**
73      * Key : expanded name of the external variable. Value a List RuntimeVarInfo
74      * used to set parameters in the JDBC statements prepared statements
75      */

76     protected Map _externalVarMap = new HashMap();
77
78     /**
79      * Key: an SQLExecution node. Value: a List of NodeStatementInfo to execute
80      * at every execution of the XDBC prepared statements
81      */

82     protected Map _queryMap = new HashMap();
83
84
85     /**
86      * Constructor
87      * @param connection
88      * @param stmtId
89      * @param query
90      * @throws XMLDBCException
91      */

92     public PreparedExtractorStatement(ExtractorConnection connection, int stmtId, QueryFactory queryFactory, MetaDataManager metadataManager, String JavaDoc query, Map cachedStatements) throws XMLDBCException {
93         super(connection, stmtId, queryFactory, metadataManager);
94         if (cachedStatements != null) {
95             _query = (Query) cachedStatements.get(query);
96         }
97         if (_query == null) {
98             _query = queryFactory.createCompiledQuery(query);
99             if (cachedStatements != null) {
100                 cachedStatements.put(query, _query);
101             }
102         }
103         // create execution structures
104
try {
105             prepareJDBCStatements();
106         } catch (SQLException JavaDoc e) {
107             throw new XMLDBCException(MessageLibrary.getMessage("E_ERR_SQL", e.getMessage()));
108         }
109     }
110
111     public void close() throws XMLDBCException {
112         if (!_isClosed) {
113             // browse compiled query to delete temp tables, views and close prepared statements
114
CompiledQueryTreeExecutor executor = new CompiledQueryTreeExecutor() {
115
116                 public void execute(Query.SQLExecutionInfo sInfo) throws SQLException JavaDoc {
117                         // delete temp tables and views
118
if (_stmt == null)
119                         _stmt = createJdbcStatement();
120
121                     if (sInfo.sql != null)
122                         sInfo.sql.cleanAll(_stmt);
123
124                     // close prepared statements
125
NodeStatementInfo nsi = getPreparedStatements(sInfo);
126                     nsi.mainQueryStmt.close();
127                     Iterator it = null;
128                     if (nsi.firstExecStmts != null) {
129                         it = nsi.firstExecStmts.iterator();
130                         while (it.hasNext())
131                              ((PreparedStatement JavaDoc) it.next()).close();
132                     }
133                     if (nsi.nextExecStmts != null) {
134                         it = nsi.nextExecStmts.iterator();
135                         while (it.hasNext())
136                              ((PreparedStatement JavaDoc) it.next()).close();
137                     }
138                 }
139             };
140             try {
141                 browseCompiledQuery(executor);
142             } catch (SQLException JavaDoc e) { /* no op */
143             }
144
145             _externalVarMap.clear();
146             _queryMap.clear();
147
148             super.close();
149         }
150     }
151
152     private NodeStatementInfo getPreparedStatements(Query.SQLExecutionInfo sInfo) {
153         return (NodeStatementInfo) _queryMap.get(sInfo);
154     }
155
156     public PreparedStatement JavaDoc createPreparedJdbcStatement(String JavaDoc query) throws SQLException JavaDoc {
157         PreparedStatement JavaDoc retVal = null;
158         if (_connection.getExtractor().useScrollableResultSets())
159             retVal = _connection.getJdbcConnection().prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
160         else
161             retVal = _connection.getJdbcConnection().prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
162
163         return retVal;
164     }
165
166     /*********************************************************************/
167     /* PARAMETER SETTERS */
168     /*********************************************************************/
169     private void setVariable(String JavaDoc ns, String JavaDoc varName, Object JavaDoc value, byte valueType) throws XMLDBCException {
170         HashMap varMap = _query.getModule().getVariables();
171         if (varMap == null)
172             throw new XMLDBCException("Variable $" + ((ns==null)?"":"{" + ns + "}") + varName + " is not defined.");
173         varMap = (HashMap)varMap.get(ns);
174         if (varMap == null)
175             throw new XMLDBCException("Variable $" + ((ns==null)?"":"{" + ns + "}") + varName + " is not defined.");
176         Variable var = (Variable)varMap.get(varName);
177         if (var == null)
178             throw new XMLDBCException("Variable $" + ((ns==null)?"":"{" + ns + "}") + varName + " is not defined.");
179
180         List placeHolders = (List) _externalVarMap.get(ExternalVariable.getExpandedName(ns, varName));
181         if (placeHolders == null)
182             return;
183
184         RuntimeVarInfo varInfo = null;
185         for (int i = 0; i < placeHolders.size(); i++) {
186             varInfo = (RuntimeVarInfo) placeHolders.get(i);
187             try {
188                 switch (valueType) {
189                     case PARAM_OBJECT :
190                         varInfo.setObject(value);
191                         break;
192                     case PARAM_XML :
193                         varInfo.setParameter((String JavaDoc) value);
194                         break;
195                     case PARAM_DECIMAL :
196                         varInfo.setBigDecimal((BigDecimal JavaDoc) value);
197                         break;
198                     case PARAM_INPUTSTREAM :
199                         StreamInfo sInfo = (StreamInfo) value;
200                         varInfo.setInputStream(sInfo.stream, sInfo.length);
201                         break;
202                     case PARAM_BYTES :
203                         varInfo.setBytes((byte[]) value);
204                         break;
205                     case PARAM_BOOLEAN :
206                         varInfo.setBoolean(((Boolean JavaDoc) value).booleanValue());
207                         break;
208                     case PARAM_DATE :
209                         varInfo.setDate((Date) value);
210                         break;
211                     case PARAM_DOUBLE :
212                         varInfo.setDouble(((Double JavaDoc) value).doubleValue());
213                         break;
214                     case PARAM_FLOAT :
215                         varInfo.setFloat(((Float JavaDoc) value).floatValue());
216                         break;
217                     case PARAM_LONG :
218                         varInfo.setLong(((Long JavaDoc) value).longValue());
219                         break;
220                     case PARAM_STRING :
221                         varInfo.setString((String JavaDoc) value);
222                         break;
223 // case PARAM_SEQUENCE :
224
// varInfo.setSequence((ArrayList) value);
225
// break;
226
default :
227                         }
228
229             } catch (Exception JavaDoc e) {
230                 throw new XMLDBCException(MessageLibrary.getMessage("ST_VAR_SETTING"), e);
231             }
232         }
233     }
234
235     public void setExternalVariable(String JavaDoc ns, String JavaDoc varName, String JavaDoc value) throws XMLDBCException {
236         setVariable(ns, varName, value, PARAM_XML);
237     }
238
239     public void setExternalVariable(String JavaDoc varName, String JavaDoc value) throws XMLDBCException {
240         setExternalVariable(null, varName, value);
241     }
242
243     public void setObject(String JavaDoc ns, String JavaDoc varName, Object JavaDoc value) throws XMLDBCException {
244         setVariable(ns, varName, value, PARAM_OBJECT);
245     }
246
247     public void setObject(String JavaDoc varName, Object JavaDoc value) throws XMLDBCException {
248         setObject(null, varName, value);
249     }
250
251     public void setBigDecimal(String JavaDoc ns, String JavaDoc varName, BigDecimal JavaDoc value) throws XMLDBCException {
252         setVariable(ns, varName, value, PARAM_DECIMAL);
253     }
254
255     public void setBigDecimal(String JavaDoc varName, BigDecimal JavaDoc value) throws XMLDBCException {
256         setBigDecimal(null, varName, value);
257     }
258
259     protected class StreamInfo {
260         InputStream JavaDoc stream;
261         int length;
262
263         public StreamInfo(InputStream JavaDoc stream, int length) {
264             this.stream = stream;
265             this.length = length;
266         }
267     }
268
269     public void setInputStream(String JavaDoc ns, String JavaDoc varName, InputStream JavaDoc value, int length) throws XMLDBCException {
270         setVariable(ns, varName, new StreamInfo(value, length), PARAM_INPUTSTREAM);
271     }
272
273     public void setInputStream(String JavaDoc varName, InputStream JavaDoc value, int length) throws XMLDBCException {
274         setInputStream(null, varName, value, length);
275     }
276
277     public void setBytes(String JavaDoc ns, String JavaDoc varName, byte[] value) throws XMLDBCException {
278         setVariable(ns, varName, value, PARAM_BYTES);
279     }
280
281     public void setBytes(String JavaDoc varName, byte[] value) throws XMLDBCException {
282         setBytes(null, varName, value);
283     }
284
285     public void setBoolean(String JavaDoc ns, String JavaDoc varName, boolean value) throws XMLDBCException {
286         setVariable(ns, varName, new Boolean JavaDoc(value), PARAM_BOOLEAN);
287     }
288
289     public void setBoolean(String JavaDoc varName, boolean value) throws XMLDBCException {
290         setBoolean(null, varName, value);
291     }
292
293     public void setDate(String JavaDoc ns, String JavaDoc varName, Date value) throws XMLDBCException {
294         setVariable(ns, varName, value, PARAM_DATE);
295     }
296
297     public void setDate(String JavaDoc varName, Date value) throws XMLDBCException {
298         setDate(null, varName, value);
299     }
300
301     public void setDouble(String JavaDoc ns, String JavaDoc varName, double value) throws XMLDBCException {
302         setVariable(ns, varName, new Double JavaDoc(value), PARAM_DOUBLE);
303     }
304
305     public void setDouble(String JavaDoc varName, double value) throws XMLDBCException {
306         setDouble(null, varName, value);
307     }
308
309     public void setFloat(String JavaDoc ns, String JavaDoc varName, float value) throws XMLDBCException {
310         setVariable(ns, varName, new Float JavaDoc(value), PARAM_FLOAT);
311     }
312
313     public void setFloat(String JavaDoc varName, float value) throws XMLDBCException {
314         setFloat(null, varName, value);
315     }
316
317     public void setLong(String JavaDoc ns, String JavaDoc varName, long value) throws XMLDBCException {
318         setVariable(ns, varName, new Long JavaDoc(value), PARAM_LONG);
319     }
320
321     public void setLong(String JavaDoc varName, long value) throws XMLDBCException {
322         setLong(null, varName, value);
323
324     }
325
326     public void setString(String JavaDoc ns, String JavaDoc varName, String JavaDoc value) throws XMLDBCException {
327         setVariable(ns, varName, value, PARAM_STRING);
328     }
329
330     public void setString(String JavaDoc varName, String JavaDoc value) throws XMLDBCException {
331         setString(null, varName, value);
332     }
333
334     public void setSequence(String JavaDoc ns, String JavaDoc varName, List value) throws XMLDBCException {
335         setVariable(ns, varName, value, PARAM_SEQUENCE);
336     }
337
338     public void setSequence(String JavaDoc varName, List value) throws XMLDBCException {
339         setSequence(null, varName, value);
340     }
341
342     public void clearVariables() throws XMLDBCException {
343         _externalVarMap.clear();
344     }
345
346     /*********************************************************************/
347     /* EXECUTION */
348     /*********************************************************************/
349     public boolean execute() throws XMLDBCException {
350         if (_currentResultSet != null)
351             _currentResultSet.close();
352         _currentResultSet = runQuery(_query.getCompiledQuery());
353         return true;
354     }
355
356     public XMLResultSet executeQuery() throws XMLDBCException {
357         execute();
358         return _currentResultSet;
359     }
360
361     protected SynchronizedResultSet executeSQL(Query.SQLExecutionInfo sqlInfo) throws XQueryException, XMLDBCException {
362         SynchronizedResultSet retVal = null;
363         NodeStatementInfo pStmts = (NodeStatementInfo) _queryMap.get(sqlInfo);
364
365         try {
366             // TODO: check that all param were set ?
367

368             // Execute create or reset statements (empty temp tables)
369
if (pStmts.firstExecStmts != null) {
370                 if (pStmts.firstPerformed) { // resets
371
for (int i = 0; i < pStmts.nextExecStmts.size(); i++) {
372                         ((PreparedStatement JavaDoc) pStmts.nextExecStmts.get(i)).executeUpdate();
373                     }
374                 } else { // create
375
for (int i = 0; i < pStmts.firstExecStmts.size(); i++) {
376                         ((PreparedStatement JavaDoc) pStmts.firstExecStmts.get(i)).executeUpdate();
377                     }
378                     pStmts.firstPerformed = true;
379                 }
380             }
381
382             // create result set
383
retVal = new SynchronizedResultSet(pStmts.mainQueryStmt, sqlInfo.mapper, _metadataManager.getDbmsInfo());
384         } catch (XMLDBCException ex) {
385             throw ex;
386         } catch (SQLException JavaDoc ex) {
387             throw new XMLDBCException(ex.getMessage(), ex);
388         }
389
390         return retVal;
391     }
392
393     private void prepareJDBCStatements() throws SQLException JavaDoc {
394         CompiledQueryTreeExecutor executor = new CompiledQueryTreeExecutor() {
395
396             public void execute(Query.SQLExecutionInfo sInfo) throws SQLException JavaDoc {
397                 List requestList = sInfo.sql.getRequestList();
398
399                 if (log.isDebugEnabled()) {
400                     log.debug("=================< SQL >=================");
401                     for (int i = 0; i < requestList.size(); i++)
402                         log.debug(((StatementInfo) requestList.get(i)).sStmt);
403                 }
404
405                 //Trace.log("================< Mapper >================");
406
//Trace.log(mapper.pprint());
407

408                 // Add an item in query map
409
NodeStatementInfo pStmts = new NodeStatementInfo();
410                 _queryMap.put(sInfo, pStmts);
411
412                 // create "init" prepared statements
413
StatementInfo stmtInfo = null;
414                 PreparedStatement JavaDoc pStmt = null;
415                 if (requestList.size() > 1)
416                     pStmts.firstExecStmts = new ArrayList();
417                 for (int i = 0; i < requestList.size() - 1; i++) {
418                     stmtInfo = (StatementInfo) requestList.get(i);
419                     pStmt = createPreparedJdbcStatement(stmtInfo.sStmt);
420                     pStmts.firstExecStmts.add(pStmt);
421                     registerPlaceHolders(stmtInfo.parameterList, pStmt);
422                 }
423
424                 // create "main" prepared statements
425
stmtInfo = (StatementInfo) requestList.get(requestList.size() - 1);
426                 pStmt = createPreparedJdbcStatement(stmtInfo.sStmt);
427                 pStmts.mainQueryStmt = pStmt;
428                 registerPlaceHolders(stmtInfo.parameterList, pStmt);
429
430                 // create "reset" prepared statements
431
requestList = sInfo.sql.getResetStatementList();
432
433                 if (log.isDebugEnabled()) {
434                     log.debug("==============< SQL Reset >==============");
435                     for (int i = 0; i < requestList.size(); i++)
436                         log.debug(((StatementInfo) requestList.get(i)).sStmt);
437                 }
438
439                 if (!requestList.isEmpty())
440                     pStmts.nextExecStmts = new ArrayList();
441                 for (int i = 0; i < requestList.size(); i++) {
442                     stmtInfo = (StatementInfo) requestList.get(i);
443                     pStmt = createPreparedJdbcStatement(stmtInfo.sStmt);
444                     pStmts.nextExecStmts.add(pStmt);
445                     registerPlaceHolders(stmtInfo.parameterList, pStmt);
446                 }
447             }
448         };
449         browseCompiledQuery(executor);
450     }
451
452     private void registerPlaceHolders(List placeholders, PreparedStatement JavaDoc pStmt) {
453         for (int i = 0; i < placeholders.size(); i++) {
454             registerPlaceHolder((PlaceHolderInfo) placeholders.get(i), pStmt);
455         }
456     }
457
458     private void registerPlaceHolder(PlaceHolderInfo placeholder, PreparedStatement JavaDoc pStmt) {
459         List runTimeVarInfos = (List) _externalVarMap.get(placeholder.varId);
460         if (runTimeVarInfos == null) {
461             runTimeVarInfos = new ArrayList();
462             _externalVarMap.put(placeholder.varId, runTimeVarInfos);
463         }
464         runTimeVarInfos.add(new RuntimeVarInfo(placeholder, pStmt));
465     }
466
467     /*********************************************************************/
468     /* UTILITIES */
469     /*********************************************************************/
470     protected class NodeStatementInfo {
471         boolean firstPerformed = false;
472         List firstExecStmts = null;
473         List nextExecStmts = null;
474         PreparedStatement JavaDoc mainQueryStmt = null;
475     }
476
477     protected void browseCompiledQuery(CompiledQueryTreeExecutor executor) throws SQLException JavaDoc {
478         Iterator it = _query.getCompiledQuery().iterator();
479         while (it.hasNext())
480             browseQueryTree(executor, ((Query.CompiledExpression) it.next()).sqlInfoTree);
481     }
482
483     protected void browseQueryTree(CompiledQueryTreeExecutor executor, Query.SQLExecutionInfo sInfo) throws SQLException JavaDoc {
484         // in the case there is no Qdb
485
if (sInfo == null)
486             return;
487             
488         if (sInfo.sql != null)
489             executor.execute(sInfo);
490
491         // recursive call
492
if (sInfo.childrenQueries != null) {
493             Iterator it = sInfo.childrenQueries.iterator();
494             while (it.hasNext())
495                 browseQueryTree(executor, (Query.SQLExecutionInfo) it.next());
496         }
497     }
498
499     protected interface CompiledQueryTreeExecutor {
500         void execute(Query.SQLExecutionInfo sInfo) throws SQLException JavaDoc;
501     }
502
503     // add LARS 24/05/04
504
/**
505      * Gets the array of parameter names of the statement
506      */

507     public javax.xml.namespace.QName JavaDoc[] getParameterNames() {
508         ArrayList names = new ArrayList();
509         XQueryModule module = _query.getModule();
510         if (module.getDeclList() != null) {
511             for (int i = 0; i < module.getDeclList().size(); i++) {
512                 QName name = (QName) module.getDeclList().get(i);
513                 HashMap map = null;
514                 if (module.getVariables() != null) {
515                     map = (HashMap) module.getVariables().get(name.getNameSpace());
516                     if (map != null) {
517                         Variable vari = (Variable) map.get(name.getLocalName());
518                         if (vari != null && vari.getExpression() == null) {
519                             names.add(new javax.xml.namespace.QName JavaDoc(vari.getVarName().getNameSpace(),vari.getVarName().getLocalName()));
520                         }
521                     }
522                 }
523             }
524         }
525         javax.xml.namespace.QName JavaDoc qnames[] = new javax.xml.namespace.QName JavaDoc[names.size()];
526         return (javax.xml.namespace.QName JavaDoc[]) names.toArray(qnames);
527     }
528     /**
529      * Gets the base schema type of a particular parameter given it's name
530      */

531     public javax.xml.namespace.QName JavaDoc getParameterType(javax.xml.namespace.QName JavaDoc varName) {
532         XQueryModule module = _query.getModule();
533         org.xquark.xquery.parser.ExternalVariable extVar = (org.xquark.xquery.parser.ExternalVariable) module.getExternalVariables().get(varName);
534         Type type = extVar.getQType().getSimpleType().getBaseType();
535         return new javax.xml.namespace.QName JavaDoc(type.getNamespace(), type.getName());
536     }
537
538 }
539
Popular Tags