use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RulePlaceAccess method addAccessNode.
/**
* Adds a access node if the node is a source leaf node.
*
* @param metadata
* @param sourceNode
* @return true if the source node has an access pattern
* @throws QueryMetadataException
* @throws TeiidComponentException
*/
private void addAccessNode(QueryMetadataInterface metadata, PlanNode sourceNode, CapabilitiesFinder finder, boolean[] additionalRules) throws QueryMetadataException, TeiidComponentException {
boolean isInsert = false;
Object req = sourceNode.getProperty(NodeConstants.Info.ATOMIC_REQUEST);
if (req == null) {
req = sourceNode.getProperty(NodeConstants.Info.NESTED_COMMAND);
}
if (sourceNode.getProperty(NodeConstants.Info.TABLE_FUNCTION) != null) {
return;
}
if (req instanceof Insert) {
isInsert = true;
} else {
PlanNode parent = sourceNode.getParent();
if (parent.getType() == NodeConstants.Types.PROJECT && parent.getProperty(NodeConstants.Info.INTO_GROUP) != null) {
isInsert = true;
}
}
PlanNode apNode = sourceNode;
if (sourceNode.getChildCount() == 0) {
// Create the access node and insert
PlanNode accessNode = NodeFactory.getNewNode(NodeConstants.Types.ACCESS);
accessNode.addGroups(sourceNode.getGroups());
copyProperties(sourceNode, accessNode);
SourceHint sourceHint = (SourceHint) sourceNode.removeProperty(Info.SOURCE_HINT);
// TODO: trim the hint to only the sources possible under this model (typically 1, but could be more in
// multi-source
accessNode.setProperty(Info.SOURCE_HINT, sourceHint);
Object hint = sourceNode.removeProperty(NodeConstants.Info.IS_OPTIONAL);
if (hint != null) {
accessNode.setProperty(NodeConstants.Info.IS_OPTIONAL, hint);
}
Object modelId = null;
if (sourceNode.getGroups().size() == 1) {
GroupSymbol gs = sourceNode.getGroups().iterator().next();
modelId = gs.getModelMetadataId();
if (modelId != null) {
accessNode.setProperty(NodeConstants.Info.MODEL_ID, modelId);
}
}
if (req instanceof Create || req instanceof Drop) {
modelId = TempMetadataAdapter.TEMP_MODEL;
} else {
modelId = RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata);
}
if (modelId != null) {
boolean multiSource = metadata.isMultiSource(modelId);
if (multiSource) {
accessNode.setProperty(Info.IS_MULTI_SOURCE, multiSource);
}
accessNode.setProperty(NodeConstants.Info.MODEL_ID, modelId);
}
if (req == null && modelId != null) {
// add "conformed" sources if they exist
GroupSymbol group = sourceNode.getGroups().iterator().next();
Object gid = group.getMetadataID();
String sources = metadata.getExtensionProperty(gid, CONFORMED_SOURCES, false);
if (sources != null) {
Set<Object> conformed = new LinkedHashSet<Object>();
conformed.add(modelId);
for (String source : StringUtil.split(sources, ",")) {
// $NON-NLS-1$
Object mid = metadata.getModelID(source.trim());
if (metadata.isVirtualModel(mid)) {
// TODO: could validate this up-front
throw new QueryMetadataException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31148, metadata.getName(mid), group));
}
conformed.add(mid);
}
accessNode.setProperty(Info.CONFORMED_SOURCES, conformed);
}
}
// Insert
sourceNode.addAsParent(accessNode);
apNode = accessNode;
// set additional information
for (GroupSymbol group : accessNode.getGroups()) {
if (group.getCheckMatViewStatus() != null) {
LinkedHashSet<Object> viewsToCheck = new LinkedHashSet<Object>();
viewsToCheck.add(group.getCheckMatViewStatus());
accessNode.setProperty(Info.CHECK_MAT_VIEW, viewsToCheck);
}
Object modelID = metadata.getModelID(group.getMetadataID());
if (CapabilitiesUtil.requiresCriteria(modelID, metadata, finder)) {
additionalRules[1] = true;
}
}
}
// Add access pattern(s), if any, as property of access node
if (!isInsert && addAccessPatternsProperty(apNode, metadata)) {
additionalRules[0] = true;
}
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RulePlanJoins method createJoinNode.
private PlanNode createJoinNode(PlanNode accessNode1, PlanNode accessNode2, List<Criteria> joinCriteria, JoinType joinType) {
PlanNode joinNode = createJoinNode();
joinNode.getGroups().addAll(accessNode1.getGroups());
joinNode.getGroups().addAll(accessNode2.getGroups());
joinNode.addFirstChild(accessNode2);
joinNode.addLastChild(accessNode1);
joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, joinType);
joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCriteria);
return joinNode;
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RulePlanJoins method createJoinNode.
static PlanNode createJoinNode() {
PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS);
joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP);
return joinNode;
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RulePlanJoins method groupAcrossLeftOuter.
private void groupAcrossLeftOuter(QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, CommandContext context, JoinRegion joinRegion) throws QueryMetadataException, TeiidComponentException, AssertionError {
if (joinRegion.getLeft() == null || joinRegion.getJoinRoot().getLastChild().getType() != NodeConstants.Types.ACCESS || joinRegion.getJoinRoot().getFirstChild().getType() == NodeConstants.Types.ACCESS) {
return;
}
PlanNode planNodeRight = joinRegion.getJoinRoot().getLastChild();
Object modelId = RuleRaiseAccess.getModelIDFromAccess(planNodeRight, metadata);
Map<Object, List<PlanNode>> accessMapLeft = getAccessMap(metadata, capabilitiesFinder, joinRegion.getLeft());
// TODO: what about same connector, but not the same model
List<PlanNode> joinSourcesLeft = accessMapLeft.get(modelId);
if (joinSourcesLeft == null) {
return;
}
SupportedJoinCriteria sjc = CapabilitiesUtil.getSupportedJoinCriteria(modelId, metadata, capabilitiesFinder);
Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
List<Criteria> joinCriteria = (List<Criteria>) joinRegion.getJoinRoot().getProperty(Info.JOIN_CRITERIA);
for (Criteria crit : joinCriteria) {
if (!RuleRaiseAccess.isSupportedJoinCriteria(sjc, crit, modelId, metadata, capabilitiesFinder, null)) {
return;
}
}
GroupsUsedByElementsVisitor.getGroups(joinCriteria, groups);
groups.removeAll(planNodeRight.getGroups());
for (PlanNode planNode : joinSourcesLeft) {
if (!planNode.getGroups().containsAll(groups)) {
continue;
}
// see if we can group the planNode with the other side
if (RuleRaiseAccess.canRaiseOverJoin(Arrays.asList(planNode, planNodeRight), metadata, capabilitiesFinder, joinCriteria, JoinType.JOIN_LEFT_OUTER, null, context, false, false) == null) {
continue;
}
// remove the parent loj, create a new loj
joinRegion.getLeft().getJoinSourceNodes().remove(planNode);
PlanNode joinNode = createJoinNode(planNode, planNodeRight, joinCriteria, JoinType.JOIN_LEFT_OUTER);
PlanNode newAccess = RuleRaiseAccess.raiseAccessOverJoin(joinNode, joinNode.getFirstChild(), modelId, capabilitiesFinder, metadata, false);
for (Set<PlanNode> source : joinRegion.getLeft().getCritieriaToSourceMap().values()) {
if (source.remove(planNode)) {
source.add(newAccess);
}
}
joinRegion.getLeft().getJoinSourceNodes().put(newAccess, newAccess);
PlanNode root = joinRegion.getJoinRoot();
root.getParent().replaceChild(root, root.getFirstChild());
joinRegion.getLeft().reconstructJoinRegoin();
break;
}
}
use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.
the class RulePlanOuterJoins method checkLeftOrdering.
/**
* Check if the current join spans inner/left outer joins, such that
* a different tree structure would group the join for pushing
*
* TODO: this is not tolerant to more complex left nesting structures
*
* @param metadata
* @param capabilitiesFinder
* @param analysisRecord
* @param context
* @param join
* @return true if the current join has been restructured
* @throws QueryMetadataException
* @throws TeiidComponentException
*/
private boolean checkLeftOrdering(QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, AnalysisRecord analysisRecord, CommandContext context, PlanNode join) throws QueryMetadataException, TeiidComponentException {
if (join.getFirstChild().getType() != NodeConstants.Types.JOIN || !(join.getFirstChild().getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER || join.getFirstChild().getProperty(Info.JOIN_TYPE) == JoinType.JOIN_INNER)) {
return false;
}
PlanNode childJoin = null;
PlanNode left = join.getFirstChild();
PlanNode right = join.getLastChild();
boolean nested = false;
boolean hasOuter = join.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER;
childJoin = left;
while (childJoin.getFirstChild() != null && childJoin.getFirstChild().getType() != NodeConstants.Types.ACCESS) {
if (childJoin.getType() != NodeConstants.Types.JOIN || !(childJoin.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER || childJoin.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_INNER)) {
return false;
}
hasOuter |= childJoin.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER;
List<Criteria> childJoinCriteria = (List<Criteria>) childJoin.getProperty(Info.JOIN_CRITERIA);
if (!isCriteriaValid(childJoinCriteria, metadata, childJoin)) {
return false;
}
childJoin = childJoin.getFirstChild();
left = childJoin;
nested = true;
}
if (nested && hasOuter && !left.hasBooleanProperty(Info.PRESERVE)) {
if (right.getType() != NodeConstants.Types.ACCESS) {
return false;
}
List<Criteria> joinCriteria = (List<Criteria>) join.getProperty(Info.JOIN_CRITERIA);
if (!isCriteriaValid(joinCriteria, metadata, join)) {
return false;
}
joinCriteria = new ArrayList<>(joinCriteria);
RuleChooseJoinStrategy.filterOptionalCriteria(joinCriteria, false);
Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(joinCriteria);
if (groups.containsAll(left.getFirstChild().getGroups()) && groups.containsAll(right.getGroups()) && groups.size() == left.getFirstChild().getGroups().size() + right.getGroups().size()) {
Object modelId = RuleRaiseAccess.canRaiseOverJoin(Arrays.asList(left.getFirstChild(), right), metadata, capabilitiesFinder, joinCriteria, JoinType.JOIN_LEFT_OUTER, analysisRecord, context, false, false);
if (modelId == null) {
return false;
}
PlanNode parent = join.getParent();
parent.replaceChild(join, join.getFirstChild());
join.removeAllChildren();
left.getFirstChild().addAsParent(join);
join.addLastChild(right);
join.getGroups().clear();
updateGroups(join);
parent.getGroups().clear();
updateGroups(parent);
return true;
}
}
return false;
}
Aggregations