improved sql parser, support petadata.

This commit is contained in:
wenshao
2017-11-15 13:04:26 +08:00
parent c73191ad41
commit d8ba3a30d0
18 changed files with 692 additions and 17 deletions
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
@@ -30,14 +31,15 @@ import com.alibaba.druid.util.JdbcConstants;
public class MySqlDeleteStatement extends SQLDeleteStatement {
private boolean lowPriority = false;
private boolean quick = false;
private boolean ignore = false;
private boolean lowPriority = false;
private boolean quick = false;
private boolean ignore = false;
private SQLOrderBy orderBy;
private SQLLimit limit;
private SQLLimit limit;
private List<SQLCommentHint> hints;
// for petadata
private boolean forceAllPartitions = false;
private SQLName forcePartition;
public MySqlDeleteStatement(){
super(JdbcConstants.MYSQL);
@@ -137,14 +139,33 @@ public class MySqlDeleteStatement extends SQLDeleteStatement {
protected void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, getTableSource());
acceptChild(visitor, getWhere());
acceptChild(visitor, getFrom());
acceptChild(visitor, getUsing());
acceptChild(visitor, tableSource);
acceptChild(visitor, where);
acceptChild(visitor, from);
acceptChild(visitor, using);
acceptChild(visitor, orderBy);
acceptChild(visitor, limit);
}
visitor.endVisit(this);
}
public boolean isForceAllPartitions() {
return forceAllPartitions;
}
public void setForceAllPartitions(boolean forceAllPartitions) {
this.forceAllPartitions = forceAllPartitions;
}
public SQLName getForcePartition() {
return forcePartition;
}
public void setForcePartition(SQLName x) {
if (x != null) {
x.setParent(this);
}
this.forcePartition = x;
}
}
@@ -40,6 +40,7 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO
private List<SQLExpr> procedureArgumentList;
private boolean lockInShareMode;
private List<SQLCommentHint> hints;
private SQLName forcePartition; // for petadata
public MySqlSelectQueryBlock(){
dbType = JdbcConstants.MYSQL;
@@ -241,6 +242,7 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.selectList);
acceptChild(visitor, this.forcePartition);
acceptChild(visitor, this.from);
acceptChild(visitor, this.where);
acceptChild(visitor, this.groupBy);
@@ -254,6 +256,17 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO
visitor.endVisit(this);
}
public SQLName getForcePartition() {
return forcePartition;
}
public void setForcePartition(SQLName x) {
if (x != null) {
x.setParent(this);
}
this.forcePartition = x;
}
public String toString() {
return SQLUtils.toMySqlString(this);
}
@@ -0,0 +1,40 @@
/*
* 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.sql.dialect.mysql.ast.statement;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlShowDatabasePartitionStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {
private SQLName database;
public SQLName getDatabase() {
return database;
}
public void setDatabase(SQLName database) {
this.database = database;
}
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, database);
}
visitor.endVisit(this);
}
}
@@ -16,6 +16,7 @@
package com.alibaba.druid.sql.dialect.mysql.ast.statement;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.ast.SQLLimit;
@@ -26,13 +27,17 @@ import com.alibaba.druid.util.JdbcConstants;
public class MySqlUpdateStatement extends SQLUpdateStatement implements MySqlStatement {
private SQLLimit limit;
private boolean lowPriority = false;
private boolean ignore = false;
private boolean commitOnSuccess = false;
private boolean rollBackOnFail = false;
private boolean queryOnPk = false;
private boolean lowPriority = false;
private boolean ignore = false;
private boolean commitOnSuccess = false;
private boolean rollBackOnFail = false;
private boolean queryOnPk = false;
private SQLExpr targetAffectRow;
// for petadata
private boolean forceAllPartitions = false;
private SQLName forcePartition;
public MySqlUpdateStatement(){
super(JdbcConstants.MYSQL);
}
@@ -119,5 +124,22 @@ public class MySqlUpdateStatement extends SQLUpdateStatement implements MySqlSta
this.targetAffectRow = targetAffectRow;
}
public boolean isForceAllPartitions() {
return forceAllPartitions;
}
public void setForceAllPartitions(boolean forceAllPartitions) {
this.forceAllPartitions = forceAllPartitions;
}
public SQLName getForcePartition() {
return forcePartition;
}
public void setForcePartition(SQLName x) {
if (x != null) {
x.setParent(this);
}
this.forcePartition = x;
}
}
@@ -160,6 +160,13 @@ public class MySqlSelectParser extends SQLSelectParser {
}
parseSelectList(queryBlock);
if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {
lexer.nextToken();
accept(Token.PARTITION);
SQLName partition = this.exprParser.name();
queryBlock.setForcePartition(partition);
}
parseInto(queryBlock);
}
@@ -297,6 +304,25 @@ public class MySqlSelectParser extends SQLSelectParser {
update.setTargetAffectRow(targetAffectRow);
}
if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {
lexer.nextToken();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
acceptIdentifier("PARTITIONS");
update.setForceAllPartitions(true);
} else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)){
lexer.nextToken();
update.setForceAllPartitions(true);
} else if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
SQLName partition = this.exprParser.name();
update.setForcePartition(partition);
} else {
throw new ParserException("TODO. " + lexer.info());
}
}
SQLSelectParser selectParser = this.exprParser.createSelectParser();
SQLTableSource updateTableSource = selectParser.parseTableSource();
update.setTableSource(updateTableSource);
@@ -157,6 +157,26 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
}
if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {
Lexer.SavePoint savePoint = lexer.mark();
lexer.nextToken();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
acceptIdentifier("PARTITIONS");
deleteStatement.setForceAllPartitions(true);
} else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)){
lexer.nextToken();
deleteStatement.setForceAllPartitions(true);
} else if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
SQLName partition = this.exprParser.name();
deleteStatement.setForcePartition(partition);
} else {
lexer.reset(savePoint);
}
}
if (lexer.token() == Token.IDENTIFIER) {
deleteStatement.setTableSource(createSQLSelectParser().parseTableSource());
@@ -1740,6 +1760,16 @@ public class MySqlStatementParser extends SQLStatementParser {
return stmt;
}
if (lexer.token() == Token.DATABASE) {
lexer.nextToken();
accept(Token.PARTITION);
acceptIdentifier("STATUS");
accept(Token.FOR);
MySqlShowDatabasePartitionStatusStatement stmt = new MySqlShowDatabasePartitionStatusStatement();
stmt.setDatabase(this.exprParser.name());
return stmt;
}
if (lexer.identifierEquals("TRIGGERS")) {
lexer.nextToken();
MySqlShowTriggersStatement stmt = new MySqlShowTriggersStatement();
@@ -491,4 +491,7 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
boolean visit(MySqlAlterTablespaceStatement x);
void endVisit(MySqlAlterTablespaceStatement x);
boolean visit(MySqlShowDatabasePartitionStatusStatement x);
void endVisit(MySqlShowDatabasePartitionStatusStatement x);
} //
@@ -1218,4 +1218,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq
}
@Override
public boolean visit(MySqlShowDatabasePartitionStatusStatement x) {
return true;
}
@Override
public void endVisit(MySqlShowDatabasePartitionStatusStatement x) {
}
} //
@@ -173,6 +173,13 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
printSelectList(x.getSelectList());
SQLName forcePartition = x.getForcePartition();
if (forcePartition != null) {
println();
print0(ucase ? "FORCE PARTITION " : "force partition ");
printExpr(forcePartition);
}
SQLExprTableSource into = x.getInto();
if (into != null) {
println();
@@ -782,6 +789,17 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
print0(ucase ? "IGNORE " : "ignore ");
}
if (x.isForceAllPartitions()) {
print0(ucase ? "FORCE ALL PARTITIONS " : "force all partitions ");
} else {
SQLName partition = x.getForcePartition();
if (partition != null) {
print0(ucase ? "FORCE PARTITION " : "force partition ");
printExpr(partition);
print(' ');
}
}
SQLTableSource from = x.getFrom();
if (from == null) {
print0(ucase ? "FROM " : "from ");
@@ -1593,6 +1611,17 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
print(' ');
}
if (x.isForceAllPartitions()) {
print0(ucase ? "FORCE ALL PARTITIONS " : "force all partitions ");
} else {
SQLName partition = x.getForcePartition();
if (partition != null) {
print0(ucase ? "FORCE PARTITION " : "force partition ");
printExpr(partition);
print(' ');
}
}
printTableSource(x.getTableSource());
println();
@@ -4037,6 +4066,18 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
@Override
public boolean visit(MySqlShowDatabasePartitionStatusStatement x) {
print0(ucase ? "SHOW DATABASE PARTITION STATUS FOR " : "show database partition status for ");
x.getDatabase().accept(this);
return false;
}
@Override
public void endVisit(MySqlShowDatabasePartitionStatusStatement x) {
}
protected void printQuery(SQLSelectQuery x) {
Class<?> clazz = x.getClass();
if (clazz == MySqlSelectQueryBlock.class) {
@@ -1344,4 +1344,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
public void endVisit(MySqlAlterTablespaceStatement x) {
}
@Override
public boolean visit(MySqlShowDatabasePartitionStatusStatement x) {
return false;
}
@Override
public void endVisit(MySqlShowDatabasePartitionStatusStatement x) {
}
}
@@ -2992,8 +2992,24 @@ public class SQLExprParser extends SQLParser {
if ((token == Token.IDENTIFIER && hash_lower != FnvHash.Constants.CURRENT)
|| token == Token.MODEL) {
String as = lexer.stringVal();
lexer.nextTokenComma();
String as;
if (lexer.hash_lower == FnvHash.Constants.FORCE && JdbcConstants.MYSQL.equals(dbType)) {
String force = lexer.stringVal();
Lexer.SavePoint savePoint = lexer.mark();
lexer.nextToken();
if (lexer.token == Token.PARTITION) {
lexer.reset(savePoint);
as = null;
} else {
as = force;
lexer.nextTokenComma();
}
} else {
as = lexer.stringVal();
lexer.nextTokenComma();
}
return new SQLSelectItem(expr, as, connectByRoot);
}
@@ -614,5 +614,6 @@ public final class FnvHash {
long CLUSTERED = fnv1a_64_lower("CLUSTERED");
long SORTED = fnv1a_64_lower("SORTED");
long LIFECYCLE = fnv1a_64_lower("LIFECYCLE");
long PARTITIONS = fnv1a_64_lower("PARTITIONS");
}
}