// (usually class indicator fields) that defines the class identity.
// inheritanceExpression is for this table (it doesn't reference any other tables).
// In Employee example, query with reference class LargeProject calls this for PROJECT table
deleteStatement = buildDeleteAllStatement(table, inheritanceExpression, null, null, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
} else {
ClassDescriptor desc = getHighestDescriptorMappingTable(table);
if(desc == getDescriptor()) {
if(isLastTable) {
// In Employee example, query with reference class LargeProject calls this for LPROJECT table;
deleteStatement = buildDeleteAllStatement(table, null, selectCallForExist, selectStatementForExist, null, null, primaryKeyFields);
} else {
// Class has multiple tables that are not inherited.
// In extended Employee example:
// Employee2 class inherits from Employee and
// mapped to two additional tables: EMPLOYEE2 and SALARY2.
// Query with reference class Employee2 calls this for EMPLOYEE2 table.
deleteStatement = buildDeleteAllStatement(table, null, null, null, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
}
} else {
// This table is mapped through descriptor that stands higher in inheritance hierarchy
// (but not the highest one - this is taken care in another case).
//
// inheritanceSelectStatementForExist is created for the higher descriptor,
// but the inheritance expression from the current descriptor is used.
// Note that this trick doesn't work in case the higher descriptor was defined with
// inheritance policy set not to read subclasses
// (descriptor.getInheritancePolicy().dontReadSubclassesOnQueries()).
// In that case inheritance expression for the higher descriptor can't
// be removed - it still appears in the sql and collides with the inheritance
// expression from the current descriptor - the selection expression is never true.
//
// In extended Employee example:
// VeryLargeProject inherits from LargeProject,
// mapped to an additional table VLPROJECT;
// VeryVeryLargeProject inherits from VeryLargeProject,
// mapped to the same tables as it's parent.
//
// Note that this doesn't work in case LargeProject descriptor was set not to read subclasses:
// in that case the selection expression will have (PROJ_TYPE = 'L') AND (PROJ_TYPE = 'V')
//
SQLSelectStatement inheritanceSelectStatementForExist = createSQLSelectStatementForModifyAll(null, inheritanceExpression, desc);
SQLCall inheritanceSelectCallForExist = (SQLCall)inheritanceSelectStatementForExist.buildCall(getSession());
if(isLastTable) {
// In extended Employee example:
// Query with reference class VeryVeryLargeProject calls this for VLPROJECT table.
deleteStatement = buildDeleteAllStatement(table, null, inheritanceSelectCallForExist, inheritanceSelectStatementForExist, null, null, primaryKeyFields);
} else {
// In extended Employee example:
// Query with reference class VeryLargeProject calls this for LPROJECT table.
// Note that both EXISTS and NOT EXISTS clauses created.
deleteStatement = buildDeleteAllStatement(table, null, inheritanceSelectCallForExist, inheritanceSelectStatementForExist, selectCallForNotExist, selectStatementForNotExist, primaryKeyFields);
}
}
}
}
}
if (getDescriptor().getTables().size() > 1) {
getSQLStatements().addElement(deleteStatement);
} else {
setSQLStatement(deleteStatement);
}
}
} else {
// A simple case:
// there is only one table mapped to the descriptor, and
// selection criteria doesn't reference any other tables
// A simple sql call with no subselect should be built.
// In Employee example, query with reference class:
// Project will build a simple sql call for PROJECT(and will make nested method calls for LargeProject and SmallProject);
// SmallProject will build a simple sql call for PROJECT
setSQLStatement(buildDeleteAllStatement(getDescriptor().getDefaultTable(), inheritanceExpression, selectCallForExist, selectStatementForExist, null, null, null));
}
if(selectCallForExist == null) {
// Getting there means there is no whereClause.
// To handle the mappings selectCallForExist may be required in this case, too.
if(hasInheritance && (tablesToIgnore != null || inheritanceExpression != null)) {
// The only case NOT to create the call for no whereClause is either no inheritance,
// or it's an original (not a nested) method call and there is no inheritance expression.
// In Employee example:
// query with reference class Project and no where clause for m-to-m mapping generates:
// DELETE FROM EMP_PROJ;
// as opposed to query with reference class SmallProject:
// DELETE FROM EMP_PROJ WHERE EXISTS(SELECT PROJ_ID FROM PROJECT WHERE (PROJ_TYPE = ?) AND PROJ_ID = EMP_PROJ.PROJ_ID).
//
selectCallForExist = (SQLCall)selectStatementForExist.buildCall(getSession());
}
}
// Add statements for ManyToMany and DirectCollection mappings
Vector deleteStatementsForMappings = buildDeleteAllStatementsForMappings(selectCallForExist, selectStatementForExist, tablesToIgnore == null);
if(!deleteStatementsForMappings.isEmpty()) {
if(getSQLStatement() != null) {
getSQLStatements().add(getSQLStatement());
setSQLStatement(null);
}
getSQLStatements().addAll(deleteStatementsForMappings);
}
}
// Indicates whether the descriptor has children using extra tables.
boolean hasChildrenWithExtraTables = hasInheritance && getDescriptor().getInheritancePolicy().hasChildren() && getDescriptor().getInheritancePolicy().hasMultipleTableChild();
// TBD: should we ignore subclasses in case descriptor doesn't want us to read them in?
//** Currently in this code we do ignore.
//** If it will be decided that we need to handle children in all cases
//** the following statement should be changed to: boolean shouldHandleChildren = hasChildrenWithExtraTables;
boolean shouldHandleChildren = hasChildrenWithExtraTables && getDescriptor().getInheritancePolicy().shouldReadSubclasses();
// Perform a nested method call for each child
if(shouldHandleChildren) {
// In Employee example: query for Project will make nested calls to
// LargeProject and SmallProject and ask them to ignore PROJECT table
Vector tablesToIgnoreForChildren = new Vector();
// The tables this descriptor has ignored, its children also should ignore.
if(tablesToIgnore != null) {
tablesToIgnoreForChildren.addAll(tablesToIgnore);
}
// If the desctiptor reads subclasses there is no need for
// subclasses to process its tables for the second time.
if (getDescriptor().getInheritancePolicy().shouldReadSubclasses()) {
tablesToIgnoreForChildren.addAll(tablesInInsertOrder);
}
Iterator it = getDescriptor().getInheritancePolicy().getChildDescriptors().iterator();
while(it.hasNext()) {
// Define the same query for the child
ClassDescriptor childDescriptor = (ClassDescriptor)it.next();
// Need to process only "multiple tables" child descriptors
if ((childDescriptor.getTables().size() > getDescriptor().getTables().size()) ||
(childDescriptor.getInheritancePolicy().hasMultipleTableChild()))
{
DeleteAllQuery childQuery = new DeleteAllQuery();
childQuery.setReferenceClass(childDescriptor.getJavaClass());
childQuery.setSelectionCriteria(getSelectionCriteria());
childQuery.setDescriptor(childDescriptor);
childQuery.setSession(getSession());
ExpressionQueryMechanism childMechanism = (ExpressionQueryMechanism)childQuery.getQueryMechanism();