Unverified 提交 9d28c9f6 authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #907 from katzyn/join

Nest joins only if required and fix some issues with complex joins
......@@ -1369,8 +1369,7 @@ public class Parser {
} else {
TableFilter top;
top = readTableFilter();
top = readJoin(top, false);
top = getNested(top);
top = readJoin(top);
read(")");
alias = readFromAlias(null);
if (alias != null) {
......@@ -1717,8 +1716,7 @@ public class Parser {
return command;
}
private TableFilter readJoin(TableFilter top, boolean nested) {
boolean joined = false;
private TableFilter readJoin(TableFilter top) {
TableFilter last = top;
while (true) {
TableFilter join;
......@@ -1727,47 +1725,46 @@ public class Parser {
read("JOIN");
// the right hand side is the 'inner' table usually
join = readTableFilter();
join = readJoin(join, nested);
join = readJoin(join);
Expression on = null;
if (readIf("ON")) {
on = readExpression();
}
top = getNested(top);
join.addJoin(top, true, on);
addJoin(join, top, true, on);
top = join;
} else if (readIf("LEFT")) {
readIf("OUTER");
read("JOIN");
join = readTableFilter();
join = readJoin(join, true);
join = readJoin(join);
Expression on = null;
if (readIf("ON")) {
on = readExpression();
}
top.addJoin(join, true, on);
addJoin(top, join, true, on);
} else if (readIf("FULL")) {
throw getSyntaxError();
} else if (readIf("INNER")) {
read("JOIN");
join = readTableFilter();
top = readJoin(top, false);
top = readJoin(top);
Expression on = null;
if (readIf("ON")) {
on = readExpression();
}
top.addJoin(join, false, on);
addJoin(top, join, false, on);
} else if (readIf("JOIN")) {
join = readTableFilter();
top = readJoin(top, false);
top = readJoin(top);
Expression on = null;
if (readIf("ON")) {
on = readExpression();
}
top.addJoin(join, false, on);
addJoin(top, join, false, on);
} else if (readIf("CROSS")) {
read("JOIN");
join = readTableFilter();
top.addJoin(join, false, null);
addJoin(top, join, false, null);
} else if (readIf("NATURAL")) {
read("JOIN");
join = readTableFilter();
......@@ -1799,26 +1796,35 @@ public class Parser {
}
}
}
top.addJoin(join, false, on);
addJoin(top, join, false, on);
} else {
break;
}
joined = true;
last = join;
}
if (nested && joined) {
top = getNested(top);
}
return top;
}
private TableFilter getNested(TableFilter n) {
/**
* Add one join to another. This method creates nested join between them if
* required.
*
* @param top parent join
* @param join child join
* @param outer if child join is an outer join
* @param on the join condition
* @see TableFilter#addJoin(TableFilter, boolean, Expression)
*/
private void addJoin(TableFilter top, TableFilter join, boolean outer, Expression on) {
if (join.getJoin() != null) {
String joinTable = Constants.PREFIX_JOIN + parseIndex;
TableFilter top = new TableFilter(session, getDualTable(true),
joinTable, rightsChecked, currentSelect, n.getOrderInFrom(),
TableFilter n = new TableFilter(session, getDualTable(true),
joinTable, rightsChecked, currentSelect, join.getOrderInFrom(),
null);
top.setNestedJoin(n);
return top;
n.setNestedJoin(join);
join = n;
}
top.addJoin(join, outer, on);
}
private Prepared parseExecute() {
......@@ -2149,7 +2155,7 @@ public class Parser {
}
private void parseJoinTableFilter(TableFilter top, final Select command) {
top = readJoin(top, false);
top = readJoin(top);
command.addTableFilter(top, true);
boolean isOuter = false;
while (true) {
......
......@@ -401,7 +401,7 @@ public class IndexCondition {
return "column=" + column +
", compareType=" + compareTypeToString(compareType) +
", expression=" + expression +
", expressionList=" + expressionList.toString() +
", expressionList=" + expressionList +
", expressionQuery=" + expressionQuery;
}
......
......@@ -168,7 +168,6 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
private static Query prepareSubQuery(String sql, Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
assert filters != null;
Prepared p;
session.pushSubQueryInfo(masks, filters, filter, sortOrder);
try {
......
......@@ -265,13 +265,32 @@ public class TableFilter implements ColumnResolver {
if (nestedJoin != null) {
if (item.getNestedJoinPlan() != null) {
nestedJoin.setPlanItem(item.getNestedJoinPlan());
} else {
nestedJoin.setScanIndexes();
}
}
if (join != null) {
if (item.getJoinPlan() != null) {
join.setPlanItem(item.getJoinPlan());
} else {
join.setScanIndexes();
}
}
}
/**
* Set all missing indexes to scan indexes recursively.
*/
private void setScanIndexes() {
if (index == null) {
setIndex(table.getScanIndex(session));
}
if (join != null) {
join.setScanIndexes();
}
if (nestedJoin != null) {
nestedJoin.setScanIndexes();
}
}
/**
......
......@@ -103,6 +103,21 @@ select a.i from t1 a inner join (select a.i from t2 a inner join (select i from
> -
> rows: 0
insert into t1 values (1);
> update count: 1
insert into t2 values (1);
> update count: 1
insert into t3 values (1);
> update count: 1
select a.i from t1 a inner join (select a.i from t2 a inner join (select i from t3) b on a.i=b.i) b on a.i=b.i;
> I
> -
> 1
> rows: 1
drop table t1, t2, t3;
> ok
......@@ -747,3 +762,32 @@ DROP TABLE B;
DROP TABLE C;
> ok
CREATE TABLE T1(X1 INT);
CREATE TABLE T2(X2 INT);
CREATE TABLE T3(X3 INT);
CREATE TABLE T4(X4 INT);
CREATE TABLE T5(X5 INT);
INSERT INTO T1 VALUES (1);
INSERT INTO T1 VALUES (NULL);
INSERT INTO T2 VALUES (1);
INSERT INTO T2 VALUES (NULL);
INSERT INTO T3 VALUES (1);
INSERT INTO T3 VALUES (NULL);
INSERT INTO T4 VALUES (1);
INSERT INTO T4 VALUES (NULL);
INSERT INTO T5 VALUES (1);
INSERT INTO T5 VALUES (NULL);
SELECT T1.X1, T2.X2, T3.X3, T4.X4, T5.X5 FROM (
T1 INNER JOIN (
T2 LEFT OUTER JOIN (
T3 INNER JOIN T4 ON T3.X3 = T4.X4
) ON T2.X2 = T4.X4
) ON T1.X1 = T2.X2
) INNER JOIN T5 ON T2.X2 = T5.X5;
> X1 X2 X3 X4 X5
> -- -- -- -- --
> 1 1 1 1 1
> rows: 1
......@@ -380,7 +380,7 @@ public class TestNestedJoins extends TestBase {
assertTrue(rs.next());
sql = cleanRemarks(rs.getString(1));
assertEquals("SELECT DISTINCT T1.A, T2.A, T3.A FROM PUBLIC.T2 " +
"LEFT OUTER JOIN ( PUBLIC.T3 LEFT OUTER JOIN ( PUBLIC.T1 ) " +
"LEFT OUTER JOIN ( PUBLIC.T3 LEFT OUTER JOIN PUBLIC.T1 " +
"ON T1.B = T3.A ) ON T2.B = T1.A", sql);
rs = stat.executeQuery("select distinct t1.a, t2.a, t3.a from t1 " +
"right outer join t3 on t1.b=t3.a " +
......
......@@ -136,7 +136,7 @@ public class TestOuterJoins extends TestBase {
s.getConnection().close();
}
deleteDerby();
deleteDb("nestedJoins");
deleteDb("outerJoins");
}
private void deleteDerby() {
......@@ -289,7 +289,7 @@ public class TestOuterJoins extends TestBase {
private void testCases() throws Exception {
Connection conn = getConnection("nestedJoins");
Connection conn = getConnection("outerJoins");
Statement stat = conn.createStatement();
ResultSet rs;
String sql;
......@@ -334,7 +334,7 @@ public class TestOuterJoins extends TestBase {
sql = cleanRemarks(rs.getString(1));
assertEquals("SELECT DISTINCT T1.A, T2.A, T3.A FROM PUBLIC.T2 " +
"LEFT OUTER JOIN ( PUBLIC.T3 " +
"LEFT OUTER JOIN ( PUBLIC.T1 ) ON T1.B = T3.A ) " +
"LEFT OUTER JOIN PUBLIC.T1 ON T1.B = T3.A ) " +
"ON T2.B = T1.A", sql);
rs = stat.executeQuery("select distinct t1.a, t2.a, t3.a from t1 " +
"right outer join t3 on t1.b=t3.a right outer join t2 on t2.b=t1.a");
......@@ -571,7 +571,7 @@ public class TestOuterJoins extends TestBase {
// }
conn.close();
deleteDb("nestedJoins");
deleteDb("outerJoins");
}
private static String cleanRemarks(String sql) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论