diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanRawSql.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanRawSql.java index cb04aa0da..b23cc79ac 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanRawSql.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanRawSql.java @@ -1,15 +1,14 @@ package com.avaje.ebeaninternal.server.query; -import java.sql.ResultSet; -import java.util.List; - import com.avaje.ebean.RawSql.ColumnMapping; import com.avaje.ebean.config.dbplatform.SqlLimitResponse; import com.avaje.ebeaninternal.server.core.OrmQueryRequest; -import com.avaje.ebeaninternal.server.deploy.InheritInfo; import com.avaje.ebeaninternal.server.type.DataReader; import com.avaje.ebeaninternal.server.type.RsetDataReaderIndexed; +import java.sql.ResultSet; +import java.util.List; + /** * RawSql based query plan. */ @@ -18,9 +17,7 @@ public class CQueryPlanRawSql extends CQueryPlan { private final int[] rsetIndexPositions; public CQueryPlanRawSql(OrmQueryRequest request, SqlLimitResponse sqlRes, SqlTree sqlTree, String logWhereSql) { - super(request, sqlRes, sqlTree, true, logWhereSql); - this.rsetIndexPositions = createIndexPositions(request, sqlTree); } @@ -34,23 +31,11 @@ public class CQueryPlanRawSql extends CQueryPlan { List chain = sqlTree.buildRawSqlSelectChain(); ColumnMapping columnMapping = request.getQuery().getRawSql().getColumnMapping(); - // if the top level bean has inheritance expect first column - // to be the discriminator type column (and use offset 1) - InheritInfo inheritInfo = request.getBeanDescriptor().getInheritInfo(); - boolean addDiscriminator = inheritInfo != null; - int offset = addDiscriminator ? 1 : 0; - - int[] indexPositions = new int[chain.size() + offset]; - if (addDiscriminator) { - // discriminator column must always be first in the query - indexPositions[0] = 1; - } + int[] indexPositions = new int[chain.size()]; // set the resultSet index positions for the property expressions for (int i = 0; i < chain.size(); i++) { - String expr = chain.get(i); - int indexPos = 1 + columnMapping.getIndexPosition(expr); - indexPositions[i + offset] = indexPos; + indexPositions[i] = 1 + columnMapping.getIndexPosition(chain.get(i)); } // check and handle the case where a discriminator column for diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java index b200378cd..0e04d693c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java @@ -160,6 +160,10 @@ public class SqlTreeNodeBean implements SqlTreeNode { public void buildRawSqlSelectChain(List selectChain) { if (readId) { + if (desc.hasInheritance()) { + // discriminator column always proceeds id column + selectChain.add(getPath(prefix, desc.getInheritInfo().getDiscriminatorColumn())); + } idBinder.buildRawSqlSelectChain(prefix, selectChain); } for (int i = 0, x = properties.length; i < x; i++) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/RsetDataReaderIndexed.java b/src/main/java/com/avaje/ebeaninternal/server/type/RsetDataReaderIndexed.java index 36af385cf..6fc8df7e3 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/RsetDataReaderIndexed.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/RsetDataReaderIndexed.java @@ -4,6 +4,9 @@ import com.avaje.ebeaninternal.server.core.timezone.DataTimeZone; import java.sql.ResultSet; +/** + * A DataReader with indexed positions for the properties to read specifically for RawSql use. + */ public class RsetDataReaderIndexed extends RsetDataReader { private final int[] rsetIndexPositions; diff --git a/src/test/java/com/avaje/tests/rawsql/inherit/ParentQueryTest.java b/src/test/java/com/avaje/tests/rawsql/inherit/ParentQueryTest.java index 23ecb1d60..af5061306 100644 --- a/src/test/java/com/avaje/tests/rawsql/inherit/ParentQueryTest.java +++ b/src/test/java/com/avaje/tests/rawsql/inherit/ParentQueryTest.java @@ -24,15 +24,15 @@ public class ParentQueryTest extends BaseTestCase { exampleData.add(new Data(1)); exampleData.add(new Data(2)); - ChildA a = new ChildA(0); + ChildA a = new ChildA(0, "PA"); a.setData(exampleData); Ebean.save(a); - ChildB b = new ChildB(1); + ChildB b = new ChildB(1, "PB"); b.setData(exampleData); Ebean.save(b); - ChildA c = new ChildA(2); + ChildA c = new ChildA(2, "PC"); c.setData(exampleData); Ebean.save(c); diff --git a/src/test/java/com/avaje/tests/rawsql/inherit/ParentRawSqlTest.java b/src/test/java/com/avaje/tests/rawsql/inherit/ParentRawSqlTest.java index d77641e8e..15109274d 100644 --- a/src/test/java/com/avaje/tests/rawsql/inherit/ParentRawSqlTest.java +++ b/src/test/java/com/avaje/tests/rawsql/inherit/ParentRawSqlTest.java @@ -30,15 +30,15 @@ public class ParentRawSqlTest extends BaseTestCase { exampleData.add(new Data(1)); exampleData.add(new Data(2)); - ChildA a = new ChildA(0); + ChildA a = new ChildA(0, "PA"); a.setData(exampleData); Ebean.save(a); - ChildB b = new ChildB(1); + ChildB b = new ChildB(1, "PB"); b.setData(exampleData); Ebean.save(b); - ChildA c = new ChildA(2); + ChildA c = new ChildA(2, "PC"); c.setData(exampleData); Ebean.save(c); @@ -62,15 +62,15 @@ public class ParentRawSqlTest extends BaseTestCase { exampleData.add(new Data(1)); exampleData.add(new Data(2)); - ChildA a = new ChildA(0); + ChildA a = new ChildA(0, "PA"); a.setData(exampleData); Ebean.save(a); - ChildB b = new ChildB(1); + ChildB b = new ChildB(1, "PB"); b.setData(exampleData); Ebean.save(b); - ChildA c = new ChildA(2); + ChildA c = new ChildA(2, "PC"); c.setData(exampleData); Ebean.save(c); @@ -80,25 +80,44 @@ public class ParentRawSqlTest extends BaseTestCase { Ebean.save(e1); joinToInheritanceHierarchy_withAliasMapping(); - joinToInheritanceHierarchy(); + joinToInheritanceHierarchy_bug416(); + joinToInheritanceHierarchy_with_queryJoin(); joinToInheritanceHierarchy_withIgnore(); useColumnMappingIgnore(); - useColumnMappingWithDiscriminator(); - useExtraColumnMappingIgnore(); } - private void joinToInheritanceHierarchy() { + private void joinToInheritanceHierarchy_bug416() { + + // For bug 416 we need the parent.more to trigger it RawSql rawSql = RawSqlBuilder - .unparsed("select u.id, u.name, p.type as ptype, p.id as pid from rawinherit_uncle u join rawinherit_parent p on p.id = u.parent_id") + .unparsed("select u.id, u.name, p.type as p_type, p.id as p_id, p.more as p_more from rawinherit_uncle u join rawinherit_parent p on p.id = u.parent_id") .columnMapping("id", "id") .columnMapping("name", "name") - .columnMapping("ptype", "parent.type") - .columnMapping("pid", "parent.id") + .columnMapping("p_type", "parent.type") + .columnMapping("p_id", "parent.id") + .columnMapping("p_more", "parent.more") + .create(); + + List uncles = Ebean.find(EUncle.class).setRawSql(rawSql).findList(); + + assertNotNull(uncles.get(0)); + Parent parent = uncles.get(0).getParent(); + assertTrue(parent instanceof ChildB); + } + + private void joinToInheritanceHierarchy_with_queryJoin() { + + RawSql rawSql = RawSqlBuilder + .unparsed("select u.id, u.name, p.type as p_type, p.id as p_id from rawinherit_uncle u join rawinherit_parent p on p.id = u.parent_id") + .columnMapping("id", "id") + .columnMapping("name", "name") + .columnMapping("p_type", "parent.type") + .columnMapping("p_id", "parent.id") .create(); List uncles = Ebean.find(EUncle.class).setRawSql(rawSql) diff --git a/src/test/java/org/avaje/test/model/rawsql/inherit/ChildA.java b/src/test/java/org/avaje/test/model/rawsql/inherit/ChildA.java index b58ff73db..030a99f85 100644 --- a/src/test/java/org/avaje/test/model/rawsql/inherit/ChildA.java +++ b/src/test/java/org/avaje/test/model/rawsql/inherit/ChildA.java @@ -7,12 +7,12 @@ import javax.persistence.Entity; @DiscriminatorValue("A") public class ChildA extends Parent { - public String getName() { - return "A Name"; - } + public String getName() { + return "A Name"; + } - public ChildA(Integer number) { - super(number); - } + public ChildA(Integer number, String more) { + super(number, more); + } } diff --git a/src/test/java/org/avaje/test/model/rawsql/inherit/ChildB.java b/src/test/java/org/avaje/test/model/rawsql/inherit/ChildB.java index 24c4fd7a4..e6deab956 100644 --- a/src/test/java/org/avaje/test/model/rawsql/inherit/ChildB.java +++ b/src/test/java/org/avaje/test/model/rawsql/inherit/ChildB.java @@ -7,11 +7,11 @@ import javax.persistence.Entity; @DiscriminatorValue("B") public class ChildB extends Parent { - public String getName() { - return "B Name"; - } + public String getName() { + return "B Name"; + } - public ChildB(Integer number) { - super(number); - } + public ChildB(Integer number, String more) { + super(number, more); + } } diff --git a/src/test/java/org/avaje/test/model/rawsql/inherit/Parent.java b/src/test/java/org/avaje/test/model/rawsql/inherit/Parent.java index 7d16b7ab6..2a5376be4 100644 --- a/src/test/java/org/avaje/test/model/rawsql/inherit/Parent.java +++ b/src/test/java/org/avaje/test/model/rawsql/inherit/Parent.java @@ -13,38 +13,48 @@ import java.util.List; @Entity @Table(name = "rawinherit_parent") -@Inheritance(strategy= InheritanceType.SINGLE_TABLE) -@DiscriminatorColumn(name="type") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "type") public abstract class Parent { - @Id - private Long id; + @Id + private Long id; - private Integer val; + private Integer val; - @ManyToMany(cascade = CascadeType.PERSIST) - private List data = new ArrayList(); + private String more; - protected Parent(Integer val) { - this.val = val; - } + @ManyToMany(cascade = CascadeType.PERSIST) + private List data = new ArrayList(); - public abstract String getName(); + protected Parent(Integer val, String more) { + this.val = val; + this.more = more; + } - public Long getId() { - return id; - } + public abstract String getName(); - public Integer getVal() { - return val; - } + public Long getId() { + return id; + } - public List getData() { - return data; - } + public Integer getVal() { + return val; + } - public void setData(List datas) { - this.data = datas; - } + public List getData() { + return data; + } + public void setData(List datas) { + this.data = datas; + } + + public String getMore() { + return more; + } + + public void setMore(String more) { + this.more = more; + } }