use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RuleAssignOutputElements method removeGroupBy.
static PlanNode removeGroupBy(PlanNode root, QueryMetadataInterface metadata) throws QueryPlannerException {
PlanNode next = root.getFirstChild();
NodeEditor.removeChildNode(root.getParent(), root);
SymbolMap symbolMap = (SymbolMap) root.getProperty(NodeConstants.Info.SYMBOL_MAP);
if (!symbolMap.asMap().isEmpty()) {
FrameUtil.convertFrame(next.getParent(), symbolMap.asMap().keySet().iterator().next().getGroupSymbol(), null, symbolMap.asMap(), metadata);
}
PlanNode parent = next.getParent();
while (parent.getParent() != null && parent.getParent().getType() != NodeConstants.Types.SOURCE && parent.getParent().getType() != NodeConstants.Types.SET_OP) {
parent = parent.getParent();
}
return parent;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RuleAssignOutputElements method filterVirtualElements.
/**
* <p>This method looks at a source node, which defines a virtual group, and filters the
* virtual elements defined by the group down into just the output elements needed
* by that source node. This means, for instance, that the PROJECT node at the top
* of the virtual group might need to have some elements removed from the project as
* those elements are no longer needed. </p>
*
* <p>One special case that is handled here is when a virtual group is defined by
* a UNION ALL. In this case, the various branches of the union have elements defined
* and filtering must occur identically in all branches of the union. </p>
*
* @param sourceNode Node to filter
* @param metadata Metadata implementation
* @return The filtered list of columns for this node (used in recursing tree)
* @throws QueryPlannerException
*/
static List<Expression> filterVirtualElements(PlanNode sourceNode, List<Expression> outputColumns, QueryMetadataInterface metadata) throws QueryPlannerException {
PlanNode virtualRoot = sourceNode.getLastChild();
// Update project cols - typically there is exactly one and that node can
// just get the filteredCols determined above. In the case of one or more
// nested set operations (UNION, INTERSECT, EXCEPT) there will be 2 or more
// projects.
List<PlanNode> allProjects = NodeEditor.findAllNodes(virtualRoot, NodeConstants.Types.PROJECT, NodeConstants.Types.PROJECT);
int[] filteredIndex = new int[outputColumns.size()];
Arrays.fill(filteredIndex, -1);
SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
List<ElementSymbol> originalOrder = symbolMap.getKeys();
boolean updateGroups = outputColumns.size() != originalOrder.size();
boolean[] seenIndex = new boolean[outputColumns.size()];
boolean newSymbols = false;
int newSymbolIndex = 0;
for (int i = 0; i < outputColumns.size(); i++) {
Expression expr = outputColumns.get(i);
filteredIndex[i] = originalOrder.indexOf(expr);
if (filteredIndex[i] == -1) {
updateGroups = true;
// we're adding this symbol, which needs to be updated against respective symbol maps
newSymbols = true;
} else {
newSymbolIndex++;
}
if (!updateGroups) {
seenIndex[filteredIndex[i]] = true;
}
}
if (!updateGroups) {
for (boolean b : seenIndex) {
if (!b) {
updateGroups = true;
break;
}
}
}
List<Expression> newCols = null;
for (int i = allProjects.size() - 1; i >= 0; i--) {
PlanNode projectNode = allProjects.get(i);
List<Expression> projectCols = (List<Expression>) projectNode.getProperty(NodeConstants.Info.PROJECT_COLS);
newCols = RelationalNode.projectTuple(filteredIndex, projectCols, true);
if (newSymbols) {
SymbolMap childMap = SymbolMap.createSymbolMap(symbolMap.getKeys(), projectCols);
for (int j = 0; j < filteredIndex.length; j++) {
if (filteredIndex[j] != -1) {
continue;
}
Expression ex = (Expression) outputColumns.get(j).clone();
ExpressionMappingVisitor.mapExpressions(ex, childMap.asMap());
newCols.set(j, ex);
if (i == 0) {
filteredIndex[j] = newSymbolIndex++;
}
}
}
projectNode.setProperty(NodeConstants.Info.PROJECT_COLS, newCols);
if (updateGroups) {
projectNode.getGroups().clear();
projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(newCols));
projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(projectNode.getCorrelatedReferenceElements()));
}
}
if (!updateGroups) {
for (int i : filteredIndex) {
if (i != filteredIndex[i]) {
updateGroups = true;
break;
}
}
}
if (updateGroups) {
SymbolMap newMap = new SymbolMap();
List<Expression> originalExpressionOrder = symbolMap.getValues();
for (int i = 0; i < filteredIndex.length; i++) {
if (filteredIndex[i] < originalOrder.size()) {
newMap.addMapping(originalOrder.get(filteredIndex[i]), originalExpressionOrder.get(filteredIndex[i]));
}
// else TODO: we may need to create a fake symbol
}
sourceNode.setProperty(NodeConstants.Info.SYMBOL_MAP, newMap);
}
// Create output columns for virtual group project
return newCols;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RulePushAggregates method createSymbolMap.
static SymbolMap createSymbolMap(GroupSymbol group, List<? extends Expression> virtualElements, PlanNode child, QueryMetadataInterface metadata) throws TeiidComponentException, QueryMetadataException {
List<ElementSymbol> projectedSymbols = defineNewGroup(group, virtualElements, metadata);
SymbolMap symbolMap = SymbolMap.createSymbolMap(projectedSymbols, (List<Expression>) NodeEditor.findNodePreOrder(child, NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS));
return symbolMap;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RulePushSelectCriteria method pushAcrossGroupBy.
boolean pushAcrossGroupBy(PlanNode sourceNode, PlanNode critNode, QueryMetadataInterface metadata, boolean inPlan, CapabilitiesFinder capFinder) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
if (critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
return false;
}
if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
if (accessNode != null) {
List<Expression> cols = (List<Expression>) sourceNode.getProperty(Info.GROUP_COLS);
if (cols != null) {
boolean hasExpression = false;
boolean hasLiteral = false;
for (final Iterator<Expression> iterator = cols.iterator(); iterator.hasNext(); ) {
Expression ex = iterator.next();
hasExpression |= !(ex instanceof ElementSymbol);
hasLiteral |= EvaluatableVisitor.willBecomeConstant(ex, true);
}
if (hasLiteral || (hasExpression && !CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder))) {
markDependent(critNode, accessNode, metadata, capFinder);
critNode.setProperty(Info.IS_HAVING, true);
return false;
}
}
}
}
if (sourceNode.hasBooleanProperty(Info.ROLLUP)) {
// but instead we'll just clone the node
if (inPlan) {
PlanNode copy = copyNode(critNode);
critNode.setProperty(Info.IS_PUSHED, true);
critNode.setProperty(Info.IS_HAVING, true);
critNode.getFirstChild().addAsParent(copy);
critNode = copy;
}
}
boolean moved = false;
SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
FrameUtil.convertNode(critNode, null, null, symbolMap.asMap(), metadata, true);
if (inPlan) {
NodeEditor.removeChildNode(critNode.getParent(), critNode);
sourceNode.getFirstChild().addAsParent(critNode);
}
moved = true;
if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
if (accessNode != null) {
markDependent(critNode, accessNode, metadata, capFinder);
// terminal position
moved = false;
}
}
return moved;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RulePushSelectCriteria method moveNodeAcrossFrame.
Boolean moveNodeAcrossFrame(PlanNode critNode, PlanNode sourceNode, final QueryMetadataInterface metadata) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
// Check that sourceNode has a child to push across
if (sourceNode.getChildCount() == 0) {
return false;
}
final PlanNode projectNode = NodeEditor.findNodePreOrder(sourceNode.getFirstChild(), NodeConstants.Types.PROJECT, NodeConstants.Types.SOURCE);
if (FrameUtil.isProcedure(projectNode)) {
return false;
}
final SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
final GroupSymbol sourceGroup = sourceNode.getGroups().iterator().next();
if (!placeConvertedSelectNode(critNode, sourceGroup, projectNode, symbolMap, metadata)) {
if (createdNodes == null) {
Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
if (isMultiAttributeDependentSet(crit) && splitSet(critNode, new DependentNodeTest() {
@Override
public boolean isValid(PlanNode copyNode) throws QueryMetadataException, QueryPlannerException, TeiidComponentException {
return createConvertedSelectNode(copyNode, sourceGroup, projectNode, symbolMap, metadata) != null;
}
}, (DependentSetCriteria) crit, sourceNode)) {
return null;
}
}
return false;
}
if (createdNodes == null) {
satisfyConditions(critNode, sourceNode, metadata);
}
// Mark critNode as a "phantom"
critNode.setProperty(NodeConstants.Info.IS_PHANTOM, Boolean.TRUE);
return true;
}
Aggregations