improved sql parser.

This commit is contained in:
wenshao
2017-09-29 21:49:59 +08:00
parent 236e99bf45
commit bc8032c595
11 changed files with 2113 additions and 35 deletions
@@ -20,6 +20,7 @@ import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleWithSubqueryEntry;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleSysdateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;
import com.alibaba.druid.util.FnvHash;
@@ -762,6 +763,13 @@ public class SQLTransformUtils {
return y;
}
if (x instanceof OracleWithSubqueryEntry) {
SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry();
((OracleWithSubqueryEntry) x).cloneTo(entry);
entry.setParent(x.getParent());
return entry;
}
return x;
}
@@ -74,7 +74,7 @@ public class SQLWithSubqueryClause extends SQLObjectImpl {
protected SQLSelect subQuery;
protected SQLStatement returningStatement;
protected void cloneTo(Entry x) {
public void cloneTo(Entry x) {
for (SQLName column : columns) {
SQLName column2 = column.clone();
column2.setParent(x);
@@ -63,7 +63,7 @@ public class OracleWithSubqueryEntry extends Entry implements OracleSQLObject {
this.accept0((OracleASTVisitor) visitor);
}
protected void cloneTo(OracleWithSubqueryEntry x) {
public void cloneTo(OracleWithSubqueryEntry x) {
super.cloneTo(x);
if (searchClause != null) {
@@ -885,17 +885,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
@Override
public boolean visit(OracleCursorExpr x) {
print0(ucase ? "CURSOR(" : "cursor(");
this.indentCount++;
println();
x.getQuery().accept(this);
this.indentCount--;
println();
print(')');
return false;
}
@Override
public void endVisit(OracleCursorExpr x) {
File diff suppressed because it is too large Load Diff
@@ -37,6 +37,8 @@ import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause;
import com.alibaba.druid.sql.ast.statement.SQLWhileStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;
import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreatePackageStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;
@@ -2668,7 +2670,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
if (left instanceof SQLJoinTableSource
&& ((SQLJoinTableSource) left).getJoinType() == JoinType.COMMA
&& x.getJoinType() != JoinType.COMMA) {
&& x.getJoinType() != JoinType.COMMA
&& !JdbcConstants.POSTGRESQL.equals(dbType)) {
print('(');
printTableSource(left);
print(')');
@@ -5388,4 +5391,33 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
this.ucase = isEnabled(VisitorFeature.OutputUCase);
this.parameterized = isEnabled(VisitorFeature.OutputParameterized);
}
/////////////// for oracle
public boolean visit(OracleCursorExpr x) {
print0(ucase ? "CURSOR(" : "cursor(");
this.indentCount++;
println();
x.getQuery().accept(this);
this.indentCount--;
println();
print(')');
return false;
}
public boolean visit(OracleDatetimeExpr x) {
x.getExpr().accept(this);
SQLExpr timeZone = x.getTimeZone();
if (timeZone instanceof SQLIdentifierExpr) {
if (((SQLIdentifierExpr) timeZone).getName().equalsIgnoreCase("LOCAL")) {
print0(ucase ? " AT LOCAL" : "alter session set ");
return false;
}
}
print0(ucase ? " AT TIME ZONE " : " at time zone ");
timeZone.accept(this);
return false;
}
}
@@ -0,0 +1,137 @@
package com.alibaba.druid.bvt.sql.oracle;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.util.JdbcConstants;
import junit.framework.TestCase;
public class SQLSortTest extends TestCase {
public void test_sort() throws Exception {
String sql = "CREATE TABLE \"ECC_FND\".\"FORM_URL\" \n" +
" (\t\"FORM_URL_ID\" NUMBER(10,0) NOT NULL ENABLE, \n" +
"\t\"FORM_ID\" NUMBER(10,0) NOT NULL ENABLE, \n" +
"\t\"URL\" VARCHAR2(1024) NOT NULL ENABLE, \n" +
"\t\"OPR_TYPE\" VARCHAR2(16) DEFAULT 'ADD' NOT NULL ENABLE, \n" +
"\t\"ENABLE_FLAG\" VARCHAR2(10) DEFAULT 'T' NOT NULL ENABLE, \n" +
"\t CONSTRAINT \"PK_FORM_URL12\" PRIMARY KEY (\"FORM_URL_ID\")\n" +
" USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS \n" +
" STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" +
" PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)\n" +
" TABLESPACE \"ECC_IDX_TSP\" ENABLE, \n" +
"\t CONSTRAINT \"FK_REFERE83\" FOREIGN KEY (\"FORM_ID\")\n" +
"\t REFERENCES \"ECC_FND\".\"FORM\" (\"FORM_ID\") ENABLE\n" +
" ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING\n" +
" STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" +
" PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)\n" +
" TABLESPACE \"ECC_TSP\"; \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" CREATE TABLE \"ECC_FND\".\"FORM\" \n" +
" (\t\"FORM_ID\" NUMBER(10,0) NOT NULL ENABLE, \n" +
"\t\"NAME\" VARCHAR2(32) NOT NULL ENABLE, \n" +
"\t\"CODE\" VARCHAR2(128), \n" +
"\t\"DESCRIPTION\" VARCHAR2(1024) NOT NULL ENABLE, \n" +
"\t\"FORM_TYPE_ID\" NUMBER(10,0) NOT NULL ENABLE, \n" +
"\t\"ENABLE_FLAG\" VARCHAR2(10) NOT NULL ENABLE, \n" +
"\t CONSTRAINT \"PK_FORM7\" PRIMARY KEY (\"FORM_ID\")\n" +
" USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS \n" +
" STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" +
" PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)\n" +
" TABLESPACE \"ECC_IDX_TSP\" ENABLE\n" +
" ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING\n" +
" STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" +
" PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)\n" +
" TABLESPACE \"ECC_TSP\" ";
String sortedSql = SQLUtils.sort(sql, JdbcConstants.ORACLE);
assertEquals("CREATE TABLE \"ECC_FND\".\"FORM\" (\n" +
"\t\"FORM_ID\" NUMBER(10, 0) NOT NULL ENABLE,\n" +
"\t\"NAME\" VARCHAR2(32) NOT NULL ENABLE,\n" +
"\t\"CODE\" VARCHAR2(128),\n" +
"\t\"DESCRIPTION\" VARCHAR2(1024) NOT NULL ENABLE,\n" +
"\t\"FORM_TYPE_ID\" NUMBER(10, 0) NOT NULL ENABLE,\n" +
"\t\"ENABLE_FLAG\" VARCHAR2(10) NOT NULL ENABLE,\n" +
"\tCONSTRAINT \"PK_FORM7\" PRIMARY KEY (\"FORM_ID\")\n" +
"\t\tUSING INDEX\n" +
"\t\tPCTFREE 10\n" +
"\t\tINITRANS 2\n" +
"\t\tMAXTRANS 255\n" +
"\t\tTABLESPACE \"ECC_IDX_TSP\"\n" +
"\t\tSTORAGE (\n" +
"\t\t\tINITIAL 65536\n" +
"\t\t\tNEXT 1048576\n" +
"\t\t\tMINEXTENTS 1\n" +
"\t\t\tMAXEXTENTS 2147483645\n" +
"\t\t\tPCTINCREASE 0\n" +
"\t\t\tFREELISTS 1\n" +
"\t\t\tFREELIST GROUPS 1\n" +
"\t\t\tBUFFER_POOL DEFAULT\n" +
"\t\t)\n" +
"\t\tCOMPUTE STATISTICS\n" +
"\t\tENABLE\n" +
")\n" +
"PCTFREE 10\n" +
"PCTUSED 40\n" +
"INITRANS 1\n" +
"MAXTRANS 255\n" +
"NOCOMPRESS\n" +
"LOGGING\n" +
"TABLESPACE \"ECC_TSP\"\n" +
"STORAGE (\n" +
"\tINITIAL 65536\n" +
"\tNEXT 1048576\n" +
"\tMINEXTENTS 1\n" +
"\tMAXEXTENTS 2147483645\n" +
"\tPCTINCREASE 0\n" +
"\tFREELISTS 1\n" +
"\tFREELIST GROUPS 1\n" +
"\tBUFFER_POOL DEFAULT\n" +
")\n" +
"CREATE TABLE \"ECC_FND\".\"FORM_URL\" (\n" +
"\t\"FORM_URL_ID\" NUMBER(10, 0) NOT NULL ENABLE,\n" +
"\t\"FORM_ID\" NUMBER(10, 0) NOT NULL ENABLE,\n" +
"\t\"URL\" VARCHAR2(1024) NOT NULL ENABLE,\n" +
"\t\"OPR_TYPE\" VARCHAR2(16) DEFAULT 'ADD' NOT NULL ENABLE,\n" +
"\t\"ENABLE_FLAG\" VARCHAR2(10) DEFAULT 'T' NOT NULL ENABLE,\n" +
"\tCONSTRAINT \"PK_FORM_URL12\" PRIMARY KEY (\"FORM_URL_ID\")\n" +
"\t\tUSING INDEX\n" +
"\t\tPCTFREE 10\n" +
"\t\tINITRANS 2\n" +
"\t\tMAXTRANS 255\n" +
"\t\tTABLESPACE \"ECC_IDX_TSP\"\n" +
"\t\tSTORAGE (\n" +
"\t\t\tINITIAL 65536\n" +
"\t\t\tNEXT 1048576\n" +
"\t\t\tMINEXTENTS 1\n" +
"\t\t\tMAXEXTENTS 2147483645\n" +
"\t\t\tPCTINCREASE 0\n" +
"\t\t\tFREELISTS 1\n" +
"\t\t\tFREELIST GROUPS 1\n" +
"\t\t\tBUFFER_POOL DEFAULT\n" +
"\t\t)\n" +
"\t\tCOMPUTE STATISTICS\n" +
"\t\tENABLE,\n" +
"\tCONSTRAINT \"FK_REFERE83\" FOREIGN KEY (\"FORM_ID\")\n" +
"\t\tREFERENCES \"ECC_FND\".\"FORM\" (\"FORM_ID\") ENABLE\n" +
")\n" +
"PCTFREE 10\n" +
"PCTUSED 40\n" +
"INITRANS 1\n" +
"MAXTRANS 255\n" +
"NOCOMPRESS\n" +
"LOGGING\n" +
"TABLESPACE \"ECC_TSP\"\n" +
"STORAGE (\n" +
"\tINITIAL 65536\n" +
"\tNEXT 1048576\n" +
"\tMINEXTENTS 1\n" +
"\tMAXEXTENTS 2147483645\n" +
"\tPCTINCREASE 0\n" +
"\tFREELISTS 1\n" +
"\tFREELIST GROUPS 1\n" +
"\tBUFFER_POOL DEFAULT\n" +
");", sortedSql);
}
}
@@ -0,0 +1,21 @@
package com.alibaba.druid.bvt.sql.oracle;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.util.JdbcConstants;
import junit.framework.TestCase;
public class SQLSortTest_1 extends TestCase {
public void test_sort() throws Exception {
String sql = "create view v1 as select * from v0; create view v0 as select * from t;";
String sortedSql = SQLUtils.sort(sql, JdbcConstants.ORACLE);
assertEquals("CREATE VIEW v0\n" +
"AS\n" +
"SELECT *\n" +
"FROM t;\n" +
"CREATE VIEW v1\n" +
"AS\n" +
"SELECT *\n" +
"FROM v0;", sortedSql);
}
}
@@ -0,0 +1,43 @@
package com.alibaba.druid.demo.sql;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
import com.alibaba.druid.util.JdbcConstants;
import junit.framework.TestCase;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MySqlVisitorDemo extends TestCase {
public void test_for_demo() throws Exception {
String sql = "select * from mytable a where a.id = 3";
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
ExportTableAliasVisitor visitor = new ExportTableAliasVisitor();
for (SQLStatement stmt : stmtList) {
stmt.accept(visitor);
}
SQLTableSource tableSource = visitor.getAliasMap().get("a");
System.out.println(tableSource);
}
public static class ExportTableAliasVisitor extends MySqlASTVisitorAdapter {
private Map<String, SQLTableSource> aliasMap = new HashMap<String, SQLTableSource>();
public boolean visit(SQLExprTableSource x) {
String alias = x.getAlias();
aliasMap.put(alias, x);
return true;
}
public Map<String, SQLTableSource> getAliasMap() {
return aliasMap;
}
}
}
@@ -1,7 +1,6 @@
package com.alibaba.druid.demo.sql;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
@@ -18,7 +17,7 @@ public class OracleVisitorDemo extends TestCase {
String sql = "select * from mytable a where a.id = 3";
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);
MyOracleVisitor visitor = new MyOracleVisitor();
ExportTableAliasVisitor visitor = new ExportTableAliasVisitor();
for (SQLStatement stmt : stmtList) {
stmt.accept(visitor);
}
@@ -27,7 +26,7 @@ public class OracleVisitorDemo extends TestCase {
System.out.println(tableSource);
}
public static class MyOracleVisitor extends OracleASTVisitorAdapter {
public static class ExportTableAliasVisitor extends OracleASTVisitorAdapter {
private Map<String, SQLTableSource> aliasMap = new HashMap<String, SQLTableSource>();
public boolean visit(OracleSelectTableReference x) {
String alias = x.getAlias();
@@ -0,0 +1,42 @@
package com.alibaba.druid.demo.sql;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter;
import com.alibaba.druid.util.JdbcConstants;
import junit.framework.TestCase;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PGVisitorDemo extends TestCase {
public void test_for_demo() throws Exception {
String sql = "select * from mytable a where a.id = 3";
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.POSTGRESQL);
ExportTableAliasVisitor visitor = new ExportTableAliasVisitor();
for (SQLStatement stmt : stmtList) {
stmt.accept(visitor);
}
SQLTableSource tableSource = visitor.getAliasMap().get("a");
System.out.println(tableSource);
}
public static class ExportTableAliasVisitor extends PGASTVisitorAdapter {
private Map<String, SQLTableSource> aliasMap = new HashMap<String, SQLTableSource>();
public boolean visit(SQLExprTableSource x) {
String alias = x.getAlias();
aliasMap.put(alias, x);
return true;
}
public Map<String, SQLTableSource> getAliasMap() {
return aliasMap;
}
}
}