diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitorUtils.java b/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitorUtils.java index 9e91c559c0..5d5fff7f3a 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitorUtils.java @@ -4,14 +4,18 @@ import java.util.Map; import com.alibaba.druid.mapping.DruidMappingException; import com.alibaba.druid.mapping.Entity; +import com.alibaba.druid.mapping.MappingEngine; import com.alibaba.druid.mapping.Property; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; public class MappingVisitorUtils { @@ -122,4 +126,24 @@ public class MappingVisitorUtils { return entity; } + public static void setDataSource(MappingEngine engine, SQLDeleteStatement stmt) { + if (stmt.getTableSource() == null) { + Entity entity = engine.getFirstEntity(); + stmt.setTableSource(new SQLIdentifierExpr(entity.getName())); + } + } + + public static void setDataSource(MappingEngine engine, SQLUpdateStatement stmt) { + if (stmt.getTableSource() == null) { + Entity entity = engine.getFirstEntity(); + stmt.setTableSource(new SQLIdentifierExpr(entity.getName())); + } + } + + public static void setDataSource(MappingEngine engine, SQLInsertStatement stmt) { + if (stmt.getTableSource() == null) { + Entity entity = engine.getFirstEntity(); + stmt.setTableSource(new SQLIdentifierExpr(entity.getName())); + } + } } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingProvider.java b/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingProvider.java index 3a0f4116d9..33c22408b1 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingProvider.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingProvider.java @@ -2,9 +2,7 @@ package com.alibaba.druid.mapping.spi; import java.util.List; -import com.alibaba.druid.mapping.Entity; import com.alibaba.druid.mapping.MappingEngine; -import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; @@ -57,10 +55,7 @@ public class MySqlMappingProvider implements MappingProvider { MySqlStatementParser parser = new MySqlStatementParser(sql); MySqlDeleteStatement stmt = parser.parseDeleteStatement(); - if (stmt.getTableSource() == null) { - Entity entity = engine.getFirstEntity(); - stmt.setTableSource(new SQLIdentifierExpr(entity.getName())); - } + MappingVisitorUtils.setDataSource(engine, stmt); return stmt; } @@ -69,10 +64,7 @@ public class MySqlMappingProvider implements MappingProvider { MySqlStatementParser parser = new MySqlStatementParser(sql); SQLUpdateStatement stmt = parser.parseUpdateStatement(); - if (stmt.getTableSource() == null) { - Entity entity = engine.getFirstEntity(); - stmt.setTableSource(new SQLIdentifierExpr(entity.getName())); - } + MappingVisitorUtils.setDataSource(engine, stmt); return stmt; } @@ -80,11 +72,8 @@ public class MySqlMappingProvider implements MappingProvider { public SQLInsertStatement explainToInsertSQLObject(MappingEngine engine, String sql) { MySqlStatementParser parser = new MySqlStatementParser(sql); SQLInsertStatement stmt = (SQLInsertStatement) parser.parseInsert(); - - if (stmt.getTableSource() == null) { - Entity entity = engine.getFirstEntity(); - stmt.setTableSource(new SQLIdentifierExpr(entity.getName())); - } + + MappingVisitorUtils.setDataSource(engine, stmt); return stmt; } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingProvider.java b/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingProvider.java index 2e449545ad..1c5dd6336e 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingProvider.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingProvider.java @@ -2,9 +2,7 @@ package com.alibaba.druid.mapping.spi; import java.util.List; -import com.alibaba.druid.mapping.Entity; import com.alibaba.druid.mapping.MappingEngine; -import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; @@ -37,23 +35,27 @@ public class OracleMappingProvider implements MappingProvider { public OracleDeleteStatement explainToDeleteSQLObject(MappingEngine engine, String sql) { OracleStatementParser parser = new OracleStatementParser(sql); OracleDeleteStatement stmt = parser.parseDeleteStatement(); - - if (stmt.getTableSource() == null) { - Entity entity = engine.getFirstEntity(); - stmt.setTableName(new SQLIdentifierExpr(entity.getName())); - } + + MappingVisitorUtils.setDataSource(engine, stmt); return stmt; } public SQLUpdateStatement explainToUpdateSQLObject(MappingEngine engine, String sql) { OracleStatementParser parser = new OracleStatementParser(sql); - return parser.parseUpdateStatement(); + SQLUpdateStatement stmt = parser.parseUpdateStatement(); + + MappingVisitorUtils.setDataSource(engine, stmt); + + return stmt; } public SQLInsertStatement explainToInsertSQLObject(MappingEngine engine, String sql) { OracleStatementParser parser = new OracleStatementParser(sql); - return (SQLInsertStatement) parser.parseInsert(); + SQLInsertStatement stmt = (SQLInsertStatement) parser.parseInsert(); + MappingVisitorUtils.setDataSource(engine, stmt); + return stmt; + } @Override diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 06d13f53f3..b84a936387 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -725,6 +725,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV x.getTableName().accept(this); if (x.getColumns().size() > 0) { + incrementIndent(); println(); print("("); for (int i = 0, size = x.getColumns().size(); i < size; ++i) { @@ -738,6 +739,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV x.getColumns().get(i).accept(this); } print(")"); + decrementIndent(); } if (x.getValuesList().size() != 0) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java index 61daa0b29c..584542ee43 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java @@ -21,10 +21,6 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { super(appender); } - public void println() { - print(' '); - } - public boolean visit(SQLInListExpr x) { x.getExpr().accept(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 66f5fb242f..445d6137c3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -1227,6 +1227,16 @@ public class OracleStatementParser extends SQLStatementParser { } public OracleStatement parseInsert() { + if (lexer.token() == Token.LPAREN) { + OracleInsertStatement stmt = new OracleInsertStatement(); + parseInsert0(stmt, false); + + stmt.setReturning(parseReturningClause()); + stmt.setErrorLogging(parseErrorLoggingClause()); + + return stmt; + } + accept(Token.INSERT); List hints = new ArrayList(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java index b0859eccdc..9c7d998ab9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java @@ -37,20 +37,23 @@ public class OracleUpdateParser extends SQLStatementParser { } public OracleUpdateStatement parseUpdateStatement() throws ParserException { - accept(Token.UPDATE); - OracleUpdateStatement update = new OracleUpdateStatement(); - parseHints(update); + + if (lexer.token() == Token.UPDATE) { + lexer.nextToken(); - if (identifierEquals("ONLY")) { - update.setOnly(true); - } + parseHints(update); - SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); - update.setTableSource(tableSource); + if (identifierEquals("ONLY")) { + update.setOnly(true); + } - if ((update.getAlias() == null) || (update.getAlias().length() == 0)) { - update.setAlias(as()); + SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); + update.setTableSource(tableSource); + + if ((update.getAlias() == null) || (update.getAlias().length() == 0)) { + update.setAlias(as()); + } } parseSet(update); @@ -71,30 +74,30 @@ public class OracleUpdateParser extends SQLStatementParser { private void parseReturn(OracleUpdateStatement update) throws ParserException { if (identifierEquals("RETURN") || lexer.token() == Token.RETURNING) { lexer.nextToken(); - + for (;;) { SQLExpr item = this.exprParser.expr(); update.getReturning().add(item); - + if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } - + break; } - + accept(Token.INTO); - + for (;;) { SQLExpr item = this.exprParser.expr(); update.getReturningInto().add(item); - + if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } - + break; } } @@ -118,7 +121,7 @@ public class OracleUpdateParser extends SQLStatementParser { for (;;) { SQLUpdateSetItem item = new SQLUpdateSetItem(); - + if (lexer.token() == (Token.LPAREN)) { lexer.nextToken(); SQLListExpr list = new SQLListExpr(); @@ -135,7 +138,7 @@ public class OracleUpdateParser extends SQLStatementParser { if (lexer.token() != Token.COMMA) { break; } - + lexer.nextToken(); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java index 4782877617..ecf33ca02d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java @@ -19,9 +19,9 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor { public OracleParameterizedOutputVisitor(Appendable appender){ super(appender); } - - public void println() { - print(' '); + + public OracleParameterizedOutputVisitor(Appendable appender, boolean printPostSemi){ + super (appender, printPostSemi); } public boolean visit(SQLInListExpr x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index 8f9eb1727c..e50b99707a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -37,7 +37,7 @@ public class PGSQLStatementParser extends SQLStatementParser { public PGSelectParser createSQLSelectParser() { return new PGSelectParser(this.lexer); } - + public SQLUpdateStatement parseUpdateStatement() throws ParserException { accept(Token.UPDATE); @@ -68,10 +68,10 @@ public class PGSQLStatementParser extends SQLStatementParser { lexer.nextToken(); udpateStatement.setWhere(this.exprParser.expr()); } - + if (lexer.token() == Token.RETURNING) { lexer.nextToken(); - + for (;;) { udpateStatement.getReturning().add(this.exprParser.expr()); if (lexer.token() == Token.COMMA) { @@ -86,17 +86,20 @@ public class PGSQLStatementParser extends SQLStatementParser { } public PGInsertStatement parseInsert() { - accept(Token.INSERT); - accept(Token.INTO); - PGInsertStatement stmt = new PGInsertStatement(); - SQLName tableName = this.exprParser.name(); - stmt.setTableName(tableName); - - if (lexer.token() == Token.IDENTIFIER) { - stmt.setAlias(lexer.stringVal()); + if (lexer.token() == Token.INSERT) { lexer.nextToken(); + accept(Token.INTO); + + SQLName tableName = this.exprParser.name(); + stmt.setTableName(tableName); + + if (lexer.token() == Token.IDENTIFIER) { + stmt.setAlias(lexer.stringVal()); + lexer.nextToken(); + } + } if (lexer.token() == (Token.LPAREN)) { @@ -124,7 +127,7 @@ public class PGSQLStatementParser extends SQLStatementParser { SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr(); stmt.setQuery(queryExpr.getSubQuery()); } - + if (lexer.token() == Token.RETURNING) { lexer.nextToken(); SQLExpr returning = this.exprParser.expr(); @@ -242,7 +245,7 @@ public class PGSQLStatementParser extends SQLStatementParser { return false; } - + public PGWithClause parseWithClause() { lexer.nextToken(); @@ -269,7 +272,7 @@ public class PGSQLStatementParser extends SQLStatementParser { private PGWithQuery withQuery() { PGWithQuery withQuery = new PGWithQuery(); withQuery.setName(this.createExprParser().expr()); - + if (lexer.token() == Token.LPAREN) { lexer.nextToken(); @@ -305,17 +308,17 @@ public class PGSQLStatementParser extends SQLStatementParser { throw new ParserException("syntax error, support token '" + lexer.token() + "'"); } withQuery.setQuery(query); - + accept(Token.RPAREN); } - + return withQuery; } - + public PGSelectStatement parseSelect() throws ParserException { return new PGSelectStatement(createSQLSelectParser().select()); } - + public SQLStatement parseWith() { PGWithClause with = this.parseWithClause(); if (lexer.token() == Token.INSERT) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java index a2c3af317e..94f7ddb5fb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java @@ -13,187 +13,188 @@ import com.alibaba.druid.sql.parser.Token; public class PGSelectParser extends SQLSelectParser { - public PGSelectParser(Lexer lexer) { - super(lexer); - } + public PGSelectParser(Lexer lexer){ + super(lexer); + } - public PGSelectParser(String sql) throws ParserException { - this(new PGLexer(sql)); - this.lexer.nextToken(); - } + public PGSelectParser(String sql) throws ParserException{ + this(new PGLexer(sql)); + this.lexer.nextToken(); + } - @Override - public SQLSelectQuery query() throws ParserException { - PGSelectQueryBlock queryBlock = new PGSelectQueryBlock(); + @Override + public SQLSelectQuery query() throws ParserException { + PGSelectQueryBlock queryBlock = new PGSelectQueryBlock(); - accept(Token.SELECT); + if (lexer.token() == Token.SELECT) { + lexer.nextToken(); - if (lexer.token() == Token.DISTINCT) { - queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); - lexer.nextToken(); + if (lexer.token() == Token.DISTINCT) { + queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); + lexer.nextToken(); - if (lexer.token() == Token.ON) { - lexer.nextToken(); + if (lexer.token() == Token.ON) { + lexer.nextToken(); - for (;;) { - SQLExpr expr = this.createExprParser().expr(); - queryBlock.getDistinctOn().add(expr); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - } - } else if (lexer.token() == Token.ALL) { - queryBlock.setDistionOption(SQLSetQuantifier.ALL); - lexer.nextToken(); - } - - parseSelectList(queryBlock); - - if (lexer.token() == Token.INTO) { - IntoClause into = new IntoClause(); - lexer.nextToken(); - - if (lexer.token() == Token.TEMPORARY) { - lexer.nextToken(); - into.setOption(IntoClause.Option.TEMPORARY); - } else if (lexer.token() == Token.TEMP) { - lexer.nextToken(); - into.setOption(IntoClause.Option.TEMP); - } else if (lexer.token() == Token.UNLOGGED) { - lexer.nextToken(); - into.setOption(IntoClause.Option.UNLOGGED); - } - - if (lexer.token() == Token.TABLE) { - lexer.nextToken(); - } - - SQLExpr name = this.createExprParser().name(); - into.setTable(name); - - queryBlock.setInto(into); - } + for (;;) { + SQLExpr expr = this.createExprParser().expr(); + queryBlock.getDistinctOn().add(expr); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else { + break; + } + } + } + } else if (lexer.token() == Token.ALL) { + queryBlock.setDistionOption(SQLSetQuantifier.ALL); + lexer.nextToken(); + } - parseFrom(queryBlock); + parseSelectList(queryBlock); - parseWhere(queryBlock); + if (lexer.token() == Token.INTO) { + IntoClause into = new IntoClause(); + lexer.nextToken(); - parseGroupBy(queryBlock); + if (lexer.token() == Token.TEMPORARY) { + lexer.nextToken(); + into.setOption(IntoClause.Option.TEMPORARY); + } else if (lexer.token() == Token.TEMP) { + lexer.nextToken(); + into.setOption(IntoClause.Option.TEMP); + } else if (lexer.token() == Token.UNLOGGED) { + lexer.nextToken(); + into.setOption(IntoClause.Option.UNLOGGED); + } - if (lexer.token() == Token.WINDOW) { - lexer.nextToken(); - PGSelectQueryBlock.WindowClause window = new PGSelectQueryBlock.WindowClause(); - window.setName(this.expr()); - accept(Token.AS); + if (lexer.token() == Token.TABLE) { + lexer.nextToken(); + } - for (;;) { - SQLExpr expr = this.createExprParser().expr(); - window.getDefinition().add(expr); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - queryBlock.setWindow(window); - } + SQLExpr name = this.createExprParser().name(); + into.setTable(name); - queryBlock.setOrderBy(this.createExprParser().parseOrderBy()); + queryBlock.setInto(into); + } + } - if (lexer.token() == Token.LIMIT) { - lexer.nextToken(); - if (lexer.token() == Token.ALL) { - queryBlock.setLimit(new SQLIdentifierExpr("ALL")); - lexer.nextToken(); - } else { - SQLExpr limit = expr(); - queryBlock.setLimit(limit); - } - } + parseFrom(queryBlock); - if (lexer.token() == Token.OFFSET) { - lexer.nextToken(); - SQLExpr offset = expr(); - queryBlock.setOffset(offset); + parseWhere(queryBlock); - if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) { - lexer.nextToken(); - } else { - throw new ParserException("expect 'ROW' or 'ROWS'"); - } - } + parseGroupBy(queryBlock); - if (lexer.token() == Token.FETCH) { - lexer.nextToken(); - PGSelectQueryBlock.FetchClause fetch = new PGSelectQueryBlock.FetchClause(); + if (lexer.token() == Token.WINDOW) { + lexer.nextToken(); + PGSelectQueryBlock.WindowClause window = new PGSelectQueryBlock.WindowClause(); + window.setName(this.expr()); + accept(Token.AS); - if (lexer.token() == Token.FIRST) { - fetch.setOption(PGSelectQueryBlock.FetchClause.Option.FIRST); - } else if (lexer.token() == Token.NEXT) { - fetch.setOption(PGSelectQueryBlock.FetchClause.Option.NEXT); - } else { - throw new ParserException("expect 'FIRST' or 'NEXT'"); - } + for (;;) { + SQLExpr expr = this.createExprParser().expr(); + window.getDefinition().add(expr); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else { + break; + } + } + queryBlock.setWindow(window); + } - SQLExpr count = expr(); - fetch.setCount(count); + queryBlock.setOrderBy(this.createExprParser().parseOrderBy()); - if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) { - lexer.nextToken(); - } else { - throw new ParserException("expect 'ROW' or 'ROWS'"); - } + if (lexer.token() == Token.LIMIT) { + lexer.nextToken(); + if (lexer.token() == Token.ALL) { + queryBlock.setLimit(new SQLIdentifierExpr("ALL")); + lexer.nextToken(); + } else { + SQLExpr limit = expr(); + queryBlock.setLimit(limit); + } + } - if (lexer.token() == Token.ONLY) { - lexer.nextToken(); - } else { - throw new ParserException("expect 'ONLY'"); - } - - queryBlock.setFetch(fetch); - } + if (lexer.token() == Token.OFFSET) { + lexer.nextToken(); + SQLExpr offset = expr(); + queryBlock.setOffset(offset); - if (lexer.token() == Token.FOR) { - lexer.nextToken(); + if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) { + lexer.nextToken(); + } else { + throw new ParserException("expect 'ROW' or 'ROWS'"); + } + } - PGSelectQueryBlock.ForClause forClause = new PGSelectQueryBlock.ForClause(); + if (lexer.token() == Token.FETCH) { + lexer.nextToken(); + PGSelectQueryBlock.FetchClause fetch = new PGSelectQueryBlock.FetchClause(); - if (lexer.token() == Token.UPDATE) { - forClause.setOption(PGSelectQueryBlock.ForClause.Option.UPDATE); - } else if (lexer.token() == Token.SHARE) { - forClause.setOption(PGSelectQueryBlock.ForClause.Option.SHARE); - } else { - throw new ParserException("expect 'FIRST' or 'NEXT'"); - } + if (lexer.token() == Token.FIRST) { + fetch.setOption(PGSelectQueryBlock.FetchClause.Option.FIRST); + } else if (lexer.token() == Token.NEXT) { + fetch.setOption(PGSelectQueryBlock.FetchClause.Option.NEXT); + } else { + throw new ParserException("expect 'FIRST' or 'NEXT'"); + } - accept(Token.OF); + SQLExpr count = expr(); + fetch.setCount(count); - for (;;) { - SQLExpr expr = this.createExprParser().expr(); - forClause.getOf().add(expr); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } + if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) { + lexer.nextToken(); + } else { + throw new ParserException("expect 'ROW' or 'ROWS'"); + } - if (lexer.token() == Token.NOWAIT) { - lexer.nextToken(); - forClause.setNoWait(true); - } - - queryBlock.setForClause(forClause); - } - - return queryRest(queryBlock); - } + if (lexer.token() == Token.ONLY) { + lexer.nextToken(); + } else { + throw new ParserException("expect 'ONLY'"); + } + + queryBlock.setFetch(fetch); + } + + if (lexer.token() == Token.FOR) { + lexer.nextToken(); + + PGSelectQueryBlock.ForClause forClause = new PGSelectQueryBlock.ForClause(); + + if (lexer.token() == Token.UPDATE) { + forClause.setOption(PGSelectQueryBlock.ForClause.Option.UPDATE); + } else if (lexer.token() == Token.SHARE) { + forClause.setOption(PGSelectQueryBlock.ForClause.Option.SHARE); + } else { + throw new ParserException("expect 'FIRST' or 'NEXT'"); + } + + accept(Token.OF); + + for (;;) { + SQLExpr expr = this.createExprParser().expr(); + forClause.getOf().add(expr); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else { + break; + } + } + + if (lexer.token() == Token.NOWAIT) { + lexer.nextToken(); + forClause.setNoWait(true); + } + + queryBlock.setForClause(forClause); + } + + return queryRest(queryBlock); + } - } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java index 47515e9871..d88a79ec49 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java @@ -45,26 +45,28 @@ public class SQLServerSelectParser extends SQLSelectParser { return queryRest(select); } - accept(Token.SELECT); - SQLServerSelectQueryBlock queryBlock = new SQLServerSelectQueryBlock(); - if (lexer.token() == Token.DISTINCT) { - queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); + if (lexer.token() == Token.SELECT) { lexer.nextToken(); - } else if (lexer.token() == Token.ALL) { - queryBlock.setDistionOption(SQLSetQuantifier.ALL); - lexer.nextToken(); - } - if (lexer.token() == Token.TOP) { - Top top = new Top(); - lexer.nextToken(); - top.setExpr(createExprParser().primary()); - queryBlock.setTop(top); - } + if (lexer.token() == Token.DISTINCT) { + queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); + lexer.nextToken(); + } else if (lexer.token() == Token.ALL) { + queryBlock.setDistionOption(SQLSetQuantifier.ALL); + lexer.nextToken(); + } - parseSelectList(queryBlock); + if (lexer.token() == Token.TOP) { + Top top = new Top(); + lexer.nextToken(); + top.setExpr(createExprParser().primary()); + queryBlock.setTop(top); + } + + parseSelectList(queryBlock); + } parseFrom(queryBlock); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 308bb729a4..b90116e289 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -189,9 +189,11 @@ public class SQLStatementParser extends SQLParser { } public SQLStatement parseInsert() { - accept(Token.INSERT); - SQLInsertStatement insertStatement = new SQLInsertStatement(); + + if (lexer.token() == Token.INSERT) { + accept(Token.INSERT); + } parseInsert0(insertStatement); return insertStatement; @@ -206,20 +208,22 @@ public class SQLStatementParser extends SQLParser { } protected void parseInsert0(SQLInsertInto insertStatement, boolean acceptSubQuery) { - accept(Token.INTO); - - SQLName tableName = this.exprParser.name(); - insertStatement.setTableName(tableName); - - if (lexer.token() == Token.LITERAL_ALIAS) { - insertStatement.setAlias(as()); - } - - parseInsert0_hinits(insertStatement); - - if (lexer.token() == Token.IDENTIFIER) { - insertStatement.setAlias(lexer.stringVal()); + if (lexer.token() == Token.INTO) { lexer.nextToken(); + + SQLName tableName = this.exprParser.name(); + insertStatement.setTableName(tableName); + + if (lexer.token() == Token.LITERAL_ALIAS) { + insertStatement.setAlias(as()); + } + + parseInsert0_hinits(insertStatement); + + if (lexer.token() == Token.IDENTIFIER) { + insertStatement.setAlias(lexer.stringVal()); + lexer.nextToken(); + } } if (lexer.token() == (Token.LPAREN)) { @@ -347,14 +351,14 @@ public class SQLStatementParser extends SQLParser { public SQLUpdateStatement parseUpdateStatement() throws ParserException { SQLUpdateStatement udpateStatement = new SQLUpdateStatement(); - + if (lexer.token() == Token.UPDATE) { lexer.nextToken(); SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); udpateStatement.setTableSource(tableSource); } - + accept(Token.SET); for (;;) { @@ -382,15 +386,18 @@ public class SQLStatementParser extends SQLParser { } public SQLDeleteStatement parseDeleteStatement() throws ParserException { - lexer.nextToken(); - if (lexer.token() == (Token.FROM)) { - lexer.nextToken(); - } - - SQLName tableName = exprParser.name(); - SQLDeleteStatement deleteStatement = new SQLDeleteStatement(); - deleteStatement.setTableName(tableName); + + if (lexer.token() == Token.DELETE) { + lexer.nextToken(); + if (lexer.token() == (Token.FROM)) { + lexer.nextToken(); + } + + SQLName tableName = exprParser.name(); + + deleteStatement.setTableName(tableName); + } if (lexer.token() == (Token.WHERE)) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 49d7181a1a..128e4deb42 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -681,7 +681,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { if (x.getValues() != null) { println(); - print("VALUES "); + print("VALUES"); + println(); x.getValues().accept(this); } else { if (x.getQuery() != null) { diff --git a/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorOracleTest.java b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorOracleTest.java index 1c5f563dcb..aea1ffa7b9 100644 --- a/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorOracleTest.java +++ b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorOracleTest.java @@ -41,5 +41,15 @@ public class MappingVisitorOracleTest extends TestCase { Assert.assertEquals("DELETE FROM device\nWHERE ip = '127.0.0.1'", engine.explainToDeleteSQL("WHERE IP地址 = '127.0.0.1'")); } + + public void test_update() throws Exception { + Assert.assertEquals("UPDATE device\nSET serviceTag = ?\nWHERE ip = '127.0.0.1'", + engine.explainToUpdateSQL("SET 编号 = ? WHERE IP地址 = '127.0.0.1'")); + } + + public void test_insert() throws Exception { + Assert.assertEquals("INSERT INTO device\n\t(serviceTag, ip)\nVALUES\n(?, ?)", + engine.explainToInsertSQL("(编号, IP地址) VALUES (?, ?)")); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorTest.java index ebd8b58a6f..9adf5ca50f 100644 --- a/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorTest.java @@ -46,7 +46,7 @@ public class MappingVisitorTest extends TestCase { } public void test_insert() throws Exception { - Assert.assertEquals("INSERT INTO device\n(serviceTag, ip)\nVALUES\n(?, ?)", + Assert.assertEquals("INSERT INTO device\n\t(serviceTag, ip)\nVALUES\n(?, ?)", engine.explainToInsertSQL("(编号, IP地址) VALUES (?, ?)")); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/AssignmentOperatorsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/AssignmentOperatorsTest.java index c53505f9e8..1367de51d4 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/AssignmentOperatorsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/AssignmentOperatorsTest.java @@ -79,7 +79,7 @@ public class AssignmentOperatorsTest extends TestCase { String text = output(stmtList); - Assert.assertEquals("UPDATE t1 SET c1 = 2 WHERE c1 = (@var1 := 1);", text); + Assert.assertEquals("UPDATE t1\nSET c1 = 2\nWHERE c1 = (@var1 := 1);", text); } private String output(List stmtList) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MiscellaneousFunctionsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MiscellaneousFunctionsTest.java index 23ab6704e1..8c0e46946d 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MiscellaneousFunctionsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MiscellaneousFunctionsTest.java @@ -35,7 +35,7 @@ public class MiscellaneousFunctionsTest extends TestCase { String text = output(stmtList); - Assert.assertEquals("UPDATE t SET i = DEFAULT(i) + 1 WHERE id < 100;", text); + Assert.assertEquals("UPDATE t\nSET i = DEFAULT(i) + 1\nWHERE id < 100;", text); } public void test_1() throws Exception { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java index f686a83052..d0a061e3cd 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java @@ -14,19 +14,19 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVis public class MySqlParameterizedOutputVisitorTest extends TestCase { public void test_0() throws Exception { - validate("SELECT * FROM T WHERE ID IN (?, ?, ?)", "SELECT * FROM T WHERE ID IN (?)"); - validate("SELECT * FROM T WHERE ID = 5", "SELECT * FROM T WHERE ID = ?"); - validate("SELECT * FROM T WHERE 1 = 0 AND ID = 5", "SELECT * FROM T WHERE 1 = 0 AND ID = ?"); - validate("SELECT * FROM T WHERE ID = ? OR ID = ?", "SELECT * FROM T WHERE ID = ?"); - validate("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT * FROM T WHERE A.ID = ?"); + validate("SELECT * FROM T WHERE ID IN (?, ?, ?)", "SELECT *\nFROM T\nWHERE ID IN (?)"); + validate("SELECT * FROM T WHERE ID = 5", "SELECT *\nFROM T\nWHERE ID = ?"); + validate("SELECT * FROM T WHERE 1 = 0 AND ID = 5", "SELECT *\nFROM T\nWHERE 1 = 0\nAND ID = ?"); + validate("SELECT * FROM T WHERE ID = ? OR ID = ?", "SELECT *\nFROM T\nWHERE ID = ?"); + validate("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT *\nFROM T\nWHERE A.ID = ?"); validate("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", - "SELECT * FROM T WHERE 1 = 0 OR a.id = ?"); + "SELECT *\nFROM T\nWHERE 1 = 0\nOR a.id = ?"); validateOracle("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", - "SELECT * FROM T WHERE 1 = 0 OR a.id = ?; "); - validateOracle("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT * FROM T WHERE A.ID = ?; "); + "SELECT *\nFROM T\nWHERE 1 = 0\nOR a.id = ?"); + validateOracle("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT *\nFROM T\nWHERE A.ID = ?"); validate("INSERT INTO T (F1, F2) VALUES(?, ?), (?, ?), (?, ?)", "INSERT INTO T (F1, F2) VALUES (?, ?)"); validate("update net_device d, sys_user u set d.resp_user_id=u.id where d.resp_user_login_name=u.username and d.id in (42354)", // - "UPDATE net_device d, sys_user u SET d.resp_user_id = u.id WHERE d.resp_user_login_name = u.username AND d.id IN (?)"); + "UPDATE net_device d, sys_user u\nSET d.resp_user_id = u.id\nWHERE d.resp_user_login_name = u.username\nAND d.id IN (?)"); // System.out.println("SELECT * FORM A WHERE ID = (##)".replaceAll("##", "?")); } @@ -55,7 +55,7 @@ public class MySqlParameterizedOutputVisitorTest extends TestCase { Assert.assertEquals(1, statementList.size()); StringBuilder out = new StringBuilder(); - OracleParameterizedOutputVisitor visitor = new OracleParameterizedOutputVisitor(out); + OracleParameterizedOutputVisitor visitor = new OracleParameterizedOutputVisitor(out, false); statemen.accept(visitor); Assert.assertEquals(expect, out.toString()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest2.java index e2a2723922..cf9eac1a7f 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest2.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest2.java @@ -19,8 +19,8 @@ public class MySqlParameterizedOutputVisitorTest2 extends TestCase { sql += " OR ID = ?"; } - validate(sql, "SELECT * FROM T WHERE ID = ?"); - validateOracle(sql, "SELECT * FROM T WHERE ID = ?; "); + validate(sql, "SELECT *\nFROM T\nWHERE ID = ?"); + validateOracle(sql, "SELECT *\nFROM T\nWHERE ID = ?"); } void validate(String sql, String expect) { @@ -47,7 +47,7 @@ public class MySqlParameterizedOutputVisitorTest2 extends TestCase { Assert.assertEquals(1, statementList.size()); StringBuilder out = new StringBuilder(); - OracleParameterizedOutputVisitor visitor = new OracleParameterizedOutputVisitor(out); + OracleParameterizedOutputVisitor visitor = new OracleParameterizedOutputVisitor(out, false); statemen.accept(visitor); Assert.assertEquals(expect, out.toString()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringFunctionsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringFunctionsTest.java index ff59add0fb..aa9b964faa 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringFunctionsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringFunctionsTest.java @@ -321,7 +321,7 @@ public class StringFunctionsTest extends TestCase { String text = output(stmtList); - Assert.assertEquals("UPDATE t SET blob_col = LOAD_FILE('/tmp/picture') WHERE id = 1;", text); + Assert.assertEquals("UPDATE t\nSET blob_col = LOAD_FILE('/tmp/picture')\nWHERE id = 1;", text); } public void test_27() throws Exception { diff --git a/src/test/resources/bvt/parser/mysql-10.txt b/src/test/resources/bvt/parser/mysql-10.txt index 6fc7badcea..7dd485e3c7 100644 --- a/src/test/resources/bvt/parser/mysql-10.txt +++ b/src/test/resources/bvt/parser/mysql-10.txt @@ -1,5 +1,9 @@ UPDATE AVATAR_CASE SET GMT_MODIFIED=sysdate,STATUS = ?,SYS_DECISION = ?,MANUAL_DECISION = ?,OPERATOR=? , MEMO = ? where id in ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) --------------------------- -UPDATE AVATAR_CASE SET GMT_MODIFIED = sysdate, STATUS = ?, SYS_DECISION = ?, MANUAL_DECISION = ?, OPERATOR = ?, MEMO = ? WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) +UPDATE AVATAR_CASE +SET GMT_MODIFIED = sysdate, STATUS = ?, SYS_DECISION = ?, MANUAL_DECISION = ?, OPERATOR = ?, MEMO = ? +WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) --------------------------- -UPDATE AVATAR_CASE SET GMT_MODIFIED = sysdate, STATUS = ?, SYS_DECISION = ?, MANUAL_DECISION = ?, OPERATOR = ?, MEMO = ? WHERE id IN (?) +UPDATE AVATAR_CASE +SET GMT_MODIFIED = sysdate, STATUS = ?, SYS_DECISION = ?, MANUAL_DECISION = ?, OPERATOR = ?, MEMO = ? +WHERE id IN (?) diff --git a/src/test/resources/bvt/parser/mysql-9.txt b/src/test/resources/bvt/parser/mysql-9.txt index dd191c94e5..56a1cd5db8 100644 --- a/src/test/resources/bvt/parser/mysql-9.txt +++ b/src/test/resources/bvt/parser/mysql-9.txt @@ -96,4 +96,12 @@ WHERE 1 = 0 ORDER BY lastChangeTimeOfAlarmRule DESC LIMIT ?, ? --------------------------- -SELECT a.id AS "appId", a.name AS "appName", b.number AS "instanceNumber", b.hostname AS "hostname", c.name AS "monitorItemName" , d.id AS "alarmRuleStatusId", d.name AS "alarmRuleName", d.current_status AS "alarmRuleStatus", d.last_change_time AS "lastChangeTimeOfAlarmRule" FROM mi_alarm_rule_status d LEFT JOIN monitor_item_status c ON d.mi_status_id = c.id LEFT JOIN instance b ON b.number = c.inst_num AND b.app_num = c.app_num AND b.hostname = c.hostname LEFT JOIN app a ON a.number = b.app_num WHERE 1 = 0 OR a.id = ? ORDER BY lastChangeTimeOfAlarmRule DESC LIMIT ?, ? +SELECT a.id AS "appId", a.name AS "appName", b.number AS "instanceNumber", b.hostname AS "hostname", c.name AS "monitorItemName" + , d.id AS "alarmRuleStatusId", d.name AS "alarmRuleName", d.current_status AS "alarmRuleStatus", d.last_change_time AS "lastChangeTimeOfAlarmRule" +FROM mi_alarm_rule_status d LEFT JOIN monitor_item_status c ON d.mi_status_id = c.id LEFT JOIN instance b ON b.number = c.inst_num +AND b.app_num = c.app_num +AND b.hostname = c.hostname LEFT JOIN app a ON a.number = b.app_num +WHERE 1 = 0 +OR a.id = ? +ORDER BY lastChangeTimeOfAlarmRule DESC +LIMIT ?, ?