mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved mysql parser, support more create view syntax.
This commit is contained in:
@@ -33,6 +33,10 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt
|
||||
protected SQLSelect subQuery;
|
||||
protected boolean ifNotExists = false;
|
||||
|
||||
protected String algorithm;
|
||||
protected SQLName definer;
|
||||
protected String sqlSecurity;
|
||||
|
||||
protected final List<Column> columns = new ArrayList<Column>();
|
||||
|
||||
private Level with;
|
||||
@@ -109,6 +113,33 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public void setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public SQLName getDefiner() {
|
||||
return definer;
|
||||
}
|
||||
|
||||
public void setDefiner(SQLName definer) {
|
||||
if (definer != null) {
|
||||
definer.setParent(this);
|
||||
}
|
||||
this.definer = definer;
|
||||
}
|
||||
|
||||
public String getSqlSecurity() {
|
||||
return sqlSecurity;
|
||||
}
|
||||
|
||||
public void setSqlSecurity(String sqlSecurity) {
|
||||
this.sqlSecurity = sqlSecurity;
|
||||
}
|
||||
|
||||
public void output(StringBuffer buf) {
|
||||
buf.append("CREATE VIEW ");
|
||||
this.name.output(buf);
|
||||
|
||||
@@ -37,55 +37,8 @@ import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterDatabaseStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddConstraint;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddIndex;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAnalyzePartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableCheckPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableCoalescePartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableConvertCharSet;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableConstraint;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableKeys;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDiscardPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropColumnItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropConstraint;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropForeignKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropIndex;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropPrimaryKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableConstraint;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableKeys;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableImportPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableOptimizePartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableReOrganizePartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableRebuildPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableRepairPartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableTruncatePartition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLBlockStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateProcedureStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLIfStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLLoopStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSetStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLShowTablesStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnique;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.clause.ConditionValue;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.clause.ConditionValue.ConditionType;
|
||||
@@ -179,7 +132,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTableStatusSta
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTriggersStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowVariantsStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLStartTransactionStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnlockTablesStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MysqlDeallocatePrepareStatement;
|
||||
@@ -376,7 +328,8 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
return parseCreateUser();
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.VIEW) {
|
||||
if (lexer.token() == Token.VIEW
|
||||
|| identifierEquals("ALGORITHM")) {
|
||||
if (replace) {
|
||||
lexer.reset(markBp, markChar, Token.CREATE);
|
||||
}
|
||||
@@ -398,7 +351,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
return parseCreateProcedure();
|
||||
}
|
||||
|
||||
throw new ParserException("TODO " + lexer.token());
|
||||
throw new ParserException("TODO " + lexer.info());
|
||||
}
|
||||
|
||||
public SQLStatement parseCreateIndex(boolean acceptCreate) {
|
||||
|
||||
@@ -1927,6 +1927,30 @@ public class SQLStatementParser extends SQLParser {
|
||||
createView.setOrReplace(true);
|
||||
}
|
||||
|
||||
if (identifierEquals("ALGORITHM")) {
|
||||
lexer.nextToken();
|
||||
accept(Token.EQ);
|
||||
String algorithm = lexer.stringVal();
|
||||
createView.setAlgorithm(algorithm);
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (identifierEquals("DEFINER")) {
|
||||
lexer.nextToken();
|
||||
accept(Token.EQ);
|
||||
SQLName definer = this.exprParser.name();
|
||||
createView.setDefiner(definer);
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (identifierEquals("SQL")) {
|
||||
lexer.nextToken();
|
||||
acceptIdentifier("SECURITY");
|
||||
String sqlSecurity = lexer.stringVal();
|
||||
createView.setSqlSecurity(sqlSecurity);
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
this.accept(Token.VIEW);
|
||||
|
||||
if (lexer.token() == Token.IF || identifierEquals("IF")) {
|
||||
|
||||
@@ -2053,6 +2053,31 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
if (x.isOrReplace()) {
|
||||
print0(ucase ? "OR REPLACE " : "or replace ");
|
||||
}
|
||||
|
||||
incrementIndent();
|
||||
String algorithm = x.getAlgorithm();
|
||||
if (algorithm != null && algorithm.length() > 0) {
|
||||
print0(ucase ? "ALGORITHM = " : "algorithm = ");
|
||||
print0(algorithm);
|
||||
println();
|
||||
}
|
||||
|
||||
SQLName definer = x.getDefiner();
|
||||
if (definer != null) {
|
||||
print0(ucase ? "DEFINER = " : "definer = ");
|
||||
definer.accept(this);
|
||||
println();
|
||||
}
|
||||
|
||||
String sqlSecurity = x.getSqlSecurity();
|
||||
if (sqlSecurity != null && sqlSecurity.length() > 0) {
|
||||
print0(ucase ? "SQL SECURITY = " : "sql security = ");
|
||||
print0(sqlSecurity);
|
||||
println();
|
||||
}
|
||||
|
||||
decrementIndent();
|
||||
|
||||
print0(ucase ? "VIEW " : "view ");
|
||||
|
||||
if (x.isIfNotExists()) {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.mysql.create;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
import com.alibaba.druid.stat.TableStat;
|
||||
import com.alibaba.druid.stat.TableStat.Column;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MySqlCreateViewTest1 extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "CREATE ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW view_audit_enroll AS " +
|
||||
"SELECT a.enroll_id AS 'enrollId', case when ((SELECT audit FROM actvty_audit WHERE enroll_id = a.enroll_id AND rankjurisdiction = 1) > 0) then \"县站已审核\" else NULL end AS 'countyAudit', case when ((SELECT audit FROM actvty_audit WHERE enroll_id = a.enroll_id AND rankjurisdiction = 2) > 0) then \"市馆已审核\" else NULL end AS 'cityAudit', case when ((SELECT audit FROM actvty_audit WHERE enroll_id = a.enroll_id AND rankjurisdiction = 3) > 0) then \"省馆已审核\" else NULL end AS 'provinceAudit' FROM actvty_audit a GROUP BY a.enroll_id";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);
|
||||
// print(statementList);
|
||||
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
|
||||
stmt.accept(visitor);
|
||||
|
||||
Assert.assertEquals("CREATE ALGORITHM = UNDEFINED\n" +
|
||||
"\tDEFINER = root\n" +
|
||||
"\tSQL SECURITY = DEFINER\n" +
|
||||
"\tVIEW view_audit_enroll\n" +
|
||||
"AS\n" +
|
||||
"SELECT a.enroll_id AS 'enrollId', CASE WHEN (\n" +
|
||||
"\t\tSELECT audit\n" +
|
||||
"\t\tFROM actvty_audit\n" +
|
||||
"\t\tWHERE enroll_id = a.enroll_id\n" +
|
||||
"\t\t\tAND rankjurisdiction = 1\n" +
|
||||
"\t\t) > 0 THEN '县站已审核' ELSE NULL END AS 'countyAudit', CASE WHEN (\n" +
|
||||
"\t\tSELECT audit\n" +
|
||||
"\t\tFROM actvty_audit\n" +
|
||||
"\t\tWHERE enroll_id = a.enroll_id\n" +
|
||||
"\t\t\tAND rankjurisdiction = 2\n" +
|
||||
"\t\t) > 0 THEN '市馆已审核' ELSE NULL END AS 'cityAudit', CASE WHEN (\n" +
|
||||
"\t\tSELECT audit\n" +
|
||||
"\t\tFROM actvty_audit\n" +
|
||||
"\t\tWHERE enroll_id = a.enroll_id\n" +
|
||||
"\t\t\tAND rankjurisdiction = 3\n" +
|
||||
"\t\t) > 0 THEN '省馆已审核' ELSE NULL END AS 'provinceAudit'\n" +
|
||||
"FROM actvty_audit a\n" +
|
||||
"GROUP BY a.enroll_id", //
|
||||
SQLUtils.toMySqlString(stmt));
|
||||
|
||||
Assert.assertEquals("create algorithm = UNDEFINED\n" +
|
||||
"\tdefiner = root\n" +
|
||||
"\tsql security = DEFINER\n" +
|
||||
"\tview view_audit_enroll\n" +
|
||||
"as\n" +
|
||||
"select a.enroll_id as 'enrollId', case when (\n" +
|
||||
"\t\tselect audit\n" +
|
||||
"\t\tfrom actvty_audit\n" +
|
||||
"\t\twhere enroll_id = a.enroll_id\n" +
|
||||
"\t\t\tand rankjurisdiction = 1\n" +
|
||||
"\t\t) > 0 then '县站已审核' else null end as 'countyAudit', case when (\n" +
|
||||
"\t\tselect audit\n" +
|
||||
"\t\tfrom actvty_audit\n" +
|
||||
"\t\twhere enroll_id = a.enroll_id\n" +
|
||||
"\t\t\tand rankjurisdiction = 2\n" +
|
||||
"\t\t) > 0 then '市馆已审核' else null end as 'cityAudit', case when (\n" +
|
||||
"\t\tselect audit\n" +
|
||||
"\t\tfrom actvty_audit\n" +
|
||||
"\t\twhere enroll_id = a.enroll_id\n" +
|
||||
"\t\t\tand rankjurisdiction = 3\n" +
|
||||
"\t\t) > 0 then '省馆已审核' else null end as 'provinceAudit'\n" +
|
||||
"from actvty_audit a\n" +
|
||||
"group by a.enroll_id", //
|
||||
SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
|
||||
|
||||
// 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(3, visitor.getColumns().size());
|
||||
Assert.assertEquals(2, visitor.getConditions().size());
|
||||
|
||||
Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("actvty_audit")));
|
||||
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("actvty_audit", "audit")));
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("actvty_audit", "enroll_id")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user