diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java index 25d5489cee..65b9d81e2c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java @@ -37,6 +37,7 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace protected final List using = new ArrayList(); protected boolean natural = false; protected UDJ udj; // for maxcompute + protected boolean asof; // for clickhouse public SQLJoinTableSource(String alias){ super(alias); @@ -93,6 +94,14 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace this.udj = x; } + public boolean isAsof() { + return asof; + } + + public void setAsof(boolean asof) { + this.asof = asof; + } + public JoinType getJoinType() { return this.joinType; } @@ -324,6 +333,7 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace } x.natural = natural; + x.asof = asof; if (udj != null) { x.udj = udj.clone(); @@ -348,6 +358,7 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace if (right instanceof SQLJoinTableSource) { ((SQLJoinTableSource) right).reverse(); } + } /** diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index 32eff3c059..1e971d67d9 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -154,6 +154,14 @@ public class SQLParser { return null; } return ident; + } else if (hash == FnvHash.Constants.ASOF && dbType == DbType.clickhouse) { + Lexer.SavePoint mark = lexer.mark(); + lexer.nextToken(); + if (lexer.token == Token.LEFT || lexer.token == Token.JOIN) { + lexer.reset(mark); + return null; + } + return ident; } } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index bb069efaa4..156a199b48 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -1151,7 +1151,7 @@ public class SQLSelectParser extends SQLParser { && ((hash = lexer.hash_lower()) == FnvHash.Constants.STRAIGHT_JOIN || hash == FnvHash.Constants.CROSS))) { - String alias = tableAlias(); + String alias = tableAlias(false); if (alias != null) { if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && alias.length() > 1) { alias = StringUtils.removeNameQuotes(alias); @@ -1192,6 +1192,12 @@ public class SQLSelectParser extends SQLParser { lexer.nextToken(); } + boolean asof = false; + if (lexer.identifierEquals(FnvHash.Constants.ASOF) && dbType == DbType.clickhouse) { + lexer.nextToken(); + asof = true; + } + switch (lexer.token) { case LEFT: lexer.nextToken(); @@ -1276,6 +1282,9 @@ public class SQLSelectParser extends SQLParser { SQLJoinTableSource join = new SQLJoinTableSource(); join.setLeft(tableSource); join.setJoinType(joinType); + if (asof) { + join.setAsof(true); + } boolean isBrace = false; if (SQLJoinTableSource.JoinType.COMMA == joinType) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index f15a41f71a..1f47803b31 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -3962,6 +3962,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else { println(); + boolean asof = x.isAsof(); + if (asof) { + print0(ucase ? " ASOF ": " asof"); + } + if (x.isNatural()) { print0(ucase ? "NATURAL " : "natural "); } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index a74e3c87e0..b7d9abf349 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -1115,5 +1115,7 @@ public final class FnvHash { long TRANSFORM = fnv1a_64_lower("TRANSFORM"); long NESTED = fnv1a_64_lower("NESTED"); long RESTART = fnv1a_64_lower("RESTART"); + + long ASOF = fnv1a_64_lower("ASOF"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/ClickHouseResourceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/ClickHouseResourceTest.java index 9e153a5277..f0ba762e88 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/ClickHouseResourceTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/ClickHouseResourceTest.java @@ -44,6 +44,10 @@ public class ClickHouseResourceTest extends OracleTest { exec_test("bvt/parser/clickhouse-1.txt"); } + public void test_2() throws Exception { + exec_test("bvt/parser/clickhouse-2.txt"); + } + public void exec_test(String resource) throws Exception { System.out.println(resource); InputStream is = null; diff --git a/src/test/resources/bvt/parser/clickhouse-2.txt b/src/test/resources/bvt/parser/clickhouse-2.txt new file mode 100644 index 0000000000..a0c7ceebac --- /dev/null +++ b/src/test/resources/bvt/parser/clickhouse-2.txt @@ -0,0 +1,10 @@ +SELECT expressions_list +FROM table_1 +ASOF LEFT JOIN table_2 +ON equi_cond AND closest_match_cond +--------------------------- +SELECT expressions_list +FROM table_1 + ASOF LEFT JOIN table_2 + ON equi_cond + AND closest_match_cond \ No newline at end of file