提交 17d2a88c authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #302 from igelbox/recursive-with-join-and-subqueries

add support for "with"-subqueries into "join" & "sub-query" statements
......@@ -477,8 +477,8 @@ public class Parser {
break;
case 'w':
case 'W':
if (readIf("WITH")) {
c = parseWith();
if (isToken("WITH")) {
c = parseSelect();
}
break;
case ';':
......@@ -999,7 +999,7 @@ public class Parser {
// need to read ahead, it could be a nested union:
// ((select 1) union (select 1))
}
boolean select = isToken("SELECT") || isToken("FROM");
boolean select = isToken("SELECT") || isToken("FROM") || isToken("WITH");
parseIndex = start;
read();
return select;
......@@ -1676,7 +1676,7 @@ public class Parser {
readIf("FOR");
}
}
if (isToken("SELECT") || isToken("FROM") || isToken("(")) {
if (isToken("SELECT") || isToken("FROM") || isToken("(") || isToken("WITH")) {
command.setCommand(parseSelect());
} else if (readIf("DELETE")) {
command.setCommand(parseDelete());
......@@ -1686,8 +1686,6 @@ public class Parser {
command.setCommand(parseInsert());
} else if (readIf("MERGE")) {
command.setCommand(parseMerge());
} else if (readIf("WITH")) {
command.setCommand(parseWith());
} else {
throw getSyntaxError();
}
......@@ -1887,6 +1885,8 @@ public class Parser {
read(")");
return command;
}
if (readIf("WITH"))
return parseWith();
Select select = parseSelectSimple();
return select;
}
......@@ -2772,12 +2772,9 @@ public class Parser {
r = p;
break;
case KEYWORD:
if (isToken("SELECT") || isToken("FROM")) {
if (isToken("SELECT") || isToken("FROM") || isToken("WITH")) {
Query query = parseSelect();
r = new Subquery(query);
} else if (readIf("WITH")) {
Query query = parseWith();
r = new Subquery(query);
} else {
throw getSyntaxError();
}
......@@ -4781,7 +4778,7 @@ public class Parser {
view.setTemporary(true);
session.addLocalTempTable(view);
view.setOnCommitDrop(true);
Query q = parseSelect();
Query q = parseSelectUnion();
q.setPrepareAlways(true);
return q;
}
......
......@@ -38,6 +38,7 @@ import org.h2.table.IndexColumn;
import org.h2.table.JoinBatch;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.table.TableView;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
......@@ -1082,7 +1083,21 @@ public class Select extends Query {
// but indexes may be set manually as well
Expression[] exprList = expressions.toArray(
new Expression[expressions.size()]);
StatementBuilder buff = new StatementBuilder("SELECT");
StatementBuilder buff = new StatementBuilder();
for (TableFilter f : topFilters) {
Table t = f.getTable();
if ((t instanceof TableView) && ((TableView) t).isRecursive()) {
buff.append("WITH RECURSIVE ").append(t.getName()).append('(');
buff.resetCount();
for (Column c : t.getColumns()) {
buff.appendExceptFirst(",");
buff.append(c.getName());
}
buff.append(") AS ").append(t.getSQL()).append("\n");
}
}
buff.resetCount();
buff.append("SELECT");
if (distinct) {
buff.append(" DISTINCT");
}
......
......@@ -816,6 +816,9 @@ public class TableFilter implements ColumnResolver {
}
return buff.toString();
}
if ((table instanceof TableView) && ((TableView) table).isRecursive())
buff.append(table.getName());
else
buff.append(table.getSQL());
if (table.isView() && ((TableView) table).isInvalid()) {
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, table.getName(), "not compiled");
......
......@@ -579,6 +579,10 @@ public class TableView extends Table {
return result;
}
public boolean isRecursive() {
return recursive;
}
@Override
public boolean isDeterministic() {
if (recursive || viewQuery == null) {
......
......@@ -10228,6 +10228,49 @@ select 0 from ((
};
> update count: 0
explain with recursive r(n) as (
(select 1) union all (select n+1 from r where n < 3)
)
select n from r;
> PLAN
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> WITH RECURSIVE R(N) AS ( (SELECT 1 FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */) UNION ALL (SELECT (N + 1) FROM PUBLIC.R /* PUBLIC.R.tableScan */ WHERE N < 3) ) SELECT N FROM R /* null */
> rows: 1
select sum(n) from (
with recursive r(n) as (
(select 1) union all (select n+1 from r where n < 3)
)
select n from r
);
> SUM(N)
> ------
> 6
> rows: 1
select sum(n) from (select 0) join (
with recursive r(n) as (
(select 1) union all (select n+1 from r where n < 3)
)
select n from r
) on 1=1;
> SUM(N)
> ------
> 6
> rows: 1
select 0 from (
select 0 where 0 in (
with recursive r(n) as (
(select 1) union all (select n+1 from r where n < 3)
)
select n from r
)
);
> 0
> -
> rows: 0
create table x(id int not null);
> ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论