enhance sql parser

This commit is contained in:
温少
2012-02-25 12:04:12 +08:00
parent dba8dd063a
commit 7d34b6efc5
18 changed files with 404 additions and 66 deletions
@@ -0,0 +1,42 @@
package com.alibaba.druid.sql.dialect.oracle.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
public class OracleReturningClause extends OracleSQLObjectImpl {
private static final long serialVersionUID = 1L;
private List<SQLExpr> items = new ArrayList<SQLExpr>();
private List<SQLExpr> values = new ArrayList<SQLExpr>();
public List<SQLExpr> getItems() {
return items;
}
public void setItems(List<SQLExpr> items) {
this.items = items;
}
public List<SQLExpr> getValues() {
return values;
}
public void setValues(List<SQLExpr> values) {
this.values = values;
}
@Override
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, items);
acceptChild(visitor, values);
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,49 @@
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleInsertStatement extends SQLInsertStatement implements OracleStatement {
private static final long serialVersionUID = 1L;
private OracleReturningClause returning;
private OracleErrorLoggingClause errorLogging;
public OracleReturningClause getReturning() {
return returning;
}
public void setReturning(OracleReturningClause returning) {
this.returning = returning;
}
public OracleErrorLoggingClause getErrorLogging() {
return errorLogging;
}
public void setErrorLogging(OracleErrorLoggingClause errorLogging) {
this.errorLogging = errorLogging;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
}
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
this.acceptChild(visitor, tableName);
this.acceptChild(visitor, columns);
this.acceptChild(visitor, values);
this.acceptChild(visitor, query);
this.acceptChild(visitor, returning);
this.acceptChild(visitor, errorLogging);
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,15 @@
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
public class OracleMultiInsertStatement extends OracleStatementImpl {
private static final long serialVersionUID = 1L;
@Override
public void accept0(OracleASTVisitor visitor) {
}
}
@@ -1,7 +1,8 @@
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;
public interface OracleStatement extends OracleSQLObject {
public interface OracleStatement extends SQLStatement, OracleSQLObject {
}
@@ -97,11 +97,11 @@ public class OracleExprParser extends SQLExprParser {
return new SQLVariantRefExpr(name);
} else if (lexer.token() == Token.IDENTIFIER) {
String name = lexer.stringVal();
if (name.startsWith("B")) {
if (name.charAt(0) == 'B' || name.charAt(0) == 'b') {
lexer.nextToken();
return new SQLVariantRefExpr(":" + name);
}
throw new ParserException("syntax error : " + lexer.token());
throw new ParserException("syntax error : " + lexer.token() + " " + lexer.stringVal());
} else {
throw new ParserException("syntax error : " + lexer.token());
}
@@ -1,36 +0,0 @@
/*
* Copyright 1999-2011 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.oracle.parser;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
public class OracleInsertParser extends SQLStatementParser {
public OracleInsertParser(String sql) throws ParserException{
super(sql);
}
public OracleInsertParser(Lexer lexer){
super(lexer);
}
protected SQLExprParser createExprParser() {
return new OracleExprParser(lexer);
}
}
@@ -111,6 +111,8 @@ public class OracleLexer extends Lexer {
map.put("ERRORS", Token.ERRORS);
map.put("REJECT", Token.REJECT);
map.put("UNLIMITED", Token.UNLIMITED);
map.put("RETURNING", Token.RETURNING);
map.put("LIMIT", Token.LIMIT);
DEFAULT_ORACLE_KEYWORDS = new Keywords(map);
}
@@ -17,13 +17,17 @@ package com.alibaba.druid.sql.dialect.oracle.parser;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLStatementParser;
@@ -85,7 +89,7 @@ public class OracleStatementParser extends SQLStatementParser {
}
if (lexer.token() == Token.INSERT) {
statementList.add(new OracleInsertParser(this.lexer).parseInsert());
statementList.add(parseInsert());
continue;
}
@@ -137,13 +141,13 @@ public class OracleStatementParser extends SQLStatementParser {
stmt.setAlias(as());
accept(Token.USING);
SQLTableSource using = this.createSQLSelectParser().parseTableSource();
stmt.setUsing(using);
accept(Token.ON);
stmt.setOn(exprParser.expr());
boolean insertFlag = false;
if (lexer.token() == Token.WHEN) {
lexer.nextToken();
@@ -153,7 +157,7 @@ public class OracleStatementParser extends SQLStatementParser {
accept(Token.THEN);
accept(Token.UPDATE);
accept(Token.SET);
for (;;) {
SQLUpdateSetItem item = new SQLUpdateSetItem();
item.setColumn(this.exprParser.name());
@@ -169,39 +173,39 @@ public class OracleStatementParser extends SQLStatementParser {
break;
}
if (lexer.token() == Token.WHERE) {
lexer.nextToken();
updateClause.setWhere(exprParser.expr());
}
if (lexer.token() == Token.DELETE) {
lexer.nextToken();
accept(Token.WHERE);
updateClause.setWhere(exprParser.expr());
}
stmt.setUpdateClause(updateClause);
} else if (lexer.token() == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (!insertFlag) {
if (lexer.token() == Token.WHEN) {
lexer.nextToken();
}
if (lexer.token() == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (insertFlag) {
OracleMergeStatement.MergeInsertClause insertClause = new OracleMergeStatement.MergeInsertClause();
accept(Token.MATCHED);
accept(Token.THEN);
accept(Token.INSERT);
@@ -212,40 +216,90 @@ public class OracleStatementParser extends SQLStatementParser {
accept(Token.LPAREN);
exprParser.exprList(insertClause.getValues());
accept(Token.RPAREN);
if (lexer.token() == Token.WHERE) {
lexer.nextToken();
insertClause.setWhere(exprParser.expr());
}
stmt.setInsertClause(insertClause);
}
OracleErrorLoggingClause errorClause = parseErrorLoggingClause();
stmt.setErrorLoggingClause(errorClause);
return stmt;
}
public OracleStatement parseInsert() {
accept(Token.INSERT);
accept(Token.INTO);
OracleInsertStatement stmt = new OracleInsertStatement();
parseInsert0(stmt);
stmt.setReturning(parseReturningClause());
stmt.setErrorLogging(parseErrorLoggingClause());
return stmt;
}
private OracleErrorLoggingClause parseErrorLoggingClause() {
if (lexer.token() == Token.LOG) {
OracleErrorLoggingClause errorClause = new OracleErrorLoggingClause();
lexer.nextToken();
accept(Token.ERRORS);
if (lexer.token() == Token.INTO) {
lexer.nextToken();
errorClause.setInto(exprParser.name());
}
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
errorClause.setSimpleExpression(exprParser.expr());
accept(Token.RPAREN);
}
if (lexer.token() == Token.REJECT) {
lexer.nextToken();
accept(Token.LIMIT);
errorClause.setLimit(exprParser.expr());
}
stmt.setErrorLoggingClause(errorClause);
}
return stmt;
return errorClause;
}
return null;
}
private OracleReturningClause parseReturningClause() {
OracleReturningClause clause = null;
if (lexer.token() == Token.RETURNING) {
lexer.nextToken();
clause = new OracleReturningClause();
for (;;) {
SQLExpr item = exprParser.expr();
clause.getItems().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.INTO);
for (;;) {
SQLExpr item = exprParser.expr();
clause.getValues().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
}
return clause;
}
}
@@ -17,6 +17,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelRulesCla
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitionClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SearchClause;
@@ -37,6 +38,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause;
@@ -691,5 +693,25 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora
public void endVisit(OracleErrorLoggingClause x) {
}
@Override
public boolean visit(OracleReturningClause x) {
return true;
}
@Override
public void endVisit(OracleReturningClause x) {
}
@Override
public boolean visit(OracleInsertStatement x) {
return true;
}
@Override
public void endVisit(OracleInsertStatement x) {
}
}
@@ -24,6 +24,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.Vers
import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SearchClause;
@@ -43,6 +44,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleOrderByItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement;
@@ -300,4 +302,12 @@ public interface OracleASTVisitor extends SQLASTVisitor {
boolean visit(OracleErrorLoggingClause x);
void endVisit(OracleErrorLoggingClause x);
boolean visit(OracleReturningClause x);
void endVisit(OracleReturningClause x);
boolean visit(OracleInsertStatement x);
void endVisit(OracleInsertStatement x);
}
@@ -27,6 +27,7 @@ import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
@@ -49,6 +50,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitio
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReferenceModelClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SearchClause;
@@ -68,6 +70,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause;
@@ -1438,4 +1441,40 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public void endVisit(OracleErrorLoggingClause x) {
}
@Override
public boolean visit(OracleReturningClause x) {
print("RETURNING ");
printAndAccept(x.getItems(), ", ");
print(" INTO ");
printAndAccept(x.getValues(), ", ");
return false;
}
@Override
public void endVisit(OracleReturningClause x) {
}
@Override
public boolean visit(OracleInsertStatement x) {
visit((SQLInsertStatement) x);
if (x.getReturning() != null) {
println();
x.getReturning().accept(this);
}
if (x.getErrorLogging() != null) {
println();
x.getErrorLogging().accept(this);
}
return false;
}
@Override
public void endVisit(OracleInsertStatement x) {
endVisit((SQLInsertStatement) x);
}
}
@@ -11,6 +11,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint;
@@ -30,6 +31,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitio
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SearchClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SubqueryFactoringClause;
@@ -63,6 +65,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot.Item;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.CheckOption;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.ReadOnly;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot;
@@ -883,6 +886,26 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
public void endVisit(OracleErrorLoggingClause x) {
}
@Override
public boolean visit(OracleReturningClause x) {
return true;
}
@Override
public void endVisit(OracleReturningClause x) {
}
@Override
public boolean visit(OracleInsertStatement x) {
return visit((SQLInsertStatement) x);
}
@Override
public void endVisit(OracleInsertStatement x) {
endVisit((SQLInsertStatement) x);
}
}
@@ -21,7 +21,6 @@ import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleDeleteParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleInsertParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleSelectParser;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
@@ -80,7 +79,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
}
if (lexer.token() == Token.INSERT) {
statementList.add(new OracleInsertParser(this.lexer).parseInsert());
statementList.add(parseInsert());
continue;
}
@@ -144,6 +144,10 @@ public class Lexer {
protected final void scanChar() {
ch = buf[++bp];
}
protected void unscan() {
ch = buf[--bp];
}
/**
* Report an error at the given position using the provided arguments.
@@ -253,6 +257,11 @@ public class Lexer {
return;
case '.':
scanChar();
if (isDigit(ch)) {
unscan();
scanNumber();
return;
}
token = Token.DOT;
return;
case '\'':
@@ -165,6 +165,11 @@ public class SQLStatementParser extends SQLParser {
SQLInsertStatement insertStatement = new SQLInsertStatement();
parseInsert0(insertStatement);
return insertStatement;
}
protected void parseInsert0(SQLInsertStatement insertStatement) {
SQLName tableName = this.exprParser.name();
insertStatement.setTableName(tableName);
@@ -190,7 +195,6 @@ public class SQLStatementParser extends SQLParser {
SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr();
insertStatement.setQuery(queryExpr.getSubQuery());
}
return insertStatement;
}
public boolean parseStatementListDialect(List<SQLStatement> statementList) {
@@ -390,14 +390,19 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
}
public boolean visit(SQLQueryExpr x) {
if (x.getParent() instanceof SQLStatement) {
SQLObject parent = x.getParent();
if (parent instanceof SQLSelect) {
parent = parent.getParent();
}
if (parent instanceof SQLStatement) {
incrementIndent();
println();
x.getSubQuery().accept(this);
decrementIndent();
} else if (x.getParent() instanceof ValuesClause) {
} else if (parent instanceof ValuesClause) {
println();
x.getSubQuery().accept(this);
println();
@@ -428,6 +433,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
}
public boolean visit(SQLSelect x) {
x.getQuery().setParent(x);
x.getQuery().accept(this);
if (x.getOrderBy() != null) {
@@ -609,6 +615,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
} else {
if (x.getQuery() != null) {
println();
x.getQuery().setParent(x);
x.getQuery().accept(this);
}
}