Unverified 提交 58a8b8bf authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1769 from katzyn/join

Delay creation of index conditions for ON conditions to avoid NPE
......@@ -21,6 +21,10 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #1762: NullPointerException in Parser. Introduced in 1.4.198
</li>
<li>PR #1768: Add more context-sensitive keywords
</li>
<li>Issue #1758: sequence restart issue with 1.4.198
</li>
<li>Issue #1759: SELECT &#8230; FOR UPDATE returns old data in 1.4.198
......
......@@ -1382,6 +1382,7 @@ public class Select extends Query {
private double preparePlan(boolean parse) {
TableFilter[] topArray = topFilters.toArray(new TableFilter[0]);
for (TableFilter t : topArray) {
t.createIndexConditions();
t.setFullCondition(condition);
}
......
......@@ -711,16 +711,29 @@ public class TableFilter implements ColumnResolver {
public void mapAndAddFilter(Expression on) {
on.mapColumns(this, 0, Expression.MAP_INITIAL);
addFilterCondition(on, true);
on.createIndexConditions(session, this);
if (nestedJoin != null) {
on.mapColumns(nestedJoin, 0, Expression.MAP_INITIAL);
on.createIndexConditions(session, nestedJoin);
}
if (join != null) {
join.mapAndAddFilter(on);
}
}
public void createIndexConditions() {
if (joinCondition != null) {
joinCondition.createIndexConditions(session, this);
if (nestedJoin != null) {
joinCondition.createIndexConditions(session, nestedJoin);
}
}
if (join != null) {
join.createIndexConditions();
}
if (nestedJoin != null) {
nestedJoin.createIndexConditions();
}
}
public TableFilter getJoin() {
return join;
}
......
......@@ -1172,14 +1172,14 @@ public class TestCases extends TestDb {
" P.SALARY,\n" +
" O.ID,\n" +
" O.NAME\n" +
"FROM PUBLIC.ORGANIZATION O\n" +
" /* PUBLIC.PRIMARY_KEY_D: ID = ?1 */\n" +
" /* WHERE O.ID = ?1\n" +
"FROM PUBLIC.PERSON P\n" +
" /* PUBLIC.PRIMARY_KEY_8: ID = ?1 */\n" +
" /* WHERE P.ID = ?1\n" +
" */\n" +
" /* scanCount: 2 */\n" +
"INNER JOIN PUBLIC.PERSON P\n" +
" /* PUBLIC.PRIMARY_KEY_8: ID = O.ID\n" +
" AND ID = ?1\n" +
"INNER JOIN PUBLIC.ORGANIZATION O\n" +
" /* PUBLIC.PRIMARY_KEY_D: ID = ?1\n" +
" AND ID = P.ID\n" +
" */\n" +
" ON 1=1\n" +
" /* scanCount: 2 */\n" +
......
......@@ -204,8 +204,8 @@ is null or three.val>=DATE'2006-07-01';
explain select * from one natural join two left join two three on
one.id=three.id left join one four on two.id=four.id where three.val
is null or three.val>=DATE'2006-07-01';
#+mvStore#>> SELECT ONE.ID, TWO.VAL, THREE.ID, THREE.VAL, FOUR.ID FROM PUBLIC.ONE /* PUBLIC.ONE.tableScan */ INNER JOIN PUBLIC.TWO /* PUBLIC.PRIMARY_KEY_14: ID = PUBLIC.ONE.ID AND ID = PUBLIC.ONE.ID */ ON 1=1 /* WHERE PUBLIC.ONE.ID = PUBLIC.TWO.ID */ LEFT OUTER JOIN PUBLIC.TWO THREE /* PUBLIC.PRIMARY_KEY_14: ID = ONE.ID */ ON ONE.ID = THREE.ID LEFT OUTER JOIN PUBLIC.ONE FOUR /* PUBLIC.PRIMARY_KEY_1: ID = TWO.ID */ ON TWO.ID = FOUR.ID WHERE (PUBLIC.ONE.ID = PUBLIC.TWO.ID) AND ((THREE.VAL IS NULL) OR (THREE.VAL >= DATE '2006-07-01'))
#-mvStore#>> SELECT ONE.ID, TWO.VAL, THREE.ID, THREE.VAL, FOUR.ID FROM PUBLIC.ONE /* PUBLIC.PRIMARY_KEY_1 */ INNER JOIN PUBLIC.TWO /* PUBLIC.PRIMARY_KEY_14: ID = PUBLIC.ONE.ID AND ID = PUBLIC.ONE.ID */ ON 1=1 /* WHERE PUBLIC.ONE.ID = PUBLIC.TWO.ID */ LEFT OUTER JOIN PUBLIC.TWO THREE /* PUBLIC.PRIMARY_KEY_14: ID = ONE.ID */ ON ONE.ID = THREE.ID LEFT OUTER JOIN PUBLIC.ONE FOUR /* PUBLIC.PRIMARY_KEY_1: ID = TWO.ID */ ON TWO.ID = FOUR.ID WHERE (PUBLIC.ONE.ID = PUBLIC.TWO.ID) AND ((THREE.VAL IS NULL) OR (THREE.VAL >= DATE '2006-07-01'))
#+mvStore#>> SELECT ONE.ID, TWO.VAL, THREE.ID, THREE.VAL, FOUR.ID FROM PUBLIC.ONE /* PUBLIC.ONE.tableScan */ INNER JOIN PUBLIC.TWO /* PUBLIC.PRIMARY_KEY_14: ID = PUBLIC.ONE.ID */ ON 1=1 /* WHERE PUBLIC.ONE.ID = PUBLIC.TWO.ID */ LEFT OUTER JOIN PUBLIC.TWO THREE /* PUBLIC.PRIMARY_KEY_14: ID = ONE.ID */ ON ONE.ID = THREE.ID LEFT OUTER JOIN PUBLIC.ONE FOUR /* PUBLIC.PRIMARY_KEY_1: ID = TWO.ID */ ON TWO.ID = FOUR.ID WHERE (PUBLIC.ONE.ID = PUBLIC.TWO.ID) AND ((THREE.VAL IS NULL) OR (THREE.VAL >= DATE '2006-07-01'))
#-mvStore#>> SELECT ONE.ID, TWO.VAL, THREE.ID, THREE.VAL, FOUR.ID FROM PUBLIC.ONE /* PUBLIC.PRIMARY_KEY_1 */ INNER JOIN PUBLIC.TWO /* PUBLIC.PRIMARY_KEY_14: ID = PUBLIC.ONE.ID */ ON 1=1 /* WHERE PUBLIC.ONE.ID = PUBLIC.TWO.ID */ LEFT OUTER JOIN PUBLIC.TWO THREE /* PUBLIC.PRIMARY_KEY_14: ID = ONE.ID */ ON ONE.ID = THREE.ID LEFT OUTER JOIN PUBLIC.ONE FOUR /* PUBLIC.PRIMARY_KEY_1: ID = TWO.ID */ ON TWO.ID = FOUR.ID WHERE (PUBLIC.ONE.ID = PUBLIC.TWO.ID) AND ((THREE.VAL IS NULL) OR (THREE.VAL >= DATE '2006-07-01'))
-- Query #4: same as #3, but the joins have been manually re-ordered
-- Correct result set, same as expected for #3.
......@@ -254,8 +254,8 @@ explain select * from test1
inner join test2 on test1.id=test2.id left
outer join test3 on test2.id=test3.id
where test3.id is null;
#+mvStore#>> SELECT TEST1.ID, TEST2.ID, TEST3.ID FROM PUBLIC.TEST2 /* PUBLIC.TEST2.tableScan */ LEFT OUTER JOIN PUBLIC.TEST3 /* PUBLIC.PRIMARY_KEY_4C0: ID = TEST2.ID */ ON TEST2.ID = TEST3.ID INNER JOIN PUBLIC.TEST1 /* PUBLIC.PRIMARY_KEY_4: ID = TEST2.ID */ ON 1=1 WHERE (TEST3.ID IS NULL) AND (TEST1.ID = TEST2.ID)
#-mvStore#>> SELECT TEST1.ID, TEST2.ID, TEST3.ID FROM PUBLIC.TEST1 /* PUBLIC.PRIMARY_KEY_4 */ INNER JOIN PUBLIC.TEST2 /* PUBLIC.PRIMARY_KEY_4C: ID = TEST1.ID AND ID = TEST1.ID */ ON 1=1 /* WHERE TEST1.ID = TEST2.ID */ LEFT OUTER JOIN PUBLIC.TEST3 /* PUBLIC.PRIMARY_KEY_4C0: ID = TEST2.ID */ ON TEST2.ID = TEST3.ID WHERE (TEST3.ID IS NULL) AND (TEST1.ID = TEST2.ID)
#+mvStore#>> SELECT TEST1.ID, TEST2.ID, TEST3.ID FROM PUBLIC.TEST1 /* PUBLIC.TEST1.tableScan */ INNER JOIN PUBLIC.TEST2 /* PUBLIC.PRIMARY_KEY_4C: ID = TEST1.ID */ ON 1=1 /* WHERE TEST1.ID = TEST2.ID */ LEFT OUTER JOIN PUBLIC.TEST3 /* PUBLIC.PRIMARY_KEY_4C0: ID = TEST2.ID */ ON TEST2.ID = TEST3.ID WHERE (TEST3.ID IS NULL) AND (TEST1.ID = TEST2.ID)
#-mvStore#>> SELECT TEST1.ID, TEST2.ID, TEST3.ID FROM PUBLIC.TEST1 /* PUBLIC.PRIMARY_KEY_4 */ INNER JOIN PUBLIC.TEST2 /* PUBLIC.PRIMARY_KEY_4C: ID = TEST1.ID */ ON 1=1 /* WHERE TEST1.ID = TEST2.ID */ LEFT OUTER JOIN PUBLIC.TEST3 /* PUBLIC.PRIMARY_KEY_4C0: ID = TEST2.ID */ ON TEST2.ID = TEST3.ID WHERE (TEST3.ID IS NULL) AND (TEST1.ID = TEST2.ID)
insert into test1 select x from system_range(2, 1000);
> update count: 999
......@@ -570,7 +570,7 @@ select * from t1 natural join t2;
> rows: 0
explain select * from t1 natural join t2;
>> SELECT T1.ID, T1.NAME FROM PUBLIC.T2 /* PUBLIC.T2.tableScan */ INNER JOIN PUBLIC.T1 /* PUBLIC.T1.tableScan */ ON 1=1 WHERE (PUBLIC.T1.ID = PUBLIC.T2.ID) AND (PUBLIC.T1.NAME = PUBLIC.T2.NAME)
>> SELECT T1.ID, T1.NAME FROM PUBLIC.T1 /* PUBLIC.T1.tableScan */ INNER JOIN PUBLIC.T2 /* PUBLIC.T2.tableScan */ ON 1=1 WHERE (PUBLIC.T1.ID = PUBLIC.T2.ID) AND (PUBLIC.T1.NAME = PUBLIC.T2.NAME)
drop table t1;
> ok
......@@ -785,3 +785,20 @@ SELECT T1.X1, T2.X2, T3.X3, T4.X4, T5.X5 FROM (
> -- -- -- -- --
> 1 1 1 1 1
> rows: 1
CREATE TABLE A(X INT);
> ok
CREATE TABLE B(Y INT);
> ok
CREATE TABLE C(Z INT);
> ok
SELECT A.X FROM A JOIN B ON A.X = B.Y AND B.Y >= COALESCE((SELECT Z FROM C FETCH FIRST ROW ONLY), 0);
> X
> -
> rows: 0
DROP TABLE A, B, C;
> ok
......@@ -5250,7 +5250,7 @@ EXPLAIN PLAN FOR SELECT NAME, COUNT(*) FROM TEST GROUP BY NAME HAVING COUNT(*) >
>> SELECT NAME, COUNT(*) FROM PUBLIC.TEST /* PUBLIC.TEST.tableScan */ GROUP BY NAME HAVING COUNT(*) > 1
EXPLAIN PLAN FOR SELECT * FROM test t1 inner join test t2 on t1.id=t2.id and t2.name is not null where t1.id=1;
>> SELECT T1.ID, T1.NAME, T2.ID, T2.NAME FROM PUBLIC.TEST T1 /* PUBLIC.PRIMARY_KEY_2: ID = 1 */ /* WHERE T1.ID = 1 */ INNER JOIN PUBLIC.TEST T2 /* PUBLIC.PRIMARY_KEY_2: ID = T1.ID AND ID = T1.ID */ ON 1=1 WHERE (T1.ID = 1) AND ((T2.NAME IS NOT NULL) AND (T1.ID = T2.ID))
>> SELECT T1.ID, T1.NAME, T2.ID, T2.NAME FROM PUBLIC.TEST T1 /* PUBLIC.PRIMARY_KEY_2: ID = 1 */ /* WHERE T1.ID = 1 */ INNER JOIN PUBLIC.TEST T2 /* PUBLIC.PRIMARY_KEY_2: ID = T1.ID */ ON 1=1 WHERE (T1.ID = 1) AND ((T2.NAME IS NOT NULL) AND (T1.ID = T2.ID))
EXPLAIN PLAN FOR SELECT * FROM test t1 left outer join test t2 on t1.id=t2.id and t2.name is not null where t1.id=1;
>> SELECT T1.ID, T1.NAME, T2.ID, T2.NAME FROM PUBLIC.TEST T1 /* PUBLIC.PRIMARY_KEY_2: ID = 1 */ /* WHERE T1.ID = 1 */ LEFT OUTER JOIN PUBLIC.TEST T2 /* PUBLIC.PRIMARY_KEY_2: ID = T1.ID */ ON (T2.NAME IS NOT NULL) AND (T1.ID = T2.ID) WHERE T1.ID = 1
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论