diff --git a/src/main/java/com/alibaba/druid/mapping/MappingEngine.java b/src/main/java/com/alibaba/druid/mapping/MappingEngine.java index 7bb53b783f..c5399790e7 100644 --- a/src/main/java/com/alibaba/druid/mapping/MappingEngine.java +++ b/src/main/java/com/alibaba/druid/mapping/MappingEngine.java @@ -5,6 +5,8 @@ import java.util.LinkedHashMap; import com.alibaba.druid.mapping.spi.MappingProvider; import com.alibaba.druid.mapping.spi.MappingVisitor; import com.alibaba.druid.mapping.spi.MySqlMappingProvider; +import com.alibaba.druid.sql.ast.SQLObject; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -55,9 +57,25 @@ public class MappingEngine { query.accept(this.createMappingVisitor()); + return toSQL(query); + } + + public SQLDeleteStatement explainToDeleteSQLObject(String sql) { + return provider.explainToDeleteSQLObject(this, sql); + } + + public String explainToDeleteSQLObjectSQL(String sql) { + SQLDeleteStatement query = explainToDeleteSQLObject(sql); + + query.accept(this.createMappingVisitor()); + + return toSQL(query); + } + + public String toSQL(SQLObject sqlObject) { StringBuilder out = new StringBuilder(); SQLASTOutputVisitor outputVisitor = createOutputVisitor(out); - query.accept(outputVisitor); + sqlObject.accept(outputVisitor); return out.toString(); } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java index 65361d06df..904b041560 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java @@ -2,10 +2,13 @@ package com.alibaba.druid.mapping.spi; import com.alibaba.druid.mapping.MappingEngine; import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; +import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerSelectParser; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -13,7 +16,7 @@ public class MSSQLServerMappingProvider implements MappingProvider { @Override public MappingVisitor createMappingVisitor(MappingEngine engine) { - return new MySqlMappingVisitor(engine.getEntities()); + return new MSSQLServerMappingVisitor(engine.getEntities()); } @Override @@ -33,7 +36,7 @@ public class MSSQLServerMappingProvider implements MappingProvider { top.setExpr(new SQLNumberExpr(maxLimit)); query.setTop(top); } else { - SQLNumberExpr rowCountExpr = (SQLNumberExpr) query.getTop().getExpr(); + SQLNumericLiteralExpr rowCountExpr = (SQLNumericLiteralExpr) query.getTop().getExpr(); int rowCount = rowCountExpr.getNumber().intValue(); if (rowCount > maxLimit.intValue()) { rowCountExpr.setNumber(maxLimit); @@ -43,4 +46,9 @@ public class MSSQLServerMappingProvider implements MappingProvider { return query; } + + public SQLDeleteStatement explainToDeleteSQLObject(MappingEngine engine, String sql) { + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + return parser.parseDeleteStatement(); + } } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MappingProvider.java b/src/main/java/com/alibaba/druid/mapping/spi/MappingProvider.java index 3aa78072ac..380f438ba7 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MappingProvider.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MappingProvider.java @@ -1,6 +1,7 @@ package com.alibaba.druid.mapping.spi; import com.alibaba.druid.mapping.MappingEngine; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -11,4 +12,6 @@ public interface MappingProvider { SQLASTOutputVisitor createOutputVisitor(MappingEngine engine, Appendable out); SQLSelectQueryBlock explainToSelectSQLObject(MappingEngine engine, String sql); + + SQLDeleteStatement explainToDeleteSQLObject(MappingEngine engine, String sql); } 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 324779e2d0..92db029e86 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingProvider.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingProvider.java @@ -1,11 +1,14 @@ package com.alibaba.druid.mapping.spi; import com.alibaba.druid.mapping.MappingEngine; -import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; +import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlSelectParser; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -20,7 +23,7 @@ public class MySqlMappingProvider implements MappingProvider { public SQLASTOutputVisitor createOutputVisitor(MappingEngine engine, Appendable out) { return new MySqlOutputVisitor(out); } - + public SQLSelectQueryBlock explainToSelectSQLObject(MappingEngine engine, String sql) { MySqlSelectParser selectParser = new MySqlSelectParser(sql); MySqlSelectQueryBlock query = (MySqlSelectQueryBlock) selectParser.query(); @@ -30,10 +33,10 @@ public class MySqlMappingProvider implements MappingProvider { if (maxLimit != null) { if (query.getLimit() == null) { Limit limit = new Limit(); - limit.setRowCount(new SQLNumberExpr(maxLimit)); + limit.setRowCount(new SQLIntegerExpr(maxLimit)); query.setLimit(limit); } else { - SQLNumberExpr rowCountExpr = (SQLNumberExpr) query.getLimit().getRowCount(); + SQLNumericLiteralExpr rowCountExpr = (SQLNumericLiteralExpr) query.getLimit().getRowCount(); int rowCount = rowCountExpr.getNumber().intValue(); if (rowCount > maxLimit.intValue()) { rowCountExpr.setNumber(maxLimit); @@ -43,4 +46,9 @@ public class MySqlMappingProvider implements MappingProvider { return query; } + + public MySqlDeleteStatement explainToDeleteSQLObject(MappingEngine engine, String sql) { + MySqlStatementParser parser = new MySqlStatementParser(sql); + return parser.parseDeleteStatement(); + } } 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 5ee4557115..bd4850657b 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingProvider.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingProvider.java @@ -2,8 +2,10 @@ package com.alibaba.druid.mapping.spi; import com.alibaba.druid.mapping.MappingEngine; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.parser.OracleSelectParser; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -26,4 +28,8 @@ public class OracleMappingProvider implements MappingProvider { return query; } + public OracleDeleteStatement explainToDeleteSQLObject(MappingEngine engine, String sql) { + OracleStatementParser parser = new OracleStatementParser(sql); + return parser.parseDeleteStatement(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java index d688d499d0..420aebcd27 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java @@ -24,4 +24,6 @@ public abstract class SQLNumericLiteralExpr extends SQLLiteralExpr { } public abstract Number getNumber(); + + public abstract void setNumber(Number number); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index e086be60b9..5937075e72 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -26,7 +26,6 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; -import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; @@ -87,7 +86,7 @@ public class MySqlStatementParser extends SQLStatementParser { return new SQLSelectStatement(new MySqlSelectParser(lexer).select()); } - public SQLDeleteStatement parseDeleteStatement() throws ParserException { + public MySqlDeleteStatement parseDeleteStatement() throws ParserException { accept(Token.DELETE); MySqlDeleteStatement deleteStatement = new MySqlDeleteStatement(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java index 88e16a7b0a..376b9c004d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java @@ -72,4 +72,14 @@ public class OracleBinaryDoubleExpr extends SQLNumericLiteralExpr implements Ora return true; } + @Override + public void setNumber(Number number) { + if (number == null) { + this.setValue(null); + return; + } + + this.setValue(number.doubleValue()); + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java index d548e6e3b4..c5a0a1782f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java @@ -72,4 +72,14 @@ public class OracleBinaryFloatExpr extends SQLNumericLiteralExpr implements Orac return true; } + @Override + public void setNumber(Number number) { + if (number == null) { + this.setValue(null); + return; + } + + this.setValue(number.floatValue()); + } + } 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 5b459fb69e..7591bd87b5 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 @@ -176,7 +176,7 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == (Token.DELETE)) { - statementList.add(parseDelete()); + statementList.add(parseDeleteStatement()); continue; } @@ -1413,7 +1413,7 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } - public OracleDeleteStatement parseDelete() throws ParserException { + public OracleDeleteStatement parseDeleteStatement() throws ParserException { accept(Token.DELETE); OracleDeleteStatement deleteStatement = new OracleDeleteStatement(); diff --git a/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorSQLServerTest.java b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorSQLServerTest.java new file mode 100644 index 0000000000..80f4c8cfe6 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorSQLServerTest.java @@ -0,0 +1,49 @@ +package com.alibaba.druid.bvt.mapping; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.mapping.Entity; +import com.alibaba.druid.mapping.MappingEngine; +import com.alibaba.druid.mapping.Property; +import com.alibaba.druid.mapping.spi.MSSQLServerMappingProvider; + +public class MappingVisitorSQLServerTest extends TestCase { + + MappingEngine engine = new MappingEngine(new MSSQLServerMappingProvider()); + + protected void setUp() throws Exception { + Entity entity = new Entity(); + entity.setName("设备"); + entity.setDescription("Device"); + entity.setTableName("device"); + + entity.addProperty(new Property("编号", "", "serviceTag")); + entity.addProperty(new Property("IP地址", "", "ip")); + + engine.addEntity(entity); + } + + public void test_0() throws Exception { + + Assert.assertEquals("SELECT serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device", engine.explainToSelectSQL("select *")); + Assert.assertEquals("SELECT serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device\nWHERE ip = '127.0.0.1'", + engine.explainToSelectSQL("select 编号, IP地址 WHERE IP地址 = '127.0.0.1'")); + + } + + public void test_1() throws Exception { + engine.setMaxLimit(10); + + Assert.assertEquals("SELECT TOP 10 serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device", engine.explainToSelectSQL("select *")); + Assert.assertEquals("SELECT TOP 10 serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device\nWHERE ip = '127.0.0.1'", + engine.explainToSelectSQL("select 编号, IP地址 WHERE IP地址 = '127.0.0.1'")); + + Assert.assertEquals("SELECT TOP 3 serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device\nWHERE ip = '127.0.0.1'", + engine.explainToSelectSQL("select top 3 编号, IP地址 WHERE IP地址 = '127.0.0.1'")); + + engine.setMaxLimit(null); + + } +} 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 0523b464c2..4c6a7bd368 100644 --- a/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/mapping/MappingVisitorTest.java @@ -38,6 +38,8 @@ public class MappingVisitorTest extends TestCase { Assert.assertEquals("SELECT serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device\nLIMIT 10", engine.explainToSelectSQL("select *")); Assert.assertEquals("SELECT serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device\nWHERE ip = '127.0.0.1'\nLIMIT 10", engine.explainToSelectSQL("select 编号, IP地址 WHERE IP地址 = '127.0.0.1'")); + Assert.assertEquals("SELECT serviceTag AS \"编号\", ip AS \"IP地址\"\nFROM device\nWHERE ip = '127.0.0.1'\nLIMIT 3", + engine.explainToSelectSQL("select 编号, IP地址 WHERE IP地址 = '127.0.0.1' limit 3")); engine.setMaxLimit(null);