use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.
the class JoinRegion method initializeJoinInformation.
/**
* Initializes information on the joinRegion about dependency information, etc.
*
* TODO: assumptions are made here about how dependent criteria must look that are a little restrictive
*/
public void initializeJoinInformation() {
critieriaToSourceMap = new HashMap<PlanNode, Set<PlanNode>>();
LinkedList<PlanNode> crits = new LinkedList<PlanNode>(criteriaNodes);
crits.addAll(dependentCritieraNodes);
LinkedHashMap<PlanNode, PlanNode> source = new LinkedHashMap<PlanNode, PlanNode>(joinSourceNodes);
source.putAll(dependentJoinSourceNodes);
for (PlanNode critNode : crits) {
for (GroupSymbol group : critNode.getGroups()) {
for (PlanNode node : source.keySet()) {
if (node.getGroups().contains(group)) {
Set<PlanNode> sources = critieriaToSourceMap.get(critNode);
if (sources == null) {
sources = new HashSet<PlanNode>();
critieriaToSourceMap.put(critNode, sources);
}
sources.add(node);
break;
}
}
}
}
if (unsatisfiedAccessPatterns.isEmpty()) {
return;
}
Map<GroupSymbol, PlanNode> dependentGroupToSourceMap = new HashMap<GroupSymbol, PlanNode>();
for (PlanNode node : dependentJoinSourceNodes.keySet()) {
for (GroupSymbol symbol : node.getGroups()) {
dependentGroupToSourceMap.put(symbol, node);
}
}
for (Iterator<PlanNode> i = getCriteriaNodes().iterator(); i.hasNext(); ) {
PlanNode node = i.next();
for (GroupSymbol symbol : node.getGroups()) {
if (dependentGroupToSourceMap.containsKey(symbol)) {
i.remove();
dependentCritieraNodes.add(node);
break;
}
}
}
dependentCriteriaElements = new HashMap<ElementSymbol, Set<Collection<GroupSymbol>>>();
for (PlanNode critNode : dependentCritieraNodes) {
Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
if (!(crit instanceof CompareCriteria)) {
continue;
}
CompareCriteria compCrit = (CompareCriteria) crit;
if (compCrit.getOperator() != CompareCriteria.EQ) {
continue;
}
CompareCriteria compareCriteria = (CompareCriteria) crit;
// this may be a proper dependent join criteria
Collection<ElementSymbol>[] critElements = new Collection[2];
critElements[0] = ElementCollectorVisitor.getElements(compareCriteria.getLeftExpression(), true);
if (critElements[0].isEmpty()) {
continue;
}
critElements[1] = ElementCollectorVisitor.getElements(compareCriteria.getRightExpression(), true);
if (critElements[1].isEmpty()) {
continue;
}
for (int expr = 0; expr < critElements.length; expr++) {
// simplifying assumption that there will be a single element on the dependent side
if (critElements[expr].size() != 1) {
continue;
}
ElementSymbol elem = critElements[expr].iterator().next();
if (!dependentGroupToSourceMap.containsKey(elem.getGroupSymbol())) {
continue;
}
// this is also a simplifying assumption. don't consider criteria that can't be pushed
if (containsFunctionsThatCannotBePushed(expr == 0 ? compareCriteria.getRightExpression() : compareCriteria.getLeftExpression())) {
continue;
}
Set<Collection<GroupSymbol>> independentGroups = dependentCriteriaElements.get(elem);
if (independentGroups == null) {
independentGroups = new HashSet<Collection<GroupSymbol>>();
dependentCriteriaElements.put(elem, independentGroups);
}
// set the other side as independent elements
independentGroups.add(GroupsUsedByElementsVisitor.getGroups(critElements[(expr + 1) % 2]));
}
}
}
use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.
the class JoinRegion method getDepJoinCost.
private Float getDepJoinCost(QueryMetadataInterface metadata, CapabilitiesFinder capFinder, CommandContext context, PlanNode indNode, List<PlanNode> applicableCriteria, PlanNode depNode) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
if (depNode.hasBooleanProperty(Info.MAKE_NOT_DEP)) {
return null;
}
float indCost = indNode.getCardinality();
if (indCost == NewCalculateCostUtil.UNKNOWN_VALUE) {
return null;
}
List<Criteria> crits = new ArrayList<Criteria>(applicableCriteria.size());
for (PlanNode planNode : applicableCriteria) {
crits.add((Criteria) planNode.getProperty(NodeConstants.Info.SELECT_CRITERIA));
}
List<Expression> leftExpressions = new LinkedList<Expression>();
List<Expression> rightExpressions = new LinkedList<Expression>();
RuleChooseJoinStrategy.separateCriteria(indNode.getGroups(), depNode.getGroups(), leftExpressions, rightExpressions, crits, new LinkedList<Criteria>());
if (leftExpressions.isEmpty()) {
return null;
}
return NewCalculateCostUtil.computeCostForDepJoin(indNode, depNode, leftExpressions, rightExpressions, metadata, capFinder, context).expectedCardinality;
}
use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.
the class JoinRegion method estimateCriteriaSelectivity.
/**
* @param metadata
* @throws QueryMetadataException
* @throws TeiidComponentException
*/
private void estimateCriteriaSelectivity(QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException {
for (PlanNode node : criteriaNodes) {
Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
float[] baseCosts = new float[] { 100, 10000, 1000000 };
float filterValue = 0;
for (int j = 0; j < baseCosts.length; j++) {
float filter = NewCalculateCostUtil.recursiveEstimateCostOfCriteria(baseCosts[j], node, crit, metadata);
filterValue += filter / baseCosts[j];
}
filterValue /= baseCosts.length;
node.setProperty(NodeConstants.Info.EST_SELECTIVITY, new Float(filterValue));
}
}
use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.
the class JoinUtil method optimizeJoinType.
/**
* Will attempt to optimize the join type based upon the criteria provided.
*
* Returns the new join type if one is found, otherwise null
*
* An outer join can be optimized if criteria that is not dependent upon null values
* is applied on the inner side of the join.
*
* @param critNode
* @param joinNode
* @return
*/
static final JoinType optimizeJoinType(PlanNode critNode, PlanNode joinNode, QueryMetadataInterface metadata, boolean modifyJoin) {
if (critNode.getGroups().isEmpty() || !joinNode.getGroups().containsAll(critNode.getGroups()) || joinNode.hasBooleanProperty(Info.PRESERVE)) {
return null;
}
JoinType joinType = (JoinType) joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);
if (!joinType.isOuter()) {
return null;
}
PlanNode left = joinNode.getFirstChild();
left = FrameUtil.findJoinSourceNode(left);
PlanNode right = joinNode.getLastChild();
right = FrameUtil.findJoinSourceNode(right);
Collection<GroupSymbol> outerGroups = left.getGroups();
Collection<GroupSymbol> innerGroups = right.getGroups();
if (joinType == JoinType.JOIN_RIGHT_OUTER) {
outerGroups = innerGroups;
innerGroups = left.getGroups();
}
// sanity check
if ((joinType == JoinType.JOIN_LEFT_OUTER || joinType == JoinType.JOIN_RIGHT_OUTER) && outerGroups.containsAll(critNode.getGroups())) {
return null;
}
Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
boolean isNullDepdendent = isNullDependent(metadata, innerGroups, crit);
JoinType result = JoinType.JOIN_INNER;
if (joinType == JoinType.JOIN_LEFT_OUTER || joinType == JoinType.JOIN_RIGHT_OUTER) {
if (isNullDepdendent) {
return null;
}
} else {
boolean isNullDepdendentOther = isNullDependent(metadata, outerGroups, crit);
if (isNullDepdendent && isNullDepdendentOther) {
return null;
}
if (isNullDepdendent && !isNullDepdendentOther) {
result = JoinType.JOIN_LEFT_OUTER;
} else if (!isNullDepdendent && isNullDepdendentOther) {
if (modifyJoin) {
JoinUtil.swapJoinChildren(joinNode);
result = JoinType.JOIN_LEFT_OUTER;
}
}
}
if (modifyJoin) {
joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, result);
}
return result;
}
use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.
the class RuleAssignOutputElements method collectRequiredInputSymbols.
/**
* Collect all required input symbols for a given node. Input symbols
* are any symbols that are required in the processing of this node,
* for instance to create a new element symbol or sort on it, etc.
* @param node Node to collect for
* @param metadata
* @param capFinder
* @throws TeiidComponentException
* @throws QueryMetadataException
*/
private List<Expression> collectRequiredInputSymbols(PlanNode node, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException {
Set<Expression> requiredSymbols = new LinkedHashSet<Expression>();
Set<Expression> createdSymbols = new HashSet<Expression>();
List<Expression> outputCols = (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
switch(node.getType()) {
case NodeConstants.Types.PROJECT:
{
List<Expression> projectCols = (List<Expression>) node.getProperty(NodeConstants.Info.PROJECT_COLS);
PlanNode accessParent = NodeEditor.findParent(node, NodeConstants.Types.ACCESS);
PlanNode accessNode = null;
if (accessParent == null) {
// find the direct access node
accessNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.ACCESS, NodeConstants.Types.SOURCE | NodeConstants.Types.JOIN | NodeConstants.Types.SET_OP | NodeConstants.Types.GROUP);
}
for (Expression ss : projectCols) {
if (ss instanceof AliasSymbol) {
createdSymbols.add(ss);
ss = ((AliasSymbol) ss).getSymbol();
}
if (ss instanceof WindowFunction || ss instanceof ExpressionSymbol) {
createdSymbols.add(ss);
}
if (!pushProjection(node, metadata, capFinder, requiredSymbols, accessParent, accessNode, ss)) {
ElementCollectorVisitor.getElements(ss, requiredSymbols);
}
}
break;
}
case NodeConstants.Types.SELECT:
Criteria selectCriteria = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
ElementCollectorVisitor.getElements(selectCriteria, requiredSymbols);
break;
case NodeConstants.Types.JOIN:
List<Criteria> crits = (List) node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
if (crits != null) {
for (Criteria joinCriteria : crits) {
ElementCollectorVisitor.getElements(joinCriteria, requiredSymbols);
}
}
break;
case NodeConstants.Types.GROUP:
List<Expression> groupCols = (List<Expression>) node.getProperty(NodeConstants.Info.GROUP_COLS);
PlanNode accessParent = NodeEditor.findParent(node, NodeConstants.Types.ACCESS);
PlanNode accessNode = null;
if (accessParent == null) {
// find the direct access node
accessNode = NodeEditor.findNodePreOrder(node.getFirstChild(), NodeConstants.Types.ACCESS, NodeConstants.Types.SOURCE | NodeConstants.Types.JOIN | NodeConstants.Types.SET_OP | NodeConstants.Types.GROUP);
}
if (groupCols != null) {
for (Expression expression : groupCols) {
if (!pushProjection(node, metadata, capFinder, requiredSymbols, accessParent, accessNode, expression)) {
ElementCollectorVisitor.getElements(expression, requiredSymbols);
}
}
}
SymbolMap symbolMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP);
Set<ElementSymbol> usedAggregates = new HashSet<ElementSymbol>();
// Take credit for creating any aggregates that are needed above
for (Expression outputSymbol : outputCols) {
if (!(outputSymbol instanceof ElementSymbol)) {
continue;
}
createdSymbols.add(outputSymbol);
Expression ex = symbolMap.getMappedExpression((ElementSymbol) outputSymbol);
if (ex instanceof AggregateSymbol) {
AggregateSymbol agg = (AggregateSymbol) ex;
Expression[] aggExprs = agg.getArgs();
for (Expression expression : aggExprs) {
if (!pushProjection(node, metadata, capFinder, requiredSymbols, accessParent, accessNode, expression)) {
ElementCollectorVisitor.getElements(expression, requiredSymbols);
}
}
OrderBy orderBy = agg.getOrderBy();
if (orderBy != null) {
ElementCollectorVisitor.getElements(orderBy, requiredSymbols);
}
Expression condition = agg.getCondition();
if (condition != null) {
ElementCollectorVisitor.getElements(condition, requiredSymbols);
}
usedAggregates.add((ElementSymbol) outputSymbol);
}
}
// update the aggs in the symbolmap
for (Map.Entry<ElementSymbol, Expression> entry : new ArrayList<Map.Entry<ElementSymbol, Expression>>(symbolMap.asMap().entrySet())) {
if (entry.getValue() instanceof AggregateSymbol && !usedAggregates.contains(entry.getKey())) {
symbolMap.asUpdatableMap().remove(entry.getKey());
}
}
if (requiredSymbols.isEmpty() && usedAggregates.isEmpty()) {
node.setProperty(Info.IS_OPTIONAL, true);
}
break;
}
// Gather elements from correlated subquery references;
for (SymbolMap refs : node.getAllReferences()) {
for (Expression expr : refs.asMap().values()) {
ElementCollectorVisitor.getElements(expr, requiredSymbols);
}
}
// Add any columns to required that are in this node's output but were not created here
for (Expression currentOutputSymbol : outputCols) {
if (!createdSymbols.contains(currentOutputSymbol) && (finalRun || node.getType() != NodeConstants.Types.PROJECT || currentOutputSymbol instanceof ElementSymbol)) {
requiredSymbols.add(currentOutputSymbol);
}
}
// TODO: this should depend upon whether the expressions are deterministic
if (node.getType() == NodeConstants.Types.PROJECT) {
Set<Expression> expressions = new HashSet<Expression>();
for (Iterator<Expression> iterator = requiredSymbols.iterator(); iterator.hasNext(); ) {
Expression ses = iterator.next();
if (!expressions.add(SymbolMap.getExpression(ses))) {
iterator.remove();
}
}
}
return new ArrayList<Expression>(requiredSymbols);
}
Aggregations