From ee31a42afcbed1341580ebfc1dd648b07d444d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Sat, 25 Jun 2016 17:11:51 +0800 Subject: [PATCH] improved odps sql parser, support true/false/close, fixed issue #1294 --- .../dialect/odps/parser/OdpsExprParser.java | 9 +- .../sql/dialect/odps/parser/OdpsLexer.java | 2 + .../alibaba/druid/sql/parser/SQLParser.java | 181 +++++++++--------- .../bvt/sql/db2/DB2DropSequenceTest_0.java | 2 - .../druid/bvt/sql/odps/OdpsSelectTest6.java | 56 ++++++ .../druid/bvt/sql/odps/OdpsSelectTest7.java | 59 ++++++ 6 files changed, 217 insertions(+), 92 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest6.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest7.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java index b621624860..7ec7c320d9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java @@ -77,6 +77,7 @@ public class OdpsExprParser extends SQLExprParser { expr = expr(); } + String alias = null; if (lexer.token() == Token.AS) { lexer.nextToken(); @@ -88,7 +89,7 @@ public class OdpsExprParser extends SQLExprParser { selectItem.setExpr(expr); for (;;) { - String alias = lexer.stringVal(); + alias = lexer.stringVal(); lexer.nextToken(); selectItem.getAliasList().add(alias); @@ -103,10 +104,12 @@ public class OdpsExprParser extends SQLExprParser { accept(Token.RPAREN); return selectItem; + } else { + alias = alias(); } + } else { + alias = as(); } - - final String alias = as(); SQLSelectItem item = new SQLSelectItem(expr, alias); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java index d11d4a69b5..cc36308187 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java @@ -45,6 +45,8 @@ public class OdpsLexer extends Lexer { map.put("LIMIT", Token.LIMIT); map.put("IF", Token.IF); map.put("DISTRIBUTE", Token.DISTRIBUTE); + map.put("TRUE", Token.TRUE); + map.put("FALSE", Token.FALSE); DEFAULT_ODPS_KEYWORDS = new Keywords(map); } 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 a777aef19f..27406d607e 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -66,93 +66,7 @@ public class SQLParser { if (lexer.token() == Token.AS) { lexer.nextToken(); - if (lexer.token() == Token.LITERAL_ALIAS) { - alias = '"' + lexer.stringVal() + '"'; - lexer.nextToken(); - } else if (lexer.token() == Token.IDENTIFIER) { - alias = lexer.stringVal(); - lexer.nextToken(); - } else if (lexer.token() == Token.LITERAL_CHARS) { - alias = "'" + lexer.stringVal() + "'"; - lexer.nextToken(); - } else { - switch (lexer.token()) { - case KEY: - case INDEX: - case CASE: - case MODEL: - case PCTFREE: - case INITRANS: - case MAXTRANS: - case SEGMENT: - case CREATION: - case IMMEDIATE: - case DEFERRED: - case STORAGE: - case NEXT: - case MINEXTENTS: - case MAXEXTENTS: - case MAXSIZE: - case PCTINCREASE: - case FLASH_CACHE: - case CELL_FLASH_CACHE: - case KEEP: - case NONE: - case LOB: - case STORE: - case ROW: - case CHUNK: - case CACHE: - case NOCACHE: - case LOGGING: - case NOCOMPRESS: - case KEEP_DUPLICATES: - case EXCEPTIONS: - case PURGE: - case INITIALLY: - case END: - case COMMENT: - case ENABLE: - case DISABLE: - case SEQUENCE: - case USER: - case ANALYZE: - case OPTIMIZE: - case GRANT: - case REVOKE: - case FULL: - case TO: - case NEW: - case INTERVAL: - case LOCK: - case LIMIT: - case IDENTIFIED: - case PASSWORD: - case BINARY: - case WINDOW: - case OFFSET: - case SHARE: - case START: - case CONNECT: - case MATCHED: - case ERRORS: - case REJECT: - case UNLIMITED: - case BEGIN: - case EXCLUSIVE: - case MODE: - case ADVISE: - case TYPE: - alias = lexer.stringVal(); - lexer.nextToken(); - return alias; - case QUES: - alias = "?"; - lexer.nextToken(); - default: - break; - } - } + alias = alias(); if (alias != null) { while (lexer.token() == Token.DOT) { @@ -205,6 +119,99 @@ public class SQLParser { return alias; } + protected String alias() { + String alias = null; + if (lexer.token() == Token.LITERAL_ALIAS) { + alias = '"' + lexer.stringVal() + '"'; + lexer.nextToken(); + } else if (lexer.token() == Token.IDENTIFIER) { + alias = lexer.stringVal(); + lexer.nextToken(); + } else if (lexer.token() == Token.LITERAL_CHARS) { + alias = "'" + lexer.stringVal() + "'"; + lexer.nextToken(); + } else { + switch (lexer.token()) { + case KEY: + case INDEX: + case CASE: + case MODEL: + case PCTFREE: + case INITRANS: + case MAXTRANS: + case SEGMENT: + case CREATION: + case IMMEDIATE: + case DEFERRED: + case STORAGE: + case NEXT: + case MINEXTENTS: + case MAXEXTENTS: + case MAXSIZE: + case PCTINCREASE: + case FLASH_CACHE: + case CELL_FLASH_CACHE: + case KEEP: + case NONE: + case LOB: + case STORE: + case ROW: + case CHUNK: + case CACHE: + case NOCACHE: + case LOGGING: + case NOCOMPRESS: + case KEEP_DUPLICATES: + case EXCEPTIONS: + case PURGE: + case INITIALLY: + case END: + case COMMENT: + case ENABLE: + case DISABLE: + case SEQUENCE: + case USER: + case ANALYZE: + case OPTIMIZE: + case GRANT: + case REVOKE: + case FULL: + case TO: + case NEW: + case INTERVAL: + case LOCK: + case LIMIT: + case IDENTIFIED: + case PASSWORD: + case BINARY: + case WINDOW: + case OFFSET: + case SHARE: + case START: + case CONNECT: + case MATCHED: + case ERRORS: + case REJECT: + case UNLIMITED: + case BEGIN: + case EXCLUSIVE: + case MODE: + case ADVISE: + case TYPE: + case CLOSE: + alias = lexer.stringVal(); + lexer.nextToken(); + return alias; + case QUES: + alias = "?"; + lexer.nextToken(); + default: + break; + } + } + return alias; + } + protected void printError(Token token) { String arround; if (lexer.mark >= 0 && (lexer.text.length() > lexer.mark + 30)) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2DropSequenceTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2DropSequenceTest_0.java index beb82c1ce6..eef498cdbe 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2DropSequenceTest_0.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2DropSequenceTest_0.java @@ -24,8 +24,6 @@ import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser; import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor; -import com.alibaba.druid.stat.TableStat; -import com.alibaba.druid.stat.TableStat.Column; import com.alibaba.druid.util.JdbcConstants; public class DB2DropSequenceTest_0 extends DB2Test { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest6.java new file mode 100644 index 0000000000..1017c47f74 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest6.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.odps; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import junit.framework.TestCase; + +public class OdpsSelectTest6 extends TestCase { + + public void test_select() throws Exception { + String sql = "select true from abc";// + Assert.assertEquals("SELECT true" + + "\nFROM abc", SQLUtils.formatOdps(sql)); + Assert.assertEquals("select true" + + "\nfrom abc", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest7.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest7.java new file mode 100644 index 0000000000..f3d733de67 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest7.java @@ -0,0 +1,59 @@ +/* + * 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.odps; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat.Column; +import com.alibaba.druid.util.JdbcConstants; + +import junit.framework.TestCase; + +public class OdpsSelectTest7 extends TestCase { + + public void test_select() throws Exception { + String sql = "select name as close from abc";// + Assert.assertEquals("SELECT name AS close" + + "\nFROM abc", SQLUtils.formatOdps(sql)); + Assert.assertEquals("select name as close" + + "\nfrom abc", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(1, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getColumns().contains(new Column("abc", "name"))); + } + +}