diff --git a/src/main/java/com/alibaba/druid/mapping/MappingEngine.java b/src/main/java/com/alibaba/druid/mapping/MappingEngine.java index f142091a8e..debea1322e 100644 --- a/src/main/java/com/alibaba/druid/mapping/MappingEngine.java +++ b/src/main/java/com/alibaba/druid/mapping/MappingEngine.java @@ -4,6 +4,7 @@ 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.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -11,7 +12,15 @@ public class MappingEngine { private LinkedHashMap entities = new LinkedHashMap(); private Integer maxLimit; - private MappingProvider provider; + private final MappingProvider provider; + + public MappingEngine(){ + this(new MySqlMappingProvider()); + } + + public MappingEngine(MappingProvider provider){ + this.provider = provider; + } public Integer getMaxLimit() { return maxLimit; @@ -36,7 +45,7 @@ public class MappingEngine { public SQLASTOutputVisitor createOutputVisitor(Appendable out) { return provider.createOutputVisitor(this, out); } - + public SQLSelectQueryBlock explainToSQLObject(String sql) { return provider.explainToSQLObject(this, sql); } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java new file mode 100644 index 0000000000..af23b0b63c --- /dev/null +++ b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingProvider.java @@ -0,0 +1,46 @@ +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.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.visitor.SQLServerOutputVisitor; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; + +public class MSSQLServerMappingProvider implements MappingProvider { + + @Override + public MappingVisitor createMappingVisitor(MappingEngine engine) { + return new MySqlMappingVisitor(engine.getEntities()); + } + + @Override + public SQLASTOutputVisitor createOutputVisitor(MappingEngine engine, Appendable out) { + return new SQLServerOutputVisitor(out); + } + + public SQLSelectQueryBlock explainToSQLObject(MappingEngine engine, String sql) { + SQLServerSelectParser selectParser = new SQLServerSelectParser(sql); + SQLServerSelectQueryBlock query = (SQLServerSelectQueryBlock) selectParser.query(); + + Integer maxLimit = engine.getMaxLimit(); + + if (maxLimit != null) { + if (query.getTop() == null) { + Top top = new Top(); + top.setExpr(new SQLNumberExpr(maxLimit)); + query.setTop(top); + } else { + SQLNumberExpr rowCountExpr = (SQLNumberExpr) query.getTop().getExpr(); + int rowCount = rowCountExpr.getNumber().intValue(); + if (rowCount > maxLimit.intValue()) { + rowCountExpr.setNumber(maxLimit); + } + } + } + + return query; + } +} diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java new file mode 100644 index 0000000000..0e676e9e81 --- /dev/null +++ b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java @@ -0,0 +1,84 @@ +package com.alibaba.druid.mapping.spi; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.alibaba.druid.mapping.Entity; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLSelectItem; +import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter; + +public class MSSQLServerMappingVisitor extends SQLServerASTVisitorAdapter implements MappingVisitor { + + private final LinkedHashMap entities; + private final Map tableSources = new LinkedHashMap(); + + public MSSQLServerMappingVisitor(LinkedHashMap entities){ + super(); + this.entities = entities; + } + + public LinkedHashMap getEntities() { + return entities; + } + + public Map getTableSources() { + return tableSources; + } + + @Override + public Entity getFirstEntity() { + for (Map.Entry entry : entities.entrySet()) { + return entry.getValue(); + } + + return null; + } + + public Entity getEntity(String name) { + return MappingVisitorUtils.getEntity(this, name); + } + + @Override + public boolean visit(SQLSelectItem x) { + x.getExpr().setParent(x); + return true; + } + + @Override + public boolean visit(SQLServerSelectQueryBlock x) { + return MappingVisitorUtils.visit(this, x); + } + + @Override + public boolean visit(SQLSelectQueryBlock x) { + return MappingVisitorUtils.visit(this, x); + } + + @Override + public boolean visit(SQLIdentifierExpr x) { + return MappingVisitorUtils.visit(this, x); + } + + @Override + public boolean visit(SQLSubqueryTableSource x) { + return MappingVisitorUtils.visit(this, x); + } + + @Override + public boolean visit(SQLJoinTableSource x) { + return MappingVisitorUtils.visit(this, x); + } + + @Override + public boolean visit(SQLExprTableSource x) { + return MappingVisitorUtils.visit(this, x); + } + +} 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 12a9a3aa69..b5d8829e7f 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitorUtils.java @@ -1,5 +1,7 @@ package com.alibaba.druid.mapping.spi; +import java.util.Map; + import com.alibaba.druid.mapping.DruidMappingException; import com.alibaba.druid.mapping.Entity; import com.alibaba.druid.mapping.Property; @@ -12,6 +14,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; public class MappingVisitorUtils { + public static boolean visit(MappingVisitor visitor, SQLExprTableSource x) { SQLExpr expr = x.getExpr(); @@ -34,12 +37,12 @@ public class MappingVisitorUtils { return false; } - + public static boolean visit(MappingVisitor visitor, SQLTableSource x) { if (x.getAlias() != null) { visitor.getTableSources().put(x.getAlias(), x); } - + return true; } @@ -103,4 +106,19 @@ public class MappingVisitorUtils { return true; } + + public static Entity getEntity(MappingVisitor visitor, String name) { + Entity entity = visitor.getEntities().get(name); + + if (entity == null) { + for (Map.Entry entry : visitor.getEntities().entrySet()) { + if (entry.getKey().equalsIgnoreCase(name)) { + entity = entry.getValue(); + break; + } + } + } + + return entity; + } } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingVisitor.java b/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingVisitor.java index 50d8907e06..765f61f2b1 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingVisitor.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingVisitor.java @@ -40,49 +40,41 @@ public class MySqlMappingVisitor extends MySqlASTVisitorAdapter implements Mappi } public Entity getEntity(String name) { - Entity entity = this.entities.get(name); - - if (entity == null) { - for (Map.Entry entry : entities.entrySet()) { - if (entry.getKey().equalsIgnoreCase(name)) { - entity = entry.getValue(); - break; - } - } - } - - return entity; + return MappingVisitorUtils.getEntity(this, name); } + @Override public boolean visit(SQLSelectItem x) { x.getExpr().setParent(x); return true; } + @Override public boolean visit(MySqlSelectQueryBlock x) { return MappingVisitorUtils.visit(this, x); } + @Override public boolean visit(SQLSelectQueryBlock x) { return MappingVisitorUtils.visit(this, x); } - protected void fillSelectList(SQLSelectQueryBlock x) { - MappingVisitorUtils.fillSelectList(this, x); - } - + @Override public boolean visit(SQLIdentifierExpr x) { return MappingVisitorUtils.visit(this, x); } + @Override public boolean visit(SQLSubqueryTableSource x) { return MappingVisitorUtils.visit(this, x); } + @Override public boolean visit(SQLJoinTableSource x) { return MappingVisitorUtils.visit(this, x); } + @Override public boolean visit(SQLExprTableSource x) { return MappingVisitorUtils.visit(this, x); } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingVisitor.java b/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingVisitor.java index 15781bf69f..74ef2ab442 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingVisitor.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingVisitor.java @@ -16,79 +16,73 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVIsitorAdapter; public class OracleMappingVisitor extends OracleASTVIsitorAdapter implements MappingVisitor { - private final LinkedHashMap entities; - private final Map tableSources = new LinkedHashMap(); - public OracleMappingVisitor(LinkedHashMap entities) { - super(); - this.entities = entities; - } + private final LinkedHashMap entities; + private final Map tableSources = new LinkedHashMap(); - public LinkedHashMap getEntities() { - return entities; - } + public OracleMappingVisitor(LinkedHashMap entities){ + super(); + this.entities = entities; + } - public Map getTableSources() { - return tableSources; - } + public LinkedHashMap getEntities() { + return entities; + } - public Entity getFirstEntity() { - for (Map.Entry entry : entities.entrySet()) { - return entry.getValue(); - } + public Map getTableSources() { + return tableSources; + } - return null; - } - - public Entity getEntity(String name) { - Entity entity = this.entities.get(name); + public Entity getFirstEntity() { + for (Map.Entry entry : entities.entrySet()) { + return entry.getValue(); + } - if (entity == null) { - for (Map.Entry entry : entities.entrySet()) { - if (entry.getKey().equalsIgnoreCase(name)) { - entity = entry.getValue(); - break; - } - } - } + return null; + } - return entity; - } - - public boolean visit(SQLSelectItem x) { - x.getExpr().setParent(x); - return true; - } + public Entity getEntity(String name) { + return MappingVisitorUtils.getEntity(this, name); + } - public boolean visit(OracleSelectQueryBlock x) { - return MappingVisitorUtils.visit(this, x); - } + @Override + public boolean visit(SQLSelectItem x) { + x.getExpr().setParent(x); + return true; + } - public boolean visit(SQLSelectQueryBlock x) { - return MappingVisitorUtils.visit(this, x); - } + @Override + public boolean visit(OracleSelectQueryBlock x) { + return MappingVisitorUtils.visit(this, x); + } - protected void fillSelectList(SQLSelectQueryBlock x) { - MappingVisitorUtils.fillSelectList(this, x); - } + @Override + public boolean visit(SQLSelectQueryBlock x) { + return MappingVisitorUtils.visit(this, x); + } - public boolean visit(SQLIdentifierExpr x) { - return MappingVisitorUtils.visit(this, x); - } + @Override + public boolean visit(SQLIdentifierExpr x) { + return MappingVisitorUtils.visit(this, x); + } - public boolean visit(SQLSubqueryTableSource x) { - return MappingVisitorUtils.visit(this, x); - } + @Override + public boolean visit(SQLSubqueryTableSource x) { + return MappingVisitorUtils.visit(this, x); + } - public boolean visit(SQLJoinTableSource x) { - return MappingVisitorUtils.visit(this, x); - } + @Override + public boolean visit(SQLJoinTableSource x) { + return MappingVisitorUtils.visit(this, x); + } - public boolean visit(SQLExprTableSource x) { - return MappingVisitorUtils.visit(this, x); - } - - public boolean visit(OracleSelectTableReference x) { - return MappingVisitorUtils.visit(this, x); - } + @Override + public boolean visit(SQLExprTableSource x) { + return MappingVisitorUtils.visit(this, x); + } + + @Override + public boolean visit(OracleSelectTableReference x) { + return MappingVisitorUtils.visit(this, x); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java new file mode 100644 index 0000000000..9eff67f70d --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java @@ -0,0 +1,29 @@ +package com.alibaba.druid.sql.dialect.sqlserver.visitor; + +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; +import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; +import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; + +public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements SQLServerASTVisitor { + + @Override + public boolean visit(SQLServerSelectQueryBlock x) { + return true; + } + + @Override + public void endVisit(SQLServerSelectQueryBlock x) { + + } + + @Override + public boolean visit(Top x) { + return true; + } + + @Override + public void endVisit(Top x) { + + } + +}