From bb0a557b81dc0e0cdd7a36bcd8b164672f57de3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Tue, 8 May 2012 19:32:39 +0800 Subject: [PATCH] bug fixed for mapping --- .../alibaba/druid/mapping/MappingEngine.java | 4 + .../spi/MSSQLServerMappingVisitor.java | 19 +++- .../druid/mapping/spi/MappingVisitor.java | 5 + .../mapping/spi/MappingVisitorUtils.java | 93 +++++++++++++++++-- .../mapping/spi/MySqlMappingVisitor.java | 14 ++- .../mapping/spi/OracleMappingVisitor.java | 14 ++- .../bvt/mapping/MySqlMappingShardingTest.java | 88 ++++++++++++++---- 7 files changed, 204 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/alibaba/druid/mapping/MappingEngine.java b/src/main/java/com/alibaba/druid/mapping/MappingEngine.java index 5a87922249..01225e168e 100644 --- a/src/main/java/com/alibaba/druid/mapping/MappingEngine.java +++ b/src/main/java/com/alibaba/druid/mapping/MappingEngine.java @@ -98,6 +98,7 @@ public class MappingEngine { MappingVisitor visitor = this.createMappingVisitor(parameters); query.accept(visitor); + visitor.afterResolve(); afterResole(visitor); return toSQL(query); @@ -116,6 +117,7 @@ public class MappingEngine { MappingVisitor visitor = this.createMappingVisitor(Collections.emptyList()); stmt.accept(visitor); + visitor.afterResolve(); afterResole(visitor); return toSQL(stmt); @@ -138,6 +140,7 @@ public class MappingEngine { MappingVisitor visitor = this.createMappingVisitor(Collections.emptyList()); stmt.accept(visitor); + visitor.afterResolve(); afterResole(visitor); return toSQL(stmt); @@ -152,6 +155,7 @@ public class MappingEngine { MappingVisitor visitor = this.createMappingVisitor(Collections.emptyList()); stmt.accept(visitor); + visitor.afterResolve(); afterResole(visitor); return toSQL(stmt); diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java index c93bb4fecd..9b9d7a75d3 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MSSQLServerMappingVisitor.java @@ -9,6 +9,7 @@ import java.util.Map; 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.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; @@ -30,6 +31,7 @@ public class MSSQLServerMappingVisitor extends SQLServerASTVisitorAdapter implem private final List parameters; private final List propertyValues = new ArrayList(); private int variantIndex = 0; + private final List unresolveList = new ArrayList(); public MSSQLServerMappingVisitor(MappingEngine engine){ this(engine, Collections.emptyList()); @@ -81,8 +83,7 @@ public class MSSQLServerMappingVisitor extends SQLServerASTVisitorAdapter implem @Override public boolean visit(SQLSelectItem x) { - x.getExpr().setParent(x); - return true; + return MappingVisitorUtils.visit(this, x); } @Override @@ -129,13 +130,23 @@ public class MSSQLServerMappingVisitor extends SQLServerASTVisitorAdapter implem public boolean visit(SQLExprTableSource x) { return MappingVisitorUtils.visit(this, x); } - + @Override public int getAndIncrementVariantIndex() { return variantIndex++; } - + public int getVariantIndex() { return variantIndex; } + + public List getUnresolveList() { + return unresolveList; + } + + @Override + public void afterResolve() { + MappingVisitorUtils.afterResolve(this); + } + } diff --git a/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitor.java b/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitor.java index 8061e781fb..b5764e398f 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitor.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MappingVisitor.java @@ -6,6 +6,7 @@ import java.util.Map; 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.statement.SQLTableSource; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -29,4 +30,8 @@ public interface MappingVisitor extends SQLASTVisitor { List getPropertyValues(); int getAndIncrementVariantIndex(); + + List getUnresolveList(); + + void afterResolve(); } 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 61f6d9a6da..8f9794387c 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,6 @@ package com.alibaba.druid.mapping.spi; +import java.util.Iterator; import java.util.Map; import com.alibaba.druid.mapping.DruidMappingException; @@ -74,6 +75,11 @@ public class MappingVisitorUtils { Property property = null; Entity entity = visitor.getEntity(ownerName); + + if (entity == null) { + visitor.getUnresolveList().add(x); + return false; + } property = entity.getProperty(propertyName); if (property == null) { @@ -100,16 +106,21 @@ public class MappingVisitorUtils { Property property = null; Entity propertyEntity = null; - for (Entity entity : visitor.getEntities().values()) { - property = entity.getProperty(propertyName); - if (property != null) { - propertyEntity = entity; - break; + + for (SQLTableSource tableSource : visitor.getTableSources().values()) { + Entity entity = (Entity) tableSource.getAttribute("mapping.entity"); + if (entity != null) { + property = entity.getProperty(propertyName); + if (property != null) { + propertyEntity = entity; + break; + } } } if (property == null) { - throw new DruidMappingException("property not found : " + propertyName); + visitor.getUnresolveList().add(x); + return false; } String dbColumName = visitor.resovleColumnName(propertyEntity, property); @@ -128,6 +139,11 @@ public class MappingVisitorUtils { return false; } + public static boolean visit(MappingVisitor visitor, SQLSelectItem x) { + x.getExpr().setParent(x); + return true; + } + public static boolean visit(MappingVisitor visitor, SQLBinaryOpExpr x) { if (x.getOperator() == SQLBinaryOperator.Equality) { if (x.getLeft() instanceof SQLIdentifierExpr && isSimpleValue(visitor, x.getRight())) { @@ -190,6 +206,71 @@ public class MappingVisitorUtils { return false; } + public static void afterResolve(MappingVisitor visitor) { + for (Iterator iter = visitor.getUnresolveList().iterator();iter.hasNext();) { + SQLExpr expr = iter.next(); + if (expr instanceof SQLIdentifierExpr) { + if (resolve(visitor, (SQLIdentifierExpr) expr)) { + iter.remove(); + } + } else if (expr instanceof SQLPropertyExpr) { + if (resolve(visitor, (SQLPropertyExpr) expr)) { + iter.remove(); + } + } + } + } + + public static boolean resolve(MappingVisitor visitor, SQLIdentifierExpr x) { + String propertyName = x.getName(); + + for (SQLTableSource tableSource : visitor.getTableSources().values()) { + Entity entity = (Entity) tableSource.getAttribute("mapping.entity"); + if (entity != null) { + Property property = entity.getProperty(propertyName); + if (property != null) { + String columnName = visitor.resovleColumnName(entity, property); + x.setName(columnName); + + x.putAttribute("mapping.entity", entity); + x.putAttribute("mapping.property", property); + return true; + } + } + } + + return false; + } + + public static boolean resolve(MappingVisitor visitor, SQLPropertyExpr x) { + if (x.getOwner() instanceof SQLIdentifierExpr) { + String ownerName = ((SQLIdentifierExpr) x.getOwner()).getName(); + SQLTableSource tableSource = visitor.getTableSources().get(ownerName); + Entity entity = (Entity) tableSource.getAttribute("mapping.entity"); + + if (entity != null) { + Property property = entity.getProperty(x.getName()); + if (property != null) { + String columnName = visitor.resovleColumnName(entity, property); + x.setName(columnName); + x.putAttribute("mapping.entity", entity); + x.putAttribute("mapping.property", property); + + if (x.getParent() instanceof SQLSelectItem) { + SQLSelectItem selectItem = (SQLSelectItem) x.getParent(); + if (selectItem.getAlias() == null) { + selectItem.setAlias('"' + property.getName() + '"'); + } + } + + return true; + } + } + } + + return false; + } + public static boolean visit(MappingVisitor visitor, SQLVariantRefExpr x) { Map attributes = x.getAttributes(); Integer varIndex = (Integer) attributes.get("mapping.varIndex"); 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 e423ff87d7..4227b978ef 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingVisitor.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/MySqlMappingVisitor.java @@ -9,6 +9,7 @@ import java.util.Map; 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.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; @@ -30,6 +31,7 @@ public class MySqlMappingVisitor extends MySqlASTVisitorAdapter implements Mappi private final List parameters; private final List propertyValues = new ArrayList(); private int variantIndex = 0; + private final List unresolveList = new ArrayList(); public MySqlMappingVisitor(MappingEngine engine){ this(engine, Collections.emptyList()); @@ -80,8 +82,7 @@ public class MySqlMappingVisitor extends MySqlASTVisitorAdapter implements Mappi @Override public boolean visit(SQLSelectItem x) { - x.getExpr().setParent(x); - return true; + return MappingVisitorUtils.visit(this, x); } @Override @@ -137,4 +138,13 @@ public class MySqlMappingVisitor extends MySqlASTVisitorAdapter implements Mappi public int getVariantIndex() { return variantIndex; } + + public List getUnresolveList() { + return unresolveList; + } + + @Override + public void afterResolve() { + MappingVisitorUtils.afterResolve(this); + } } 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 f3c6a024c0..37b97bcfd6 100644 --- a/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingVisitor.java +++ b/src/main/java/com/alibaba/druid/mapping/spi/OracleMappingVisitor.java @@ -9,6 +9,7 @@ import java.util.Map; 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.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; @@ -32,6 +33,7 @@ public class OracleMappingVisitor extends OracleASTVisitorAdapter implements Map private final List parameters; private final List propertyValues = new ArrayList(); private int variantIndex = 0; + private final List unresolveList = new ArrayList(); public OracleMappingVisitor(MappingEngine engine){ this(engine, Collections.emptyList()); @@ -82,8 +84,7 @@ public class OracleMappingVisitor extends OracleASTVisitorAdapter implements Map @Override public boolean visit(SQLSelectItem x) { - x.getExpr().setParent(x); - return true; + return MappingVisitorUtils.visit(this, x); } @Override @@ -150,4 +151,13 @@ public class OracleMappingVisitor extends OracleASTVisitorAdapter implements Map public int getVariantIndex() { return variantIndex; } + + public List getUnresolveList() { + return unresolveList; + } + + @Override + public void afterResolve() { + MappingVisitorUtils.afterResolve(this); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/mapping/MySqlMappingShardingTest.java b/src/test/java/com/alibaba/druid/bvt/mapping/MySqlMappingShardingTest.java index c7d1c519c0..4061086f3a 100644 --- a/src/test/java/com/alibaba/druid/bvt/mapping/MySqlMappingShardingTest.java +++ b/src/test/java/com/alibaba/druid/bvt/mapping/MySqlMappingShardingTest.java @@ -19,14 +19,26 @@ public class MySqlMappingShardingTest extends TestCase { MappingEngine engine = new ShardingMappingEngine(); protected void setUp() throws Exception { - Entity entity = new Entity(); - entity.setName("用户"); - entity.setTableName("user"); + { + Entity entity = new Entity(); + entity.setName("用户"); + entity.setTableName("user"); - entity.addProperty(new Property("名称", "", "uid")); - entity.addProperty(new Property("昵称", "", "name")); + entity.addProperty(new Property("名称", "", "uid")); + entity.addProperty(new Property("昵称", "", "name")); + + engine.addEntity(entity); + } + { + Entity entity = new Entity(); + entity.setName("英雄"); + entity.setTableName("hero"); - engine.addEntity(entity); + entity.addProperty(new Property("用户名", "", "uid")); + entity.addProperty(new Property("称号", "", "name")); + + engine.addEntity(entity); + } } public void test_0() throws Exception { @@ -35,33 +47,71 @@ public class MySqlMappingShardingTest extends TestCase { String sql = engine.explainToSelectSQL(oql); String expected = "SELECT uid AS \"名称\", name AS \"昵称\"\n" + // - "FROM user_a u\n" + // - "WHERE u.uid = 'a'"; - + "FROM user_a u\n" + // + "WHERE u.uid = 'a'"; + Assert.assertEquals(expected, sql); } - + public void test_1() throws Exception { String oql = "select * from 用户 u where u.名称 = ?"; - String sql = engine.explainToSelectSQL(oql, Collections.singletonList("a")); + String sql = engine.explainToSelectSQL(oql, Collections. singletonList("a")); String expected = "SELECT uid AS \"名称\", name AS \"昵称\"\n" + // - "FROM user_a u\n" + // - "WHERE u.uid = ?"; - + "FROM user_a u\n" + // + "WHERE u.uid = ?"; + Assert.assertEquals(expected, sql); } - + public void test_2() throws Exception { String oql = "select * from 用户 u where u.名称 = ?"; - String sql = engine.explainToSelectSQL(oql, Collections.singletonList("b")); + String sql = engine.explainToSelectSQL(oql, Collections. singletonList("b")); String expected = "SELECT uid AS \"名称\", name AS \"昵称\"\n" + // - "FROM user_x u\n" + // - "WHERE u.uid = ?"; - + "FROM user_x u\n" + // + "WHERE u.uid = ?"; + + Assert.assertEquals(expected, sql); + } + + public void test_3() throws Exception { + String oql = "select h.用户名, u.昵称 from 用户 u left join 英雄 h on h.用户名 = u.名称 where u.名称 = 2"; + + String sql = engine.explainToSelectSQL(oql, Collections. singletonList("b")); + + String expected = "SELECT h.uid AS \"用户名\", u.name AS \"昵称\"\n" + // + "FROM user_x u LEFT JOIN hero h ON h.uid = u.uid\n" + // + "WHERE u.uid = 2"; + + System.out.println(sql); + Assert.assertEquals(expected, sql); + } + + public void test_4() throws Exception { + String oql = "select * from 用户 u where 名称 = ?"; + + String sql = engine.explainToSelectSQL(oql, Collections. singletonList("b")); + + String expected = "SELECT uid AS \"名称\", name AS \"昵称\"\n" + // + "FROM user_x u\n" + // + "WHERE uid = ?"; + + Assert.assertEquals(expected, sql); + } + + public void test_5() throws Exception { + String oql = "select h.用户名, u.昵称 from 用户 u left join 英雄 h on h.用户名 = u.名称 where 名称 = 2"; + + String sql = engine.explainToSelectSQL(oql, Collections. singletonList("b")); + + String expected = "SELECT h.uid AS \"用户名\", u.name AS \"昵称\"\n" + // + "FROM user_x u LEFT JOIN hero h ON h.uid = u.uid\n" + // + "WHERE uid = 2"; + + System.out.println(sql); Assert.assertEquals(expected, sql); }