001: /**
002: * com.mckoi.database.interpret.SQLQueryExecutor 25 Mar 2002
003: *
004: * Mckoi SQL Database ( http://www.mckoi.com/database )
005: * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * Version 2 as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License Version 2 for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * Version 2 along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: * Change Log:
021: *
022: *
023: */package com.mckoi.database.interpret;
024:
025: import com.mckoi.database.*;
026: import com.mckoi.database.jdbc.SQLQuery;
027: import com.mckoi.database.sql.SQL;
028: import com.mckoi.database.sql.ParseException;
029:
030: import java.io.StringReader;
031: import java.sql.SQLException;
032:
033: /**
034: * An object used to execute SQL queries against a given DatabaseConnection
035: * object. The object maintains an SQL parser object as state which is
036: * reused as necessary.
037: * <p>
038: * This object is a convenient way to execute SQL queries.
039: *
040: * @author Tobias Downer
041: */
042:
043: public class SQLQueryExecutor {
044:
045: /**
046: * The SQL parser state.
047: */
048: private static SQL sql_parser;
049:
050: static {
051: // Set up the sql parser.
052: sql_parser = new SQL(new StringReader(""));
053: }
054:
055: /**
056: * Constructs the executor.
057: */
058: public SQLQueryExecutor() {
059: }
060:
061: /**
062: * Executes the given SQLQuery object on the given DatabaseConnection object.
063: * Returns a Table object that contains the result of the execution.
064: * <p>
065: * Note that this method does not perform any locking. Any locking must have
066: * happened before this method is called.
067: * <p>
068: * Also note that the returned Table object is onld valid within the
069: * life-time of the lock unless the root lock requirements are satisified.
070: */
071: public Table execute(DatabaseConnection connection, SQLQuery query)
072: throws SQLException, DatabaseException,
073: TransactionException, ParseException {
074:
075: // StatementTree caching
076:
077: // Create a new parser and set the parameters...
078: String query_str = query.getQuery();
079: StatementTree statement_tree = null;
080: StatementCache statement_cache = connection.getSystem()
081: .getStatementCache();
082:
083: if (statement_cache != null) {
084: // Is this query cached?
085: statement_tree = statement_cache.get(query_str);
086: }
087: if (statement_tree == null) {
088: synchronized (sql_parser) {
089: sql_parser.ReInit(new StringReader(query_str));
090: sql_parser.reset();
091: // Parse the statement.
092: statement_tree = sql_parser.Statement();
093: }
094: // Put the statement tree in the cache
095: if (statement_cache != null) {
096: statement_cache.put(query_str, statement_tree);
097: }
098: }
099:
100: // Substitute all parameter substitutions in the statement tree.
101: final Object[] vars = query.getVars();
102: ExpressionPreparer preparer = new ExpressionPreparer() {
103: public boolean canPrepare(Object element) {
104: return (element instanceof ParameterSubstitution);
105: }
106:
107: public Object prepare(Object element) {
108: ParameterSubstitution ps = (ParameterSubstitution) element;
109: int param_id = ps.getID();
110: return TObject.objectVal(vars[param_id]);
111: }
112: };
113: statement_tree.prepareAllExpressions(preparer);
114:
115: // Convert the StatementTree to a statement object
116: Statement statement;
117: String statement_class = statement_tree.getClassName();
118: try {
119: Class c = Class.forName(statement_class);
120: statement = (Statement) c.newInstance();
121: } catch (ClassNotFoundException e) {
122: throw new SQLException("Could not find statement class: "
123: + statement_class);
124: } catch (InstantiationException e) {
125: throw new SQLException("Could not instantiate class: "
126: + statement_class);
127: } catch (IllegalAccessException e) {
128: throw new SQLException("Could not access class: "
129: + statement_class);
130: }
131:
132: // Initialize the statement
133: statement.init(connection, statement_tree, query);
134:
135: // Automated statement tree preparation
136: statement.resolveTree();
137:
138: // Prepare the statement.
139: statement.prepare();
140:
141: // Evaluate the SQL statement.
142: Table result = statement.evaluate();
143:
144: return result;
145:
146: }
147:
148: }
|