From 8feabe0ee216c32f22c08bba2ac55cbbfd10c23b Mon Sep 17 00:00:00 2001 From: shawkins Date: Fri, 26 Feb 2016 14:29:21 -0500 Subject: [PATCH] TEIID-4005 allowing predicates to be split --- .../rules/RulePushSelectCriteria.java | 49 +++++++++++++------ .../relational/rules/RuleRaiseAccess.java | 2 +- .../query/processor/TestDependentJoins.java | 28 +++++++++++ 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java b/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java index e787b237fa..d60b00dba6 100644 --- a/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java +++ b/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java @@ -22,15 +22,7 @@ package org.teiid.query.optimizer.relational.rules; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.Stack; +import java.util.*; import org.teiid.api.exception.query.QueryMetadataException; import org.teiid.api.exception.query.QueryPlannerException; @@ -391,7 +383,7 @@ private boolean splitSet(PlanNode critNode, DependentNodeTest test, DependentSet throws QueryMetadataException, TeiidComponentException, QueryPlannerException { boolean result = false; - List dscList = splitDependentSetCriteria(dscOrig); + List dscList = splitDependentSetCriteria(dscOrig, false, null); List pushable = new ArrayList(); List nonPushable = new ArrayList(); for (DependentSetCriteria dsc : dscList) { @@ -519,10 +511,9 @@ private void markDependent(PlanNode critNode, PlanNode accessNode, QueryMetadata } accessNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE); Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA); - if (isMultiAttributeDependentSet(crit) - && !CapabilitiesUtil.supports(Capability.ARRAY_TYPE, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder)) { - //split the criteria into individual predicates - List crits = splitDependentSetCriteria((DependentSetCriteria) crit); + if (isMultiAttributeDependentSet(crit)) { + //split the criteria as needed + List crits = splitDependentSetCriteria((DependentSetCriteria) crit, CapabilitiesUtil.supports(Capability.ARRAY_TYPE, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder), metadata); critNode.setProperty(NodeConstants.Info.SELECT_CRITERIA, new CompoundCriteria(crits)); } @@ -550,12 +541,38 @@ private void markDependent(PlanNode critNode, PlanNode accessNode, QueryMetadata } } - private List splitDependentSetCriteria(DependentSetCriteria dsc) { + private List splitDependentSetCriteria(DependentSetCriteria dsc, boolean supportsArray, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { List attributes = dsc.getAttributes(); List crits = new ArrayList(attributes.size()); + + Map> splits = new LinkedHashMap>(); + for (int i = 0; i < attributes.size(); i++) { + Object key = null; DependentSetCriteria.AttributeComparison comp = attributes.get(i); - DependentSetCriteria crit = RuleChooseDependent.createDependentSetCriteria(dsc.getContextSymbol(), Arrays.asList(comp)); + if (supportsArray && (comp.dep instanceof ElementSymbol)) { + ElementSymbol es = (ElementSymbol)comp.dep; + GroupSymbol group = es.getGroupSymbol(); + if (!metadata.isVirtualGroup(group.getMetadataID())) { + key = group; + } + //TODO: we could try to determine further if this is allowable + //for now since we are pushing as far as we can, this is a good indication, + //that it will need split + } + if (key == null) { + key = splits.size(); + } + List comps = splits.get(key); + if (comps == null) { + comps = new ArrayList(2); + splits.put(key, comps); + } + comps.add(comp); + } + + for (List comps : splits.values()) { + DependentSetCriteria crit = RuleChooseDependent.createDependentSetCriteria(dsc.getContextSymbol(), comps); crit.setMakeDepOptions(dsc.getMakeDepOptions()); crits.add(crit); } diff --git a/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java b/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java index 9e7c21a757..4f80d2a8f4 100644 --- a/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java +++ b/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java @@ -965,7 +965,7 @@ static PlanNode raiseAccessOverJoin(PlanNode joinNode, PlanNode accessNode, Obje // Combine hints if necessary RulePlaceAccess.copyDependentHints(other, accessNode); - RulePlaceAccess.copyDependentHints(joinNode, other); + RulePlaceAccess.copyDependentHints(joinNode, accessNode); combineSourceHints(accessNode, other); if (other.hasBooleanProperty(Info.IS_MULTI_SOURCE)) { diff --git a/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java b/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java index f8bf4e09d2..703695bd47 100644 --- a/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java +++ b/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java @@ -1376,4 +1376,32 @@ private void helpTestMax(String sql) { new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm2.g1 AS g_0 ORDER BY c_0", "SELECT g_1.e1 AS c_0, g_0.e1 AS c_1, g_1.e2 AS c_2 FROM pm1.g2 AS g_0, pm1.g1 AS g_1 WHERE (g_0.e1 = g_1.e1) AND (g_1.e1 IN ()) ORDER BY c_0" }, new DefaultCapabilitiesFinder(caps), TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING ); //$NON-NLS-1$ //$NON-NLS-2$ } + @Test public void testSplitPredicateSameTable() throws Exception { + // Create query + String sql = "SELECT a.e1, b.e3 FROM /*+ makedep */ (select pm1.g1.e1, pm1.g1.e2 from pm1.g1, pm1.g2 where pm1.g1.e3 = pm1.g2.e3) as a, " + + "(select pm2.g1.e1, pm2.g1.e2, pm2.g2.e3 from pm2.g1, pm2.g2 where pm2.g1.e3 = pm2.g2.e3) as b WHERE a.e1=b.e1 AND a.e2=b.e2"; //$NON-NLS-1$ + + BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities(); + bsc.setCapabilitySupport(Capability.ARRAY_TYPE, true); + + // Run query + TestOptimizer.helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] { + "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm1.g1 AS g_0, pm1.g2 AS g_1 WHERE (g_0.e3 = g_1.e3) AND ((g_0.e1, g_0.e2) IN ()) ORDER BY c_0, c_1", + "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_1.e3 AS c_2 FROM pm2.g1 AS g_0, pm2.g2 AS g_1 WHERE g_0.e3 = g_1.e3 ORDER BY c_0, c_1"}, new DefaultCapabilitiesFinder(bsc), ComparisonMode.EXACT_COMMAND_STRING); + } + + @Test public void testSplitPredicateDifferentTable() throws Exception { + // Create query + String sql = "SELECT a.e1, b.e3 FROM /*+ makedep */ (select pm1.g1.e1, pm1.g2.e2 from pm1.g1, pm1.g2 where pm1.g1.e3 = pm1.g2.e3) as a, " + + "(select pm2.g1.e1, pm2.g1.e2, pm2.g2.e3 from pm2.g1, pm2.g2 where pm2.g1.e3 = pm2.g2.e3) as b WHERE a.e1=b.e1 AND a.e2=b.e2"; //$NON-NLS-1$ + + BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities(); + bsc.setCapabilitySupport(Capability.ARRAY_TYPE, true); + + // Run query + TestOptimizer.helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] { + "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_1.e3 AS c_2 FROM pm2.g1 AS g_0, pm2.g2 AS g_1 WHERE g_0.e3 = g_1.e3 ORDER BY c_0, c_1" + , "SELECT g_0.e1 AS c_0, g_1.e2 AS c_1 FROM pm1.g1 AS g_0, pm1.g2 AS g_1 WHERE (g_0.e3 = g_1.e3) AND (g_0.e1 IN ()) AND (g_1.e2 IN ()) ORDER BY c_0, c_1"}, new DefaultCapabilitiesFinder(bsc), ComparisonMode.EXACT_COMMAND_STRING); + } + }