001: /**********************************************************************
002: Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: 2003 Andy Jefferson - coding standards
017: ...
018: **********************************************************************/package org.jpox.store.expression;
019:
020: import java.util.ArrayList;
021: import java.util.Iterator;
022:
023: import org.jpox.store.DatastoreClass;
024: import org.jpox.store.DatastoreContainerObject;
025: import org.jpox.store.DatastoreField;
026: import org.jpox.store.DatastoreIdentifier;
027: import org.jpox.store.DatastoreObject;
028: import org.jpox.store.FetchStatement;
029: import org.jpox.store.exceptions.TableMismatchException;
030:
031: /**
032: * A SQL table expression that joins superclass tables by constructing a parenthesized sub-SELECT statement.
033: *
034: * @see QueryExpression
035: */
036: public class TableExprAsSubquery extends LogicSetExpression {
037: protected final ArrayList columns = new ArrayList();
038:
039: protected boolean multipleTablesReferenced = false;
040:
041: /**
042: * Constructor for a table expressed as a subquery.
043: * @param qs the QueryExpression
044: * @param mainTable the main table in the query
045: * @param alias The alias/identifier of the table in the query
046: */
047: public TableExprAsSubquery(QueryExpression qs,
048: DatastoreContainerObject mainTable,
049: DatastoreIdentifier alias) {
050: super (qs, mainTable, alias);
051: }
052:
053: public String referenceColumn(DatastoreField col) {
054: assertNotFrozen();
055:
056: DatastoreObject table = col.getDatastoreContainerObject();
057: if (!table.equals(mainTable)) {
058: if (!(mainTable instanceof DatastoreClass)
059: || !(table instanceof DatastoreClass)) {
060: throw new TableMismatchException(col, mainTable);
061: }
062:
063: /*
064: * Since both tables are DatastoreClass we assume that the column
065: * is a superclass field, meaning 'table' is a supertable of
066: * 'mainTable'. We set the flag indicating that this expression
067: * must become a subquery that joins the necessary tables.
068: */
069: multipleTablesReferenced = true;
070: }
071:
072: if (!columns.contains(col)) {
073: columns.add(col);
074: }
075:
076: if (mainAlias.toString().length() > 0) {
077: return col.applySelectFunction(mainAlias + "."
078: + col.getIdentifier());
079: } else {
080: return col.applySelectFunction(col.getIdentifier()
081: .toString());
082: }
083: }
084:
085: public String toString() {
086: if (sqlText == null) {
087: StringBuffer sb = new StringBuffer();
088: DatastoreIdentifier mainTableName = mainTable
089: .getIdentifier();
090:
091: if (!multipleTablesReferenced) {
092: sb.append(mainTable.toString());
093: if (!mainAlias.equals(mainTableName)) {
094: sb.append(' ').append(mainAlias);
095: }
096: } else {
097: FetchStatement subQuery = mainTable.getStoreManager()
098: .getFetchStatement(mainTable);
099: Iterator i = columns.iterator();
100: while (i.hasNext()) {
101: subQuery.select((DatastoreField) i.next());
102: }
103:
104: // Assumed to not want any locking in this statement
105: sb.append('(').append(subQuery.toString(false)).append(
106: ") ").append(mainAlias);
107: }
108:
109: sqlText = sb.toString();
110: }
111:
112: return sqlText;
113: }
114: }
|