use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RelationalPlanner method addNestedCommand.
private void addNestedCommand(PlanNode node, GroupSymbol group, Command nestedCommand, Command toPlan, boolean merge, boolean isStackEntry) throws TeiidComponentException, QueryMetadataException, TeiidProcessingException {
if (nestedCommand instanceof QueryCommand) {
// remove unnecessary order by
QueryCommand queryCommand = (QueryCommand) nestedCommand;
if (queryCommand.getLimit() == null) {
queryCommand.setOrderBy(null);
}
}
Set<PlanningStackEntry> entries = null;
PlanningStackEntry entry = null;
if (isStackEntry) {
entries = planningStack.get();
entry = createPlanningStackEntry(group, nestedCommand, toPlan.getType() == Command.TYPE_UPDATE_PROCEDURE, entries);
}
try {
node.setProperty(NodeConstants.Info.NESTED_COMMAND, nestedCommand);
if (merge) {
mergeTempMetadata(nestedCommand, parentCommand);
PlanNode childRoot = generatePlan(nestedCommand);
node.addFirstChild(childRoot);
List<Expression> projectCols = nestedCommand.getProjectedSymbols();
SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
node.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
} else {
QueryMetadataInterface actualMetadata = metadata;
if (actualMetadata instanceof TempMetadataAdapter) {
actualMetadata = ((TempMetadataAdapter) metadata).getMetadata();
}
ProcessorPlan plan = QueryOptimizer.optimizePlan(toPlan, actualMetadata, idGenerator, capFinder, analysisRecord, context);
// hack for the optimizer not knowing the containing command when forming the plan
if (nestedCommand instanceof StoredProcedure && plan instanceof ProcedurePlan) {
StoredProcedure container = (StoredProcedure) nestedCommand;
ProcedurePlan pp = (ProcedurePlan) plan;
pp.setUpdateCount(container.getUpdateCount());
if (container.returnParameters()) {
List<ElementSymbol> outParams = new LinkedList<ElementSymbol>();
for (SPParameter param : container.getParameters()) {
if (param.getParameterType() == SPParameter.RETURN_VALUE) {
outParams.add(param.getParameterSymbol());
}
}
for (SPParameter param : container.getParameters()) {
if (param.getParameterType() == SPParameter.INOUT || param.getParameterType() == SPParameter.OUT) {
outParams.add(param.getParameterSymbol());
}
}
if (outParams.size() > 0) {
pp.setOutParams(outParams);
}
}
pp.setParams(container.getProcedureParameters());
}
node.setProperty(NodeConstants.Info.PROCESSOR_PLAN, plan);
}
} finally {
if (entries != null) {
entries.remove(entry);
}
}
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class PlanNode method getCorrelatedReferences.
public List<SymbolMap> getCorrelatedReferences() {
List<SubqueryContainer<?>> containers = getSubqueryContainers();
if (containers.isEmpty()) {
return Collections.emptyList();
}
ArrayList<SymbolMap> result = new ArrayList<SymbolMap>(containers.size());
for (SubqueryContainer<?> container : containers) {
SymbolMap map = container.getCommand().getCorrelatedReferences();
if (map != null) {
result.add(map);
}
}
return result;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RuleMergeCriteria method planQuery.
public boolean planQuery(Collection<GroupSymbol> leftGroups, boolean requireDistinct, PlannedResult plannedResult) throws QueryMetadataException, TeiidComponentException {
if ((plannedResult.query.getLimit() != null && !plannedResult.query.getLimit().isImplicit()) || plannedResult.query.getFrom() == null) {
return false;
}
if ((plannedResult.type == ExistsCriteria.class || plannedResult.type == ScalarSubquery.class) && plannedResult.query.getCorrelatedReferences() == null) {
// TODO: do this check earlier
return false;
}
plannedResult.query = (Query) plannedResult.query.clone();
for (Command c : CommandCollectorVisitor.getCommands(plannedResult.query)) {
// subqueries either need to be re-resolved or replanned to maintain
// multilevel correlated references. it's easier for now to replan
c.setProcessorPlan(null);
}
plannedResult.query.setLimit(null);
List<GroupSymbol> rightGroups = plannedResult.query.getFrom().getGroups();
Set<Expression> requiredExpressions = new LinkedHashSet<Expression>();
final SymbolMap refs = plannedResult.query.getCorrelatedReferences();
boolean addGroupBy = false;
if (refs != null) {
boolean hasAggregates = plannedResult.query.hasAggregates();
Criteria where = plannedResult.query.getCriteria();
if (plannedResult.query.getGroupBy() == null) {
plannedResult.query.setCriteria(null);
}
Criteria having = plannedResult.query.getHaving();
plannedResult.query.setHaving(null);
if (hasCorrelatedReferences(plannedResult.query, refs)) {
return false;
}
if (plannedResult.query.getGroupBy() == null) {
processCriteria(leftGroups, plannedResult, rightGroups, requiredExpressions, refs, where, null, true);
if (hasAggregates) {
if (!plannedResult.nonEquiJoinCriteria.isEmpty()) {
return false;
}
addGroupBy = true;
}
}
processCriteria(leftGroups, plannedResult, rightGroups, requiredExpressions, refs, having, plannedResult.query.getGroupBy(), false);
}
if (plannedResult.additionalCritieria != null) {
RuleChooseJoinStrategy.separateCriteria(leftGroups, rightGroups, plannedResult.leftExpressions, plannedResult.rightExpressions, Criteria.separateCriteriaByAnd(plannedResult.additionalCritieria), plannedResult.nonEquiJoinCriteria);
}
if (plannedResult.leftExpressions.isEmpty()) {
return false;
}
plannedResult.leftExpressions = RuleChooseJoinStrategy.createExpressionSymbols(plannedResult.leftExpressions);
plannedResult.rightExpressions = RuleChooseJoinStrategy.createExpressionSymbols(plannedResult.rightExpressions);
if (requireDistinct && !addGroupBy) {
// ensure that uniqueness applies to the in condition
if (plannedResult.rightExpressions.size() > 1 && (plannedResult.type != SubquerySetCriteria.class || !isDistinct(plannedResult.query, plannedResult.rightExpressions.subList(plannedResult.rightExpressions.size() - 1, plannedResult.rightExpressions.size()), metadata))) {
return false;
}
if (!isDistinct(plannedResult.query, plannedResult.rightExpressions, metadata)) {
if (plannedResult.type == ExistsCriteria.class) {
if (requiredExpressions.size() > plannedResult.leftExpressions.size()) {
// not an equi join
return false;
}
} else if (!requiredExpressions.isEmpty() && !isDistinct(plannedResult.query, plannedResult.query.getProjectedSymbols(), metadata)) {
return false;
}
plannedResult.query.getSelect().setDistinct(true);
plannedResult.madeDistinct = true;
}
}
// it doesn't matter what the select columns are
if (plannedResult.type == ExistsCriteria.class) {
plannedResult.query.getSelect().clearSymbols();
}
if (addGroupBy) {
LinkedHashSet<Expression> groupingSymbols = new LinkedHashSet<Expression>();
for (Expression expr : (List<Expression>) plannedResult.rightExpressions) {
AggregateSymbolCollectorVisitor.getAggregates(expr, null, groupingSymbols, null, null, null);
}
if (!groupingSymbols.isEmpty()) {
plannedResult.query.setGroupBy((GroupBy) new GroupBy(new ArrayList<Expression>(groupingSymbols)).clone());
}
}
HashSet<Expression> projectedSymbols = new HashSet<Expression>();
for (Expression ses : plannedResult.query.getProjectedSymbols()) {
projectedSymbols.add(SymbolMap.getExpression(ses));
}
for (Expression ses : requiredExpressions) {
if (projectedSymbols.add(ses)) {
plannedResult.query.getSelect().addSymbol((Expression) ses.clone());
}
}
for (Expression ses : (List<Expression>) plannedResult.rightExpressions) {
if (projectedSymbols.add(SymbolMap.getExpression(ses))) {
plannedResult.query.getSelect().addSymbol((Expression) ses.clone());
}
}
return true;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RulePlanJoins method execute.
/**
* @see org.teiid.query.optimizer.relational.OptimizerRule#execute(org.teiid.query.optimizer.relational.plantree.PlanNode, org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.optimizer.capabilities.CapabilitiesFinder, org.teiid.query.optimizer.relational.RuleStack, org.teiid.query.analysis.AnalysisRecord, org.teiid.query.util.CommandContext)
*/
public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
List<JoinRegion> joinRegions = new LinkedList<JoinRegion>();
findJoinRegions(plan, null, joinRegions);
// dependency phase
List<JoinRegion> leftOuterJoinRegions = new LinkedList<JoinRegion>();
for (Iterator<JoinRegion> joinRegionIter = joinRegions.iterator(); joinRegionIter.hasNext(); ) {
JoinRegion joinRegion = joinRegionIter.next();
// skip regions that have nothing to plan
if (joinRegion.getJoinSourceNodes().size() + joinRegion.getDependentJoinSourceNodes().size() < 2) {
joinRegionIter.remove();
if (joinRegion.getLeft() != null) {
leftOuterJoinRegions.add(joinRegion);
}
continue;
}
joinRegion.initializeJoinInformation();
// account for nested table correlations
for (PlanNode joinSource : joinRegion.getJoinSourceNodes().keySet()) {
SymbolMap map = (SymbolMap) joinSource.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
if (map != null) {
joinSource.setProperty(NodeConstants.Info.REQUIRED_ACCESS_PATTERN_GROUPS, GroupsUsedByElementsVisitor.getGroups(map.getValues()));
joinRegion.setContainsNestedTable(true);
}
}
// check for unsatisfied dependencies
if (joinRegion.getUnsatisfiedAccessPatterns().isEmpty()) {
continue;
}
// quick check for satisfiability
if (!joinRegion.isSatisfiable()) {
throw new QueryPlannerException(QueryPlugin.Event.TEIID30275, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30275, joinRegion.getUnsatisfiedAccessPatterns()));
}
planForDependencies(joinRegion);
}
// optimization phase
for (JoinRegion joinRegion : joinRegions) {
groupJoinsForPushing(metadata, capabilitiesFinder, joinRegion, context);
}
// check for optimizing across left outer joins
for (JoinRegion joinRegion : leftOuterJoinRegions) {
groupAcrossLeftOuter(metadata, capabilitiesFinder, context, joinRegion);
}
for (Iterator<JoinRegion> joinRegionIter = joinRegions.iterator(); joinRegionIter.hasNext(); ) {
JoinRegion joinRegion = joinRegionIter.next();
// move the dependent nodes back into all joinSources
joinRegion.getJoinSourceNodes().putAll(joinRegion.getDependentJoinSourceNodes());
joinRegion.getCriteriaNodes().addAll(joinRegion.getDependentCriteriaNodes());
joinRegion.getDependentJoinSourceNodes().clear();
joinRegion.getDependentCriteriaNodes().clear();
if (joinRegion.getJoinSourceNodes().size() < 2) {
joinRegion.reconstructJoinRegoin();
joinRegionIter.remove();
continue;
}
joinRegion.initializeCostingInformation(metadata);
Object[] bestOrder = findBestJoinOrder(joinRegion, metadata, capabilitiesFinder, context);
// if no best order was found, just stick with how the user entered the query
if (bestOrder == null) {
continue;
}
joinRegion.changeJoinOrder(bestOrder);
joinRegion.reconstructJoinRegoin();
}
return plan;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RulePushAggregates method collectAggregates.
/**
* Walk up the plan from the GROUP node. Should encounter only (optionally) a SELECT and can stop at the PROJECT node. Need to
* collect any AggregateSymbols used in the select criteria or projected columns.
*
* @param groupNode
* @return the set of aggregate symbols found
* @since 4.2
*/
static LinkedHashSet<AggregateSymbol> collectAggregates(PlanNode groupNode) {
LinkedHashSet<AggregateSymbol> aggregates = new LinkedHashSet<AggregateSymbol>();
PlanNode currentNode = groupNode.getParent();
SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
while (currentNode != null) {
if (currentNode.getType() == NodeConstants.Types.PROJECT) {
List<Expression> projectedSymbols = (List<Expression>) currentNode.getProperty(NodeConstants.Info.PROJECT_COLS);
for (Expression symbol : projectedSymbols) {
mapAggregates(ElementCollectorVisitor.getAggregates(symbol, true), symbolMap, aggregates);
}
break;
}
if (currentNode.getType() == NodeConstants.Types.SELECT) {
Criteria crit = (Criteria) currentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
mapAggregates(ElementCollectorVisitor.getAggregates(crit, true), symbolMap, aggregates);
}
currentNode = currentNode.getParent();
}
return aggregates;
}
Aggregations