improved sql parser.

This commit is contained in:
wenshao
2017-08-10 14:29:21 +08:00
parent 85db17a907
commit 1c900720d8
9 changed files with 258 additions and 6 deletions
@@ -186,6 +186,10 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
}
for (;;) {
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
}
if (identifierEquals("ENGINE")) {
lexer.nextToken();
if (lexer.token() == Token.EQ) {
@@ -279,6 +279,12 @@ public class SQLSelectParser extends SQLParser {
accept(Token.BY);
SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause();
if (identifierEquals("ROLLUP")) {
lexer.nextToken();
accept(Token.LPAREN);
groupBy.setWithRollUp(true);
}
for (;;) {
SQLExpr item = parseGroupByItem();
@@ -291,6 +297,9 @@ public class SQLSelectParser extends SQLParser {
lexer.nextToken();
}
if (groupBy.isWithRollUp()) {
accept(Token.RPAREN);
}
if (lexer.token() == (Token.HAVING)) {
lexer.nextToken();
@@ -275,10 +275,27 @@ public class SchemaRepository {
for (SQLStatement stmt : stmtList) {
if (stmt instanceof MySqlShowColumnsStatement) {
MySqlShowColumnsStatement showColumns = ((MySqlShowColumnsStatement) stmt);
SQLName table = showColumns.getTable();
SchemaObject schemaObject = findTable(table);
MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();
createTableStmt.showCoumns(buf);
SQLName db = showColumns.getDatabase();
Schema schema;
if (db == null) {
schema = getDefaultSchema();
} else {
schema = findSchema(db.getSimpleName());
}
SQLName table = null;
SchemaObject schemaObject = null;
if (schema != null) {
table = showColumns.getTable();
schemaObject = schema.findTable(table.getSimpleName());
}
if (schemaObject == null) {
buf.append("ERROR 1146 (42S02): Table '" + table + "' doesn't exist\n");
} else {
MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();
createTableStmt.showCoumns(buf);
}
} else if (stmt instanceof MySqlShowCreateTableStatement) {
MySqlShowCreateTableStatement showCreateTableStmt = (MySqlShowCreateTableStatement) stmt;
SQLName table = showCreateTableStmt.getName();
@@ -1307,9 +1307,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
public boolean visit(SQLSelectGroupByClause x) {
boolean oracle = JdbcConstants.ORACLE.equals(dbType);
boolean rollup = x.isWithRollUp();
int itemSize = x.getItems().size();
if (itemSize > 0) {
print0(ucase ? "GROUP BY " : "group by ");
if (oracle && rollup) {
print0(ucase ? "ROLLUP (" : "rollup (");
}
incrementIndent();
for (int i = 0; i < itemSize; ++i) {
if (i != 0) {
@@ -1321,6 +1328,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
x.getItems().get(i).accept(this);
}
if (oracle && rollup) {
print(')');
}
decrementIndent();
}
@@ -1330,7 +1340,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
x.getHaving().accept(this);
}
if (x.isWithRollUp()) {
if (x.isWithRollUp() && !oracle) {
print0(ucase ? " WITH ROLLUP" : " with rollup");
}
@@ -916,6 +916,10 @@ public class MySqlCreateTable_showColumns_repository_test extends MysqlTest {
, repository.console("show create table test1"));
assertEquals("ERROR 1146 (42S02): Table 'test1' doesn't exist\n"
, repository.console("show columns from test1"));
assertEquals("CREATE TABLE test1_xx (\n" +
"\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" +
"\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" +
@@ -968,5 +972,15 @@ public class MySqlCreateTable_showColumns_repository_test extends MysqlTest {
")"
, repository.console("show create table test5"));
repository.console("CREATE TABLE tddl5_00.ljh_test1(be_id VARCHAR(20) NOT NULL DEFAULT '' COMMENT '企业标识')ENGINE = InnoDB, CHARACTER SET = utf8, COMMENT = '应用层-汇总销售及销售毛利表'");
assertEquals("+-------+-------------+------+-----+---------+-------+\n" +
"| Field | Type | Null | Key | Default | Extra |\n" +
"+-------+-------------+------+-----+---------+-------+\n" +
"| be_id | VARCHAR(20) | NO | | '' | |\n" +
"+-------+-------------+------+-----+---------+-------+\n"
, repository.console("show columns from tddl5_00.ljh_test1"));
}
}
@@ -36,7 +36,7 @@ public class OracleFlashbackQueryTest3 extends TestCase {
"\t, AVG(salary) * 12 AS \"Average Sal\"\n" +
"FROM employees e, departments d\n" +
"WHERE d.department_id = e.department_id\n" +
"GROUP BY ROLLUP(department_name, job_id);";
"GROUP BY ROLLUP (department_name, job_id);";
OracleStatementParser parser = new OracleStatementParser(sql);
SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatementList().get(0);
@@ -0,0 +1,98 @@
/*
* Copyright 1999-2017 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.oracle.select;
import com.alibaba.druid.sql.OracleTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import org.junit.Assert;
import java.util.List;
public class OracleSelectTest71 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"select * from (\n" +
" select a.*,rownum rn from (SELECT\n" +
" A.ID,A.SIM_NO,A.ICCID,A.IMSI,A.IMEI,A.OPERATOR,\n" +
" A.CHARGES_PLAN_ID,A.USED_TRAFFIC,\n" +
" A.STATUS,A.MEMO,A.TYPE,A.TER_ID,B.ID DEVICE_ID,C.TER_CODE,\n" +
" D.ID VECL_ID,D.VIN VECL_VIN,D.LPN VECL_LPN,D.LPC VECL_LPC,E.APP_KEY\n" +
" FROM\n" +
" BAS_SIM A LEFT JOIN BAS_DEVICE B ON A.TER_ID=B.TER_ID\n" +
" LEFT JOIN BAS_TERMINAL C ON A.TER_ID=C.ID\n" +
" LEFT JOIN BAS_VEHICLE D ON B.VECL_ID=D.ID\n" +
" LEFT JOIN BAS_APPLICATION E ON A.APP_ID=E.ID\n" +
" WHERE 1=1\n" +
" \n" +
" \n" +
" AND A.SIM_NO LIKE '%'||?||'%' \n" +
" order by A.SIM_NO ASC ) a\n" +
"\n" +
" ) where rn > ?*(?-1) and rn <= ?*?"; //
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
Assert.assertEquals(1, statementList.size());
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.accept(visitor);
System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
System.out.println("coditions : " + visitor.getConditions());
System.out.println("relationships : " + visitor.getRelationships());
System.out.println("orderBy : " + visitor.getOrderByColumns());
assertEquals(5, visitor.getTables().size());
assertEquals(26, visitor.getColumns().size());
{
String text = SQLUtils.toOracleString(stmt);
assertEquals("SELECT *\n" +
"FROM (\n" +
"\tSELECT a.*, rownum AS rn\n" +
"\tFROM (\n" +
"\t\tSELECT A.ID, A.SIM_NO, A.ICCID, A.IMSI, A.IMEI\n" +
"\t\t\t, A.OPERATOR, A.CHARGES_PLAN_ID, A.USED_TRAFFIC, A.STATUS, A.MEMO\n" +
"\t\t\t, A.TYPE, A.TER_ID, B.ID AS DEVICE_ID, C.TER_CODE, D.ID AS VECL_ID\n" +
"\t\t\t, D.VIN AS VECL_VIN, D.LPN AS VECL_LPN, D.LPC AS VECL_LPC, E.APP_KEY\n" +
"\t\tFROM BAS_SIM A\n" +
"\t\tLEFT JOIN BAS_DEVICE B ON A.TER_ID = B.TER_ID \n" +
"\t\tLEFT JOIN BAS_TERMINAL C ON A.TER_ID = C.ID \n" +
"\t\tLEFT JOIN BAS_VEHICLE D ON B.VECL_ID = D.ID \n" +
"\t\t\tLEFT JOIN BAS_APPLICATION E ON A.APP_ID = E.ID \n" +
"\t\tWHERE 1 = 1\n" +
"\t\t\tAND A.SIM_NO LIKE ('%' || ? || '%')\n" +
"\t\tORDER BY A.SIM_NO ASC\n" +
"\t) a\n" +
")\n" +
"WHERE rn > ? * (? - 1)\n" +
"\tAND rn <= ? * ?", text);
}
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh")));
// Assert.assertTrue(visitor.getOrderByColumns().contains(new TableStat.Column("employees", "last_name")));
}
}
@@ -0,0 +1,64 @@
/*
* Copyright 1999-2017 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.oracle.select;
import com.alibaba.druid.sql.OracleTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import org.junit.Assert;
import java.util.List;
public class OracleSelectTest72 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"Select A,B,C,sum(E) from test group by rollup(A,B,C)"; //
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
Assert.assertEquals(1, statementList.size());
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.accept(visitor);
System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
System.out.println("coditions : " + visitor.getConditions());
System.out.println("relationships : " + visitor.getRelationships());
System.out.println("orderBy : " + visitor.getOrderByColumns());
assertEquals(1, visitor.getTables().size());
assertEquals(4, visitor.getColumns().size());
{
String text = SQLUtils.toOracleString(stmt);
assertEquals("SELECT A, B, C, SUM(E)\n" +
"FROM test\n" +
"GROUP BY ROLLUP (A, B, C)", text);
}
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh")));
// Assert.assertTrue(visitor.getOrderByColumns().contains(new TableStat.Column("employees", "last_name")));
}
}
@@ -0,0 +1,36 @@
package com.alibaba.druid.oracle;
import com.alibaba.druid.DbTestCase;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
import java.sql.Connection;
import java.util.Collections;
import java.util.List;
/**
* Created by wenshao on 23/07/2017.
*/
public class Oracle_getCreateTableScriptTest_sonar extends DbTestCase {
public Oracle_getCreateTableScriptTest_sonar() {
super("pool_config/oracle_db_sonar.properties");
}
public void test_oracle() throws Exception {
Connection conn = getConnection();
// 从Oracle通过DBMS_METADATA.GET_DDL获取CreateTable语句列表
//String createTableScript = JdbcUtils.getCreateTableScript(conn, JdbcConstants.ORACLE);
//System.out.println(createTableScript);
List<String> tables = JdbcUtils.showTables(conn, JdbcConstants.ORACLE);
for (String table : tables) {
Object cnt = JdbcUtils.executeQuery(conn, "select count(*) CNT from " + table, Collections.emptyList())
.get(0)
.get("CNT");
System.out.println(table + " : " + cnt);
}
conn.close();
}
}