/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.expressions; import java.io.*; import java.util.*; import org.eclipse.persistence.internal.helper.*; import org.eclipse.persistence.expressions.*; /** * A TableExpression allows for a raw database table to be referenced in a query. * This is used for ManyToMany and DirectCollection mappings to define their selection criteria. * It can also be used directly to mix SQL artifacts with Expressions. */ public class TableExpression extends DataExpression { protected DatabaseTable table; public TableExpression() { super(); } public TableExpression(DatabaseTable table) { super(); this.table = table; } /** * INTERNAL: * Alias a particular table within this node */ @Override protected void assignAlias(DatabaseTable alias, DatabaseTable table) { if (this.baseExpression.isQueryKeyExpression()){ QueryKeyExpression qkExpression = ((QueryKeyExpression)this.baseExpression); if (qkExpression.getTableAliases() != null && qkExpression.getTableAliases().keyAtValue(table) != null ) { return; } } super.assignAlias(alias, table); } /** * INTERNAL: * Return if the expression is equal to the other. * This is used to allow dynamic expression's SQL to be cached. */ @Override public boolean equals(Object object) { if (this == object) { return true; } if (!super.equals(object)) { return false; } TableExpression expression = (TableExpression) object; return ((this.table == expression.table) || ((this.table != null) && this.table.equals(expression.table))); } /** * INTERNAL: * Compute a consistent hash-code for the expression. * This is used to allow dynamic expression's SQL to be cached. */ @Override public int computeHashCode() { int hashCode = super.computeHashCode(); if (getTable() != null) { hashCode = hashCode + getTable().hashCode(); } return hashCode; } /** * INTERNAL: * Used for debug printing. */ @Override public String descriptionOfNodeType() { return "Table"; } /** * INTERNAL: * Fully-qualify the databaseField if the table is known. * CR 3791 */ @Override public Expression getField(String fieldName) { // we need to check for full table qualification DatabaseField field = new DatabaseField(fieldName); if (!field.hasTableName()) { field.setTable(getTable()); } return getField(field); } /** * INTERNAL: */ @Override public List<DatabaseTable> getOwnedTables() { List<DatabaseTable> result = new ArrayList(1); result.add(getTable()); return result; } public DatabaseTable getTable() { return table; } @Override public boolean isTableExpression() { return true; } /** * INTERNAL: * Normalize the expression into a printable structure. * Any joins must be added to form a new root. */ @Override public Expression normalize(ExpressionNormalizer normalizer) { if (this.hasBeenNormalized) { return this; } // Bug4736461 Only setTableQualifier if getDatasourceLogin().getTableQualifier() is an empty string to make the window much smaller when // DatabaseTable.qualifiedName is reset if (getTable().getTableQualifier().length() == 0 && (normalizer.getSession().getDatasourceLogin().getTableQualifier().length() != 0)) { getTable().setTableQualifier(normalizer.getSession().getDatasourceLogin().getTableQualifier()); } return super.normalize(normalizer); } /** * INTERNAL: * This expression is built on a different base than the one we want. Rebuild it and * return the root of the new tree */ @Override public Expression rebuildOn(Expression newBase) { Expression newLocalBase = getBaseExpression().rebuildOn(newBase); return newLocalBase.getTable(getTable()); } /** * INTERNAL: * Added for temporal querying. */ public void setTable(DatabaseTable table) { this.table = table; } /** * INTERNAL: * Rebuild myself against the base, with the values of parameters supplied by the context * expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping) * into part of some larger expression. You normally would not call this directly, instead calling twist * See the comment there for more details" */ @Override public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) { Expression twistedBase = getBaseExpression().twistedForBaseAndContext(newBase, context, oldBase); return twistedBase.getTable(getTable()); } /** * INTERNAL: * Used to print a debug form of the expression tree. */ @Override public void writeDescriptionOn(BufferedWriter writer) throws IOException { writer.write(getTable().toString()); writer.write(tableAliasesDescription()); } }