#1613 - When using transaction.setPersistCascade(false) ... a Delete query should not cascade

This commit is contained in:
rob bygrave
2019-01-22 00:05:19 +13:00
parent 1d49e5b341
commit 26d1288757
9 changed files with 49 additions and 7 deletions
@@ -11,4 +11,8 @@ public interface CQueryPlanKey {
*/
String getPartialKey();
/**
* Return a query plan key taking into account persist cascading.
*/
CQueryPlanKey withDeleteByIds();
}
@@ -439,6 +439,11 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
*/
void setDelete();
/**
* Set the query to be delete by ids due to cascading delete.
*/
CQueryPlanKey setDeleteByIdsPlan();
/**
* Set the query to select the id property only.
*/
@@ -118,7 +118,14 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
@Override
public boolean isDeleteByStatement() {
return !transaction.isPersistCascade() || beanDescriptor.isDeleteByStatement();
if (!transaction.isPersistCascade() || beanDescriptor.isDeleteByStatement()) {
// plain delete by query
return true;
} else {
// delete by ids due to cascading delete needs
queryPlanKey = query.setDeleteByIdsPlan();
return false;
}
}
@Override
@@ -43,8 +43,11 @@ import java.util.List;
*/
class CQueryBuilder {
protected final String tableAliasPlaceHolder;
protected final String columnAliasPrefix;
private static final String DELETE = "Delete";
private static final String UPDATE = "Update";
final String tableAliasPlaceHolder;
final String columnAliasPrefix;
private final SqlLimiter sqlLimiter;
@@ -98,8 +101,9 @@ class CQueryBuilder {
/**
* Build the delete query.
*/
<T> CQueryUpdate buildUpdateQuery(String type, OrmQueryRequest<T> request) {
<T> CQueryUpdate buildUpdateQuery(boolean deleteRequest, OrmQueryRequest<T> request) {
String type = (deleteRequest) ? DELETE : UPDATE;
SpiQuery<T> query = request.getQuery();
String rootTableAlias = query.getAlias();
query.setDelete();
@@ -117,7 +121,7 @@ class CQueryBuilder {
SqlTree sqlTree = createSqlTree(request, predicates);
String sql;
if (type.equals("Delete")) {
if (deleteRequest) {
sql = buildDeleteSql(request, rootTableAlias, predicates, sqlTree);
} else {
sql = buildUpdateSql(request, rootTableAlias, predicates, sqlTree);
@@ -68,12 +68,12 @@ public class CQueryEngine {
}
public <T> int delete(OrmQueryRequest<T> request) {
CQueryUpdate query = queryBuilder.buildUpdateQuery("Delete", request);
CQueryUpdate query = queryBuilder.buildUpdateQuery(true, request);
return executeUpdate(request, query);
}
public <T> int update(OrmQueryRequest<T> request) {
CQueryUpdate query = queryBuilder.buildUpdateQuery("Update", request);
CQueryUpdate query = queryBuilder.buildUpdateQuery(false, request);
return executeUpdate(request, query);
}
@@ -18,6 +18,11 @@ public class NativeSqlQueryPlanKey implements CQueryPlanKey {
return getPartialKey();
}
@Override
public CQueryPlanKey withDeleteByIds() {
throw new IllegalStateException("Not allowed");
}
/**
* Return as a partial key. For rawSql hash the sql is part of the key and as such
* needs to be included in order to have a complete key. Typically the MD5 of the sql
@@ -24,6 +24,11 @@ class RawSqlQueryPlanKey implements CQueryPlanKey {
return getPartialKey() + ":r";
}
@Override
public CQueryPlanKey withDeleteByIds() {
throw new IllegalStateException("Not allowed");
}
/**
* Return as a partial key. For rawSql hash the sql is part of the key and as such
* needs to be included in order to have a complete key. Typically the MD5 of the sql
@@ -679,6 +679,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
setSelectId();
}
@Override
public CQueryPlanKey setDeleteByIdsPlan() {
// re-build plan for cascading via delete by ids
queryPlanKey = queryPlanKey.withDeleteByIds();
return queryPlanKey;
}
/**
* Set the select clause to select the Id property.
*/
@@ -25,6 +25,11 @@ class OrmQueryPlanKey implements CQueryPlanKey {
this.planHash = hc;
}
@Override
public CQueryPlanKey withDeleteByIds() {
return new OrmQueryPlanKey(description + ":deleteByIds", 0, 0, null);
}
@Override
public String getPartialKey() {
return description;