From d54cffacea3253ecf2ddd6b5a65f863a07d8b89d Mon Sep 17 00:00:00 2001 From: rbygrave Date: Wed, 17 Dec 2014 00:53:42 +1300 Subject: [PATCH] #222 - SQL Server - OnetoMany with compound key using IN is not legal in mssql --- .../server/deploy/BeanDescriptor.java | 50 +++++++------------ .../server/deploy/BeanPropertyAssocMany.java | 4 +- .../server/deploy/id/IdBinder.java | 5 ++ .../server/deploy/id/IdBinderEmbedded.java | 10 ++-- .../server/deploy/id/IdBinderEmpty.java | 4 ++ .../server/deploy/id/IdBinderSimple.java | 6 ++- 6 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index cc4ef6d7d..c6f238484 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -1,24 +1,5 @@ package com.avaje.ebeaninternal.server.deploy; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import javax.persistence.PersistenceException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.avaje.ebean.SqlUpdate; import com.avaje.ebean.Transaction; import com.avaje.ebean.annotation.ConcurrencyMode; @@ -35,11 +16,7 @@ import com.avaje.ebean.event.BeanPersistListener; import com.avaje.ebean.event.BeanQueryAdapter; import com.avaje.ebean.meta.MetaBeanInfo; import com.avaje.ebean.meta.MetaQueryPlanStatistic; -import com.avaje.ebeaninternal.api.HashQueryPlan; -import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.api.SpiQuery; -import com.avaje.ebeaninternal.api.SpiTransaction; -import com.avaje.ebeaninternal.api.SpiUpdatePlan; +import com.avaje.ebeaninternal.api.*; import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; import com.avaje.ebeaninternal.server.cache.CachedBeanData; import com.avaje.ebeaninternal.server.cache.CachedManyIds; @@ -50,13 +27,7 @@ import com.avaje.ebeaninternal.server.core.PersistRequestBean; import com.avaje.ebeaninternal.server.deploy.id.IdBinder; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyLists; -import com.avaje.ebeaninternal.server.el.ElComparator; -import com.avaje.ebeaninternal.server.el.ElComparatorCompound; -import com.avaje.ebeaninternal.server.el.ElComparatorProperty; -import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder; -import com.avaje.ebeaninternal.server.el.ElPropertyDeploy; -import com.avaje.ebeaninternal.server.el.ElPropertyValue; -import com.avaje.ebeaninternal.server.persist.DmlUtil; +import com.avaje.ebeaninternal.server.el.*; import com.avaje.ebeaninternal.server.query.CQueryPlan; import com.avaje.ebeaninternal.server.query.CQueryPlanStats.Snapshot; import com.avaje.ebeaninternal.server.query.SplitName; @@ -68,6 +39,15 @@ import com.avaje.ebeaninternal.util.SortByClause; import com.avaje.ebeaninternal.util.SortByClause.Property; import com.avaje.ebeaninternal.util.SortByClauseParser; import com.fasterxml.jackson.core.JsonParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.persistence.PersistenceException; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.sql.SQLException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Describes Beans including their deployment information. @@ -1036,6 +1016,14 @@ public class BeanDescriptor implements MetaBeanInfo { return null; } + /** + * Return a raw expression for 'where parent id in ...' clause. + */ + public String getParentIdInExpr(int parentIdSize, String rawWhere) { + String inClause = idBinder.getIdInValueExpr(parentIdSize); + return idBinder.isIdInExpandedForm() ? inClause : rawWhere + inClause; + } + /** * Return the IdBinder which is helpful for handling the various types of Id. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java index 25b45de1c..c781738cd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java @@ -278,9 +278,7 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc { query.setIncludeTableJoin(inverseJoin); } String rawWhere = deriveWhereParentIdSql(true, tableAlias); - String inClause = descriptor.getIdBinder().getIdInValueExpr(parentIds.size()); - - String expr = rawWhere + inClause; + String expr = descriptor.getParentIdInExpr(parentIds.size(), rawWhere); // Flatten the bind values if needed (embeddedId) List bindValues = getBindParentIds(parentIds); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java index 7eab5eaf9..41b807cf9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java @@ -25,6 +25,11 @@ public interface IdBinder { */ public void initialise(); + /** + * Return true if this is a compound key and must use expanded and or form. + */ + public boolean isIdInExpandedForm(); + /** * Write the Id value to binary DataOuput. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java index ddb3d9e25..1f17ad28b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java @@ -43,17 +43,21 @@ public final class IdBinderEmbedded implements IdBinder { this.idInValueSql = idInExpandedForm ? idInExpanded() : idInCompressed(); } + public boolean isIdInExpandedForm() { + return idInExpandedForm; + } + private String idInExpanded() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(30); sb.append("("); for (int i = 0; i < props.length; i++) { if (i > 0) { sb.append(" and "); } - sb.append(embIdProperty.getName()); + sb.append(idDesc.getBaseTableAlias()); sb.append("."); - sb.append(props[i].getName()); + sb.append(props[i].getDbColumn()); sb.append("=?"); } sb.append(")"); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java index defe57740..fe1efe507 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java @@ -30,6 +30,10 @@ public final class IdBinderEmpty implements IdBinder { } + public boolean isIdInExpandedForm() { + return false; + } + public String getOrderBy(String pathPrefix, boolean ascending) { return pathPrefix; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java index babff92ea..7120a680a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java @@ -41,7 +41,11 @@ public final class IdBinderSimple implements IdBinder { public void initialise(){ // do nothing } - + + public boolean isIdInExpandedForm() { + return false; + } + public String getOrderBy(String pathPrefix, boolean ascending) { StringBuilder sb = new StringBuilder();