From 3197ae8db9b95cd2cf344f7c006264653ae3f5ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Tue, 12 Jan 2021 22:32:04 +0800 Subject: [PATCH] sql parser improved pg support, fix #4128 --- .../ast/statement/SQLAlterTableStatement.java | 10 ++++++++++ .../parser/PGSQLStatementParser.java | 4 ++++ .../druid/sql/parser/SQLStatementParser.java | 7 +++++++ .../sql/visitor/SQLASTOutputVisitor.java | 5 +++++ .../java/com/alibaba/druid/util/FnvHash.java | 2 ++ .../postgresql/PostgresqlResourceTest.java | 12 +++++++++++ src/test/resources/bvt/parser/hive-4.txt | 4 ++++ src/test/resources/bvt/parser/hive-5.txt | 4 ++++ .../resources/bvt/parser/postgresql-4.txt | 20 +++++++++++++++++++ .../resources/bvt/parser/postgresql-5.txt | 5 +++++ .../resources/bvt/parser/postgresql-6.txt | 5 +++++ 11 files changed, 78 insertions(+) create mode 100644 src/test/resources/bvt/parser/hive-4.txt create mode 100644 src/test/resources/bvt/parser/hive-5.txt create mode 100644 src/test/resources/bvt/parser/postgresql-4.txt create mode 100644 src/test/resources/bvt/parser/postgresql-5.txt create mode 100644 src/test/resources/bvt/parser/postgresql-6.txt diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java index 7d3d609c5b..f206cba167 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java @@ -53,6 +53,8 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt protected int buckets; protected int shards; + private boolean ifExists = false; + public SQLAlterTableStatement(){ } @@ -85,6 +87,14 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt this.offline = offline; } + public boolean isIfExists() { + return ifExists; + } + + public void setIfExists(boolean ifExists) { + this.ifExists = ifExists; + } + public boolean isRemovePatiting() { return removePatiting; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index c1892839c1..3dcb9bb882 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -557,6 +557,10 @@ public class PGSQLStatementParser extends SQLStatementParser { values.add(new SQLCharExpr(lexer.stringVal())); } else if (lexer.token() == Token.LITERAL_INT) { values.add(new SQLIdentifierExpr(lexer.numberString())); + } else if (lexer.identifierEquals(FnvHash.Constants.JSON_SET) + || lexer.identifierEquals(FnvHash.Constants.JSONB_SET)) { + SQLExpr json_set = this.exprParser.expr(); + values.add(json_set); } else { values.add(new SQLIdentifierExpr(lexer.stringVal())); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 0c6b3b88eb..cf536a4f02 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -1763,6 +1763,13 @@ public class SQLStatementParser extends SQLParser { lexer.nextToken(); SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType()); + + if (lexer.token == Token.IF) { + lexer.nextToken(); + accept(Token.EXISTS); + stmt.setIfExists(true); + } + stmt.setName(this.exprParser.name()); for (;;) { 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 0b1ee642b1..21be6fc8f8 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -5405,6 +5405,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLAlterTableStatement x) { print0(ucase ? "ALTER TABLE " : "alter table "); + + if (x.isIfExists()) { + print0(ucase ? "IF EXISTS " : "if exists "); + } + printTableSourceExpr(x.getName()); this.indentCount++; for (int i = 0; i < x.getItems().size(); ++i) { diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index b7d9abf349..55bd9ae9f8 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -1117,5 +1117,7 @@ public final class FnvHash { long RESTART = fnv1a_64_lower("RESTART"); long ASOF = fnv1a_64_lower("ASOF"); + long JSON_SET = fnv1a_64_lower("JSON_SET"); + long JSONB_SET = fnv1a_64_lower("JSONB_SET"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java index eda88e3cba..74c79c33b6 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java @@ -52,6 +52,18 @@ public class PostgresqlResourceTest extends PGTest { exec_test("bvt/parser/postgresql-3.txt"); } + public void test_4() throws Exception { + exec_test("bvt/parser/postgresql-4.txt"); + } + + public void test_5() throws Exception { + exec_test("bvt/parser/postgresql-5.txt"); + } + + public void test_6() throws Exception { + exec_test("bvt/parser/postgresql-6.txt"); + } + public void exec_test(String resource) throws Exception { System.out.println(resource); InputStream is = null; diff --git a/src/test/resources/bvt/parser/hive-4.txt b/src/test/resources/bvt/parser/hive-4.txt new file mode 100644 index 0000000000..8d9ac811c2 --- /dev/null +++ b/src/test/resources/bvt/parser/hive-4.txt @@ -0,0 +1,4 @@ +ALTER TABLE tb_a ADD COLUMNS ( a bigint ); +--------------------------- +ALTER TABLE tb_a + ADD COLUMNS (a bigint); \ No newline at end of file diff --git a/src/test/resources/bvt/parser/hive-5.txt b/src/test/resources/bvt/parser/hive-5.txt new file mode 100644 index 0000000000..bb7b23347e --- /dev/null +++ b/src/test/resources/bvt/parser/hive-5.txt @@ -0,0 +1,4 @@ +INSERT INTO tb_a VALUES ( 1 ); +--------------------------- +INSERT INTO TABLE tb_a +VALUES (1); \ No newline at end of file diff --git a/src/test/resources/bvt/parser/postgresql-4.txt b/src/test/resources/bvt/parser/postgresql-4.txt new file mode 100644 index 0000000000..a63c63f63c --- /dev/null +++ b/src/test/resources/bvt/parser/postgresql-4.txt @@ -0,0 +1,20 @@ +SET data = jsonb_set( +data, +ARRAY[( +SELECT idx - 1 AS idx +FROM cgm_data c1, +jsonb_array_elements(data) +WHERE +info ->> 'index' = ? +and c1.id = ? +)]::TEXT[], +?::jsonb +) +WHERE t1.id = ?; +--------------------------- +SET data TO jsonb_set(data, ARRAY[( + SELECT idx - 1 AS idx + FROM cgm_data c1, jsonb_array_elements(data) + WHERE info ->> 'index' = ? + AND c1.id = ? +)]::TEXT[], ?::jsonb), t1, id, id diff --git a/src/test/resources/bvt/parser/postgresql-5.txt b/src/test/resources/bvt/parser/postgresql-5.txt new file mode 100644 index 0000000000..42eab76b7a --- /dev/null +++ b/src/test/resources/bvt/parser/postgresql-5.txt @@ -0,0 +1,5 @@ +select * from com_demo order by sex asc nulls first +--------------------------- +SELECT * +FROM com_demo +ORDER BY sex ASC NULLS FIRST \ No newline at end of file diff --git a/src/test/resources/bvt/parser/postgresql-6.txt b/src/test/resources/bvt/parser/postgresql-6.txt new file mode 100644 index 0000000000..0c1b92ce8b --- /dev/null +++ b/src/test/resources/bvt/parser/postgresql-6.txt @@ -0,0 +1,5 @@ +alter table if exists tcweatherdata +add column predictiontime timestamp +--------------------------- +ALTER TABLE IF EXISTS tcweatherdata + ADD COLUMN predictiontime timestamp \ No newline at end of file