001: /*
002: * Copyright (C) 1999-2004 <a href="mailto:mandarax@jbdietrich.com">Jens Dietrich</a>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package org.mandarax.jdbc.server.sql;
020:
021: import java.sql.Types;
022: import java.util.*;
023: import org.mandarax.jdbc.*;
024: import org.mandarax.jdbc.server.*;
025: import org.mandarax.kernel.*;
026: import org.mandarax.util.CachedResultSet;
027: import org.mandarax.util.StringUtils;
028: import org.mandarax.util.resultsetfilters.AggregationFunction;
029: import org.mandarax.util.resultsetfilters.GroupByFilter;
030: import org.mandarax.util.resultsetfilters.OrderByFilter;
031: import org.mandarax.util.resultsetfilters.WhereFilter;
032:
033: /**
034: * Represents the SQL SELECT statement.
035: * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
036: * @version 3.3.2 <29 December 2004>
037: * @since 3.0
038: */
039:
040: public class SelectStatement extends SQLObject {
041: private SelectClause selectClause = null;
042: private WhereClause whereClause = null;
043: private FromClause fromClause = null;
044: private OrderByClause orderByClause = null;
045: private List hostVariables = null;
046: private KnowledgeBase kb = null;
047: private GroupByClause groupByClause = null;
048: private HavingClause havingClause = null;
049: private boolean distinct = false;
050: private boolean normalized = false;
051: private Map variablesByName = null;
052:
053: // cached properties needed in order to build the mandarax query
054: // this is the predicate in the original query
055: private Predicate predicate = null;
056: // this is the predicate in the final result set. filters, in particular
057: // GROUP BY may result in a different predicate !
058: private Predicate resultsetPredicate = null;
059: private Object[] termTemplates = null; // terms plus host variables - to be reused (when building terms for the mandarax query)!
060:
061: private static LogicFactory lfactory = LogicFactory
062: .getDefaultFactory();
063:
064: // class used to represent result sets generated by SELECT COUNT(*) statements
065: private static String varName = "COUNT(*)";
066: private static List queryVars = new ArrayList(1);
067: private static VariableTerm queryVar = lfactory.createVariableTerm(
068: varName, Integer.class);
069:
070: class CountAllResultSet extends CachedResultSet {
071: CountAllResultSet(int count) {
072: super ();
073: synchronized (queryVars) {
074: if (queryVars.size() == 0)
075: queryVars.add(queryVar);
076: }
077: this .results = new ArrayList(1);
078: results.add(new Result(queryVar, lfactory
079: .createConstantTerm(new Integer(count))));
080: }
081:
082: public List getQueryVariables() throws InferenceException {
083: return queryVars;
084: }
085: }
086:
087: /**
088: * Constructor.
089: */
090: public SelectStatement() {
091: super ();
092: }
093:
094: /**
095: * Constructor.
096: * @param tableName a table name
097: */
098: public SelectStatement(String tableName) {
099: super ();
100: this .setTableName(tableName);
101: }
102:
103: /**
104: * Constructor.
105: * @param tableName a table name
106: * @param columns - comma separated column names or a *
107: */
108: public SelectStatement(String tableName, String columns) {
109: super ();
110: this .setTableName(tableName);
111: if (columns.trim().equals("*"))
112: this .setSelect2Star();
113: else {
114: SelectClauseColumnList colList = new SelectClauseColumnList();
115: setSelectClause(colList);
116: for (StringTokenizer tokenizer = new StringTokenizer(
117: columns, ","); tokenizer.hasMoreTokens();) {
118: String token = tokenizer.nextToken();
119: ColumnName colName = new ColumnName(token);
120: colList.add(colName);
121: colName.setOwner(colList);
122: }
123: }
124: }
125:
126: /**
127: * Constructor.
128: * @param tableName a table name
129: * @param columns - an array of column names
130: */
131: public SelectStatement(String tableName, String[] columns) {
132: super ();
133: this .setTableName(tableName);
134: this .setSelectColumnList(columns);
135: }
136:
137: /**
138: * Compares objects.
139: * @param obj another object.
140: * @return a boolean
141: */
142: public boolean sameAs(Object obj) {
143: if (obj != null && obj instanceof SelectStatement) {
144: SelectStatement s = (SelectStatement) obj;
145: boolean result = true;
146: result = result
147: && (this .selectClause == null ? s.selectClause == null
148: : selectClause.sameAs(s.selectClause));
149: result = result
150: && (this .whereClause == null ? s.whereClause == null
151: : whereClause.sameAs(s.whereClause));
152: result = result
153: && (this .fromClause == null ? s.fromClause == null
154: : fromClause.sameAs(s.fromClause));
155: result = result
156: && (this .orderByClause == null ? s.orderByClause == null
157: : orderByClause.sameAs(s.orderByClause));
158: result = result
159: && (this .groupByClause == null ? s.groupByClause == null
160: : groupByClause.sameAs(s.groupByClause));
161: result = result
162: && (this .havingClause == null ? s.havingClause == null
163: : havingClause.sameAs(s.havingClause));
164: return result;
165: }
166: return false;
167: }
168:
169: /**
170: * Set the table name.
171: * @param tableName the table name
172: */
173: public void setTableName(String tableName) {
174: int pos = tableName.lastIndexOf('.');
175: String table = null;
176: if (pos == -1)
177: table = tableName;
178: else {
179: // scoped table name. not really supported, but generic tools like to use it
180: // so we add minimal support
181: // TODO this should be done by the parser
182: table = tableName.substring(pos + 1);
183: String schemaName = tableName.substring(0, pos);
184: if (!DatabaseMetaDataImpl.DEFAULT_SCHEMA.equals(schemaName)) {
185: throw new IllegalArgumentException(
186: "This is an unknown schema " + schemaName);
187: }
188:
189: }
190: FromClause from = new FromClauseOneTable(table);
191: setFromClause(from);
192: from.setOwner(this );
193: }
194:
195: /**
196: * Set the select clause to a star.
197: */
198: public void setSelect2Star() {
199: setSelectClause(new SelectClauseStar());
200: }
201:
202: /**
203: * Set a column list.
204: * @param cols an array of column names
205: */
206: public void setSelectColumnList(String[] cols) {
207: SelectClauseColumnList colList = new SelectClauseColumnList();
208: for (int i = 0; i < cols.length; i++) {
209: ColumnName colName = new ColumnName(cols[i]);
210: colList.add(colName);
211: colName.setOwner(colList);
212: }
213: setSelectClause(colList);
214: }
215:
216: /** Getter for property fromClause.
217: * @return Value of property fromClause.
218: *
219: */
220: public org.mandarax.jdbc.server.sql.FromClause getFromClause() {
221: return fromClause;
222: }
223:
224: /** Setter for property fromClause.
225: * @param fromClause New value of property fromClause.
226: *
227: */
228: public void setFromClause(
229: org.mandarax.jdbc.server.sql.FromClause fromClause) {
230: this .fromClause = fromClause;
231: fromClause.setOwner(this );
232:
233: }
234:
235: /** Getter for property selectClause.
236: * @return Value of property selectClause.
237: *
238: */
239: public org.mandarax.jdbc.server.sql.SelectClause getSelectClause() {
240: return selectClause;
241: }
242:
243: /** Setter for property selectClause.
244: * @param selectClause New value of property selectClause.
245: *
246: */
247: public void setSelectClause(
248: org.mandarax.jdbc.server.sql.SelectClause selectClause) {
249: this .selectClause = selectClause;
250: selectClause.setOwner(this );
251: }
252:
253: /** Getter for property whereClause.
254: * @return Value of property whereClause.
255: *
256: */
257: public org.mandarax.jdbc.server.sql.WhereClause getWhereClause() {
258: return whereClause;
259: }
260:
261: /**
262: * Prepare the statement, i.e. gather the host variables.
263: */
264: public synchronized void prepare() {
265: if (hostVariables == null) {
266: hostVariables = new ArrayList();
267: if (whereClause != null)
268: whereClause.prepare(hostVariables);
269: }
270: }
271:
272: /**
273: * Get the host variables.
274: * @return a list of host variables.
275: */
276: private List getHostVariables() {
277: prepare();
278: return hostVariables;
279: }
280:
281: /**
282: * Get a host variable.
283: * @param index an index
284: * @return a host variable.
285: */
286: private HostVariable getHostVariable(int index) {
287: List vars = getHostVariables();
288: if (index < 1)
289: throw new IllegalArgumentException(
290: "No host variable found - index must be > 0 !");
291: if (index > vars.size())
292: throw new IllegalArgumentException(
293: "No host variable found - index must be < "
294: + vars.size());
295: return (HostVariable) vars.get(index - 1);
296: }
297:
298: /**
299: * Bind a host variable.
300: * @param value a value
301: * @param index a slot index (starting with 1)
302: * @exception illegal argument exception
303: */
304: public void bind(int index, Object value) {
305: getHostVariable(index).bind(value);
306: }
307:
308: /**
309: * Reset a host variable.
310: * @param index a slot index (starting with 1)
311: * @exception illegal argument exception
312: */
313: public void reset(int index) {
314: getHostVariable(index).reset();
315: }
316:
317: /**
318: * Indicates whether a host variable has been bound.
319: * @param index a slot index (starting with 1)
320: * @return a boolean
321: * @exception illegal argument exception
322: */
323: public boolean isBound(int index) {
324: return getHostVariable(index).isBound();
325: }
326:
327: /**
328: * Check whether all host variables are bound - throw an exception if not.
329: */
330: public void checkBindings() throws JDBCException {
331: List vars = getHostVariables();
332: for (int i = 0; i < vars.size(); i++) {
333: if (!((HostVariable) vars.get(i)).isBound())
334: throw new JDBCException(
335: "Unbound host variable in prepared statement found at position "
336: + (i + 1));
337: }
338: }
339:
340: /**
341: * Resets all host variables.
342: */
343: public void resetAll() {
344: List vars = getHostVariables();
345: for (int i = 0; i < vars.size(); i++) {
346: ((HostVariable) vars.get(i)).reset();
347: }
348: }
349:
350: /**
351: * Indicates whether this statement has host variables.
352: */
353: public boolean hasHostVariables() {
354: return getHostVariables().size() > 0;
355: }
356:
357: /**
358: * Sets the whereClause.
359: * @param whereClause The whereClause to set
360: */
361: public void setWhereClause(WhereClause whereClause) {
362: this .whereClause = whereClause;
363: whereClause.setOwner(this );
364: }
365:
366: /**
367: * Normalize the statement. I.e. remove redundant nestings,
368: * set types fro context, etc
369: * @param typesByColumn associations between column names and (SQL) types
370: */
371: public void normalize(Map typesByColumn) {
372: fromClause.normalize(typesByColumn);
373: selectClause.normalize(typesByColumn);
374: if (whereClause != null)
375: whereClause.normalize(typesByColumn);
376: normalized = true;
377: }
378:
379: /**
380: * Get the knowledge base.
381: * @return a knowledge base
382: */
383: public KnowledgeBase getKB() {
384: return kb;
385: }
386:
387: /**
388: * Sets the kb.
389: * @param kb The knowledge base to set
390: */
391: public void setKB(KnowledgeBase kb) {
392: this .kb = kb;
393: }
394:
395: /**
396: * Build a mandarax query.
397: * @return a mandarax query.
398: */
399: public Query asMandaraxQuery() throws JDBCException {
400:
401: boolean debugOn = LOG_JDBC.isDebugEnabled();
402: if (debugOn)
403: LOG_JDBC
404: .debug("Converting SQL statement into Mandarax query: "
405: + this );
406:
407: if (kb == null)
408: throw new JDBCException(
409: "The knowledge base must be set to build a mandarax query from a SelectStatement");
410: String tableName = ((FromClauseOneTable) getFromClause())
411: .getTableName();
412: // find predicate
413: if (predicate == null)
414: predicate = JDBC2KBUtils.getPredicate(kb, tableName);
415: if (predicate == null)
416: throw new JDBCException(
417: "No predicate found for table name " + tableName
418: + " in kb " + kb);
419:
420: // normalize the statement
421: if (!normalized) {
422: // prepare col name - type associations
423: Class[] struct = predicate.getStructure();
424: String[] names = predicate.getSlotNames();
425: Map typesByColumn = new HashMap(struct.length);
426: for (int i = 0; i < struct.length; i++)
427: typesByColumn.put(names[i], new Integer(JDBCUtils
428: .getTypeMapping(struct[i])));
429: normalize(typesByColumn);
430: }
431:
432: // prepare terms using equal conditions
433: if (termTemplates == null)
434: prepareMandaraxQueryTerms();
435:
436: // bind host variables
437: Term[] terms = new Term[termTemplates.length];
438: for (int i = 0; i < terms.length; i++) {
439: if (termTemplates[i] instanceof HostVariable) {
440: HostVariable hVar = (HostVariable) termTemplates[i];
441: if (!hVar.isBound()) {
442: // throw new JDBCException("Unbound host variable encountered - cannot build mandarax query");
443: // use variable
444: terms[i] = lfactory.createVariableTerm("@" + i,
445: predicate.getStructure()[i]);
446: } else {
447: terms[i] = lfactory.createConstantTerm(hVar
448: .getValue(), predicate.getStructure()[i]);
449: }
450: } else {
451: terms[i] = (Term) termTemplates[i];
452: }
453: }
454: if (debugOn) {
455: LOG_JDBC.debug("Query predicate is: " + predicate);
456: LOG_JDBC.debug("Query terms are: "
457: + StringUtils.toString(terms));
458: }
459:
460: // finally build the query
461: return lfactory.createQuery(lfactory.createFact(predicate,
462: terms), "");
463: }
464:
465: /**
466: * Get the name->variable mappings.
467: * @param rs a result set
468: * @return a map containing name -> variable associations
469: */
470: private Map getVariablesByName(ResultSet rs)
471: throws InferenceException {
472: if (variablesByName == null)
473: variablesByName = new IdentityHashMap();
474: Map mappings = (Map) variablesByName.get(rs);
475: if (mappings == null) {
476: mappings = new HashMap();
477: variablesByName.put(rs, mappings);
478: for (Iterator iter = rs.getQueryVariables().iterator(); iter
479: .hasNext();) {
480: VariableTerm var = (VariableTerm) iter.next();
481: mappings.put(var.getName(), var);
482: }
483: }
484: return mappings;
485: }
486:
487: /**
488: * Apply the conditions build from the WHERE clause using a mandarax result set filter.
489: * Note that some conditions are used directly in the mandarax query (to bind variables)
490: * and do not occur as conditions here. This method should be called after the mandarax query has been built.
491: * @param rs the result set to be filtered
492: * @param debugOn whether debug is switched on
493: * @return a condition that can be used to build a filter
494: */
495: private ResultSet applyWhereCondition(ResultSet rs, boolean debugOn)
496: throws InferenceException {
497: if (whereClause == null || whereClause.isEmpty()) {
498: if (debugOn)
499: LOG_JDBC
500: .debug("No where clause found, skip where filter");
501: return rs;
502: }
503: whereClause.setVariablesByName(this .getVariablesByName(rs));
504: if (debugOn)
505: LOG_JDBC.debug("Applying where filter");
506: // apply conditions
507: return new WhereFilter(rs, whereClause);
508: }
509:
510: /**
511: * Apply the count all condition in statements without GROUP BY clause.
512: * @param rs the result set to be filtered
513: * @param debugOn whether debug is switched on
514: * @return a condition that can be used to build a filter
515: */
516: private ResultSet applyCountAllCondition(ResultSet rs,
517: boolean debugOn) throws InferenceException {
518: if (groupByClause == null) {
519: if (selectClause instanceof SelectClauseColumnList) {
520: List cols = ((SelectClauseColumnList) selectClause)
521: .getColumns();
522: if (cols.size() == 1
523: && cols.get(0) instanceof ComplexTerm1) {
524: ComplexTerm1 ct1 = (ComplexTerm1) cols.get(0);
525: if (ct1.getFunction() == Functions.COUNT) {
526: // count result set
527: if (debugOn)
528: LOG_JDBC
529: .debug("Counting results in result set to support COUNT(*) query - this can be expensive!");
530: rs.last();
531: int rowCount = rs.getCursorPosition() + 1;
532: // build result set
533: return new CountAllResultSet(rowCount);
534: }
535: }
536: }
537: }
538: return rs;
539: }
540:
541: /**
542: * Apply the conditions build from the HAVING clause using a mandarax result set filter.
543: * @param rs the result set to be filtered
544: * @param debugOn whether debug is switched on
545: * @return a condition that can be used to build a filter
546: */
547: private ResultSet applyHavingCondition(ResultSet rs, boolean debugOn)
548: throws InferenceException {
549: if (havingClause == null || havingClause.isEmpty()) {
550: if (debugOn)
551: LOG_JDBC
552: .debug("No having clause found, skip having filter");
553: return rs;
554: }
555: havingClause.setVariablesByName(this .getVariablesByName(rs));
556: if (debugOn)
557: LOG_JDBC.debug("Applying having filter");
558: // apply conditions
559: return new WhereFilter(rs, havingClause);
560: }
561:
562: /**
563: * Apply clauses in the select filters (WHERE, ORDER BY) as filters.
564: * @param rs the result set
565: * @return the filtered result set
566: */
567: public ResultSet applyFilters(ResultSet rs)
568: throws InferenceException {
569: ResultSet filteredRS = rs;
570: boolean debugOn = LOG_JDBC.isDebugEnabled();
571: // check whether predicate has to be transformed
572: setResultSetPredicate(rs, debugOn);
573:
574: // filters
575: filteredRS = applyWhereCondition(filteredRS, debugOn);
576: filteredRS = applyCountAllCondition(filteredRS, debugOn);
577: filteredRS = applyGroupByCondition(filteredRS, debugOn);
578: filteredRS = applyHavingCondition(filteredRS, debugOn);
579: filteredRS = applyOrderByCondition(filteredRS, debugOn);
580: return filteredRS;
581: }
582:
583: /**
584: * Build a new predicate for the result set.
585: * In general, the result set has a structure that differs from the original
586: * due to functions, a subset of columns used, count(*) expression etc. <br>
587: * In case this statement contains a group by clause, this is done in the
588: * applyGroupByCondition method.
589: * @param rs a result set
590: * @param debugOn whether debug is switched on
591: * @throws InferenceException
592: */
593: private void setResultSetPredicate(ResultSet rs, boolean debugOn)
594: throws InferenceException {
595: if (groupByClause == null
596: && (selectClause instanceof SelectClauseColumnList)) {
597: if (debugOn)
598: LOG_JDBC.debug("Transforming predicate for result set");
599: List colList = ((SelectClauseColumnList) selectClause)
600: .getColumns();
601: String name = predicate.getName() + " (transf.)";
602: if (debugOn)
603: LOG_JDBC.debug("Predicate name in result set will be "
604: + name);
605: Class[] structure = new Class[colList.size()];
606: String[] slotNames = new String[colList.size()];
607: String[] origSlotNames = predicate.getSlotNames();
608: for (int i = 0; i < structure.length; i++) {
609: ColumnTerm col = (ColumnTerm) colList.get(i);
610: if (col instanceof ColumnName) {
611: String colName = ((ColumnName) col).getName();
612: // look up index
613: int j = 0;
614: while (j < origSlotNames.length
615: && structure[i] == null) {
616: if (colName.equals(origSlotNames[j])) {
617: structure[i] = predicate.getStructure()[j];
618: slotNames[i] = origSlotNames[j];
619: }
620: j = j + 1;
621: }
622: if (structure[i] == null)
623: throw new InferenceException(
624: "Unknown column (slot) " + colName
625: + " in predicate " + name);
626: } else if (col instanceof ComplexTerm1
627: && ((ComplexTerm1) col).getFunction() == Functions.COUNT) {
628: slotNames[i] = "COUNT(*)";
629: structure[i] = Integer.class;
630: }
631: // TODO generalize this and add support for functions such as || (concatenation),
632: // UPPER etc (in the next version)
633: }
634: resultsetPredicate = new SimplePredicate(name, structure);
635: resultsetPredicate.setSlotNames(slotNames);
636: }
637: }
638:
639: /**
640: * Apply the conditions build from the WHERE clause using a mandarax result set filter.
641: * @param rs the result set to be filtered
642: * @param debugOn whether debug is switched on
643: * @return the filtered result set
644: */
645: private ResultSet applyOrderByCondition(ResultSet rs,
646: boolean debugOn) throws InferenceException {
647: if (orderByClause == null || orderByClause.isEmpty()) {
648: if (debugOn)
649: LOG_JDBC
650: .debug("No order by clause found, skip order by filter");
651: return rs;
652: }
653: orderByClause.setVariablesByName(this .getVariablesByName(rs));
654: if (debugOn)
655: LOG_JDBC.debug("Applying order by filter");
656: // apply conditions
657: return new OrderByFilter(rs, orderByClause.getConditions());
658: }
659:
660: /**
661: * Apply the conditions build from the GROUP BY clause using a mandarax result set filter.
662: * @param rs the result set to be filtered
663: * @param debugOn whether debug is switched on
664: * @return the filtered result set
665: */
666: private ResultSet applyGroupByCondition(ResultSet rs,
667: boolean debugOn) throws InferenceException {
668: if (groupByClause == null || groupByClause.isEmpty()) {
669: if (debugOn)
670: LOG_JDBC
671: .debug("No group by clause found, skip group by filter");
672: return rs;
673: }
674: groupByClause.setVariablesByName(this .getVariablesByName(rs));
675: // apply conditions
676: AggregationFunction[] aggregationFunctions = groupByClause
677: .getAggregationFunctions();
678: VariableTerm[] groupByTerms = groupByClause
679: .getAggregationTerms();
680: VariableTerm[] selectedColumnNames = groupByClause
681: .getSelectedAggregationTerms();
682: // build result set predicate
683: Class[] structure = new Class[selectedColumnNames.length
684: + aggregationFunctions.length];
685: String[] slotNames = new String[selectedColumnNames.length
686: + aggregationFunctions.length];
687: for (int i = 0; i < selectedColumnNames.length; i++) {
688: structure[i] = selectedColumnNames[i].getType();
689: slotNames[i] = selectedColumnNames[i].getName();
690: }
691: for (int i = 0; i < aggregationFunctions.length; i++) {
692: structure[i + groupByTerms.length] = aggregationFunctions[i]
693: .getResultType();
694: slotNames[i + groupByTerms.length] = aggregationFunctions[i]
695: .getVariableInResult().getName();
696: }
697: if (debugOn) {
698: LOG_JDBC.debug("Applying group by filter");
699: LOG_JDBC.debug("Building new GROUP BY variable names: "
700: + StringUtils.toString(slotNames));
701: LOG_JDBC.debug("Building new GROUP BY variable terms: "
702: + StringUtils.toString(structure));
703: }
704: String name = predicate.getName() + " (aggr.)";
705: if (debugOn)
706: LOG_JDBC
707: .debug("Predicate name in GROUP BY result set will be "
708: + name);
709: resultsetPredicate = new SimplePredicate(name, structure);
710: resultsetPredicate.setSlotNames(slotNames);
711:
712: return new GroupByFilter(rs, aggregationFunctions, groupByTerms);
713: }
714:
715: /**
716: * Prepare the terms for the sql query. I.e., prepare the array termTemplates containing terms as well as
717: * host variables (which will be turned into terms later). Terms means terms in the mandarax sense.
718: */
719: private void prepareMandaraxQueryTerms() {
720: Class[] structure = predicate.getStructure();
721: termTemplates = new Object[structure.length];
722: List equalConditions = whereClause == null ? new ArrayList()
723: : whereClause.extractEqualConditions();
724: SimpleCondition cond = null;
725: ColumnTerm ct1, ct2 = null;
726: for (int i = 0; i < termTemplates.length; i++) {
727: // replace only if null - might already be initialized through a col1=col2 condition
728: // warning: "col1=col2 and col2='value'" not yet handled !
729: String colName = JDBC2KBUtils.getSlotName(predicate, i);
730: if (termTemplates[i] == null) {
731: for (int j = 0; j < equalConditions.size(); j++) {
732: cond = (SimpleCondition) equalConditions.get(j);
733: if (cond.isCondition4Column(colName)) {
734: ct1 = cond.getColumnTerm(0);
735: ct2 = cond.getColumnTerm(1);
736: if (ct1 instanceof Value
737: && ct2 instanceof ColumnName) {
738: termTemplates[i] = lfactory
739: .createConstantTerm(((Value) ct1)
740: .getConvertedValue(),
741: structure[i]);
742: } else if (ct2 instanceof Value
743: && ct1 instanceof ColumnName) {
744: termTemplates[i] = lfactory
745: .createConstantTerm(((Value) ct2)
746: .getConvertedValue(),
747: structure[i]);
748: } else if (ct1 instanceof HostVariable
749: && ct2 instanceof ColumnName) {
750: termTemplates[i] = ct1;
751: } else if (ct2 instanceof HostVariable
752: && ct1 instanceof ColumnName) {
753: termTemplates[i] = ct2;
754: } else if (ct1 instanceof ColumnName
755: && ct2 instanceof ColumnName) {
756: String colName1 = ((ColumnName) ct1)
757: .getName();
758: String colName2 = ((ColumnName) ct2)
759: .getName();
760: if (colName.equals(colName1)) {
761: VariableTerm var = lfactory
762: .createVariableTerm(colName,
763: structure[i]);
764: termTemplates[i] = var;
765: termTemplates[JDBC2KBUtils
766: .getSlotNumber(predicate,
767: colName2)] = var;
768: }
769: }
770: }
771: }
772: }
773: if (termTemplates[i] == null) {
774: // if still null then this is a variable term
775: termTemplates[i] = lfactory.createVariableTerm(
776: JDBC2KBUtils.getSlotName(predicate, i),
777: structure[i]);
778: }
779: }
780: }
781:
782: /**
783: * @return boolean
784: */
785: public boolean isDistinct() {
786: return distinct;
787: }
788:
789: /**
790: * Sets the distinct.
791: * @param distinct The distinct to set
792: */
793: public void setDistinct(boolean distinct) {
794: this .distinct = distinct;
795: }
796:
797: /**
798: * Returns the ORDER BY clause.
799: * @return the ORDER BY clause
800: */
801: public OrderByClause getOrderByClause() {
802: return orderByClause;
803: }
804:
805: /**
806: * Sets the ORDER BY clause.
807: * @param orderByClause The ORDER BY clause to set
808: */
809: public void setOrderByClause(OrderByClause orderByClause) {
810: this .orderByClause = orderByClause;
811: orderByClause.setOwner(this );
812: }
813:
814: /**
815: * Returns the GROUP BY clause.
816: * @return the GROUP BY clause
817: */
818: public GroupByClause getGroupByClause() {
819: return groupByClause;
820: }
821:
822: /**
823: * Sets the GROUP BY clause.
824: * @param groupByClause the GROUP BY clause
825: */
826: public void setGroupByClause(GroupByClause groupByClause) {
827: this .groupByClause = groupByClause;
828: groupByClause.setOwner(this );
829: }
830:
831: /**
832: * Returns the HAVING clause.
833: * @return the HAVING clause to set
834: */
835: public HavingClause getHavingClause() {
836: return havingClause;
837: }
838:
839: /**
840: * Sets the HAVING clause.
841: * @param havingClause the HAVING clause to set
842: */
843: public void setHavingClause(HavingClause havingClause) {
844: this .havingClause = havingClause;
845: havingClause.setOwner(this );
846: }
847:
848: /**
849: * Get the predicate in the final result set.
850: * @return a predicate
851: */
852: public Predicate getResultSetPredicate() {
853: if (this .resultsetPredicate != null)
854: return resultsetPredicate;
855: else
856: return predicate;
857: }
858:
859: /**
860: * Get a list of column terms from the SELECT statement.
861: * @return a list of column terms
862: */
863: List getColumns() throws InferenceException {
864: if (selectClause instanceof SelectClauseColumnList) {
865: return ((SelectClauseColumnList) selectClause).getColumns();
866: }
867: LOG_JDBC
868: .debug("Cannot list columns in statement, return empty list");
869: return new ArrayList();
870: }
871:
872: /**
873: * Get a list of column names from the SELECT statement.
874: * @return a list of column names
875: */
876: List getColumnNames() throws InferenceException {
877: List columns = getColumns();
878: List columnNames = new ArrayList(columns.size());
879: for (int i = 0; i < columns.size(); i++) {
880: if (columns.get(i) instanceof ColumnName)
881: columnNames.add(columns.get(i));
882: }
883: return columnNames;
884: }
885:
886: /**
887: * Print the object on a buffer in order to display the parsed SQL.
888: * @param out a string bufer to print on
889: */
890: public void print(StringBuffer out) {
891: out.append("SELECT ");
892: if (isDistinct())
893: out.append(" DISTINCT ");
894: selectClause.print(out);
895: out.append(" FROM ");
896: fromClause.print(out);
897: if (whereClause != null) {
898: out.append(" WHERE ");
899: whereClause.print(out);
900: }
901: if (groupByClause != null) {
902: out.append(" GROUP BY ");
903: groupByClause.print(out);
904: }
905: if (havingClause != null) {
906: out.append(" HAVING ");
907: havingClause.print(out);
908: }
909: if (orderByClause != null) {
910: out.append(" ORDER BY ");
911: orderByClause.print(out);
912: }
913:
914: }
915:
916: }
|