* Check whether the mapping's attribute should be optimized through batch and joining.
* @param shouldUseSopObject indicates whether sopObject stored in the row should be used to extract the value (and fields/values stored in the row ignored).
*/
protected Object valueFromRowInternal(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession, boolean shouldUseSopObject) throws DatabaseException {
// PERF: Direct variable access.
ReadQuery targetQuery = this.selectionQuery;
if (shouldUseSopObject) {
Object sopAttribute = getAttributeValueFromObject(row.getSopObject());
Object sopRealAttribute;
if (isCollectionMapping()) {
if (sopAttribute == null) {
return getContainerPolicy().containerInstance();
}
sopRealAttribute = getIndirectionPolicy().getRealAttributeValueFromObject(row.getSopObject(), sopAttribute);
if (getContainerPolicy().isEmpty(sopRealAttribute)) {
return sopAttribute;
}
} else {
if (sopAttribute == null) {
return this.indirectionPolicy.nullValueFromRow();
}
// As part of SOP object the indirection should be already triggered
sopRealAttribute = getIndirectionPolicy().getRealAttributeValueFromObject(row.getSopObject(), sopAttribute);
if (sopRealAttribute == null) {
return sopAttribute;
}
}
DatabaseRecord sopRow = new DatabaseRecord(0);
sopRow.setSopObject(sopRealAttribute);
row = sopRow;
}
// Copy nested fetch group from the source query
if (targetQuery.isObjectLevelReadQuery() && targetQuery.getDescriptor().hasFetchGroupManager()) {
FetchGroup sourceFG = sourceQuery.getExecutionFetchGroup(this.getDescriptor());
if (sourceFG != null) {
FetchGroup targetFetchGroup = sourceFG.getGroup(getAttributeName());
if(targetFetchGroup != null) {
// perf: bug#4751950, first prepare the query before cloning.
if (targetQuery.shouldPrepare()) {
targetQuery.checkPrepare(executionSession, row);
}
targetQuery = (ObjectLevelReadQuery)targetQuery.clone();
targetQuery.setIsExecutionClone(true);
((ObjectLevelReadQuery)targetQuery).setFetchGroup(targetFetchGroup);
}
}
}
// CR #4365, 3610825 - moved up from the block below, needs to be set with
// indirection off. Clone the query and set its id.
// All indirections are triggered in sopObject, therefore if sopObject is used then indirection on targetQuery to be triggered, too.
if (!this.indirectionPolicy.usesIndirection() || shouldUseSopObject) {
if (targetQuery == this.selectionQuery) {
// perf: bug#4751950, first prepare the query before cloning.
if (targetQuery.shouldPrepare()) {
targetQuery.checkPrepare(executionSession, row);
}
targetQuery = (ObjectLevelReadQuery)targetQuery.clone();
targetQuery.setIsExecutionClone(true);
}
targetQuery.setQueryId(sourceQuery.getQueryId());
if (sourceQuery.usesResultSetAccessOptimization()) {
targetQuery.setAccessors(sourceQuery.getAccessors());
}
((ObjectLevelReadQuery)targetQuery).setRequiresDeferredLocks(sourceQuery.requiresDeferredLocks());
}
// If the source query is cascading then the target query must use the same settings.
if (targetQuery.isObjectLevelReadQuery()) {
if (sourceQuery.shouldCascadeAllParts() || (this.isPrivateOwned && sourceQuery.shouldCascadePrivateParts()) || (this.cascadeRefresh && sourceQuery.shouldCascadeByMapping())) {
// If the target query has already been cloned (we're refreshing) avoid
// re-cloning the query again.
if (targetQuery == this.selectionQuery) {
// perf: bug#4751950, first prepare the query before cloning.
if (targetQuery.shouldPrepare()) {
targetQuery.checkPrepare(executionSession, row);
}
targetQuery = (ObjectLevelReadQuery)targetQuery.clone();
targetQuery.setIsExecutionClone(true);
}
((ObjectLevelReadQuery)targetQuery).setShouldRefreshIdentityMapResult(sourceQuery.shouldRefreshIdentityMapResult());
targetQuery.setCascadePolicy(sourceQuery.getCascadePolicy());
// For queries that have turned caching off, such as aggregate collection, leave it off.
if (targetQuery.shouldMaintainCache()) {
targetQuery.setShouldMaintainCache(sourceQuery.shouldMaintainCache());
}
// For flashback: Read attributes as of the same time if required.
if (((ObjectLevelReadQuery)sourceQuery).hasAsOfClause()) {
targetQuery.setSelectionCriteria((Expression)targetQuery.getSelectionCriteria().clone());
((ObjectLevelReadQuery)targetQuery).setAsOfClause(((ObjectLevelReadQuery)sourceQuery).getAsOfClause());
}
}
if (isExtendingPessimisticLockScope(sourceQuery)) {
if (this.extendPessimisticLockScope == ExtendPessimisticLockScope.TARGET_QUERY) {
if (targetQuery == this.selectionQuery) {
// perf: bug#4751950, first prepare the query before cloning.
if (targetQuery.shouldPrepare()) {
targetQuery.checkPrepare(executionSession, row);
}
targetQuery = (ObjectLevelReadQuery)targetQuery.clone();
targetQuery.setIsExecutionClone(true);
}
extendPessimisticLockScopeInTargetQuery((ObjectLevelReadQuery)targetQuery, sourceQuery);
} else if (this.extendPessimisticLockScope == ExtendPessimisticLockScope.DEDICATED_QUERY) {
ReadQuery dedicatedQuery = getExtendPessimisticLockScopeDedicatedQuery(executionSession, sourceQuery.getLockMode());
executionSession.executeQuery(dedicatedQuery, row);
}
}
}
targetQuery = prepareHistoricalQuery(targetQuery, sourceQuery, executionSession);