001: /*
002: * $Header: /cvsroot/webman-cms/source/webman/com/teamkonzept/db/TKUnprepQuery.java,v 1.9 2002/02/16 16:03:15 alex Exp $
003: *
004: */
005: package com.teamkonzept.db;
006:
007: import java.sql.*;
008: import java.util.*;
009:
010: import com.teamkonzept.lib.*;
011: import com.teamkonzept.lib.templates.*;
012:
013: /** Abstrakte Klasse, zur Erstellung nicht-präparierter Queries.
014: * Der einer solchen Query zugrundeliegende SQL-String wird aus einem
015: * TKTemplate bei Ausführung der Query erzeugt.
016: *
017: * @see java.sql.Statement
018: * @see com.teamkonzept.lib.TKTemplate
019: * @author
020: * @version
021: */
022: public abstract class TKUnprepQuery extends TKQuery {
023: /** Eine Listiteratorklasse, um auch Felder in das SQL-Template
024: * einfügen zu können. Wird einem Query-Parameter mittels
025: * der Methode setQueryParams() nicht ein einzelner Wert, sondern ein
026: * Feld zugewiesen, so wird in dem SQL-Template das Tag VALUE,
027: * innerhalb derjeniegen Liste mit dem Namen des Query-Parameters,
028: * durch die Werte des zugewiesenen Feldes ersetzt. Zusätzlich
029: * wird das Tag KOMMA durch ',', für alle Elemente ausgenommen dem
030: * letzten, ersetzt.
031: *
032: * Bsp.:
033: * final Integer[] field = { new Integer(1), new Integer(2) };
034: * q.setQueryParams( "MY_LIST", field );
035: *
036: * erzeugt für das Template
037: * <TK_LIST:MY_LIST> ( <TK:VALUE> <TK:KOMMA> ) </TK_LIST:MY_LIST>
038: *
039: * ( 1, 2 )
040: * @author
041: * @version
042: */
043: private class QueryListIterator implements TKListIterator {
044:
045: /** Name der Liste
046: */
047: String name;
048: /** Elemente, welche in die Liste einzufügen sind
049: */
050: Object[] items;
051:
052: /** Index des zu bearbeitenden Listenelementes
053: */
054: int idx = -1;
055:
056: /** Konstruktor.
057: *
058: * @param name - Name der Liste
059: * @param items - Feld der in die Liste einzufügenden Elemente
060: */
061: QueryListIterator(final String name, final Object[] items) {
062: this .name = name;
063: this .items = items;
064: }
065:
066: /** Methode, welche für die entsprechende Liste die
067: * Methode doSubstitutions() aufruft.
068: *
069: * @param template - SQL-Template in dem die Liste
070: * bearbeitet werden soll.
071: * @param idx - wird nicht verwendet
072: * @param type - Name der Liste
073: *
074: * @return false, wenn der Iterator bereits das letzte Element
075: * bearbeitet hat; true, sonst.
076: *
077: * @exception com.teamkonzept.db.TKSQLError
078: */
079: final public boolean apply(final TKTemplate template,
080: final int idx, final String type) {
081: final QueryListIterator list = (QueryListIterator) listIterators
082: .get(type);
083:
084: if (list == null && foreignIterator != null) {
085: return foreignIterator.apply(template, idx, type);
086: } else {
087: list.idx++;
088: return list.doSubstitutions(template);
089: }
090: }
091:
092: /** Methode, welche die Tags VALUE u. KOMMA innerhalb der Liste
093: * ersetzt.
094: *
095: * @param templ - SQL-Template in dem die Liste
096: * bearbeitet werden soll.
097: *
098: * @return false, wenn der Iterator bereits das letzte Element
099: * bearbeitet hat; true, sonst.
100: *
101: * @exception com.teamkonzept.db.TKSQLError
102: */
103: public boolean doSubstitutions(final TKTemplate tmpl) {
104: if (idx < items.length) {
105: try {
106: tmpl.add("VALUE", convert(name, items[idx]));
107: } catch (final SQLException sqle) {
108: printSqlException(sqle,
109: "parameter conversion in QueryListIterator "
110: + name);
111: }
112:
113: tmpl.add("KOMMA", idx < (items.length - 1) ? "," : "");
114:
115: return true;
116: } else {
117: idx = -1;
118: return false;
119: }
120: }
121:
122: /** Liefert einer Hash-Code für den Listiterator
123: *
124: * @return Hash-Code des Listiterators.
125: */
126: final public int hashCode() {
127: return name.hashCode();
128: }
129: }
130:
131: /** Hashtable aller QueryListiteratoren
132: */
133: TKHashtable listIterators = new TKHashtable();
134: /** "fremder" Listiterator
135: */
136: TKListIterator foreignIterator = null;
137: /** SQL-TemplateSyntaxobjekt
138: */
139: TKTemplateSyntax sqlTmplSyntax;
140: /** Typkonverter für die DB-Verbindung
141: */
142: TKSQLTypeConverter typeConverter;
143:
144: /** Methode zur Initialisierung der Query.
145: * Diese Methode wird üblicherweise vom DB-Manager aufgerufen,
146: * um die Query zu initialisieren.
147: *
148: * @param tkConn - Verbindung zu der DB
149: * @param conv - der der DB zugeordnete Typ-Konverter
150: * @param queryID Name der Query Klasse ( wird nicht verwendet )
151: *
152: * @see com.teamkonzept.db.TKDBManager
153: * @see com.teamkonzept.db.TKDBManager#newQuery
154: */
155: public void initQuery(final TKSQLTypeConverter conv,
156: final TKDBConnection tkConn, Object queryID) {
157: this .aTKDBConnection = tkConn;
158: this .typeConverter = conv;
159: initQuery(tkConn.getConnection());
160: }
161:
162: /** Methode zur Initialisierung des Queryobjektes
163: *
164: * @param conn - Verbindung zur DB
165: * @param paramTypes - Liste von Parametername, Parametertyp Paaren
166: * @param setRelevants - geordnete Liste, welche angibt, welche
167: * SQl(Teil)Queries relevante ResultSets liefern.
168: * @param sqlTmplSyntax - Dem der Query zugrundeliegende
169: * SQL-TemplateSyntaxobjekt.
170: *
171: * @exception com.teamkonzept.db.TKSQLError
172: */
173: public void initQuery(final Connection conn,
174: final Object[][] paramTypes, final boolean[] setRelevants,
175: final TKTemplateSyntax sqlTmplSyntax) {
176: super .initQuery(conn, paramTypes, setRelevants);
177:
178: try {
179: this .stmt = conn.createStatement();
180: } catch (SQLException sqle) {
181: printSqlException(sqle, "Create Statement");
182: }
183: this .sqlTmplSyntax = sqlTmplSyntax;
184: this .sqlString = sqlTmplSyntax.getSource();
185: }
186:
187: /** Methode, um die Query auszuführen
188: *
189: * @return true, falls die Query ein java.sql.ResultSet geliefert hat,
190: * false, falls das Resultat der Query ein "Update Count" ist
191: * oder leer ist.
192: *
193: * @exception java.sql.SQLException
194: * @exception com.teamkonzept.db.TKIllegalConversionException
195: */
196: public boolean execute() throws SQLException,
197: TKIllegalConversionException {
198:
199: deregisterIndex = registerQuery();
200: final TKTemplate sqlTmpl = sqlTmplSyntax.getNewTemplate();
201: final Enumeration param_keys = queryParams.keys();
202:
203: while (param_keys.hasMoreElements()) {
204: final String key = (String) param_keys.nextElement();
205: final Object val = queryParams.get(key);
206:
207: sqlTmpl.add(key, convert(key, val));
208: }
209:
210: if (!listIterators.isEmpty()) {
211: sqlTmpl.setListIterator((TKListIterator) listIterators
212: .elements().nextElement());
213: } else if (foreignIterator != null) {
214: sqlTmpl.setListIterator(foreignIterator);
215: }
216:
217: try {
218: sqlTmpl.doTagSubstitution();
219: } catch (TKTemplateSyntaxException tse) {
220: throw new TKTemplateSyntaxError(tse.what, tse.type,
221: tse.info);
222: }
223:
224: sqlString = sqlTmpl.getText();
225:
226: try {
227: currIsResultSet = stmt.execute(sqlString);
228: } catch (SQLException sqle) {
229: printSqlException(sqle, "Execute Unprepared Statement");
230: }
231:
232: queryParams.clear();
233: listIterators.clear();
234: sqlString = sqlTmplSyntax.getSource();
235: foreignIterator = null;
236: currPos = 0;
237:
238: return currIsResultSet;
239: }
240:
241: /** Schließt das zu der Query gehörige SQL-Statement und
242: * gibt die zugehörigen DB u. JDBC-Resourcen wieder frei.
243: *
244: *
245: * @exception java.sql.SQLException
246: */
247: public void specClose() throws SQLException {
248: deregisterQuery();
249: if (stmt != null) {
250: throwawayResults();
251: stmt.close();
252: //stmt = null;
253: }
254: }
255:
256: /** Liefert das gegebene Object val, als SQL-String, Der JDBC-Typ in dem
257: * das Objekt dargestellt werden soll, ist durch den Type des Queryparameters
258: * key gegeben.
259: *
260: * @param key - Name des Queryparameters, welcher den JDBC-Typ definiert.
261: * @param val - Das Objekt, für das der SQL-String erzeugt werden soll.
262: *
263: * @throws SQLException
264: * @throws TKIllegalConversionException
265: */
266: final public String convert(final String key, final Object val)
267: throws SQLException, TKIllegalConversionException {
268: if (paramTypes == null) {
269: return typeConverter.convert(Types.INTEGER, val);
270: } else {
271: final Integer type = (Integer) paramTypes.get(key);
272:
273: if (type == null) {
274: return typeConverter.convert(Types.INTEGER, val);
275: } else {
276: return typeConverter.convert(type.intValue(), val);
277: }
278: }
279: }
280:
281: /** Methode, welche einem Query-Parameter einen Wert oder
282: * ein Feld zuweist.
283: *
284: * @param param - Name des Parameters
285: * @param val - Wert/Feld des Parameters
286: */
287: public void setQueryParams(final String param, final Object val) {
288: if (val instanceof Object[]) {
289: listIterators.put(param, new QueryListIterator(param,
290: (Object[]) val));
291: } else {
292: super .setQueryParams(param, val);
293: }
294: }
295:
296: /** Ermöglich das setzen eines eignen Listiterators für
297: * das SQL-Template
298: *
299: * @param iter - Der Listiterator, der verwendet werden
300: * soll, wenn für eine Liste kein
301: * QueryListIterator vorhanden ist.
302: */
303: public void setListIterator(final TKListIterator iter) {
304: foreignIterator = iter;
305: }
306:
307: }
|