#1251 - Delete cascade with 11+ and Postgres throws exception

Fix
This commit is contained in:
Rob Bygrave
2018-02-07 16:47:59 +13:00
parent 7a816ae2da
commit 9bade12c9d
3 changed files with 105 additions and 124 deletions
@@ -1,7 +1,11 @@
package io.ebeaninternal.server.deploy;
import io.ebean.EbeanServer;
import io.ebean.Query;
import io.ebean.bean.EntityBean;
import io.ebean.text.PathProperties;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.core.InternString;
import io.ebeaninternal.server.deploy.id.IdBinder;
import io.ebeaninternal.server.deploy.id.ImportedId;
@@ -10,7 +14,7 @@ import io.ebeaninternal.server.deploy.id.ImportedIdSimple;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import io.ebeaninternal.server.el.ElPropertyChainBuilder;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.persist.MultiValueWrapper;
import io.ebeaninternal.server.query.SqlJoinType;
import io.ebeanservice.docstore.api.mapping.DocMappingBuilder;
import io.ebeanservice.docstore.api.mapping.DocPropertyMapping;
@@ -402,17 +406,83 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty {
throw new PersistenceException(msg);
}
protected void bindWhereParentId(List<Object> bindValues, Object parentId) {
private List<Object> flattenParentIds(List<Object> parentIds) {
List<Object> bindValues = new ArrayList<>(parentIds.size() * 3);
for (Object parentId : parentIds) {
flatten(bindValues, parentId);
}
return bindValues;
}
if (exportedProperties.length == 1) {
private List<Object> flattenParentId(Object parentId) {
List<Object> bindValues = new ArrayList<>();
flatten(bindValues, parentId);
return bindValues;
}
private void flatten(List<Object> bindValues, Object parentId) {
if (isExportedSimple()) {
bindValues.add(parentId);
} else {
EntityBean parent = (EntityBean) parentId;
for (ExportedProperty exportedProperty : exportedProperties) {
Object embVal = exportedProperty.getValue(parent);
bindValues.add(embVal);
bindValues.add(exportedProperty.getValue(parent));
}
}
}
EbeanServer server() {
return getBeanDescriptor().getEbeanServer();
}
void bindParentIds(DefaultSqlUpdate delete, List<Object> parentIds) {
if (isExportedSimple()) {
delete.addParameter(new MultiValueWrapper(parentIds));
} else {
// embedded ids etc
List<Object> bindValues = flattenParentIds(parentIds);
for (Object bindValue : bindValues) {
delete.addParameter(bindValue);
}
}
}
void bindParentId(DefaultSqlUpdate sqlUpd, Object parentId) {
if (isExportedSimple()) {
sqlUpd.addParameter(parentId);
return;
}
EntityBean parent = (EntityBean) parentId;
for (ExportedProperty exportedProperty : exportedProperties) {
sqlUpd.addParameter(exportedProperty.getValue(parent));
}
}
void bindParentIdEq(String expr, Object parentId, Query<?> q) {
if (isExportedSimple()) {
q.where().raw(expr, parentId);
} else {
// embedded ids etc
List<Object> bindValues = flattenParentId(parentId);
q.where().raw(expr, bindValues.toArray());
}
}
void bindParentIdsIn(String expr, List<Object> parentIds, Query<?> q) {
if (isExportedSimple()) {
q.where().raw(expr, new MultiValueWrapper(parentIds));
} else {
// embedded ids etc
List<Object> bindValues = flattenParentIds(parentIds);
q.where().raw(expr, bindValues.toArray());
}
}
private boolean isExportedSimple() {
return exportedProperties.length == 1;
}
}
@@ -1,7 +1,6 @@
package io.ebeaninternal.server.deploy;
import io.ebean.EbeanServer;
import io.ebean.Expression;
import io.ebean.Query;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
@@ -18,7 +17,6 @@ import io.ebeaninternal.server.deploy.id.ImportedId;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import io.ebeaninternal.server.el.ElPropertyChainBuilder;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.persist.MultiValueWrapper;
import io.ebeaninternal.server.query.SqlBeanLoad;
import io.ebeaninternal.server.text.json.ReadJson;
import io.ebeaninternal.server.text.json.SpiJsonWriter;
@@ -290,7 +288,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
private SqlUpdate deleteByParentId(Object parentId) {
DefaultSqlUpdate sqlDelete = new DefaultSqlUpdate(deleteByParentIdSql);
bindWhereParendId(sqlDelete, parentId);
bindParentId(sqlDelete, parentId);
return sqlDelete;
}
@@ -308,18 +306,13 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
private List<Object> findIdsByParentId(Object parentId, Transaction t, List<Object> excludeDetailIds) {
String rawWhere = deriveWhereParentIdSql(false, "");
List<Object> bindValues = new ArrayList<>();
bindWhereParentId(bindValues, parentId);
EbeanServer server = getBeanDescriptor().getEbeanServer();
Query<?> q = server.find(getPropertyType())
.where()
.raw(rawWhere, bindValues.toArray())
.query();
EbeanServer server = server();
Query<?> q = server.find(getPropertyType());
bindParentIdEq(rawWhere, parentId, q);
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
Expression idIn = q.getExpressionFactory().idIn(excludeDetailIds);
q.where().not(idIn);
q.where().not(q.getExpressionFactory().idIn(excludeDetailIds));
}
return server.findIds(q, t);
@@ -334,16 +327,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
return false;
}
/**
* Add the loaded current bean to its associated parent.
*/
public void lazyLoadMany(EntityBean current) {
EntityBean parentBean = childMasterProperty.getValueAsEntityBean(current);
if (parentBean != null) {
addBeanToCollectionWithCreate(parentBean, current, true);
}
}
public void addWhereParentIdIn(SpiQuery<?> query, List<Object> parentIds, boolean useDocStore) {
if (useDocStore) {
// assumes the ManyToOne property is included
@@ -365,59 +348,35 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
String rawWhere = deriveWhereParentIdSql(true, tableAlias);
String expr = descriptor.getParentIdInExpr(parentIds.size(), rawWhere);
// Flatten the bind values if needed (embeddedId)
List<Object> bindValues = getBindParentIds(parentIds);
if (descriptor.isSimpleId()) {
query.where().raw(expr, new MultiValueWrapper(bindValues));
} else {
query.where().raw(expr, bindValues.toArray());
}
bindParentIdsIn(expr, parentIds, query);
}
private List<Object> findIdsByParentIdList(List<Object> parentIdList, Transaction t, List<Object> excludeDetailIds) {
private List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t, List<Object> excludeDetailIds) {
String rawWhere = deriveWhereParentIdSql(true, "");
String inClause = buildInClauseBinding(parentIdList.size(), exportedPropertyBindProto);
String inClause = buildInClauseBinding(parentIds.size(), exportedPropertyBindProto);
String expr = rawWhere + inClause;
List<Object> bindValues = new ArrayList<>();
for (Object aParentIdList : parentIdList) {
bindWhereParentId(bindValues, aParentIdList);
}
EbeanServer server = getBeanDescriptor().getEbeanServer();
Query<?> q = server.find(getPropertyType());
if (descriptor.isSimpleId()) {
q.where().raw(expr, new MultiValueWrapper(bindValues));
} else {
q.where().raw(expr, bindValues.toArray());
}
EbeanServer server = descriptor.getEbeanServer();
Query<?> q = server.find(propertyType);
bindParentIdsIn(expr, parentIds, q);
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
Expression idIn = q.getExpressionFactory().idIn(excludeDetailIds);
q.where().not(idIn);
q.where().not(q.getExpressionFactory().idIn(excludeDetailIds));
}
return server.findIds(q, t);
}
private SqlUpdate deleteByParentIdList(List<Object> parentIdList) {
private SqlUpdate deleteByParentIdList(List<Object> parentIds) {
StringBuilder sb = new StringBuilder(100);
sb.append(deleteByParentIdInSql);
String inClause = buildInClauseBinding(parentIdList.size(), exportedPropertyBindProto);
sb.append(inClause);
sb.append(buildInClauseBinding(parentIds.size(), exportedPropertyBindProto));
DefaultSqlUpdate delete = new DefaultSqlUpdate(sb.toString());
if (exportedProperties.length == 1) {
bindWhereParendId(delete, new MultiValueWrapper(parentIdList));
} else {
for (Object aParentIdist : parentIdList) {
bindWhereParendId(delete, aParentIdist);
}
}
bindParentIds(delete, parentIds);
return delete;
}
@@ -678,33 +637,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
return descriptor.getId(parentBean);
}
public List<Object> getBindParentIds(List<Object> parentIds) {
if (exportedProperties.length == 1) {
return parentIds;
}
List<Object> expandedList = new ArrayList<>(parentIds.size() * exportedProperties.length);
for (Object parentId : parentIds) {
for (ExportedProperty exportedProperty : exportedProperties) {
Object compId = parentId;
expandedList.add(exportedProperty.getValue((EntityBean) compId));
}
}
return expandedList;
}
private void bindWhereParendId(DefaultSqlUpdate sqlUpd, Object parentId) {
if (exportedProperties.length == 1) {
sqlUpd.addParameter(parentId);
return;
}
EntityBean parent = (EntityBean) parentId;
for (ExportedProperty exportedProperty : exportedProperties) {
Object embVal = exportedProperty.getValue(parent);
sqlUpd.addParameter(embVal);
}
}
public void addSelectExported(DbSqlContext ctx, String tableAlias) {
String alias = manyToMany ? "int_" : tableAlias;
@@ -7,6 +7,7 @@ import io.ebean.Transaction;
import io.ebean.ValuePair;
import io.ebean.bean.EntityBean;
import io.ebean.bean.PersistenceContext;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.cache.CacheChangeSet;
import io.ebeaninternal.server.cache.CachedBeanData;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
@@ -14,7 +15,6 @@ import io.ebeaninternal.server.deploy.id.ImportedId;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import io.ebeaninternal.server.el.ElPropertyChainBuilder;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.query.SqlBeanLoad;
import io.ebeaninternal.server.query.SqlJoinType;
import io.ebeaninternal.server.text.json.ReadJson;
@@ -202,38 +202,29 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
}
private SqlUpdate deleteByParentIdList(List<Object> parentIdist) {
private SqlUpdate deleteByParentIdList(List<Object> parentIds) {
StringBuilder sb = new StringBuilder(100);
sb.append(deleteByParentIdInSql);
String inClause = targetIdBinder.getIdInValueExpr(false, parentIdist.size());
sb.append(inClause);
sb.append(targetIdBinder.getIdInValueExpr(false, parentIds.size()));
DefaultSqlUpdate delete = new DefaultSqlUpdate(sb.toString());
for (Object aParentIdist : parentIdist) {
targetIdBinder.bindId(delete, aParentIdist);
}
bindParentIds(delete, parentIds);
return delete;
}
private SqlUpdate deleteByParentId(Object parentId) {
DefaultSqlUpdate delete = new DefaultSqlUpdate(deleteByParentIdSql);
if (exportedProperties.length == 1) {
delete.addParameter(parentId);
} else {
targetDescriptor.getIdBinder().bindId(delete, parentId);
}
bindParentId(delete, parentId);
return delete;
}
public List<Object> findIdsByParentId(Object parentId, List<Object> parentIdist, Transaction t) {
public List<Object> findIdsByParentId(Object parentId, List<Object> parentIds, Transaction t) {
if (parentId != null) {
return findIdsByParentId(parentId, t);
} else {
return findIdsByParentIdList(parentIdist, t);
return findIdsByParentIdList(parentIds, t);
}
}
@@ -241,33 +232,21 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
String rawWhere = deriveWhereParentIdSql(false);
List<Object> bindValues = new ArrayList<>();
bindWhereParentId(bindValues, parentId);
EbeanServer server = getBeanDescriptor().getEbeanServer();
Query<?> q = server.find(getPropertyType())
.where()
.raw(rawWhere, bindValues.toArray())
.query();
EbeanServer server = server();
Query<?> q = server.find(getPropertyType());
bindParentIdEq(rawWhere, parentId, q);
return server.findIds(q, t);
}
private List<Object> findIdsByParentIdList(List<Object> parentIdList, Transaction t) {
private List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t) {
String rawWhere = deriveWhereParentIdSql(true);
String inClause = targetIdBinder.getIdInValueExpr(false, parentIdList.size());
String inClause = targetIdBinder.getIdInValueExpr(false, parentIds.size());
String expr = rawWhere + inClause;
List<Object> bindValues = new ArrayList<>();
for (Object aParentIdList : parentIdList) {
bindWhereParentId(bindValues, aParentIdList);
}
EbeanServer server = getBeanDescriptor().getEbeanServer();
Query<?> q = server.find(getPropertyType())
.where().raw(expr, bindValues.toArray()).query();
EbeanServer server = server();
Query<?> q = server.find(getPropertyType());
bindParentIdsIn(expr, parentIds, q);
return server.findIds(q, t);
}