use of org.teiid.query.sql.symbol.AliasSymbol in project teiid by teiid.
the class TempMetadataStore method createElementSymbol.
private TempMetadataID createElementSymbol(String tempName, Expression symbol, boolean isTempTable) {
// Create new element name
String elementName = tempName + Symbol.SEPARATOR + Symbol.getShortName(symbol);
Object metadataID = null;
if (symbol instanceof AliasSymbol) {
AliasSymbol as = (AliasSymbol) symbol;
symbol = as.getSymbol();
}
// the following allows for original metadata ids to be determined for proc inputs
if (symbol instanceof ExpressionSymbol) {
Expression expr = ((ExpressionSymbol) symbol).getExpression();
if (expr instanceof Reference) {
expr = ((Reference) expr).getExpression();
}
if (expr instanceof ElementSymbol) {
symbol = expr;
}
}
if (symbol instanceof ElementSymbol) {
metadataID = ((ElementSymbol) symbol).getMetadataID();
}
while (metadataID != null && metadataID instanceof TempMetadataID) {
metadataID = ((TempMetadataID) metadataID).getOriginalMetadataID();
}
TempMetadataID elementID = new TempMetadataID(elementName, symbol.getType(), metadataID);
elementID.setTempTable(isTempTable);
return elementID;
}
use of org.teiid.query.sql.symbol.AliasSymbol in project teiid by teiid.
the class RulePlanSorts method checkForProjectOptimization.
static PlanNode checkForProjectOptimization(PlanNode node, PlanNode root, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord record, CommandContext context) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
PlanNode projectNode = node.getFirstChild();
PlanNode parent = node.getParent();
boolean raiseAccess = false;
// special check for unrelated order by compensation
if (projectNode.getType() == NodeConstants.Types.ACCESS && RuleRaiseAccess.canRaiseOverSort(projectNode, metadata, capFinder, node, record, true, context)) {
projectNode = NodeEditor.findNodePreOrder(projectNode, NodeConstants.Types.PROJECT, NodeConstants.Types.SOURCE | NodeConstants.Types.SET_OP);
if (projectNode == null) {
// no interviening project
return root;
}
raiseAccess = true;
} else if (projectNode.getType() == NodeConstants.Types.PROJECT && projectNode.getFirstChild() != null) {
raiseAccess = projectNode.getFirstChild().getType() == NodeConstants.Types.ACCESS && RuleRaiseAccess.canRaiseOverSort(projectNode.getFirstChild(), metadata, capFinder, node, record, false, context);
// if we can't raise the access node and this doesn't have a limit, there's no point in optimizing
if (!raiseAccess && (parent == null || parent.getType() != NodeConstants.Types.TUPLE_LIMIT)) {
return root;
}
} else {
return root;
}
List<Expression> childOutputCols = (List<Expression>) projectNode.getFirstChild().getProperty(Info.OUTPUT_COLS);
OrderBy orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER);
List<Expression> orderByKeys = orderBy.getSortKeys();
LinkedHashSet<Expression> toProject = new LinkedHashSet();
for (Expression ss : orderByKeys) {
Expression original = ss;
if (ss instanceof AliasSymbol) {
ss = ((AliasSymbol) ss).getSymbol();
}
if (ss instanceof ExpressionSymbol) {
if (!raiseAccess) {
// TODO: insert a new project node to handle this case
return root;
}
}
if (!childOutputCols.contains(ss)) {
if (!raiseAccess) {
return root;
}
toProject.add(original);
}
}
PlanNode toRepair = projectNode.getParent();
if (!toProject.isEmpty()) {
PlanNode intermediateProject = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
toProject.addAll(childOutputCols);
List<Expression> projectCols = new ArrayList<Expression>(toProject);
childOutputCols = projectCols;
intermediateProject.setProperty(NodeConstants.Info.PROJECT_COLS, projectCols);
intermediateProject.setProperty(NodeConstants.Info.OUTPUT_COLS, new ArrayList<Expression>(projectCols));
toRepair.getFirstChild().addAsParent(intermediateProject);
}
NodeEditor.removeChildNode(projectNode.getParent(), projectNode);
if (parent != null && parent.getType() == NodeConstants.Types.TUPLE_LIMIT && parent.getParent() != null) {
parent.addAsParent(projectNode);
} else {
if (parent == null) {
root = projectNode;
}
if (parent != null && parent.getType() == NodeConstants.Types.TUPLE_LIMIT) {
if (root == parent) {
root = projectNode;
}
projectNode.addFirstChild(parent);
} else {
projectNode.addFirstChild(node);
}
}
List<Expression> orderByOutputSymbols = (List<Expression>) node.getProperty(Info.OUTPUT_COLS);
boolean unrelated = false;
if (node.hasBooleanProperty(Info.UNRELATED_SORT)) {
node.setProperty(Info.UNRELATED_SORT, false);
unrelated = true;
}
for (OrderByItem item : orderBy.getOrderByItems()) {
if (unrelated || !toProject.isEmpty()) {
// update sort order
int index = childOutputCols.indexOf(item.getSymbol());
item.setExpressionPosition(index);
}
if (toProject.isEmpty()) {
// strip alias as project was raised
if (item.getSymbol() instanceof AliasSymbol) {
item.setSymbol(((AliasSymbol) item.getSymbol()).getSymbol());
}
}
}
while (toRepair != node) {
toRepair.setProperty(Info.OUTPUT_COLS, childOutputCols);
toRepair = toRepair.getParent();
}
projectNode.setProperty(Info.OUTPUT_COLS, orderByOutputSymbols);
projectNode.setProperty(Info.PROJECT_COLS, orderByOutputSymbols);
node.setProperty(Info.OUTPUT_COLS, childOutputCols);
if (parent != null) {
parent.setProperty(Info.OUTPUT_COLS, childOutputCols);
}
if (raiseAccess) {
PlanNode accessNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.ACCESS);
// instead of just calling ruleraiseaccess, we're more selective
// we do not want to raise the access node over a project that is handling an unrelated sort
PlanNode newRoot = RuleRaiseAccess.raiseAccessNode(root, accessNode, metadata, capFinder, true, record, context);
if (newRoot != null) {
accessNode.setProperty(NodeConstants.Info.OUTPUT_COLS, childOutputCols);
root = newRoot;
if (!toProject.isEmpty()) {
newRoot = RuleRaiseAccess.raiseAccessNode(root, accessNode, metadata, capFinder, true, record, context);
}
if (newRoot != null) {
root = newRoot;
if (accessNode.getParent().getType() == NodeConstants.Types.TUPLE_LIMIT) {
newRoot = RulePushLimit.raiseAccessOverLimit(root, accessNode, metadata, capFinder, accessNode.getParent(), record);
}
if (newRoot != null) {
root = newRoot;
}
}
}
}
return root;
}
use of org.teiid.query.sql.symbol.AliasSymbol in project teiid by teiid.
the class AliasGenerator method visit.
public void visit(OrderBy obj) {
// add/correct aliases if necessary
for (int i = 0; i < obj.getVariableCount(); i++) {
OrderByItem item = obj.getOrderByItems().get(i);
Expression element = item.getSymbol();
visitNode(element);
Expression expr = SymbolMap.getExpression(element);
if (item.isUnrelated()) {
item.setSymbol(expr);
continue;
}
String name = null;
if (visitor.namingContext.currentSymbols != null) {
name = visitor.namingContext.currentSymbols.get(element);
}
if (name == null) {
// this is a bit messy, because we have cloned to do the aliasing, there
// is a chance that a subquery is throwing off the above get
int pos = item.getExpressionPosition();
if (pos < visitor.namingContext.currentSymbols.size()) {
ArrayList<Map.Entry<Expression, String>> list = new ArrayList<Map.Entry<Expression, String>>(visitor.namingContext.currentSymbols.entrySet());
name = list.get(pos).getValue();
expr = SymbolMap.getExpression(list.get(pos).getKey());
} else {
name = Symbol.getShortName(element);
}
}
boolean needsAlias = visitor.namingContext.aliasColumns;
if (name == null) {
continue;
}
if (expr instanceof ElementSymbol) {
needsAlias &= needsAlias(name, (ElementSymbol) expr);
}
if (needsAlias) {
element = new AliasSymbol(Symbol.getShortName(element), expr);
} else {
element = expr;
if (expr instanceof ElementSymbol && visitor.namingContext.aliasColumns) {
((ElementSymbol) expr).setDisplayMode(DisplayMode.SHORT_OUTPUT_NAME);
}
}
item.setSymbol(element);
if (element instanceof Symbol) {
((Symbol) element).setShortName(name);
}
}
}
use of org.teiid.query.sql.symbol.AliasSymbol in project teiid by teiid.
the class QueryResolver method resolveWithBindingMetadata.
/**
* Bindings are a poor mans input parameters. They are represented in legacy metadata
* by ElementSymbols and placed positionally into the command or by alias symbols
* and matched by names. After resolving bindings will be replaced with their
* referenced symbols (input names will not be used) and those symbols will
* be marked as external references.
*/
public static TempMetadataStore resolveWithBindingMetadata(Command currentCommand, QueryMetadataInterface metadata, QueryNode queryNode, boolean replaceBindings) throws TeiidComponentException, QueryResolverException {
Map<ElementSymbol, ElementSymbol> symbolMap = null;
if (queryNode.getBindings() != null && queryNode.getBindings().size() > 0) {
symbolMap = new HashMap<ElementSymbol, ElementSymbol>();
// Create ElementSymbols for each InputParameter
final List<ElementSymbol> elements = new ArrayList<ElementSymbol>(queryNode.getBindings().size());
boolean positional = true;
for (Expression ses : parseBindings(queryNode)) {
String name = Symbol.getShortName(ses);
if (ses instanceof AliasSymbol) {
ses = ((AliasSymbol) ses).getSymbol();
positional = false;
}
ElementSymbol elementSymbol = (ElementSymbol) ses;
ResolverVisitor.resolveLanguageObject(elementSymbol, metadata);
elementSymbol.setIsExternalReference(true);
if (!positional) {
symbolMap.put(new ElementSymbol("INPUT" + Symbol.SEPARATOR + name), elementSymbol.clone());
symbolMap.put(new ElementSymbol(BINDING_GROUP + Symbol.SEPARATOR + name), elementSymbol.clone());
elementSymbol.setShortName(name);
}
elements.add(elementSymbol);
}
if (positional) {
ExpressionMappingVisitor emv = new ExpressionMappingVisitor(null) {
@Override
public Expression replaceExpression(Expression element) {
if (!(element instanceof Reference)) {
return element;
}
Reference ref = (Reference) element;
if (!ref.isPositional()) {
return ref;
}
return elements.get(ref.getIndex()).clone();
}
};
DeepPostOrderNavigator.doVisit(currentCommand, emv);
} else {
TempMetadataStore rootExternalStore = new TempMetadataStore();
GroupContext externalGroups = new GroupContext();
// $NON-NLS-1$
ProcedureContainerResolver.addScalarGroup("INPUT", rootExternalStore, externalGroups, elements);
ProcedureContainerResolver.addScalarGroup(BINDING_GROUP, rootExternalStore, externalGroups, elements);
QueryResolver.setChildMetadata(currentCommand, rootExternalStore, externalGroups);
}
}
TempMetadataStore result = resolveCommand(currentCommand, metadata, false);
if (replaceBindings && symbolMap != null && !symbolMap.isEmpty()) {
ExpressionMappingVisitor emv = new ExpressionMappingVisitor(symbolMap);
DeepPostOrderNavigator.doVisit(currentCommand, emv);
}
return result;
}
use of org.teiid.query.sql.symbol.AliasSymbol in project teiid by teiid.
the class ProjectNode method init.
void init() {
List<? extends Expression> childElements = getChildren()[0].getElements();
// Create element lookup map for evaluating project expressions
this.elementMap = createLookupMap(childElements);
// Check whether project needed at all - this occurs if:
// 1. outputMap == null (see previous block)
// 2. project elements are either elements or aggregate symbols (no processing required)
// 3. order of input values == order of output values
needsProject = childElements.size() != selectSymbols.size();
for (int i = 0; i < selectSymbols.size(); i++) {
Expression symbol = selectSymbols.get(i);
if (symbol instanceof AliasSymbol) {
Integer index = elementMap.get(symbol);
if (index != null && index.intValue() == i) {
projectionIndexes[i] = index;
continue;
}
symbol = ((AliasSymbol) symbol).getSymbol();
}
Integer index = elementMap.get(symbol);
if (index == null) {
needsProject = true;
} else {
if (index.intValue() != i) {
needsProject = true;
}
projectionIndexes[i] = index;
}
}
}
Aggregations