support select ... from update .. for alibaba mysql

This commit is contained in:
Yako
2015-09-24 17:18:22 +08:00
parent 370604fd82
commit 5504c7125e
8 changed files with 276 additions and 1 deletions
@@ -0,0 +1,55 @@
/*
* 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.sql.dialect.mysql.ast.statement;
import com.alibaba.druid.sql.ast.statement.SQLTableSourceImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
// just for alibaba mysql
public class MySqlUpdateTableSource extends SQLTableSourceImpl {
private MySqlUpdateStatement update;
public MySqlUpdateTableSource(MySqlUpdateStatement update){
this.update = update;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor instanceof MySqlASTVisitor) {
accept0((MySqlASTVisitor) visitor);
} else {
throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName());
}
}
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, update);
}
visitor.endVisit(this);
}
public MySqlUpdateStatement getUpdate() {
return update;
}
public void setUpdate(MySqlUpdateStatement update) {
this.update = update;
}
}
@@ -19,11 +19,16 @@ import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.ast.statement.SQLUnionQueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlForceIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIgnoreIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIndexHint;
@@ -32,8 +37,10 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateTableSource;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
@@ -166,6 +173,94 @@ public class MySqlSelectParser extends SQLSelectParser {
return queryRest(queryBlock);
}
public SQLTableSource parseTableSource() {
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
SQLTableSource tableSource;
if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) {
SQLSelect select = select();
accept(Token.RPAREN);
SQLSelectQuery query = queryRest(select.getQuery());
if (query instanceof SQLUnionQuery) {
tableSource = new SQLUnionQueryTableSource((SQLUnionQuery) query);
} else {
tableSource = new SQLSubqueryTableSource(select);
}
} else if (lexer.token() == Token.LPAREN) {
tableSource = parseTableSource();
accept(Token.RPAREN);
} else {
tableSource = parseTableSource();
accept(Token.RPAREN);
}
return parseTableSourceRest(tableSource);
}
if(lexer.token() == Token.UPDATE) {
SQLTableSource tableSource = new MySqlUpdateTableSource(parseUpdateStatment());
return parseTableSourceRest(tableSource);
}
if (lexer.token() == Token.SELECT) {
throw new ParserException("TODO");
}
SQLExprTableSource tableReference = new SQLExprTableSource();
parseTableSourceQueryTableExpr(tableReference);
SQLTableSource tableSrc = parseTableSourceRest(tableReference);
if (lexer.hasComment() && lexer.isKeepComments()) {
tableSrc.addAfterComment(lexer.readAndResetComments());
}
return tableSrc;
}
private MySqlUpdateStatement parseUpdateStatment() {
MySqlUpdateStatement update = new MySqlUpdateStatement();
lexer.nextToken();
if (identifierEquals("LOW_PRIORITY")) {
lexer.nextToken();
update.setLowPriority(true);
}
if (identifierEquals("IGNORE")) {
lexer.nextToken();
update.setIgnore(true);
}
SQLTableSource updateTableSource = this.exprParser.createSelectParser().parseTableSource();
update.setTableSource(updateTableSource);
accept(Token.SET);
for (;;) {
SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();
update.addItem(item);
if (lexer.token() != Token.COMMA) {
break;
}
lexer.nextToken();
}
if (lexer.token() == (Token.WHERE)) {
lexer.nextToken();
update.setWhere(this.exprParser.expr());
}
update.setOrderBy(this.exprParser.parseOrderBy());
update.setLimit(parseLimit());
return update;
}
protected void parseInto(SQLSelectQueryBlock queryBlock) {
if (lexer.token() == (Token.INTO)) {
lexer.nextToken();
@@ -136,6 +136,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
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.MySqlUpdateTableSource;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public interface MySqlASTVisitor extends SQLASTVisitor {
@@ -650,5 +651,9 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
boolean visit(MySqlCursorDeclareStatement x);
void endVisit(MySqlCursorDeclareStatement x);
boolean visit(MySqlUpdateTableSource x);
void endVisit(MySqlUpdateTableSource x);
} //
@@ -141,6 +141,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
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.MySqlUpdateTableSource;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySqlASTVisitor {
@@ -1466,5 +1467,15 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlUpdateTableSource x) {
return true;
}
@Override
public void endVisit(MySqlUpdateTableSource x) {
}
} //
@@ -168,6 +168,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
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.MySqlUpdateTableSource;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTVisitor {
@@ -3585,4 +3586,17 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
@Override
public boolean visit(MySqlUpdateTableSource x) {
MySqlUpdateStatement update = x.getUpdate();
if (update != null) {
update.accept0(this);
}
return false;
}
@Override
public void endVisit(MySqlUpdateTableSource x) {
}
} //
@@ -156,6 +156,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
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.MySqlUpdateTableSource;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.stat.TableStat.Mode;
@@ -1570,5 +1571,18 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlUpdateTableSource x) {
if (x.getUpdate() != null) {
return this.visit(x.getUpdate());
}
return false;
}
@Override
public void endVisit(MySqlUpdateTableSource x) {
}
}
@@ -355,7 +355,7 @@ public class SQLSelectParser extends SQLParser {
return tableSrc;
}
private void parseTableSourceQueryTableExpr(SQLExprTableSource tableReference) {
protected void parseTableSourceQueryTableExpr(SQLExprTableSource tableReference) {
if (lexer.token() == Token.LITERAL_ALIAS || lexer.token() == Token.IDENTIFIED
|| lexer.token() == Token.LITERAL_CHARS) {
tableReference.setExpr(this.exprParser.name());