From 9889299812dfb3dd193d974a06850ec95941f757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Fri, 18 Mar 2016 09:24:08 +0800 Subject: [PATCH 1/2] add teradata support --- .../java/com/alibaba/druid/sql/SQLUtils.java | 62 +++++++++++-------- .../dialect/teradata/ast/TeradataObject.java | 7 +++ .../teradata/parser/TeradataExprParser.java | 24 +++++++ .../teradata/parser/TeradataLexer.java | 25 ++++++++ .../parser/TeradataStatementParser.java | 16 +++++ .../teradata/visitor/TeradataASTVisitor.java | 7 +++ .../visitor/TeradataASTVisitorAdapter.java | 7 +++ .../visitor/TeradataOutputVisitor.java | 11 ++++ .../visitor/TeradataSchemaStatVisitor.java | 13 ++++ .../com/alibaba/druid/util/JdbcConstants.java | 3 + .../bvt/filter/wall/TenantDeleteTest.java | 2 + 11 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TeradataObject.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index fca98cccab..54316c274c 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -46,6 +46,8 @@ import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataOutputVisitor; +import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataSchemaStatVisitor; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLParserUtils; @@ -56,7 +58,6 @@ import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; import com.alibaba.druid.util.JdbcConstants; -import com.alibaba.druid.util.JdbcUtils; import com.alibaba.druid.util.StringUtils; public class SQLUtils { @@ -109,35 +110,35 @@ public class SQLUtils { } public static SQLExpr toMySqlExpr(String sql) { - return toSQLExpr(sql, JdbcUtils.MYSQL); + return toSQLExpr(sql, JdbcConstants.MYSQL); } public static String formatMySql(String sql) { - return format(sql, JdbcUtils.MYSQL); + return format(sql, JdbcConstants.MYSQL); } public static String formatMySql(String sql, FormatOption option) { - return format(sql, JdbcUtils.MYSQL, option); + return format(sql, JdbcConstants.MYSQL, option); } public static String formatOracle(String sql) { - return format(sql, JdbcUtils.ORACLE); + return format(sql, JdbcConstants.ORACLE); } public static String formatOracle(String sql, FormatOption option) { - return format(sql, JdbcUtils.ORACLE, option); + return format(sql, JdbcConstants.ORACLE, option); } public static String formatOdps(String sql) { - return format(sql, JdbcUtils.ODPS); + return format(sql, JdbcConstants.ODPS); } public static String formatOdps(String sql, FormatOption option) { - return format(sql, JdbcUtils.ODPS, option); + return format(sql, JdbcConstants.ODPS, option); } public static String formatSQLServer(String sql) { - return format(sql, JdbcUtils.SQL_SERVER); + return format(sql, JdbcConstants.SQL_SERVER); } public static String toOracleString(SQLObject sqlObject) { @@ -173,7 +174,7 @@ public class SQLUtils { } public static String formatPGSql(String sql, FormatOption option) { - return format(sql, JdbcUtils.POSTGRESQL, option); + return format(sql, JdbcConstants.POSTGRESQL, option); } public static SQLExpr toSQLExpr(String sql, String dbType) { @@ -344,7 +345,7 @@ public class SQLUtils { public static SQLASTOutputVisitor createFormatOutputVisitor(Appendable out, // List statementList, // String dbType) { - if (JdbcUtils.ORACLE.equals(dbType) || JdbcUtils.ALI_ORACLE.equals(dbType)) { + if (JdbcConstants.ORACLE.equals(dbType) || JdbcConstants.ALI_ORACLE.equals(dbType)) { if (statementList == null || statementList.size() == 1) { return new OracleOutputVisitor(out, false); } else { @@ -352,27 +353,31 @@ public class SQLUtils { } } - if (JdbcUtils.MYSQL.equals(dbType) || // - JdbcUtils.MARIADB.equals(dbType) || // - JdbcUtils.H2.equals(dbType)) { + if (JdbcConstants.MYSQL.equals(dbType) // + || JdbcConstants.MARIADB.equals(dbType) // + || JdbcConstants.H2.equals(dbType)) { return new MySqlOutputVisitor(out); } - if (JdbcUtils.POSTGRESQL.equals(dbType)) { + if (JdbcConstants.POSTGRESQL.equals(dbType)) { return new PGOutputVisitor(out); } - if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { + if (JdbcConstants.SQL_SERVER.equals(dbType) || JdbcConstants.JTDS.equals(dbType)) { return new SQLServerOutputVisitor(out); } - if (JdbcUtils.DB2.equals(dbType)) { + if (JdbcConstants.DB2.equals(dbType)) { return new DB2OutputVisitor(out); } - if (JdbcUtils.ODPS.equals(dbType)) { + if (JdbcConstants.ODPS.equals(dbType)) { return new OdpsOutputVisitor(out); } + + if (JdbcConstants.TERADATA.equals(dbType)) { + return new TeradataOutputVisitor(out); + } return new SQLASTOutputVisitor(out); } @@ -383,31 +388,35 @@ public class SQLUtils { } public static SchemaStatVisitor createSchemaStatVisitor(String dbType) { - if (JdbcUtils.ORACLE.equals(dbType) || JdbcUtils.ALI_ORACLE.equals(dbType)) { + if (JdbcConstants.ORACLE.equals(dbType) || JdbcConstants.ALI_ORACLE.equals(dbType)) { return new OracleSchemaStatVisitor(); } - if (JdbcUtils.MYSQL.equals(dbType) || // - JdbcUtils.MARIADB.equals(dbType) || // - JdbcUtils.H2.equals(dbType)) { + if (JdbcConstants.MYSQL.equals(dbType) || // + JdbcConstants.MARIADB.equals(dbType) || // + JdbcConstants.H2.equals(dbType)) { return new MySqlSchemaStatVisitor(); } - if (JdbcUtils.POSTGRESQL.equals(dbType)) { + if (JdbcConstants.POSTGRESQL.equals(dbType)) { return new PGSchemaStatVisitor(); } - if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { + if (JdbcConstants.SQL_SERVER.equals(dbType) || JdbcConstants.JTDS.equals(dbType)) { return new SQLServerSchemaStatVisitor(); } - if (JdbcUtils.DB2.equals(dbType)) { + if (JdbcConstants.DB2.equals(dbType)) { return new DB2SchemaStatVisitor(); } - if (JdbcUtils.ODPS.equals(dbType)) { + if (JdbcConstants.ODPS.equals(dbType)) { return new OdpsSchemaStatVisitor(); } + + if (JdbcConstants.TERADATA.equals(dbType)) { + return new TeradataSchemaStatVisitor(); + } return new SchemaStatVisitor(); } @@ -647,3 +656,4 @@ public class SQLUtils { } } } + diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TeradataObject.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TeradataObject.java new file mode 100644 index 0000000000..22a0f6ce4e --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TeradataObject.java @@ -0,0 +1,7 @@ +package com.alibaba.druid.sql.dialect.teradata.ast; + +import com.alibaba.druid.sql.ast.SQLObject; + +public interface TeradataObject extends SQLObject { + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java new file mode 100644 index 0000000000..d4c9d86f94 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java @@ -0,0 +1,24 @@ +package com.alibaba.druid.sql.dialect.teradata.parser; + +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.util.JdbcConstants; + +public class TeradataExprParser extends SQLExprParser { + + public final static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM", "ROW_NUMBER" }; + + public TeradataExprParser(String sql){ + this(new TeradataLexer(sql)); + this.lexer.nextToken(); + this.dbType = JdbcConstants.TERADATA; + } + + public TeradataExprParser(Lexer lexer){ + super(lexer); + this.aggregateFunctions = AGGREGATE_FUNCTIONS; + this.dbType = JdbcConstants.TERADATA; + } + + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java new file mode 100644 index 0000000000..ea117ac69e --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java @@ -0,0 +1,25 @@ +package com.alibaba.druid.sql.dialect.teradata.parser; + +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.druid.sql.parser.Keywords; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.Token; + +public class TeradataLexer extends Lexer { + public final static Keywords DEFAULT_PG_KEYWORDS; + + static { + Map map = new HashMap(); + map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords()); + + DEFAULT_PG_KEYWORDS = new Keywords(map); + } + + public TeradataLexer(String input){ + super(input); + super.keywods = DEFAULT_PG_KEYWORDS; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java new file mode 100644 index 0000000000..a847102eee --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java @@ -0,0 +1,16 @@ +package com.alibaba.druid.sql.dialect.teradata.parser; + +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLStatementParser; + +public class TeradataStatementParser extends SQLStatementParser { + + public TeradataStatementParser(String sql){ + super(new TeradataExprParser(sql)); + } + + public TeradataStatementParser(Lexer lexer){ + super(new TeradataExprParser(lexer)); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java new file mode 100644 index 0000000000..a0bee2499b --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java @@ -0,0 +1,7 @@ +package com.alibaba.druid.sql.dialect.teradata.visitor; + +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public interface TeradataASTVisitor extends SQLASTVisitor { + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java new file mode 100644 index 0000000000..d6bc6a50b0 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java @@ -0,0 +1,7 @@ +package com.alibaba.druid.sql.dialect.teradata.visitor; + +import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; + +public class TeradataASTVisitorAdapter extends SQLASTVisitorAdapter implements TeradataASTVisitor { + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java new file mode 100644 index 0000000000..dfc81f1f5c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java @@ -0,0 +1,11 @@ +package com.alibaba.druid.sql.dialect.teradata.visitor; + +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; + +public class TeradataOutputVisitor extends SQLASTOutputVisitor implements TeradataASTVisitor { + + public TeradataOutputVisitor(Appendable appender){ + super(appender); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java new file mode 100644 index 0000000000..efa2e33378 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java @@ -0,0 +1,13 @@ +package com.alibaba.druid.sql.dialect.teradata.visitor; + +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcUtils; + +public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements TeradataASTVisitor { + + @Override + public String getDbType() { + return JdbcUtils.POSTGRESQL; + } + +} diff --git a/src/main/java/com/alibaba/druid/util/JdbcConstants.java b/src/main/java/com/alibaba/druid/util/JdbcConstants.java index cc47401dca..e76e071371 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcConstants.java +++ b/src/main/java/com/alibaba/druid/util/JdbcConstants.java @@ -71,6 +71,9 @@ public interface JdbcConstants { */ public static final String ODPS = "odps"; public static final String ODPS_DRIVER = "com.aliyun.odps.jdbc.OdpsDriver"; + + public static final String TERADATA = "teradata"; + public static final String TERADATA_DRIVER = "com.teradata.jdbc.TeraDriver"; /** * Log4JDBC diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantDeleteTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantDeleteTest.java index c631e7cb85..2e1f5715e5 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantDeleteTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantDeleteTest.java @@ -40,6 +40,8 @@ public class TenantDeleteTest extends TestCase { public void testMySql() throws Exception { WallProvider.setTenantValue(123); MySqlWallProvider provider = new MySqlWallProvider(config); + + WallProvider.setTenantValue("test"); WallCheckResult checkResult = provider.check(sql); Assert.assertEquals(0, checkResult.getViolations().size()); From 48c33cb911f1670030c3c43b2c67da5ebb4e995e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Fri, 18 Mar 2016 09:24:22 +0800 Subject: [PATCH 2/2] add db2testcase --- .../druid/bvt/sql/db2/DB2SelectTest_9.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_9.java diff --git a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_9.java b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_9.java new file mode 100644 index 0000000000..56744005d3 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_9.java @@ -0,0 +1,79 @@ +/* + * 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.db2; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.DB2Test; +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.util.JdbcConstants; + +public class DB2SelectTest_9 extends DB2Test { + + public void test_0() throws Exception { + String sql = "select tsuserstb0_.USERID as USERID1_1_, tsuserstb0_.CREASTAF as CREASTAF2_1_" + + " , tsuserstb0_.CREATIME as CREATIME3_1_, tsuserstb0_.LOCORGNO as LOCORGNO4_1_" + + " , tsuserstb0_.PWDMODIFYTIME as PWDMODIF5_1_, tsuserstb0_.REMARK01 as REMARK6_1_" + + " , tsuserstb0_.REMARK02 as REMARK7_1_, tsuserstb0_.STAORGNO as STAORGNO8_1_" + + " , tsuserstb0_.UPDASTAF as UPDASTAF9_1_, tsuserstb0_.UPDATIME as UPDATIM10_1_, tsuserstb0_.USERNAME as USERNAM11_1_" + + " , tsuserstb0_.USERPWD as USERPWD12_1_, tsuserstb0_.USERSTATE as USERSTA13_1_" + + " from TS_USERSTB tsuserstb0_ fetch first 10 rows only"; + + DB2StatementParser parser = new DB2StatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor(); + 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(13, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("TS_USERSTB"))); + + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "last_name"))); + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name"))); + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "full_name"))); + + Assert.assertEquals("SELECT tsuserstb0_.USERID AS USERID1_1_, tsuserstb0_.CREASTAF AS CREASTAF2_1_, tsuserstb0_.CREATIME AS CREATIME3_1_, tsuserstb0_.LOCORGNO AS LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME AS PWDMODIF5_1_" + + "\n\t, tsuserstb0_.REMARK01 AS REMARK6_1_, tsuserstb0_.REMARK02 AS REMARK7_1_, tsuserstb0_.STAORGNO AS STAORGNO8_1_, tsuserstb0_.UPDASTAF AS UPDASTAF9_1_, tsuserstb0_.UPDATIME AS UPDATIM10_1_" + + "\n\t, tsuserstb0_.USERNAME AS USERNAM11_1_, tsuserstb0_.USERPWD AS USERPWD12_1_, tsuserstb0_.USERSTATE AS USERSTA13_1_" + + "\nFROM TS_USERSTB tsuserstb0_" + + "\nFETCH FIRST 10 ROWS ONLY", // + SQLUtils.toSQLString(stmt, JdbcConstants.DB2)); + Assert.assertEquals("select tsuserstb0_.USERID as USERID1_1_, tsuserstb0_.CREASTAF as CREASTAF2_1_, tsuserstb0_.CREATIME as CREATIME3_1_, tsuserstb0_.LOCORGNO as LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME as PWDMODIF5_1_" + + "\n\t, tsuserstb0_.REMARK01 as REMARK6_1_, tsuserstb0_.REMARK02 as REMARK7_1_, tsuserstb0_.STAORGNO as STAORGNO8_1_, tsuserstb0_.UPDASTAF as UPDASTAF9_1_, tsuserstb0_.UPDATIME as UPDATIM10_1_" + + "\n\t, tsuserstb0_.USERNAME as USERNAM11_1_, tsuserstb0_.USERPWD as USERPWD12_1_, tsuserstb0_.USERSTATE as USERSTA13_1_" + + "\nfrom TS_USERSTB tsuserstb0_" + + "\nfetch first 10 rows only", // + SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + } +}