Skip to content

Commit

Permalink
TEIID-4737 fixing merging of virtual layers under an outer join
Browse files Browse the repository at this point in the history
  • Loading branch information
shawkins committed Feb 2, 2017
1 parent bb5f5f3 commit 5a11487
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 23 deletions.
Expand Up @@ -174,28 +174,15 @@ static PlanNode doMerge(PlanNode frame,
return root; //only consider no sources when the frame is simple and there is a parent join
}
if (sources.isEmpty() && parentJoin != null) {
PlanNode parent = frame.getParent();
boolean hasCriteria = false;
while (parent != parentJoin) {
if (parent.getType() != NodeConstants.Types.SELECT) {
return root; //sanity check, can only be filters
}
if (!parent.hasBooleanProperty(Info.IS_PHANTOM)) {
hasCriteria = true;
}
parent = parent.getParent();
}
PlanNode left = FrameUtil.findJoinSourceNode(parentJoin.getFirstChild());
boolean isLeft = left == frame;
JoinType jt = (JoinType) parentJoin.getProperty(Info.JOIN_TYPE);
if (jt.isOuter() && (hasCriteria || jt != JoinType.JOIN_LEFT_OUTER || FrameUtil.findJoinSourceNode(parentJoin.getFirstChild()) == frame)) {
return root; //cannot remove if the no source side is an outer side
if (jt.isOuter()) {
return root; //cannot remove if the no source side is an outer side, or if it can change the meaning of the plan
}
if (sources.isEmpty()) {
PlanNode left = FrameUtil.findJoinSourceNode(parentJoin.getFirstChild());
boolean isLeft = left == frame;
PlanNode other = isLeft? FrameUtil.findJoinSourceNode(parentJoin.getLastChild()):left;
if (other != null && (SymbolMap)other.getProperty(NodeConstants.Info.CORRELATED_REFERENCES) != null) {
return root; //TODO: we don't have the logic yet to then replace the correlated references
}
PlanNode other = isLeft? FrameUtil.findJoinSourceNode(parentJoin.getLastChild()):left;
if (other != null && (SymbolMap)other.getProperty(NodeConstants.Info.CORRELATED_REFERENCES) != null) {
return root; //TODO: we don't have the logic yet to then replace the correlated references
}
}
}
Expand Down
Expand Up @@ -459,11 +459,12 @@ public class TestRuleMergeVirtual {
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}

//should not allow the merge since it's an outer join
@Test public void testNoSourcesMerge3() throws Exception {
TestOptimizer.helpPlan("select z.* from pm1.g1 left outer join (select 1 as a, 2, 3) as z on pm1.g1.e2 = z.a", //$NON-NLS-1$
RealMetadataFactory.example1Cached(),
new String[] {
"SELECT 3 FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
"SELECT g_0.e2 AS c_0 FROM pm1.g1 AS g_0 ORDER BY c_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$

}

Expand All @@ -490,10 +491,10 @@ public class TestRuleMergeVirtual {
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setFunctionSupport("convert", true); //$NON-NLS-1$
caps.setFunctionSupport("array_get", true); //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan("select z.* from pm1.g1 left outer join arraytable(cast(pm1.g1.e1 as object) COLUMNS one integer, two integer, three integer) as z on (pm1.g1.e2 = z.one)", //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan("select z.* from pm1.g1 inner join arraytable(cast(pm1.g1.e1 as object) COLUMNS one integer, two integer, three integer) as z on (pm1.g1.e2 = z.one)", //$NON-NLS-1$
RealMetadataFactory.example1Cached(),
new String[] {
"SELECT convert(array_get(convert(g_0.e1, object), 1), integer), convert(array_get(convert(g_0.e1, object), 2), integer), convert(array_get(convert(g_0.e1, object), 3), integer) FROM pm1.g1 AS g_0"}, new DefaultCapabilitiesFinder(caps), ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
"SELECT convert(array_get(convert(g_0.e1, object), 1), integer), convert(array_get(convert(g_0.e1, object), 2), integer), convert(array_get(convert(g_0.e1, object), 3), integer) FROM pm1.g1 AS g_0 WHERE (convert(g_0.e1, object) IS NOT NULL) AND (g_0.e2 = convert(array_get(convert(g_0.e1, object), 1), integer))"}, new DefaultCapabilitiesFinder(caps), ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$

TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
Expand Down
20 changes: 20 additions & 0 deletions engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Expand Up @@ -7895,5 +7895,25 @@ private void sampleDataBQT2a(FakeDataManager dataMgr) throws Exception {
TestProcessor.helpProcess(plan, dataManager, new List<?>[] {Arrays.asList("a", "a")});
}

@Test public void testOuterJoinWithNoInnerSources() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.fromDDL("create foreign table test_emails(email string); CREATE view test_view_emails as SELECT 'test1@mail.com' as email", "x", "pm1");

String sql = "SELECT a.email, b.email, lower(a.email), lower(b.email) FROM test_emails as a left join test_view_emails as b on lower(a.email)=lower(b.email)";
ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata);
HardcodedDataManager dataManager = new HardcodedDataManager();
dataManager.addData("SELECT pm1.test_emails.email FROM pm1.test_emails", Arrays.asList("Test1@mail.com"), Arrays.asList("test2@mail.com"));
TestProcessor.helpProcess(plan, dataManager, new List<?>[] {Arrays.asList("Test1@mail.com", "test1@mail.com", "test1@mail.com", "test1@mail.com"), Arrays.asList("test2@mail.com", null, "test2@mail.com", null)});
}

@Test public void testOuterJoinWithNoOuterSources() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.fromDDL("create foreign table test_emails(email string); CREATE view test_view_emails as SELECT 'test1@mail.com' as email", "x", "pm1");

String sql = "SELECT a.email, b.email, lower(a.email), lower(b.email) FROM test_emails as a right outer join test_view_emails as b on lower(a.email)=lower(b.email)";
ProcessorPlan plan = TestProcessor.helpGetPlan(sql, metadata);
HardcodedDataManager dataManager = new HardcodedDataManager();
dataManager.addData("SELECT pm1.test_emails.email FROM pm1.test_emails", Arrays.asList("Test1@mail.com"), Arrays.asList("test2@mail.com"));
TestProcessor.helpProcess(plan, dataManager, new List<?>[] {Arrays.asList("Test1@mail.com", "test1@mail.com", "test1@mail.com", "test1@mail.com")});
}

private static final boolean DEBUG = false;
}

0 comments on commit 5a11487

Please sign in to comment.