improved sql parser. for issue #1919

This commit is contained in:
wenshao
2017-08-19 21:20:32 +08:00
parent b4479d515c
commit 75526cb351
16 changed files with 369 additions and 3 deletions
@@ -112,6 +112,9 @@ public class FilterManager {
try {
filter = (Filter) filterClass.newInstance();
} catch (ClassCastException e) {
LOG.error("load filter error.", e);
continue;
} catch (InstantiationException e) {
throw new SQLException("load managed jdbc driver event listener error. " + filterName, e);
} catch (IllegalAccessException e) {
@@ -78,6 +78,12 @@ public class MySqlExprParser extends SQLExprParser {
this.lexer.nextToken();
}
public MySqlExprParser(String sql, boolean skipComment,boolean keepComments){
this(new MySqlLexer(sql, skipComment, keepComments));
this.lexer.nextToken();
}
public SQLExpr relationalRest(SQLExpr expr) {
if (identifierEquals("REGEXP")) {
lexer.nextToken();
@@ -98,6 +98,10 @@ public class MySqlStatementParser extends SQLStatementParser {
super(new MySqlExprParser(sql, keepComments));
}
public MySqlStatementParser(String sql, boolean skipComment, boolean keepComments) {
super(new MySqlExprParser(sql, skipComment, keepComments));
}
public MySqlStatementParser(Lexer lexer) {
super(new MySqlExprParser(lexer));
}
@@ -1003,4 +1003,14 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or
public void endVisit(OracleTreatExpr x) {
}
@Override
public boolean visit(OracleCreateSynonymStatement x) {
return false;
}
@Override
public void endVisit(OracleCreateSynonymStatement x) {
}
}
@@ -0,0 +1,57 @@
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
public class OracleCreateSynonymStatement extends OracleStatementImpl {
private boolean orReplace;
private SQLName name;
private boolean isPublic;
private SQLName object;
@Override
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, name);
acceptChild(visitor, object);
}
}
public boolean isPublic() {
return isPublic;
}
public void setPublic(boolean value) {
isPublic = value;
}
public SQLName getName() {
return name;
}
public void setName(SQLName name) {
if (name != null) {
name.setParent(this);
}
this.name = name;
}
public SQLName getObject() {
return object;
}
public void setObject(SQLName object) {
if (object != null) {
object.setParent(this);
}
this.object = object;
}
public boolean isOrReplace() {
return orReplace;
}
public void setOrReplace(boolean orReplace) {
this.orReplace = orReplace;
}
}
@@ -968,8 +968,19 @@ public class OracleExprParser extends SQLExprParser {
}
OracleDbLinkExpr dbLink = new OracleDbLinkExpr();
dbLink.setExpr(name);
dbLink.setDbLink(lexer.stringVal());
String link = lexer.stringVal();
lexer.nextToken();
while (lexer.token() == Token.DOT) {
lexer.nextToken();
String stringVal = lexer.stringVal();
accept(Token.IDENTIFIER);
link += "." + stringVal;
}
dbLink.setDbLink(link);
return dbLink;
}
@@ -2293,4 +2293,29 @@ public class OracleStatementParser extends SQLStatementParser {
accept(Token.SEMI);
return stmt;
}
public SQLStatement parseCreateSynonym() {
OracleCreateSynonymStatement stmt = new OracleCreateSynonymStatement();
accept(Token.CREATE);
if (lexer.token() == Token.OR) {
lexer.nextToken();
accept(Token.REPLACE);
stmt.setOrReplace(true);
}
if (identifierEquals("PUBLIC")) {
lexer.nextToken();
stmt.setPublic(true);
}
acceptIdentifier("SYNONYM");
stmt.setName(this.exprParser.name());
accept(Token.FOR);
stmt.setObject(this.exprParser.name());
return stmt;
}
}
@@ -427,4 +427,8 @@ public interface OracleASTVisitor extends SQLASTVisitor {
boolean visit(OracleTreatExpr x);
void endVisit(OracleTreatExpr x);
boolean visit(OracleCreateSynonymStatement x);
void endVisit(OracleCreateSynonymStatement x);
}
@@ -1052,4 +1052,14 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora
public void endVisit(OracleTreatExpr x) {
}
@Override
public boolean visit(OracleCreateSynonymStatement x) {
return true;
}
@Override
public void endVisit(OracleCreateSynonymStatement x) {
}
}
@@ -3268,4 +3268,32 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public void endVisit(OracleTreatExpr x) {
}
@Override
public boolean visit(OracleCreateSynonymStatement x) {
if (x.isOrReplace()) {
print0(ucase ? "CREATE OR REPLACE " : "create or replace ");
} else {
print0(ucase ? "CREATE " : "create ");
}
if (x.isPublic()) {
print0(ucase ? "PUBLIC " : "public ");
}
print0(ucase ? "SYNONYM " : "synonym ");
x.getName().accept(this);
print0(ucase ? " FOR " : " for ");
x.getObject().accept(this);
return false;
}
@Override
public void endVisit(OracleCreateSynonymStatement x) {
}
}
@@ -1445,4 +1445,14 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
public void endVisit(OracleTreatExpr x) {
}
@Override
public boolean visit(OracleCreateSynonymStatement x) {
return false;
}
@Override
public void endVisit(OracleCreateSynonymStatement x) {
}
}
@@ -1853,9 +1853,21 @@ public class SQLStatementParser extends SQLParser {
lexer.reset(markBp, markChar, Token.CREATE);
return parseCreateDatabase();
} else if (identifierEquals("PUBLIC") || identifierEquals("SHARE")) {
} else if (identifierEquals("PUBLIC")) {
lexer.nextToken();
if (identifierEquals("SYNONYM")) {
lexer.reset(markBp, markChar, Token.CREATE);
return parseCreateSynonym();
} else {
lexer.reset(markBp, markChar, Token.CREATE);
return parseCreateDbLink();
}
} else if (identifierEquals("SHARE")) {
lexer.reset(markBp, markChar, Token.CREATE);
return parseCreateDbLink();
} else if (identifierEquals("SYNONYM")) {
lexer.reset(markBp, markChar, Token.CREATE);
return parseCreateSynonym();
} else if (token == Token.VIEW) {
return parseCreateView();
} else if (token == Token.TRIGGER) {
@@ -1963,6 +1975,10 @@ public class SQLStatementParser extends SQLParser {
throw new ParserException("TODO " + lexer.token());
}
public SQLStatement parseCreateSynonym() {
throw new ParserException("TODO " + lexer.token());
}
public SQLStatement parseCreateTrigger() {
accept(Token.CREATE);
@@ -47,7 +47,7 @@ public interface JdbcConstants {
public static final String MYSQL = "mysql";
public static final String MYSQL_DRIVER = "com.mysql.jdbc.Driver";
public static final String MYSQL_DRIVER_6 = "com.mysql.cj.jdbc.Driver";
public static final String MYSQL_DRIVER_REPLICATE = "com.mysql.jdbc.ReplicationDriver";
public static final String MYSQL_DRIVER_REPLICATE = "com.mysql.jdbc.";
public static final String MARIADB = "mariadb";
public static final String MARIADB_DRIVER = "org.mariadb.jdbc.Driver";
@@ -0,0 +1,61 @@
/*
* 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.create;
import com.alibaba.druid.sql.OracleTest;
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 OracleCreateSynonymTest extends OracleTest {
public void test_0() throws Exception {
String sql = //
"CREATE SYNONYM offices \n" +
" FOR hr.locations;";
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());
Assert.assertEquals(0, visitor.getTables().size());
// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("cdc.en_complaint_ipr_stat_fdt0")));
Assert.assertEquals(0, visitor.getColumns().size());
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*")));
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR")));
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode")));
assertEquals("CREATE SYNONYM offices FOR hr.locations;", stmt.toString());
}
}
@@ -0,0 +1,60 @@
/*
* 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.create;
import com.alibaba.druid.sql.OracleTest;
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 OracleCreateSynonymTest1 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"CREATE PUBLIC SYNONYM customers FOR oe.customers;";
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());
Assert.assertEquals(0, visitor.getTables().size());
// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("cdc.en_complaint_ipr_stat_fdt0")));
Assert.assertEquals(0, visitor.getColumns().size());
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*")));
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR")));
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode")));
assertEquals("CREATE PUBLIC SYNONYM customers FOR oe.customers;", stmt.toString());
}
}
@@ -0,0 +1,61 @@
/*
* 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.create;
import com.alibaba.druid.sql.OracleTest;
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 OracleCreateSynonymTest2 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"CREATE PUBLIC SYNONYM emp_table \n" +
" FOR hr.employees@remote.us.oracle.com;";
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());
Assert.assertEquals(0, visitor.getTables().size());
// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("cdc.en_complaint_ipr_stat_fdt0")));
Assert.assertEquals(0, visitor.getColumns().size());
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*")));
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR")));
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode")));
assertEquals("CREATE PUBLIC SYNONYM emp_table FOR hr.employees@remote.us.oracle.com;", stmt.toString());
}
}