improved sql parser.

This commit is contained in:
wenshao
2017-09-10 03:42:21 +08:00
parent 3330643479
commit 7d54eea716
37 changed files with 848 additions and 243 deletions
@@ -284,7 +284,12 @@ public class SQLUtils {
visitor.setTableMapping(tableMapping);
}
boolean printStmtSeperator = !JdbcConstants.ORACLE.equals(dbType);
boolean printStmtSeperator;
if (JdbcConstants.SQL_SERVER.equals(dbType)) {
printStmtSeperator = false;
} else {
printStmtSeperator = !JdbcConstants.ORACLE.equals(dbType);
}
for (int i = 0, size = statementList.size(); i < size; i++) {
SQLStatement stmt = statementList.get(i);
@@ -168,6 +168,10 @@ public abstract class SQLObjectImpl implements SQLObject {
@SuppressWarnings("unchecked")
public void addAfterComment(List<String> comments) {
if (comments == null) {
return;
}
if (attributes == null) {
attributes = new HashMap<String, Object>(1);
}
@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
package com.alibaba.druid.sql.ast.statement;
import com.alibaba.druid.sql.ast.SQLStatementImpl;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OraclePLSQLCommitStatement extends OracleStatementImpl {
public class SQLScriptCommitStatement extends SQLStatementImpl {
public OraclePLSQLCommitStatement(){
public SQLScriptCommitStatement(){
}
public void accept0(OracleASTVisitor visitor) {
public void accept0(SQLASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
}
@@ -144,18 +144,13 @@ public class MySqlLexer extends Lexer {
}
public void scanVariable() {
if (ch != '@' && ch != ':' && ch != '#' && ch != '$') {
if (ch != ':' && ch != '#' && ch != '$') {
throw new ParserException("illegal variable. " + info());
}
mark = pos;
bufPos = 1;
if (charAt(pos + 1) == '@') {
ch = charAt(++pos);
bufPos++;
}
if (charAt(pos + 1) == '`') {
++pos;
++bufPos;
@@ -221,6 +216,61 @@ public class MySqlLexer extends Lexer {
token = Token.VARIANT;
}
protected void scanVariable_at() {
if (ch != '@') {
throw new ParserException("illegal variable. " + info());
}
mark = pos;
bufPos = 1;
if (charAt(pos + 1) == '@') {
ch = charAt(++pos);
bufPos++;
}
if (charAt(pos + 1) == '`') {
++pos;
++bufPos;
char ch;
for (;;) {
ch = charAt(++pos);
if (ch == '`') {
bufPos++;
++pos;
break;
} else if (ch == EOI) {
throw new ParserException("illegal identifier. " + info());
}
bufPos++;
continue;
}
this.ch = charAt(pos);
stringVal = subString(mark, bufPos);
token = Token.VARIANT;
} else {
for (; ; ) {
ch = charAt(++pos);
if (!isIdentifierChar(ch)) {
break;
}
bufPos++;
continue;
}
}
this.ch = charAt(pos);
stringVal = subString(mark, bufPos);
token = Token.VARIANT;
}
public void scanIdentifier() {
hash_lower = 0;
hash = 0;
@@ -342,6 +392,8 @@ public class MySqlLexer extends Lexer {
}
}
protected final void scanString() {
scanString2();
}
@@ -17,15 +17,7 @@ package com.alibaba.druid.sql.dialect.mysql.parser;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.SQLParameter.ParameterType;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
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.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
@@ -65,7 +57,6 @@ public class MySqlStatementParser extends SQLStatementParser {
private static final String GLOBAL = "GLOBAL";
private static final String VARIABLES = "VARIABLES";
private static final String STATUS = "STATUS";
private static final String IGNORE = "IGNORE";
private static final String RESET = "RESET";
private static final String DESCRIBE = "DESCRIBE";
private static final String WRITE = "WRITE";
@@ -75,7 +66,6 @@ public class MySqlStatementParser extends SQLStatementParser {
private static final String TEMPORARY = "TEMPORARY";
private static final String SPATIAL = "SPATIAL";
private static final String FULLTEXT = "FULLTEXT";
private static final String DELAYED = "DELAYED";
private static final String LOW_PRIORITY = "LOW_PRIORITY";
private static final String CONNECTION = "CONNECTION";
private static final String EXTENDED = "EXTENDED";
@@ -151,7 +141,7 @@ public class MySqlStatementParser extends SQLStatementParser {
this.getExprParser().parseHints(deleteStatement.getHints());
}
if (lexer.identifierEquals(LOW_PRIORITY)) {
if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
deleteStatement.setLowPriority(true);
lexer.nextToken();
}
@@ -161,7 +151,7 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
}
if (lexer.identifierEquals(IGNORE)) {
if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {
deleteStatement.setIgnore(true);
lexer.nextToken();
}
@@ -607,7 +597,7 @@ public class MySqlStatementParser extends SQLStatementParser {
}
} else if (lexer.identifierEquals(WRITE)) {
stmt.setLockType(LockType.WRITE);
} else if (lexer.identifierEquals(LOW_PRIORITY)) {
} else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
lexer.nextToken();
acceptIdentifier(WRITE);
stmt.setLockType(LockType.LOW_PRIORITY_WRITE);
@@ -1792,12 +1782,12 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
}
if (lexer.identifierEquals(LOW_PRIORITY)) {
if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
stmt.setLowPriority(true);
lexer.nextToken();
}
if (lexer.identifierEquals(DELAYED)) {
if (lexer.identifierEquals(FnvHash.Constants.DELAYED)) {
stmt.setDelayed(true);
lexer.nextToken();
}
@@ -1879,7 +1869,7 @@ public class MySqlStatementParser extends SQLStatementParser {
MySqlLoadXmlStatement stmt = new MySqlLoadXmlStatement();
if (lexer.identifierEquals(LOW_PRIORITY)) {
if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
stmt.setLowPriority(true);
lexer.nextToken();
}
@@ -1904,7 +1894,7 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
}
if (lexer.identifierEquals(IGNORE)) {
if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {
stmt.setIgnore(true);
lexer.nextToken();
}
@@ -1936,7 +1926,7 @@ public class MySqlStatementParser extends SQLStatementParser {
stmt.setRowsIdentifiedBy(rowsIdentifiedBy);
}
if (lexer.identifierEquals(IGNORE)) {
if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {
throw new ParserException("TODO. " + lexer.info());
}
@@ -1953,7 +1943,7 @@ public class MySqlStatementParser extends SQLStatementParser {
MySqlLoadDataInFileStatement stmt = new MySqlLoadDataInFileStatement();
if (lexer.identifierEquals(LOW_PRIORITY)) {
if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
stmt.setLowPriority(true);
lexer.nextToken();
}
@@ -1978,7 +1968,7 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
}
if (lexer.identifierEquals(IGNORE)) {
if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {
stmt.setIgnore(true);
lexer.nextToken();
}
@@ -2048,7 +2038,7 @@ public class MySqlStatementParser extends SQLStatementParser {
}
}
if (lexer.identifierEquals(IGNORE)) {
if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {
lexer.nextToken();
stmt.setIgnoreLinesNumber(this.exprParser.expr());
acceptIdentifier("LINES");
@@ -2115,35 +2105,40 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
for (; ; ) {
if (lexer.identifierEquals(LOW_PRIORITY)) {
insertStatement.setLowPriority(true);
lexer.nextToken();
continue;
if (lexer.token() == Token.IDENTIFIER) {
long hash = lexer.hash_lower();
if (hash == FnvHash.Constants.LOW_PRIORITY) {
insertStatement.setLowPriority(true);
lexer.nextToken();
continue;
}
if (hash == FnvHash.Constants.DELAYED) {
insertStatement.setDelayed(true);
lexer.nextToken();
continue;
}
if (hash == FnvHash.Constants.HIGH_PRIORITY) {
insertStatement.setHighPriority(true);
lexer.nextToken();
continue;
}
if (hash == FnvHash.Constants.IGNORE) {
insertStatement.setIgnore(true);
lexer.nextToken();
continue;
}
if (hash == FnvHash.Constants.ROLLBACK_ON_FAIL) {
insertStatement.setRollbackOnFail(true);
lexer.nextToken();
continue;
}
}
if (lexer.identifierEquals(DELAYED)) {
insertStatement.setDelayed(true);
lexer.nextToken();
continue;
}
if (lexer.identifierEquals("HIGH_PRIORITY")) {
insertStatement.setHighPriority(true);
lexer.nextToken();
continue;
}
if (lexer.identifierEquals(IGNORE)) {
insertStatement.setIgnore(true);
lexer.nextToken();
continue;
}
if (lexer.identifierEquals("ROLLBACK_ON_FAIL")) {
insertStatement.setRollbackOnFail(true);
lexer.nextToken();
continue;
}
break;
}
@@ -2155,7 +2150,8 @@ public class MySqlStatementParser extends SQLStatementParser {
SQLName tableName = this.exprParser.name();
insertStatement.setTableName(tableName);
if (lexer.token() == Token.IDENTIFIER && !lexer.identifierEquals("VALUE")) {
if (lexer.token() == Token.IDENTIFIER
&& !lexer.identifierEquals(FnvHash.Constants.VALUE)) {
insertStatement.setAlias(lexer.stringVal());
lexer.nextToken();
}
@@ -2163,20 +2159,59 @@ public class MySqlStatementParser extends SQLStatementParser {
}
int columnSize = 0;
if (lexer.token() == (Token.LPAREN)) {
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() == (Token.SELECT)) {
if (lexer.token() == Token.SELECT) {
SQLSelect select = this.exprParser.createSelectParser().select();
select.setParent(insertStatement);
insertStatement.setQuery(select);
} else {
this.exprParser.exprList(insertStatement.getColumns(), insertStatement);
columnSize = insertStatement.getColumns().size();
List<SQLExpr> columns = insertStatement.getColumns();
//this.exprParser.exprList(insertStatement.getColumns(), insertStatement);
if (lexer.token() != Token.RPAREN) {
for (; ; ) {
String identName;
long hash;
Token token = lexer.token();
if (token == Token.IDENTIFIER) {
identName = lexer.stringVal();
hash = lexer.hash_lower();
} else if (token == Token.LITERAL_CHARS) {
identName = '\'' + lexer.stringVal() + '\'';
hash = 0;
} else {
identName = lexer.stringVal();
hash = 0;
}
lexer.nextTokenComma();
SQLExpr expr = new SQLIdentifierExpr(identName, hash);
while (lexer.token() == Token.DOT) {
lexer.nextToken();
String propertyName = lexer.stringVal();
lexer.nextToken();
expr = new SQLPropertyExpr(expr, propertyName);
}
expr.setParent(insertStatement);
columns.add(expr);
columnSize++;
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
columnSize = insertStatement.getColumns().size();
}
}
accept(Token.RPAREN);
}
if (lexer.token() == Token.VALUES || lexer.identifierEquals("VALUE")) {
if (lexer.token() == Token.VALUES || lexer.identifierEquals(FnvHash.Constants.VALUE)) {
lexer.nextTokenLParen();
parseValueClause(insertStatement.getValuesList(), columnSize, insertStatement);
} else if (lexer.token() == Token.SET) {
@@ -2472,7 +2507,7 @@ public class MySqlStatementParser extends SQLStatementParser {
boolean ignore = false;
if (lexer.identifierEquals(IGNORE)) {
if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {
ignore = true;
lexer.nextToken();
}
@@ -1072,7 +1072,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
print0(ucase ? "INTO " : "into ");
printExpr(x.getTableName());
printTableSourceExpr(x.getTableName());
List<SQLExpr> columns = x.getColumns();
if (columns.size() > 0) {
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.mysql.visitor;
import com.alibaba.druid.sql.ast.statement.SQLScriptCommitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.*;
@@ -34,10 +35,6 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or
super(appender, parameterized);
}
@Override
public void endVisit(OraclePLSQLCommitStatement astNode) {
}
@Override
public void endVisit(OracleAnalytic x) {
@@ -109,11 +106,6 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or
}
@Override
public boolean visit(OraclePLSQLCommitStatement astNode) {
return false;
}
@Override
public boolean visit(OracleAnalytic x) {
return false;
@@ -153,24 +153,6 @@ public class OdpsExprParser extends SQLExprParser {
return super.primaryRest(expr);
}
public SQLExpr equalityRest(SQLExpr expr) {
if (lexer.token() == Token.EQEQ) {
SQLExpr rightExp;
lexer.nextToken();
try {
rightExp = bitOr();
} catch (EOFParserException e) {
throw new ParserException("EOF, " + expr + "=", e);
}
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, getDbType());
return expr;
}
return super.equalityRest(expr);
}
public SQLExpr relationalRest(SQLExpr expr) {
if (lexer.identifierEquals("REGEXP")) {
@@ -362,6 +362,10 @@ public class OdpsLexer extends Lexer {
super.scanVariable();
}
protected void scanVariable_at() {
scanVariable();
}
protected final void scanString() {
scanString2();
}
@@ -998,43 +998,6 @@ public class OracleExprParser extends SQLExprParser {
return name;
}
public SQLExpr equalityRest(SQLExpr expr) {
SQLExpr rightExp;
if (lexer.token() == Token.EQ) {
lexer.nextToken();
if (lexer.token() == Token.GT) {
lexer.nextToken();
rightExp = expr();
String argumentName = ((SQLIdentifierExpr) expr).getName();
return new OracleArgumentExpr(argumentName, rightExp);
}
rightExp = shift();
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, getDbType());
} else if (lexer.token() == Token.BANGEQ || lexer.token() == Token.CARETEQ) {
lexer.nextToken();
rightExp = shift();
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType());
} else if (lexer.token() == Token.BANG) {
lexer.nextToken();
accept(Token.EQ);
rightExp = shift();
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType());
}
return expr;
}
public OraclePrimaryKey parsePrimaryKey() {
lexer.nextToken();
accept(Token.KEY);
@@ -1043,7 +1006,6 @@ public class OracleExprParser extends SQLExprParser {
accept(Token.LPAREN);
orderBy(primaryKey.getColumns(), primaryKey);
accept(Token.RPAREN);
if (lexer.token() == Token.USING) {
OracleUsingIndexClause using = parseUsingIndex();
@@ -144,12 +144,6 @@ public class OracleLexer extends Lexer {
}
public void scanVariable() {
if (ch == '@') {
scanChar();
token = Token.MONKEYS_AT;
return;
}
if (ch != ':' && ch != '#' && ch != '$') {
throw new ParserException("illegal variable. " + info());
}
@@ -206,6 +200,12 @@ public class OracleLexer extends Lexer {
}
}
protected void scanVariable_at() {
scanChar();
token = Token.MONKEYS_AT;
return;
}
public void scanComment() {
if (ch != '/' && ch != '-') {
throw new IllegalStateException();
@@ -129,7 +129,7 @@ public class OracleStatementParser extends SQLStatementParser {
if (lexer.token() == (Token.SLASH)) {
lexer.nextToken();
SQLStatement stmt = new OraclePLSQLCommitStatement();
SQLStatement stmt = new SQLScriptCommitStatement();
stmt.setParent(parent);
statementList.add(stmt);
continue;
@@ -36,7 +36,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public interface OracleASTVisitor extends SQLASTVisitor {
void endVisit(OraclePLSQLCommitStatement astNode);
void endVisit(OracleAnalytic x);
@@ -68,8 +68,6 @@ public interface OracleASTVisitor extends SQLASTVisitor {
void endVisit(OracleUpdateStatement x);
boolean visit(OraclePLSQLCommitStatement astNode);
boolean visit(OracleAnalytic x);
boolean visit(OracleAnalyticWindowing x);
@@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.oracle.visitor;
import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause;
import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause;
import com.alibaba.druid.sql.ast.statement.SQLScriptCommitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
@@ -49,7 +50,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements OracleASTVisitor {
@Override
public void endVisit(OraclePLSQLCommitStatement astNode) {
public void endVisit(SQLScriptCommitStatement astNode) {
}
@@ -124,7 +125,7 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora
}
@Override
public boolean visit(OraclePLSQLCommitStatement astNode) {
public boolean visit(SQLScriptCommitStatement astNode) {
return true;
}
@@ -212,7 +212,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
return false;
}
public boolean visit(OraclePLSQLCommitStatement astNode) {
public boolean visit(SQLScriptCommitStatement astNode) {
print('/');
println();
return false;
@@ -624,11 +624,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
return false;
}
@Override
public void endVisit(OraclePLSQLCommitStatement astNode) {
}
@Override
public void endVisit(OracleAnalytic x) {
@@ -17,7 +17,6 @@ package com.alibaba.druid.sql.dialect.oracle.visitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
@@ -222,11 +221,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
return super.visit(x);
}
@Override
public void endVisit(OraclePLSQLCommitStatement astNode) {
}
@Override
public void endVisit(OracleAnalytic x) {
@@ -288,7 +282,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
}
@Override
public boolean visit(OraclePLSQLCommitStatement astNode) {
public boolean visit(SQLScriptCommitStatement astNode) {
return true;
}
@@ -15,15 +15,13 @@
*/
package com.alibaba.druid.sql.dialect.postgresql.parser;
import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;
import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.druid.sql.parser.Keywords;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLParserFeature;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.JdbcConstants;
public class PGLexer extends Lexer {
@@ -187,4 +185,43 @@ public class PGLexer extends Lexer {
token = Token.POUND;
}
}
protected void scanVariable_at() {
if (ch != '@') {
throw new ParserException("illegal variable. " + info());
}
mark = pos;
bufPos = 1;
char ch;
final char c1 = charAt(pos + 1);
if (c1 == '@') {
pos += 2;
token = Token.MONKEYS_AT_AT;
this.ch = charAt(++pos);
return;
} else if (c1 == '>') {
pos += 2;
token = Token.MONKEYS_AT_GT;
this.ch = charAt(++pos);
return;
}
for (;;) {
ch = charAt(++pos);
if (!isIdentifierChar(ch)) {
break;
}
bufPos++;
continue;
}
this.ch = charAt(pos);
stringVal = addSymbol();
token = Token.VARIANT;
}
}
@@ -38,6 +38,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionI
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerWaitForStatement;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.FnvHash;
public class SQLServerStatementParser extends SQLStatementParser {
@@ -64,7 +65,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
return true;
}
if (lexer.identifierEquals("EXEC") || lexer.identifierEquals("EXECUTE")) {
if (lexer.identifierEquals(FnvHash.Constants.EXEC) || lexer.identifierEquals(FnvHash.Constants.EXECUTE)) {
lexer.nextToken();
SQLServerExecStatement execStmt = new SQLServerExecStatement();
@@ -109,10 +110,18 @@ public class SQLServerStatementParser extends SQLStatementParser {
return true;
}
if (lexer.identifierEquals("WAITFOR")) {
if (lexer.identifierEquals(FnvHash.Constants.WAITFOR)) {
statementList.add(this.parseWaitFor());
return true;
}
if (lexer.identifierEquals(FnvHash.Constants.GO)) {
lexer.nextToken();
SQLStatement stmt = new SQLScriptCommitStatement();
statementList.add(stmt);
return true;
}
return false;
}
@@ -442,7 +451,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
stmt.setCondition(this.exprParser.expr());
this.parseStatementList(stmt.getStatements(), 1);
this.parseStatementList(stmt.getStatements(), 1, stmt);
if(lexer.token() == Token.SEMI) {
lexer.nextToken();
@@ -452,7 +461,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
lexer.nextToken();
SQLIfStatement.Else elseItem = new SQLIfStatement.Else();
this.parseStatementList(elseItem.getStatements(), 1);
this.parseStatementList(elseItem.getStatements(), 1, elseItem);
stmt.setElseItem(elseItem);
}
@@ -573,4 +573,10 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
return false;
}
@Override
public boolean visit(SQLScriptCommitStatement x) {
print0(ucase ? "GO" : "go");
return false;
}
}
@@ -325,6 +325,40 @@ public class Lexer {
nextToken();
}
public final void nextTokenEq() {
if (ch == ' ') {
scanChar();
}
if (ch == '=') {
scanChar();
token = EQ;
return;
}
if (ch == '.') {
scanChar();
token = DOT;
return;
}
if (ch == 'a' || ch == 'A') {
char ch_next = charAt(pos + 1);
if (ch_next == 's' || ch_next == 'S') {
char ch_next_2 = charAt(pos + 2);
if (ch_next_2 == ' ') {
pos += 2;
ch = ' ';
token = Token.AS;
stringVal = "AS";
return;
}
}
}
nextToken();
}
public final void nextTokenLParen() {
if (ch == ' ') {
scanChar();
@@ -362,7 +396,30 @@ public class Lexer {
return;
}
if (isFirstIdentifierChar(ch) && ch != 'N') {
if (ch == 'n' || ch == 'N') {
char c1 = 0, c2, c3, c4;
if (pos + 4 < text.length()
&& ((c1 = text.charAt(pos + 1)) == 'u' || c1 == 'U')
&& ((c2 = text.charAt(pos + 2)) == 'l' || c2 == 'L')
&& ((c3 = text.charAt(pos + 3)) == 'l' || c3 == 'L')
&& (isWhitespace(c4 = text.charAt(pos + 4)) || c4 == ',' || c4 == ')')) {
pos += 4;
ch = c4;
token = Token.NULL;
stringVal = "NULL";
return;
}
if (c1 == '\'') {
++pos;
ch = '\'';
scanString();
token = Token.LITERAL_NCHARS;
return;
}
}
if (isFirstIdentifierChar(ch)) {
scanIdentifier();
return;
}
@@ -608,7 +665,7 @@ public class Lexer {
case '`':
throw new ParserException("TODO. " + info()); // TODO
case '@':
scanVariable();
scanVariable_at();
return;
case '-':
if (charAt(pos +1) == '-') {
@@ -736,6 +793,9 @@ public class Lexer {
if (ch == '=') {
scanChar();
token = Token.EQEQ;
} else if (ch == '>') {
scanChar();
token = Token.EQGT;
} else {
token = Token.EQ;
}
@@ -781,6 +841,9 @@ public class Lexer {
break;
case '!':
scanChar();
while (isWhitespace(ch)) {
scanChar();
}
if (ch == '=') {
scanChar();
token = Token.BANGEQ;
@@ -1145,7 +1208,7 @@ public class Lexer {
}
public void scanVariable() {
if (ch != '@' && ch != ':' && ch != '#' && ch != '$') {
if (ch != ':' && ch != '#' && ch != '$') {
throw new ParserException("illegal variable. " + info());
}
@@ -1154,17 +1217,7 @@ public class Lexer {
char ch;
final char c1 = charAt(pos + 1);
if (c1 == '@') {
if (JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) {
pos += 2;
token = Token.MONKEYS_AT_AT;
this.ch = charAt(++pos);
return;
}
ch = charAt(++pos);
bufPos++;
} else if (c1 == '>' && JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) {
if (c1 == '>' && JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) {
pos += 2;
token = Token.MONKEYS_AT_GT;
this.ch = charAt(++pos);
@@ -1214,6 +1267,38 @@ public class Lexer {
token = Token.VARIANT;
}
protected void scanVariable_at() {
if (ch != '@') {
throw new ParserException("illegal variable. " + info());
}
mark = pos;
bufPos = 1;
char ch;
final char c1 = charAt(pos + 1);
if (c1 == '@') {
++pos;
bufPos++;
}
for (;;) {
ch = charAt(++pos);
if (!isIdentifierChar(ch)) {
break;
}
bufPos++;
continue;
}
this.ch = charAt(pos);
stringVal = addSymbol();
token = Token.VARIANT;
}
public void scanComment() {
if (!allowComment) {
throw new NotAllowCommentException();
@@ -1641,12 +1726,12 @@ public class Lexer {
}
multmin = negative ? MULTMIN_RADIX_TEN : N_MULTMAX_RADIX_TEN;
if (i < max) {
digit = digits[charAt(i++)];
digit = charAt(i++) - '0';
result = -digit;
}
while (i < max) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = digits[charAt(i++)];
digit = charAt(i++) - '0';
if (result < multmin) {
return new BigInteger(numberString());
}
@@ -44,6 +44,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLUnique;
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
@@ -1462,12 +1463,38 @@ public class SQLExprParser extends SQLParser {
accept(Token.RPAREN);
item.setColumn(list);
} else {
item.setColumn(this.primary());
String identName;
long hash;
Token token = lexer.token();
if (token == Token.IDENTIFIER) {
identName = lexer.stringVal();
hash = lexer.hash_lower();
} else if (token == Token.LITERAL_CHARS) {
identName = '\'' + lexer.stringVal() + '\'';
hash = 0;
} else {
identName = lexer.stringVal();
hash = 0;
}
lexer.nextTokenEq();
SQLExpr expr = new SQLIdentifierExpr(identName, hash);
while (lexer.token() == Token.DOT) {
lexer.nextToken();
String propertyName = lexer.stringVal();
lexer.nextTokenEq();
expr = new SQLPropertyExpr(expr, propertyName);
}
item.setColumn(expr);
}
if (lexer.token == Token.COLONEQ) {
lexer.nextToken();
lexer.nextTokenValue();
} else if (lexer.token == Token.EQ) {
lexer.nextTokenValue();
} else {
accept(Token.EQ);
throw new ParserException("syntax error, expect EQ, actual " + lexer.token + " "
+ lexer.info());
}
item.setValue(this.expr());
@@ -1519,28 +1546,28 @@ public class SQLExprParser extends SQLParser {
} catch (EOFParserException e) {
throw new ParserException("EOF, " + expr + "=", e);
}
rightExp = equalityRest(rightExp);
if (lexer.token == Token.COLONEQ) {
lexer.nextToken();
SQLExpr colonExpr = expr();
rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);
}
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);
} else if (token == Token.BANGEQ) {
} else if (lexer.token() == Token.EQGT) {
lexer.nextToken();
rightExp = expr();
String argumentName = ((SQLIdentifierExpr) expr).getName();
return new OracleArgumentExpr(argumentName, rightExp);
} else if (token == Token.BANGEQ || token == Token.CARETEQ) {
lexer.nextToken();
rightExp = bitOr();
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType());
} else if (token == Token.BANG) {
lexer.nextToken();
accept(Token.EQ);
rightExp = bitOr();
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, dbType);
} else if (token == Token.COLONEQ) {
lexer.nextToken();
rightExp = expr();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, dbType);
}
return expr;
@@ -1562,9 +1589,19 @@ public class SQLExprParser extends SQLParser {
return queryExpr;
}
exprList(inListExpr.getTargetList(), inListExpr);
List<SQLExpr> targetList = inListExpr.getTargetList();
for (;;) {
SQLExpr item = this.expr();
item.setParent(inListExpr);
targetList.add(item);
if (lexer.token == Token.COMMA) {
lexer.nextTokenValue();
continue;
}
break;
}
accept(Token.RPAREN);
expr = inListExpr;
} else {
SQLExpr itemExpr = primary();
itemExpr.setParent(inListExpr);
@@ -2632,6 +2669,13 @@ public class SQLExprParser extends SQLParser {
String as = lexer.stringVal();
lexer.nextTokenComma();
if (lexer.token == Token.DOT) {
lexer.nextToken();
as += '.' + lexer.stringVal();
lexer.nextToken();
}
return new SQLSelectItem(expr, as, connectByRoot);
}
@@ -18,8 +18,11 @@ package com.alibaba.druid.sql.parser;
import java.util.List;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
@@ -317,7 +320,7 @@ public class SQLSelectParser extends SQLParser {
}
SQLExpr where = expr();
if (where != null && beforeComments != null) {
if (beforeComments != null) {
where.addBeforeComment(beforeComments);
}
@@ -19,12 +19,10 @@ import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
@@ -77,7 +75,7 @@ public class SQLStatementParser extends SQLParser {
}
public void parseStatementList(List<SQLStatement> statementList) {
parseStatementList(statementList, -1);
parseStatementList(statementList, -1, null);
}
public void parseStatementList(List<SQLStatement> statementList, int max) {
@@ -2430,7 +2428,7 @@ public class SQLStatementParser extends SQLParser {
*/
public SQLStatement parseStatement( final boolean tryBest) {
List<SQLStatement> list = new ArrayList<SQLStatement>();
this.parseStatementList(list, 1);
this.parseStatementList(list, 1, null);
if (tryBest) {
if (lexer.token != Token.EOF) {
throw new ParserException("sql syntax error, no terminated. " + lexer.token);
@@ -317,7 +317,8 @@ public enum Token {
COLON(":"),
COLONCOLON("::"),
COLONEQ(":="),
EQEQ("=="),
EQEQ("=="),
EQGT("=>"),
LTEQ("<="),
LTEQGT("<=>"),
LTGT("<>"),
@@ -1041,13 +1041,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
public boolean visit(SQLIdentifierExpr x) {
final String name = x.getName();
if (!this.parameterized) {
print0(x.getName());
return false;
}
return printName(x, name);
print0(x.getName());
return false;
}
private boolean printName(SQLName x, String name) {
@@ -1535,7 +1530,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
if (mapTableName != null) {
print0(mapTableName);
} else {
printExpr(owner);
if (owner instanceof SQLIdentifierExpr) {
SQLIdentifierExpr ownerIdent = (SQLIdentifierExpr) owner;
printName(ownerIdent, ownerIdent.getName());
} else {
printExpr(owner);
}
}
print('.');
@@ -1961,9 +1961,54 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
if (expr instanceof SQLIdentifierExpr) {
visit((SQLIdentifierExpr) expr);
SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
final String name = identifierExpr.getName();
if (!this.parameterized) {
print0(name);
return;
}
boolean shardingSupport = this.shardingSupport
&& this.parameterized;
if (shardingSupport) {
String nameUnwrappe = unwrapShardingTable(name);
if (!name.equals(nameUnwrappe)) {
incrementReplaceCunt();
}
print0(nameUnwrappe);
} else {
print0(name);
}
} else if (expr instanceof SQLPropertyExpr) {
visit((SQLPropertyExpr) expr);
SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
SQLExpr owner = propertyExpr.getOwner();
printTableSourceExpr(owner);
print('.');
final String name = propertyExpr.getName();
if (!this.parameterized) {
print0(propertyExpr.getName());
return;
}
boolean shardingSupport = this.shardingSupport
&& this.parameterized;
if (shardingSupport) {
String nameUnwrappe = unwrapShardingTable(name);
if (!name.equals(nameUnwrappe)) {
incrementReplaceCunt();
}
print0(nameUnwrappe);
} else {
print0(name);
}
} else {
expr.accept(this);
}
@@ -738,5 +738,8 @@ public interface SQLASTVisitor {
boolean visit(SQLBinaryOpExprGroup x);
void endVisit(SQLBinaryOpExprGroup x);
//
boolean visit(SQLScriptCommitStatement astNode);
void endVisit(SQLScriptCommitStatement astNode);
}
@@ -1689,6 +1689,16 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
features = VisitorFeature.config(features, feature, state);
}
@Override
public boolean visit(SQLScriptCommitStatement x) {
return true;
}
@Override
public void endVisit(SQLScriptCommitStatement astNode) {
}
public final boolean isEnabled(VisitorFeature feature) {
return VisitorFeature.isEnabled(this.features, feature);
}