diff --git a/enginetest/engine_only_test.go b/enginetest/engine_only_test.go index 1458995d0f..6dca9573a6 100644 --- a/enginetest/engine_only_test.go +++ b/enginetest/engine_only_test.go @@ -646,7 +646,6 @@ func TestShowCharset(t *testing.T) { } func TestTableFunctions(t *testing.T) { - // TODO different error messages harness := enginetest.NewDefaultMemoryHarness() harness.Setup(setup.MydbData) diff --git a/enginetest/evaluation.go b/enginetest/evaluation.go index 847476dd53..95421cdc3f 100644 --- a/enginetest/evaluation.go +++ b/enginetest/evaluation.go @@ -140,7 +140,7 @@ func TestScriptWithEngine(t *testing.T, e QueryEngine, harness Harness, script q } TestQueryWithContext(t, ctx, e, harness, assertion.Query, expected, assertion.ExpectedColumns, assertion.Bindings) } - if assertion.ExpectedIndexes != nil { + if assertion.ExpectedIndexes != nil && !IsServerEngine(e) { evalIndexTest(t, harness, e, assertion.Query, assertion.ExpectedIndexes, assertion.Skip) } if assertion.JoinTypes != nil { diff --git a/enginetest/join_planning_tests.go b/enginetest/join_planning_tests.go index b99d05ab5d..3d34d9168b 100644 --- a/enginetest/join_planning_tests.go +++ b/enginetest/join_planning_tests.go @@ -354,12 +354,12 @@ var JoinPlanningTests = []struct { }, { q: "select * from xy where x not in (select u from uv where u not in (select a from ab where a not in (select r from rs where r = 1))) order by 1;", - types: []plan.JoinType{plan.JoinTypeLeftOuterHashExcludeNulls, plan.JoinTypeLeftOuterHashExcludeNulls, plan.JoinTypeLeftOuterMerge}, + types: []plan.JoinType{plan.JoinTypeLeftOuterHashExcludeNulls, plan.JoinTypeLeftOuterHashExcludeNulls, plan.JoinTypeLeftOuterLookup}, exp: []sql.Row{{0, 2}, {2, 1}, {3, 3}}, }, { q: "select * from xy where x != (select r from rs where r = 1) order by 1;", - types: []plan.JoinType{plan.JoinTypeLeftOuterMerge}, + types: []plan.JoinType{plan.JoinTypeLeftOuterLookup}, exp: []sql.Row{{0, 2}, {2, 1}, {3, 3}}, }, { @@ -380,7 +380,7 @@ select * from uv where u > ( order by 1 limit 1 ) order by 1;`, - types: []plan.JoinType{plan.JoinTypeSemi, plan.JoinTypeCrossHash, plan.JoinTypeLeftOuterMerge}, + types: []plan.JoinType{plan.JoinTypeSemi, plan.JoinTypeCrossHash, plan.JoinTypeLeftOuterLookup}, exp: []sql.Row{{1, 1}, {2, 2}, {3, 2}}, }, { @@ -392,7 +392,7 @@ order by 1;`, { // order by will be discarded q: "select * from xy where x != (select r from rs where r = 1 order by 1) order by 1;", - types: []plan.JoinType{plan.JoinTypeLeftOuterMerge}, + types: []plan.JoinType{plan.JoinTypeLeftOuterLookup}, exp: []sql.Row{{0, 2}, {2, 1}, {3, 3}}, }, { @@ -409,7 +409,7 @@ order by 1;`, { // semi join will be right-side, be passed non-nil parent row q: "select x,a from ab, (select * from xy where x = (select r from rs where r = 1) order by 1) sq order by 1,2", - types: []plan.JoinType{plan.JoinTypeCrossHash, plan.JoinTypeLookup}, + types: []plan.JoinType{plan.JoinTypeCrossHash, plan.JoinTypeSemiLookup}, exp: []sql.Row{{1, 0}, {1, 1}, {1, 2}, {1, 3}}, }, //{ @@ -445,7 +445,7 @@ order by 1;`, }, { q: "select * from xy where x in (select u from uv join ab on u = a and a = 2) order by 1;", - types: []plan.JoinType{plan.JoinTypeHash, plan.JoinTypeMerge}, + types: []plan.JoinType{plan.JoinTypeLookup, plan.JoinTypeLookup}, exp: []sql.Row{{2, 1}}, }, { @@ -509,7 +509,7 @@ HAVING count(v) >= 1)`, }, { q: "select * from xy where y-1 = (select u from uv where v = 2 order by 1 limit 1);", - types: []plan.JoinType{plan.JoinTypeSemiLookup}, + types: []plan.JoinType{plan.JoinTypeSemi}, exp: []sql.Row{{3, 3}}, }, { @@ -537,7 +537,7 @@ HAVING count(v) >= 1)`, EXISTS (SELECT * FROM xy Alias1 WHERE Alias1.x = (xy.x + 1)) AND EXISTS (SELECT * FROM uv Alias2 WHERE Alias2.u = (xy.x + 2)));`, // These should both be JoinTypeSemiLookup, but for https://github.com/dolthub/go-mysql-server/issues/1893 - types: []plan.JoinType{plan.JoinTypeSemiLookup, plan.JoinTypeMerge}, + types: []plan.JoinType{plan.JoinTypeSemiLookup, plan.JoinTypeSemiLookup}, exp: []sql.Row{{0, 2}, {1, 0}}, }, { @@ -545,7 +545,7 @@ HAVING count(v) >= 1)`, EXISTS (SELECT * FROM xy Alias1 WHERE Alias1.x = (xy.x + 1)) AND EXISTS (SELECT * FROM uv Alias1 WHERE Alias1.u = (xy.x + 2)));`, // These should both be JoinTypeSemiLookup, but for https://github.com/dolthub/go-mysql-server/issues/1893 - types: []plan.JoinType{plan.JoinTypeSemiLookup, plan.JoinTypeMerge}, + types: []plan.JoinType{plan.JoinTypeSemiLookup, plan.JoinTypeSemiLookup}, exp: []sql.Row{{0, 2}, {1, 0}}, }, { @@ -579,7 +579,7 @@ WHERE EXISTS ( select x from xy where not exists (select a from ab where a = x and a = 1) and not exists (select a from ab where a = x and a = 2)`, - types: []plan.JoinType{plan.JoinTypeLeftOuterLookup, plan.JoinTypeLeftOuterMerge}, + types: []plan.JoinType{plan.JoinTypeLeftOuterLookup, plan.JoinTypeLeftOuterLookup}, exp: []sql.Row{{0}, {3}}, }, { @@ -615,7 +615,7 @@ FROM xy }, { q: `select * from xy where exists (select * from uv join ab on u = a)`, - types: []plan.JoinType{plan.JoinTypeCrossHash, plan.JoinTypeMerge}, + types: []plan.JoinType{plan.JoinTypeCrossHash, plan.JoinTypeLookup}, exp: []sql.Row{{0, 2}, {1, 0}, {2, 1}, {3, 3}}, }, }, @@ -754,7 +754,7 @@ where u in (select * from rec);`, tests: []JoinPlanTest{ { q: "select * from xy where x in (select u from uv join ab on u = a and a = 2) order by 1;", - types: []plan.JoinType{plan.JoinTypeHash, plan.JoinTypeMerge}, + types: []plan.JoinType{plan.JoinTypeHash, plan.JoinTypeLookup}, exp: []sql.Row{{2, 1}}, }, { diff --git a/enginetest/queries/integration_plans.go b/enginetest/queries/integration_plans.go index b89a384ec9..a0b9a0d622 100644 --- a/enginetest/queries/integration_plans.go +++ b/enginetest/queries/integration_plans.go @@ -880,7 +880,7 @@ WHERE ) `, ExpectedPlan: "Project\n" + - " ├─ columns: [ct.id:0!null as id, ci.FTQLQ:16!null as VCGT3, nd.TW55N:23!null as UWBAI, aac.BTXC5:13 as TPXBU, ct.V5DPX:8!null as V5DPX, ct.S3Q3Y:9!null as S3Q3Y, ct.ZRV3B:10!null as ZRV3B]\n" + + " ├─ columns: [ct.id:0!null as id, ci.FTQLQ:33!null as VCGT3, nd.TW55N:18!null as UWBAI, aac.BTXC5:13 as TPXBU, ct.V5DPX:8!null as V5DPX, ct.S3Q3Y:9!null as S3Q3Y, ct.ZRV3B:10!null as ZRV3B]\n" + " └─ Filter\n" + " ├─ Or\n" + " │ ├─ AND\n" + @@ -1007,12 +1007,9 @@ WHERE " │ └─ tableId: 9\n" + " └─ HashJoin\n" + " ├─ Eq\n" + - " │ ├─ nd.id:20!null\n" + - " │ └─ ct.LUEVY:2!null\n" + - " ├─ HashJoin\n" + - " │ ├─ Eq\n" + - " │ │ ├─ ci.id:15!null\n" + - " │ │ └─ ct.FZ2R5:1!null\n" + + " │ ├─ ci.id:32!null\n" + + " │ └─ ct.FZ2R5:1!null\n" + + " ├─ LookupJoin\n" + " │ ├─ LookupJoin\n" + " │ │ ├─ TableAlias(ct)\n" + " │ │ │ └─ ProcessTable\n" + @@ -1028,22 +1025,23 @@ WHERE " │ │ └─ Table\n" + " │ │ ├─ name: TPXBU\n" + " │ │ └─ columns: [id btxc5 fhcyt]\n" + - " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(ct.FZ2R5:1!null)\n" + - " │ ├─ right-key: TUPLE(ci.id:0!null)\n" + - " │ └─ TableAlias(ci)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: JDLNA\n" + - " │ └─ columns: [id ftqlq fwwiq o3qxw fhcyt]\n" + + " │ └─ TableAlias(nd)\n" + + " │ └─ IndexedTableAccess(E2I7U)\n" + + " │ ├─ index: [E2I7U.id]\n" + + " │ ├─ keys: [ct.LUEVY:2!null]\n" + + " │ ├─ colSet: (18-34)\n" + + " │ ├─ tableId: 3\n" + + " │ └─ Table\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(ct.LUEVY:2!null)\n" + - " ├─ right-key: TUPLE(nd.id:0!null)\n" + - " └─ TableAlias(nd)\n" + + " ├─ left-key: TUPLE(ct.FZ2R5:1!null)\n" + + " ├─ right-key: TUPLE(ci.id:0!null)\n" + + " └─ TableAlias(ci)\n" + " └─ ProcessTable\n" + " └─ Table\n" + - " ├─ name: E2I7U\n" + - " └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + + " ├─ name: JDLNA\n" + + " └─ columns: [id ftqlq fwwiq o3qxw fhcyt]\n" + "", }, { @@ -1200,19 +1198,16 @@ WHERE TVTJS.SWCQV = 1 `, ExpectedPlan: "Project\n" + - " ├─ columns: [ct.id:0!null as id, ci.FTQLQ:13!null as VCGT3, nd.TW55N:15!null as UWBAI, aac.BTXC5:9 as TPXBU, ct.V5DPX:5!null as V5DPX, ct.S3Q3Y:6!null as S3Q3Y, ct.ZRV3B:7!null as ZRV3B]\n" + + " ├─ columns: [ct.id:0!null as id, ci.FTQLQ:15!null as VCGT3, nd.TW55N:11!null as UWBAI, aac.BTXC5:9 as TPXBU, ct.V5DPX:5!null as V5DPX, ct.S3Q3Y:6!null as S3Q3Y, ct.ZRV3B:7!null as ZRV3B]\n" + " └─ HashJoin\n" + " ├─ Eq\n" + - " │ ├─ nd.id:14!null\n" + - " │ └─ ct.LUEVY:2!null\n" + + " │ ├─ ci.id:14!null\n" + + " │ └─ ct.FZ2R5:1!null\n" + " ├─ HashJoin\n" + " │ ├─ Eq\n" + - " │ │ ├─ ci.id:12!null\n" + - " │ │ └─ ct.FZ2R5:1!null\n" + - " │ ├─ HashJoin\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ tvtjs.id:10!null\n" + - " │ │ │ └─ ct.XMM6Q:4\n" + + " │ │ ├─ tvtjs.id:12!null\n" + + " │ │ └─ ct.XMM6Q:4\n" + + " │ ├─ LookupJoin\n" + " │ │ ├─ LookupJoin\n" + " │ │ │ ├─ TableAlias(ct)\n" + " │ │ │ │ └─ ProcessTable\n" + @@ -1228,34 +1223,35 @@ WHERE " │ │ │ └─ Table\n" + " │ │ │ ├─ name: TPXBU\n" + " │ │ │ └─ columns: [id btxc5]\n" + - " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(ct.XMM6Q:4)\n" + - " │ │ ├─ right-key: TUPLE(tvtjs.id:0!null)\n" + - " │ │ └─ Filter\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ tvtjs.SWCQV:1!null\n" + - " │ │ │ └─ 1 (tinyint)\n" + - " │ │ └─ TableAlias(tvtjs)\n" + - " │ │ └─ ProcessTable\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: HU5A5\n" + - " │ │ └─ columns: [id swcqv]\n" + + " │ │ └─ TableAlias(nd)\n" + + " │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ ├─ index: [E2I7U.id]\n" + + " │ │ ├─ keys: [ct.LUEVY:2!null]\n" + + " │ │ ├─ colSet: (31-47)\n" + + " │ │ ├─ tableId: 4\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: E2I7U\n" + + " │ │ └─ columns: [id tw55n]\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(ct.FZ2R5:1!null)\n" + - " │ ├─ right-key: TUPLE(ci.id:0!null)\n" + - " │ └─ TableAlias(ci)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: JDLNA\n" + - " │ └─ columns: [id ftqlq]\n" + + " │ ├─ left-key: TUPLE(ct.XMM6Q:4)\n" + + " │ ├─ right-key: TUPLE(tvtjs.id:0!null)\n" + + " │ └─ Filter\n" + + " │ ├─ Eq\n" + + " │ │ ├─ tvtjs.SWCQV:1!null\n" + + " │ │ └─ 1 (tinyint)\n" + + " │ └─ TableAlias(tvtjs)\n" + + " │ └─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: HU5A5\n" + + " │ └─ columns: [id swcqv]\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(ct.LUEVY:2!null)\n" + - " ├─ right-key: TUPLE(nd.id:0!null)\n" + - " └─ TableAlias(nd)\n" + + " ├─ left-key: TUPLE(ct.FZ2R5:1!null)\n" + + " ├─ right-key: TUPLE(ci.id:0!null)\n" + + " └─ TableAlias(ci)\n" + " └─ ProcessTable\n" + " └─ Table\n" + - " ├─ name: E2I7U\n" + - " └─ columns: [id tw55n]\n" + + " ├─ name: JDLNA\n" + + " └─ columns: [id ftqlq]\n" + "", }, { @@ -1350,105 +1346,87 @@ WHERE PV6R5.NUMK2 <> 1 `, ExpectedPlan: "Project\n" + - " ├─ columns: [rn.id:8!null as id, concat(nsplt.TW55N:1!null,FDNCN (longtext),lqncx.TW55N:7!null) as X37NA, concat(xlza5.TW55N:13!null,FDNCN (longtext),afjmd.TW55N:18!null) as THWCS, rn.HVHRZ:11!null as HVHRZ]\n" + + " ├─ columns: [rn.id:0!null as id, concat(nsplt.TW55N:9!null,FDNCN (longtext),lqncx.TW55N:11!null) as X37NA, concat(xlza5.TW55N:16!null,FDNCN (longtext),afjmd.TW55N:18!null) as THWCS, rn.HVHRZ:3!null as HVHRZ]\n" + " └─ Filter\n" + " ├─ Or\n" + " │ ├─ NOT\n" + " │ │ └─ Eq\n" + - " │ │ ├─ pv6r5.FFTBJ:4!null\n" + - " │ │ └─ zyutc.BRQP2:15!null\n" + + " │ │ ├─ pv6r5.FFTBJ:6!null\n" + + " │ │ └─ zyutc.BRQP2:13!null\n" + " │ └─ NOT\n" + " │ └─ Eq\n" + - " │ ├─ pv6r5.NUMK2:5!null\n" + + " │ ├─ pv6r5.NUMK2:7!null\n" + " │ └─ 1 (tinyint)\n" + " └─ HashJoin\n" + " ├─ Eq\n" + - " │ ├─ rn.HHVLX:10!null\n" + - " │ └─ zyutc.id:14!null\n" + + " │ ├─ rn.HHVLX:2!null\n" + + " │ └─ zyutc.id:12!null\n" + " ├─ HashJoin\n" + " │ ├─ Eq\n" + - " │ │ ├─ rn.WNUNU:9!null\n" + - " │ │ └─ pv6r5.id:2!null\n" + - " │ ├─ HashJoin\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ lqncx.id:6!null\n" + - " │ │ │ └─ pv6r5.FFTBJ:4!null\n" + - " │ │ ├─ MergeJoin\n" + - " │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ ├─ nsplt.id:0!null\n" + - " │ │ │ │ └─ pv6r5.BRQP2:3!null\n" + - " │ │ │ ├─ TableAlias(nsplt)\n" + - " │ │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ │ ├─ index: [E2I7U.id]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (27-43)\n" + - " │ │ │ │ ├─ tableId: 4\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: E2I7U\n" + - " │ │ │ │ └─ columns: [id tw55n]\n" + - " │ │ │ └─ TableAlias(pv6r5)\n" + - " │ │ │ └─ IndexedTableAccess(NOXN3)\n" + - " │ │ │ ├─ index: [NOXN3.BRQP2]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (7-16)\n" + - " │ │ │ ├─ tableId: 2\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: NOXN3\n" + - " │ │ │ └─ columns: [id brqp2 fftbj numk2]\n" + - " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(pv6r5.FFTBJ:4!null)\n" + - " │ │ ├─ right-key: TUPLE(lqncx.id:0!null)\n" + - " │ │ └─ TableAlias(lqncx)\n" + - " │ │ └─ ProcessTable\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: E2I7U\n" + - " │ │ └─ columns: [id tw55n]\n" + + " │ │ ├─ rn.WNUNU:1!null\n" + + " │ │ └─ pv6r5.id:4!null\n" + + " │ ├─ TableAlias(rn)\n" + + " │ │ └─ ProcessTable\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: QYWQD\n" + + " │ │ └─ columns: [id wnunu hhvlx hvhrz]\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(pv6r5.id:2!null)\n" + - " │ ├─ right-key: TUPLE(rn.WNUNU:1!null)\n" + - " │ └─ TableAlias(rn)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: QYWQD\n" + - " │ └─ columns: [id wnunu hhvlx hvhrz]\n" + + " │ ├─ left-key: TUPLE(rn.WNUNU:1!null)\n" + + " │ ├─ right-key: TUPLE(pv6r5.id:0!null)\n" + + " │ └─ LookupJoin\n" + + " │ ├─ LookupJoin\n" + + " │ │ ├─ TableAlias(pv6r5)\n" + + " │ │ │ └─ ProcessTable\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: NOXN3\n" + + " │ │ │ └─ columns: [id brqp2 fftbj numk2]\n" + + " │ │ └─ TableAlias(nsplt)\n" + + " │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ ├─ index: [E2I7U.id]\n" + + " │ │ ├─ keys: [pv6r5.BRQP2:5!null]\n" + + " │ │ ├─ colSet: (27-43)\n" + + " │ │ ├─ tableId: 4\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: E2I7U\n" + + " │ │ └─ columns: [id tw55n]\n" + + " │ └─ TableAlias(lqncx)\n" + + " │ └─ IndexedTableAccess(E2I7U)\n" + + " │ ├─ index: [E2I7U.id]\n" + + " │ ├─ keys: [pv6r5.FFTBJ:6!null]\n" + + " │ ├─ colSet: (44-60)\n" + + " │ ├─ tableId: 5\n" + + " │ └─ Table\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id tw55n]\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(rn.HHVLX:10!null)\n" + - " ├─ right-key: TUPLE(zyutc.id:2!null)\n" + - " └─ HashJoin\n" + - " ├─ Eq\n" + - " │ ├─ afjmd.id:17!null\n" + - " │ └─ zyutc.FFTBJ:16!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ xlza5.id:12!null\n" + - " │ │ └─ zyutc.BRQP2:15!null\n" + - " │ ├─ TableAlias(xlza5)\n" + - " │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ ├─ index: [E2I7U.id]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (61-77)\n" + - " │ │ ├─ tableId: 6\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: E2I7U\n" + - " │ │ └─ columns: [id tw55n]\n" + - " │ └─ TableAlias(zyutc)\n" + - " │ └─ IndexedTableAccess(NOXN3)\n" + - " │ ├─ index: [NOXN3.BRQP2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (17-26)\n" + - " │ ├─ tableId: 3\n" + + " ├─ left-key: TUPLE(rn.HHVLX:2!null)\n" + + " ├─ right-key: TUPLE(zyutc.id:0!null)\n" + + " └─ LookupJoin\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(zyutc)\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: NOXN3\n" + + " │ │ ├─ columns: [id brqp2 fftbj]\n" + + " │ │ ├─ colSet: (17-26)\n" + + " │ │ └─ tableId: 3\n" + + " │ └─ TableAlias(xlza5)\n" + + " │ └─ IndexedTableAccess(E2I7U)\n" + + " │ ├─ index: [E2I7U.id]\n" + + " │ ├─ keys: [zyutc.BRQP2:13!null]\n" + + " │ ├─ colSet: (61-77)\n" + + " │ ├─ tableId: 6\n" + " │ └─ Table\n" + - " │ ├─ name: NOXN3\n" + - " │ └─ columns: [id brqp2 fftbj]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(zyutc.FFTBJ:16!null)\n" + - " ├─ right-key: TUPLE(afjmd.id:0!null)\n" + - " └─ TableAlias(afjmd)\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id tw55n]\n" + + " └─ TableAlias(afjmd)\n" + + " └─ IndexedTableAccess(E2I7U)\n" + + " ├─ index: [E2I7U.id]\n" + + " ├─ keys: [zyutc.FFTBJ:14!null]\n" + + " ├─ colSet: (78-94)\n" + + " ├─ tableId: 7\n" + " └─ Table\n" + " ├─ name: E2I7U\n" + - " ├─ columns: [id tw55n]\n" + - " ├─ colSet: (78-94)\n" + - " └─ tableId: 7\n" + + " └─ columns: [id tw55n]\n" + "", }, { @@ -1493,123 +1471,100 @@ WHERE rn.WNUNU IS NULL AND rn.HHVLX IS NULL `, ExpectedPlan: "Project\n" + - " ├─ columns: [sn.id:7!null as DRIWM, concat(oe56m.TW55N:6!null,FDNCN (longtext),cgfrz.TW55N:16!null) as GRVSE, skpm6.id:2!null as JIEVY, concat(v5say.TW55N:14!null,FDNCN (longtext),fqthf.TW55N:1!null) as ENCM3, 1 (decimal(2,1)) as OHD3R]\n" + + " ├─ columns: [sn.id:5!null as DRIWM, concat(oe56m.TW55N:10!null,FDNCN (longtext),cgfrz.TW55N:12!null) as GRVSE, skpm6.id:0!null as JIEVY, concat(v5say.TW55N:14!null,FDNCN (longtext),fqthf.TW55N:4!null) as ENCM3, 1 (decimal(2,1)) as OHD3R]\n" + " └─ Filter\n" + " ├─ AND\n" + - " │ ├─ rn.WNUNU:11!null IS NULL\n" + - " │ └─ rn.HHVLX:12!null IS NULL\n" + - " └─ HashJoin\n" + + " │ ├─ rn.WNUNU:15!null IS NULL\n" + + " │ └─ rn.HHVLX:16!null IS NULL\n" + + " └─ LeftOuterHashJoin\n" + " ├─ AND\n" + + " │ ├─ Eq\n" + + " │ │ ├─ rn.WNUNU:15!null\n" + + " │ │ └─ sn.id:5!null\n" + + " │ └─ Eq\n" + + " │ ├─ rn.HHVLX:16!null\n" + + " │ └─ skpm6.id:0!null\n" + + " ├─ HashJoin\n" + " │ ├─ AND\n" + " │ │ ├─ AND\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ cgfrz.id:15!null\n" + - " │ │ │ │ └─ sn.FFTBJ:9!null\n" + + " │ │ │ │ ├─ skpm6.BRQP2:1!null\n" + + " │ │ │ │ └─ sn.FFTBJ:7!null\n" + " │ │ │ └─ Eq\n" + " │ │ │ ├─ v5say.id:13!null\n" + - " │ │ │ └─ skpm6.BRQP2:3!null\n" + + " │ │ │ └─ skpm6.BRQP2:1!null\n" + " │ │ └─ Eq\n" + - " │ │ ├─ sn.FFTBJ:9!null\n" + - " │ │ └─ v5say.id:13!null\n" + - " │ └─ Eq\n" + - " │ ├─ skpm6.BRQP2:3!null\n" + - " │ └─ cgfrz.id:15!null\n" + - " ├─ LeftOuterHashJoin\n" + - " │ ├─ AND\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ rn.WNUNU:11!null\n" + - " │ │ │ └─ sn.id:7!null\n" + - " │ │ └─ Eq\n" + - " │ │ ├─ rn.HHVLX:12!null\n" + - " │ │ └─ skpm6.id:2!null\n" + - " │ ├─ HashJoin\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ skpm6.BRQP2:3!null\n" + - " │ │ │ └─ sn.FFTBJ:9!null\n" + - " │ │ ├─ MergeJoin\n" + - " │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ ├─ fqthf.id:0!null\n" + - " │ │ │ │ └─ skpm6.FFTBJ:4!null\n" + - " │ │ │ ├─ TableAlias(fqthf)\n" + - " │ │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ │ ├─ index: [E2I7U.id]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (78-94)\n" + - " │ │ │ │ ├─ tableId: 7\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: E2I7U\n" + - " │ │ │ │ └─ columns: [id tw55n]\n" + - " │ │ │ └─ TableAlias(skpm6)\n" + - " │ │ │ └─ IndexedTableAccess(NOXN3)\n" + - " │ │ │ ├─ index: [NOXN3.FFTBJ]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (11-20)\n" + - " │ │ │ ├─ tableId: 2\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: NOXN3\n" + - " │ │ │ └─ columns: [id brqp2 fftbj]\n" + - " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(skpm6.BRQP2:3!null)\n" + - " │ │ ├─ right-key: TUPLE(sn.FFTBJ:4!null)\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ oe56m.id:5!null\n" + - " │ │ │ └─ sn.BRQP2:8!null\n" + - " │ │ ├─ TableAlias(oe56m)\n" + - " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ ├─ index: [E2I7U.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (27-43)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: E2I7U\n" + - " │ │ │ └─ columns: [id tw55n]\n" + - " │ │ └─ Filter\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ sn.NUMK2:3!null\n" + - " │ │ │ └─ 1 (tinyint)\n" + - " │ │ └─ TableAlias(sn)\n" + - " │ │ └─ IndexedTableAccess(NOXN3)\n" + - " │ │ ├─ index: [NOXN3.BRQP2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-10)\n" + - " │ │ ├─ tableId: 1\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: NOXN3\n" + - " │ │ └─ columns: [id brqp2 fftbj numk2]\n" + + " │ │ ├─ skpm6.BRQP2:1!null\n" + + " │ │ └─ cgfrz.id:11!null\n" + + " │ ├─ LookupJoin\n" + + " │ │ ├─ TableAlias(skpm6)\n" + + " │ │ │ └─ ProcessTable\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: NOXN3\n" + + " │ │ │ └─ columns: [id brqp2 fftbj]\n" + + " │ │ └─ TableAlias(fqthf)\n" + + " │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ ├─ index: [E2I7U.id]\n" + + " │ │ ├─ keys: [skpm6.FFTBJ:2!null]\n" + + " │ │ ├─ colSet: (78-94)\n" + + " │ │ ├─ tableId: 7\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: E2I7U\n" + + " │ │ └─ columns: [id tw55n]\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(sn.id:7!null, skpm6.id:2!null)\n" + - " │ ├─ right-key: TUPLE(rn.WNUNU:0!null, rn.HHVLX:1!null)\n" + - " │ └─ TableAlias(rn)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: QYWQD\n" + - " │ └─ columns: [wnunu hhvlx]\n" + + " │ ├─ left-key: TUPLE(skpm6.BRQP2:1!null, skpm6.BRQP2:1!null, skpm6.BRQP2:1!null)\n" + + " │ ├─ right-key: TUPLE(sn.FFTBJ:2!null, v5say.id:8!null, cgfrz.id:6!null)\n" + + " │ └─ LookupJoin\n" + + " │ ├─ Eq\n" + + " │ │ ├─ cgfrz.id:11!null\n" + + " │ │ └─ v5say.id:13!null\n" + + " │ ├─ LookupJoin\n" + + " │ │ ├─ LookupJoin\n" + + " │ │ │ ├─ Filter\n" + + " │ │ │ │ ├─ Eq\n" + + " │ │ │ │ │ ├─ sn.NUMK2:3!null\n" + + " │ │ │ │ │ └─ 1 (tinyint)\n" + + " │ │ │ │ └─ TableAlias(sn)\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: NOXN3\n" + + " │ │ │ │ ├─ columns: [id brqp2 fftbj numk2]\n" + + " │ │ │ │ ├─ colSet: (1-10)\n" + + " │ │ │ │ └─ tableId: 1\n" + + " │ │ │ └─ TableAlias(oe56m)\n" + + " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ │ ├─ index: [E2I7U.id]\n" + + " │ │ │ ├─ keys: [sn.BRQP2:6!null]\n" + + " │ │ │ ├─ colSet: (27-43)\n" + + " │ │ │ ├─ tableId: 4\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: E2I7U\n" + + " │ │ │ └─ columns: [id tw55n]\n" + + " │ │ └─ TableAlias(cgfrz)\n" + + " │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ ├─ index: [E2I7U.id]\n" + + " │ │ ├─ keys: [sn.FFTBJ:7!null]\n" + + " │ │ ├─ colSet: (44-60)\n" + + " │ │ ├─ tableId: 5\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: E2I7U\n" + + " │ │ └─ columns: [id tw55n]\n" + + " │ └─ TableAlias(v5say)\n" + + " │ └─ IndexedTableAccess(E2I7U)\n" + + " │ ├─ index: [E2I7U.id]\n" + + " │ ├─ keys: [sn.FFTBJ:7!null]\n" + + " │ ├─ colSet: (61-77)\n" + + " │ ├─ tableId: 6\n" + + " │ └─ Table\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id tw55n]\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(sn.FFTBJ:9!null, skpm6.BRQP2:3!null, sn.FFTBJ:9!null, skpm6.BRQP2:3!null)\n" + - " ├─ right-key: TUPLE(cgfrz.id:2!null, v5say.id:0!null, v5say.id:0!null, cgfrz.id:2!null)\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ v5say.id:13!null\n" + - " │ └─ cgfrz.id:15!null\n" + - " ├─ TableAlias(v5say)\n" + - " │ └─ IndexedTableAccess(E2I7U)\n" + - " │ ├─ index: [E2I7U.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (61-77)\n" + - " │ ├─ tableId: 6\n" + - " │ └─ Table\n" + - " │ ├─ name: E2I7U\n" + - " │ └─ columns: [id tw55n]\n" + - " └─ TableAlias(cgfrz)\n" + - " └─ IndexedTableAccess(E2I7U)\n" + - " ├─ index: [E2I7U.id]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (44-60)\n" + - " ├─ tableId: 5\n" + - " └─ Table\n" + - " ├─ name: E2I7U\n" + - " └─ columns: [id tw55n]\n" + + " ├─ left-key: TUPLE(sn.id:5!null, skpm6.id:0!null)\n" + + " ├─ right-key: TUPLE(rn.WNUNU:0!null, rn.HHVLX:1!null)\n" + + " └─ TableAlias(rn)\n" + + " └─ ProcessTable\n" + + " └─ Table\n" + + " ├─ name: QYWQD\n" + + " └─ columns: [wnunu hhvlx]\n" + "", }, { @@ -2135,12 +2090,12 @@ WHERE ) `, ExpectedPlan: "Project\n" + - " ├─ columns: [mf.id:17!null as id, cla.FTQLQ:38!null as T4IBQ, nd.TW55N:3!null as UWBAI, aac.BTXC5:35 as TPXBU, mf.FSDY2:27!null as FSDY2]\n" + + " ├─ columns: [mf.id:0!null as id, cla.FTQLQ:22!null as T4IBQ, nd.TW55N:54!null as UWBAI, aac.BTXC5:69 as TPXBU, mf.FSDY2:10!null as FSDY2]\n" + " └─ Filter\n" + " ├─ Or\n" + " │ ├─ AND\n" + " │ │ ├─ NOT\n" + - " │ │ │ └─ mf.QQV4M:32 IS NULL\n" + + " │ │ │ └─ mf.QQV4M:15 IS NULL\n" + " │ │ └─ Or\n" + " │ │ ├─ Eq\n" + " │ │ │ ├─ Subquery\n" + @@ -2151,11 +2106,11 @@ WHERE " │ │ │ │ └─ Filter\n" + " │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ ├─ tj5d2.id:71!null\n" + - " │ │ │ │ │ └─ mf.QQV4M:32\n" + + " │ │ │ │ │ └─ mf.QQV4M:15\n" + " │ │ │ │ └─ TableAlias(tj5d2)\n" + " │ │ │ │ └─ IndexedTableAccess(SZW6V)\n" + " │ │ │ │ ├─ index: [SZW6V.id]\n" + - " │ │ │ │ ├─ keys: [mf.QQV4M:32]\n" + + " │ │ │ │ ├─ keys: [mf.QQV4M:15]\n" + " │ │ │ │ ├─ colSet: (72-79)\n" + " │ │ │ │ ├─ tableId: 6\n" + " │ │ │ │ └─ Table\n" + @@ -2180,11 +2135,11 @@ WHERE " │ │ │ │ └─ Filter\n" + " │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ ├─ tj5d2.id:88!null\n" + - " │ │ │ │ │ └─ mf.QQV4M:32\n" + + " │ │ │ │ │ └─ mf.QQV4M:15\n" + " │ │ │ │ └─ TableAlias(tj5d2)\n" + " │ │ │ │ └─ IndexedTableAccess(SZW6V)\n" + " │ │ │ │ ├─ index: [SZW6V.id]\n" + - " │ │ │ │ ├─ keys: [mf.QQV4M:32]\n" + + " │ │ │ │ ├─ keys: [mf.QQV4M:15]\n" + " │ │ │ │ ├─ colSet: (97-104)\n" + " │ │ │ │ ├─ tableId: 8\n" + " │ │ │ │ └─ Table\n" + @@ -2196,123 +2151,111 @@ WHERE " │ │ │ ├─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + " │ │ │ ├─ colSet: (80-96)\n" + " │ │ │ └─ tableId: 7\n" + - " │ │ └─ mf.LUEVY:19!null\n" + + " │ │ └─ mf.LUEVY:2!null\n" + " │ └─ AND\n" + " │ ├─ NOT\n" + - " │ │ └─ mf.TEUJA:31 IS NULL\n" + + " │ │ └─ mf.TEUJA:14 IS NULL\n" + " │ └─ InSubquery\n" + - " │ ├─ left: mf.TEUJA:31\n" + + " │ ├─ left: mf.TEUJA:14\n" + " │ └─ right: Subquery\n" + " │ ├─ cacheable: true\n" + " │ ├─ alias-string: select umf.id as ORB3K from SZW6V as TJ5D2 join NZKPM as umf on umf.T4IBQ = TJ5D2.T4IBQ and umf.FGG57 = TJ5D2.V7UFH and umf.SYPKF = TJ5D2.SYPKF where TJ5D2.SWCQV = 0 and TJ5D2.id not in (select QQV4M from HGMQ6 where QQV4M is not null)\n" + " │ └─ Project\n" + " │ ├─ columns: [umf.id:79!null as ORB3K]\n" + - " │ └─ Project\n" + - " │ ├─ columns: [tj5d2.id:71!null, tj5d2.T4IBQ:72!null, tj5d2.V7UFH:73!null, tj5d2.SYPKF:74!null, tj5d2.H4DMT:75!null, tj5d2.SWCQV:76!null, tj5d2.YKSSU:77, tj5d2.FHCYT:78, umf.id:79!null, umf.T4IBQ:80, umf.FGG57:81, umf.SSHPJ:82, umf.NLA6O:83, umf.SFJ6L:84, umf.TJPT7:85, umf.ARN5P:86, umf.SYPKF:87, umf.IVFMK:88, umf.IDE43:89, umf.AZ6SP:90, umf.FSDY2:91, umf.XOSD4:92, umf.HMW4H:93, umf.S76OM:94, umf.vaf:95, umf.ZROH6:96, umf.QCGTS:97, umf.LNFM6:98, umf.TVAWL:99, umf.HDLCL:100, umf.BHHW6:101, umf.FHCYT:102, umf.QZ6VT:103]\n" + - " │ └─ Filter\n" + - " │ ├─ hgmq6.QQV4M:104 IS NULL\n" + - " │ └─ LeftOuterLookupJoin\n" + - " │ ├─ LookupJoin\n" + - " │ │ ├─ AND\n" + - " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ umf.T4IBQ:80\n" + - " │ │ │ │ └─ tj5d2.T4IBQ:72!null\n" + - " │ │ │ └─ Eq\n" + - " │ │ │ ├─ umf.SYPKF:87\n" + - " │ │ │ └─ tj5d2.SYPKF:74!null\n" + - " │ │ ├─ Filter\n" + - " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ tj5d2.SWCQV:76!null\n" + - " │ │ │ │ └─ 0 (tinyint)\n" + - " │ │ │ └─ TableAlias(tj5d2)\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: SZW6V\n" + - " │ │ │ ├─ columns: [id t4ibq v7ufh sypkf h4dmt swcqv ykssu fhcyt]\n" + - " │ │ │ ├─ colSet: (105-112)\n" + - " │ │ │ └─ tableId: 9\n" + - " │ │ └─ TableAlias(umf)\n" + - " │ │ └─ IndexedTableAccess(NZKPM)\n" + - " │ │ ├─ index: [NZKPM.FGG57]\n" + - " │ │ ├─ keys: [tj5d2.V7UFH:73!null]\n" + - " │ │ ├─ colSet: (113-137)\n" + - " │ │ ├─ tableId: 10\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: NZKPM\n" + - " │ │ └─ columns: [id t4ibq fgg57 sshpj nla6o sfj6l tjpt7 arn5p sypkf ivfmk ide43 az6sp fsdy2 xosd4 hmw4h s76om vaf zroh6 qcgts lnfm6 tvawl hdlcl bhhw6 fhcyt qz6vt]\n" + - " │ └─ Filter\n" + - " │ ├─ NOT\n" + - " │ │ └─ hgmq6.QQV4M:71 IS NULL\n" + - " │ └─ IndexedTableAccess(HGMQ6)\n" + - " │ ├─ index: [HGMQ6.QQV4M]\n" + - " │ ├─ keys: [tj5d2.id:71!null]\n" + - " │ ├─ colSet: (138-154)\n" + - " │ ├─ tableId: 11\n" + - " │ └─ Table\n" + - " │ ├─ name: HGMQ6\n" + - " │ └─ columns: [qqv4m]\n" + + " │ └─ LookupJoin\n" + + " │ ├─ AND\n" + + " │ │ ├─ Eq\n" + + " │ │ │ ├─ umf.T4IBQ:80\n" + + " │ │ │ └─ tj5d2.T4IBQ:72!null\n" + + " │ │ └─ Eq\n" + + " │ │ ├─ umf.SYPKF:87\n" + + " │ │ └─ tj5d2.SYPKF:74!null\n" + + " │ ├─ Project\n" + + " │ │ ├─ columns: [tj5d2.id:71!null, tj5d2.T4IBQ:72!null, tj5d2.V7UFH:73!null, tj5d2.SYPKF:74!null, tj5d2.H4DMT:75!null, tj5d2.SWCQV:76!null, tj5d2.YKSSU:77, tj5d2.FHCYT:78]\n" + + " │ │ └─ Filter\n" + + " │ │ ├─ hgmq6.QQV4M:79 IS NULL\n" + + " │ │ └─ LeftOuterLookupJoin\n" + + " │ │ ├─ Filter\n" + + " │ │ │ ├─ Eq\n" + + " │ │ │ │ ├─ tj5d2.SWCQV:76!null\n" + + " │ │ │ │ └─ 0 (tinyint)\n" + + " │ │ │ └─ TableAlias(tj5d2)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: SZW6V\n" + + " │ │ │ ├─ columns: [id t4ibq v7ufh sypkf h4dmt swcqv ykssu fhcyt]\n" + + " │ │ │ ├─ colSet: (105-112)\n" + + " │ │ │ └─ tableId: 9\n" + + " │ │ └─ Filter\n" + + " │ │ ├─ NOT\n" + + " │ │ │ └─ hgmq6.QQV4M:71 IS NULL\n" + + " │ │ └─ IndexedTableAccess(HGMQ6)\n" + + " │ │ ├─ index: [HGMQ6.QQV4M]\n" + + " │ │ ├─ keys: [tj5d2.id:71!null]\n" + + " │ │ ├─ colSet: (138-154)\n" + + " │ │ ├─ tableId: 11\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: HGMQ6\n" + + " │ │ └─ columns: [qqv4m]\n" + + " │ └─ TableAlias(umf)\n" + + " │ └─ IndexedTableAccess(NZKPM)\n" + + " │ ├─ index: [NZKPM.FGG57]\n" + + " │ ├─ keys: [tj5d2.V7UFH:73!null]\n" + + " │ ├─ colSet: (113-137)\n" + + " │ ├─ tableId: 10\n" + + " │ └─ Table\n" + + " │ ├─ name: NZKPM\n" + + " │ └─ columns: [id t4ibq fgg57 sshpj nla6o sfj6l tjpt7 arn5p sypkf ivfmk ide43 az6sp fsdy2 xosd4 hmw4h s76om vaf zroh6 qcgts lnfm6 tvawl hdlcl bhhw6 fhcyt qz6vt]\n" + " └─ HashJoin\n" + " ├─ Eq\n" + - " │ ├─ bs.id:67!null\n" + - " │ └─ mf.GXLUB:18!null\n" + + " │ ├─ aac.id:68!null\n" + + " │ └─ mf.M22QN:3!null\n" + " ├─ HashJoin\n" + " │ ├─ Eq\n" + - " │ │ ├─ aac.id:34!null\n" + - " │ │ └─ mf.M22QN:20!null\n" + - " │ ├─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ nd.id:0!null\n" + - " │ │ │ └─ mf.LUEVY:19!null\n" + - " │ │ ├─ TableAlias(nd)\n" + - " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ ├─ index: [E2I7U.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (52-68)\n" + - " │ │ │ ├─ tableId: 4\n" + + " │ │ ├─ nd.id:51!null\n" + + " │ │ └─ mf.LUEVY:2!null\n" + + " │ ├─ HashJoin\n" + + " │ │ ├─ Eq\n" + + " │ │ │ ├─ bs.id:17!null\n" + + " │ │ │ └─ mf.GXLUB:1!null\n" + + " │ │ ├─ TableAlias(mf)\n" + + " │ │ │ └─ ProcessTable\n" + " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: E2I7U\n" + - " │ │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + - " │ │ └─ TableAlias(mf)\n" + - " │ │ └─ IndexedTableAccess(HGMQ6)\n" + - " │ │ ├─ index: [HGMQ6.LUEVY]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-17)\n" + - " │ │ ├─ tableId: 1\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: HGMQ6\n" + - " │ │ └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" + + " │ │ │ ├─ name: HGMQ6\n" + + " │ │ │ └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" + + " │ │ └─ HashLookup\n" + + " │ │ ├─ left-key: TUPLE(mf.GXLUB:1!null)\n" + + " │ │ ├─ right-key: TUPLE(bs.id:0!null)\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ ProcessTable\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ └─ columns: [id nfryn ixuxu fhcyt]\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:19]\n" + + " │ │ ├─ colSet: (22-51)\n" + + " │ │ ├─ tableId: 3\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(mf.M22QN:20!null)\n" + - " │ ├─ right-key: TUPLE(aac.id:0!null)\n" + - " │ └─ TableAlias(aac)\n" + + " │ ├─ left-key: TUPLE(mf.LUEVY:2!null)\n" + + " │ ├─ right-key: TUPLE(nd.id:0!null)\n" + + " │ └─ TableAlias(nd)\n" + " │ └─ ProcessTable\n" + " │ └─ Table\n" + - " │ ├─ name: TPXBU\n" + - " │ └─ columns: [id btxc5 fhcyt]\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(mf.GXLUB:18!null)\n" + - " ├─ right-key: TUPLE(bs.id:30!null)\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ cla.id:37!null\n" + - " │ └─ bs.IXUXU:69\n" + - " ├─ TableAlias(cla)\n" + - " │ └─ IndexedTableAccess(YK2GW)\n" + - " │ ├─ index: [YK2GW.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (22-51)\n" + - " │ ├─ tableId: 3\n" + - " │ └─ Table\n" + - " │ ├─ name: YK2GW\n" + - " │ └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" + - " └─ TableAlias(bs)\n" + - " └─ IndexedTableAccess(THNTS)\n" + - " ├─ index: [THNTS.IXUXU]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (18-21)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: THNTS\n" + - " └─ columns: [id nfryn ixuxu fhcyt]\n" + + " ├─ left-key: TUPLE(mf.M22QN:3!null)\n" + + " ├─ right-key: TUPLE(aac.id:0!null)\n" + + " └─ TableAlias(aac)\n" + + " └─ ProcessTable\n" + + " └─ Table\n" + + " ├─ name: TPXBU\n" + + " └─ columns: [id btxc5 fhcyt]\n" + "", }, { @@ -2384,15 +2327,14 @@ WHERE " └─ HashLookup\n" + " ├─ left-key: TUPLE(umf.FGG57:2)\n" + " ├─ right-key: TUPLE(nd.FGG57:6)\n" + - " └─ TableAlias(nd)\n" + - " └─ IndexedTableAccess(E2I7U)\n" + - " ├─ index: [E2I7U.FGG57]\n" + - " ├─ static: [{(NULL, ∞)}]\n" + - " ├─ colSet: (26-42)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: E2I7U\n" + - " └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + + " └─ Filter\n" + + " ├─ NOT\n" + + " │ └─ nd.FGG57:6 IS NULL\n" + + " └─ TableAlias(nd)\n" + + " └─ ProcessTable\n" + + " └─ Table\n" + + " ├─ name: E2I7U\n" + + " └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + "", }, { @@ -2684,16 +2626,9 @@ WHERE " │ └─ HashLookup\n" + " │ ├─ left-key: TUPLE(mf.GXLUB:1!null)\n" + " │ ├─ right-key: TUPLE(bs.id:0!null)\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ bs.IXUXU:35\n" + - " │ │ └─ cla.id:37!null\n" + + " │ └─ LookupJoin\n" + " │ ├─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (31-34)\n" + - " │ │ ├─ tableId: 2\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: THNTS\n" + " │ │ └─ columns: [id nfryn ixuxu fhcyt]\n" + @@ -2704,7 +2639,7 @@ WHERE " │ └─ TableAlias(cla)\n" + " │ └─ IndexedTableAccess(YK2GW)\n" + " │ ├─ index: [YK2GW.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [bs.IXUXU:35]\n" + " │ ├─ colSet: (1-30)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -3170,16 +3105,9 @@ WHERE " │ └─ HashLookup\n" + " │ ├─ left-key: TUPLE(mf.GXLUB:1!null)\n" + " │ ├─ right-key: TUPLE(bs.id:0!null)\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ bs.IXUXU:35\n" + - " │ │ └─ cla.id:37!null\n" + + " │ └─ LookupJoin\n" + " │ ├─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (31-34)\n" + - " │ │ ├─ tableId: 2\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: THNTS\n" + " │ │ └─ columns: [id nfryn ixuxu fhcyt]\n" + @@ -3190,7 +3118,7 @@ WHERE " │ └─ TableAlias(cla)\n" + " │ └─ IndexedTableAccess(YK2GW)\n" + " │ ├─ index: [YK2GW.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [bs.IXUXU:35]\n" + " │ ├─ colSet: (1-30)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -3560,44 +3488,35 @@ WHERE " └─ Window\n" + " ├─ row_number() over ( order by sn.id ASC)\n" + " ├─ s7egw.TW55N:8!null\n" + - " ├─ tymvl.TW55N:1!null\n" + - " ├─ sn.NUMK2:5!null\n" + - " ├─ sn.LETOE:6!null\n" + - " ├─ sn.id:2!null\n" + - " └─ HashJoin\n" + - " ├─ Eq\n" + - " │ ├─ sn.BRQP2:3!null\n" + - " │ └─ s7egw.id:7!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ tymvl.id:0!null\n" + - " │ │ └─ sn.FFTBJ:4!null\n" + - " │ ├─ TableAlias(tymvl)\n" + - " │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ ├─ index: [E2I7U.id]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (28-44)\n" + - " │ │ ├─ tableId: 3\n" + + " ├─ tymvl.TW55N:6!null\n" + + " ├─ sn.NUMK2:3!null\n" + + " ├─ sn.LETOE:4!null\n" + + " ├─ sn.id:0!null\n" + + " └─ LookupJoin\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(sn)\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: E2I7U\n" + - " │ │ └─ columns: [id tw55n]\n" + - " │ └─ TableAlias(sn)\n" + - " │ └─ IndexedTableAccess(NOXN3)\n" + - " │ ├─ index: [NOXN3.FFTBJ]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-10)\n" + - " │ ├─ tableId: 1\n" + + " │ │ ├─ name: NOXN3\n" + + " │ │ └─ columns: [id brqp2 fftbj numk2 letoe]\n" + + " │ └─ TableAlias(tymvl)\n" + + " │ └─ IndexedTableAccess(E2I7U)\n" + + " │ ├─ index: [E2I7U.id]\n" + + " │ ├─ keys: [sn.FFTBJ:2!null]\n" + + " │ ├─ colSet: (28-44)\n" + + " │ ├─ tableId: 3\n" + " │ └─ Table\n" + - " │ ├─ name: NOXN3\n" + - " │ └─ columns: [id brqp2 fftbj numk2 letoe]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(sn.BRQP2:3!null)\n" + - " ├─ right-key: TUPLE(s7egw.id:0!null)\n" + - " └─ TableAlias(s7egw)\n" + - " └─ ProcessTable\n" + - " └─ Table\n" + - " ├─ name: E2I7U\n" + - " └─ columns: [id tw55n]\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id tw55n]\n" + + " └─ TableAlias(s7egw)\n" + + " └─ IndexedTableAccess(E2I7U)\n" + + " ├─ index: [E2I7U.id]\n" + + " ├─ keys: [sn.BRQP2:1!null]\n" + + " ├─ colSet: (11-27)\n" + + " ├─ tableId: 2\n" + + " └─ Table\n" + + " ├─ name: E2I7U\n" + + " └─ columns: [id tw55n]\n" + "", }, { @@ -3842,19 +3761,13 @@ WHERE " │ ├─ tableId: 3\n" + " │ └─ Project\n" + " │ ├─ columns: [bs.id:0!null as B2TX3, cla.FTQLQ:3!null as T4IBQ]\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ bs.IXUXU:1\n" + - " │ │ └─ cla.id:2!null\n" + + " │ └─ LookupJoin\n" + " │ ├─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: THNTS\n" + + " │ │ ├─ columns: [id ixuxu]\n" + " │ │ ├─ colSet: (31-34)\n" + - " │ │ ├─ tableId: 2\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ └─ tableId: 2\n" + " │ └─ Filter\n" + " │ ├─ HashIn\n" + " │ │ ├─ cla.FTQLQ:1!null\n" + @@ -3862,7 +3775,7 @@ WHERE " │ └─ TableAlias(cla)\n" + " │ └─ IndexedTableAccess(YK2GW)\n" + " │ ├─ index: [YK2GW.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [bs.IXUXU:1]\n" + " │ ├─ colSet: (1-30)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -4033,14 +3946,14 @@ WHERE " ├─ colSet: (194-200)\n" + " ├─ tableId: 22\n" + " └─ Project\n" + - " ├─ columns: [bs.T4IBQ:1!null as T4IBQ, pa.DZLIM:8!null as ECUWU, pga.DZLIM:17!null as GSTQA, pog.B5OUF:15, fc.OZTQF:20!null, f26zw.YHYLK:24, nd.TW55N:3!null as TW55N]\n" + + " ├─ columns: [bs.T4IBQ:1!null as T4IBQ, pa.DZLIM:3!null as ECUWU, pga.DZLIM:12!null as GSTQA, pog.B5OUF:10, fc.OZTQF:20!null, f26zw.YHYLK:24, nd.TW55N:16!null as TW55N]\n" + " └─ Filter\n" + " ├─ Eq\n" + - " │ ├─ ms.D237E:11!null\n" + + " │ ├─ ms.D237E:6!null\n" + " │ └─ true (tinyint(1))\n" + " └─ LeftOuterHashJoin\n" + " ├─ Eq\n" + - " │ ├─ nd.HPCMS:4!null\n" + + " │ ├─ nd.HPCMS:17!null\n" + " │ └─ nma.id:25!null\n" + " ├─ LeftOuterHashJoin\n" + " │ ├─ AND\n" + @@ -4049,18 +3962,18 @@ WHERE " │ │ │ └─ bs.T4IBQ:1!null\n" + " │ │ └─ Eq\n" + " │ │ ├─ f26zw.BRQP2:22!null\n" + - " │ │ └─ nd.id:2!null\n" + + " │ │ └─ nd.id:15!null\n" + " │ ├─ LeftOuterHashJoin\n" + " │ │ ├─ AND\n" + " │ │ │ ├─ Eq\n" + " │ │ │ │ ├─ bs.id:0!null\n" + " │ │ │ │ └─ fc.GXLUB:18!null\n" + " │ │ │ └─ Eq\n" + - " │ │ │ ├─ nd.id:2!null\n" + + " │ │ │ ├─ nd.id:15!null\n" + " │ │ │ └─ fc.LUEVY:19!null\n" + " │ │ ├─ LeftOuterHashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ ms.GXLUB:9!null\n" + + " │ │ │ │ ├─ ms.GXLUB:4!null\n" + " │ │ │ │ └─ bs.id:0!null\n" + " │ │ │ ├─ SubqueryAlias\n" + " │ │ │ │ ├─ name: bs\n" + @@ -4074,109 +3987,97 @@ WHERE " │ │ │ │ │ ├─ T4IBQ:1!null\n" + " │ │ │ │ │ └─ TUPLE(SQ1 (longtext))\n" + " │ │ │ │ └─ Project\n" + - " │ │ │ │ ├─ columns: [thnts.id:2!null, yk2gw.FTQLQ:1!null as T4IBQ]\n" + - " │ │ │ │ └─ MergeJoin\n" + - " │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ ├─ yk2gw.id:0!null\n" + - " │ │ │ │ │ └─ thnts.IXUXU:3\n" + - " │ │ │ │ ├─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (43-72)\n" + - " │ │ │ │ │ ├─ tableId: 8\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: YK2GW\n" + - " │ │ │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (39-42)\n" + - " │ │ │ │ ├─ tableId: 7\n" + + " │ │ │ │ ├─ columns: [thnts.id:0!null, yk2gw.FTQLQ:3!null as T4IBQ]\n" + + " │ │ │ │ └─ LookupJoin\n" + + " │ │ │ │ ├─ Table\n" + + " │ │ │ │ │ ├─ name: THNTS\n" + + " │ │ │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ │ │ ├─ colSet: (39-42)\n" + + " │ │ │ │ │ └─ tableId: 7\n" + + " │ │ │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ │ │ ├─ index: [YK2GW.id]\n" + + " │ │ │ │ ├─ keys: [thnts.IXUXU:1]\n" + + " │ │ │ │ ├─ colSet: (43-72)\n" + + " │ │ │ │ ├─ tableId: 8\n" + " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: THNTS\n" + - " │ │ │ │ └─ columns: [id ixuxu]\n" + + " │ │ │ │ ├─ name: YK2GW\n" + + " │ │ │ │ └─ columns: [id ftqlq]\n" + " │ │ │ └─ HashLookup\n" + " │ │ │ ├─ left-key: TUPLE(bs.id:0!null)\n" + - " │ │ │ ├─ right-key: TUPLE(ms.GXLUB:7!null)\n" + + " │ │ │ ├─ right-key: TUPLE(ms.GXLUB:2!null)\n" + " │ │ │ └─ HashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ pog.id:12!null\n" + - " │ │ │ │ └─ gz7z4.GMSGA:6!null\n" + - " │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ ├─ nd.id:2!null\n" + - " │ │ │ │ │ └─ gz7z4.LUEVY:5!null\n" + - " │ │ │ │ ├─ TableAlias(nd)\n" + - " │ │ │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ │ │ ├─ index: [E2I7U.id]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (22-38)\n" + - " │ │ │ │ │ ├─ tableId: 6\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: E2I7U\n" + - " │ │ │ │ │ └─ columns: [id tw55n hpcms]\n" + - " │ │ │ │ └─ TableAlias(gz7z4)\n" + - " │ │ │ │ └─ IndexedTableAccess(FEIOE)\n" + - " │ │ │ │ ├─ index: [FEIOE.LUEVY,FEIOE.GMSGA]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (16-21)\n" + - " │ │ │ │ ├─ tableId: 5\n" + + " │ │ │ │ ├─ pog.id:7!null\n" + + " │ │ │ │ └─ gz7z4.GMSGA:14!null\n" + + " │ │ │ ├─ HashJoin\n" + + " │ │ │ │ ├─ Eq\n" + + " │ │ │ │ │ ├─ pog.XVSBH:9\n" + + " │ │ │ │ │ └─ pga.id:11!null\n" + + " │ │ │ │ ├─ LeftOuterHashJoin\n" + + " │ │ │ │ │ ├─ Eq\n" + + " │ │ │ │ │ │ ├─ pa.id:2!null\n" + + " │ │ │ │ │ │ └─ pog.CH3FR:8!null\n" + + " │ │ │ │ │ ├─ MergeJoin\n" + + " │ │ │ │ │ │ ├─ cmp: Eq\n" + + " │ │ │ │ │ │ │ ├─ pa.id:2!null\n" + + " │ │ │ │ │ │ │ └─ ms.CH3FR:5!null\n" + + " │ │ │ │ │ │ ├─ TableAlias(pa)\n" + + " │ │ │ │ │ │ │ └─ IndexedTableAccess(XOAOP)\n" + + " │ │ │ │ │ │ │ ├─ index: [XOAOP.id]\n" + + " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ ├─ colSet: (6-8)\n" + + " │ │ │ │ │ │ │ ├─ tableId: 2\n" + + " │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ ├─ name: XOAOP\n" + + " │ │ │ │ │ │ │ └─ columns: [id dzlim]\n" + + " │ │ │ │ │ │ └─ TableAlias(ms)\n" + + " │ │ │ │ │ │ └─ IndexedTableAccess(SZQWJ)\n" + + " │ │ │ │ │ │ ├─ index: [SZQWJ.CH3FR]\n" + + " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ ├─ colSet: (1-5)\n" + + " │ │ │ │ │ │ ├─ tableId: 1\n" + + " │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ ├─ name: SZQWJ\n" + + " │ │ │ │ │ │ └─ columns: [gxlub ch3fr d237e]\n" + + " │ │ │ │ │ └─ HashLookup\n" + + " │ │ │ │ │ ├─ left-key: TUPLE(pa.id:2!null)\n" + + " │ │ │ │ │ ├─ right-key: TUPLE(pog.CH3FR:1!null)\n" + + " │ │ │ │ │ └─ TableAlias(pog)\n" + + " │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ ├─ name: NPCYY\n" + + " │ │ │ │ │ ├─ columns: [id ch3fr xvsbh b5ouf]\n" + + " │ │ │ │ │ ├─ colSet: (9-12)\n" + + " │ │ │ │ │ └─ tableId: 3\n" + + " │ │ │ │ └─ HashLookup\n" + + " │ │ │ │ ├─ left-key: TUPLE(pog.XVSBH:9)\n" + + " │ │ │ │ ├─ right-key: TUPLE(pga.id:0!null)\n" + + " │ │ │ │ └─ TableAlias(pga)\n" + " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: FEIOE\n" + - " │ │ │ │ └─ columns: [luevy gmsga]\n" + + " │ │ │ │ ├─ name: PG27A\n" + + " │ │ │ │ ├─ columns: [id dzlim]\n" + + " │ │ │ │ ├─ colSet: (13-15)\n" + + " │ │ │ │ └─ tableId: 4\n" + " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(gz7z4.GMSGA:6!null)\n" + - " │ │ │ ├─ right-key: TUPLE(pog.id:5!null)\n" + - " │ │ │ └─ HashJoin\n" + - " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ pog.XVSBH:14\n" + - " │ │ │ │ └─ pga.id:16!null\n" + - " │ │ │ ├─ LeftOuterHashJoin\n" + - " │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ ├─ pa.id:7!null\n" + - " │ │ │ │ │ └─ pog.CH3FR:13!null\n" + - " │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ ├─ pa.id:7!null\n" + - " │ │ │ │ │ │ └─ ms.CH3FR:10!null\n" + - " │ │ │ │ │ ├─ TableAlias(pa)\n" + - " │ │ │ │ │ │ └─ IndexedTableAccess(XOAOP)\n" + - " │ │ │ │ │ │ ├─ index: [XOAOP.id]\n" + - " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ │ ├─ colSet: (6-8)\n" + - " │ │ │ │ │ │ ├─ tableId: 2\n" + - " │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ ├─ name: XOAOP\n" + - " │ │ │ │ │ │ └─ columns: [id dzlim]\n" + - " │ │ │ │ │ └─ TableAlias(ms)\n" + - " │ │ │ │ │ └─ IndexedTableAccess(SZQWJ)\n" + - " │ │ │ │ │ ├─ index: [SZQWJ.CH3FR]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (1-5)\n" + - " │ │ │ │ │ ├─ tableId: 1\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: SZQWJ\n" + - " │ │ │ │ │ └─ columns: [gxlub ch3fr d237e]\n" + - " │ │ │ │ └─ HashLookup\n" + - " │ │ │ │ ├─ left-key: TUPLE(pa.id:7!null)\n" + - " │ │ │ │ ├─ right-key: TUPLE(pog.CH3FR:1!null)\n" + - " │ │ │ │ └─ TableAlias(pog)\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: NPCYY\n" + - " │ │ │ │ ├─ columns: [id ch3fr xvsbh b5ouf]\n" + - " │ │ │ │ ├─ colSet: (9-12)\n" + - " │ │ │ │ └─ tableId: 3\n" + - " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(pog.XVSBH:14)\n" + - " │ │ │ ├─ right-key: TUPLE(pga.id:0!null)\n" + - " │ │ │ └─ TableAlias(pga)\n" + + " │ │ │ ├─ left-key: TUPLE(pog.id:7!null)\n" + + " │ │ │ ├─ right-key: TUPLE(gz7z4.GMSGA:1!null)\n" + + " │ │ │ └─ LookupJoin\n" + + " │ │ │ ├─ TableAlias(gz7z4)\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: FEIOE\n" + + " │ │ │ │ ├─ columns: [luevy gmsga]\n" + + " │ │ │ │ ├─ colSet: (16-21)\n" + + " │ │ │ │ └─ tableId: 5\n" + + " │ │ │ └─ TableAlias(nd)\n" + + " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ │ ├─ index: [E2I7U.id]\n" + + " │ │ │ ├─ keys: [gz7z4.LUEVY:13!null]\n" + + " │ │ │ ├─ colSet: (22-38)\n" + + " │ │ │ ├─ tableId: 6\n" + " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: PG27A\n" + - " │ │ │ ├─ columns: [id dzlim]\n" + - " │ │ │ ├─ colSet: (13-15)\n" + - " │ │ │ └─ tableId: 4\n" + + " │ │ │ ├─ name: E2I7U\n" + + " │ │ │ └─ columns: [id tw55n hpcms]\n" + " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(bs.id:0!null, nd.id:2!null)\n" + + " │ │ ├─ left-key: TUPLE(bs.id:0!null, nd.id:15!null)\n" + " │ │ ├─ right-key: TUPLE(fc.GXLUB:0!null, fc.LUEVY:1!null)\n" + " │ │ └─ TableAlias(fc)\n" + " │ │ └─ Table\n" + @@ -4185,7 +4086,7 @@ WHERE " │ │ ├─ colSet: (76-83)\n" + " │ │ └─ tableId: 10\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(bs.T4IBQ:1!null, nd.id:2!null)\n" + + " │ ├─ left-key: TUPLE(bs.T4IBQ:1!null, nd.id:15!null)\n" + " │ ├─ right-key: TUPLE(f26zw.T4IBQ:0!null, f26zw.BRQP2:1!null)\n" + " │ └─ SubqueryAlias\n" + " │ ├─ name: f26zw\n" + @@ -4386,7 +4287,7 @@ WHERE " │ ├─ colSet: (176-181)\n" + " │ └─ tableId: 19\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(nd.HPCMS:4!null)\n" + + " ├─ left-key: TUPLE(nd.HPCMS:17!null)\n" + " ├─ right-key: TUPLE(nma.id:0!null)\n" + " └─ TableAlias(nma)\n" + " └─ Table\n" + @@ -4551,14 +4452,14 @@ WHERE " ├─ colSet: (194-200)\n" + " ├─ tableId: 22\n" + " └─ Project\n" + - " ├─ columns: [bs.T4IBQ:1!null as T4IBQ, pa.DZLIM:8!null as ECUWU, pga.DZLIM:17!null as GSTQA, pog.B5OUF:15, fc.OZTQF:20!null, f26zw.YHYLK:24, nd.TW55N:3!null as TW55N]\n" + + " ├─ columns: [bs.T4IBQ:1!null as T4IBQ, pa.DZLIM:3!null as ECUWU, pga.DZLIM:12!null as GSTQA, pog.B5OUF:10, fc.OZTQF:20!null, f26zw.YHYLK:24, nd.TW55N:16!null as TW55N]\n" + " └─ Filter\n" + " ├─ Eq\n" + - " │ ├─ ms.D237E:11!null\n" + + " │ ├─ ms.D237E:6!null\n" + " │ └─ true (tinyint(1))\n" + " └─ LeftOuterHashJoin\n" + " ├─ Eq\n" + - " │ ├─ nd.HPCMS:4!null\n" + + " │ ├─ nd.HPCMS:17!null\n" + " │ └─ nma.id:25!null\n" + " ├─ LeftOuterHashJoin\n" + " │ ├─ AND\n" + @@ -4567,18 +4468,18 @@ WHERE " │ │ │ └─ bs.T4IBQ:1!null\n" + " │ │ └─ Eq\n" + " │ │ ├─ f26zw.BRQP2:22!null\n" + - " │ │ └─ nd.id:2!null\n" + + " │ │ └─ nd.id:15!null\n" + " │ ├─ LeftOuterHashJoin\n" + " │ │ ├─ AND\n" + " │ │ │ ├─ Eq\n" + " │ │ │ │ ├─ bs.id:0!null\n" + " │ │ │ │ └─ fc.GXLUB:18!null\n" + " │ │ │ └─ Eq\n" + - " │ │ │ ├─ nd.id:2!null\n" + + " │ │ │ ├─ nd.id:15!null\n" + " │ │ │ └─ fc.LUEVY:19!null\n" + " │ │ ├─ LeftOuterHashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ ms.GXLUB:9!null\n" + + " │ │ │ │ ├─ ms.GXLUB:4!null\n" + " │ │ │ │ └─ bs.id:0!null\n" + " │ │ │ ├─ SubqueryAlias\n" + " │ │ │ │ ├─ name: bs\n" + @@ -4592,109 +4493,97 @@ WHERE " │ │ │ │ │ ├─ T4IBQ:1!null\n" + " │ │ │ │ │ └─ TUPLE(SQ1 (longtext))\n" + " │ │ │ │ └─ Project\n" + - " │ │ │ │ ├─ columns: [thnts.id:2!null, yk2gw.FTQLQ:1!null as T4IBQ]\n" + - " │ │ │ │ └─ MergeJoin\n" + - " │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ ├─ yk2gw.id:0!null\n" + - " │ │ │ │ │ └─ thnts.IXUXU:3\n" + - " │ │ │ │ ├─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (43-72)\n" + - " │ │ │ │ │ ├─ tableId: 8\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: YK2GW\n" + - " │ │ │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (39-42)\n" + - " │ │ │ │ ├─ tableId: 7\n" + + " │ │ │ │ ├─ columns: [thnts.id:0!null, yk2gw.FTQLQ:3!null as T4IBQ]\n" + + " │ │ │ │ └─ LookupJoin\n" + + " │ │ │ │ ├─ Table\n" + + " │ │ │ │ │ ├─ name: THNTS\n" + + " │ │ │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ │ │ ├─ colSet: (39-42)\n" + + " │ │ │ │ │ └─ tableId: 7\n" + + " │ │ │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ │ │ ├─ index: [YK2GW.id]\n" + + " │ │ │ │ ├─ keys: [thnts.IXUXU:1]\n" + + " │ │ │ │ ├─ colSet: (43-72)\n" + + " │ │ │ │ ├─ tableId: 8\n" + " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: THNTS\n" + - " │ │ │ │ └─ columns: [id ixuxu]\n" + + " │ │ │ │ ├─ name: YK2GW\n" + + " │ │ │ │ └─ columns: [id ftqlq]\n" + " │ │ │ └─ HashLookup\n" + " │ │ │ ├─ left-key: TUPLE(bs.id:0!null)\n" + - " │ │ │ ├─ right-key: TUPLE(ms.GXLUB:7!null)\n" + + " │ │ │ ├─ right-key: TUPLE(ms.GXLUB:2!null)\n" + " │ │ │ └─ HashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ pog.id:12!null\n" + - " │ │ │ │ └─ gz7z4.GMSGA:6!null\n" + - " │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ ├─ nd.id:2!null\n" + - " │ │ │ │ │ └─ gz7z4.LUEVY:5!null\n" + - " │ │ │ │ ├─ TableAlias(nd)\n" + - " │ │ │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ │ │ ├─ index: [E2I7U.id]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (22-38)\n" + - " │ │ │ │ │ ├─ tableId: 6\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: E2I7U\n" + - " │ │ │ │ │ └─ columns: [id tw55n hpcms]\n" + - " │ │ │ │ └─ TableAlias(gz7z4)\n" + - " │ │ │ │ └─ IndexedTableAccess(FEIOE)\n" + - " │ │ │ │ ├─ index: [FEIOE.LUEVY,FEIOE.GMSGA]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (16-21)\n" + - " │ │ │ │ ├─ tableId: 5\n" + + " │ │ │ │ ├─ pog.id:7!null\n" + + " │ │ │ │ └─ gz7z4.GMSGA:14!null\n" + + " │ │ │ ├─ HashJoin\n" + + " │ │ │ │ ├─ Eq\n" + + " │ │ │ │ │ ├─ pog.XVSBH:9\n" + + " │ │ │ │ │ └─ pga.id:11!null\n" + + " │ │ │ │ ├─ LeftOuterHashJoin\n" + + " │ │ │ │ │ ├─ Eq\n" + + " │ │ │ │ │ │ ├─ pa.id:2!null\n" + + " │ │ │ │ │ │ └─ pog.CH3FR:8!null\n" + + " │ │ │ │ │ ├─ MergeJoin\n" + + " │ │ │ │ │ │ ├─ cmp: Eq\n" + + " │ │ │ │ │ │ │ ├─ pa.id:2!null\n" + + " │ │ │ │ │ │ │ └─ ms.CH3FR:5!null\n" + + " │ │ │ │ │ │ ├─ TableAlias(pa)\n" + + " │ │ │ │ │ │ │ └─ IndexedTableAccess(XOAOP)\n" + + " │ │ │ │ │ │ │ ├─ index: [XOAOP.id]\n" + + " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ ├─ colSet: (6-8)\n" + + " │ │ │ │ │ │ │ ├─ tableId: 2\n" + + " │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ ├─ name: XOAOP\n" + + " │ │ │ │ │ │ │ └─ columns: [id dzlim]\n" + + " │ │ │ │ │ │ └─ TableAlias(ms)\n" + + " │ │ │ │ │ │ └─ IndexedTableAccess(SZQWJ)\n" + + " │ │ │ │ │ │ ├─ index: [SZQWJ.CH3FR]\n" + + " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ ├─ colSet: (1-5)\n" + + " │ │ │ │ │ │ ├─ tableId: 1\n" + + " │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ ├─ name: SZQWJ\n" + + " │ │ │ │ │ │ └─ columns: [gxlub ch3fr d237e]\n" + + " │ │ │ │ │ └─ HashLookup\n" + + " │ │ │ │ │ ├─ left-key: TUPLE(pa.id:2!null)\n" + + " │ │ │ │ │ ├─ right-key: TUPLE(pog.CH3FR:1!null)\n" + + " │ │ │ │ │ └─ TableAlias(pog)\n" + + " │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ ├─ name: NPCYY\n" + + " │ │ │ │ │ ├─ columns: [id ch3fr xvsbh b5ouf]\n" + + " │ │ │ │ │ ├─ colSet: (9-12)\n" + + " │ │ │ │ │ └─ tableId: 3\n" + + " │ │ │ │ └─ HashLookup\n" + + " │ │ │ │ ├─ left-key: TUPLE(pog.XVSBH:9)\n" + + " │ │ │ │ ├─ right-key: TUPLE(pga.id:0!null)\n" + + " │ │ │ │ └─ TableAlias(pga)\n" + " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: FEIOE\n" + - " │ │ │ │ └─ columns: [luevy gmsga]\n" + + " │ │ │ │ ├─ name: PG27A\n" + + " │ │ │ │ ├─ columns: [id dzlim]\n" + + " │ │ │ │ ├─ colSet: (13-15)\n" + + " │ │ │ │ └─ tableId: 4\n" + " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(gz7z4.GMSGA:6!null)\n" + - " │ │ │ ├─ right-key: TUPLE(pog.id:5!null)\n" + - " │ │ │ └─ HashJoin\n" + - " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ pog.XVSBH:14\n" + - " │ │ │ │ └─ pga.id:16!null\n" + - " │ │ │ ├─ LeftOuterHashJoin\n" + - " │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ ├─ pa.id:7!null\n" + - " │ │ │ │ │ └─ pog.CH3FR:13!null\n" + - " │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ ├─ pa.id:7!null\n" + - " │ │ │ │ │ │ └─ ms.CH3FR:10!null\n" + - " │ │ │ │ │ ├─ TableAlias(pa)\n" + - " │ │ │ │ │ │ └─ IndexedTableAccess(XOAOP)\n" + - " │ │ │ │ │ │ ├─ index: [XOAOP.id]\n" + - " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ │ ├─ colSet: (6-8)\n" + - " │ │ │ │ │ │ ├─ tableId: 2\n" + - " │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ ├─ name: XOAOP\n" + - " │ │ │ │ │ │ └─ columns: [id dzlim]\n" + - " │ │ │ │ │ └─ TableAlias(ms)\n" + - " │ │ │ │ │ └─ IndexedTableAccess(SZQWJ)\n" + - " │ │ │ │ │ ├─ index: [SZQWJ.CH3FR]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (1-5)\n" + - " │ │ │ │ │ ├─ tableId: 1\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: SZQWJ\n" + - " │ │ │ │ │ └─ columns: [gxlub ch3fr d237e]\n" + - " │ │ │ │ └─ HashLookup\n" + - " │ │ │ │ ├─ left-key: TUPLE(pa.id:7!null)\n" + - " │ │ │ │ ├─ right-key: TUPLE(pog.CH3FR:1!null)\n" + - " │ │ │ │ └─ TableAlias(pog)\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: NPCYY\n" + - " │ │ │ │ ├─ columns: [id ch3fr xvsbh b5ouf]\n" + - " │ │ │ │ ├─ colSet: (9-12)\n" + - " │ │ │ │ └─ tableId: 3\n" + - " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(pog.XVSBH:14)\n" + - " │ │ │ ├─ right-key: TUPLE(pga.id:0!null)\n" + - " │ │ │ └─ TableAlias(pga)\n" + + " │ │ │ ├─ left-key: TUPLE(pog.id:7!null)\n" + + " │ │ │ ├─ right-key: TUPLE(gz7z4.GMSGA:1!null)\n" + + " │ │ │ └─ LookupJoin\n" + + " │ │ │ ├─ TableAlias(gz7z4)\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: FEIOE\n" + + " │ │ │ │ ├─ columns: [luevy gmsga]\n" + + " │ │ │ │ ├─ colSet: (16-21)\n" + + " │ │ │ │ └─ tableId: 5\n" + + " │ │ │ └─ TableAlias(nd)\n" + + " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ │ ├─ index: [E2I7U.id]\n" + + " │ │ │ ├─ keys: [gz7z4.LUEVY:13!null]\n" + + " │ │ │ ├─ colSet: (22-38)\n" + + " │ │ │ ├─ tableId: 6\n" + " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: PG27A\n" + - " │ │ │ ├─ columns: [id dzlim]\n" + - " │ │ │ ├─ colSet: (13-15)\n" + - " │ │ │ └─ tableId: 4\n" + + " │ │ │ ├─ name: E2I7U\n" + + " │ │ │ └─ columns: [id tw55n hpcms]\n" + " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(bs.id:0!null, nd.id:2!null)\n" + + " │ │ ├─ left-key: TUPLE(bs.id:0!null, nd.id:15!null)\n" + " │ │ ├─ right-key: TUPLE(fc.GXLUB:0!null, fc.LUEVY:1!null)\n" + " │ │ └─ TableAlias(fc)\n" + " │ │ └─ Table\n" + @@ -4703,7 +4592,7 @@ WHERE " │ │ ├─ colSet: (76-83)\n" + " │ │ └─ tableId: 10\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(bs.T4IBQ:1!null, nd.id:2!null)\n" + + " │ ├─ left-key: TUPLE(bs.T4IBQ:1!null, nd.id:15!null)\n" + " │ ├─ right-key: TUPLE(f26zw.T4IBQ:0!null, f26zw.BRQP2:1!null)\n" + " │ └─ SubqueryAlias\n" + " │ ├─ name: f26zw\n" + @@ -4799,95 +4688,80 @@ WHERE " │ │ │ ├─ colSet: (168-172)\n" + " │ │ │ ├─ tableId: 17\n" + " │ │ │ └─ Project\n" + - " │ │ │ ├─ columns: [cla.FTQLQ:7!null as T4IBQ, sn.BRQP2:8!null, mf.id:2!null as Z7CP5, mf.FSDY2:5!null, nma.DZLIM:10!null as IDWIO]\n" + + " │ │ │ ├─ columns: [cla.FTQLQ:7!null as T4IBQ, sn.BRQP2:8!null, mf.id:0!null as Z7CP5, mf.FSDY2:3!null, nma.DZLIM:12!null as IDWIO]\n" + " │ │ │ └─ HashJoin\n" + " │ │ │ ├─ AND\n" + " │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ ├─ mf.LUEVY:4!null\n" + - " │ │ │ │ │ └─ nd.id:11!null\n" + + " │ │ │ │ │ ├─ mf.LUEVY:2!null\n" + + " │ │ │ │ │ └─ nd.id:9!null\n" + " │ │ │ │ └─ Eq\n" + - " │ │ │ │ ├─ mf.LUEVY:4!null\n" + + " │ │ │ │ ├─ mf.LUEVY:2!null\n" + " │ │ │ │ └─ sn.BRQP2:8!null\n" + " │ │ │ ├─ HashJoin\n" + " │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ ├─ bs.IXUXU:1\n" + - " │ │ │ │ │ └─ cla.id:6!null\n" + - " │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ ├─ bs.id:0!null\n" + - " │ │ │ │ │ │ └─ mf.GXLUB:3!null\n" + - " │ │ │ │ │ ├─ TableAlias(bs)\n" + - " │ │ │ │ │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ │ │ │ │ ├─ index: [THNTS.id]\n" + - " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ │ ├─ colSet: (101-104)\n" + - " │ │ │ │ │ │ ├─ tableId: 12\n" + - " │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ ├─ name: THNTS\n" + - " │ │ │ │ │ │ └─ columns: [id ixuxu]\n" + - " │ │ │ │ │ └─ TableAlias(mf)\n" + - " │ │ │ │ │ └─ IndexedTableAccess(HGMQ6)\n" + - " │ │ │ │ │ ├─ index: [HGMQ6.GXLUB]\n" + - " │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ │ ├─ colSet: (84-100)\n" + - " │ │ │ │ │ ├─ tableId: 11\n" + - " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: HGMQ6\n" + - " │ │ │ │ │ └─ columns: [id gxlub luevy fsdy2]\n" + + " │ │ │ │ │ ├─ mf.GXLUB:1!null\n" + + " │ │ │ │ │ └─ bs.id:4!null\n" + + " │ │ │ │ ├─ TableAlias(mf)\n" + + " │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ ├─ name: HGMQ6\n" + + " │ │ │ │ │ ├─ columns: [id gxlub luevy fsdy2]\n" + + " │ │ │ │ │ ├─ colSet: (84-100)\n" + + " │ │ │ │ │ └─ tableId: 11\n" + " │ │ │ │ └─ HashLookup\n" + - " │ │ │ │ ├─ left-key: TUPLE(bs.IXUXU:1)\n" + - " │ │ │ │ ├─ right-key: TUPLE(cla.id:0!null)\n" + - " │ │ │ │ └─ Filter\n" + - " │ │ │ │ ├─ HashIn\n" + - " │ │ │ │ │ ├─ cla.FTQLQ:1!null\n" + - " │ │ │ │ │ └─ TUPLE(SQ1 (longtext))\n" + - " │ │ │ │ └─ TableAlias(cla)\n" + - " │ │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ │ ├─ index: [YK2GW.FTQLQ]\n" + - " │ │ │ │ ├─ static: [{[SQ1, SQ1]}]\n" + - " │ │ │ │ ├─ colSet: (105-134)\n" + - " │ │ │ │ ├─ tableId: 13\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: YK2GW\n" + - " │ │ │ │ └─ columns: [id ftqlq]\n" + + " │ │ │ │ ├─ left-key: TUPLE(mf.GXLUB:1!null)\n" + + " │ │ │ │ ├─ right-key: TUPLE(bs.id:0!null)\n" + + " │ │ │ │ └─ LookupJoin\n" + + " │ │ │ │ ├─ TableAlias(bs)\n" + + " │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ ├─ name: THNTS\n" + + " │ │ │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ │ │ ├─ colSet: (101-104)\n" + + " │ │ │ │ │ └─ tableId: 12\n" + + " │ │ │ │ └─ Filter\n" + + " │ │ │ │ ├─ HashIn\n" + + " │ │ │ │ │ ├─ cla.FTQLQ:1!null\n" + + " │ │ │ │ │ └─ TUPLE(SQ1 (longtext))\n" + + " │ │ │ │ └─ TableAlias(cla)\n" + + " │ │ │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ │ │ ├─ index: [YK2GW.id]\n" + + " │ │ │ │ ├─ keys: [bs.IXUXU:5]\n" + + " │ │ │ │ ├─ colSet: (105-134)\n" + + " │ │ │ │ ├─ tableId: 13\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: YK2GW\n" + + " │ │ │ │ └─ columns: [id ftqlq]\n" + " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(mf.LUEVY:4!null, mf.LUEVY:4!null)\n" + - " │ │ │ ├─ right-key: TUPLE(nd.id:3!null, sn.BRQP2:0!null)\n" + + " │ │ │ ├─ left-key: TUPLE(mf.LUEVY:2!null, mf.LUEVY:2!null)\n" + + " │ │ │ ├─ right-key: TUPLE(nd.id:1!null, sn.BRQP2:0!null)\n" + " │ │ │ └─ HashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ sn.BRQP2:8!null\n" + - " │ │ │ │ └─ nd.id:11!null\n" + - " │ │ │ ├─ TableAlias(sn)\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: NOXN3\n" + - " │ │ │ │ ├─ columns: [brqp2]\n" + - " │ │ │ │ ├─ colSet: (155-164)\n" + - " │ │ │ │ └─ tableId: 16\n" + + " │ │ │ │ ├─ nd.HPCMS:10!null\n" + + " │ │ │ │ └─ nma.id:11!null\n" + + " │ │ │ ├─ LookupJoin\n" + + " │ │ │ │ ├─ TableAlias(sn)\n" + + " │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ ├─ name: NOXN3\n" + + " │ │ │ │ │ ├─ columns: [brqp2]\n" + + " │ │ │ │ │ ├─ colSet: (155-164)\n" + + " │ │ │ │ │ └─ tableId: 16\n" + + " │ │ │ │ └─ TableAlias(nd)\n" + + " │ │ │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ │ │ ├─ index: [E2I7U.id]\n" + + " │ │ │ │ ├─ keys: [sn.BRQP2:8!null]\n" + + " │ │ │ │ ├─ colSet: (135-151)\n" + + " │ │ │ │ ├─ tableId: 14\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: E2I7U\n" + + " │ │ │ │ └─ columns: [id hpcms]\n" + " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(sn.BRQP2:8!null)\n" + - " │ │ │ ├─ right-key: TUPLE(nd.id:2!null)\n" + - " │ │ │ └─ MergeJoin\n" + - " │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ ├─ nma.id:9!null\n" + - " │ │ │ │ └─ nd.HPCMS:12!null\n" + - " │ │ │ ├─ TableAlias(nma)\n" + - " │ │ │ │ └─ IndexedTableAccess(TNMXI)\n" + - " │ │ │ │ ├─ index: [TNMXI.id]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ │ ├─ colSet: (152-154)\n" + - " │ │ │ │ ├─ tableId: 15\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: TNMXI\n" + - " │ │ │ │ └─ columns: [id dzlim]\n" + - " │ │ │ └─ TableAlias(nd)\n" + - " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ ├─ index: [E2I7U.HPCMS]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (135-151)\n" + - " │ │ │ ├─ tableId: 14\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: E2I7U\n" + - " │ │ │ └─ columns: [id hpcms]\n" + + " │ │ │ ├─ left-key: TUPLE(nd.HPCMS:10!null)\n" + + " │ │ │ ├─ right-key: TUPLE(nma.id:0!null)\n" + + " │ │ │ └─ TableAlias(nma)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: TNMXI\n" + + " │ │ │ ├─ columns: [id dzlim]\n" + + " │ │ │ ├─ colSet: (152-154)\n" + + " │ │ │ └─ tableId: 15\n" + " │ │ └─ HashLookup\n" + " │ │ ├─ left-key: TUPLE(iq.Z7CP5:2!null)\n" + " │ │ ├─ right-key: TUPLE(w2mao.Z7CP5:0!null)\n" + @@ -4907,7 +4781,7 @@ WHERE " │ ├─ colSet: (176-181)\n" + " │ └─ tableId: 19\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(nd.HPCMS:4!null)\n" + + " ├─ left-key: TUPLE(nd.HPCMS:17!null)\n" + " ├─ right-key: TUPLE(nma.id:0!null)\n" + " └─ TableAlias(nma)\n" + " └─ Table\n" + @@ -5539,74 +5413,75 @@ WHERE " │ │ ├─ colSet: (81-87)\n" + " │ │ ├─ tableId: 8\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [cla.FTQLQ:15!null as T4IBQ, sn.id:8!null as BDNYB, aac.BTXC5:11 as BTXC5, mf.id:0!null as Z7CP5, CASE WHEN NOT\n" + - " │ │ │ └─ mf.LT7K6:5 IS NULL\n" + - " │ │ │ THEN mf.LT7K6:5 ELSE mf.SPPYD:6 END as vaf, CASE WHEN NOT\n" + - " │ │ │ └─ mf.QCGTS:7 IS NULL\n" + - " │ │ │ THEN mf.QCGTS:7 ELSE 0.5 (decimal(2,1)) END as QCGTS, CASE WHEN Eq\n" + - " │ │ │ ├─ vc.ZNP4P:17!null\n" + + " │ │ ├─ columns: [cla.FTQLQ:17!null as T4IBQ, sn.id:18!null as BDNYB, aac.BTXC5:11 as BTXC5, mf.id:2!null as Z7CP5, CASE WHEN NOT\n" + + " │ │ │ └─ mf.LT7K6:7 IS NULL\n" + + " │ │ │ THEN mf.LT7K6:7 ELSE mf.SPPYD:8 END as vaf, CASE WHEN NOT\n" + + " │ │ │ └─ mf.QCGTS:9 IS NULL\n" + + " │ │ │ THEN mf.QCGTS:9 ELSE 0.5 (decimal(2,1)) END as QCGTS, CASE WHEN Eq\n" + + " │ │ │ ├─ vc.ZNP4P:13!null\n" + " │ │ │ └─ L5Q44 (longtext)\n" + " │ │ │ THEN 1 (tinyint) ELSE 0 (tinyint) END as SNY4H]\n" + " │ │ └─ HashJoin\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ w2mao.Z7CP5:18!null\n" + - " │ │ │ └─ mf.id:0!null\n" + + " │ │ │ ├─ sn.BRQP2:19!null\n" + + " │ │ │ └─ mf.LUEVY:4!null\n" + " │ │ ├─ HashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ mf.GXLUB:1!null\n" + - " │ │ │ │ └─ bs.id:12!null\n" + + " │ │ │ │ ├─ mf.GXLUB:3!null\n" + + " │ │ │ │ └─ bs.id:14!null\n" + " │ │ │ ├─ HashJoin\n" + " │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ ├─ aac.id:10!null\n" + - " │ │ │ │ │ └─ mf.M22QN:3!null\n" + - " │ │ │ │ ├─ HashJoin\n" + - " │ │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ │ ├─ sn.BRQP2:9!null\n" + - " │ │ │ │ │ │ └─ mf.LUEVY:2!null\n" + - " │ │ │ │ │ ├─ Filter\n" + - " │ │ │ │ │ │ ├─ HashIn\n" + - " │ │ │ │ │ │ │ ├─ mf.FSDY2:4!null\n" + - " │ │ │ │ │ │ │ └─ TUPLE(SRARY (longtext), UBQWG (longtext))\n" + - " │ │ │ │ │ │ └─ TableAlias(mf)\n" + - " │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ ├─ name: HGMQ6\n" + - " │ │ │ │ │ │ ├─ columns: [id gxlub luevy m22qn fsdy2 lt7k6 sppyd qcgts]\n" + - " │ │ │ │ │ │ ├─ colSet: (35-51)\n" + - " │ │ │ │ │ │ └─ tableId: 3\n" + - " │ │ │ │ │ └─ HashLookup\n" + - " │ │ │ │ │ ├─ left-key: TUPLE(mf.LUEVY:2!null)\n" + - " │ │ │ │ │ ├─ right-key: TUPLE(sn.BRQP2:1!null)\n" + - " │ │ │ │ │ └─ TableAlias(sn)\n" + + " │ │ │ │ │ ├─ vc.id:12!null\n" + + " │ │ │ │ │ └─ w2mao.YH4XB:1!null\n" + + " │ │ │ │ ├─ LookupJoin\n" + + " │ │ │ │ │ ├─ LookupJoin\n" + + " │ │ │ │ │ │ ├─ TableAlias(w2mao)\n" + + " │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ ├─ name: SEQS3\n" + + " │ │ │ │ │ │ │ ├─ columns: [z7cp5 yh4xb]\n" + + " │ │ │ │ │ │ │ ├─ colSet: (65-67)\n" + + " │ │ │ │ │ │ │ └─ tableId: 6\n" + + " │ │ │ │ │ │ └─ Filter\n" + + " │ │ │ │ │ │ ├─ HashIn\n" + + " │ │ │ │ │ │ │ ├─ mf.FSDY2:4!null\n" + + " │ │ │ │ │ │ │ └─ TUPLE(SRARY (longtext), UBQWG (longtext))\n" + + " │ │ │ │ │ │ └─ TableAlias(mf)\n" + + " │ │ │ │ │ │ └─ IndexedTableAccess(HGMQ6)\n" + + " │ │ │ │ │ │ ├─ index: [HGMQ6.id]\n" + + " │ │ │ │ │ │ ├─ keys: [w2mao.Z7CP5:0!null]\n" + + " │ │ │ │ │ │ ├─ colSet: (35-51)\n" + + " │ │ │ │ │ │ ├─ tableId: 3\n" + + " │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ ├─ name: HGMQ6\n" + + " │ │ │ │ │ │ └─ columns: [id gxlub luevy m22qn fsdy2 lt7k6 sppyd qcgts]\n" + + " │ │ │ │ │ └─ TableAlias(aac)\n" + + " │ │ │ │ │ └─ IndexedTableAccess(TPXBU)\n" + + " │ │ │ │ │ ├─ index: [TPXBU.id]\n" + + " │ │ │ │ │ ├─ keys: [mf.M22QN:5!null]\n" + + " │ │ │ │ │ ├─ colSet: (62-64)\n" + + " │ │ │ │ │ ├─ tableId: 5\n" + " │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ ├─ name: NOXN3\n" + - " │ │ │ │ │ ├─ columns: [id brqp2]\n" + - " │ │ │ │ │ ├─ colSet: (52-61)\n" + - " │ │ │ │ │ └─ tableId: 4\n" + + " │ │ │ │ │ ├─ name: TPXBU\n" + + " │ │ │ │ │ └─ columns: [id btxc5]\n" + " │ │ │ │ └─ HashLookup\n" + - " │ │ │ │ ├─ left-key: TUPLE(mf.M22QN:3!null)\n" + - " │ │ │ │ ├─ right-key: TUPLE(aac.id:0!null)\n" + - " │ │ │ │ └─ TableAlias(aac)\n" + + " │ │ │ │ ├─ left-key: TUPLE(w2mao.YH4XB:1!null)\n" + + " │ │ │ │ ├─ right-key: TUPLE(vc.id:0!null)\n" + + " │ │ │ │ └─ TableAlias(vc)\n" + " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: TPXBU\n" + - " │ │ │ │ ├─ columns: [id btxc5]\n" + - " │ │ │ │ ├─ colSet: (62-64)\n" + - " │ │ │ │ └─ tableId: 5\n" + + " │ │ │ │ ├─ name: D34QP\n" + + " │ │ │ │ ├─ columns: [id znp4p]\n" + + " │ │ │ │ ├─ colSet: (68-73)\n" + + " │ │ │ │ └─ tableId: 7\n" + " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(mf.GXLUB:1!null)\n" + + " │ │ │ ├─ left-key: TUPLE(mf.GXLUB:3!null)\n" + " │ │ │ ├─ right-key: TUPLE(bs.id:0!null)\n" + - " │ │ │ └─ MergeJoin\n" + - " │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ ├─ bs.IXUXU:13\n" + - " │ │ │ │ └─ cla.id:14!null\n" + + " │ │ │ └─ LookupJoin\n" + " │ │ │ ├─ TableAlias(bs)\n" + - " │ │ │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: THNTS\n" + + " │ │ │ │ ├─ columns: [id ixuxu]\n" + " │ │ │ │ ├─ colSet: (31-34)\n" + - " │ │ │ │ ├─ tableId: 2\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: THNTS\n" + - " │ │ │ │ └─ columns: [id ixuxu]\n" + + " │ │ │ │ └─ tableId: 2\n" + " │ │ │ └─ Filter\n" + " │ │ │ ├─ HashIn\n" + " │ │ │ │ ├─ cla.FTQLQ:1!null\n" + @@ -5614,37 +5489,21 @@ WHERE " │ │ │ └─ TableAlias(cla)\n" + " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ ├─ keys: [bs.IXUXU:15]\n" + " │ │ │ ├─ colSet: (1-30)\n" + " │ │ │ ├─ tableId: 1\n" + " │ │ │ └─ Table\n" + " │ │ │ ├─ name: YK2GW\n" + " │ │ │ └─ columns: [id ftqlq]\n" + " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(mf.id:0!null)\n" + - " │ │ ├─ right-key: TUPLE(w2mao.Z7CP5:2!null)\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ vc.id:16!null\n" + - " │ │ │ └─ w2mao.YH4XB:19!null\n" + - " │ │ ├─ TableAlias(vc)\n" + - " │ │ │ └─ IndexedTableAccess(D34QP)\n" + - " │ │ │ ├─ index: [D34QP.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (68-73)\n" + - " │ │ │ ├─ tableId: 7\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: D34QP\n" + - " │ │ │ └─ columns: [id znp4p]\n" + - " │ │ └─ TableAlias(w2mao)\n" + - " │ │ └─ IndexedTableAccess(SEQS3)\n" + - " │ │ ├─ index: [SEQS3.YH4XB]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (65-67)\n" + - " │ │ ├─ tableId: 6\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: SEQS3\n" + - " │ │ └─ columns: [z7cp5 yh4xb]\n" + + " │ │ ├─ left-key: TUPLE(mf.LUEVY:4!null)\n" + + " │ │ ├─ right-key: TUPLE(sn.BRQP2:1!null)\n" + + " │ │ └─ TableAlias(sn)\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: NOXN3\n" + + " │ │ ├─ columns: [id brqp2]\n" + + " │ │ ├─ colSet: (52-61)\n" + + " │ │ └─ tableId: 4\n" + " │ └─ SubqueryAlias\n" + " │ ├─ name: e52ap\n" + " │ ├─ outerVisibility: false\n" + @@ -6187,23 +6046,17 @@ WHERE " │ │ │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ │ │ ├─ nhmxw.id:10!null\n" + " │ │ │ │ │ │ │ │ └─ ism.PRUV2:9\n" + - " │ │ │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ │ │ └─ ism.NZ4MQ:8!null\n" + + " │ │ │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ │ │ ├─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q]\n" + " │ │ │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q]\n" + + " │ │ │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ │ │ └─ Table\n" + @@ -6310,23 +6163,17 @@ WHERE " │ │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ │ ├─ nhmxw.id:10!null\n" + " │ │ │ │ │ │ │ └─ ism.PRUV2:9\n" + - " │ │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ │ └─ ism.NZ4MQ:8!null\n" + + " │ │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ │ ├─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q]\n" + " │ │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q]\n" + + " │ │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ │ └─ Table\n" + @@ -6436,23 +6283,17 @@ WHERE " │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ ├─ nhmxw.id:10!null\n" + " │ │ │ │ │ │ └─ ism.PRUV2:9\n" + - " │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ └─ ism.NZ4MQ:8!null\n" + + " │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ ├─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q]\n" + " │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q]\n" + + " │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ └─ Table\n" + @@ -6529,46 +6370,37 @@ WHERE " ├─ columns: [cla.FTQLQ:6!null, mf.LUEVY:1!null, mf.M22QN:2!null]\n" + " └─ HashJoin\n" + " ├─ Eq\n" + - " │ ├─ cla.id:5!null\n" + - " │ └─ bs.IXUXU:4\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ mf.GXLUB:0!null\n" + - " │ │ └─ bs.id:3!null\n" + - " │ ├─ TableAlias(mf)\n" + - " │ │ └─ IndexedTableAccess(HGMQ6)\n" + - " │ │ ├─ index: [HGMQ6.GXLUB]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (185-201)\n" + - " │ │ ├─ tableId: 21\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: HGMQ6\n" + - " │ │ └─ columns: [gxlub luevy m22qn]\n" + - " │ └─ TableAlias(bs)\n" + - " │ └─ IndexedTableAccess(THNTS)\n" + - " │ ├─ index: [THNTS.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (181-184)\n" + - " │ ├─ tableId: 20\n" + - " │ └─ Table\n" + - " │ ├─ name: THNTS\n" + - " │ └─ columns: [id ixuxu]\n" + + " │ ├─ bs.id:3!null\n" + + " │ └─ mf.GXLUB:0!null\n" + + " ├─ TableAlias(mf)\n" + + " │ └─ Table\n" + + " │ ├─ name: HGMQ6\n" + + " │ ├─ columns: [gxlub luevy m22qn]\n" + + " │ ├─ colSet: (185-201)\n" + + " │ └─ tableId: 21\n" + " └─ HashLookup\n" + - " ├─ left-key: TUPLE(bs.IXUXU:4)\n" + - " ├─ right-key: TUPLE(cla.id:0!null)\n" + - " └─ Filter\n" + - " ├─ HashIn\n" + - " │ ├─ cla.FTQLQ:1!null\n" + - " │ └─ TUPLE(SQ1 (longtext))\n" + - " └─ TableAlias(cla)\n" + - " └─ IndexedTableAccess(YK2GW)\n" + - " ├─ index: [YK2GW.FTQLQ]\n" + - " ├─ static: [{[SQ1, SQ1]}]\n" + - " ├─ colSet: (151-180)\n" + - " ├─ tableId: 19\n" + - " └─ Table\n" + - " ├─ name: YK2GW\n" + - " └─ columns: [id ftqlq]\n" + + " ├─ left-key: TUPLE(mf.GXLUB:0!null)\n" + + " ├─ right-key: TUPLE(bs.id:0!null)\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(bs)\n" + + " │ └─ Table\n" + + " │ ├─ name: THNTS\n" + + " │ ├─ columns: [id ixuxu]\n" + + " │ ├─ colSet: (181-184)\n" + + " │ └─ tableId: 20\n" + + " └─ Filter\n" + + " ├─ HashIn\n" + + " │ ├─ cla.FTQLQ:1!null\n" + + " │ └─ TUPLE(SQ1 (longtext))\n" + + " └─ TableAlias(cla)\n" + + " └─ IndexedTableAccess(YK2GW)\n" + + " ├─ index: [YK2GW.id]\n" + + " ├─ keys: [bs.IXUXU:4]\n" + + " ├─ colSet: (151-180)\n" + + " ├─ tableId: 19\n" + + " └─ Table\n" + + " ├─ name: YK2GW\n" + + " └─ columns: [id ftqlq]\n" + "", }, { @@ -7078,26 +6910,20 @@ WHERE " │ │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ │ ├─ nhmxw.id:17!null\n" + " │ │ │ │ │ │ │ └─ ism.PRUV2:14\n" + - " │ │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ │ └─ ism.NZ4MQ:12!null\n" + + " │ │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ │ ├─ Filter\n" + " │ │ │ │ │ │ │ │ ├─ NOT\n" + " │ │ │ │ │ │ │ │ │ └─ g3yxs.TUV25:5 IS NULL\n" + " │ │ │ │ │ │ │ │ └─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + " │ │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + + " │ │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ │ └─ Table\n" + @@ -7490,26 +7316,20 @@ WHERE " │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ ├─ nhmxw.id:17!null\n" + " │ │ │ │ │ │ └─ ism.PRUV2:14\n" + - " │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ └─ ism.NZ4MQ:12!null\n" + + " │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ ├─ Filter\n" + " │ │ │ │ │ │ │ ├─ NOT\n" + " │ │ │ │ │ │ │ │ └─ g3yxs.TUV25:5 IS NULL\n" + " │ │ │ │ │ │ │ └─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + " │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + + " │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ └─ Table\n" + @@ -7756,15 +7576,15 @@ WHERE " │ │ ├─ colSet: (157-159)\n" + " │ │ ├─ tableId: 16\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [cla.FTQLQ:6!null as T4IBQ, sn.id:3!null as BDNYB, mf.M22QN:2!null as M22QN]\n" + + " │ │ ├─ columns: [cla.FTQLQ:6!null as T4IBQ, sn.id:7!null as BDNYB, mf.M22QN:2!null as M22QN]\n" + " │ │ └─ HashJoin\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ bs.id:7!null\n" + - " │ │ │ └─ mf.GXLUB:0!null\n" + + " │ │ │ ├─ sn.BRQP2:8!null\n" + + " │ │ │ └─ mf.LUEVY:1!null\n" + " │ │ ├─ HashJoin\n" + " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ sn.BRQP2:4!null\n" + - " │ │ │ │ └─ mf.LUEVY:1!null\n" + + " │ │ │ │ ├─ bs.id:3!null\n" + + " │ │ │ │ └─ mf.GXLUB:0!null\n" + " │ │ │ ├─ TableAlias(mf)\n" + " │ │ │ │ └─ Table\n" + " │ │ │ │ ├─ name: HGMQ6\n" + @@ -7772,43 +7592,37 @@ WHERE " │ │ │ │ ├─ colSet: (93-109)\n" + " │ │ │ │ └─ tableId: 12\n" + " │ │ │ └─ HashLookup\n" + - " │ │ │ ├─ left-key: TUPLE(mf.LUEVY:1!null)\n" + - " │ │ │ ├─ right-key: TUPLE(sn.BRQP2:1!null)\n" + - " │ │ │ └─ TableAlias(sn)\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: NOXN3\n" + - " │ │ │ ├─ columns: [id brqp2]\n" + - " │ │ │ ├─ colSet: (144-153)\n" + - " │ │ │ └─ tableId: 15\n" + + " │ │ │ ├─ left-key: TUPLE(mf.GXLUB:0!null)\n" + + " │ │ │ ├─ right-key: TUPLE(bs.id:0!null)\n" + + " │ │ │ └─ LookupJoin\n" + + " │ │ │ ├─ TableAlias(bs)\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: THNTS\n" + + " │ │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ │ ├─ colSet: (110-113)\n" + + " │ │ │ │ └─ tableId: 13\n" + + " │ │ │ └─ Filter\n" + + " │ │ │ ├─ HashIn\n" + + " │ │ │ │ ├─ cla.FTQLQ:1!null\n" + + " │ │ │ │ └─ TUPLE(SQ1 (longtext))\n" + + " │ │ │ └─ TableAlias(cla)\n" + + " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ │ ├─ index: [YK2GW.id]\n" + + " │ │ │ ├─ keys: [bs.IXUXU:4]\n" + + " │ │ │ ├─ colSet: (114-143)\n" + + " │ │ │ ├─ tableId: 14\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: YK2GW\n" + + " │ │ │ └─ columns: [id ftqlq]\n" + " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(mf.GXLUB:0!null)\n" + - " │ │ ├─ right-key: TUPLE(bs.id:2!null)\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:5!null\n" + - " │ │ │ └─ bs.IXUXU:8\n" + - " │ │ ├─ Filter\n" + - " │ │ │ ├─ HashIn\n" + - " │ │ │ │ ├─ cla.FTQLQ:1!null\n" + - " │ │ │ │ └─ TUPLE(SQ1 (longtext))\n" + - " │ │ │ └─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (114-143)\n" + - " │ │ │ ├─ tableId: 14\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (110-113)\n" + - " │ │ ├─ tableId: 13\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ left-key: TUPLE(mf.LUEVY:1!null)\n" + + " │ │ ├─ right-key: TUPLE(sn.BRQP2:1!null)\n" + + " │ │ └─ TableAlias(sn)\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: NOXN3\n" + + " │ │ ├─ columns: [id brqp2]\n" + + " │ │ ├─ colSet: (144-153)\n" + + " │ │ └─ tableId: 15\n" + " │ └─ HashLookup\n" + " │ ├─ left-key: TUPLE()\n" + " │ ├─ right-key: TUPLE()\n" + @@ -8076,26 +7890,20 @@ WHERE " │ │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ │ ├─ nhmxw.id:17!null\n" + " │ │ │ │ │ │ │ └─ ism.PRUV2:14\n" + - " │ │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ │ └─ ism.NZ4MQ:12!null\n" + + " │ │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ │ ├─ Filter\n" + " │ │ │ │ │ │ │ │ ├─ NOT\n" + " │ │ │ │ │ │ │ │ │ └─ g3yxs.TUV25:5 IS NULL\n" + " │ │ │ │ │ │ │ │ └─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + " │ │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + + " │ │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ │ └─ Table\n" + @@ -8181,15 +7989,15 @@ WHERE " │ ├─ colSet: (157-159)\n" + " │ ├─ tableId: 16\n" + " │ └─ Project\n" + - " │ ├─ columns: [cla.FTQLQ:6!null as T4IBQ, sn.id:3!null as BDNYB, mf.M22QN:2!null as M22QN]\n" + + " │ ├─ columns: [cla.FTQLQ:6!null as T4IBQ, sn.id:7!null as BDNYB, mf.M22QN:2!null as M22QN]\n" + " │ └─ HashJoin\n" + " │ ├─ Eq\n" + - " │ │ ├─ bs.id:7!null\n" + - " │ │ └─ mf.GXLUB:0!null\n" + + " │ │ ├─ sn.BRQP2:8!null\n" + + " │ │ └─ mf.LUEVY:1!null\n" + " │ ├─ HashJoin\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ sn.BRQP2:4!null\n" + - " │ │ │ └─ mf.LUEVY:1!null\n" + + " │ │ │ ├─ bs.id:3!null\n" + + " │ │ │ └─ mf.GXLUB:0!null\n" + " │ │ ├─ TableAlias(mf)\n" + " │ │ │ └─ Table\n" + " │ │ │ ├─ name: HGMQ6\n" + @@ -8197,43 +8005,37 @@ WHERE " │ │ │ ├─ colSet: (93-109)\n" + " │ │ │ └─ tableId: 12\n" + " │ │ └─ HashLookup\n" + - " │ │ ├─ left-key: TUPLE(mf.LUEVY:1!null)\n" + - " │ │ ├─ right-key: TUPLE(sn.BRQP2:1!null)\n" + - " │ │ └─ TableAlias(sn)\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: NOXN3\n" + - " │ │ ├─ columns: [id brqp2]\n" + - " │ │ ├─ colSet: (144-153)\n" + - " │ │ └─ tableId: 15\n" + + " │ │ ├─ left-key: TUPLE(mf.GXLUB:0!null)\n" + + " │ │ ├─ right-key: TUPLE(bs.id:0!null)\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (110-113)\n" + + " │ │ │ └─ tableId: 13\n" + + " │ │ └─ Filter\n" + + " │ │ ├─ HashIn\n" + + " │ │ │ ├─ cla.FTQLQ:1!null\n" + + " │ │ │ └─ TUPLE(SQ1 (longtext))\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:4]\n" + + " │ │ ├─ colSet: (114-143)\n" + + " │ │ ├─ tableId: 14\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(mf.GXLUB:0!null)\n" + - " │ ├─ right-key: TUPLE(bs.id:2!null)\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ cla.id:5!null\n" + - " │ │ └─ bs.IXUXU:8\n" + - " │ ├─ Filter\n" + - " │ │ ├─ HashIn\n" + - " │ │ │ ├─ cla.FTQLQ:1!null\n" + - " │ │ │ └─ TUPLE(SQ1 (longtext))\n" + - " │ │ └─ TableAlias(cla)\n" + - " │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ ├─ index: [YK2GW.id]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (114-143)\n" + - " │ │ ├─ tableId: 14\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: YK2GW\n" + - " │ │ └─ columns: [id ftqlq]\n" + - " │ └─ TableAlias(bs)\n" + - " │ └─ IndexedTableAccess(THNTS)\n" + - " │ ├─ index: [THNTS.IXUXU]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (110-113)\n" + - " │ ├─ tableId: 13\n" + - " │ └─ Table\n" + - " │ ├─ name: THNTS\n" + - " │ └─ columns: [id ixuxu]\n" + + " │ ├─ left-key: TUPLE(mf.LUEVY:1!null)\n" + + " │ ├─ right-key: TUPLE(sn.BRQP2:1!null)\n" + + " │ └─ TableAlias(sn)\n" + + " │ └─ Table\n" + + " │ ├─ name: NOXN3\n" + + " │ ├─ columns: [id brqp2]\n" + + " │ ├─ colSet: (144-153)\n" + + " │ └─ tableId: 15\n" + " └─ SubqueryAlias\n" + " ├─ name: p4pjz\n" + " ├─ outerVisibility: false\n" + @@ -8488,26 +8290,20 @@ WHERE " │ │ │ │ │ ├─ Eq\n" + " │ │ │ │ │ │ ├─ nhmxw.id:17!null\n" + " │ │ │ │ │ │ └─ ism.PRUV2:14\n" + - " │ │ │ │ │ ├─ MergeJoin\n" + - " │ │ │ │ │ │ ├─ cmp: Eq\n" + - " │ │ │ │ │ │ │ ├─ g3yxs.id:0!null\n" + - " │ │ │ │ │ │ │ └─ ism.NZ4MQ:12!null\n" + + " │ │ │ │ │ ├─ LookupJoin\n" + " │ │ │ │ │ │ ├─ Filter\n" + " │ │ │ │ │ │ │ ├─ NOT\n" + " │ │ │ │ │ │ │ │ └─ g3yxs.TUV25:5 IS NULL\n" + " │ │ │ │ │ │ │ └─ TableAlias(g3yxs)\n" + - " │ │ │ │ │ │ │ └─ IndexedTableAccess(YYBCX)\n" + - " │ │ │ │ │ │ │ ├─ index: [YYBCX.id]\n" + - " │ │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ │ └─ Table\n" + + " │ │ │ │ │ │ │ ├─ name: YYBCX\n" + + " │ │ │ │ │ │ │ ├─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + " │ │ │ │ │ │ │ ├─ colSet: (24-31)\n" + - " │ │ │ │ │ │ │ ├─ tableId: 5\n" + - " │ │ │ │ │ │ │ └─ Table\n" + - " │ │ │ │ │ │ │ ├─ name: YYBCX\n" + - " │ │ │ │ │ │ │ └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" + + " │ │ │ │ │ │ │ └─ tableId: 5\n" + " │ │ │ │ │ │ └─ TableAlias(ism)\n" + " │ │ │ │ │ │ └─ IndexedTableAccess(HDDVB)\n" + " │ │ │ │ │ │ ├─ index: [HDDVB.NZ4MQ]\n" + - " │ │ │ │ │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ │ │ │ │ ├─ keys: [g3yxs.id:0!null]\n" + " │ │ │ │ │ │ ├─ colSet: (15-23)\n" + " │ │ │ │ │ │ ├─ tableId: 4\n" + " │ │ │ │ │ │ └─ Table\n" + @@ -8962,39 +8758,30 @@ ORDER BY cla.FTQLQ ASC`, " └─ Project\n" + " ├─ columns: [cla.FTQLQ:22!null]\n" + " └─ Sort(cla.FTQLQ:22!null ASC nullsFirst)\n" + - " └─ Project\n" + - " ├─ columns: [mf.id:4!null, mf.GXLUB:5!null, mf.LUEVY:6!null, mf.M22QN:7!null, mf.TJPT7:8!null, mf.ARN5P:9!null, mf.XOSD4:10!null, mf.IDE43:11, mf.HMW4H:12, mf.ZBT6R:13, mf.FSDY2:14!null, mf.LT7K6:15, mf.SPPYD:16, mf.QCGTS:17, mf.TEUJA:18, mf.QQV4M:19, mf.FHCYT:20, bs.id:0!null, bs.NFRYN:1!null, bs.IXUXU:2, bs.FHCYT:3, cla.id:21!null, cla.FTQLQ:22!null, cla.TUXML:23, cla.PAEF5:24, cla.RUCY4:25, cla.TPNJ6:26!null, cla.LBL53:27, cla.NB3QS:28, cla.EO7IV:29, cla.MUHJF:30, cla.FM34L:31, cla.TY5RF:32, cla.ZHTLH:33, cla.NPB7W:34, cla.SX3HH:35, cla.ISBNF:36, cla.YA7YB:37, cla.C5YKB:38, cla.QK7KT:39, cla.FFGE6:40, cla.FIIGJ:41, cla.SH3NC:42, cla.NTENA:43, cla.M4AUB:44, cla.X5AIR:45, cla.SAB6M:46, cla.G5QI5:47, cla.ZVQVD:48, cla.YKSSU:49, cla.FHCYT:50]\n" + - " └─ HashJoin\n" + - " ├─ Eq\n" + - " │ ├─ bs.IXUXU:2\n" + - " │ └─ cla.id:21!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ bs.id:0!null\n" + - " │ │ └─ mf.GXLUB:5!null\n" + - " │ ├─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.id]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (18-21)\n" + - " │ │ ├─ tableId: 2\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id nfryn ixuxu fhcyt]\n" + - " │ └─ TableAlias(mf)\n" + - " │ └─ IndexedTableAccess(HGMQ6)\n" + - " │ ├─ index: [HGMQ6.GXLUB]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-17)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: HGMQ6\n" + - " │ └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(bs.IXUXU:2)\n" + - " ├─ right-key: TUPLE(cla.id:0!null)\n" + + " └─ HashJoin\n" + + " ├─ Eq\n" + + " │ ├─ mf.GXLUB:1!null\n" + + " │ └─ bs.id:17!null\n" + + " ├─ TableAlias(mf)\n" + + " │ └─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: HGMQ6\n" + + " │ └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE(mf.GXLUB:1!null)\n" + + " ├─ right-key: TUPLE(bs.id:0!null)\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(bs)\n" + + " │ └─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: THNTS\n" + + " │ └─ columns: [id nfryn ixuxu fhcyt]\n" + " └─ TableAlias(cla)\n" + - " └─ ProcessTable\n" + + " └─ IndexedTableAccess(YK2GW)\n" + + " ├─ index: [YK2GW.id]\n" + + " ├─ keys: [bs.IXUXU:19]\n" + + " ├─ colSet: (22-51)\n" + + " ├─ tableId: 3\n" + " └─ Table\n" + " ├─ name: YK2GW\n" + " └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" + @@ -10558,33 +10345,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:14!null]\n" + + " │ │ ├─ columns: [bs.id:12!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:13!null\n" + + " │ │ │ ├─ cla.FTQLQ:15!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:12!null\n" + - " │ │ │ └─ bs.IXUXU:15\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:13]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'NER'\n" + @@ -10614,33 +10395,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:9!null]\n" + + " │ │ ├─ columns: [bs.id:7!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:8!null\n" + + " │ │ │ ├─ cla.FTQLQ:10!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:7!null\n" + - " │ │ │ └─ bs.IXUXU:10\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:8]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'NER'\n" + @@ -10764,33 +10539,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:14!null]\n" + + " │ │ ├─ columns: [bs.id:12!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:13!null\n" + + " │ │ │ ├─ cla.FTQLQ:15!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:12!null\n" + - " │ │ │ └─ bs.IXUXU:15\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:13]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'BER'\n" + @@ -10820,33 +10589,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:9!null]\n" + + " │ │ ├─ columns: [bs.id:7!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:8!null\n" + + " │ │ │ ├─ cla.FTQLQ:10!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:7!null\n" + - " │ │ │ └─ bs.IXUXU:10\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:8]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'BER'\n" + @@ -10970,33 +10733,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:14!null]\n" + + " │ │ ├─ columns: [bs.id:12!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:13!null\n" + + " │ │ │ ├─ cla.FTQLQ:15!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:12!null\n" + - " │ │ │ └─ bs.IXUXU:15\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:13]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'HR'\n" + @@ -11026,33 +10783,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:9!null]\n" + + " │ │ ├─ columns: [bs.id:7!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:8!null\n" + + " │ │ │ ├─ cla.FTQLQ:10!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:7!null\n" + - " │ │ │ └─ bs.IXUXU:10\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:8]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'HR'\n" + @@ -11176,33 +10927,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:14!null]\n" + + " │ │ ├─ columns: [bs.id:12!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:13!null\n" + + " │ │ │ ├─ cla.FTQLQ:15!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:12!null\n" + - " │ │ │ └─ bs.IXUXU:15\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:13]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'MMR'\n" + @@ -11232,33 +10977,27 @@ WHERE " │ │ ├─ cacheable: false\n" + " │ │ ├─ alias-string: select bs.id from THNTS as bs join YK2GW as cla on cla.id = bs.IXUXU where cla.FTQLQ = ums.T4IBQ\n" + " │ │ └─ Project\n" + - " │ │ ├─ columns: [bs.id:9!null]\n" + + " │ │ ├─ columns: [bs.id:7!null]\n" + " │ │ └─ Filter\n" + " │ │ ├─ Eq\n" + - " │ │ │ ├─ cla.FTQLQ:8!null\n" + + " │ │ │ ├─ cla.FTQLQ:10!null\n" + " │ │ │ └─ ums.T4IBQ:1\n" + - " │ │ └─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ cla.id:7!null\n" + - " │ │ │ └─ bs.IXUXU:10\n" + - " │ │ ├─ TableAlias(cla)\n" + - " │ │ │ └─ IndexedTableAccess(YK2GW)\n" + - " │ │ │ ├─ index: [YK2GW.id]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (18-47)\n" + - " │ │ │ ├─ tableId: 4\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: YK2GW\n" + - " │ │ │ └─ columns: [id ftqlq]\n" + - " │ │ └─ TableAlias(bs)\n" + - " │ │ └─ IndexedTableAccess(THNTS)\n" + - " │ │ ├─ index: [THNTS.IXUXU]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-17)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ LookupJoin\n" + + " │ │ ├─ TableAlias(bs)\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: THNTS\n" + + " │ │ │ ├─ columns: [id ixuxu]\n" + + " │ │ │ ├─ colSet: (14-17)\n" + + " │ │ │ └─ tableId: 3\n" + + " │ │ └─ TableAlias(cla)\n" + + " │ │ └─ IndexedTableAccess(YK2GW)\n" + + " │ │ ├─ index: [YK2GW.id]\n" + + " │ │ ├─ keys: [bs.IXUXU:8]\n" + + " │ │ ├─ colSet: (18-47)\n" + + " │ │ ├─ tableId: 4\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: THNTS\n" + - " │ │ └─ columns: [id ixuxu]\n" + + " │ │ ├─ name: YK2GW\n" + + " │ │ └─ columns: [id ftqlq]\n" + " │ │ as GXLUB, Subquery\n" + " │ │ ├─ cacheable: true\n" + " │ │ ├─ alias-string: select id from XOAOP where DZLIM = 'MMR'\n" + @@ -12725,10 +12464,7 @@ WHERE " │ │ ├─ nk7fp.VYO5E:1\n" + " │ │ └─ N/A (longtext)\n" + " │ │ THEN NULL (null) ELSE nk7fp.VYO5E:1 END as VYO5E, nt.id:21!null as DKCAJ, nt.DZLIM:22!null as F35MI]\n" + - " │ └─ HashJoin\n" + - " │ ├─ Eq\n" + - " │ │ ├─ nt.id:21!null\n" + - " │ │ └─ nd.DKCAJ:5!null\n" + + " │ └─ LookupJoin\n" + " │ ├─ LookupJoin\n" + " │ │ ├─ Or\n" + " │ │ │ ├─ AND\n" + @@ -12792,31 +12528,33 @@ WHERE " │ │ │ └─ tableId: 3\n" + " │ │ └─ TableAlias(nd)\n" + " │ │ └─ Concat\n" + - " │ │ ├─ IndexedTableAccess(E2I7U)\n" + - " │ │ │ ├─ index: [E2I7U.TW55N]\n" + - " │ │ │ ├─ keys: [nk7fp.FVUCX:3!null]\n" + - " │ │ │ ├─ colSet: (32-48)\n" + - " │ │ │ ├─ tableId: 5\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: E2I7U\n" + - " │ │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + - " │ │ └─ IndexedTableAccess(E2I7U)\n" + - " │ │ ├─ index: [E2I7U.ZH72S]\n" + - " │ │ ├─ keys: [nk7fp.ZH72S:2]\n" + - " │ │ ├─ colSet: (32-48)\n" + - " │ │ ├─ tableId: 5\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: E2I7U\n" + - " │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + - " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(nd.DKCAJ:5!null)\n" + - " │ ├─ right-key: TUPLE(nt.id:0!null)\n" + - " │ └─ TableAlias(nt)\n" + + " │ │ ├─ TableAlias(nd)\n" + + " │ │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ │ ├─ index: [E2I7U.TW55N]\n" + + " │ │ │ ├─ keys: [nk7fp.FVUCX:3!null]\n" + + " │ │ │ ├─ colSet: (32-48)\n" + + " │ │ │ ├─ tableId: 5\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: E2I7U\n" + + " │ │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + + " │ │ └─ TableAlias(nd)\n" + + " │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ ├─ index: [E2I7U.ZH72S]\n" + + " │ │ ├─ keys: [nk7fp.ZH72S:2]\n" + + " │ │ ├─ colSet: (32-48)\n" + + " │ │ ├─ tableId: 5\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: E2I7U\n" + + " │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + + " │ └─ TableAlias(nt)\n" + + " │ └─ IndexedTableAccess(F35MI)\n" + + " │ ├─ index: [F35MI.id]\n" + + " │ ├─ keys: [nd.DKCAJ:5!null]\n" + + " │ ├─ colSet: (49-51)\n" + + " │ ├─ tableId: 6\n" + " │ └─ Table\n" + " │ ├─ name: F35MI\n" + - " │ ├─ columns: [id dzlim f3yue]\n" + - " │ ├─ colSet: (49-51)\n" + - " │ └─ tableId: 6\n" + + " │ └─ columns: [id dzlim f3yue]\n" + " └─ BEGIN .. END\n" + " ├─ IF BLOCK\n" + " │ └─ IF(Or\n" + @@ -13279,22 +13017,24 @@ WHERE " │ │ └─ tableId: 3\n" + " │ └─ TableAlias(nd)\n" + " │ └─ Concat\n" + - " │ ├─ IndexedTableAccess(E2I7U)\n" + - " │ │ ├─ index: [E2I7U.ZH72S]\n" + - " │ │ ├─ keys: [pqsxb.K3B6V:9]\n" + - " │ │ ├─ colSet: (104-120)\n" + - " │ │ ├─ tableId: 9\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: E2I7U\n" + - " │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + - " │ └─ IndexedTableAccess(E2I7U)\n" + - " │ ├─ index: [E2I7U.TW55N]\n" + - " │ ├─ keys: [pqsxb.H4DMT:11!null]\n" + - " │ ├─ colSet: (104-120)\n" + - " │ ├─ tableId: 9\n" + - " │ └─ Table\n" + - " │ ├─ name: E2I7U\n" + - " │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + + " │ ├─ TableAlias(nd)\n" + + " │ │ └─ IndexedTableAccess(E2I7U)\n" + + " │ │ ├─ index: [E2I7U.ZH72S]\n" + + " │ │ ├─ keys: [pqsxb.K3B6V:9]\n" + + " │ │ ├─ colSet: (104-120)\n" + + " │ │ ├─ tableId: 9\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: E2I7U\n" + + " │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + + " │ └─ TableAlias(nd)\n" + + " │ └─ IndexedTableAccess(E2I7U)\n" + + " │ ├─ index: [E2I7U.TW55N]\n" + + " │ ├─ keys: [pqsxb.H4DMT:11!null]\n" + + " │ ├─ colSet: (104-120)\n" + + " │ ├─ tableId: 9\n" + + " │ └─ Table\n" + + " │ ├─ name: E2I7U\n" + + " │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + " └─ BEGIN .. END\n" + " ├─ IF BLOCK\n" + " │ └─ IF(InSubquery\n" + @@ -13491,10 +13231,7 @@ WHERE " │ └─ Distinct\n" + " │ └─ Project\n" + " │ ├─ columns: [tvtjs.NO52D:7!null as NO52D, tvtjs.VYO5E:9 as VYO5E, nt.id:30!null as DKCAJ, nt.DZLIM:31!null as F35MI]\n" + - " │ └─ HashJoin\n" + - " │ ├─ Eq\n" + - " │ │ ├─ nt.id:30!null\n" + - " │ │ └─ nd.DKCAJ:14!null\n" + + " │ └─ LookupJoin\n" + " │ ├─ LookupJoin\n" + " │ │ ├─ Filter\n" + " │ │ │ ├─ HashIn\n" + @@ -13518,15 +13255,15 @@ WHERE " │ │ └─ Table\n" + " │ │ ├─ name: E2I7U\n" + " │ │ └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" + - " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(nd.DKCAJ:14!null)\n" + - " │ ├─ right-key: TUPLE(nt.id:0!null)\n" + - " │ └─ TableAlias(nt)\n" + + " │ └─ TableAlias(nt)\n" + + " │ └─ IndexedTableAccess(F35MI)\n" + + " │ ├─ index: [F35MI.id]\n" + + " │ ├─ keys: [nd.DKCAJ:14!null]\n" + + " │ ├─ colSet: (37-39)\n" + + " │ ├─ tableId: 4\n" + " │ └─ Table\n" + " │ ├─ name: F35MI\n" + - " │ ├─ columns: [id dzlim f3yue]\n" + - " │ ├─ colSet: (37-39)\n" + - " │ └─ tableId: 4\n" + + " │ └─ columns: [id dzlim f3yue]\n" + " └─ BEGIN .. END\n" + " ├─ IF BLOCK\n" + " │ └─ IF(Or\n" + diff --git a/enginetest/queries/query_plans.go b/enginetest/queries/query_plans.go index 935b6daabd..0735d6e97a 100644 --- a/enginetest/queries/query_plans.go +++ b/enginetest/queries/query_plans.go @@ -447,7 +447,10 @@ WHERE " └─ GroupBy\n" + " ├─ select: COUNTDISTINCT([stock1.s_i_id])\n" + " ├─ group: \n" + - " └─ LookupJoin\n" + + " └─ HashJoin\n" + + " ├─ Eq\n" + + " │ ├─ stock1.s_i_id:4!null\n" + + " │ └─ order_line1.ol_i_id:3\n" + " ├─ IndexedTableAccess(order_line1)\n" + " │ ├─ index: [order_line1.ol_w_id,order_line1.ol_d_id,order_line1.ol_o_id,order_line1.ol_number]\n" + " │ ├─ static: [{[5, 5], [2, 2], [2981, 3001), [NULL, ∞)}]\n" + @@ -456,22 +459,21 @@ WHERE " │ └─ Table\n" + " │ ├─ name: order_line1\n" + " │ └─ columns: [ol_o_id ol_d_id ol_w_id ol_i_id]\n" + - " └─ Filter\n" + - " ├─ AND\n" + - " │ ├─ Eq\n" + - " │ │ ├─ stock1.s_w_id:1!null\n" + - " │ │ └─ 5 (tinyint)\n" + - " │ └─ LessThan\n" + - " │ ├─ stock1.s_quantity:2\n" + - " │ └─ 15 (tinyint)\n" + - " └─ IndexedTableAccess(stock1)\n" + - " ├─ index: [stock1.s_w_id,stock1.s_i_id]\n" + - " ├─ keys: [5 (tinyint) order_line1.ol_i_id:3]\n" + - " ├─ colSet: (11-27)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: stock1\n" + - " └─ columns: [s_i_id s_w_id s_quantity]\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE(order_line1.ol_i_id:3)\n" + + " ├─ right-key: TUPLE(stock1.s_i_id:0!null)\n" + + " └─ Filter\n" + + " ├─ LessThan\n" + + " │ ├─ stock1.s_quantity:2\n" + + " │ └─ 15 (tinyint)\n" + + " └─ IndexedTableAccess(stock1)\n" + + " ├─ index: [stock1.s_w_id,stock1.s_i_id]\n" + + " ├─ static: [{[5, 5], [NULL, ∞)}]\n" + + " ├─ colSet: (11-27)\n" + + " ├─ tableId: 2\n" + + " └─ Table\n" + + " ├─ name: stock1\n" + + " └─ columns: [s_i_id s_w_id s_quantity]\n" + "", }, { @@ -517,23 +519,23 @@ WHERE Query: `select * from asset am join asset am2 on (am.orgId = am2.orgId and am.name = am2.name and am.val = am2.val);`, ExpectedPlan: "Project\n" + " ├─ columns: [am.id:5!null, am.orgId:6, am.assetId:7, am.name:8, am.val:9, am2.id:0!null, am2.orgId:1, am2.assetId:2, am2.name:3, am2.val:4]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(am2.orgId:1, am2.name:3, am2.val:4)\n" + - " │ └─ TUPLE(am.orgId:6, am.name:8, am.val:9)\n" + + " └─ LookupJoin\n" + + " ├─ AND\n" + + " │ ├─ Eq\n" + + " │ │ ├─ am.name:8\n" + + " │ │ └─ am2.name:3\n" + + " │ └─ Eq\n" + + " │ ├─ am.val:9\n" + + " │ └─ am2.val:4\n" + " ├─ TableAlias(am2)\n" + - " │ └─ IndexedTableAccess(asset)\n" + - " │ ├─ index: [asset.orgId,asset.name,asset.val]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (6-10)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: asset\n" + " │ └─ columns: [id orgid assetid name val]\n" + " └─ TableAlias(am)\n" + " └─ IndexedTableAccess(asset)\n" + - " ├─ index: [asset.orgId,asset.name,asset.val]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞), [NULL, ∞)}]\n" + + " ├─ index: [asset.orgId,asset.assetId]\n" + + " ├─ keys: [am2.orgId:1]\n" + " ├─ colSet: (1-5)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -716,41 +718,39 @@ where " └─ RecursiveCTE\n" + " └─ Union all\n" + " ├─ Project\n" + - " │ ├─ columns: [parts.sub_part:1!null, parts.part:0!null, parts.quantity:2!null]\n" + - " │ └─ Project\n" + - " │ ├─ columns: [parts.part:0!null, parts.sub_part:1!null, parts.quantity:2!null]\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ parts.part:0!null\n" + - " │ │ └─ parts_1.part:3!null\n" + - " │ ├─ IndexedTableAccess(parts)\n" + - " │ │ ├─ index: [parts.part,parts.sub_part]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-3)\n" + - " │ │ ├─ tableId: 1\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: parts\n" + - " │ │ └─ columns: [part sub_part quantity]\n" + - " │ └─ Distinct\n" + - " │ └─ Project\n" + - " │ ├─ columns: [parts_1.part:0!null]\n" + - " │ └─ Filter\n" + - " │ ├─ AND\n" + - " │ │ ├─ Eq\n" + - " │ │ │ ├─ parts_1.part:0!null\n" + - " │ │ │ └─ pie (longtext)\n" + - " │ │ └─ Eq\n" + - " │ │ ├─ parts_1.sub_part:1!null\n" + - " │ │ └─ crust (longtext)\n" + - " │ └─ TableAlias(parts_1)\n" + - " │ └─ IndexedTableAccess(parts)\n" + - " │ ├─ index: [parts.part,parts.sub_part]\n" + - " │ ├─ static: [{[pie, pie], [NULL, ∞)}]\n" + - " │ ├─ colSet: (4-6)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: parts\n" + - " │ └─ columns: [part sub_part quantity]\n" + + " │ ├─ columns: [parts.sub_part:2!null, parts.part:1!null, parts.quantity:3!null]\n" + + " │ └─ LookupJoin\n" + + " │ ├─ Eq\n" + + " │ │ ├─ parts.part:1!null\n" + + " │ │ └─ parts_1.part:0!null\n" + + " │ ├─ Distinct\n" + + " │ │ └─ Project\n" + + " │ │ ├─ columns: [parts_1.part:0!null]\n" + + " │ │ └─ Filter\n" + + " │ │ ├─ AND\n" + + " │ │ │ ├─ Eq\n" + + " │ │ │ │ ├─ parts_1.part:0!null\n" + + " │ │ │ │ └─ pie (longtext)\n" + + " │ │ │ └─ Eq\n" + + " │ │ │ ├─ parts_1.sub_part:1!null\n" + + " │ │ │ └─ crust (longtext)\n" + + " │ │ └─ TableAlias(parts_1)\n" + + " │ │ └─ IndexedTableAccess(parts)\n" + + " │ │ ├─ index: [parts.part,parts.sub_part]\n" + + " │ │ ├─ static: [{[pie, pie], [crust, crust]}]\n" + + " │ │ ├─ colSet: (4-6)\n" + + " │ │ ├─ tableId: 2\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: parts\n" + + " │ │ └─ columns: [part sub_part quantity]\n" + + " │ └─ IndexedTableAccess(parts)\n" + + " │ ├─ index: [parts.part,parts.sub_part]\n" + + " │ ├─ keys: [parts_1.part:0!null]\n" + + " │ ├─ colSet: (1-3)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: parts\n" + + " │ └─ columns: [part sub_part quantity]\n" + " └─ Project\n" + " ├─ columns: [p.sub_part:4!null, p.part:3!null, p.quantity:5!null]\n" + " └─ LookupJoin\n" + @@ -1004,7 +1004,7 @@ Select * from ( "", }, { - Query: `select /*+ RIGHT_SEMI_LOOKUP_JOIN(xy,scalarSubq0) */ * from xy where x in (select a from ab);`, + Query: `select /*+ LOOKUP_JOIN(xy,scalarSubq0) */ * from xy where x in (select a from ab);`, ExpectedPlan: "SemiLookupJoin\n" + " ├─ ProcessTable\n" + " │ └─ Table\n" + @@ -1023,7 +1023,7 @@ Select * from ( "", }, { - Query: `select /*+ RIGHT_SEMI_LOOKUP_JOIN(xy,ab) MERGE_JOIN(ab,uv) JOIN_ORDER(ab,uv,xy) */ * from xy where EXISTS (select 1 from ab join uv on a = u where x = a);`, + Query: `select /*+ LOOKUP_JOIN(xy,ab) MERGE_JOIN(ab,uv) JOIN_ORDER(ab,uv,xy) */ * from xy where EXISTS (select 1 from ab join uv on a = u where x = a);`, ExpectedPlan: "Project\n" + " ├─ columns: [xy.x:1!null, xy.y:2]\n" + " └─ LookupJoin\n" + @@ -1140,26 +1140,34 @@ Select * from ( { Query: `SELECT mytable.s FROM mytable WHERE mytable.i = (SELECT othertable.i2 FROM othertable WHERE othertable.s2 = 'second')`, ExpectedPlan: "Project\n" + - " ├─ columns: [mytable.s:1!null]\n" + - " └─ SemiLookupJoin\n" + - " ├─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ Project\n" + - " ├─ columns: [othertable.i2:1!null]\n" + - " └─ Filter\n" + - " ├─ Eq\n" + - " │ ├─ othertable.s2:0!null\n" + - " │ └─ second (longtext)\n" + - " └─ IndexedTableAccess(othertable)\n" + - " ├─ index: [othertable.s2,othertable.i2]\n" + - " ├─ keys: [second (longtext) mytable.i:0!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: othertable\n" + - " └─ columns: [s2 i2]\n" + + " ├─ columns: [mytable.s:2!null]\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ mytable.i:1!null\n" + + " │ └─ othertable.i2:0!null\n" + + " ├─ Distinct\n" + + " │ └─ Project\n" + + " │ ├─ columns: [othertable.i2:1!null]\n" + + " │ └─ Filter\n" + + " │ ├─ Eq\n" + + " │ │ ├─ othertable.s2:0!null\n" + + " │ │ └─ second (longtext)\n" + + " │ └─ IndexedTableAccess(othertable)\n" + + " │ ├─ index: [othertable.s2]\n" + + " │ ├─ static: [{[second, second]}]\n" + + " │ ├─ colSet: (3,4)\n" + + " │ ├─ tableId: 2\n" + + " │ └─ Table\n" + + " │ ├─ name: othertable\n" + + " │ └─ columns: [s2 i2]\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [othertable.i2:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { @@ -1167,31 +1175,21 @@ Select * from ( ExpectedPlan: "Project\n" + " ├─ columns: [mytable.s:1!null]\n" + " └─ Sort(mytable.i:0!null ASC nullsFirst)\n" + - " └─ Project\n" + - " ├─ columns: [mytable.i:1!null, mytable.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:0!null\n" + - " │ └─ mytable.i:1!null\n" + - " ├─ Distinct\n" + - " │ └─ Project\n" + - " │ ├─ columns: [othertable.i2:1!null]\n" + - " │ └─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: othertable\n" + - " │ └─ columns: [s2 i2]\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (1,2)\n" + - " ├─ tableId: 1\n" + + " └─ SemiLookupJoin\n" + + " ├─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: mytable\n" + + " │ └─ columns: [i s]\n" + + " └─ Project\n" + + " ├─ columns: [othertable.i2:1!null]\n" + + " └─ IndexedTableAccess(othertable)\n" + + " ├─ index: [othertable.i2]\n" + + " ├─ keys: [mytable.i:0!null]\n" + + " ├─ colSet: (3,4)\n" + + " ├─ tableId: 2\n" + " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i s]\n" + + " ├─ name: othertable\n" + + " └─ columns: [s2 i2]\n" + "", }, { @@ -1231,21 +1229,15 @@ Select * from ( " │ ├─ cacheable: true\n" + " │ ├─ colSet: (7-10)\n" + " │ ├─ tableId: 4\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ ab.a:0!null\n" + - " │ │ └─ xy.y:3\n" + - " │ ├─ IndexedTableAccess(ab)\n" + - " │ │ ├─ index: [ab.a]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ └─ LookupJoin\n" + + " │ ├─ Table\n" + + " │ │ ├─ name: ab\n" + + " │ │ ├─ columns: [a b]\n" + " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: ab\n" + - " │ │ └─ columns: [a b]\n" + + " │ │ └─ tableId: 2\n" + " │ └─ IndexedTableAccess(xy)\n" + " │ ├─ index: [xy.y]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [ab.a:0!null]\n" + " │ ├─ colSet: (5,6)\n" + " │ ├─ tableId: 3\n" + " │ └─ Table\n" + @@ -1262,21 +1254,14 @@ Select * from ( }, { Query: `select /*+ JOIN_ORDER(ab, xy) */ * from ab join xy on y = a`, - ExpectedPlan: "MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ ab.a:0!null\n" + - " │ └─ xy.y:3\n" + - " ├─ IndexedTableAccess(ab)\n" + - " │ ├─ index: [ab.a]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + ExpectedPlan: "LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: ab\n" + " │ └─ columns: [a b]\n" + " └─ IndexedTableAccess(xy)\n" + " ├─ index: [xy.y]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [ab.a:0!null]\n" + " ├─ colSet: (3,4)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -1287,21 +1272,14 @@ Select * from ( { Query: `select /*+ JOIN_ORDER(rs, xy) */ * from rs join xy on y = s order by 1, 3`, ExpectedPlan: "Sort(rs.r:0!null ASC nullsFirst, xy.x:2!null ASC nullsFirst)\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ rs.s:1\n" + - " │ └─ xy.y:3\n" + - " ├─ IndexedTableAccess(rs)\n" + - " │ ├─ index: [rs.s]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: rs\n" + " │ └─ columns: [r s]\n" + " └─ IndexedTableAccess(xy)\n" + " ├─ index: [xy.y]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [rs.s:1]\n" + " ├─ colSet: (3,4)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -1311,21 +1289,14 @@ Select * from ( }, { Query: `select /*+ JOIN_ORDER(rs, xy) */ * from rs join xy on y = s`, - ExpectedPlan: "MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ rs.s:1\n" + - " │ └─ xy.y:3\n" + - " ├─ IndexedTableAccess(rs)\n" + - " │ ├─ index: [rs.s]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + ExpectedPlan: "LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: rs\n" + " │ └─ columns: [r s]\n" + " └─ IndexedTableAccess(xy)\n" + " ├─ index: [xy.y]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [rs.s:1]\n" + " ├─ colSet: (3,4)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -1974,32 +1945,39 @@ Select * from ( { Query: `select * from mytable t1 natural join mytable t2 join othertable t3 on t2.i = t3.i2;`, ExpectedPlan: "Project\n" + - " ├─ columns: [t1.i:2!null, t1.s:3!null, t3.s2:4!null, t3.i2:5!null]\n" + + " ├─ columns: [t1.i:2!null, t1.s:3!null, t3.s2:0!null, t3.i2:1!null]\n" + " └─ LookupJoin\n" + + " ├─ AND\n" + + " │ ├─ Eq\n" + + " │ │ ├─ t1.s:3!null\n" + + " │ │ └─ t2.s:5!null\n" + + " │ └─ Eq\n" + + " │ ├─ t2.i:4!null\n" + + " │ └─ t3.i2:1!null\n" + " ├─ LookupJoin\n" + - " │ ├─ TableAlias(t2)\n" + + " │ ├─ TableAlias(t3)\n" + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: mytable\n" + - " │ │ └─ columns: [i s]\n" + + " │ │ ├─ name: othertable\n" + + " │ │ └─ columns: [s2 i2]\n" + " │ └─ TableAlias(t1)\n" + " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.s,mytable.i]\n" + - " │ ├─ keys: [t2.s:1!null t2.i:0!null]\n" + + " │ ├─ index: [mytable.i]\n" + + " │ ├─ keys: [t3.i2:1!null]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i s]\n" + - " └─ TableAlias(t3)\n" + - " └─ IndexedTableAccess(othertable)\n" + - " ├─ index: [othertable.i2]\n" + - " ├─ keys: [t2.i:0!null]\n" + - " ├─ colSet: (5,6)\n" + - " ├─ tableId: 3\n" + + " └─ TableAlias(t2)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [t1.i:2!null]\n" + + " ├─ colSet: (3,4)\n" + + " ├─ tableId: 2\n" + " └─ Table\n" + - " ├─ name: othertable\n" + - " └─ columns: [s2 i2]\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { @@ -2158,25 +2136,25 @@ Select * from ( { Query: `select * from ab where exists (select * from ab where a = 1)`, ExpectedPlan: "Project\n" + - " ├─ columns: [ab.a:0!null, ab.b:1]\n" + + " ├─ columns: [ab.a:2!null, ab.b:3]\n" + " └─ CrossHashJoin\n" + - " ├─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: ab\n" + - " │ └─ columns: [a b]\n" + + " ├─ Limit(1)\n" + + " │ └─ TableAlias(ab_1)\n" + + " │ └─ IndexedTableAccess(ab)\n" + + " │ ├─ index: [ab.a]\n" + + " │ ├─ static: [{[1, 1]}]\n" + + " │ ├─ colSet: (3,4)\n" + + " │ ├─ tableId: 2\n" + + " │ └─ Table\n" + + " │ ├─ name: ab\n" + + " │ └─ columns: [a b]\n" + " └─ HashLookup\n" + " ├─ left-key: TUPLE()\n" + " ├─ right-key: TUPLE()\n" + - " └─ Limit(1)\n" + - " └─ TableAlias(ab_1)\n" + - " └─ IndexedTableAccess(ab)\n" + - " ├─ index: [ab.a]\n" + - " ├─ static: [{[1, 1]}]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: ab\n" + - " └─ columns: [a b]\n" + + " └─ ProcessTable\n" + + " └─ Table\n" + + " ├─ name: ab\n" + + " └─ columns: [a b]\n" + "", }, { @@ -2568,21 +2546,14 @@ where exists " ├─ OrderedDistinct\n" + " │ └─ Project\n" + " │ ├─ columns: [uv.u:0!null]\n" + - " │ └─ LeftOuterMergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ uv.u:0!null\n" + - " │ │ └─ pq.p:2!null\n" + - " │ ├─ IndexedTableAccess(uv)\n" + - " │ │ ├─ index: [uv.u]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + + " │ └─ LeftOuterLookupJoin\n" + + " │ ├─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: uv\n" + " │ │ └─ columns: [u v]\n" + " │ └─ IndexedTableAccess(pq)\n" + " │ ├─ index: [pq.p]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [uv.u:0!null]\n" + " │ ├─ colSet: (5,6)\n" + " │ ├─ tableId: 3\n" + " │ └─ Table\n" + @@ -2812,31 +2783,21 @@ inner join pq on true Query: `select i from mytable a where exists (select 1 from mytable b where a.i = b.i)`, ExpectedPlan: "Project\n" + " ├─ columns: [a.i:0!null]\n" + - " └─ Project\n" + - " ├─ columns: [a.i:1!null, a.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ b.i:0!null\n" + - " │ └─ a.i:1!null\n" + - " ├─ OrderedDistinct\n" + - " │ └─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: mytable\n" + - " │ └─ columns: [i]\n" + - " └─ TableAlias(a)\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (1,2)\n" + - " ├─ tableId: 1\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i s]\n" + + " └─ SemiLookupJoin\n" + + " ├─ TableAlias(a)\n" + + " │ └─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: mytable\n" + + " │ └─ columns: [i s]\n" + + " └─ TableAlias(b)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [a.i:0!null]\n" + + " ├─ colSet: (3,4)\n" + + " ├─ tableId: 2\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i]\n" + "", }, { @@ -2847,23 +2808,16 @@ inner join pq on true " ├─ columns: [a.i:0!null, a.s:1!null]\n" + " └─ Filter\n" + " ├─ b.i:2!null IS NULL\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ a.i:0!null\n" + - " │ └─ b.i:2!null\n" + + " └─ LeftOuterLookupJoin\n" + " ├─ TableAlias(a)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i s]\n" + " └─ TableAlias(b)\n" + " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ index: [mytable.i,mytable.s]\n" + + " ├─ keys: [a.i:0!null]\n" + " ├─ colSet: (3,4)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -2897,21 +2851,14 @@ inner join pq on true " └─ Project\n" + " ├─ columns: [mytable.i:2!null, mytable.s:3!null, othertable.s2:0!null, othertable.i2:1!null, t4.s2:4!null, t4.i2:5!null]\n" + " └─ LeftOuterLookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ othertable.i2:1!null\n" + - " │ │ └─ mytable.i:2!null\n" + - " │ ├─ IndexedTableAccess(othertable)\n" + - " │ │ ├─ index: [othertable.i2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + + " ├─ LookupJoin\n" + + " │ ├─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: othertable\n" + " │ │ └─ columns: [s2 i2]\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [othertable.i2:1!null]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -3036,21 +2983,14 @@ inner join pq on true " └─ Window\n" + " ├─ row_number() over ( order by mytable.i DESC)\n" + " ├─ mytable.i:1!null\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:0!null\n" + - " │ └─ mytable.i:1!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3129,24 +3069,24 @@ inner join pq on true " ├─ columns: [row_number() over ( order by mytable.i desc):0!null, mytable.i:1!null, mytable.i:1!null as i2]\n" + " └─ Window\n" + " ├─ row_number() over ( order by mytable.i DESC)\n" + - " ├─ mytable.i:0!null\n" + + " ├─ mytable.i:1!null\n" + " └─ LookupJoin\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[2, 2]}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + - " │ ├─ name: mytable\n" + - " │ └─ columns: [i]\n" + - " └─ IndexedTableAccess(othertable)\n" + - " ├─ index: [othertable.i2]\n" + - " ├─ keys: [mytable.i:0!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: othertable\n" + - " └─ columns: [i2]\n" + + " │ ├─ name: othertable\n" + + " │ └─ columns: [i2]\n" + + " └─ Filter\n" + + " ├─ Eq\n" + + " │ ├─ mytable.i:0!null\n" + + " │ └─ 2 (tinyint)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [othertable.i2:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i]\n" + "", }, { @@ -3251,27 +3191,30 @@ inner join pq on true { Query: `SELECT /*+ JOIN_ORDER(t1, t2, t3) */ t1.i FROM mytable t1 JOIN mytable t2 on t1.i = t2.i + 1 where t1.i = 2 and t2.i = 1`, ExpectedPlan: "Project\n" + - " ├─ columns: [t1.i:1!null]\n" + + " ├─ columns: [t1.i:0!null]\n" + " └─ LookupJoin\n" + - " ├─ TableAlias(t2)\n" + + " ├─ Eq\n" + + " │ ├─ t1.i:0!null\n" + + " │ └─ (t2.i:1!null + 1 (tinyint))\n" + + " ├─ TableAlias(t1)\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[1, 1]}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " │ ├─ static: [{[2, 2]}]\n" + + " │ ├─ colSet: (1,2)\n" + + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ Filter\n" + " ├─ Eq\n" + - " │ ├─ t1.i:0!null\n" + - " │ └─ 2 (tinyint)\n" + - " └─ TableAlias(t1)\n" + + " │ ├─ t2.i:0!null\n" + + " │ └─ 1 (tinyint)\n" + + " └─ TableAlias(t2)\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ keys: [(t2.i:0!null + 1 (tinyint))]\n" + - " ├─ colSet: (1,2)\n" + - " ├─ tableId: 1\n" + + " ├─ keys: [1 (tinyint)]\n" + + " ├─ colSet: (3,4)\n" + + " ├─ tableId: 2\n" + " └─ Table\n" + " ├─ name: mytable\n" + " └─ columns: [i]\n" + @@ -3310,21 +3253,14 @@ inner join pq on true Query: `SELECT i, i2, s2 FROM mytable INNER JOIN othertable ON i = i2`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3491,21 +3427,14 @@ inner join pq on true ExpectedPlan: "Union distinct\n" + " ├─ Project\n" + " │ ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ othertable.i2:1!null\n" + - " │ │ └─ mytable.i:2!null\n" + - " │ ├─ IndexedTableAccess(othertable)\n" + - " │ │ ├─ index: [othertable.i2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + + " │ └─ LookupJoin\n" + + " │ ├─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: othertable\n" + " │ │ └─ columns: [s2 i2]\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [othertable.i2:1!null]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -3513,21 +3442,14 @@ inner join pq on true " │ └─ columns: [i]\n" + " └─ Project\n" + " ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (7,8)\n" + - " │ ├─ tableId: 4\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (5,6)\n" + " ├─ tableId: 3\n" + " └─ Table\n" + @@ -3552,21 +3474,15 @@ inner join pq on true " │ ├─ tableId: 3\n" + " │ └─ Project\n" + " │ ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ othertable.i2:1!null\n" + - " │ │ └─ mytable.i:2!null\n" + - " │ ├─ IndexedTableAccess(othertable)\n" + - " │ │ ├─ index: [othertable.i2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ └─ LookupJoin\n" + + " │ ├─ Table\n" + + " │ │ ├─ name: othertable\n" + + " │ │ ├─ columns: [s2 i2]\n" + " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: othertable\n" + - " │ │ └─ columns: [s2 i2]\n" + + " │ │ └─ tableId: 2\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [othertable.i2:1!null]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -3599,21 +3515,15 @@ inner join pq on true " │ ├─ tableId: 4\n" + " │ └─ Project\n" + " │ ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ othertable.i2:1!null\n" + - " │ │ └─ mytable.i:2!null\n" + - " │ ├─ IndexedTableAccess(othertable)\n" + - " │ │ ├─ index: [othertable.i2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ └─ LookupJoin\n" + + " │ ├─ Table\n" + + " │ │ ├─ name: othertable\n" + + " │ │ ├─ columns: [s2 i2]\n" + " │ │ ├─ colSet: (5,6)\n" + - " │ │ ├─ tableId: 3\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: othertable\n" + - " │ │ └─ columns: [s2 i2]\n" + + " │ │ └─ tableId: 3\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [othertable.i2:1!null]\n" + " │ ├─ colSet: (3,4)\n" + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + @@ -3633,7 +3543,7 @@ inner join pq on true Query: `SELECT sub.i, sub.i2, sub.s2, ot.i2, ot.s2 FROM othertable ot LEFT JOIN (SELECT i, i2, s2 FROM mytable INNER JOIN othertable ON i = i2 WHERE CONVERT(s2, signed) <> 0) sub ON sub.i = ot.i2 WHERE ot.i2 > 0`, ExpectedPlan: "Project\n" + " ├─ columns: [sub.i:2!null, sub.i2:3!null, sub.s2:4!null, ot.i2:1!null, ot.s2:0!null]\n" + - " └─ LeftOuterJoin\n" + + " └─ LeftOuterHashJoin\n" + " ├─ Eq\n" + " │ ├─ sub.i:2!null\n" + " │ └─ ot.i2:1!null\n" + @@ -3646,124 +3556,119 @@ inner join pq on true " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + - " └─ SubqueryAlias\n" + - " ├─ name: sub\n" + - " ├─ outerVisibility: false\n" + - " ├─ isLateral: false\n" + - " ├─ cacheable: true\n" + - " ├─ colSet: (7-9)\n" + - " ├─ tableId: 4\n" + - " └─ Project\n" + - " ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " └─ LookupJoin\n" + - " ├─ Filter\n" + - " │ ├─ NOT\n" + - " │ │ └─ Eq\n" + - " │ │ ├─ convert\n" + - " │ │ │ ├─ type: signed\n" + - " │ │ │ └─ othertable.s2:0!null\n" + - " │ │ └─ 0 (tinyint)\n" + - " │ └─ Table\n" + - " │ ├─ name: othertable\n" + - " │ ├─ columns: [s2 i2]\n" + - " │ ├─ colSet: (5,6)\n" + - " │ └─ tableId: 3\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ keys: [othertable.i2:1!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i]\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE(ot.i2:1!null)\n" + + " ├─ right-key: TUPLE(sub.i:0!null)\n" + + " └─ SubqueryAlias\n" + + " ├─ name: sub\n" + + " ├─ outerVisibility: false\n" + + " ├─ isLateral: false\n" + + " ├─ cacheable: true\n" + + " ├─ colSet: (7-9)\n" + + " ├─ tableId: 4\n" + + " └─ Project\n" + + " ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + + " └─ LookupJoin\n" + + " ├─ Filter\n" + + " │ ├─ NOT\n" + + " │ │ └─ Eq\n" + + " │ │ ├─ convert\n" + + " │ │ │ ├─ type: signed\n" + + " │ │ │ └─ othertable.s2:0!null\n" + + " │ │ └─ 0 (tinyint)\n" + + " │ └─ Table\n" + + " │ ├─ name: othertable\n" + + " │ ├─ columns: [s2 i2]\n" + + " │ ├─ colSet: (5,6)\n" + + " │ └─ tableId: 3\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + + " ├─ colSet: (3,4)\n" + + " ├─ tableId: 2\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i]\n" + "", }, { Query: `select /*+ JOIN_ORDER( i, k, j ) */ * from one_pk i join one_pk k on i.pk = k.pk join (select pk, rand() r from one_pk) j on i.pk = j.pk`, - ExpectedPlan: "InnerJoin\n" + + ExpectedPlan: "HashJoin\n" + " ├─ Eq\n" + " │ ├─ i.pk:0!null\n" + " │ └─ j.pk:12!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ i.pk:0!null\n" + - " │ │ └─ k.pk:6!null\n" + + " ├─ LookupJoin\n" + " │ ├─ TableAlias(i)\n" + - " │ │ └─ IndexedTableAccess(one_pk)\n" + - " │ │ ├─ index: [one_pk.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-6)\n" + - " │ │ ├─ tableId: 1\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: one_pk\n" + " │ │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " │ └─ TableAlias(k)\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [i.pk:0!null]\n" + " │ ├─ colSet: (7-12)\n" + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + - " └─ SubqueryAlias\n" + - " ├─ name: j\n" + - " ├─ outerVisibility: false\n" + - " ├─ isLateral: false\n" + - " ├─ cacheable: false\n" + - " ├─ colSet: (20,21)\n" + - " ├─ tableId: 4\n" + - " └─ Project\n" + - " ├─ columns: [one_pk.pk:0!null, rand() as r]\n" + - " └─ Table\n" + - " ├─ name: one_pk\n" + - " ├─ columns: [pk]\n" + - " ├─ colSet: (13-18)\n" + - " └─ tableId: 3\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE(i.pk:0!null)\n" + + " ├─ right-key: TUPLE(j.pk:0!null)\n" + + " └─ SubqueryAlias\n" + + " ├─ name: j\n" + + " ├─ outerVisibility: false\n" + + " ├─ isLateral: false\n" + + " ├─ cacheable: false\n" + + " ├─ colSet: (20,21)\n" + + " ├─ tableId: 4\n" + + " └─ Project\n" + + " ├─ columns: [one_pk.pk:0!null, rand() as r]\n" + + " └─ Table\n" + + " ├─ name: one_pk\n" + + " ├─ columns: [pk]\n" + + " ├─ colSet: (13-18)\n" + + " └─ tableId: 3\n" + "", }, { Query: `select /*+ JOIN_ORDER( i, k, j ) */ * from one_pk i join one_pk k on i.pk = k.pk join (select pk, rand() r from one_pk) j on i.pk = j.pk`, - ExpectedPlan: "InnerJoin\n" + + ExpectedPlan: "HashJoin\n" + " ├─ Eq\n" + " │ ├─ i.pk:0!null\n" + " │ └─ j.pk:12!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ i.pk:0!null\n" + - " │ │ └─ k.pk:6!null\n" + + " ├─ LookupJoin\n" + " │ ├─ TableAlias(i)\n" + - " │ │ └─ IndexedTableAccess(one_pk)\n" + - " │ │ ├─ index: [one_pk.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-6)\n" + - " │ │ ├─ tableId: 1\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: one_pk\n" + " │ │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " │ └─ TableAlias(k)\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [i.pk:0!null]\n" + " │ ├─ colSet: (7-12)\n" + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + - " └─ SubqueryAlias\n" + - " ├─ name: j\n" + - " ├─ outerVisibility: false\n" + - " ├─ isLateral: false\n" + - " ├─ cacheable: false\n" + - " ├─ colSet: (20,21)\n" + - " ├─ tableId: 4\n" + - " └─ Project\n" + - " ├─ columns: [one_pk.pk:0!null, rand() as r]\n" + - " └─ Table\n" + - " ├─ name: one_pk\n" + - " ├─ columns: [pk]\n" + - " ├─ colSet: (13-18)\n" + - " └─ tableId: 3\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE(i.pk:0!null)\n" + + " ├─ right-key: TUPLE(j.pk:0!null)\n" + + " └─ SubqueryAlias\n" + + " ├─ name: j\n" + + " ├─ outerVisibility: false\n" + + " ├─ isLateral: false\n" + + " ├─ cacheable: false\n" + + " ├─ colSet: (20,21)\n" + + " ├─ tableId: 4\n" + + " └─ Project\n" + + " ├─ columns: [one_pk.pk:0!null, rand() as r]\n" + + " └─ Table\n" + + " ├─ name: one_pk\n" + + " ├─ columns: [pk]\n" + + " ├─ colSet: (13-18)\n" + + " └─ tableId: 3\n" + "", }, { @@ -3792,21 +3697,15 @@ inner join pq on true " │ ├─ tableId: 5\n" + " │ └─ Project\n" + " │ ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ othertable.i2:1!null\n" + - " │ │ └─ mytable.i:2!null\n" + - " │ ├─ IndexedTableAccess(othertable)\n" + - " │ │ ├─ index: [othertable.i2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ └─ LookupJoin\n" + + " │ ├─ Table\n" + + " │ │ ├─ name: othertable\n" + + " │ │ ├─ columns: [s2 i2]\n" + " │ │ ├─ colSet: (7,8)\n" + - " │ │ ├─ tableId: 4\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: othertable\n" + - " │ │ └─ columns: [s2 i2]\n" + + " │ │ └─ tableId: 4\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [othertable.i2:1!null]\n" + " │ ├─ colSet: (5,6)\n" + " │ ├─ tableId: 3\n" + " │ └─ Table\n" + @@ -3855,21 +3754,14 @@ inner join pq on true }, { Query: `SELECT s2, i2, i FROM mytable INNER JOIN othertable ON i = i2`, - ExpectedPlan: "MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + ExpectedPlan: "LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3881,21 +3773,14 @@ inner join pq on true Query: `SELECT i, i2, s2 FROM othertable JOIN mytable ON i = i2`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:0!null, othertable.i2:2!null, othertable.s2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ mytable.i:0!null\n" + - " │ └─ othertable.i2:2!null\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ IndexedTableAccess(othertable)\n" + " ├─ index: [othertable.i2]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [mytable.i:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3907,21 +3792,14 @@ inner join pq on true Query: `SELECT s2, i2, i FROM othertable JOIN mytable ON i = i2`, ExpectedPlan: "Project\n" + " ├─ columns: [othertable.s2:1!null, othertable.i2:2!null, mytable.i:0!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ mytable.i:0!null\n" + - " │ └─ othertable.i2:2!null\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ IndexedTableAccess(othertable)\n" + " ├─ index: [othertable.i2]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [mytable.i:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3933,21 +3811,14 @@ inner join pq on true Query: `SELECT s2, i2, i FROM othertable JOIN mytable ON i = i2`, ExpectedPlan: "Project\n" + " ├─ columns: [othertable.s2:1!null, othertable.i2:2!null, mytable.i:0!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ mytable.i:0!null\n" + - " │ └─ othertable.i2:2!null\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ IndexedTableAccess(othertable)\n" + " ├─ index: [othertable.i2]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [mytable.i:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3960,21 +3831,14 @@ inner join pq on true ExpectedPlan: "Limit(1)\n" + " └─ Project\n" + " ├─ columns: [othertable.s2:1!null, othertable.i2:2!null, mytable.i:0!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ mytable.i:0!null\n" + - " │ └─ othertable.i2:2!null\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ IndexedTableAccess(othertable)\n" + " ├─ index: [othertable.i2]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [mytable.i:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -3986,21 +3850,14 @@ inner join pq on true Query: `SELECT i, i2, s2 FROM mytable INNER JOIN othertable ON i2 = i`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, othertable.i2:1!null, othertable.s2:0!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4010,21 +3867,14 @@ inner join pq on true }, { Query: `SELECT s2, i2, i FROM mytable INNER JOIN othertable ON i2 = i`, - ExpectedPlan: "MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + ExpectedPlan: "LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4036,23 +3886,16 @@ inner join pq on true Query: `SELECT * FROM MYTABLE JOIN OTHERTABLE ON i = i2 AND NOT (s2 <=> s)`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, mytable.s:3!null, othertable.s2:0!null, othertable.i2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ sel: NOT\n" + + " └─ LookupJoin\n" + + " ├─ NOT\n" + " │ └─ (othertable.s2:0!null <=> mytable.s:3!null)\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4064,25 +3907,18 @@ inner join pq on true Query: `SELECT * FROM MYTABLE JOIN OTHERTABLE ON i = i2 AND NOT (s2 = s)`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, mytable.s:3!null, othertable.s2:0!null, othertable.i2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ sel: NOT\n" + + " └─ LookupJoin\n" + + " ├─ NOT\n" + " │ └─ Eq\n" + " │ ├─ othertable.s2:0!null\n" + " │ └─ mytable.s:3!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4094,23 +3930,16 @@ inner join pq on true Query: `SELECT * FROM MYTABLE JOIN OTHERTABLE ON i = i2 AND CONCAT(s, s2) IS NOT NULL`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, mytable.s:3!null, othertable.s2:0!null, othertable.i2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ sel: NOT\n" + + " └─ LookupJoin\n" + + " ├─ NOT\n" + " │ └─ concat(mytable.s:3!null,othertable.s2:0!null) IS NULL\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4122,24 +3951,17 @@ inner join pq on true Query: `SELECT * FROM MYTABLE JOIN OTHERTABLE ON i = i2 AND s > s2`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, mytable.s:3!null, othertable.s2:0!null, othertable.i2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ sel: GreaterThan\n" + + " └─ LookupJoin\n" + + " ├─ GreaterThan\n" + " │ ├─ mytable.s:3!null\n" + " │ └─ othertable.s2:0!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4151,24 +3973,17 @@ inner join pq on true Query: `SELECT * FROM MYTABLE JOIN OTHERTABLE ON i = i2 AND NOT(s > s2)`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:2!null, mytable.s:3!null, othertable.s2:0!null, othertable.i2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:1!null\n" + - " │ └─ mytable.i:2!null\n" + - " ├─ sel: LessThanOrEqual\n" + + " └─ LookupJoin\n" + + " ├─ LessThanOrEqual\n" + " │ ├─ mytable.s:3!null\n" + " │ └─ othertable.s2:0!null\n" + - " ├─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:1!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4287,42 +4102,34 @@ inner join pq on true { Query: `SELECT a.* FROM mytable a inner join mytable b on (a.i = b.s) WHERE a.s is not null`, ExpectedPlan: "Project\n" + - " ├─ columns: [a.i:0!null, a.s:1!null]\n" + + " ├─ columns: [a.i:1!null, a.s:2!null]\n" + " └─ LookupJoin\n" + - " ├─ TableAlias(a)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.s]\n" + - " │ ├─ static: [{(NULL, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + " ├─ TableAlias(b)\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ TableAlias(b)\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.s]\n" + - " ├─ keys: [a.i:0!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [s]\n" + + " │ └─ columns: [s]\n" + + " └─ Filter\n" + + " ├─ NOT\n" + + " │ └─ a.s:1!null IS NULL\n" + + " └─ TableAlias(a)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [b.s:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { Query: `SELECT /*+ JOIN_ORDER(b, a) */ a.* FROM mytable a inner join mytable b on (a.i = b.s) WHERE a.s is not null`, ExpectedPlan: "Project\n" + " ├─ columns: [a.i:1!null, a.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ b.s:0!null\n" + - " │ └─ a.i:1!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.s,mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [s]\n" + @@ -4332,7 +4139,7 @@ inner join pq on true " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [b.s:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4652,23 +4459,16 @@ inner join pq on true Query: `SELECT a.* FROM mytable a, mytable b where a.i = b.i`, ExpectedPlan: "Project\n" + " ├─ columns: [a.i:1!null, a.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ b.i:0!null\n" + - " │ └─ a.i:1!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [b.i:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -4695,22 +4495,24 @@ inner join pq on true " │ └─ columns: [i]\n" + " └─ TableAlias(a)\n" + " └─ Concat\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ keys: [1 (tinyint)]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.s,mytable.i]\n" + - " ├─ keys: [b.i:0!null]\n" + - " ├─ colSet: (1,2)\n" + - " ├─ tableId: 1\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i s]\n" + + " ├─ TableAlias(a)\n" + + " │ └─ IndexedTableAccess(mytable)\n" + + " │ ├─ index: [mytable.i]\n" + + " │ ├─ keys: [1 (tinyint)]\n" + + " │ ├─ colSet: (1,2)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: mytable\n" + + " │ └─ columns: [i s]\n" + + " └─ TableAlias(a)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.s,mytable.i]\n" + + " ├─ keys: [b.i:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { @@ -4849,23 +4651,16 @@ inner join pq on true " │ ├─ Eq\n" + " │ │ ├─ b.i:0!null\n" + " │ │ └─ d.i:3!null\n" + - " │ ├─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ b.i:0!null\n" + - " │ │ │ └─ a.i:1!null\n" + + " │ ├─ LookupJoin\n" + " │ │ ├─ TableAlias(b)\n" + - " │ │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ │ ├─ index: [mytable.i]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (3,4)\n" + - " │ │ │ ├─ tableId: 2\n" + + " │ │ │ └─ ProcessTable\n" + " │ │ │ └─ Table\n" + " │ │ │ ├─ name: mytable\n" + " │ │ │ └─ columns: [i]\n" + " │ │ └─ TableAlias(a)\n" + " │ │ └─ IndexedTableAccess(mytable)\n" + " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ ├─ keys: [b.i:0!null]\n" + " │ │ ├─ colSet: (1,2)\n" + " │ │ ├─ tableId: 1\n" + " │ │ └─ Table\n" + @@ -4919,22 +4714,24 @@ inner join pq on true " │ │ │ └─ columns: [s]\n" + " │ │ └─ TableAlias(c)\n" + " │ │ └─ Concat\n" + - " │ │ ├─ IndexedTableAccess(mytable)\n" + - " │ │ │ ├─ index: [mytable.i]\n" + - " │ │ │ ├─ keys: [2 (tinyint)]\n" + - " │ │ │ ├─ colSet: (5,6)\n" + - " │ │ │ ├─ tableId: 3\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: mytable\n" + - " │ │ │ └─ columns: [i]\n" + - " │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ keys: [d.s:0!null]\n" + - " │ │ ├─ colSet: (5,6)\n" + - " │ │ ├─ tableId: 3\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: mytable\n" + - " │ │ └─ columns: [i]\n" + + " │ │ ├─ TableAlias(c)\n" + + " │ │ │ └─ IndexedTableAccess(mytable)\n" + + " │ │ │ ├─ index: [mytable.i]\n" + + " │ │ │ ├─ keys: [2 (tinyint)]\n" + + " │ │ │ ├─ colSet: (5,6)\n" + + " │ │ │ ├─ tableId: 3\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: mytable\n" + + " │ │ │ └─ columns: [i]\n" + + " │ │ └─ TableAlias(c)\n" + + " │ │ └─ IndexedTableAccess(mytable)\n" + + " │ │ ├─ index: [mytable.i]\n" + + " │ │ ├─ keys: [d.s:0!null]\n" + + " │ │ ├─ colSet: (5,6)\n" + + " │ │ ├─ tableId: 3\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: mytable\n" + + " │ │ └─ columns: [i]\n" + " │ └─ TableAlias(a)\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + @@ -4972,23 +4769,17 @@ inner join pq on true " ├─ Eq\n" + " │ ├─ b.i:3!null\n" + " │ └─ c.i:0!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ c.i:0!null\n" + - " │ │ └─ a.i:1!null\n" + + " ├─ LookupJoin\n" + " │ ├─ TableAlias(c)\n" + - " │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: mytable\n" + + " │ │ ├─ columns: [i]\n" + " │ │ ├─ colSet: (5,6)\n" + - " │ │ ├─ tableId: 3\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: mytable\n" + - " │ │ └─ columns: [i]\n" + + " │ │ └─ tableId: 3\n" + " │ └─ TableAlias(a)\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [c.i:0!null]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -5009,23 +4800,16 @@ inner join pq on true Query: `SELECT a.* FROM mytable a CROSS JOIN mytable b where a.i = b.i`, ExpectedPlan: "Project\n" + " ├─ columns: [a.i:1!null, a.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ b.i:0!null\n" + - " │ └─ a.i:1!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + " │ └─ columns: [i]\n" + " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [b.i:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -5052,22 +4836,24 @@ inner join pq on true " │ └─ columns: [i s]\n" + " └─ TableAlias(a)\n" + " └─ Concat\n" + - " ├─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ keys: [b.s:1!null]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ keys: [b.i:0!null]\n" + - " ├─ colSet: (1,2)\n" + - " ├─ tableId: 1\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i s]\n" + + " ├─ TableAlias(a)\n" + + " │ └─ IndexedTableAccess(mytable)\n" + + " │ ├─ index: [mytable.i]\n" + + " │ ├─ keys: [b.s:1!null]\n" + + " │ ├─ colSet: (1,2)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: mytable\n" + + " │ └─ columns: [i s]\n" + + " └─ TableAlias(a)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [b.i:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { @@ -5180,23 +4966,16 @@ inner join pq on true " │ ├─ Eq\n" + " │ │ ├─ b.i:0!null\n" + " │ │ └─ d.i:3!null\n" + - " │ ├─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ b.i:0!null\n" + - " │ │ │ └─ a.i:1!null\n" + + " │ ├─ LookupJoin\n" + " │ │ ├─ TableAlias(b)\n" + - " │ │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ │ ├─ index: [mytable.i]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (3,4)\n" + - " │ │ │ ├─ tableId: 2\n" + + " │ │ │ └─ ProcessTable\n" + " │ │ │ └─ Table\n" + " │ │ │ ├─ name: mytable\n" + " │ │ │ └─ columns: [i]\n" + " │ │ └─ TableAlias(a)\n" + " │ │ └─ IndexedTableAccess(mytable)\n" + " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ ├─ keys: [b.i:0!null]\n" + " │ │ ├─ colSet: (1,2)\n" + " │ │ ├─ tableId: 1\n" + " │ │ └─ Table\n" + @@ -5250,22 +5029,24 @@ inner join pq on true " │ │ │ └─ columns: [s]\n" + " │ │ └─ TableAlias(c)\n" + " │ │ └─ Concat\n" + - " │ │ ├─ IndexedTableAccess(mytable)\n" + - " │ │ │ ├─ index: [mytable.i]\n" + - " │ │ │ ├─ keys: [2 (tinyint)]\n" + - " │ │ │ ├─ colSet: (5,6)\n" + - " │ │ │ ├─ tableId: 3\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: mytable\n" + - " │ │ │ └─ columns: [i]\n" + - " │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ keys: [d.s:0!null]\n" + - " │ │ ├─ colSet: (5,6)\n" + - " │ │ ├─ tableId: 3\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: mytable\n" + - " │ │ └─ columns: [i]\n" + + " │ │ ├─ TableAlias(c)\n" + + " │ │ │ └─ IndexedTableAccess(mytable)\n" + + " │ │ │ ├─ index: [mytable.i]\n" + + " │ │ │ ├─ keys: [2 (tinyint)]\n" + + " │ │ │ ├─ colSet: (5,6)\n" + + " │ │ │ ├─ tableId: 3\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: mytable\n" + + " │ │ │ └─ columns: [i]\n" + + " │ │ └─ TableAlias(c)\n" + + " │ │ └─ IndexedTableAccess(mytable)\n" + + " │ │ ├─ index: [mytable.i]\n" + + " │ │ ├─ keys: [d.s:0!null]\n" + + " │ │ ├─ colSet: (5,6)\n" + + " │ │ ├─ tableId: 3\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: mytable\n" + + " │ │ └─ columns: [i]\n" + " │ └─ TableAlias(a)\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.i]\n" + @@ -5300,23 +5081,17 @@ inner join pq on true " ├─ left-key: TUPLE()\n" + " ├─ right-key: TUPLE()\n" + " └─ LookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ c.s:0!null\n" + - " │ │ └─ b.s:2!null\n" + + " ├─ LookupJoin\n" + " │ ├─ TableAlias(c)\n" + - " │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ ├─ index: [mytable.s,mytable.i]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: mytable\n" + + " │ │ ├─ columns: [s]\n" + " │ │ ├─ colSet: (5,6)\n" + - " │ │ ├─ tableId: 3\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: mytable\n" + - " │ │ └─ columns: [s]\n" + + " │ │ └─ tableId: 3\n" + " │ └─ TableAlias(b)\n" + " │ └─ IndexedTableAccess(mytable)\n" + " │ ├─ index: [mytable.s]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [c.s:0!null]\n" + " │ ├─ colSet: (3,4)\n" + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + @@ -5336,26 +5111,30 @@ inner join pq on true { Query: `SELECT a.* FROM mytable a inner join mytable b on (a.i = b.s) WHERE a.i BETWEEN 10 AND 20`, ExpectedPlan: "Project\n" + - " ├─ columns: [a.i:0!null, a.s:1!null]\n" + + " ├─ columns: [a.i:1!null, a.s:2!null]\n" + " └─ LookupJoin\n" + - " ├─ TableAlias(a)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[10, 20]}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + " ├─ TableAlias(b)\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ TableAlias(b)\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.s]\n" + - " ├─ keys: [a.i:0!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [s]\n" + + " │ └─ columns: [s]\n" + + " └─ Filter\n" + + " ├─ AND\n" + + " │ ├─ GreaterThanOrEqual\n" + + " │ │ ├─ a.i:0!null\n" + + " │ │ └─ 10 (tinyint)\n" + + " │ └─ LessThanOrEqual\n" + + " │ ├─ a.i:0!null\n" + + " │ └─ 20 (tinyint)\n" + + " └─ TableAlias(a)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [b.s:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { @@ -5560,25 +5339,21 @@ inner join pq on true Query: `SELECT mytable.i, mytable.s FROM mytable WHERE mytable.i = (SELECT i2 FROM othertable LIMIT 1)`, ExpectedPlan: "Project\n" + " ├─ columns: [mytable.i:1!null, mytable.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:0!null\n" + - " │ └─ mytable.i:1!null\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ mytable.i:1!null\n" + + " │ └─ othertable.i2:0!null\n" + " ├─ Distinct\n" + " │ └─ Limit(1)\n" + " │ └─ Project\n" + " │ ├─ columns: [othertable.i2:1!null]\n" + - " │ └─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [othertable.i2:0!null]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -5588,31 +5363,21 @@ inner join pq on true }, { Query: `SELECT mytable.i, mytable.s FROM mytable WHERE mytable.i IN (SELECT i2 FROM othertable)`, - ExpectedPlan: "Project\n" + - " ├─ columns: [mytable.i:1!null, mytable.s:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ othertable.i2:0!null\n" + - " │ └─ mytable.i:1!null\n" + - " ├─ Distinct\n" + - " │ └─ Project\n" + - " │ ├─ columns: [othertable.i2:1!null]\n" + - " │ └─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (3,4)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: othertable\n" + - " │ └─ columns: [s2 i2]\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (1,2)\n" + - " ├─ tableId: 1\n" + + ExpectedPlan: "SemiLookupJoin\n" + + " ├─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: mytable\n" + + " │ └─ columns: [i s]\n" + + " └─ Project\n" + + " ├─ columns: [othertable.i2:1!null]\n" + + " └─ IndexedTableAccess(othertable)\n" + + " ├─ index: [othertable.i2]\n" + + " ├─ keys: [mytable.i:0!null]\n" + + " ├─ colSet: (3,4)\n" + + " ├─ tableId: 2\n" + " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i s]\n" + + " ├─ name: othertable\n" + + " └─ columns: [s2 i2]\n" + "", }, { @@ -5643,25 +5408,27 @@ inner join pq on true }, { Query: `SELECT * FROM mytable mt INNER JOIN othertable ot ON mt.i = ot.i2 AND mt.i > 2`, - ExpectedPlan: "LookupJoin\n" + - " ├─ TableAlias(mt)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{(2, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ TableAlias(ot)\n" + - " └─ IndexedTableAccess(othertable)\n" + - " ├─ index: [othertable.i2]\n" + - " ├─ keys: [mt.i:0!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: othertable\n" + - " └─ columns: [s2 i2]\n" + + ExpectedPlan: "Project\n" + + " ├─ columns: [mt.i:2!null, mt.s:3!null, ot.s2:0!null, ot.i2:1!null]\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(ot)\n" + + " │ └─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: othertable\n" + + " │ └─ columns: [s2 i2]\n" + + " └─ Filter\n" + + " ├─ GreaterThan\n" + + " │ ├─ mt.i:0!null\n" + + " │ └─ 2 (tinyint)\n" + + " └─ TableAlias(mt)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [ot.i2:1!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { @@ -5696,7 +5463,7 @@ inner join pq on true " │ ├─ name: othertable\n" + " │ └─ columns: [s2 i2]\n" + " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + + " ├─ index: [mytable.i,mytable.s]\n" + " ├─ keys: [(othertable.i2:1!null - 1 (tinyint))]\n" + " ├─ colSet: (1,2)\n" + " ├─ tableId: 1\n" + @@ -5708,79 +5475,68 @@ inner join pq on true { Query: `SELECT * FROM tabletest, mytable mt INNER JOIN othertable ot ON mt.i = ot.i2`, ExpectedPlan: "Project\n" + - " ├─ columns: [tabletest.i:0!null, tabletest.s:1!null, mt.i:4!null, mt.s:5!null, ot.s2:2!null, ot.i2:3!null]\n" + + " ├─ columns: [tabletest.i:4!null, tabletest.s:5!null, mt.i:2!null, mt.s:3!null, ot.s2:0!null, ot.i2:1!null]\n" + " └─ CrossHashJoin\n" + - " ├─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: tabletest\n" + - " │ └─ columns: [i s]\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(ot)\n" + + " │ │ └─ ProcessTable\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: othertable\n" + + " │ │ └─ columns: [s2 i2]\n" + + " │ └─ TableAlias(mt)\n" + + " │ └─ IndexedTableAccess(mytable)\n" + + " │ ├─ index: [mytable.i]\n" + + " │ ├─ keys: [ot.i2:1!null]\n" + + " │ ├─ colSet: (3,4)\n" + + " │ ├─ tableId: 2\n" + + " │ └─ Table\n" + + " │ ├─ name: mytable\n" + + " │ └─ columns: [i s]\n" + " └─ HashLookup\n" + " ├─ left-key: TUPLE()\n" + " ├─ right-key: TUPLE()\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ ot.i2:3!null\n" + - " │ └─ mt.i:4!null\n" + - " ├─ TableAlias(ot)\n" + - " │ └─ IndexedTableAccess(othertable)\n" + - " │ ├─ index: [othertable.i2]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (5,6)\n" + - " │ ├─ tableId: 3\n" + - " │ └─ Table\n" + - " │ ├─ name: othertable\n" + - " │ └─ columns: [s2 i2]\n" + - " └─ TableAlias(mt)\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i s]\n" + + " └─ ProcessTable\n" + + " └─ Table\n" + + " ├─ name: tabletest\n" + + " └─ columns: [i s]\n" + "", }, { Query: `SELECT t1.timestamp FROM reservedWordsTable t1 JOIN reservedWordsTable t2 ON t1.TIMESTAMP = t2.tImEstamp`, ExpectedPlan: "Project\n" + - " ├─ columns: [t1.timestamp:0!null]\n" + - " └─ InnerJoin\n" + - " ├─ Eq\n" + - " │ ├─ t1.TIMESTAMP:0!null\n" + - " │ └─ t2.tImEstamp:1!null\n" + - " ├─ TableAlias(t1)\n" + + " ├─ columns: [t1.timestamp:1!null]\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(t2)\n" + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: reservedWordsTable\n" + " │ └─ columns: [timestamp]\n" + - " └─ TableAlias(t2)\n" + - " └─ Table\n" + - " ├─ name: reservedWordsTable\n" + - " ├─ columns: [timestamp]\n" + - " ├─ colSet: (5-8)\n" + - " └─ tableId: 2\n" + + " └─ TableAlias(t1)\n" + + " └─ IndexedTableAccess(reservedWordsTable)\n" + + " ├─ index: [reservedWordsTable.Timestamp]\n" + + " ├─ keys: [t2.tImEstamp:0!null]\n" + + " ├─ colSet: (1-4)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: reservedWordsTable\n" + + " └─ columns: [timestamp]\n" + "", }, { Query: `SELECT pk,pk1,pk2 FROM one_pk JOIN two_pk ON one_pk.pk=two_pk.pk1 AND one_pk.pk=two_pk.pk2`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null, two_pk.pk1:0!null, two_pk.pk2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(two_pk.pk1:0!null, two_pk.pk2:1!null)\n" + - " │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ one_pk.pk:2!null\n" + + " │ └─ two_pk.pk2:1!null\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -5818,23 +5574,19 @@ inner join pq on true Query: `SELECT pk,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON opk.pk=tpk.pk1 AND opk.pk=tpk.pk2`, ExpectedPlan: "Project\n" + " ├─ columns: [opk.pk:2!null, tpk.pk1:0!null, tpk.pk2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(tpk.pk1:0!null, tpk.pk2:1!null)\n" + - " │ └─ TUPLE(opk.pk:2!null, opk.pk:2!null)\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ opk.pk:2!null\n" + + " │ └─ tpk.pk2:1!null\n" + " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + " └─ TableAlias(opk)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [tpk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -5846,21 +5598,17 @@ inner join pq on true Query: `SELECT pk,pk1,pk2 FROM one_pk JOIN two_pk ON one_pk.pk=two_pk.pk1 AND one_pk.pk=two_pk.pk2`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null, two_pk.pk1:0!null, two_pk.pk2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(two_pk.pk1:0!null, two_pk.pk2:1!null)\n" + - " │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ one_pk.pk:2!null\n" + + " │ └─ two_pk.pk2:1!null\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -5891,22 +5639,14 @@ inner join pq on true Query: `SELECT pk,pk1,pk2 FROM one_pk LEFT JOIN two_pk ON one_pk.pk = two_pk.pk1 AND one_pk.pk <=> two_pk.pk2`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null, two_pk.pk1:1!null, two_pk.pk2:2!null]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ two_pk.pk1:1!null\n" + - " ├─ sel: (one_pk.pk:0!null <=> two_pk.pk2:2!null)\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null one_pk.pk:0!null]\n" + " ├─ colSet: (7-13)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -5937,21 +5677,17 @@ inner join pq on true Query: `SELECT pk,pk1,pk2 FROM one_pk RIGHT JOIN two_pk ON one_pk.pk=two_pk.pk1 AND one_pk.pk=two_pk.pk2`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null, two_pk.pk1:0!null, two_pk.pk2:1!null]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(two_pk.pk1:0!null, two_pk.pk2:1!null)\n" + - " │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ one_pk.pk:2!null\n" + + " │ └─ two_pk.pk2:1!null\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -6314,22 +6050,18 @@ inner join pq on true " │ └─ Eq\n" + " │ ├─ tpk.pk2:4!null\n" + " │ └─ tpk2.pk2:1!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ TUPLE(tpk2.pk1:0!null, tpk2.pk2:1!null)\n" + - " │ │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + + " ├─ LookupJoin\n" + + " │ ├─ Eq\n" + + " │ │ ├─ one_pk.pk:2!null\n" + + " │ │ └─ tpk2.pk2:1!null\n" + " │ ├─ TableAlias(tpk2)\n" + - " │ │ └─ IndexedTableAccess(two_pk)\n" + - " │ │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-20)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: two_pk\n" + " │ │ └─ columns: [pk1 pk2]\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [tpk2.pk1:0!null]\n" + " │ ├─ colSet: (1-6)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -6369,22 +6101,18 @@ inner join pq on true " │ └─ Eq\n" + " │ ├─ tpk.pk2:4!null\n" + " │ └─ tpk2.pk2:1!null\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ TUPLE(tpk2.pk1:0!null, tpk2.pk2:1!null)\n" + - " │ │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + + " ├─ LookupJoin\n" + + " │ ├─ Eq\n" + + " │ │ ├─ one_pk.pk:2!null\n" + + " │ │ └─ tpk2.pk2:1!null\n" + " │ ├─ TableAlias(tpk2)\n" + - " │ │ └─ IndexedTableAccess(two_pk)\n" + - " │ │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ ├─ colSet: (14-20)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: two_pk\n" + " │ │ └─ columns: [pk1 pk2]\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [tpk2.pk1:0!null]\n" + " │ ├─ colSet: (1-6)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -6409,22 +6137,18 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null]\n" + " └─ LeftOuterLookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ TUPLE(tpk.pk1:0!null, tpk.pk2:1!null)\n" + - " │ │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + + " ├─ LookupJoin\n" + + " │ ├─ Eq\n" + + " │ │ ├─ one_pk.pk:2!null\n" + + " │ │ └─ tpk.pk2:1!null\n" + " │ ├─ TableAlias(tpk)\n" + - " │ │ └─ IndexedTableAccess(two_pk)\n" + - " │ │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ ├─ colSet: (7-13)\n" + - " │ │ ├─ tableId: 2\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: two_pk\n" + " │ │ └─ columns: [pk1 pk2]\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [tpk.pk1:0!null]\n" + " │ ├─ colSet: (1-6)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -6450,41 +6174,42 @@ inner join pq on true " ├─ columns: [one_pk.pk:0!null, tpk.pk1:6!null, tpk2.pk1:13!null, tpk.pk2:7!null, tpk2.pk2:14!null]\n" + " └─ Sort(one_pk.pk:0!null ASC nullsFirst)\n" + " └─ Project\n" + - " ├─ columns: [one_pk.pk:7!null, one_pk.c1:8, one_pk.c2:9, one_pk.c3:10, one_pk.c4:11, one_pk.c5:12, tpk.pk1:0!null, tpk.pk2:1!null, tpk.c1:2!null, tpk.c2:3!null, tpk.c3:4!null, tpk.c4:5!null, tpk.c5:6!null, tpk2.pk1:13!null, tpk2.pk2:14!null, tpk2.c1:15!null, tpk2.c2:16!null, tpk2.c3:17!null, tpk2.c4:18!null, tpk2.c5:19!null]\n" + + " ├─ columns: [one_pk.pk:14!null, one_pk.c1:15, one_pk.c2:16, one_pk.c3:17, one_pk.c4:18, one_pk.c5:19, tpk.pk1:7!null, tpk.pk2:8!null, tpk.c1:9!null, tpk.c2:10!null, tpk.c3:11!null, tpk.c4:12!null, tpk.c5:13!null, tpk2.pk1:0!null, tpk2.pk2:1!null, tpk2.c1:2!null, tpk2.c2:3!null, tpk2.c3:4!null, tpk2.c4:5!null, tpk2.c5:6!null]\n" + " └─ LookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ tpk.pk1:0!null\n" + - " │ │ └─ one_pk.pk:7!null\n" + - " │ ├─ sel: Eq\n" + - " │ │ ├─ (one_pk.pk:7!null - 1 (tinyint))\n" + - " │ │ └─ tpk.pk2:1!null\n" + - " │ ├─ TableAlias(tpk)\n" + - " │ │ └─ IndexedTableAccess(two_pk)\n" + - " │ │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ ├─ colSet: (7-13)\n" + - " │ │ ├─ tableId: 2\n" + + " ├─ AND\n" + + " │ ├─ AND\n" + + " │ │ ├─ Eq\n" + + " │ │ │ ├─ (one_pk.pk:14!null - 1 (tinyint))\n" + + " │ │ │ └─ tpk.pk2:8!null\n" + + " │ │ └─ Eq\n" + + " │ │ ├─ (one_pk.pk:14!null - 1 (tinyint))\n" + + " │ │ └─ tpk2.pk1:0!null\n" + + " │ └─ Eq\n" + + " │ ├─ one_pk.pk:14!null\n" + + " │ └─ tpk2.pk2:1!null\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(tpk2)\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: two_pk\n" + " │ │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + - " │ └─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: one_pk\n" + - " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + - " └─ TableAlias(tpk2)\n" + - " └─ IndexedTableAccess(two_pk)\n" + - " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ keys: [(one_pk.pk:7!null - 1 (tinyint)) one_pk.pk:7!null]\n" + - " ├─ colSet: (14-20)\n" + - " ├─ tableId: 3\n" + - " └─ Table\n" + - " ├─ name: two_pk\n" + - " └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + + " │ └─ TableAlias(tpk)\n" + + " │ └─ IndexedTableAccess(two_pk)\n" + + " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + + " │ ├─ keys: [tpk2.pk2:1!null]\n" + + " │ ├─ colSet: (7-13)\n" + + " │ ├─ tableId: 2\n" + + " │ └─ Table\n" + + " │ ├─ name: two_pk\n" + + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + + " └─ IndexedTableAccess(one_pk)\n" + + " ├─ index: [one_pk.pk]\n" + + " ├─ keys: [tpk.pk1:7!null]\n" + + " ├─ colSet: (1-6)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: one_pk\n" + + " └─ columns: [pk c1 c2 c3 c4 c5]\n" + "", }, { @@ -6494,25 +6219,15 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null]\n" + " └─ LeftOuterLookupJoin\n" + - " ├─ LeftOuterMergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ one_pk.pk:0!null\n" + - " │ │ └─ tpk.pk1:1!null\n" + - " │ ├─ sel: Eq\n" + - " │ │ ├─ one_pk.pk:0!null\n" + - " │ │ └─ tpk.pk2:2!null\n" + - " │ ├─ IndexedTableAccess(one_pk)\n" + - " │ │ ├─ index: [one_pk.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-6)\n" + - " │ │ ├─ tableId: 1\n" + + " ├─ LeftOuterLookupJoin\n" + + " │ ├─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: one_pk\n" + " │ │ └─ columns: [pk]\n" + " │ └─ TableAlias(tpk)\n" + " │ └─ IndexedTableAccess(two_pk)\n" + " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " │ ├─ keys: [one_pk.pk:0!null one_pk.pk:0!null]\n" + " │ ├─ colSet: (7-13)\n" + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + @@ -6536,25 +6251,15 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null]\n" + " └─ LookupJoin\n" + - " ├─ LeftOuterMergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ one_pk.pk:0!null\n" + - " │ │ └─ tpk.pk1:1!null\n" + - " │ ├─ sel: Eq\n" + - " │ │ ├─ one_pk.pk:0!null\n" + - " │ │ └─ tpk.pk2:2!null\n" + - " │ ├─ IndexedTableAccess(one_pk)\n" + - " │ │ ├─ index: [one_pk.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (1-6)\n" + - " │ │ ├─ tableId: 1\n" + + " ├─ LeftOuterLookupJoin\n" + + " │ ├─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: one_pk\n" + " │ │ └─ columns: [pk]\n" + " │ └─ TableAlias(tpk)\n" + " │ └─ IndexedTableAccess(two_pk)\n" + " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " │ ├─ keys: [one_pk.pk:0!null one_pk.pk:0!null]\n" + " │ ├─ colSet: (7-13)\n" + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + @@ -6578,22 +6283,18 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null]\n" + " └─ LeftOuterLookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ TUPLE(tpk.pk1:0!null, tpk.pk2:1!null)\n" + - " │ │ └─ TUPLE(one_pk.pk:2!null, one_pk.pk:2!null)\n" + + " ├─ LookupJoin\n" + + " │ ├─ Eq\n" + + " │ │ ├─ one_pk.pk:2!null\n" + + " │ │ └─ tpk.pk2:1!null\n" + " │ ├─ TableAlias(tpk)\n" + - " │ │ └─ IndexedTableAccess(two_pk)\n" + - " │ │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ │ ├─ colSet: (7-13)\n" + - " │ │ ├─ tableId: 2\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: two_pk\n" + " │ │ └─ columns: [pk1 pk2]\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [tpk.pk1:0!null]\n" + " │ ├─ colSet: (1-6)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -6616,7 +6317,7 @@ inner join pq on true RIGHT JOIN two_pk tpk2 ON tpk.pk1=TPk2.pk2 AND tpk.pk2=TPK2.pk1`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:4!null]\n" + - " └─ LeftOuterHashJoin\n" + + " └─ LeftOuterJoin\n" + " ├─ AND\n" + " │ ├─ Eq\n" + " │ │ ├─ tpk.pk1:2!null\n" + @@ -6629,30 +6330,24 @@ inner join pq on true " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(tpk2.pk2:1!null, tpk2.pk1:0!null)\n" + - " ├─ right-key: TUPLE(tpk.pk1:0!null, tpk.pk2:1!null)\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(tpk.pk1:2!null, tpk.pk2:3!null)\n" + - " │ └─ TUPLE(one_pk.pk:4!null, one_pk.pk:4!null)\n" + - " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: two_pk\n" + - " │ └─ columns: [pk1 pk2]\n" + - " └─ IndexedTableAccess(one_pk)\n" + - " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (1-6)\n" + - " ├─ tableId: 1\n" + - " └─ Table\n" + - " ├─ name: one_pk\n" + - " └─ columns: [pk]\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ one_pk.pk:4!null\n" + + " │ └─ tpk.pk2:3!null\n" + + " ├─ TableAlias(tpk)\n" + + " │ └─ Table\n" + + " │ ├─ name: two_pk\n" + + " │ ├─ columns: [pk1 pk2]\n" + + " │ ├─ colSet: (7-13)\n" + + " │ └─ tableId: 2\n" + + " └─ IndexedTableAccess(one_pk)\n" + + " ├─ index: [one_pk.pk]\n" + + " ├─ keys: [tpk.pk1:2!null]\n" + + " ├─ colSet: (1-6)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: one_pk\n" + + " └─ columns: [pk]\n" + "", }, { @@ -6676,21 +6371,14 @@ inner join pq on true Query: `SELECT pk,pk1,pk2 FROM one_pk LEFT JOIN two_pk ON pk=pk1`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null, two_pk.pk1:1!null, two_pk.pk2:2!null]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ two_pk.pk1:1!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-13)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6702,21 +6390,14 @@ inner join pq on true Query: `SELECT pk,i,f FROM one_pk LEFT JOIN niltable ON pk=i`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null, niltable.i:1!null, niltable.f:2]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:1!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6795,23 +6476,16 @@ inner join pq on true Query: `SELECT pk,i,f FROM one_pk LEFT JOIN niltable ON pk=i AND f IS NOT NULL`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null, niltable.i:1!null, niltable.f:2]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:1!null\n" + - " ├─ sel: NOT\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ NOT\n" + " │ └─ niltable.f:2 IS NULL\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6855,21 +6529,14 @@ inner join pq on true " └─ Filter\n" + " ├─ NOT\n" + " │ └─ niltable.f:2 IS NULL\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:1!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6885,21 +6552,14 @@ inner join pq on true " ├─ GreaterThan\n" + " │ ├─ niltable.i2:2\n" + " │ └─ 1 (tinyint)\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:1!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6915,21 +6575,14 @@ inner join pq on true " ├─ GreaterThan\n" + " │ ├─ niltable.i:1!null\n" + " │ └─ 1 (tinyint)\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:1!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6941,25 +6594,18 @@ inner join pq on true Query: `SELECT pk,i,f FROM one_pk LEFT JOIN niltable ON pk=i WHERE c1 > 10`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null, niltable.i:2!null, niltable.f:3]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:2!null\n" + + " └─ LeftOuterLookupJoin\n" + " ├─ Filter\n" + " │ ├─ GreaterThan\n" + " │ │ ├─ one_pk.c1:1\n" + " │ │ └─ 10 (tinyint)\n" + - " │ └─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -6971,24 +6617,17 @@ inner join pq on true Query: `SELECT pk,i,f FROM one_pk RIGHT JOIN niltable ON pk=i WHERE f IS NOT NULL`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null, niltable.i:0!null, niltable.f:1]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ niltable.i:0!null\n" + - " │ └─ one_pk.pk:2!null\n" + + " └─ LeftOuterLookupJoin\n" + " ├─ Filter\n" + " │ ├─ NOT\n" + " │ │ └─ niltable.f:1 IS NULL\n" + - " │ └─ IndexedTableAccess(niltable)\n" + - " │ ├─ index: [niltable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (7-10)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: niltable\n" + " │ └─ columns: [i f]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [niltable.i:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7000,25 +6639,18 @@ inner join pq on true Query: `SELECT pk,i,f FROM one_pk LEFT JOIN niltable ON pk=i WHERE pk > 1`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:0!null, niltable.i:1!null, niltable.f:2]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:1!null\n" + - " ├─ Filter\n" + - " │ ├─ GreaterThan\n" + - " │ │ ├─ one_pk.pk:0!null\n" + - " │ │ └─ 1 (tinyint)\n" + - " │ └─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: one_pk\n" + - " │ └─ columns: [pk]\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ IndexedTableAccess(one_pk)\n" + + " │ ├─ index: [one_pk.pk]\n" + + " │ ├─ static: [{(1, ∞)}]\n" + + " │ ├─ colSet: (1-6)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk\n" + + " │ └─ columns: [pk]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -7084,21 +6716,14 @@ inner join pq on true Query: `SELECT pk,pk1,pk2 FROM one_pk JOIN two_pk ON pk=pk1`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null, two_pk.pk1:0!null, two_pk.pk2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ two_pk.pk1:0!null\n" + - " │ └─ one_pk.pk:2!null\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7110,21 +6735,14 @@ inner join pq on true Query: `SELECT /*+ JOIN_ORDER(two_pk, one_pk) */ pk,pk1,pk2 FROM one_pk JOIN two_pk ON pk=pk1`, ExpectedPlan: "Project\n" + " ├─ columns: [one_pk.pk:2!null, two_pk.pk1:0!null, two_pk.pk2:1!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ two_pk.pk1:0!null\n" + - " │ └─ one_pk.pk:2!null\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7139,23 +6757,16 @@ inner join pq on true " └─ Sort(a.pk1:0!null ASC nullsFirst, a.pk2:1!null ASC nullsFirst, b.pk1:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [a.pk1:7!null, a.pk2:8!null, a.c1:9!null, a.c2:10!null, a.c3:11!null, a.c4:12!null, a.c5:13!null, b.pk1:0!null, b.pk2:1!null, b.c1:2!null, b.c2:3!null, b.c3:4!null, b.c4:5!null, b.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(b.pk1:0!null, b.pk2:1!null)\n" + - " │ └─ TUPLE(a.pk1:7!null, a.pk2:8!null)\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (8-14)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [b.pk1:0!null b.pk2:1!null]\n" + " ├─ colSet: (1-7)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7194,23 +6805,16 @@ inner join pq on true " └─ Sort(a.pk1:0!null ASC nullsFirst, a.pk2:1!null ASC nullsFirst, b.pk1:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [a.pk1:7!null, a.pk2:8!null, a.c1:9!null, a.c2:10!null, a.c3:11!null, a.c4:12!null, a.c5:13!null, b.pk1:0!null, b.pk2:1!null, b.c1:2!null, b.c2:3!null, b.c3:4!null, b.c4:5!null, b.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(b.pk1:0!null, b.pk2:1!null)\n" + - " │ └─ TUPLE(a.pk1:7!null, a.pk2:8!null)\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (8-14)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [b.pk1:0!null b.pk2:1!null]\n" + " ├─ colSet: (1-7)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7223,30 +6827,21 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [a.pk1:0!null, a.pk2:1!null, b.pk1:7!null, b.pk2:8!null]\n" + " └─ Sort(a.pk1:0!null ASC nullsFirst, a.pk2:1!null ASC nullsFirst, b.pk1:7!null ASC nullsFirst)\n" + - " └─ Project\n" + - " ├─ columns: [a.pk1:7!null, a.pk2:8!null, a.c1:9!null, a.c2:10!null, a.c3:11!null, a.c4:12!null, a.c5:13!null, b.pk1:0!null, b.pk2:1!null, b.c1:2!null, b.c2:3!null, b.c3:4!null, b.c4:5!null, b.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(b.pk1:0!null, b.pk2:1!null)\n" + - " │ └─ TUPLE((a.pk1:7!null + 1 (tinyint)), (a.pk2:8!null + 1 (tinyint)))\n" + - " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (8-14)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: two_pk\n" + - " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + - " └─ TableAlias(a)\n" + - " └─ IndexedTableAccess(two_pk)\n" + - " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " ├─ colSet: (1-7)\n" + - " ├─ tableId: 1\n" + - " └─ Table\n" + - " ├─ name: two_pk\n" + - " └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(a)\n" + + " │ └─ ProcessTable\n" + + " │ └─ Table\n" + + " │ ├─ name: two_pk\n" + + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + + " └─ TableAlias(b)\n" + + " └─ IndexedTableAccess(two_pk)\n" + + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + + " ├─ keys: [(a.pk1:0!null + 1 (tinyint)) (a.pk2:1!null + 1 (tinyint))]\n" + + " ├─ colSet: (8-14)\n" + + " ├─ tableId: 2\n" + + " └─ Table\n" + + " ├─ name: two_pk\n" + + " └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + "", }, { @@ -7256,23 +6851,16 @@ inner join pq on true " └─ Sort(a.pk1:0!null ASC nullsFirst, a.pk2:1!null ASC nullsFirst, b.pk1:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [a.pk1:7!null, a.pk2:8!null, a.c1:9!null, a.c2:10!null, a.c3:11!null, a.c4:12!null, a.c5:13!null, b.pk1:0!null, b.pk2:1!null, b.c1:2!null, b.c2:3!null, b.c3:4!null, b.c4:5!null, b.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(b.pk1:0!null, b.pk2:1!null)\n" + - " │ └─ TUPLE(a.pk1:7!null, a.pk2:8!null)\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (8-14)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [b.pk1:0!null b.pk2:1!null]\n" + " ├─ colSet: (1-7)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7311,21 +6899,14 @@ inner join pq on true " └─ Sort(one_pk.c5:5 ASC nullsFirst, two_pk.pk1:6!null ASC nullsFirst, two_pk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:7!null, one_pk.c1:8, one_pk.c2:9, one_pk.c3:10, one_pk.c4:11, one_pk.c5:12, two_pk.pk1:0!null, two_pk.pk2:1!null, two_pk.c1:2!null, two_pk.c2:3!null, two_pk.c3:4!null, two_pk.c4:5!null, two_pk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ two_pk.pk1:0!null\n" + - " │ └─ one_pk.pk:7!null\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7340,23 +6921,16 @@ inner join pq on true " └─ Sort(opk.c5:5 ASC nullsFirst, tpk.pk1:6!null ASC nullsFirst, tpk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [opk.pk:7!null, opk.c1:8, opk.c2:9, opk.c3:10, opk.c4:11, opk.c5:12, tpk.pk1:0!null, tpk.pk2:1!null, tpk.c1:2!null, tpk.c2:3!null, tpk.c3:4!null, tpk.c4:5!null, tpk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ tpk.pk1:0!null\n" + - " │ └─ opk.pk:7!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(opk)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [tpk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7371,23 +6945,16 @@ inner join pq on true " └─ Sort(opk.c5:5 ASC nullsFirst, tpk.pk1:6!null ASC nullsFirst, tpk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [opk.pk:7!null, opk.c1:8, opk.c2:9, opk.c3:10, opk.c4:11, opk.c5:12, tpk.pk1:0!null, tpk.pk2:1!null, tpk.c1:2!null, tpk.c2:3!null, tpk.c3:4!null, tpk.c4:5!null, tpk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ tpk.pk1:0!null\n" + - " │ └─ opk.pk:7!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(opk)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [tpk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7402,23 +6969,16 @@ inner join pq on true " └─ Sort(opk.c5:5 ASC nullsFirst, tpk.pk1:6!null ASC nullsFirst, tpk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [opk.pk:7!null, opk.c1:8, opk.c2:9, opk.c3:10, opk.c4:11, opk.c5:12, tpk.pk1:0!null, tpk.pk2:1!null, tpk.c1:2!null, tpk.c2:3!null, tpk.c3:4!null, tpk.c4:5!null, tpk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ tpk.pk1:0!null\n" + - " │ └─ opk.pk:7!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(opk)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [tpk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7433,21 +6993,14 @@ inner join pq on true " └─ Sort(one_pk.c5:5 ASC nullsFirst, two_pk.pk1:6!null ASC nullsFirst, two_pk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:7!null, one_pk.c1:8, one_pk.c2:9, one_pk.c3:10, one_pk.c4:11, one_pk.c5:12, two_pk.pk1:0!null, two_pk.pk2:1!null, two_pk.c1:2!null, two_pk.c2:3!null, two_pk.c3:4!null, two_pk.c4:5!null, two_pk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ two_pk.pk1:0!null\n" + - " │ └─ one_pk.pk:7!null\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7525,21 +7078,14 @@ inner join pq on true " └─ Sort(one_pk.pk:0!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:0!null, one_pk.c1:1, one_pk.c2:2, one_pk.c3:3, one_pk.c4:4, one_pk.c5:5, niltable.i:6!null, niltable.i2:7, niltable.b:8, niltable.f:9]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:6!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -7557,21 +7103,14 @@ inner join pq on true " └─ Filter\n" + " ├─ NOT\n" + " │ └─ niltable.f:9 IS NULL\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:6!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -7586,25 +7125,18 @@ inner join pq on true " └─ Sort(one_pk.pk:0!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:0!null, one_pk.c1:1, one_pk.c2:2, one_pk.c3:3, one_pk.c4:4, one_pk.c5:5, niltable.i:6!null, niltable.i2:7, niltable.b:8, niltable.f:9]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ niltable.i:6!null\n" + - " ├─ Filter\n" + - " │ ├─ GreaterThan\n" + - " │ │ ├─ one_pk.pk:0!null\n" + - " │ │ └─ 1 (tinyint)\n" + - " │ └─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + - " │ └─ Table\n" + - " │ ├─ name: one_pk\n" + - " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ IndexedTableAccess(one_pk)\n" + + " │ ├─ index: [one_pk.pk]\n" + + " │ ├─ static: [{(1, ∞)}]\n" + + " │ ├─ colSet: (1-6)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk\n" + + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(niltable)\n" + " ├─ index: [niltable.i]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-10)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -7648,24 +7180,17 @@ inner join pq on true " └─ Sort(niltable.i:6!null ASC nullsFirst, niltable.f:9 ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:4!null, one_pk.c1:5, one_pk.c2:6, one_pk.c3:7, one_pk.c4:8, one_pk.c5:9, niltable.i:0!null, niltable.i2:1, niltable.b:2, niltable.f:3]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ niltable.i:0!null\n" + - " │ └─ one_pk.pk:4!null\n" + + " └─ LeftOuterLookupJoin\n" + " ├─ Filter\n" + " │ ├─ NOT\n" + " │ │ └─ niltable.f:3 IS NULL\n" + - " │ └─ IndexedTableAccess(niltable)\n" + - " │ ├─ index: [niltable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (7-10)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: niltable\n" + " │ └─ columns: [i i2 b f]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [niltable.i:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7745,21 +7270,17 @@ inner join pq on true " └─ Sort(one_pk.pk:0!null ASC nullsFirst, two_pk.pk1:6!null ASC nullsFirst, two_pk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:7!null, one_pk.c1:8, one_pk.c2:9, one_pk.c3:10, one_pk.c4:11, one_pk.c5:12, two_pk.pk1:0!null, two_pk.pk2:1!null, two_pk.c1:2!null, two_pk.c2:3!null, two_pk.c3:4!null, two_pk.c4:5!null, two_pk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(two_pk.pk1:0!null, two_pk.pk2:1!null)\n" + - " │ └─ TUPLE(one_pk.pk:7!null, one_pk.pk:7!null)\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ one_pk.pk:7!null\n" + + " │ └─ two_pk.pk2:1!null\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7815,24 +7336,14 @@ inner join pq on true " └─ Sort(one_pk.pk:0!null ASC nullsFirst, two_pk.pk1:6!null ASC nullsFirst, two_pk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:0!null, one_pk.c1:1, one_pk.c2:2, one_pk.c3:3, one_pk.c4:4, one_pk.c5:5, two_pk.pk1:6!null, two_pk.pk2:7!null, two_pk.c1:8!null, two_pk.c2:9!null, two_pk.c3:10!null, two_pk.c4:11!null, two_pk.c5:12!null]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ two_pk.pk1:6!null\n" + - " ├─ sel: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ two_pk.pk2:7!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null one_pk.pk:0!null]\n" + " ├─ colSet: (7-13)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -7847,21 +7358,14 @@ inner join pq on true " └─ Sort(one_pk.pk:0!null ASC nullsFirst, two_pk.pk1:6!null ASC nullsFirst, two_pk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:0!null, one_pk.c1:1, one_pk.c2:2, one_pk.c3:3, one_pk.c4:4, one_pk.c5:5, two_pk.pk1:6!null, two_pk.pk2:7!null, two_pk.c1:8!null, two_pk.c2:9!null, two_pk.c3:10!null, two_pk.c4:11!null, two_pk.c5:12!null]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ one_pk.pk:0!null\n" + - " │ └─ two_pk.pk1:6!null\n" + - " ├─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-6)\n" + - " │ ├─ tableId: 1\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: one_pk\n" + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(two_pk)\n" + " ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + + " ├─ keys: [one_pk.pk:0!null]\n" + " ├─ colSet: (7-13)\n" + " ├─ tableId: 2\n" + " └─ Table\n" + @@ -7876,21 +7380,17 @@ inner join pq on true " └─ Sort(one_pk.pk:0!null ASC nullsFirst, two_pk.pk1:6!null ASC nullsFirst, two_pk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:7!null, one_pk.c1:8, one_pk.c2:9, one_pk.c3:10, one_pk.c4:11, one_pk.c5:12, two_pk.pk1:0!null, two_pk.pk2:1!null, two_pk.c1:2!null, two_pk.c2:3!null, two_pk.c3:4!null, two_pk.c4:5!null, two_pk.c5:6!null]\n" + - " └─ LeftOuterMergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(two_pk.pk1:0!null, two_pk.pk2:1!null)\n" + - " │ └─ TUPLE(one_pk.pk:7!null, one_pk.pk:7!null)\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LeftOuterLookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ one_pk.pk:7!null\n" + + " │ └─ two_pk.pk2:1!null\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7905,23 +7405,19 @@ inner join pq on true " └─ Sort(opk.pk:0!null ASC nullsFirst, tpk.pk1:6!null ASC nullsFirst, tpk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [opk.pk:7!null, opk.c1:8, opk.c2:9, opk.c3:10, opk.c4:11, opk.c5:12, tpk.pk1:0!null, tpk.pk2:1!null, tpk.c1:2!null, tpk.c2:3!null, tpk.c3:4!null, tpk.c4:5!null, tpk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(tpk.pk1:0!null, tpk.pk2:1!null)\n" + - " │ └─ TUPLE(opk.pk:7!null, opk.pk:7!null)\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ opk.pk:7!null\n" + + " │ └─ tpk.pk2:1!null\n" + " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(opk)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [tpk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -7936,23 +7432,19 @@ inner join pq on true " └─ Sort(opk.pk:0!null ASC nullsFirst, tpk.pk1:6!null ASC nullsFirst, tpk.pk2:7!null ASC nullsFirst)\n" + " └─ Project\n" + " ├─ columns: [opk.pk:7!null, opk.c1:8, opk.c2:9, opk.c3:10, opk.c4:11, opk.c5:12, tpk.pk1:0!null, tpk.pk2:1!null, tpk.c1:2!null, tpk.c2:3!null, tpk.c3:4!null, tpk.c4:5!null, tpk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ TUPLE(tpk.pk1:0!null, tpk.pk2:1!null)\n" + - " │ └─ TUPLE(opk.pk:7!null, opk.pk:7!null)\n" + + " └─ LookupJoin\n" + + " ├─ Eq\n" + + " │ ├─ opk.pk:7!null\n" + + " │ └─ tpk.pk2:1!null\n" + " ├─ TableAlias(tpk)\n" + - " │ └─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ TableAlias(opk)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [tpk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -8038,30 +7530,28 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [t1.pk:0!null, t2.pk2:7!null]\n" + " └─ Sort(t1.pk:0!null ASC nullsFirst, t2.pk2:7!null ASC nullsFirst)\n" + - " └─ Project\n" + - " ├─ columns: [t1.pk:7!null, t1.c1:8, t1.c2:9, t1.c3:10, t1.c4:11, t1.c5:12, t2.pk1:0!null, t2.pk2:1!null, t2.c1:2!null, t2.c2:3!null, t2.c3:4!null, t2.c4:5!null, t2.c5:6!null]\n" + - " └─ CrossHashJoin\n" + - " ├─ Filter\n" + - " │ ├─ Eq\n" + - " │ │ ├─ t2.pk2:1!null\n" + - " │ │ └─ 1 (tinyint)\n" + - " │ └─ TableAlias(t2)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: two_pk\n" + - " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE()\n" + - " ├─ right-key: TUPLE()\n" + - " └─ TableAlias(t1)\n" + - " └─ IndexedTableAccess(one_pk)\n" + - " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[1, 1]}]\n" + - " ├─ colSet: (1-6)\n" + - " ├─ tableId: 1\n" + + " └─ CrossHashJoin\n" + + " ├─ TableAlias(t1)\n" + + " │ └─ IndexedTableAccess(one_pk)\n" + + " │ ├─ index: [one_pk.pk]\n" + + " │ ├─ static: [{[1, 1]}]\n" + + " │ ├─ colSet: (1-6)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk\n" + + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE()\n" + + " ├─ right-key: TUPLE()\n" + + " └─ Filter\n" + + " ├─ Eq\n" + + " │ ├─ t2.pk2:1!null\n" + + " │ └─ 1 (tinyint)\n" + + " └─ TableAlias(t2)\n" + + " └─ ProcessTable\n" + " └─ Table\n" + - " ├─ name: one_pk\n" + - " └─ columns: [pk c1 c2 c3 c4 c5]\n" + + " ├─ name: two_pk\n" + + " └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + "", }, { @@ -8214,30 +7704,28 @@ inner join pq on true " │ └─ columns: [pk]\n" + " │ as (SELECT pk from one_pk where pk = 1 limit 1)]\n" + " └─ Sort(t1.pk:0!null ASC nullsFirst, t2.pk2:7!null ASC nullsFirst)\n" + - " └─ Project\n" + - " ├─ columns: [t1.pk:7!null, t1.c1:8, t1.c2:9, t1.c3:10, t1.c4:11, t1.c5:12, t2.pk1:0!null, t2.pk2:1!null, t2.c1:2!null, t2.c2:3!null, t2.c3:4!null, t2.c4:5!null, t2.c5:6!null]\n" + - " └─ CrossHashJoin\n" + - " ├─ Filter\n" + - " │ ├─ Eq\n" + - " │ │ ├─ t2.pk2:1!null\n" + - " │ │ └─ 1 (tinyint)\n" + - " │ └─ TableAlias(t2)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: two_pk\n" + - " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE()\n" + - " ├─ right-key: TUPLE()\n" + - " └─ TableAlias(t1)\n" + - " └─ IndexedTableAccess(one_pk)\n" + - " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[1, 1]}]\n" + - " ├─ colSet: (1-6)\n" + - " ├─ tableId: 1\n" + + " └─ CrossHashJoin\n" + + " ├─ TableAlias(t1)\n" + + " │ └─ IndexedTableAccess(one_pk)\n" + + " │ ├─ index: [one_pk.pk]\n" + + " │ ├─ static: [{[1, 1]}]\n" + + " │ ├─ colSet: (1-6)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk\n" + + " │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE()\n" + + " ├─ right-key: TUPLE()\n" + + " └─ Filter\n" + + " ├─ Eq\n" + + " │ ├─ t2.pk2:1!null\n" + + " │ └─ 1 (tinyint)\n" + + " └─ TableAlias(t2)\n" + + " └─ ProcessTable\n" + " └─ Table\n" + - " ├─ name: one_pk\n" + - " └─ columns: [pk c1 c2 c3 c4 c5]\n" + + " ├─ name: two_pk\n" + + " └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + "", }, { @@ -8456,21 +7944,14 @@ inner join pq on true " └─ UpdateSource(SET two_pk.c1:8!null = (two_pk.c1:8!null + 1 (tinyint)))\n" + " └─ Project\n" + " ├─ columns: [one_pk.pk:7!null, one_pk.c1:8, one_pk.c2:9, one_pk.c3:10, one_pk.c4:11, one_pk.c5:12, two_pk.pk1:0!null, two_pk.pk2:1!null, two_pk.c1:2!null, two_pk.c2:3!null, two_pk.c3:4!null, two_pk.c4:5!null, two_pk.c5:6!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ two_pk.pk1:0!null\n" + - " │ └─ one_pk.pk:7!null\n" + - " ├─ IndexedTableAccess(two_pk)\n" + - " │ ├─ index: [two_pk.pk1,two_pk.pk2]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (7-13)\n" + - " │ ├─ tableId: 2\n" + + " └─ LookupJoin\n" + + " ├─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: two_pk\n" + " │ └─ columns: [pk1 pk2 c1 c2 c3 c4 c5]\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [two_pk.pk1:0!null]\n" + " ├─ colSet: (1-6)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -8682,23 +8163,16 @@ inner join pq on true ExpectedPlan: "Project\n" + " ├─ columns: [a.pk:1!null, a.c1:2, a.c2:3, a.c3:4, a.c4:5, a.c5:6]\n" + " └─ LookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ b.pk:0!null\n" + - " │ │ └─ a.pk:1!null\n" + + " ├─ LookupJoin\n" + " │ ├─ TableAlias(b)\n" + - " │ │ └─ IndexedTableAccess(one_pk)\n" + - " │ │ ├─ index: [one_pk.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (13-18)\n" + - " │ │ ├─ tableId: 3\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: one_pk\n" + " │ │ └─ columns: [pk]\n" + " │ └─ TableAlias(a)\n" + " │ └─ IndexedTableAccess(one_pk)\n" + " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ keys: [b.pk:0!null]\n" + " │ ├─ colSet: (1-6)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -8718,43 +8192,37 @@ inner join pq on true { Query: `SELECT a.* FROM one_pk a CROSS JOIN one_pk b INNER JOIN one_pk c ON b.pk = c.pk LEFT JOIN one_pk d ON c.pk = d.pk`, ExpectedPlan: "Project\n" + - " ├─ columns: [a.pk:0!null, a.c1:1, a.c2:2, a.c3:3, a.c4:4, a.c5:5]\n" + + " ├─ columns: [a.pk:1!null, a.c1:2, a.c2:3, a.c3:4, a.c4:5, a.c5:6]\n" + " └─ LeftOuterLookupJoin\n" + - " ├─ CrossHashJoin\n" + - " │ ├─ TableAlias(a)\n" + - " │ │ └─ ProcessTable\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: one_pk\n" + - " │ │ └─ columns: [pk c1 c2 c3 c4 c5]\n" + - " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE()\n" + - " │ ├─ right-key: TUPLE()\n" + - " │ └─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ c.pk:6!null\n" + - " │ │ └─ b.pk:7!null\n" + - " │ ├─ TableAlias(c)\n" + - " │ │ └─ IndexedTableAccess(one_pk)\n" + - " │ │ ├─ index: [one_pk.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (13-18)\n" + - " │ │ ├─ tableId: 3\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: one_pk\n" + - " │ │ └─ columns: [pk]\n" + - " │ └─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(one_pk)\n" + - " │ ├─ index: [one_pk.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (7-12)\n" + - " │ ├─ tableId: 2\n" + - " │ └─ Table\n" + - " │ ├─ name: one_pk\n" + - " │ └─ columns: [pk]\n" + + " ├─ LookupJoin\n" + + " │ ├─ CrossHashJoin\n" + + " │ │ ├─ TableAlias(b)\n" + + " │ │ │ └─ ProcessTable\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: one_pk\n" + + " │ │ │ └─ columns: [pk]\n" + + " │ │ └─ HashLookup\n" + + " │ │ ├─ left-key: TUPLE()\n" + + " │ │ ├─ right-key: TUPLE()\n" + + " │ │ └─ TableAlias(a)\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: one_pk\n" + + " │ │ ├─ columns: [pk c1 c2 c3 c4 c5]\n" + + " │ │ ├─ colSet: (1-6)\n" + + " │ │ └─ tableId: 1\n" + + " │ └─ TableAlias(c)\n" + + " │ └─ IndexedTableAccess(one_pk)\n" + + " │ ├─ index: [one_pk.pk]\n" + + " │ ├─ keys: [b.pk:0!null]\n" + + " │ ├─ colSet: (13-18)\n" + + " │ ├─ tableId: 3\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk\n" + + " │ └─ columns: [pk]\n" + " └─ TableAlias(d)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ keys: [c.pk:6!null]\n" + + " ├─ keys: [c.pk:7!null]\n" + " ├─ colSet: (19-24)\n" + " ├─ tableId: 4\n" + " └─ Table\n" + @@ -8970,23 +8438,17 @@ inner join pq on true " ├─ Eq\n" + " │ ├─ a.i:2!null\n" + " │ └─ (c.i:4!null - 1 (tinyint))\n" + - " ├─ LeftOuterMergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ (b.i:1!null + 1 (tinyint))\n" + - " │ │ └─ a.i:2!null\n" + + " ├─ LeftOuterLookupJoin\n" + " │ ├─ TableAlias(b)\n" + - " │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: mytable\n" + + " │ │ ├─ columns: [i]\n" + " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: mytable\n" + - " │ │ └─ columns: [i]\n" + + " │ │ └─ tableId: 2\n" + " │ └─ TableAlias(a)\n" + " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ index: [mytable.i,mytable.s]\n" + + " │ ├─ keys: [(b.i:1!null + 1 (tinyint))]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -9009,23 +8471,16 @@ inner join pq on true " │ ├─ Eq\n" + " │ │ ├─ a.i:2!null\n" + " │ │ └─ (c.i:4!null - 1 (tinyint))\n" + - " │ ├─ LeftOuterMergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ (b.i2:1!null + 1 (tinyint))\n" + - " │ │ │ └─ a.i:2!null\n" + + " │ ├─ LeftOuterLookupJoin\n" + " │ │ ├─ TableAlias(b)\n" + - " │ │ │ └─ IndexedTableAccess(othertable)\n" + - " │ │ │ ├─ index: [othertable.i2]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (3,4)\n" + - " │ │ │ ├─ tableId: 2\n" + + " │ │ │ └─ ProcessTable\n" + " │ │ │ └─ Table\n" + " │ │ │ ├─ name: othertable\n" + " │ │ │ └─ columns: [s2 i2]\n" + " │ │ └─ TableAlias(a)\n" + " │ │ └─ IndexedTableAccess(mytable)\n" + - " │ │ ├─ index: [mytable.i]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + + " │ │ ├─ index: [mytable.i,mytable.s]\n" + + " │ │ ├─ keys: [(b.i2:1!null + 1 (tinyint))]\n" + " │ │ ├─ colSet: (1,2)\n" + " │ │ ├─ tableId: 1\n" + " │ │ └─ Table\n" + @@ -9061,23 +8516,16 @@ inner join pq on true " │ │ └─ Table\n" + " │ │ ├─ name: mytable\n" + " │ │ └─ columns: [i]\n" + - " │ └─ LeftOuterMergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ (b.i2:2!null + 1 (tinyint))\n" + - " │ │ └─ a.i:3!null\n" + + " │ └─ LeftOuterLookupJoin\n" + " │ ├─ TableAlias(b)\n" + - " │ │ └─ IndexedTableAccess(othertable)\n" + - " │ │ ├─ index: [othertable.i2]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (3,4)\n" + - " │ │ ├─ tableId: 2\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + " │ │ ├─ name: othertable\n" + " │ │ └─ columns: [s2 i2]\n" + " │ └─ TableAlias(a)\n" + " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + + " │ ├─ index: [mytable.i,mytable.s]\n" + + " │ ├─ keys: [(b.i2:2!null + 1 (tinyint))]\n" + " │ ├─ colSet: (1,2)\n" + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + @@ -9097,62 +8545,48 @@ inner join pq on true { Query: `select i.pk, j.v3 from one_pk_two_idx i JOIN one_pk_three_idx j on i.v1 = j.pk;`, ExpectedPlan: "Project\n" + - " ├─ columns: [i.pk:2!null, j.v3:1]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ j.pk:0!null\n" + - " │ └─ i.v1:3\n" + - " ├─ TableAlias(j)\n" + - " │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (4-7)\n" + - " │ ├─ tableId: 2\n" + + " ├─ columns: [i.pk:0!null, j.v3:3]\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(i)\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + - " │ ├─ name: one_pk_three_idx\n" + - " │ └─ columns: [pk v3]\n" + - " └─ TableAlias(i)\n" + - " └─ IndexedTableAccess(one_pk_two_idx)\n" + - " ├─ index: [one_pk_two_idx.v1]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (1-3)\n" + - " ├─ tableId: 1\n" + + " │ ├─ name: one_pk_two_idx\n" + + " │ └─ columns: [pk v1]\n" + + " └─ TableAlias(j)\n" + + " └─ IndexedTableAccess(one_pk_three_idx)\n" + + " ├─ index: [one_pk_three_idx.pk]\n" + + " ├─ keys: [i.v1:1]\n" + + " ├─ colSet: (4-7)\n" + + " ├─ tableId: 2\n" + " └─ Table\n" + - " ├─ name: one_pk_two_idx\n" + - " └─ columns: [pk v1]\n" + + " ├─ name: one_pk_three_idx\n" + + " └─ columns: [pk v3]\n" + "", }, { Query: `select i.pk, j.v3, k.c1 from one_pk_two_idx i JOIN one_pk_three_idx j on i.v1 = j.pk JOIN one_pk k on j.v3 = k.pk;`, ExpectedPlan: "Project\n" + - " ├─ columns: [i.pk:2!null, j.v3:1, k.c1:5]\n" + + " ├─ columns: [i.pk:0!null, j.v3:3, k.c1:5]\n" + " └─ LookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ j.pk:0!null\n" + - " │ │ └─ i.v1:3\n" + - " │ ├─ TableAlias(j)\n" + - " │ │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (4-7)\n" + - " │ │ ├─ tableId: 2\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(i)\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: one_pk_three_idx\n" + - " │ │ └─ columns: [pk v3]\n" + - " │ └─ TableAlias(i)\n" + - " │ └─ IndexedTableAccess(one_pk_two_idx)\n" + - " │ ├─ index: [one_pk_two_idx.v1]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-3)\n" + - " │ ├─ tableId: 1\n" + + " │ │ ├─ name: one_pk_two_idx\n" + + " │ │ └─ columns: [pk v1]\n" + + " │ └─ TableAlias(j)\n" + + " │ └─ IndexedTableAccess(one_pk_three_idx)\n" + + " │ ├─ index: [one_pk_three_idx.pk]\n" + + " │ ├─ keys: [i.v1:1]\n" + + " │ ├─ colSet: (4-7)\n" + + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + - " │ ├─ name: one_pk_two_idx\n" + - " │ └─ columns: [pk v1]\n" + + " │ ├─ name: one_pk_three_idx\n" + + " │ └─ columns: [pk v3]\n" + " └─ TableAlias(k)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ keys: [j.v3:1]\n" + + " ├─ keys: [j.v3:3]\n" + " ├─ colSet: (8-13)\n" + " ├─ tableId: 3\n" + " └─ Table\n" + @@ -9163,62 +8597,48 @@ inner join pq on true { Query: `select i.pk, j.v3 from (one_pk_two_idx i JOIN one_pk_three_idx j on((i.v1 = j.pk)));`, ExpectedPlan: "Project\n" + - " ├─ columns: [i.pk:2!null, j.v3:1]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ j.pk:0!null\n" + - " │ └─ i.v1:3\n" + - " ├─ TableAlias(j)\n" + - " │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (4-7)\n" + - " │ ├─ tableId: 2\n" + + " ├─ columns: [i.pk:0!null, j.v3:3]\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(i)\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + - " │ ├─ name: one_pk_three_idx\n" + - " │ └─ columns: [pk v3]\n" + - " └─ TableAlias(i)\n" + - " └─ IndexedTableAccess(one_pk_two_idx)\n" + - " ├─ index: [one_pk_two_idx.v1]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (1-3)\n" + - " ├─ tableId: 1\n" + + " │ ├─ name: one_pk_two_idx\n" + + " │ └─ columns: [pk v1]\n" + + " └─ TableAlias(j)\n" + + " └─ IndexedTableAccess(one_pk_three_idx)\n" + + " ├─ index: [one_pk_three_idx.pk]\n" + + " ├─ keys: [i.v1:1]\n" + + " ├─ colSet: (4-7)\n" + + " ├─ tableId: 2\n" + " └─ Table\n" + - " ├─ name: one_pk_two_idx\n" + - " └─ columns: [pk v1]\n" + + " ├─ name: one_pk_three_idx\n" + + " └─ columns: [pk v3]\n" + "", }, { Query: `select i.pk, j.v3, k.c1 from ((one_pk_two_idx i JOIN one_pk_three_idx j on ((i.v1 = j.pk))) JOIN one_pk k on((j.v3 = k.pk)));`, ExpectedPlan: "Project\n" + - " ├─ columns: [i.pk:2!null, j.v3:1, k.c1:5]\n" + + " ├─ columns: [i.pk:0!null, j.v3:3, k.c1:5]\n" + " └─ LookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ j.pk:0!null\n" + - " │ │ └─ i.v1:3\n" + - " │ ├─ TableAlias(j)\n" + - " │ │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (4-7)\n" + - " │ │ ├─ tableId: 2\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(i)\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: one_pk_three_idx\n" + - " │ │ └─ columns: [pk v3]\n" + - " │ └─ TableAlias(i)\n" + - " │ └─ IndexedTableAccess(one_pk_two_idx)\n" + - " │ ├─ index: [one_pk_two_idx.v1]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-3)\n" + - " │ ├─ tableId: 1\n" + + " │ │ ├─ name: one_pk_two_idx\n" + + " │ │ └─ columns: [pk v1]\n" + + " │ └─ TableAlias(j)\n" + + " │ └─ IndexedTableAccess(one_pk_three_idx)\n" + + " │ ├─ index: [one_pk_three_idx.pk]\n" + + " │ ├─ keys: [i.v1:1]\n" + + " │ ├─ colSet: (4-7)\n" + + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + - " │ ├─ name: one_pk_two_idx\n" + - " │ └─ columns: [pk v1]\n" + + " │ ├─ name: one_pk_three_idx\n" + + " │ └─ columns: [pk v3]\n" + " └─ TableAlias(k)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ keys: [j.v3:1]\n" + + " ├─ keys: [j.v3:3]\n" + " ├─ colSet: (8-13)\n" + " ├─ tableId: 3\n" + " └─ Table\n" + @@ -9229,34 +8649,27 @@ inner join pq on true { Query: `select i.pk, j.v3, k.c1 from (one_pk_two_idx i JOIN one_pk_three_idx j on ((i.v1 = j.pk)) JOIN one_pk k on((j.v3 = k.pk)))`, ExpectedPlan: "Project\n" + - " ├─ columns: [i.pk:2!null, j.v3:1, k.c1:5]\n" + + " ├─ columns: [i.pk:0!null, j.v3:3, k.c1:5]\n" + " └─ LookupJoin\n" + - " ├─ MergeJoin\n" + - " │ ├─ cmp: Eq\n" + - " │ │ ├─ j.pk:0!null\n" + - " │ │ └─ i.v1:3\n" + - " │ ├─ TableAlias(j)\n" + - " │ │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (4-7)\n" + - " │ │ ├─ tableId: 2\n" + + " ├─ LookupJoin\n" + + " │ ├─ TableAlias(i)\n" + + " │ │ └─ ProcessTable\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: one_pk_three_idx\n" + - " │ │ └─ columns: [pk v3]\n" + - " │ └─ TableAlias(i)\n" + - " │ └─ IndexedTableAccess(one_pk_two_idx)\n" + - " │ ├─ index: [one_pk_two_idx.v1]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (1-3)\n" + - " │ ├─ tableId: 1\n" + + " │ │ ├─ name: one_pk_two_idx\n" + + " │ │ └─ columns: [pk v1]\n" + + " │ └─ TableAlias(j)\n" + + " │ └─ IndexedTableAccess(one_pk_three_idx)\n" + + " │ ├─ index: [one_pk_three_idx.pk]\n" + + " │ ├─ keys: [i.v1:1]\n" + + " │ ├─ colSet: (4-7)\n" + + " │ ├─ tableId: 2\n" + " │ └─ Table\n" + - " │ ├─ name: one_pk_two_idx\n" + - " │ └─ columns: [pk v1]\n" + + " │ ├─ name: one_pk_three_idx\n" + + " │ └─ columns: [pk v3]\n" + " └─ TableAlias(k)\n" + " └─ IndexedTableAccess(one_pk)\n" + " ├─ index: [one_pk.pk]\n" + - " ├─ keys: [j.v3:1]\n" + + " ├─ keys: [j.v3:3]\n" + " ├─ colSet: (8-13)\n" + " ├─ tableId: 3\n" + " └─ Table\n" + @@ -9271,66 +8684,51 @@ inner join pq on true " └─ LeftOuterHashJoin\n" + " ├─ Eq\n" + " │ ├─ a.pk:2!null\n" + - " │ └─ l.v2:6\n" + - " ├─ LeftOuterHashJoin\n" + - " │ ├─ Eq\n" + - " │ │ ├─ a.pk:2!null\n" + - " │ │ └─ i.v1:1\n" + - " │ ├─ MergeJoin\n" + - " │ │ ├─ cmp: Eq\n" + - " │ │ │ ├─ j.pk:0!null\n" + - " │ │ │ └─ i.v1:1\n" + - " │ │ ├─ TableAlias(j)\n" + - " │ │ │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ │ │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ │ ├─ colSet: (7-10)\n" + - " │ │ │ ├─ tableId: 3\n" + + " │ └─ l.v2:7\n" + + " ├─ LeftOuterLookupJoin\n" + + " │ ├─ LookupJoin\n" + + " │ │ ├─ TableAlias(i)\n" + + " │ │ │ └─ ProcessTable\n" + " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: one_pk_three_idx\n" + - " │ │ │ └─ columns: [pk]\n" + - " │ │ └─ TableAlias(i)\n" + - " │ │ └─ IndexedTableAccess(one_pk_two_idx)\n" + - " │ │ ├─ index: [one_pk_two_idx.v1]\n" + - " │ │ ├─ static: [{[NULL, ∞)}]\n" + - " │ │ ├─ colSet: (4-6)\n" + - " │ │ ├─ tableId: 2\n" + + " │ │ │ ├─ name: one_pk_two_idx\n" + + " │ │ │ └─ columns: [v1]\n" + + " │ │ └─ TableAlias(j)\n" + + " │ │ └─ IndexedTableAccess(one_pk_three_idx)\n" + + " │ │ ├─ index: [one_pk_three_idx.pk]\n" + + " │ │ ├─ keys: [i.v1:0]\n" + + " │ │ ├─ colSet: (7-10)\n" + + " │ │ ├─ tableId: 3\n" + " │ │ └─ Table\n" + - " │ │ ├─ name: one_pk_two_idx\n" + - " │ │ └─ columns: [v1]\n" + - " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(i.v1:1)\n" + - " │ ├─ right-key: TUPLE(a.pk:0!null)\n" + - " │ └─ TableAlias(a)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: one_pk_two_idx\n" + - " │ └─ columns: [pk v1 v2]\n" + + " │ │ ├─ name: one_pk_three_idx\n" + + " │ │ └─ columns: [pk]\n" + + " │ └─ TableAlias(a)\n" + + " │ └─ IndexedTableAccess(one_pk_two_idx)\n" + + " │ ├─ index: [one_pk_two_idx.pk]\n" + + " │ ├─ keys: [i.v1:0]\n" + + " │ ├─ colSet: (1-3)\n" + + " │ ├─ tableId: 1\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk_two_idx\n" + + " │ └─ columns: [pk v1 v2]\n" + " └─ HashLookup\n" + " ├─ left-key: TUPLE(a.pk:2!null)\n" + - " ├─ right-key: TUPLE(l.v2:1)\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ l.pk:5!null\n" + - " │ └─ k.v1:7\n" + - " ├─ TableAlias(l)\n" + - " │ └─ IndexedTableAccess(one_pk_three_idx)\n" + - " │ ├─ index: [one_pk_three_idx.pk]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (14-17)\n" + - " │ ├─ tableId: 5\n" + - " │ └─ Table\n" + - " │ ├─ name: one_pk_three_idx\n" + - " │ └─ columns: [pk v2]\n" + - " └─ TableAlias(k)\n" + - " └─ IndexedTableAccess(one_pk_two_idx)\n" + - " ├─ index: [one_pk_two_idx.v1]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + - " ├─ colSet: (11-13)\n" + - " ├─ tableId: 4\n" + + " ├─ right-key: TUPLE(l.v2:2)\n" + + " └─ LookupJoin\n" + + " ├─ TableAlias(k)\n" + + " │ └─ Table\n" + + " │ ├─ name: one_pk_two_idx\n" + + " │ ├─ columns: [v1]\n" + + " │ ├─ colSet: (11-13)\n" + + " │ └─ tableId: 4\n" + + " └─ TableAlias(l)\n" + + " └─ IndexedTableAccess(one_pk_three_idx)\n" + + " ├─ index: [one_pk_three_idx.pk]\n" + + " ├─ keys: [k.v1:5]\n" + + " ├─ colSet: (14-17)\n" + + " ├─ tableId: 5\n" + " └─ Table\n" + - " ├─ name: one_pk_two_idx\n" + - " └─ columns: [v1]\n" + + " ├─ name: one_pk_three_idx\n" + + " └─ columns: [pk v2]\n" + "", }, { @@ -9395,26 +8793,26 @@ inner join pq on true { Query: `select a.* from mytable a join mytable b on a.i = b.i and a.i > 2`, ExpectedPlan: "Project\n" + - " ├─ columns: [a.i:0!null, a.s:1!null]\n" + + " ├─ columns: [a.i:1!null, a.s:2!null]\n" + " └─ LookupJoin\n" + - " ├─ TableAlias(a)\n" + - " │ └─ IndexedTableAccess(mytable)\n" + - " │ ├─ index: [mytable.i]\n" + - " │ ├─ static: [{(2, ∞)}]\n" + - " │ ├─ colSet: (1,2)\n" + - " │ ├─ tableId: 1\n" + + " ├─ TableAlias(b)\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: mytable\n" + - " │ └─ columns: [i s]\n" + - " └─ TableAlias(b)\n" + - " └─ IndexedTableAccess(mytable)\n" + - " ├─ index: [mytable.i]\n" + - " ├─ keys: [a.i:0!null]\n" + - " ├─ colSet: (3,4)\n" + - " ├─ tableId: 2\n" + - " └─ Table\n" + - " ├─ name: mytable\n" + - " └─ columns: [i]\n" + + " │ └─ columns: [i]\n" + + " └─ Filter\n" + + " ├─ GreaterThan\n" + + " │ ├─ a.i:0!null\n" + + " │ └─ 2 (tinyint)\n" + + " └─ TableAlias(a)\n" + + " └─ IndexedTableAccess(mytable)\n" + + " ├─ index: [mytable.i]\n" + + " ├─ keys: [b.i:0!null]\n" + + " ├─ colSet: (1,2)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: mytable\n" + + " └─ columns: [i s]\n" + "", }, { diff --git a/enginetest/queries/script_queries.go b/enginetest/queries/script_queries.go index 706f18703c..2827902c1f 100644 --- a/enginetest/queries/script_queries.go +++ b/enginetest/queries/script_queries.go @@ -112,6 +112,7 @@ var ScriptTests = []ScriptTest{ Name: "filter pushdown through join uppercase name", SetUpScript: []string{ "create table A (A int primary key);", + "insert into A values (0),(1)", }, Assertions: []ScriptTestAssertion{ { diff --git a/enginetest/queries/sysbench_plans.go b/enginetest/queries/sysbench_plans.go index fb0044fb2d..b435c3c74e 100644 --- a/enginetest/queries/sysbench_plans.go +++ b/enginetest/queries/sysbench_plans.go @@ -22,23 +22,16 @@ var SysbenchPlanTests = []QueryPlanTest{ ExpectedPlan: "Limit(500)\n" + " └─ Project\n" + " ├─ columns: [a.id:1!null, a.small_int_col:2!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ b.id:0!null\n" + - " │ └─ a.id:1!null\n" + + " └─ LookupJoin\n" + " ├─ TableAlias(b)\n" + - " │ └─ IndexedTableAccess(sbtest1)\n" + - " │ ├─ index: [sbtest1.id]\n" + - " │ ├─ static: [{[NULL, ∞)}]\n" + - " │ ├─ colSet: (25-48)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: sbtest1\n" + " │ └─ columns: [id]\n" + " └─ TableAlias(a)\n" + " └─ IndexedTableAccess(sbtest1)\n" + " ├─ index: [sbtest1.id]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [b.id:0!null]\n" + " ├─ colSet: (1-24)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + diff --git a/enginetest/queries/tpch_plans.go b/enginetest/queries/tpch_plans.go index 44a3cead02..4d50636cbb 100644 --- a/enginetest/queries/tpch_plans.go +++ b/enginetest/queries/tpch_plans.go @@ -109,7 +109,7 @@ order by " ├─ columns: [supplier.s_acctbal:14!null, supplier.s_name:10!null, nation.n_name:22!null, part.p_partkey:0!null, part.p_mfgr:2!null, supplier.s_address:11!null, supplier.s_phone:13!null, supplier.s_comment:15!null]\n" + " └─ Sort(supplier.s_acctbal:14!null DESC nullsFirst, nation.n_name:22!null ASC nullsFirst, supplier.s_name:10!null ASC nullsFirst, part.p_partkey:0!null ASC nullsFirst)\n" + " └─ Project\n" + - " ├─ columns: [part.P_PARTKEY:12!null, part.P_NAME:13!null, part.P_MFGR:14!null, part.P_BRAND:15!null, part.P_TYPE:16!null, part.P_SIZE:17!null, part.P_CONTAINER:18!null, part.P_RETAILPRICE:19!null, part.P_COMMENT:20!null, supplier.S_SUPPKEY:5!null, supplier.S_NAME:6!null, supplier.S_ADDRESS:7!null, supplier.S_NATIONKEY:8!null, supplier.S_PHONE:9!null, supplier.S_ACCTBAL:10!null, supplier.S_COMMENT:11!null, partsupp.PS_PARTKEY:0!null, partsupp.PS_SUPPKEY:1!null, partsupp.PS_AVAILQTY:2!null, partsupp.PS_SUPPLYCOST:3!null, partsupp.PS_COMMENT:4!null, nation.N_NATIONKEY:21!null, nation.N_NAME:22!null, nation.N_REGIONKEY:23!null, nation.N_COMMENT:24, region.R_REGIONKEY:25!null, region.R_NAME:26!null, region.R_COMMENT:27]\n" + + " ├─ columns: [part.P_PARTKEY:5!null, part.P_NAME:6!null, part.P_MFGR:7!null, part.P_BRAND:8!null, part.P_TYPE:9!null, part.P_SIZE:10!null, part.P_CONTAINER:11!null, part.P_RETAILPRICE:12!null, part.P_COMMENT:13!null, supplier.S_SUPPKEY:14!null, supplier.S_NAME:15!null, supplier.S_ADDRESS:16!null, supplier.S_NATIONKEY:17!null, supplier.S_PHONE:18!null, supplier.S_ACCTBAL:19!null, supplier.S_COMMENT:20!null, partsupp.PS_PARTKEY:0!null, partsupp.PS_SUPPKEY:1!null, partsupp.PS_AVAILQTY:2!null, partsupp.PS_SUPPLYCOST:3!null, partsupp.PS_COMMENT:4!null, nation.N_NATIONKEY:21!null, nation.N_NAME:22!null, nation.N_REGIONKEY:23!null, nation.N_COMMENT:24, region.R_REGIONKEY:25!null, region.R_NAME:26!null, region.R_COMMENT:27]\n" + " └─ Filter\n" + " ├─ Eq\n" + " │ ├─ partsupp.ps_supplycost:3!null\n" + @@ -123,7 +123,7 @@ order by " │ ├─ group: \n" + " │ └─ Filter\n" + " │ ├─ Eq\n" + - " │ │ ├─ part.p_partkey:12!null\n" + + " │ │ ├─ part.p_partkey:5!null\n" + " │ │ └─ partsupp.ps_partkey:28!null\n" + " │ └─ LookupJoin\n" + " │ ├─ LookupJoin\n" + @@ -169,31 +169,31 @@ order by " │ │ │ │ └─ Table\n" + " │ │ │ │ ├─ name: partsupp\n" + " │ │ │ │ └─ columns: [ps_partkey ps_suppkey ps_availqty ps_supplycost ps_comment]\n" + - " │ │ │ └─ IndexedTableAccess(supplier)\n" + - " │ │ │ ├─ index: [supplier.S_SUPPKEY]\n" + - " │ │ │ ├─ keys: [partsupp.ps_suppkey:1!null]\n" + - " │ │ │ ├─ colSet: (10-16)\n" + - " │ │ │ ├─ tableId: 2\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: supplier\n" + - " │ │ │ └─ columns: [s_suppkey s_name s_address s_nationkey s_phone s_acctbal s_comment]\n" + - " │ │ └─ Filter\n" + - " │ │ ├─ AND\n" + - " │ │ │ ├─ Eq\n" + - " │ │ │ │ ├─ part.p_size:5!null\n" + - " │ │ │ │ └─ 15 (tinyint)\n" + - " │ │ │ └─ part.p_type LIKE '%BRASS'\n" + - " │ │ └─ IndexedTableAccess(part)\n" + - " │ │ ├─ index: [part.P_PARTKEY]\n" + - " │ │ ├─ keys: [partsupp.ps_partkey:0!null]\n" + - " │ │ ├─ colSet: (1-9)\n" + - " │ │ ├─ tableId: 1\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: part\n" + - " │ │ └─ columns: [p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment]\n" + + " │ │ │ └─ Filter\n" + + " │ │ │ ├─ AND\n" + + " │ │ │ │ ├─ Eq\n" + + " │ │ │ │ │ ├─ part.p_size:5!null\n" + + " │ │ │ │ │ └─ 15 (tinyint)\n" + + " │ │ │ │ └─ part.p_type LIKE '%BRASS'\n" + + " │ │ │ └─ IndexedTableAccess(part)\n" + + " │ │ │ ├─ index: [part.P_PARTKEY]\n" + + " │ │ │ ├─ keys: [partsupp.ps_partkey:0!null]\n" + + " │ │ │ ├─ colSet: (1-9)\n" + + " │ │ │ ├─ tableId: 1\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: part\n" + + " │ │ │ └─ columns: [p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment]\n" + + " │ │ └─ IndexedTableAccess(supplier)\n" + + " │ │ ├─ index: [supplier.S_SUPPKEY]\n" + + " │ │ ├─ keys: [partsupp.ps_suppkey:1!null]\n" + + " │ │ ├─ colSet: (10-16)\n" + + " │ │ ├─ tableId: 2\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: supplier\n" + + " │ │ └─ columns: [s_suppkey s_name s_address s_nationkey s_phone s_acctbal s_comment]\n" + " │ └─ IndexedTableAccess(nation)\n" + " │ ├─ index: [nation.N_NATIONKEY]\n" + - " │ ├─ keys: [supplier.s_nationkey:8!null]\n" + + " │ ├─ keys: [supplier.s_nationkey:17!null]\n" + " │ ├─ colSet: (22-25)\n" + " │ ├─ tableId: 4\n" + " │ └─ Table\n" + @@ -246,42 +246,40 @@ order by " └─ GroupBy\n" + " ├─ select: SUM((lineitem.l_extendedprice:1!null * (1 (tinyint) - lineitem.l_discount:2!null))), lineitem.l_orderkey:0!null, orders.o_orderdate:6!null, orders.o_shippriority:7!null\n" + " ├─ group: lineitem.l_orderkey:0!null, orders.o_orderdate:6!null, orders.o_shippriority:7!null\n" + - " └─ HashJoin\n" + - " ├─ Eq\n" + - " │ ├─ lineitem.l_orderkey:0!null\n" + - " │ └─ orders.o_orderkey:4!null\n" + - " ├─ Filter\n" + - " │ ├─ GreaterThan\n" + - " │ │ ├─ lineitem.l_shipdate:3!null\n" + - " │ │ └─ 1995-03-15 (longtext)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: lineitem\n" + - " │ └─ columns: [l_orderkey l_extendedprice l_discount l_shipdate]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(lineitem.l_orderkey:0!null)\n" + - " ├─ right-key: TUPLE(orders.o_orderkey:0!null)\n" + - " └─ LookupJoin\n" + - " ├─ Filter\n" + - " │ ├─ LessThan\n" + - " │ │ ├─ orders.o_orderdate:2!null\n" + - " │ │ └─ 1995-03-15 (longtext)\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: orders\n" + - " │ └─ columns: [o_orderkey o_custkey o_orderdate o_shippriority]\n" + - " └─ Filter\n" + - " ├─ Eq\n" + - " │ ├─ customer.c_mktsegment:1!null\n" + - " │ └─ BUILDING (longtext)\n" + - " └─ IndexedTableAccess(customer)\n" + - " ├─ index: [customer.C_CUSTKEY]\n" + - " ├─ keys: [orders.o_custkey:5!null]\n" + - " ├─ colSet: (1-8)\n" + - " ├─ tableId: 1\n" + - " └─ Table\n" + - " ├─ name: customer\n" + - " └─ columns: [c_custkey c_mktsegment]\n" + + " └─ LookupJoin\n" + + " ├─ LookupJoin\n" + + " │ ├─ Filter\n" + + " │ │ ├─ GreaterThan\n" + + " │ │ │ ├─ lineitem.l_shipdate:3!null\n" + + " │ │ │ └─ 1995-03-15 (longtext)\n" + + " │ │ └─ ProcessTable\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: lineitem\n" + + " │ │ └─ columns: [l_orderkey l_extendedprice l_discount l_shipdate]\n" + + " │ └─ Filter\n" + + " │ ├─ LessThan\n" + + " │ │ ├─ orders.o_orderdate:2!null\n" + + " │ │ └─ 1995-03-15 (longtext)\n" + + " │ └─ IndexedTableAccess(orders)\n" + + " │ ├─ index: [orders.O_ORDERKEY]\n" + + " │ ├─ keys: [lineitem.l_orderkey:0!null]\n" + + " │ ├─ colSet: (9-17)\n" + + " │ ├─ tableId: 2\n" + + " │ └─ Table\n" + + " │ ├─ name: orders\n" + + " │ └─ columns: [o_orderkey o_custkey o_orderdate o_shippriority]\n" + + " └─ Filter\n" + + " ├─ Eq\n" + + " │ ├─ customer.c_mktsegment:1!null\n" + + " │ └─ BUILDING (longtext)\n" + + " └─ IndexedTableAccess(customer)\n" + + " ├─ index: [customer.C_CUSTKEY]\n" + + " ├─ keys: [orders.o_custkey:5!null]\n" + + " ├─ colSet: (1-8)\n" + + " ├─ tableId: 1\n" + + " └─ Table\n" + + " ├─ name: customer\n" + + " └─ columns: [c_custkey c_mktsegment]\n" + "", }, { @@ -318,10 +316,7 @@ order by " ├─ group: orders.o_orderpriority:5!null\n" + " └─ Project\n" + " ├─ columns: [orders.O_ORDERKEY:1!null, orders.O_CUSTKEY:2!null, orders.O_ORDERSTATUS:3!null, orders.O_TOTALPRICE:4!null, orders.O_ORDERDATE:5!null, orders.O_ORDERPRIORITY:6!null, orders.O_CLERK:7!null, orders.O_SHIPPRIORITY:8!null, orders.O_COMMENT:9!null]\n" + - " └─ MergeJoin\n" + - " ├─ cmp: Eq\n" + - " │ ├─ lineitem.l_orderkey:0!null\n" + - " │ └─ orders.o_orderkey:1!null\n" + + " └─ LookupJoin\n" + " ├─ Distinct\n" + " │ └─ Project\n" + " │ ├─ columns: [lineitem.l_orderkey:0!null]\n" + @@ -329,11 +324,7 @@ order by " │ ├─ LessThan\n" + " │ │ ├─ lineitem.l_commitdate:11!null\n" + " │ │ └─ lineitem.l_receiptdate:12!null\n" + - " │ └─ IndexedTableAccess(lineitem)\n" + - " │ ├─ index: [lineitem.L_ORDERKEY,lineitem.L_LINENUMBER]\n" + - " │ ├─ static: [{[NULL, ∞), [NULL, ∞)}]\n" + - " │ ├─ colSet: (10-25)\n" + - " │ ├─ tableId: 2\n" + + " │ └─ ProcessTable\n" + " │ └─ Table\n" + " │ ├─ name: lineitem\n" + " │ └─ columns: [l_orderkey l_partkey l_suppkey l_linenumber l_quantity l_extendedprice l_discount l_tax l_returnflag l_linestatus l_shipdate l_commitdate l_receiptdate l_shipinstruct l_shipmode l_comment]\n" + @@ -347,7 +338,7 @@ order by " │ └─ 1993-10-01 00:00:00 +0000 UTC (datetime(6))\n" + " └─ IndexedTableAccess(orders)\n" + " ├─ index: [orders.O_ORDERKEY]\n" + - " ├─ static: [{[NULL, ∞)}]\n" + + " ├─ keys: [lineitem.l_orderkey:0!null]\n" + " ├─ colSet: (1-9)\n" + " ├─ tableId: 1\n" + " └─ Table\n" + @@ -393,10 +384,10 @@ order by " └─ LookupJoin\n" + " ├─ AND\n" + " │ ├─ Eq\n" + - " │ │ ├─ customer.c_nationkey:15!null\n" + - " │ │ └─ supplier.s_nationkey:5!null\n" + + " │ │ ├─ customer.c_nationkey:8!null\n" + + " │ │ └─ supplier.s_nationkey:15!null\n" + " │ └─ Eq\n" + - " │ ├─ customer.c_nationkey:15!null\n" + + " │ ├─ supplier.s_nationkey:15!null\n" + " │ └─ nation.n_nationkey:9!null\n" + " ├─ LookupJoin\n" + " │ ├─ LookupJoin\n" + @@ -406,33 +397,33 @@ order by " │ │ │ │ │ └─ Table\n" + " │ │ │ │ │ ├─ name: lineitem\n" + " │ │ │ │ │ └─ columns: [l_orderkey l_suppkey l_extendedprice l_discount]\n" + - " │ │ │ │ └─ IndexedTableAccess(supplier)\n" + - " │ │ │ │ ├─ index: [supplier.S_SUPPKEY]\n" + - " │ │ │ │ ├─ keys: [lineitem.l_suppkey:1!null]\n" + - " │ │ │ │ ├─ colSet: (34-40)\n" + - " │ │ │ │ ├─ tableId: 4\n" + - " │ │ │ │ └─ Table\n" + - " │ │ │ │ ├─ name: supplier\n" + - " │ │ │ │ └─ columns: [s_suppkey s_nationkey]\n" + - " │ │ │ └─ Filter\n" + - " │ │ │ ├─ AND\n" + - " │ │ │ │ ├─ GreaterThanOrEqual\n" + - " │ │ │ │ │ ├─ orders.o_orderdate:2!null\n" + - " │ │ │ │ │ └─ 1994-01-01 (longtext)\n" + - " │ │ │ │ └─ LessThan\n" + - " │ │ │ │ ├─ orders.o_orderdate:2!null\n" + - " │ │ │ │ └─ 1995-01-01 00:00:00 +0000 UTC (datetime(6))\n" + - " │ │ │ └─ IndexedTableAccess(orders)\n" + - " │ │ │ ├─ index: [orders.O_ORDERKEY]\n" + - " │ │ │ ├─ keys: [lineitem.l_orderkey:0!null]\n" + - " │ │ │ ├─ colSet: (9-17)\n" + - " │ │ │ ├─ tableId: 2\n" + - " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: orders\n" + - " │ │ │ └─ columns: [o_orderkey o_custkey o_orderdate]\n" + + " │ │ │ │ └─ Filter\n" + + " │ │ │ │ ├─ AND\n" + + " │ │ │ │ │ ├─ GreaterThanOrEqual\n" + + " │ │ │ │ │ │ ├─ orders.o_orderdate:2!null\n" + + " │ │ │ │ │ │ └─ 1994-01-01 (longtext)\n" + + " │ │ │ │ │ └─ LessThan\n" + + " │ │ │ │ │ ├─ orders.o_orderdate:2!null\n" + + " │ │ │ │ │ └─ 1995-01-01 00:00:00 +0000 UTC (datetime(6))\n" + + " │ │ │ │ └─ IndexedTableAccess(orders)\n" + + " │ │ │ │ ├─ index: [orders.O_ORDERKEY]\n" + + " │ │ │ │ ├─ keys: [lineitem.l_orderkey:0!null]\n" + + " │ │ │ │ ├─ colSet: (9-17)\n" + + " │ │ │ │ ├─ tableId: 2\n" + + " │ │ │ │ └─ Table\n" + + " │ │ │ │ ├─ name: orders\n" + + " │ │ │ │ └─ columns: [o_orderkey o_custkey o_orderdate]\n" + + " │ │ │ └─ IndexedTableAccess(customer)\n" + + " │ │ │ ├─ index: [customer.C_CUSTKEY]\n" + + " │ │ │ ├─ keys: [orders.o_custkey:5!null]\n" + + " │ │ │ ├─ colSet: (1-8)\n" + + " │ │ │ ├─ tableId: 1\n" + + " │ │ │ └─ Table\n" + + " │ │ │ ├─ name: customer\n" + + " │ │ │ └─ columns: [c_custkey c_nationkey]\n" + " │ │ └─ IndexedTableAccess(nation)\n" + " │ │ ├─ index: [nation.N_NATIONKEY]\n" + - " │ │ ├─ keys: [supplier.s_nationkey:5!null]\n" + + " │ │ ├─ keys: [customer.c_nationkey:8!null]\n" + " │ │ ├─ colSet: (41-44)\n" + " │ │ ├─ tableId: 5\n" + " │ │ └─ Table\n" + @@ -450,14 +441,14 @@ order by " │ └─ Table\n" + " │ ├─ name: region\n" + " │ └─ columns: [r_regionkey r_name]\n" + - " └─ IndexedTableAccess(customer)\n" + - " ├─ index: [customer.C_CUSTKEY]\n" + - " ├─ keys: [orders.o_custkey:7!null]\n" + - " ├─ colSet: (1-8)\n" + - " ├─ tableId: 1\n" + + " └─ IndexedTableAccess(supplier)\n" + + " ├─ index: [supplier.S_SUPPKEY]\n" + + " ├─ keys: [lineitem.l_suppkey:1!null]\n" + + " ├─ colSet: (34-40)\n" + + " ├─ tableId: 4\n" + " └─ Table\n" + - " ├─ name: customer\n" + - " └─ columns: [c_custkey c_nationkey]\n" + + " ├─ name: supplier\n" + + " └─ columns: [s_suppkey s_nationkey]\n" + "", }, { @@ -937,53 +928,51 @@ order by " └─ Project\n" + " ├─ columns: [sum((lineitem.l_extendedprice * (1 - lineitem.l_discount))):0!null, customer.c_custkey:1!null, customer.c_name:2!null, customer.c_acctbal:3!null, nation.n_name:4!null, customer.c_address:5!null, customer.c_phone:6!null, customer.c_comment:7!null, sum((lineitem.l_extendedprice * (1 - lineitem.l_discount))):0!null as revenue]\n" + " └─ GroupBy\n" + - " ├─ select: SUM((lineitem.l_extendedprice:13!null * (1 (tinyint) - lineitem.l_discount:14!null))), customer.c_custkey:3!null, customer.c_name:4!null, customer.c_acctbal:8!null, nation.n_name:11!null, customer.c_address:5!null, customer.c_phone:7!null, customer.c_comment:9!null\n" + - " ├─ group: customer.c_custkey:3!null, customer.c_name:4!null, customer.c_acctbal:8!null, customer.c_phone:7!null, nation.n_name:11!null, customer.c_address:5!null, customer.c_comment:9!null\n" + - " └─ HashJoin\n" + - " ├─ Eq\n" + - " │ ├─ lineitem.l_orderkey:12!null\n" + - " │ └─ orders.o_orderkey:0!null\n" + + " ├─ select: SUM((lineitem.l_extendedprice:1!null * (1 (tinyint) - lineitem.l_discount:2!null))), customer.c_custkey:7!null, customer.c_name:8!null, customer.c_acctbal:12!null, nation.n_name:15!null, customer.c_address:9!null, customer.c_phone:11!null, customer.c_comment:13!null\n" + + " ├─ group: customer.c_custkey:7!null, customer.c_name:8!null, customer.c_acctbal:12!null, customer.c_phone:11!null, nation.n_name:15!null, customer.c_address:9!null, customer.c_comment:13!null\n" + + " └─ LookupJoin\n" + " ├─ LookupJoin\n" + " │ ├─ LookupJoin\n" + " │ │ ├─ Filter\n" + - " │ │ │ ├─ AND\n" + - " │ │ │ │ ├─ GreaterThanOrEqual\n" + - " │ │ │ │ │ ├─ orders.o_orderdate:2!null\n" + - " │ │ │ │ │ └─ 1993-10-01 (longtext)\n" + - " │ │ │ │ └─ LessThan\n" + - " │ │ │ │ ├─ orders.o_orderdate:2!null\n" + - " │ │ │ │ └─ 1994-01-01 00:00:00 +0000 UTC (datetime(6))\n" + + " │ │ │ ├─ Eq\n" + + " │ │ │ │ ├─ lineitem.l_returnflag:3!null\n" + + " │ │ │ │ └─ R (longtext)\n" + " │ │ │ └─ ProcessTable\n" + " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: orders\n" + - " │ │ │ └─ columns: [o_orderkey o_custkey o_orderdate]\n" + - " │ │ └─ IndexedTableAccess(customer)\n" + - " │ │ ├─ index: [customer.C_CUSTKEY]\n" + - " │ │ ├─ keys: [orders.o_custkey:1!null]\n" + - " │ │ ├─ colSet: (1-8)\n" + - " │ │ ├─ tableId: 1\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: customer\n" + - " │ │ └─ columns: [c_custkey c_name c_address c_nationkey c_phone c_acctbal c_comment]\n" + - " │ └─ IndexedTableAccess(nation)\n" + - " │ ├─ index: [nation.N_NATIONKEY]\n" + - " │ ├─ keys: [customer.c_nationkey:6!null]\n" + - " │ ├─ colSet: (34-37)\n" + - " │ ├─ tableId: 4\n" + + " │ │ │ ├─ name: lineitem\n" + + " │ │ │ └─ columns: [l_orderkey l_extendedprice l_discount l_returnflag]\n" + + " │ │ └─ Filter\n" + + " │ │ ├─ AND\n" + + " │ │ │ ├─ GreaterThanOrEqual\n" + + " │ │ │ │ ├─ orders.o_orderdate:2!null\n" + + " │ │ │ │ └─ 1993-10-01 (longtext)\n" + + " │ │ │ └─ LessThan\n" + + " │ │ │ ├─ orders.o_orderdate:2!null\n" + + " │ │ │ └─ 1994-01-01 00:00:00 +0000 UTC (datetime(6))\n" + + " │ │ └─ IndexedTableAccess(orders)\n" + + " │ │ ├─ index: [orders.O_ORDERKEY]\n" + + " │ │ ├─ keys: [lineitem.l_orderkey:0!null]\n" + + " │ │ ├─ colSet: (9-17)\n" + + " │ │ ├─ tableId: 2\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: orders\n" + + " │ │ └─ columns: [o_orderkey o_custkey o_orderdate]\n" + + " │ └─ IndexedTableAccess(customer)\n" + + " │ ├─ index: [customer.C_CUSTKEY]\n" + + " │ ├─ keys: [orders.o_custkey:5!null]\n" + + " │ ├─ colSet: (1-8)\n" + + " │ ├─ tableId: 1\n" + " │ └─ Table\n" + - " │ ├─ name: nation\n" + - " │ └─ columns: [n_nationkey n_name]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(orders.o_orderkey:0!null)\n" + - " ├─ right-key: TUPLE(lineitem.l_orderkey:0!null)\n" + - " └─ Filter\n" + - " ├─ Eq\n" + - " │ ├─ lineitem.l_returnflag:3!null\n" + - " │ └─ R (longtext)\n" + - " └─ ProcessTable\n" + - " └─ Table\n" + - " ├─ name: lineitem\n" + - " └─ columns: [l_orderkey l_extendedprice l_discount l_returnflag]\n" + + " │ ├─ name: customer\n" + + " │ └─ columns: [c_custkey c_name c_address c_nationkey c_phone c_acctbal c_comment]\n" + + " └─ IndexedTableAccess(nation)\n" + + " ├─ index: [nation.N_NATIONKEY]\n" + + " ├─ keys: [customer.c_nationkey:10!null]\n" + + " ├─ colSet: (34-37)\n" + + " ├─ tableId: 4\n" + + " └─ Table\n" + + " ├─ name: nation\n" + + " └─ columns: [n_nationkey n_name]\n" + "", }, { @@ -1434,57 +1423,55 @@ order by " └─ GroupBy\n" + " ├─ select: COUNTDISTINCT([partsupp.ps_suppkey]), part.p_brand:8!null, part.p_type:9!null, part.p_size:10!null\n" + " ├─ group: part.p_brand:8!null, part.p_type:9!null, part.p_size:10!null\n" + - " └─ HashJoin\n" + - " ├─ Eq\n" + - " │ ├─ part.p_partkey:5!null\n" + - " │ └─ partsupp.ps_partkey:0!null\n" + - " ├─ Project\n" + - " │ ├─ columns: [partsupp.PS_PARTKEY:0!null, partsupp.PS_SUPPKEY:1!null, partsupp.PS_AVAILQTY:2!null, partsupp.PS_SUPPLYCOST:3!null, partsupp.PS_COMMENT:4!null]\n" + - " │ └─ Filter\n" + - " │ ├─ supplier.s_suppkey:5!null IS NULL\n" + - " │ └─ LeftOuterHashJoinExcludeNulls\n" + - " │ ├─ Eq\n" + - " │ │ ├─ partsupp.ps_suppkey:1!null\n" + - " │ │ └─ supplier.s_suppkey:5!null\n" + - " │ ├─ ProcessTable\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: partsupp\n" + - " │ │ └─ columns: [ps_partkey ps_suppkey ps_availqty ps_supplycost ps_comment]\n" + - " │ └─ HashLookup\n" + - " │ ├─ left-key: TUPLE(partsupp.ps_suppkey:1!null)\n" + - " │ ├─ right-key: TUPLE(supplier.s_suppkey:0!null)\n" + - " │ └─ Project\n" + - " │ ├─ columns: [supplier.s_suppkey:0!null]\n" + - " │ └─ Filter\n" + - " │ ├─ supplier.s_comment LIKE '%Customer%Complaints%'\n" + - " │ └─ ProcessTable\n" + - " │ └─ Table\n" + - " │ ├─ name: supplier\n" + - " │ └─ columns: [s_suppkey s_name s_address s_nationkey s_phone s_acctbal s_comment]\n" + - " └─ HashLookup\n" + - " ├─ left-key: TUPLE(partsupp.ps_partkey:0!null)\n" + - " ├─ right-key: TUPLE(part.p_partkey:0!null)\n" + - " └─ Filter\n" + - " ├─ AND\n" + - " │ ├─ AND\n" + - " │ │ ├─ NOT\n" + - " │ │ │ └─ Eq\n" + - " │ │ │ ├─ part.p_brand:3!null\n" + - " │ │ │ └─ Brand#45 (longtext)\n" + - " │ │ └─ Or\n" + - " │ │ ├─ LessThan\n" + - " │ │ │ ├─ part.p_type:4!null\n" + - " │ │ │ └─ MEDIUM POLISHED (longtext)\n" + - " │ │ └─ GreaterThan\n" + - " │ │ ├─ part.p_type:4!null\n" + - " │ │ └─ MEDIUM POLISHEDÿ (longtext)\n" + - " │ └─ HashIn\n" + - " │ ├─ part.p_size:5!null\n" + - " │ └─ TUPLE(49 (tinyint), 14 (tinyint), 23 (tinyint), 45 (tinyint), 19 (tinyint), 3 (tinyint), 36 (tinyint), 9 (tinyint))\n" + - " └─ ProcessTable\n" + - " └─ Table\n" + - " ├─ name: part\n" + - " └─ columns: [p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment]\n" + + " └─ Project\n" + + " ├─ columns: [partsupp.PS_PARTKEY:0!null, partsupp.PS_SUPPKEY:1!null, partsupp.PS_AVAILQTY:2!null, partsupp.PS_SUPPLYCOST:3!null, partsupp.PS_COMMENT:4!null, part.P_PARTKEY:5!null, part.P_NAME:6!null, part.P_MFGR:7!null, part.P_BRAND:8!null, part.P_TYPE:9!null, part.P_SIZE:10!null, part.P_CONTAINER:11!null, part.P_RETAILPRICE:12!null, part.P_COMMENT:13!null]\n" + + " └─ Filter\n" + + " ├─ supplier.s_suppkey:14!null IS NULL\n" + + " └─ LeftOuterHashJoinExcludeNulls\n" + + " ├─ Eq\n" + + " │ ├─ partsupp.ps_suppkey:1!null\n" + + " │ └─ supplier.s_suppkey:14!null\n" + + " ├─ LookupJoin\n" + + " │ ├─ ProcessTable\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: partsupp\n" + + " │ │ └─ columns: [ps_partkey ps_suppkey ps_availqty ps_supplycost ps_comment]\n" + + " │ └─ Filter\n" + + " │ ├─ AND\n" + + " │ │ ├─ AND\n" + + " │ │ │ ├─ NOT\n" + + " │ │ │ │ └─ Eq\n" + + " │ │ │ │ ├─ part.p_brand:3!null\n" + + " │ │ │ │ └─ Brand#45 (longtext)\n" + + " │ │ │ └─ Or\n" + + " │ │ │ ├─ LessThan\n" + + " │ │ │ │ ├─ part.p_type:4!null\n" + + " │ │ │ │ └─ MEDIUM POLISHED (longtext)\n" + + " │ │ │ └─ GreaterThan\n" + + " │ │ │ ├─ part.p_type:4!null\n" + + " │ │ │ └─ MEDIUM POLISHEDÿ (longtext)\n" + + " │ │ └─ HashIn\n" + + " │ │ ├─ part.p_size:5!null\n" + + " │ │ └─ TUPLE(49 (tinyint), 14 (tinyint), 23 (tinyint), 45 (tinyint), 19 (tinyint), 3 (tinyint), 36 (tinyint), 9 (tinyint))\n" + + " │ └─ IndexedTableAccess(part)\n" + + " │ ├─ index: [part.P_PARTKEY]\n" + + " │ ├─ keys: [partsupp.ps_partkey:0!null]\n" + + " │ ├─ colSet: (6-14)\n" + + " │ ├─ tableId: 2\n" + + " │ └─ Table\n" + + " │ ├─ name: part\n" + + " │ └─ columns: [p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment]\n" + + " └─ HashLookup\n" + + " ├─ left-key: TUPLE(partsupp.ps_suppkey:1!null)\n" + + " ├─ right-key: TUPLE(supplier.s_suppkey:0!null)\n" + + " └─ Project\n" + + " ├─ columns: [supplier.s_suppkey:0!null]\n" + + " └─ Filter\n" + + " ├─ supplier.s_comment LIKE '%Customer%Complaints%'\n" + + " └─ ProcessTable\n" + + " └─ Table\n" + + " ├─ name: supplier\n" + + " └─ columns: [s_suppkey s_name s_address s_nationkey s_phone s_acctbal s_comment]\n" + "", }, { @@ -2024,18 +2011,14 @@ order by " └─ GroupBy\n" + " ├─ select: COUNT(1 (bigint)), supplier.s_name:17!null\n" + " ├─ group: supplier.s_name:17!null\n" + - " └─ LookupJoin\n" + + " └─ SemiLookupJoin\n" + + " ├─ NOT\n" + + " │ └─ Eq\n" + + " │ ├─ l2.l_suppkey:38!null\n" + + " │ └─ l1.l_suppkey:2!null\n" + " ├─ LookupJoin\n" + " │ ├─ LookupJoin\n" + - " │ │ ├─ SemiJoin\n" + - " │ │ │ ├─ AND\n" + - " │ │ │ │ ├─ Eq\n" + - " │ │ │ │ │ ├─ l2.l_orderkey:16!null\n" + - " │ │ │ │ │ └─ l1.l_orderkey:0!null\n" + - " │ │ │ │ └─ NOT\n" + - " │ │ │ │ └─ Eq\n" + - " │ │ │ │ ├─ l2.l_suppkey:18!null\n" + - " │ │ │ │ └─ l1.l_suppkey:2!null\n" + + " │ │ ├─ LookupJoin\n" + " │ │ │ ├─ AntiJoin\n" + " │ │ │ │ ├─ AND\n" + " │ │ │ │ │ ├─ Eq\n" + @@ -2064,44 +2047,47 @@ order by " │ │ │ │ ├─ columns: [l_orderkey l_partkey l_suppkey l_linenumber l_quantity l_extendedprice l_discount l_tax l_returnflag l_linestatus l_shipdate l_commitdate l_receiptdate l_shipinstruct l_shipmode l_comment]\n" + " │ │ │ │ ├─ colSet: (53-68)\n" + " │ │ │ │ └─ tableId: 6\n" + - " │ │ │ └─ TableAlias(l2)\n" + + " │ │ │ └─ IndexedTableAccess(supplier)\n" + + " │ │ │ ├─ index: [supplier.S_SUPPKEY]\n" + + " │ │ │ ├─ keys: [l1.l_suppkey:2!null]\n" + + " │ │ │ ├─ colSet: (1-7)\n" + + " │ │ │ ├─ tableId: 1\n" + " │ │ │ └─ Table\n" + - " │ │ │ ├─ name: lineitem\n" + - " │ │ │ ├─ columns: [l_orderkey l_partkey l_suppkey l_linenumber l_quantity l_extendedprice l_discount l_tax l_returnflag l_linestatus l_shipdate l_commitdate l_receiptdate l_shipinstruct l_shipmode l_comment]\n" + - " │ │ │ ├─ colSet: (37-52)\n" + - " │ │ │ └─ tableId: 5\n" + - " │ │ └─ IndexedTableAccess(supplier)\n" + - " │ │ ├─ index: [supplier.S_SUPPKEY]\n" + - " │ │ ├─ keys: [l1.l_suppkey:2!null]\n" + - " │ │ ├─ colSet: (1-7)\n" + - " │ │ ├─ tableId: 1\n" + - " │ │ └─ Table\n" + - " │ │ ├─ name: supplier\n" + - " │ │ └─ columns: [s_suppkey s_name s_address s_nationkey s_phone s_acctbal s_comment]\n" + + " │ │ │ ├─ name: supplier\n" + + " │ │ │ └─ columns: [s_suppkey s_name s_address s_nationkey s_phone s_acctbal s_comment]\n" + + " │ │ └─ Filter\n" + + " │ │ ├─ Eq\n" + + " │ │ │ ├─ orders.o_orderstatus:2!null\n" + + " │ │ │ └─ F (longtext)\n" + + " │ │ └─ IndexedTableAccess(orders)\n" + + " │ │ ├─ index: [orders.O_ORDERKEY]\n" + + " │ │ ├─ keys: [l1.l_orderkey:0!null]\n" + + " │ │ ├─ colSet: (24-32)\n" + + " │ │ ├─ tableId: 3\n" + + " │ │ └─ Table\n" + + " │ │ ├─ name: orders\n" + + " │ │ └─ columns: [o_orderkey o_custkey o_orderstatus o_totalprice o_orderdate o_orderpriority o_clerk o_shippriority o_comment]\n" + " │ └─ Filter\n" + " │ ├─ Eq\n" + - " │ │ ├─ orders.o_orderstatus:2!null\n" + - " │ │ └─ F (longtext)\n" + - " │ └─ IndexedTableAccess(orders)\n" + - " │ ├─ index: [orders.O_ORDERKEY]\n" + - " │ ├─ keys: [l1.l_orderkey:0!null]\n" + - " │ ├─ colSet: (24-32)\n" + - " │ ├─ tableId: 3\n" + + " │ │ ├─ nation.n_name:1!null\n" + + " │ │ └─ SAUDI ARABIA (longtext)\n" + + " │ └─ IndexedTableAccess(nation)\n" + + " │ ├─ index: [nation.N_NATIONKEY]\n" + + " │ ├─ keys: [supplier.s_nationkey:19!null]\n" + + " │ ├─ colSet: (33-36)\n" + + " │ ├─ tableId: 4\n" + " │ └─ Table\n" + - " │ ├─ name: orders\n" + - " │ └─ columns: [o_orderkey o_custkey o_orderstatus o_totalprice o_orderdate o_orderpriority o_clerk o_shippriority o_comment]\n" + - " └─ Filter\n" + - " ├─ Eq\n" + - " │ ├─ nation.n_name:1!null\n" + - " │ └─ SAUDI ARABIA (longtext)\n" + - " └─ IndexedTableAccess(nation)\n" + - " ├─ index: [nation.N_NATIONKEY]\n" + - " ├─ keys: [supplier.s_nationkey:19!null]\n" + - " ├─ colSet: (33-36)\n" + - " ├─ tableId: 4\n" + + " │ ├─ name: nation\n" + + " │ └─ columns: [n_nationkey n_name n_regionkey n_comment]\n" + + " └─ TableAlias(l2)\n" + + " └─ IndexedTableAccess(lineitem)\n" + + " ├─ index: [lineitem.L_ORDERKEY,lineitem.L_LINENUMBER]\n" + + " ├─ keys: [l1.l_orderkey:0!null]\n" + + " ├─ colSet: (37-52)\n" + + " ├─ tableId: 5\n" + " └─ Table\n" + - " ├─ name: nation\n" + - " └─ columns: [n_nationkey n_name n_regionkey n_comment]\n" + + " ├─ name: lineitem\n" + + " └─ columns: [l_orderkey l_partkey l_suppkey l_linenumber l_quantity l_extendedprice l_discount l_tax l_returnflag l_linestatus l_shipdate l_commitdate l_receiptdate l_shipinstruct l_shipmode l_comment]\n" + "", }, { diff --git a/enginetest/spatial_index_tests.go b/enginetest/spatial_index_tests.go index 0050c6e87d..3fbaf242d5 100644 --- a/enginetest/spatial_index_tests.go +++ b/enginetest/spatial_index_tests.go @@ -365,7 +365,9 @@ func TestSpatialIndexPlans(t *testing.T, harness Harness) { } for _, tt := range tt.tests { evalSpatialIndexPlanCorrectness(t, harness, e, tt.q, tt.q, tt.exp, tt.skip) - evalSpatialIndexPlanTest(t, harness, e, tt.q, tt.skip, tt.noIdx) + if !IsServerEngine(e) { + evalSpatialIndexPlanTest(t, harness, e, tt.q, tt.skip, tt.noIdx) + } } }) } diff --git a/optgen/cmd/source/memo.yaml b/optgen/cmd/source/memo.yaml index a7240e63e2..4ef087d12c 100644 --- a/optgen/cmd/source/memo.yaml +++ b/optgen/cmd/source/memo.yaml @@ -12,7 +12,7 @@ exprs: - name: "LookupJoin" join: true attrs: - - [lookup, "*Lookup"] + - [lookup, "*ExprGroup"] - name: "RangeHeapJoin" join: true attrs: @@ -20,7 +20,7 @@ exprs: - name: "ConcatJoin" join: true attrs: - - [concat, "[]*Lookup"] + - [concat, "[]*ExprGroup"] - name: "HashJoin" join: true attrs: @@ -38,6 +38,11 @@ exprs: join: true - name: "TableScan" sourceType: "plan.TableIdNode" +- name: "IndexScan" + sourceType: "*plan.IndexedTableAccess" + attrs: + - [index, "*Index"] + - [Alias, "string"] - name: "Values" sourceType: "*plan.ValueDerivedTable" - name: "TableAlias" diff --git a/sql/analyzer/apply_indexes_from_outer_scope.go b/sql/analyzer/apply_indexes_from_outer_scope.go index 7ac1e59828..3ecf9c19b7 100644 --- a/sql/analyzer/apply_indexes_from_outer_scope.go +++ b/sql/analyzer/apply_indexes_from_outer_scope.go @@ -93,6 +93,7 @@ func applyIndexesFromOuterScope(ctx *sql.Context, a *Analyzer, n sql.Node, scope func pushdownIndexToTable(ctx *sql.Context, a *Analyzer, tableNode sql.NameableNode, index sql.Index, keyExpr []sql.Expression, nullmask []bool) (sql.Node, transform.TreeIdentity, error) { return transform.Node(tableNode, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { switch n := n.(type) { + case *plan.IndexedTableAccess: case sql.TableNode: table := getTable(tableNode) if table == nil { diff --git a/sql/analyzer/costed_index_scan.go b/sql/analyzer/costed_index_scan.go index f18685d308..618ec918bf 100644 --- a/sql/analyzer/costed_index_scan.go +++ b/sql/analyzer/costed_index_scan.go @@ -20,16 +20,16 @@ import ( "strings" "time" - "github.com/dolthub/go-mysql-server/sql/expression/function/spatial" - "github.com/dolthub/go-mysql-server/sql/fulltext" - "github.com/dolthub/go-mysql-server/sql/rowexec" - "github.com/dolthub/go-mysql-server/sql/types" - "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/expression" + "github.com/dolthub/go-mysql-server/sql/expression/function/spatial" + "github.com/dolthub/go-mysql-server/sql/fulltext" + "github.com/dolthub/go-mysql-server/sql/memo" "github.com/dolthub/go-mysql-server/sql/plan" + "github.com/dolthub/go-mysql-server/sql/rowexec" "github.com/dolthub/go-mysql-server/sql/stats" "github.com/dolthub/go-mysql-server/sql/transform" + "github.com/dolthub/go-mysql-server/sql/types" ) // costedIndexScans matches a Filter-ResolvedTable pattern, and tries to @@ -50,7 +50,7 @@ import ( // fraction of its conjunctions into an indexScan, with the excluded // remaining in the parent filter. Much of the format conversions focus // on maintaining this invariant. -func costedIndexScans(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scope, sel RuleSelector) (sql.Node, transform.TreeIdentity, error) { +func costedIndexScans(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, transform.TreeIdentity, error) { return transform.Node(n, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { filter, ok := n.(*plan.Filter) if !ok { @@ -83,165 +83,257 @@ func costedIndexScans(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Sco return n, transform.SameTree, err } return plan.NewFilter(filter.Expression, ret), transform.NewTree, nil - } - statistics, err := a.Catalog.StatsProvider.GetTableStats(ctx, strings.ToLower(rt.Database().Name()), strings.ToLower(rt.Name())) - if err != nil { - return n, transform.SameTree, err - } - - qualToStat := make(map[sql.StatQualifier]sql.Statistic) - for _, stat := range statistics { - if prev, ok := qualToStat[stat.Qualifier()]; !ok || ok && len(stat.Columns()) > len(prev.Columns()) { - qualToStat[stat.Qualifier()] = stat + } else if iat, ok := rt.UnderlyingTable().(sql.IndexAddressableTable); ok { + indexes, err := iat.GetIndexes(ctx) + if err != nil { + return n, transform.SameTree, err } + ita, _, filters, err := getCostedIndexScan(ctx, a.Catalog, rt, indexes, expression.SplitConjunction(filter.Expression)) + if err != nil || ita == nil { + return n, transform.SameTree, err + } + var ret sql.Node = ita + if aliasName != "" { + ret = plan.NewTableAlias(aliasName, ret) + } + // excluded from tree + not included in index scan => filter above scan + if len(filters) > 0 { + ret = plan.NewFilter(expression.JoinAnd(filters...), ret) + } + return ret, transform.NewTree, nil } + return n, transform.SameTree, nil + }) +} - // flatten expression tree for costing - c := newIndexCoster(rt.Name()) - root, leftover, imprecise := c.flatten(filter.Expression) - if root == nil { - return n, transform.SameTree, nil - } +func getCostedIndexScan(ctx *sql.Context, statsProv sql.StatsProvider, rt sql.TableNode, indexes []sql.Index, filters []sql.Expression) (*plan.IndexedTableAccess, sql.Statistic, []sql.Expression, error) { + statistics, err := statsProv.GetTableStats(ctx, strings.ToLower(rt.Database().Name()), strings.ToLower(rt.Name())) + if err != nil { + return nil, nil, nil, err + } - iat, ok := rt.UnderlyingTable().(sql.IndexAddressableTable) - if !ok { - return n, transform.SameTree, nil - } - indexes, err := iat.GetIndexes(ctx) - if err != nil { - return n, transform.SameTree, err + qualToStat := make(map[sql.StatQualifier]sql.Statistic) + for _, stat := range statistics { + if prev, ok := qualToStat[stat.Qualifier()]; !ok || ok && len(stat.Columns()) > len(prev.Columns()) { + qualToStat[stat.Qualifier()] = stat } + } - // run each index through coster, save the cheapest - var dbName string - if dbTab, ok := rt.UnderlyingTable().(sql.Databaseable); ok { - dbName = strings.ToLower(dbTab.Database()) - } - tableName := strings.ToLower(rt.UnderlyingTable().Name()) + // flatten expression tree for costing + c := newIndexCoster(rt.Name()) + root, leftover, imprecise := c.flatten(expression.JoinAnd(filters...)) + if root == nil { + return nil, nil, nil, err + } - if len(qualToStat) > 0 { - // don't mix and match real and default stats - for _, idx := range indexes { - qual := sql.NewStatQualifier(dbName, tableName, strings.ToLower(idx.ID())) - _, ok := qualToStat[qual] - if !ok { - qualToStat = nil - break - } - } - } + iat, ok := rt.UnderlyingTable().(sql.IndexAddressableTable) + if !ok { + return nil, nil, nil, err + } + // run each index through coster, save the cheapest + var dbName string + if dbTab, ok := rt.UnderlyingTable().(sql.Databaseable); ok { + dbName = strings.ToLower(dbTab.Database()) + } + tableName := strings.ToLower(rt.UnderlyingTable().Name()) + + if len(qualToStat) > 0 { + // don't mix and match real and default stats for _, idx := range indexes { qual := sql.NewStatQualifier(dbName, tableName, strings.ToLower(idx.ID())) - stat, ok := qualToStat[qual] + _, ok := qualToStat[qual] if !ok { - stat, err = uniformDistStatisticsForIndex(ctx, iat, idx) - } - err := c.cost(root, stat, idx) - if err != nil { - return nil, transform.SameTree, err + qualToStat = nil + break } } + } + + for _, idx := range indexes { + qual := sql.NewStatQualifier(dbName, tableName, strings.ToLower(idx.ID())) + stat, ok := qualToStat[qual] + if !ok { + stat, err = uniformDistStatisticsForIndex(ctx, iat, idx) + } + err := c.cost(root, stat, idx) + if err != nil { + return nil, nil, nil, err + } + } - if c.bestStat == nil || c.bestFilters.Empty() { - return n, transform.SameTree, nil + if c.bestStat == nil || c.bestFilters.Empty() { + return nil, nil, nil, err + } + + targetId := c.bestStat.Qualifier().Index() + var idx sql.Index + for _, i := range indexes { + if strings.EqualFold(i.ID(), targetId) { + idx = i + break } + } + if idx == nil { + return nil, nil, nil, fmt.Errorf("tried building indexScan with unknown statistic index: %s", targetId) + } - targetId := c.bestStat.Qualifier().Index() - var idx sql.Index - for _, i := range indexes { - if strings.EqualFold(i.ID(), targetId) { - idx = i - break + // separate |include| and |leftover| filters + b := newIndexScanRangeBuilder(ctx, idx, c.bestFilters, imprecise, c.idToExpr) + if leftover != nil { + b.leftover = append(b.leftover, leftover) + } + ranges, err := b.buildRangeCollection(root) + if err != nil { + return nil, nil, nil, err + } + + var emptyLookup bool + if len(ranges) == 0 { + emptyLookup = true + } else if len(ranges) == 1 { + emptyLookup, err = ranges[0].IsEmpty() + if err != nil { + return nil, nil, nil, err + } + allRange := true + for i, r := range ranges[0] { + _, uok := r.UpperBound.(sql.AboveAll) + _, lok := r.LowerBound.(sql.BelowNull) + allRange = allRange && uok && lok + if i == 0 && allRange { + // no prefix restriction + return nil, nil, nil, err } } - if idx == nil { - return n, transform.SameTree, fmt.Errorf("tried building indexScan with unknown statistic index: %s", targetId) + if allRange { + return nil, nil, nil, err } + } + + if !idx.CanSupport(ranges...) { + return nil, nil, nil, err + } + + if idx.IsSpatial() && len(ranges) > 1 { + // spatials don't support disjunct ranges + return nil, nil, nil, err + } + + // create ranges, lookup, ITA for best indexScan + // TODO: use FALSE filters to replace empty tables + lookup := sql.NewIndexLookup(idx, ranges, false, emptyLookup, idx.IsSpatial(), false) - // separate |include| and |leftover| filters - b := newIndexScanRangeBuilder(ctx, idx, c.bestFilters, imprecise, c.idToExpr) - if leftover != nil { - b.leftover = append(b.leftover, leftover) + var ret *plan.IndexedTableAccess + if idx.IsFullText() { + id, _ := c.bestFilters.Next(1) + ma := c.idToExpr[indexScanId(id)] + matchAgainst, ok := ma.(*expression.MatchAgainst) + if !ok { + return nil, nil, nil, fmt.Errorf("Full-Text index found in filter with unknown expression: %T", ma) + } + if matchAgainst.KeyCols.Type == fulltext.KeyType_None { + return nil, nil, nil, err } - ranges, err := b.buildRangeCollection(root) + ret = plan.NewStaticIndexedAccessForFullTextTable(rt, lookup, &rowexec.FulltextFilterTable{ + MatchAgainst: matchAgainst, + Table: rt, + }) + } else { + ret, err = plan.NewStaticIndexedAccessForTableNode(rt, lookup) if err != nil { - return nil, transform.SameTree, err + return nil, nil, nil, err } + } - var emptyLookup bool - if len(ranges) == 0 { - emptyLookup = true - } else if len(ranges) == 1 { - emptyLookup, err = ranges[0].IsEmpty() - if err != nil { - return n, transform.SameTree, err - } - allRange := true - for i, r := range ranges[0] { - _, uok := r.UpperBound.(sql.AboveAll) - _, lok := r.LowerBound.(sql.BelowNull) - allRange = allRange && uok && lok - if i == 0 && allRange { - // no prefix restriction - return n, transform.SameTree, nil - } - } - if allRange { - return n, transform.SameTree, nil - } - } + var retFilters []sql.Expression + if !iat.PreciseMatch() { + // cannot drop any filters + retFilters = filters + } else if len(b.leftover) > 0 { + // excluded from tree + not included in index scan => filter above scan + retFilters = b.leftover + } - if !idx.CanSupport(ranges...) { - return n, transform.SameTree, nil + return ret, c.bestStat, retFilters, nil +} + +func addIndexScans(m *memo.Memo) error { + return memo.DfsRel(m.Root(), func(e memo.RelExpr) error { + filter, ok := e.(*memo.Filter) + if !ok { + return nil } - if idx.IsSpatial() && len(ranges) > 1 { - // spatials don't support disjunct ranges - return n, transform.SameTree, nil + var rt sql.TableNode + var aliasName string + switch n := filter.Child.First.(type) { + case *memo.TableScan: + rt = n.Table.(sql.TableNode) + case *memo.TableAlias: + rt, ok = n.Table.Child.(sql.TableNode) + if !ok { + return nil + } + aliasName = n.Name() + default: + return nil } - // create ranges, lookup, ITA for best indexScan - // TODO pass up FALSE filter information - lookup := sql.NewIndexLookup(idx, ranges, false, emptyLookup, idx.IsSpatial(), false) + indexes := filter.Child.First.(memo.SourceRel).Indexes() - var ret sql.Node - if idx.IsFullText() { - id, _ := c.bestFilters.Next(1) - ma := c.idToExpr[indexScanId(id)] - matchAgainst, ok := ma.(*expression.MatchAgainst) - if !ok { - return nil, transform.SameTree, fmt.Errorf("Full-Text index found in filter with unknown expression: %T", ma) + if is, ok := rt.UnderlyingTable().(sql.IndexSearchableTable); ok && is.SkipIndexCosting() { + lookup, err := is.LookupForExpressions(m.Ctx, filter.Filters) + if err != nil { + return err } - if matchAgainst.KeyCols.Type == fulltext.KeyType_None { - return n, transform.SameTree, nil + if lookup.IsEmpty() { + return nil + } + ret, err := plan.NewStaticIndexedAccessForTableNode(rt, lookup) + if err != nil { + return err + } + // TODO add ITA to filter group + // todo memoize ITA + // we explicitly put ITA as child of filter group for this shortcut + var idx *memo.Index + for _, i := range indexes { + if i.SqlIdx().ID() == lookup.Index.ID() { + idx = i + break + } } - ret = plan.NewStaticIndexedAccessForFullTextTable(rt, lookup, &rowexec.FulltextFilterTable{ - MatchAgainst: matchAgainst, - Table: rt, - }) + itaGroup := m.MemoizeIndexScan(nil, ret, aliasName, idx) + m.MemoizeFilter(filter.Group(), itaGroup, filter.Filters) } else { - ret, err = plan.NewStaticIndexedAccessForTableNode(rt, lookup) + sqlIndexes := make([]sql.Index, len(indexes)) + for i, idx := range indexes { + sqlIndexes[i] = idx.SqlIdx() + } + ita, stat, filters, err := getCostedIndexScan(m.Ctx, m.StatsProvider(), rt, sqlIndexes, filter.Filters) if err != nil { - return n, transform.SameTree, nil + return err + } + if ita != nil { + var idx *memo.Index + for _, i := range indexes { + if ita.Index().ID() == i.SqlIdx().ID() { + idx = i + break + } + } + var itaGrp *memo.ExprGroup + if len(filters) > 0 { + itaGrp = m.MemoizeIndexScan(nil, ita, aliasName, idx) + m.MemoizeFilter(filter.Group(), itaGrp, filters) + } else { + itaGrp = m.MemoizeIndexScan(filter.Group(), ita, aliasName, idx) + } + itaGrp.RelProps.SetStats(stat) } } - - if aliasName != "" { - ret = plan.NewTableAlias(aliasName, ret) - } - - if !iat.PreciseMatch() { - // cannot drop any filters - return plan.NewFilter(filter.Expression, ret), transform.NewTree, nil - } - if len(b.leftover) == 0 { - // pushed all filters into index - return ret, transform.NewTree, nil - } - // excluded from tree + not included in index scan => filter above scan - newFilter := expression.JoinAnd(b.leftover...) - return plan.NewFilter(newFilter, ret), transform.NewTree, nil + return nil }) } @@ -1286,7 +1378,8 @@ func uniformDistStatisticsForIndex(ctx *sql.Context, iat sql.IndexAddressableTab var rowCount uint64 var avgSize uint64 if st, ok := iat.(sql.StatisticsTable); ok { - rowCount, _, err := st.RowCount(ctx) + var err error + rowCount, _, err = st.RowCount(ctx) if err != nil { return nil, err diff --git a/sql/analyzer/costed_index_scan_test.go b/sql/analyzer/costed_index_scan_test.go index 48d575a890..b93b2bb423 100644 --- a/sql/analyzer/costed_index_scan_test.go +++ b/sql/analyzer/costed_index_scan_test.go @@ -850,7 +850,7 @@ Filter ├─ index: [xy.x] └─ filters: [{[1, 1]}] ` - res, same, err := costedIndexScans(nil, nil, input, nil, nil) + res, same, err := costedIndexScans(nil, nil, input) require.NoError(t, err) require.False(t, bool(same)) require.Equal(t, strings.TrimSpace(exp), strings.TrimSpace(res.String()), "expected:\n%s,\nfound:\n%s\n", exp, res.String()) diff --git a/sql/analyzer/indexed_joins.go b/sql/analyzer/indexed_joins.go index f69b436682..7b75d569c3 100644 --- a/sql/analyzer/indexed_joins.go +++ b/sql/analyzer/indexed_joins.go @@ -42,7 +42,15 @@ func optimizeJoins(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scope, _, isUpdate := n.(*plan.Update) - return inOrderReplanJoin(ctx, a, scope, nil, n, isUpdate) + ret, same, err := inOrderReplanJoin(ctx, a, scope, nil, n, isUpdate) + if err != nil { + return n, transform.SameTree, err + } + if same { + // try index plans only + return costedIndexScans(ctx, a, n) + } + return ret, transform.NewTree, nil } // inOrderReplanJoin replans the first join node found @@ -101,7 +109,11 @@ func replanJoin(ctx *sql.Context, n *plan.JoinNode, a *Analyzer, scope *plan.Sco return n, nil } - err = convertSemiToInnerJoin(a, m) + err = addIndexScans(m) + if err != nil { + return nil, err + } + err = convertSemiToInnerJoin(m) if err != nil { return nil, err } @@ -187,7 +199,24 @@ func addLookupJoins(m *memo.Memo) error { return nil } - tableId, indexes, extraFilters := lookupCandidates(right.First) + tableId, indexes, extraFilters := lookupCandidates(right.First, false) + + var rt sql.TableNode + var aliasName string + switch n := right.RelProps.TableIdNodes()[0].(type) { + case sql.TableNode: + rt = n + case *plan.TableAlias: + var ok bool + rt, ok = n.Child.(sql.TableNode) + if !ok { + return nil + } + aliasName = n.Name() + default: + return nil + } + if or, ok := join.Filter[0].(*expression.Or); ok && len(join.Filter) == 1 { // Special case disjoint filter. The execution plan will perform an index // lookup for each predicate leaf in the OR tree. @@ -195,17 +224,22 @@ func addLookupJoins(m *memo.Memo) error { // can consider multiple index options. Otherwise the search space blows // up. conds := expression.SplitDisjunction(or) - var concat []*memo.Lookup + var concat []*memo.IndexScan for _, on := range conds { filters := expression.SplitConjunction(on) for _, idx := range indexes { keyExprs, _, nullmask := keyExprsForIndex(tableId, idx.Cols(), append(filters, extraFilters...)) if keyExprs != nil { - concat = append(concat, &memo.Lookup{ - Index: idx, - KeyExprs: keyExprs, - Nullmask: nullmask, - }) + ita, err := plan.NewIndexedAccessForTableNode(rt, plan.NewLookupBuilder(idx.SqlIdx(), keyExprs, nullmask)) + if err != nil { + return err + } + lookup := &memo.IndexScan{ + Table: ita, + Index: idx, + Alias: aliasName, + } + concat = append(concat, lookup) break } } @@ -213,15 +247,7 @@ func addLookupJoins(m *memo.Memo) error { if len(concat) != len(conds) { return nil } - rel := &memo.ConcatJoin{ - JoinBase: join.Copy(), - Concat: concat, - } - for _, l := range concat { - l.Parent = rel.JoinBase - } - rel.Op = rel.Op.AsLookup() - e.Group().Prepend(rel) + m.MemoizeConcatLookupJoin(e.Group(), join.Left, join.Right, join.Op, join.Filter, concat) return nil } @@ -230,16 +256,18 @@ func addLookupJoins(m *memo.Memo) error { if keyExprs == nil { continue } - rel := &memo.LookupJoin{ - JoinBase: join.Copy(), - Lookup: &memo.Lookup{ - Index: idx, - KeyExprs: keyExprs, - Nullmask: nullmask, - }, + ita, err := plan.NewIndexedAccessForTableNode(rt, plan.NewLookupBuilder(idx.SqlIdx(), keyExprs, nullmask)) + if err != nil { + return err + } + lookup := &memo.IndexScan{ + Table: ita, + Alias: aliasName, + Index: idx, } + var filters []sql.Expression - for _, filter := range rel.Filter { + for _, filter := range join.Filter { found := false for _, matchedFilter := range matchedFilters { if filter == matchedFilter { @@ -250,10 +278,8 @@ func addLookupJoins(m *memo.Memo) error { filters = append(filters, filter) } } - rel.Filter = filters - rel.Op = rel.Op.AsLookup() - rel.Lookup.Parent = rel.JoinBase - e.Group().Prepend(rel) + + m.MemoizeLookupJoin(e.Group(), join.Left, join.Right, join.Op, filters, lookup) } return nil }) @@ -331,7 +357,7 @@ func exprRefsTable(e sql.Expression, tableId sql.TableId) bool { // Ref section 2.1.1 of: // https://www.researchgate.net/publication/221311318_Cost-Based_Query_Transformation_in_Oracle // TODO: need more elegant way to extend the number of groups, interner -func convertSemiToInnerJoin(a *Analyzer, m *memo.Memo) error { +func convertSemiToInnerJoin(m *memo.Memo) error { return memo.DfsRel(m.Root(), func(e memo.RelExpr) error { semi, ok := e.(*memo.SemiJoin) if !ok { @@ -523,7 +549,18 @@ func addRightSemiJoins(m *memo.Memo) error { if len(semi.Filter) == 0 { return nil } - tableId, indexes, filters := lookupCandidates(semi.Left.First) + tableId, indexes, filters := lookupCandidates(semi.Left.First, false) + leftTab := semi.Left.RelProps.TableIdNodes()[0] + var aliasName string + var leftRt sql.TableNode + switch n := leftTab.(type) { + case *plan.TableAlias: + aliasName = n.Name() + leftRt = n.Child.(sql.TableNode) + case sql.TableNode: + leftRt = n + } + rightOutTables := semi.Right.RelProps.OutputTables() var projectExpressions []sql.Expression @@ -560,10 +597,15 @@ func addRightSemiJoins(m *memo.Memo) error { rGroup.RelProps.Distinct = memo.HashDistinctOp } - lookup := &memo.Lookup{ - Index: idx, - KeyExprs: keyExprs, - Nullmask: nullmask, + ita, err := plan.NewIndexedAccessForTableNode(leftRt, plan.NewLookupBuilder(idx.SqlIdx(), keyExprs, nullmask)) + if err != nil { + return err + } + + lookup := &memo.IndexScan{ + Table: ita, + Alias: aliasName, + Index: idx, } m.MemoizeLookupJoin(e.Group(), rGroup, semi.Left, plan.JoinTypeLookup, semi.Filter, lookup) } @@ -574,35 +616,46 @@ func addRightSemiJoins(m *memo.Memo) error { // lookupCandidates extracts source relation information required to check for // index lookups, including the source relation GroupId, the list of Indexes, // and the list of table filters. -func lookupCandidates(rel memo.RelExpr) (sql.TableId, []*memo.Index, []sql.Expression) { - var filters []sql.Expression - for done := false; !done; { - switch n := rel.(type) { - case *memo.Distinct: - rel = n.Child.First - case *memo.Filter: - rel = n.Child.First - for i := range n.Filters { - filters = append(filters, n.Filters[i]) - } - case *memo.Project: - rel = n.Child.First - default: - done = true - } +func lookupCandidates(rel memo.RelExpr, limitOk bool) (sql.TableId, []*memo.Index, []sql.Expression) { + id, indexes, filters, _ := dfsLookupCandidates(rel, limitOk) + return id, indexes, filters +} +func dfsLookupCandidates(rel memo.RelExpr, limitOk bool) (sql.TableId, []*memo.Index, []sql.Expression, bool) { + if rel == nil { + return 0, nil, nil, false + } + if !limitOk && rel.Group().RelProps.Limit != nil { + // LOOKUP through a LIMIT is invalid + return 0, nil, nil, false } switch n := rel.(type) { case *memo.TableAlias: tabId, _ := n.Group().RelProps.OutputTables().Next(1) - return sql.TableId(tabId), n.Indexes(), filters + return sql.TableId(tabId), n.Indexes(), nil, true case *memo.TableScan: tabId, _ := n.Group().RelProps.OutputTables().Next(1) - return sql.TableId(tabId), n.Indexes(), filters + return sql.TableId(tabId), n.Indexes(), nil, true + case *memo.IndexScan: + return dfsLookupCandidates(rel.Next(), limitOk) + case *memo.Filter: + var rel memo.RelExpr = n + for ; rel != nil; rel = rel.Next() { + switch rel := rel.(type) { + case *memo.Filter: + id, indexes, filters, ok := dfsLookupCandidates(rel.Child.First, limitOk) + if ok { + return id, indexes, append(filters, n.Filters...), ok + } + } + } + case *memo.Distinct: + return dfsLookupCandidates(n.Child.First, limitOk) + case *memo.Project: + return dfsLookupCandidates(n.Child.First, limitOk) default: } - return 0, nil, nil - + return 0, nil, nil, false } func addCrossHashJoins(m *memo.Memo) error { @@ -772,8 +825,11 @@ func addRangeHeapJoin(m *memo.Memo) error { return nil } - _, lIndexes, lFilters := lookupCandidates(join.Left.First) - _, rIndexes, rFilters := lookupCandidates(join.Right.First) + _, lIndexes, lFilters := lookupCandidates(join.Left.First, true) + _, rIndexes, rFilters := lookupCandidates(join.Right.First, true) + + leftTab := join.Left.RelProps.TableIdNodes()[0] + rightTab := join.Right.RelProps.TableIdNodes()[0] for _, filter := range getRangeFilters(join.Filter) { if !(satisfiesScalarRefs(filter.value, join.Left.RelProps.OutputTables()) && @@ -798,12 +854,18 @@ func addRangeHeapJoin(m *memo.Memo) error { return nil } - leftIndexScans := sortedIndexScansForTableCol(lIndexes, valueColRef, join.Left.RelProps.FuncDeps().Constants(), lFilters) + leftIndexScans, err := sortedIndexScansForTableCol(leftTab, lIndexes, valueColRef, join.Left.RelProps.FuncDeps().Constants(), lFilters) + if err != nil { + return err + } if leftIndexScans == nil { leftIndexScans = []*memo.IndexScan{nil} } for _, lIdx := range leftIndexScans { - rightIndexScans := sortedIndexScansForTableCol(rIndexes, minColRef, join.Right.RelProps.FuncDeps().Constants(), rFilters) + rightIndexScans, err := sortedIndexScansForTableCol(rightTab, rIndexes, minColRef, join.Right.RelProps.FuncDeps().Constants(), rFilters) + if err != nil { + return err + } if rightIndexScans == nil { rightIndexScans = []*memo.IndexScan{nil} } @@ -868,13 +930,16 @@ func addMergeJoins(m *memo.Memo) error { return nil } - leftTabId, lIndexes, lFilters := lookupCandidates(join.Left.First) - rightTabId, rIndexes, rFilters := lookupCandidates(join.Right.First) + leftTabId, lIndexes, lFilters := lookupCandidates(join.Left.First, true) + rightTabId, rIndexes, rFilters := lookupCandidates(join.Right.First, true) if leftTabId == 0 || rightTabId == 0 { return nil } + leftTab := join.Left.RelProps.TableIdNodes()[0] + rightTab := join.Right.RelProps.TableIdNodes()[0] + eqFilters := make([]filterAndPosition, 0, len(join.Filter)) for filterPos, filter := range join.Filter { switch eq := filter.(type) { @@ -954,11 +1019,17 @@ func addMergeJoins(m *memo.Memo) error { // To make the index scan, we need the first non-constant column in each index. leftColId := getOnlyColumnId(matchedEqFilters[0].filter.Left()) rightColId := getOnlyColumnId(matchedEqFilters[0].filter.Right()) - lIndexScan, success := makeIndexScan(lIndex, leftColId, lFilters) + lIndexScan, success, err := makeIndexScan(leftTab, lIndex, leftColId, lFilters) + if err != nil { + return err + } if !success { continue } - rIndexScan, success := makeIndexScan(rIndex, rightColId, rFilters) + rIndexScan, success, err := makeIndexScan(rightTab, rIndex, rightColId, rFilters) + if err != nil { + return err + } if !success { continue } @@ -1088,7 +1159,7 @@ func matchedFiltersForLeftIndex(lIndex *memo.Index, constants sql.ColSet, filter // sortedIndexScanForTableCol returns the first indexScan found for a relation // that provide a prefix for the joinFilters rel free attribute. I.e. the // indexScan will return the same rows as the rel, but sorted by |col|. -func sortedIndexScansForTableCol(indexes []*memo.Index, targetCol *expression.GetField, constants sql.ColSet, filters []sql.Expression) (ret []*memo.IndexScan) { +func sortedIndexScansForTableCol(tab plan.TableIdNode, indexes []*memo.Index, targetCol *expression.GetField, constants sql.ColSet, filters []sql.Expression) (ret []*memo.IndexScan, err error) { // valid index prefix is (constants..., targetCol) for _, idx := range indexes { found := false @@ -1108,15 +1179,18 @@ func sortedIndexScansForTableCol(indexes []*memo.Index, targetCol *expression.Ge if !found { continue } - indexScan, success := makeIndexScan(idx, matchedIdx, filters) + indexScan, success, err := makeIndexScan(tab, idx, matchedIdx, filters) + if err != nil { + return nil, err + } if success { ret = append(ret, indexScan) } } - return ret + return ret, nil } -func makeIndexScan(idx *memo.Index, matchedIdx sql.ColumnId, filters []sql.Expression) (*memo.IndexScan, bool) { +func makeIndexScan(tab plan.TableIdNode, idx *memo.Index, matchedIdx sql.ColumnId, filters []sql.Expression) (*memo.IndexScan, bool, error) { rang := make(sql.Range, len(idx.Cols())) var j int for { @@ -1151,12 +1225,44 @@ func makeIndexScan(idx *memo.Index, matchedIdx sql.ColumnId, filters []sql.Expre } if !idx.SqlIdx().CanSupport(rang) { - return nil, false + return nil, false, nil + } + + for i, typ := range idx.SqlIdx().ColumnExpressionTypes() { + if !types.Null.Equals(rang[i].Typ) && !typ.Type.Equals(rang[i].Typ) { + return nil, false, nil + } } + + l := sql.IndexLookup{Index: idx.SqlIdx(), Ranges: sql.RangeCollection{rang}} + + var tn sql.TableNode + var alias string + switch n := tab.(type) { + case sql.TableNode: + tn = n + case *plan.TableAlias: + child := n.Child + alias = n.Name() + var ok bool + tn, ok = child.(sql.TableNode) + if !ok { + return nil, false, fmt.Errorf("expected child of TableAlias to be sql.TableNode, found: %T", child) + } + default: + return nil, false, fmt.Errorf("expected sql.TableNode, found: %T", n) + } + + ret, err := plan.NewStaticIndexedAccessForTableNode(tn, l) + if err != nil { + return nil, false, err + } + return &memo.IndexScan{ - Idx: idx, - Range: rang, - }, true + Table: ret, + Index: idx, + Alias: alias, + }, true, nil } // isWeaklyMonotonic is a weak test of whether an expression diff --git a/sql/analyzer/rules.go b/sql/analyzer/rules.go index a9e4857533..8869818a4b 100644 --- a/sql/analyzer/rules.go +++ b/sql/analyzer/rules.go @@ -64,7 +64,6 @@ var OnceAfterDefault = []Rule{ {stripTableNameInDefaultsId, stripTableNamesFromColumnDefaults}, {pushFiltersId, pushFilters}, {optimizeJoinsId, optimizeJoins}, - {generateIndexScansId, costedIndexScans}, {finalizeSubqueriesId, finalizeSubqueries}, {applyIndexesFromOuterScopeId, applyIndexesFromOuterScope}, {replaceAggId, replaceAgg}, diff --git a/sql/memo/coster.go b/sql/memo/coster.go index 0ed61ca4f0..f7a683c6ab 100644 --- a/sql/memo/coster.go +++ b/sql/memo/coster.go @@ -108,6 +108,8 @@ func (c *coster) costRel(ctx *sql.Context, n RelExpr, s sql.StatsProvider) (floa return c.costSetOp(ctx, n, s) case *Filter: return c.costFilter(ctx, n, s) + case *IndexScan: + return c.costIndexScan(ctx, n, s) default: panic(fmt.Sprintf("coster does not support type: %T", n)) } @@ -219,14 +221,14 @@ func (c *coster) costMergeJoin(_ *sql.Context, n *MergeJoin, _ sql.StatsProvider // comparator. func isInjectiveMerge(n *MergeJoin, leftCompareExprs, rightCompareExprs []sql.Expression) bool { { - keyExprs, nullmask := keyExprsForIndexFromTupleComparison(n.Left.RelProps.tableNodes[0].Id(), n.InnerScan.Idx.Cols(), leftCompareExprs, rightCompareExprs) - if isInjectiveLookup(n.InnerScan.Idx, n.JoinBase, keyExprs, nullmask) { + keyExprs, nullmask := keyExprsForIndexFromTupleComparison(n.Left.RelProps.tableNodes[0].Id(), n.InnerScan.Index.Cols(), leftCompareExprs, rightCompareExprs) + if isInjectiveLookup(n.InnerScan.Index, n.JoinBase, keyExprs, nullmask) { return true } } { - keyExprs, nullmask := keyExprsForIndexFromTupleComparison(n.Right.RelProps.tableNodes[0].Id(), n.OuterScan.Idx.Cols(), leftCompareExprs, rightCompareExprs) - if isInjectiveLookup(n.OuterScan.Idx, n.JoinBase, keyExprs, nullmask) { + keyExprs, nullmask := keyExprsForIndexFromTupleComparison(n.Right.RelProps.tableNodes[0].Id(), n.OuterScan.Index.Cols(), leftCompareExprs, rightCompareExprs) + if isInjectiveLookup(n.OuterScan.Index, n.JoinBase, keyExprs, nullmask) { return true } } @@ -288,11 +290,19 @@ func exprReferencesTable(e sql.Expression, tabId sql.TableId) bool { func (c *coster) costLookupJoin(_ *sql.Context, n *LookupJoin, _ sql.StatsProvider) (float64, error) { l := n.Left.RelProps.card r := n.Right.RelProps.card - sel := lookupJoinSelectivity(n.Lookup) + lookup := n.Lookup.First.(*IndexScan) + sel := lookupJoinSelectivity(lookup, n.JoinBase) if sel == 0 { - return l*(cpuCostFactor+randIOCostFactor) - r*seqIOCostFactor, nil + return l*(cpuCostFactor+randIOCostFactor) - r*seqIOCostFactor - l*seqIOCostFactor, nil } - return l*r*sel*(cpuCostFactor+randIOCostFactor) - r*seqIOCostFactor, nil + if l*r*sel < l { + // 1 - (total rows - covered rows / total rows) + // + 1 to differentiate from sel = 0 case + // + coverage so bigger prefix = better + idxCoverage := 1.0 - float64(len(lookup.Index.Cols())-len(lookup.Table.Expressions()))/float64(len(lookup.Index.Cols())) + return (l+1+idxCoverage)*(cpuCostFactor+randIOCostFactor) - r*seqIOCostFactor - l*seqIOCostFactor, nil + } + return l*r*sel*(cpuCostFactor+randIOCostFactor) - r*seqIOCostFactor - l*seqIOCostFactor, nil } func (c *coster) costRangeHeapJoin(_ *sql.Context, n *RangeHeapJoin, _ sql.StatsProvider) (float64, error) { @@ -305,7 +315,7 @@ func (c *coster) costRangeHeapJoin(_ *sql.Context, n *RangeHeapJoin, _ sql.Stats return l * expectedNumberOfOverlappingJoins * (seqIOCostFactor), nil } -func (c *coster) costLateralJoin(ctx *sql.Context, n *LateralJoin, _ sql.StatsProvider) (float64, error) { +func (c *coster) costLateralJoin(_ *sql.Context, n *LateralJoin, _ sql.StatsProvider) (float64, error) { l := n.Left.RelProps.card r := n.Right.RelProps.card return (l*r-1)*seqIOCostFactor + (l*r)*cpuCostFactor, nil @@ -315,7 +325,8 @@ func (c *coster) costConcatJoin(_ *sql.Context, n *ConcatJoin, _ sql.StatsProvid l := n.Left.RelProps.card var sel float64 for _, l := range n.Concat { - sel += lookupJoinSelectivity(l) + lookup := l.First.(*IndexScan) + sel += lookupJoinSelectivity(lookup, n.JoinBase) } return l*sel*concatCostFactor*(randIOCostFactor+cpuCostFactor) - n.Right.RelProps.card*seqIOCostFactor, nil } @@ -339,11 +350,11 @@ func (c *coster) costDistinct(_ *sql.Context, n *Distinct, _ sql.StatsProvider) // lookupJoinSelectivity estimates the selectivity of a join condition with n lhs rows and m rhs rows. // A join with a selectivity of k will return k*(n*m) rows. // Special case: A join with a selectivity of 0 will return n rows. -func lookupJoinSelectivity(l *Lookup) float64 { - if isInjectiveLookup(l.Index, l.Parent, l.KeyExprs, l.Nullmask) { +func lookupJoinSelectivity(l *IndexScan, joinBase *JoinBase) float64 { + if isInjectiveLookup(l.Index, joinBase, l.Table.Expressions(), l.Table.NullMask()) { return 0 } - return math.Pow(perKeyCostReductionFactor, float64(len(l.KeyExprs))) + return math.Pow(perKeyCostReductionFactor, float64(len(l.Table.Expressions()))) * optimisticJoinSel } // isInjectiveLookup returns whether every lookup with the given key expressions is guarenteed to return @@ -416,6 +427,11 @@ func (c *coster) costFilter(_ *sql.Context, f *Filter, _ sql.StatsProvider) (flo // 1 unit of compute for each input row return f.Child.RelProps.card * cpuCostFactor * float64(len(f.Filters)), nil } + +func (c *coster) costIndexScan(_ *sql.Context, f *IndexScan, _ sql.StatsProvider) (float64, error) { + return 0, nil +} + func NewDefaultCarder() Carder { return &carder{} } @@ -461,7 +477,8 @@ func (c *carder) cardRel(ctx *sql.Context, n RelExpr, s sql.StatsProvider) (floa jp := n.JoinPrivate() switch n := n.(type) { case *LookupJoin: - sel := lookupJoinSelectivity(n.Lookup) * optimisticJoinSel + lookup := n.Lookup.First.(*IndexScan) + sel := lookupJoinSelectivity(lookup, n.JoinBase) if sel == 0 { return n.Left.RelProps.card, nil } @@ -469,7 +486,8 @@ func (c *carder) cardRel(ctx *sql.Context, n RelExpr, s sql.StatsProvider) (floa case *ConcatJoin: var sel float64 for _, l := range n.Concat { - sel += lookupJoinSelectivity(l) + lookup := l.First.(*IndexScan) + sel += lookupJoinSelectivity(lookup, n.JoinBase) } return n.Left.RelProps.card * optimisticJoinSel * sel, nil case *LateralJoin: @@ -492,6 +510,9 @@ func (c *carder) cardRel(ctx *sql.Context, n RelExpr, s sql.StatsProvider) (floa return n.Child.RelProps.card, nil case *Filter: return n.Child.RelProps.card * .75, nil + case *IndexScan: + //card := float64(n.Group().RelProps.stat.RowCount()) + return c.statsRead(ctx, n.Table.TableNode.UnderlyingTable(), n.Table.TableNode.(sql.TableNode).Database().Name(), s) default: panic(fmt.Sprintf("unknown type %T", n)) } diff --git a/sql/memo/exec_builder.go b/sql/memo/exec_builder.go index d2c98d5eb9..58fcb4ddc9 100644 --- a/sql/memo/exec_builder.go +++ b/sql/memo/exec_builder.go @@ -58,49 +58,9 @@ func (b *ExecBuilder) buildAntiJoin(j *AntiJoin, children ...sql.Node) (sql.Node return plan.NewJoin(children[0], children[1], j.Op, filters), nil } -func (b *ExecBuilder) buildLookup(l *Lookup, children ...sql.Node) (sql.Node, error) { - var ret sql.Node - var err error - - if err != nil { - return nil, err - } - switch n := children[0].(type) { - case sql.TableNode: - ret, err = plan.NewIndexedAccessForTableNode(n, plan.NewLookupBuilder(l.Index.SqlIdx(), l.KeyExprs, l.Nullmask)) - case *plan.TableAlias: - ret, err = plan.NewIndexedAccessForTableNode(n.Child.(sql.TableNode), plan.NewLookupBuilder(l.Index.SqlIdx(), l.KeyExprs, l.Nullmask)) - ret = plan.NewTableAlias(n.Name(), ret) - case *plan.Distinct: - ret, err = b.buildLookup(l, n.Child) - ret = plan.NewDistinct(ret) - case *plan.OrderedDistinct: - ret, err = b.buildLookup(l, n.Child) - ret = plan.NewOrderedDistinct(ret) - case *plan.Filter: - ret, err = b.buildLookup(l, n.Child) - ret = plan.NewFilter(n.Expression, ret) - case *plan.Project: - ret, err = b.buildLookup(l, n.Child) - ret = plan.NewProject(n.Projections, ret) - case *plan.Limit: - ret, err = b.buildLookup(l, n.Child) - ret = plan.NewLimit(n.Limit, ret) - case *plan.Sort: - ret, err = b.buildLookup(l, n.Child) - ret = plan.NewSort(n.SortFields, ret) - default: - panic(fmt.Sprintf("unexpected lookup child %T", n)) - } - if err != nil { - return nil, err - } - return ret, nil -} - func (b *ExecBuilder) buildLookupJoin(j *LookupJoin, children ...sql.Node) (sql.Node, error) { left := children[0] - right, err := b.buildLookup(j.Lookup, children[1]) + right, err := b.buildIndexScan(j.Lookup.First.(*IndexScan), children[1]) if err != nil { return nil, err } @@ -131,7 +91,7 @@ func (b *ExecBuilder) buildRangeHeap(sr *RangeHeap, children ...sql.Node) (ret s default: var childNode sql.Node if sr.MinIndex != nil { - childNode, err = b.buildIndexScan(sr.MinIndex, n) + childNode, err = b.buildIndexScan(sr.MinIndex, children[0]) } else { sortExpr := sr.MinExpr if err != nil { @@ -166,7 +126,7 @@ func (b *ExecBuilder) buildRangeHeapJoin(j *RangeHeapJoin, children ...sql.Node) var left sql.Node var err error if j.RangeHeap.ValueIndex != nil { - left, err = b.buildIndexScan(j.RangeHeap.ValueIndex, children[0]) + left, err = b.buildIndexScan(j.RangeHeap.ValueIndex) if err != nil { return nil, err } @@ -201,12 +161,12 @@ func (b *ExecBuilder) buildConcatJoin(j *ConcatJoin, children ...sql.Node) (sql. name = n.Name() } - right, err := b.buildLookup(j.Concat[0], rightC) + right, err := b.buildIndexScan(j.Concat[0].First.(*IndexScan), children[1]) if err != nil { return nil, err } for _, look := range j.Concat[1:] { - l, err := b.buildLookup(look, rightC) + l, err := b.buildIndexScan(look.First.(*IndexScan), children[1]) if err != nil { return nil, err } @@ -250,16 +210,26 @@ func (b *ExecBuilder) buildHashJoin(j *HashJoin, children ...sql.Node) (sql.Node func (b *ExecBuilder) buildIndexScan(i *IndexScan, children ...sql.Node) (sql.Node, error) { // need keyExprs for whole range for every dimension - l := sql.IndexLookup{Index: i.Idx.SqlIdx(), Ranges: sql.RangeCollection{i.Range}} + if len(children) == 0 { + if i.Alias != "" { + return plan.NewTableAlias(i.Alias, i.Table), nil + } + return i.Table, nil + } var ret sql.Node var err error switch n := children[0].(type) { case sql.TableNode: - ret, err = plan.NewStaticIndexedAccessForTableNode(n, l) + if i.Alias != "" { + ret = plan.NewTableAlias(i.Alias, i.Table) + } else { + ret = i.Table + } case *plan.TableAlias: - ret, err = plan.NewStaticIndexedAccessForTableNode(n.Child.(sql.TableNode), l) - ret = plan.NewTableAlias(n.Name(), ret) + ret = plan.NewTableAlias(n.Name(), i.Table) + case *plan.IndexedTableAccess: + ret = i.Table case *plan.Distinct: ret, err = b.buildIndexScan(i, n.Child) ret = plan.NewDistinct(ret) @@ -301,17 +271,11 @@ func (b *ExecBuilder) buildMergeJoin(j *MergeJoin, children ...sql.Node) (sql.No if err != nil { return nil, err } - if checkIndexTypeMismatch(j.InnerScan.Idx.SqlIdx(), j.InnerScan.Range) { - return nil, fmt.Errorf("index scan type mismatch") - } - outer, err := b.buildIndexScan(j.OuterScan, children[1]) if err != nil { return nil, err } - if checkIndexTypeMismatch(j.OuterScan.Idx.SqlIdx(), j.OuterScan.Range) { - return nil, fmt.Errorf("index scan type mismatch") - } + if j.SwapCmp { switch cmp := j.Filter[0].(type) { case *expression.Equals: diff --git a/sql/memo/expr_group.go b/sql/memo/expr_group.go index c061008c12..1ab1c5aec6 100644 --- a/sql/memo/expr_group.go +++ b/sql/memo/expr_group.go @@ -94,12 +94,66 @@ func (e *ExprGroup) finalize(node sql.Node) (sql.Node, error) { if props.sort != nil { result = plan.NewSort(props.sort, result) } - if props.limit != nil { - result = plan.NewLimit(props.limit, result) + if props.Limit != nil { + result = plan.NewLimit(props.Limit, result) } return result, nil } +// fixConflicts edits the children of a new best plan to account +// for implementation correctness, like conflicting table lookups +// and sorting. For example, a merge join with a filter child that +// could alternatively be implemented as an indexScan should reject +// the static indexScan to maintain the merge join's correctness. +func (e *ExprGroup) fixConflicts() { + switch n := e.Best.(type) { + case *MergeJoin: + // todo: we should permit conflicting static indexScans with same index IDs + n.Left.findIndexScanConflict() + n.Right.findIndexScanConflict() + case *LookupJoin: + // LOOKUP_JOIN is more performant than INNER_JOIN with static indexScan + n.Right.findIndexScanConflict() + } +} + +// findIndexScanConflict prevents indexScans from replacing filter nodes +// for certain query plans that require different indexes or use indexes +// in a special way. +func (e *ExprGroup) findIndexScanConflict() { + e.fixTableScanPath() +} + +// fixTableScanPath updates the intermediate group's |best| plan to +// the path leading to a tableScan leaf. +func (e *ExprGroup) fixTableScanPath() bool { + n := e.First + for n != nil { + src, ok := n.(SourceRel) + if !ok { + // not a source, try to find path through children + for _, c := range n.Children() { + if c.fixTableScanPath() { + // found path, update best + e.Best = n + return true + } + } + n = n.Next() + continue + } + _, ok = src.(*IndexScan) + if ok { + n = n.Next() + continue + } + // is a source, not an indexScan + e.Best = n + return true + } + return false +} + func (e *ExprGroup) String() string { b := strings.Builder{} n := e.First diff --git a/sql/memo/join_order_builder.go b/sql/memo/join_order_builder.go index 0e1e7f8871..7b8d1ac4af 100644 --- a/sql/memo/join_order_builder.go +++ b/sql/memo/join_order_builder.go @@ -212,7 +212,7 @@ func (j *joinOrderBuilder) populateSubgraph(n sql.Node) (vertexSet, edgeSet, *Ex return j.buildFilter(n.Child, n.Cond) case *plan.Limit: _, _, group = j.populateSubgraph(n.Child) - group.RelProps.limit = n.Limit + group.RelProps.Limit = n.Limit case *plan.Project: return j.buildProject(n) case *plan.Sort: diff --git a/sql/memo/memo.go b/sql/memo/memo.go index 045515fe57..2d208128f6 100644 --- a/sql/memo/memo.go +++ b/sql/memo/memo.go @@ -18,11 +18,11 @@ import ( "fmt" "strings" - "github.com/dolthub/go-mysql-server/sql/expression" - "github.com/dolthub/go-mysql-server/sql/transform" - "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/expression" "github.com/dolthub/go-mysql-server/sql/plan" + "github.com/dolthub/go-mysql-server/sql/stats" + "github.com/dolthub/go-mysql-server/sql/transform" ) type GroupId uint16 @@ -70,6 +70,10 @@ func (m *Memo) Root() *ExprGroup { return m.root } +func (m *Memo) StatsProvider() sql.StatsProvider { + return m.statsProv +} + // newExprGroup creates a new logical expression group to encapsulate the // action of a SQL clause. // TODO: this is supposed to deduplicate logically equivalent table scans @@ -133,24 +137,68 @@ func (m *Memo) MemoizeInnerJoin(grp, left, right *ExprGroup, op plan.JoinType, f return grp } -func (m *Memo) MemoizeLookupJoin(grp, left, right *ExprGroup, op plan.JoinType, filter []sql.Expression, lookup *Lookup) *ExprGroup { +func (m *Memo) MemoizeLookupJoin(grp, left, right *ExprGroup, op plan.JoinType, filter []sql.Expression, lookup *IndexScan) *ExprGroup { + itaGrp := m.MemoizeIndexScan(nil, lookup.Table, lookup.Alias, lookup.Index) + itaGrp.Best = itaGrp.First newJoin := &LookupJoin{ JoinBase: &JoinBase{ relBase: &relBase{}, Left: left, Right: right, - Op: op, + Op: op.AsLookup(), + Filter: filter, + }, + Lookup: itaGrp, + } + + if grp == nil { + return m.NewExprGroup(newJoin) + } + newJoin.g = grp + grp.Prepend(newJoin) + + if isInjectiveLookup(lookup.Index, newJoin.JoinBase, lookup.Table.Expressions(), lookup.Table.NullMask()) { + // lookup stats has dependency on join FDs, calculate after creating group + itaGrp.RelProps.stat = &stats.Statistic{RowCnt: 1} + } + + return grp +} + +// MemoizeConcatLookupJoin creates a lookup join over a set of disjunctions. +// If a LOOKUP_JOIN simulates x = v1, a concat lookup performs x in (v1, v2, v3, ...) +func (m *Memo) MemoizeConcatLookupJoin(grp, left, right *ExprGroup, op plan.JoinType, filter []sql.Expression, lookups []*IndexScan) *ExprGroup { + var itaGrps []*ExprGroup + for _, l := range lookups { + itaGrp := m.MemoizeIndexScan(nil, l.Table, "", l.Index) + itaGrp.Best = itaGrp.First + itaGrps = append(itaGrps, itaGrp) + } + newJoin := &ConcatJoin{ + JoinBase: &JoinBase{ + relBase: &relBase{}, + Left: left, + Right: right, + Op: op.AsLookup(), Filter: filter, }, - Lookup: lookup, + Concat: itaGrps, } - newJoin.Lookup.Parent = newJoin.JoinBase if grp == nil { return m.NewExprGroup(newJoin) } newJoin.g = grp grp.Prepend(newJoin) + + for i, itaGrp := range itaGrps { + lookup := lookups[i] + if isInjectiveLookup(lookup.Index, newJoin.JoinBase, lookup.Table.Expressions(), lookup.Table.NullMask()) { + // lookup stats has dependency on join FDs, calculate after creating group + itaGrp.RelProps.stat = &stats.Statistic{RowCnt: 1} + } + } + return grp } @@ -188,8 +236,6 @@ func (m *Memo) MemoizeMergeJoin(grp, left, right *ExprGroup, lIdx, rIdx *IndexSc OuterScan: rIdx, SwapCmp: swapCmp, } - rel.InnerScan.Parent = rel.JoinBase - rel.OuterScan.Parent = rel.JoinBase if grp == nil { return m.NewExprGroup(rel) @@ -213,6 +259,25 @@ func (m *Memo) MemoizeProject(grp, child *ExprGroup, projections []sql.Expressio return grp } +// MemoizeIndexScan creates a source node that uses a specific index to +// access data. IndexScans are either static and read a specific set of +// ranges, or dynamic and use a lookup template that is iteratively +// bound and executed during LOOKUP_JOINs. +func (m *Memo) MemoizeIndexScan(grp *ExprGroup, ita *plan.IndexedTableAccess, alias string, index *Index) *ExprGroup { + rel := &IndexScan{ + sourceBase: &sourceBase{relBase: &relBase{}}, + Table: ita, + Alias: alias, + Index: index, + } + if grp == nil { + return m.NewExprGroup(rel) + } + rel.g = grp + grp.Prepend(rel) + return grp +} + func (m *Memo) MemoizeFilter(grp, child *ExprGroup, filters []sql.Expression) *ExprGroup { rel := &Filter{ relBase: &relBase{}, @@ -297,6 +362,9 @@ func (m *Memo) optimizeMemoGroup(grp *ExprGroup) error { n = n.Next() } + // Certain "best" groups are incompatible. + grp.fixConflicts() + grp.Done = true grp.RelProps.card, err = m.s.EstimateCard(m.Ctx, grp.Best, m.statsProv) if err != nil { @@ -375,13 +443,14 @@ func (m *Memo) ApplyHint(hint Hint) { func (m *Memo) WithJoinOrder(tables []string) { // order maps groupId -> table dependencies - order := make(map[GroupId]uint64) + order := make(map[sql.TableId]uint64) for i, t := range tables { - id, ok := m.TableProps.GetId(t) - if !ok { - return + for _, n := range m.root.RelProps.TableIdNodes() { + if strings.EqualFold(t, n.Name()) { + order[n.Id()] = uint64(i) + break + } } - order[id] = uint64(i) } hint := newJoinOrderHint(order) hint.build(m.root) @@ -391,9 +460,16 @@ func (m *Memo) WithJoinOrder(tables []string) { } func (m *Memo) WithJoinOp(op HintType, left, right string) { - lGrp, _ := m.TableProps.GetId(left) - rGrp, _ := m.TableProps.GetId(right) - hint := newjoinOpHint(op, lGrp, rGrp) + var lTab, rTab sql.TableId + for _, n := range m.root.RelProps.TableIdNodes() { + if strings.EqualFold(left, n.Name()) { + lTab = n.Id() + } + if strings.EqualFold(right, n.Name()) { + rTab = n.Id() + } + } + hint := newjoinOpHint(op, lTab, rTab) if !hint.isValid() { return } @@ -688,18 +764,8 @@ func (r *JoinBase) Copy() *JoinBase { } } -type Lookup struct { - Index *Index - KeyExprs []sql.Expression - Nullmask []bool - - Parent *JoinBase -} - -type IndexScan struct { - Idx *Index - Range sql.Range - Parent *JoinBase +func (r *LookupJoin) Children() []*ExprGroup { + return []*ExprGroup{r.Left, r.Right} } // RangeHeap contains all the information necessary to construct a RangeHeap join. diff --git a/sql/memo/memo.og.go b/sql/memo/memo.og.go index 0491a868a3..ab2f7b84c9 100644 --- a/sql/memo/memo.og.go +++ b/sql/memo/memo.og.go @@ -87,7 +87,8 @@ func (r *AntiJoin) JoinPrivate() *JoinBase { type LookupJoin struct { *JoinBase - Lookup *Lookup + Lookup *ExprGroup + Injective bool } var _ RelExpr = (*LookupJoin)(nil) @@ -119,7 +120,7 @@ func (r *RangeHeapJoin) JoinPrivate() *JoinBase { type ConcatJoin struct { *JoinBase - Concat []*Lookup + Concat []*ExprGroup } var _ RelExpr = (*ConcatJoin)(nil) @@ -230,6 +231,40 @@ func (r *TableScan) Children() []*ExprGroup { return nil } +type IndexScan struct { + *sourceBase + Table *plan.IndexedTableAccess + Index *Index + Alias string +} + +var _ RelExpr = (*IndexScan)(nil) +var _ SourceRel = (*IndexScan)(nil) + +func (r *IndexScan) String() string { + return FormatExpr(r) +} + +func (r *IndexScan) Name() string { + return strings.ToLower(r.Table.Name()) +} + +func (r *IndexScan) TableId() sql.TableId { + return TableIdForSource(r.g.Id) +} + +func (r *IndexScan) TableIdNode() plan.TableIdNode { + return r.Table +} + +func (r *IndexScan) OutputCols() sql.Schema { + return r.Table.Schema() +} + +func (r *IndexScan) Children() []*ExprGroup { + return nil +} + type Values struct { *sourceBase Table *plan.ValueDerivedTable @@ -624,6 +659,8 @@ func FormatExpr(r exprType) string { return fmt.Sprintf("lateraljoin %d %d", r.Left.Id, r.Right.Id) case *TableScan: return fmt.Sprintf("tablescan: %s", r.Name()) + case *IndexScan: + return fmt.Sprintf("indexscan: %s", r.Name()) case *Values: return fmt.Sprintf("values: %s", r.Name()) case *TableAlias: @@ -686,6 +723,8 @@ func buildRelExpr(b *ExecBuilder, r RelExpr, children ...sql.Node) (sql.Node, er result, err = b.buildLateralJoin(r, children...) case *TableScan: result, err = b.buildTableScan(r, children...) + case *IndexScan: + result, err = b.buildIndexScan(r, children...) case *Values: result, err = b.buildValues(r, children...) case *TableAlias: diff --git a/sql/memo/rel_props.go b/sql/memo/rel_props.go index d8968dbda0..6164b010f2 100644 --- a/sql/memo/rel_props.go +++ b/sql/memo/rel_props.go @@ -36,10 +36,11 @@ type relProps struct { outputTables sql.FastIntSet tableNodes []plan.TableIdNode + stat sql.Statistic card float64 Distinct distinctOp - limit sql.Expression + Limit sql.Expression sort sql.SortFields } @@ -70,9 +71,14 @@ func newRelProps(rel RelExpr) *relProps { for tw, ok = n.(sql.TableNode); !ok; tw, ok = n.Children()[0].(sql.TableNode) { } - tin := tw.UnderlyingTable().(sql.PrimaryKeyTable) + var sch sql.Schema + switch n := tw.UnderlyingTable().(type) { + case sql.PrimaryKeyTable: + sch = n.PrimaryKeySchema().Schema + default: + sch = n.Schema() + } firstCol, _ := n.Columns().Next(1) - sch := tin.PrimaryKeySchema().Schema var colset sql.ColSet for _, c := range n.Schema() { @@ -102,6 +108,10 @@ func idxExprsColumns(idx sql.Index) []string { return columns } +func (p *relProps) SetStats(s sql.Statistic) { + p.stat = s +} + func (p *relProps) populateFds() { var fds *sql.FuncDepSet switch rel := p.grp.First.(type) { @@ -277,6 +287,8 @@ func allTableCols(rel SourceRel) sql.Schema { break } table = rt.UnderlyingTable() + case *IndexScan: + table = rel.Table.TableNode.UnderlyingTable() case *TableScan: table = rel.Table.(sql.TableNode).UnderlyingTable() default: @@ -344,10 +356,18 @@ func (p *relProps) populateOutputTables() { p.tableNodes = []plan.TableIdNode{n.TableIdNode()} case *AntiJoin: p.outputTables = n.Left.RelProps.OutputTables() - p.tableNodes = n.Left.RelProps.TableIdNodes() + leftNodeCnt := len(n.JoinPrivate().Left.RelProps.tableNodes) + rightNodeCnt := len(n.JoinPrivate().Right.RelProps.tableNodes) + p.tableNodes = make([]plan.TableIdNode, leftNodeCnt+rightNodeCnt) + copy(p.tableNodes, n.JoinPrivate().Left.RelProps.tableNodes) + copy(p.tableNodes[leftNodeCnt:], n.JoinPrivate().Right.RelProps.tableNodes) case *SemiJoin: p.outputTables = n.Left.RelProps.OutputTables() - p.tableNodes = n.Left.RelProps.TableIdNodes() + leftNodeCnt := len(n.JoinPrivate().Left.RelProps.tableNodes) + rightNodeCnt := len(n.JoinPrivate().Right.RelProps.tableNodes) + p.tableNodes = make([]plan.TableIdNode, leftNodeCnt+rightNodeCnt) + copy(p.tableNodes, n.JoinPrivate().Left.RelProps.tableNodes) + copy(p.tableNodes[leftNodeCnt:], n.JoinPrivate().Right.RelProps.tableNodes) case *Distinct: p.outputTables = n.Child.RelProps.OutputTables() p.tableNodes = n.Child.RelProps.TableIdNodes() @@ -378,7 +398,7 @@ func (p *relProps) populateOutputTables() { func (p *relProps) populateInputTables() { switch n := p.grp.First.(type) { case SourceRel: - p.inputTables = sql.NewFastIntSet(int(p.grp.Id)) + p.inputTables = sql.NewFastIntSet(int(n.TableIdNode().Id())) case *Distinct: p.inputTables = n.Child.RelProps.InputTables() case *Project: @@ -420,6 +440,8 @@ func (p *relProps) outputColsForRel(r RelExpr) sql.ColSet { return r.outputCols() case *Max1Row: return r.outputCols() + case *IndexScan: + return p.outputColsForRel(r.Next()) default: panic("unknown type") } @@ -501,7 +523,7 @@ func sortedColsForRel(rel RelExpr) sql.Schema { } case *MergeJoin: var ret sql.Schema - for _, e := range r.InnerScan.Idx.SqlIdx().Expressions() { + for _, e := range r.InnerScan.Table.Index().Expressions() { // TODO columns can have "." characters, this will miss cases parts := strings.Split(e, ".") var name string @@ -512,7 +534,7 @@ func sortedColsForRel(rel RelExpr) sql.Schema { } ret = append(ret, &sql.Column{ Name: strings.ToLower(name), - Source: strings.ToLower(r.InnerScan.Idx.SqlIdx().Table()), + Source: strings.ToLower(r.InnerScan.Table.Name()), Nullable: true}, ) } diff --git a/sql/memo/select_hints.go b/sql/memo/select_hints.go index 5b6aaa9802..11096916ac 100644 --- a/sql/memo/select_hints.go +++ b/sql/memo/select_hints.go @@ -163,12 +163,12 @@ func parseJoinHints(comment string) []Hint { // {1: 010, 2: 100, 3: 001, 4: 110, 5: 111} type joinOrderHint struct { groups map[GroupId]vertexSet - order map[GroupId]uint64 + order map[sql.TableId]uint64 // cache avoids recomputing satisfiability for a RelExpr cache map[uint64]bool } -func newJoinOrderHint(order map[GroupId]uint64) *joinOrderHint { +func newJoinOrderHint(order map[sql.TableId]uint64) *joinOrderHint { return &joinOrderHint{ groups: make(map[GroupId]vertexSet), cache: make(map[uint64]bool), @@ -181,7 +181,7 @@ func (o joinOrderHint) build(grp *ExprGroup) { // convert global table order to hint order inputs := grp.RelProps.InputTables() for idx, ok := inputs.Next(0); ok; idx, ok = inputs.Next(idx + 1) { - if i, ok := o.order[GroupId(idx)]; ok { + if i, ok := o.order[sql.TableId(idx)]; ok { // If group |idx+1| is a dependency of this table, record the // ordinal position of that group given by the hint order. s = s.add(i) @@ -277,7 +277,7 @@ type joinOpHint struct { l, r sql.FastIntSet } -func newjoinOpHint(op HintType, left, right GroupId) joinOpHint { +func newjoinOpHint(op HintType, left, right sql.TableId) joinOpHint { return joinOpHint{ op: op, l: sql.NewFastIntSet(int(left)), diff --git a/sql/plan/indexed_table_access.go b/sql/plan/indexed_table_access.go index 206b381d12..137471fe09 100644 --- a/sql/plan/indexed_table_access.go +++ b/sql/plan/indexed_table_access.go @@ -49,6 +49,7 @@ var _ sql.Node = (*IndexedTableAccess)(nil) var _ sql.Nameable = (*IndexedTableAccess)(nil) var _ sql.Expressioner = (*IndexedTableAccess)(nil) var _ sql.CollationCoercible = (*IndexedTableAccess)(nil) +var _ sql.TableNode = (*IndexedTableAccess)(nil) // NewIndexedAccessForTableNode creates an IndexedTableAccess node if the resolved table embeds // an IndexAddressableTable, otherwise returns an error. @@ -161,6 +162,14 @@ func NewStaticIndexedAccessForFullTextTable(node sql.TableNode, lookup sql.Index } } +func (i *IndexedTableAccess) WithDatabase(database sql.Database) (sql.Node, error) { + return i, nil +} + +func (i *IndexedTableAccess) UnderlyingTable() sql.Table { + return i.TableNode.UnderlyingTable() +} + // WithId implements sql.TableIdNode func (i *IndexedTableAccess) WithId(id sql.TableId) TableIdNode { ret := *i @@ -381,6 +390,13 @@ func (i *IndexedTableAccess) Expressions() []sql.Expression { return i.lb.Expressions() } +func (i *IndexedTableAccess) NullMask() []bool { + if !i.lookup.IsEmpty() { + return nil + } + return i.lb.matchesNullMask +} + // WithExpressions implements sql.Expressioner func (i *IndexedTableAccess) WithExpressions(exprs ...sql.Expression) (sql.Node, error) { if !i.lookup.IsEmpty() {