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.HashMap;
021:
022: import org.jpox.metadata.JoinMetaData;
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.IdentifierFactory;
028: import org.jpox.store.SecondaryDatastoreClass;
029: import org.jpox.store.exceptions.TableMismatchException;
030:
031: /**
032: * A SQL table expression that joins superclass tables by joining them directly
033: * to the surrounding QueryStatement.
034: *
035: * @see QueryExpression
036: * @version $Revision: 1.20 $
037: */
038: public class TableExprAsJoins extends LogicSetExpression {
039: protected final HashMap aliasesByTable = new HashMap();
040:
041: /**
042: * Constructor for a table expressed as a series of joins.
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 TableExprAsJoins(QueryExpression qs,
048: DatastoreContainerObject mainTable,
049: DatastoreIdentifier alias) {
050: super (qs, mainTable, alias);
051:
052: aliasesByTable.put(mainTable, alias);
053: }
054:
055: public String referenceColumn(DatastoreField col) {
056: assertNotFrozen();
057:
058: DatastoreContainerObject table = col
059: .getDatastoreContainerObject();
060: DatastoreIdentifier alias = (DatastoreIdentifier) aliasesByTable
061: .get(table);
062:
063: if (alias == null) {
064: if (!(mainTable instanceof DatastoreClass)
065: || !(table instanceof DatastoreClass)) {
066: throw new TableMismatchException(col, mainTable);
067: }
068:
069: /*
070: * Since both tables are ClassTables we assume that the column
071: * is a superclass field, meaning 'table' is a supertable of
072: * 'mainTable'. We join the supertable to the query statement using
073: * range variable derived from the main range variable (an
074: * underscore and a counter are appended).
075: *
076: * So even though the caller may have been looking for column FOO
077: * relative to rangevar THIS he may actually get back something like
078: * THIS_1.FOO.
079: */
080: IdentifierFactory idFactory = qs.getStoreManager()
081: .getIdentifierFactory();
082: alias = idFactory.newIdentifier(mainAlias, String
083: .valueOf(aliasesByTable.size()));
084: aliasesByTable.put(table, alias);
085:
086: /* mt... = "main table" */
087: /* st... = "secondary table" */
088: DatastoreClass mt = (DatastoreClass) mainTable;
089: DatastoreClass st = (DatastoreClass) table;
090: boolean useInnerJoin = true;
091: if (st instanceof SecondaryDatastoreClass) {
092: // Support join with any secondary table via outer join
093: JoinMetaData joinmd = ((SecondaryDatastoreClass) st)
094: .getJoinMetaData();
095: if (joinmd != null && joinmd.isOuter()) {
096: useInnerJoin = false;
097: }
098: }
099:
100: LogicSetExpression stTblExpr = qs.newTableExpression(st,
101: alias);
102:
103: ScalarExpression mtExpr = mt.getIDMapping()
104: .newScalarExpression(qs, this );
105: ScalarExpression stExpr = st.getIDMapping()
106: .newScalarExpression(qs, stTblExpr);
107:
108: if (useInnerJoin) {
109: qs.innerJoin(mtExpr, stExpr, stTblExpr, true, true);
110: } else {
111: qs.leftOuterJoin(mtExpr, stExpr, stTblExpr, true, true);
112: }
113: }
114: String aliasString = alias.toString();
115: if (aliasString.length() > 0) {
116: return col.applySelectFunction(aliasString + "."
117: + col.getIdentifier());
118: } else {
119: return col.applySelectFunction(col.getIdentifier()
120: .toString());
121: }
122: }
123:
124: public String toString() {
125: if (sqlText == null) {
126: DatastoreIdentifier mainTableName = mainTable
127: .getIdentifier();
128: StringBuffer sb = new StringBuffer(mainTable.toString());
129: if (!mainAlias.equals(mainTableName)) {
130: sb.append(' ').append(mainAlias);
131: }
132:
133: sqlText = sb.toString();
134: }
135:
136: return sqlText;
137: }
138: }
|