blob: d9c0071ccbfdb0f357e2bd0a81fb7c93ac31aca1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2013 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());
}
}