From d9eccdbc45a99d0b0aaa685f56d4da3cb73aa36c Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 26 Jan 2017 23:27:19 +0800 Subject: [PATCH] improved sql parser pg json operation support. #1592 --- .../druid/sql/ast/expr/SQLBinaryOperator.java | 7 ++- .../com/alibaba/druid/sql/parser/Lexer.java | 13 ++++- .../druid/sql/parser/SQLExprParser.java | 15 +++++ .../com/alibaba/druid/sql/parser/Token.java | 5 +- .../sql/postgresql/select/PGSelectTest44.java | 57 +++++++++++++++++++ .../sql/postgresql/select/PGSelectTest45.java | 56 ++++++++++++++++++ .../sql/postgresql/select/PGSelectTest46.java | 56 ++++++++++++++++++ 7 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest44.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest45.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest46.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java index 907a1ae4c0..5a4182a9fd 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java @@ -37,8 +37,11 @@ public enum SQLBinaryOperator { SubGt("->", 20), SubGtGt("->>", 20), PoundGt("#>", 20), - PoundGtGt("#>>", 20), - + PoundGtGt("#>>", 20), + QuesQues("??", 20), + QuesBar("?|", 20), + QuesAmp("?&", 20), + LeftShift("<<", 80), RightShift(">>", 80), diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index d313278e75..a008292e0c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -450,7 +450,18 @@ public class Lexer { return; case '?': scanChar(); - token = Token.QUES; + if (ch == '?') { + scanChar(); + token = Token.QUESQUES; + } else if (ch == '|') { + scanChar(); + token = Token.QUESBAR; + } else if (ch == '&') { + scanChar(); + token = Token.QUESAMP; + } else { + token = Token.QUES; + } return; case ';': scanChar(); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 8cba98c4be..710b009540 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -139,6 +139,21 @@ public class SQLExprParser extends SQLParser { SQLExpr rightExp = primary(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, getDbType()); expr = bitXorRest(expr); + } else if (token == Token.QUESQUES) { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, getDbType()); + expr = bitXorRest(expr); + } else if (token == Token.QUESBAR) { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, getDbType()); + expr = bitXorRest(expr); + } else if (token == Token.QUESAMP) { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, getDbType()); + expr = bitXorRest(expr); } return expr; diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index bbad08819f..e1390c39bc 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -305,7 +305,10 @@ public enum Token { TILDE("~"), TILDE_STAR("~*"), TILDE_EQ("~="), - QUES("?"), + QUES("?"), + QUESQUES("??"), + QUESBAR("?|"), + QUESAMP("?&"), COLON(":"), COLONCOLON("::"), COLONEQ(":="), diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest44.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest44.java new file mode 100644 index 0000000000..f7592db93f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest44.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.postgresql.select; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class PGSelectTest44 extends PGTest { + private String dbType = JdbcConstants.POSTGRESQL; + + public void test_0() throws Exception { + String sql = "SELECT count(1) FROM t_user WHERE property ?? 'name'"; + + List statementList = SQLUtils.parseStatements(sql, dbType); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals("SELECT COUNT(1)\n" + + "FROM t_user\n" + + "WHERE property ?? 'name'", SQLUtils.toPGString(stmt)); + + Assert.assertEquals("select count(1)\n" + + "from t_user\n" + + "where property ?? 'name'", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + Assert.assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); + + Assert.assertEquals(1, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getTables().size()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest45.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest45.java new file mode 100644 index 0000000000..1d0d0cff0f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest45.java @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.postgresql.select; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class PGSelectTest45 extends PGTest { + private String dbType = JdbcConstants.POSTGRESQL; + + public void test_0() throws Exception { + String sql = "SELECT count(1) FROM t_user WHERE property ?| 'name'"; + + List statementList = SQLUtils.parseStatements(sql, dbType); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals("SELECT COUNT(1)\n" + + "FROM t_user\n" + + "WHERE property ?| 'name'", SQLUtils.toPGString(stmt)); + + Assert.assertEquals("select count(1)\n" + + "from t_user\n" + + "where property ?| 'name'", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + Assert.assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); + + Assert.assertEquals(1, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getTables().size()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest46.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest46.java new file mode 100644 index 0000000000..e81919ca2f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest46.java @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.postgresql.select; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class PGSelectTest46 extends PGTest { + private String dbType = JdbcConstants.POSTGRESQL; + + public void test_0() throws Exception { + String sql = "SELECT count(1) FROM t_user WHERE property ?& 'name'"; + + List statementList = SQLUtils.parseStatements(sql, dbType); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals("SELECT COUNT(1)\n" + + "FROM t_user\n" + + "WHERE property ?& 'name'", SQLUtils.toPGString(stmt)); + + Assert.assertEquals("select count(1)\n" + + "from t_user\n" + + "where property ?& 'name'", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + Assert.assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); + + Assert.assertEquals(1, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getTables().size()); + } +}