[ACS-10041] Repository - CPU spikes and OOM errors with SQL Server 2019 (#3588)

This commit is contained in:
cezary-witkowski
2025-09-23 14:10:29 +02:00
committed by GitHub
parent 1251081a69
commit ef034e596b
5 changed files with 6538 additions and 6437 deletions

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -36,8 +36,7 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
/** /**
* Class holding properties associated with the <b>sys:referenceable</b> aspect. * Class holding properties associated with the <b>sys:referenceable</b> aspect. This aspect is common enough to warrant direct inclusion on the <b>Node</b> entity.
* This aspect is common enough to warrant direct inclusion on the <b>Node</b> entity.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.4 * @since 3.4
@@ -55,7 +54,7 @@ public class ReferenceablePropertiesEntity
} }
/** /**
* @return Returns <tt>true</tt> if the property belongs to the <b>sys:referenceable</b> aspect * @return Returns <tt>true</tt> if the property belongs to the <b>sys:referenceable</b> aspect
*/ */
public static boolean isReferenceableProperty(QName qname) public static boolean isReferenceableProperty(QName qname)
{ {
@@ -87,10 +86,8 @@ public class ReferenceablePropertiesEntity
/** /**
* Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties. * Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties.
*/ */
public static void addReferenceableProperties(Node node, Map<QName, Serializable> properties) public static void addReferenceableProperties(Long nodeId, NodeRef nodeRef, Map<QName, Serializable> properties)
{ {
Long nodeId = node.getId();
NodeRef nodeRef = node.getNodeRef();
properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol()); properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId()); properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -28,8 +28,10 @@ package org.alfresco.repo.node.getchildren;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.alfresco.repo.domain.node.NodeEntity; import org.alfresco.repo.domain.node.AuditablePropertiesEntity;
import org.alfresco.repo.domain.node.NodePropertyEntity; import org.alfresco.repo.domain.node.NodePropertyEntity;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/** /**
* Filterable/Sortable Node Entity * Filterable/Sortable Node Entity
@@ -42,12 +44,17 @@ import org.alfresco.repo.domain.node.NodePropertyEntity;
public class FilterSortNodeEntity public class FilterSortNodeEntity
{ {
private Long id; // node id private Long id; // node id
private String nodeUuid;
private Long typeQNameId;
private NodeEntity node; private AuditablePropertiesEntity auditablePropertiesEntity;
private NodePropertyEntity prop1; private NodePropertyEntity prop1;
private NodePropertyEntity prop2; private NodePropertyEntity prop2;
private NodePropertyEntity prop3; private NodePropertyEntity prop3;
private String storeProtocol;
private String storeIdentifier;
// Supplemental query-related parameters // Supplemental query-related parameters
private Long parentNodeId; private Long parentNodeId;
private Long prop1qnameId; private Long prop1qnameId;
@@ -80,6 +87,26 @@ public class FilterSortNodeEntity
this.id = id; this.id = id;
} }
public String getNodeUuid()
{
return nodeUuid;
}
public void setNodeUuid(String nodeUuid)
{
this.nodeUuid = nodeUuid;
}
public Long getTypeQNameId()
{
return typeQNameId;
}
public void setTypeQNameId(Long typeQNameId)
{
this.typeQNameId = typeQNameId;
}
public String getPattern() public String getPattern()
{ {
return pattern; return pattern;
@@ -93,22 +120,21 @@ public class FilterSortNodeEntity
do do
{ {
idx = s.indexOf(escapeChar, offset); idx = s.indexOf(escapeChar, offset);
if(idx != -1) if (idx != -1)
{ {
sb.append(s.substring(offset, idx)); sb.append(s.substring(offset, idx));
sb.append("\\"); sb.append("\\");
sb.append(escapeChar); sb.append(escapeChar);
offset = idx + 1; offset = idx + 1;
} }
} } while (idx != -1);
while(idx != -1);
sb.append(s.substring(offset)); sb.append(s.substring(offset));
return sb.toString(); return sb.toString();
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
if(pattern != null) if (pattern != null)
{ {
// escape the '%' character with '\' (standard SQL escape character) // escape the '%' character with '\' (standard SQL escape character)
pattern = escape(pattern, '%'); pattern = escape(pattern, '%');
@@ -137,6 +163,16 @@ public class FilterSortNodeEntity
this.namePropertyQNameId = namePropertyQNameId; this.namePropertyQNameId = namePropertyQNameId;
} }
public AuditablePropertiesEntity getAuditablePropertiesEntity()
{
return auditablePropertiesEntity;
}
public void setAuditablePropertiesEntity(AuditablePropertiesEntity auditablePropertiesEntity)
{
this.auditablePropertiesEntity = auditablePropertiesEntity;
}
public NodePropertyEntity getProp1() public NodePropertyEntity getProp1()
{ {
return prop1; return prop1;
@@ -167,14 +203,24 @@ public class FilterSortNodeEntity
this.prop3 = prop3; this.prop3 = prop3;
} }
public NodeEntity getNode() public String getStoreProtocol()
{ {
return node; return storeProtocol;
} }
public void setNode(NodeEntity childNode) public void setStoreProtocol(String storeProtocol)
{ {
this.node = childNode; this.storeProtocol = storeProtocol;
}
public String getStoreIdentifier()
{
return storeIdentifier;
}
public void setStoreIdentifier(String storeIdentifier)
{
this.storeIdentifier = storeIdentifier;
} }
// Supplemental query-related parameters // Supplemental query-related parameters
@@ -258,4 +304,9 @@ public class FilterSortNodeEntity
{ {
this.isPrimary = isPrimary; this.isPrimary = isPrimary;
} }
public NodeRef createNodeRef()
{
return new NodeRef(new StoreRef(storeProtocol, storeIdentifier), nodeUuid);
}
} }

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -38,13 +38,16 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryParameters; import org.alfresco.query.CannedQueryParameters;
import org.alfresco.query.CannedQuerySortDetails; import org.alfresco.query.CannedQuerySortDetails;
import org.alfresco.query.CannedQuerySortDetails.SortOrder; import org.alfresco.query.CannedQuerySortDetails.SortOrder;
import org.alfresco.repo.domain.node.AuditablePropertiesEntity; import org.alfresco.repo.domain.node.AuditablePropertiesEntity;
import org.alfresco.repo.domain.node.Node;
import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.NodeEntity; import org.alfresco.repo.domain.node.NodeEntity;
import org.alfresco.repo.domain.node.NodePropertyEntity; import org.alfresco.repo.domain.node.NodePropertyEntity;
@@ -69,15 +72,11 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.AlfrescoCollator; import org.alfresco.util.AlfrescoCollator;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* GetChildren canned query * GetChildren canned query
* *
* To get paged list of children of a parent node filtered by child type. * To get paged list of children of a parent node filtered by child type. Also optionally filtered and/or sorted by one or more properties (up to three).
* Also optionally filtered and/or sorted by one or more properties (up to three).
* *
* @author janv * @author janv
* @since 4.0 * @since 4.0
@@ -100,7 +99,6 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
public static final QName FILTER_QNAME_NODE_IS_PRIMARY = QName.createQName("", "IS_PRIMARY"); public static final QName FILTER_QNAME_NODE_IS_PRIMARY = QName.createQName("", "IS_PRIMARY");
private NodeDAO nodeDAO; private NodeDAO nodeDAO;
private QNameDAO qnameDAO; private QNameDAO qnameDAO;
private CannedQueryDAO cannedQueryDAO; private CannedQueryDAO cannedQueryDAO;
@@ -135,8 +133,8 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
} }
// TODO refactor (only apply post query if sorted - as above) // TODO refactor (only apply post query if sorted - as above)
GetChildrenCannedQueryParams paramBean = (GetChildrenCannedQueryParams)params.getParameterBean(); GetChildrenCannedQueryParams paramBean = (GetChildrenCannedQueryParams) params.getParameterBean();
if ((paramBean.getFilterProps()!= null) && (paramBean.getFilterProps().size() > 0)) if ((paramBean.getFilterProps() != null) && (paramBean.getFilterProps().size() > 0))
{ {
applyPostQueryPermissions = true; applyPostQueryPermissions = true;
} }
@@ -163,7 +161,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null); Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
// Get parameters // Get parameters
GetChildrenCannedQueryParams paramBean = (GetChildrenCannedQueryParams)parameters.getParameterBean(); GetChildrenCannedQueryParams paramBean = (GetChildrenCannedQueryParams) parameters.getParameterBean();
// Get parent node // Get parent node
NodeRef parentRef = paramBean.getParentRef(); NodeRef parentRef = paramBean.getParentRef();
@@ -192,8 +190,8 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
// Get sort details // Get sort details
CannedQuerySortDetails sortDetails = parameters.getSortDetails(); CannedQuerySortDetails sortDetails = parameters.getSortDetails();
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
final List<Pair<QName, SortOrder>> sortPairs = (List)sortDetails.getSortPairs(); final List<Pair<QName, SortOrder>> sortPairs = (List) sortDetails.getSortPairs();
if (filterProps.size() > 0) if (filterProps.size() > 0)
{ {
@@ -203,9 +201,9 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
for (FilterProp filter : filterProps) for (FilterProp filter : filterProps)
{ {
if ((filter instanceof FilterPropBoolean) && if ((filter instanceof FilterPropBoolean) &&
((FilterPropBoolean)filter).getPropName().equals(FILTER_QNAME_NODE_IS_PRIMARY)) ((FilterPropBoolean) filter).getPropName().equals(FILTER_QNAME_NODE_IS_PRIMARY))
{ {
isPrimary = ((FilterPropBoolean)filter).getPropVal(); isPrimary = ((FilterPropBoolean) filter).getPropVal();
break; break;
} }
idx++; idx++;
@@ -223,17 +221,17 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
for (Pair<QName, SortOrder> sort : sortPairs) for (Pair<QName, SortOrder> sort : sortPairs)
{ {
QName sortQName = sort.getFirst(); QName sortQName = sort.getFirst();
if(! sortFilterProps.contains(sortQName)) if (!sortFilterProps.contains(sortQName))
{ {
sortFilterProps.add(sortQName); sortFilterProps.add(sortQName);
} }
} }
for (FilterProp filter : filterProps) for (FilterProp filter : filterProps)
{ {
QName filterQName = filter.getPropName(); QName filterQName = filter.getPropName();
if(! sortFilterProps.contains(filterQName)) if (!sortFilterProps.contains(filterQName))
{ {
sortFilterProps.add(filterQName); sortFilterProps.add(filterQName);
} }
} }
@@ -241,109 +239,108 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (filterSortPropCnt > MAX_FILTER_SORT_PROPS) if (filterSortPropCnt > MAX_FILTER_SORT_PROPS)
{ {
throw new AlfrescoRuntimeException("GetChildren: exceeded maximum number filter/sort properties: (max="+MAX_FILTER_SORT_PROPS+", actual="+filterSortPropCnt); throw new AlfrescoRuntimeException("GetChildren: exceeded maximum number filter/sort properties: (max=" + MAX_FILTER_SORT_PROPS + ", actual=" + filterSortPropCnt);
} }
filterSortPropCnt = setFilterSortParams(sortFilterProps, params); filterSortPropCnt = setFilterSortParams(sortFilterProps, params);
List<NodeRef> result = new ArrayList<>(0); List<NodeRef> result = new ArrayList<>(0);
try try
{ {
if ((childNodeTypeQNames != null) && (childNodeTypeQNames.size() > 0)) if ((childNodeTypeQNames != null) && (childNodeTypeQNames.size() > 0))
{ {
// Set child node type qnames (additional filter - performed by DB query) // Set child node type qnames (additional filter - performed by DB query)
Set<Long> childNodeTypeQNameIds = qnameDAO.convertQNamesToIds(childNodeTypeQNames, false); Set<Long> childNodeTypeQNameIds = qnameDAO.convertQNamesToIds(childNodeTypeQNames, false);
if (childNodeTypeQNameIds.size() > 0) if (childNodeTypeQNameIds.size() > 0)
{ {
params.setChildNodeTypeQNameIds(new ArrayList<Long>(childNodeTypeQNameIds)); params.setChildNodeTypeQNameIds(new ArrayList<Long>(childNodeTypeQNameIds));
} }
else else
{ {
// short-circuit - return no results - given node type qname(s) do not exist // short-circuit - return no results - given node type qname(s) do not exist
return result; return result;
} }
} }
if ((assocTypeQNames != null) && (assocTypeQNames.size() > 0)) if ((assocTypeQNames != null) && (assocTypeQNames.size() > 0))
{ {
// Set assoc type qnames (additional filter - performed by DB query) // Set assoc type qnames (additional filter - performed by DB query)
Set<Long> assocTypeQNameIds = qnameDAO.convertQNamesToIds(assocTypeQNames, false); Set<Long> assocTypeQNameIds = qnameDAO.convertQNamesToIds(assocTypeQNames, false);
if (assocTypeQNameIds.size() > 0) if (assocTypeQNameIds.size() > 0)
{ {
params.setAssocTypeQNameIds(assocTypeQNameIds); params.setAssocTypeQNameIds(assocTypeQNameIds);
} }
else else
{ {
// short-circuit - return no results - given assoc type qname(s) do not exist // short-circuit - return no results - given assoc type qname(s) do not exist
return result; return result;
} }
} }
if (pattern != null) if (pattern != null)
{ {
// TODO, check that we should be tied to the content model in this way. Perhaps a configurable property // TODO, check that we should be tied to the content model in this way. Perhaps a configurable property
// name against which compare the pattern? // name against which compare the pattern?
Pair<Long, QName> nameQName = qnameDAO.getQName(ContentModel.PROP_NAME); Pair<Long, QName> nameQName = qnameDAO.getQName(ContentModel.PROP_NAME);
if(nameQName == null) if (nameQName == null)
{ {
throw new AlfrescoRuntimeException("Unable to determine qname id of name property"); throw new AlfrescoRuntimeException("Unable to determine qname id of name property");
} }
params.setNamePropertyQNameId(nameQName.getFirst()); params.setNamePropertyQNameId(nameQName.getFirst());
params.setPattern(pattern); params.setPattern(pattern);
} }
if (filterSortPropCnt > 0) if (filterSortPropCnt > 0)
{ {
// filtered and/or sorted - note: permissions will be applied post query // filtered and/or sorted - note: permissions will be applied post query
final List<FilterSortNode> children = new ArrayList<FilterSortNode>(100); final List<FilterSortNode> children = new ArrayList<FilterSortNode>(100);
final FilterSortChildQueryCallback c = getFilterSortChildQuery(children, filterProps, paramBean); final FilterSortChildQueryCallback c = getFilterSortChildQuery(children, filterProps, paramBean);
FilterSortResultHandler resultHandler = new FilterSortResultHandler(c); FilterSortResultHandler resultHandler = new FilterSortResultHandler(c);
cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_CHILDREN_WITH_PROPS, params, 0, Integer.MAX_VALUE, resultHandler); cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_CHILDREN_WITH_PROPS, params, 0, Integer.MAX_VALUE, resultHandler);
resultHandler.done(); resultHandler.done();
if (sortPairs.size() > 0) if (sortPairs.size() > 0)
{ {
Long startSort = (logger.isDebugEnabled() ? System.currentTimeMillis() : null); Long startSort = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
// sort // sort
Collections.sort(children, new PropComparatorAsc(sortPairs)); Collections.sort(children, new PropComparatorAsc(sortPairs));
if (startSort != null) if (startSort != null)
{ {
logger.debug("Post-query sort: "+children.size()+" in "+(System.currentTimeMillis()-startSort)+" msecs"); logger.debug("Post-query sort: " + children.size() + " in " + (System.currentTimeMillis() - startSort) + " msecs");
} }
} }
result = new ArrayList<NodeRef>(children.size()); result = new ArrayList<NodeRef>(children.size());
for (FilterSortNode child : children) for (FilterSortNode child : children)
{ {
result.add(tenantService.getBaseName(child.getNodeRef())); result.add(tenantService.getBaseName(child.getNodeRef()));
} }
} }
else else
{ {
// unsorted (apart from any implicit order) - note: permissions are applied during result handling to allow early cutoff // unsorted (apart from any implicit order) - note: permissions are applied during result handling to allow early cutoff
final int requestedCount = parameters.getResultsRequired(); final int requestedCount = parameters.getResultsRequired();
final List<NodeRef> rawResult = new ArrayList<NodeRef>(Math.min(1000, requestedCount)); final List<NodeRef> rawResult = new ArrayList<NodeRef>(Math.min(1000, requestedCount));
UnsortedChildQueryCallback callback = getUnsortedChildQueryCallback(rawResult, requestedCount, paramBean); UnsortedChildQueryCallback callback = getUnsortedChildQueryCallback(rawResult, requestedCount, paramBean);
UnsortedResultHandler resultHandler = new UnsortedResultHandler(callback); UnsortedResultHandler resultHandler = new UnsortedResultHandler(callback);
cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_CHILDREN_WITHOUT_PROPS, params, 0, Integer.MAX_VALUE, resultHandler); cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_CHILDREN_WITHOUT_PROPS, params, 0, Integer.MAX_VALUE, resultHandler);
resultHandler.done(); resultHandler.done();
// permissions have been applied // permissions have been applied
result = PermissionCheckedValueMixin.create(rawResult); result = PermissionCheckedValueMixin.create(rawResult);
} }
} }
finally finally
{ {
if (start != null) if (start != null)
{ {
logger.debug("Base query "+(filterSortPropCnt > 0 ? "(sort=y, perms=n)" : "(sort=n, perms=y)")+": "+result.size()+" in "+(System.currentTimeMillis()-start)+" msecs"); logger.debug("Base query " + (filterSortPropCnt > 0 ? "(sort=y, perms=n)" : "(sort=n, perms=y)") + ": " + result.size() + " in " + (System.currentTimeMillis() - start) + " msecs");
} }
} }
return result; return result;
@@ -385,14 +382,14 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
else else
{ {
// belts and braces // belts and braces
throw new AlfrescoRuntimeException("GetChildren: unexpected - cannot set sort parameter: "+cnt); throw new AlfrescoRuntimeException("GetChildren: unexpected - cannot set sort parameter: " + cnt);
} }
propCnt++; propCnt++;
} }
else else
{ {
logger.warn("Skipping filter/sort param - cannot find: "+filterSortProp); logger.warn("Skipping filter/sort param - cannot find: " + filterSortProp);
break; break;
} }
} }
@@ -443,7 +440,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
Object pv1 = null; Object pv1 = null;
Object pv2 = null; Object pv2 = null;
QName sortPropQName = (QName)sortProps.get(0).getFirst(); QName sortPropQName = (QName) sortProps.get(0).getFirst();
boolean sortAscending = (sortProps.get(0).getSecond() == SortOrder.ASCENDING); boolean sortAscending = (sortProps.get(0).getSecond() == SortOrder.ASCENDING);
FilterSortNode node1 = node1In; FilterSortNode node1 = node1In;
@@ -462,7 +459,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (pv1 == null) if (pv1 == null)
{ {
if(pv2 == null && sortProps.size() > 1) if (pv2 == null && sortProps.size() > 1)
{ {
return compareImpl(node1In, node2In, sortProps.subList(1, sortProps.size())); return compareImpl(node1In, node2In, sortProps.subList(1, sortProps.size()));
} }
@@ -478,32 +475,32 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (pv1 instanceof String) if (pv1 instanceof String)
{ {
result = collator.compare((String)pv1, (String)pv2); // TODO use collation keys (re: performance) result = collator.compare((String) pv1, (String) pv2); // TODO use collation keys (re: performance)
} }
else if (pv1 instanceof Date) else if (pv1 instanceof Date)
{ {
result = (((Date)pv1).compareTo((Date)pv2)); result = (((Date) pv1).compareTo((Date) pv2));
} }
else if (pv1 instanceof Long) else if (pv1 instanceof Long)
{ {
result = (((Long)pv1).compareTo((Long)pv2)); result = (((Long) pv1).compareTo((Long) pv2));
} }
else if (pv1 instanceof Integer) else if (pv1 instanceof Integer)
{ {
result = (((Integer)pv1).compareTo((Integer)pv2)); result = (((Integer) pv1).compareTo((Integer) pv2));
} }
else if (pv1 instanceof QName) else if (pv1 instanceof QName)
{ {
result = (((QName)pv1).compareTo((QName)pv2)); result = (((QName) pv1).compareTo((QName) pv2));
} }
else if (pv1 instanceof Boolean) else if (pv1 instanceof Boolean)
{ {
result = (((Boolean)pv1).compareTo((Boolean)pv2)); result = (((Boolean) pv1).compareTo((Boolean) pv2));
} }
else else
{ {
// TODO other comparisons // TODO other comparisons
throw new RuntimeException("Unsupported sort type: "+pv1.getClass().getName()); throw new RuntimeException("Unsupported sort type: " + pv1.getClass().getName());
} }
if ((result == 0) && (sortProps.size() > 1)) if ((result == 0) && (sortProps.size() > 1))
@@ -555,68 +552,68 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
{ {
if ((filterProp instanceof FilterPropString) && (propVal instanceof String)) if ((filterProp instanceof FilterPropString) && (propVal instanceof String))
{ {
String val = (String)propVal; String val = (String) propVal;
String filter = (String)filterProp.getPropVal(); String filter = (String) filterProp.getPropVal();
switch ((FilterTypeString)filterProp.getFilterType()) switch ((FilterTypeString) filterProp.getFilterType())
{ {
case STARTSWITH: case STARTSWITH:
if (val.startsWith(filter)) if (val.startsWith(filter))
{ {
return true; return true;
} }
break; break;
case STARTSWITH_IGNORECASE: case STARTSWITH_IGNORECASE:
if (val.toLowerCase().startsWith(filter.toLowerCase())) if (val.toLowerCase().startsWith(filter.toLowerCase()))
{ {
return true; return true;
} }
break;
case EQUALS:
if (val.equals(filter))
{
return true;
}
break; break;
case EQUALS_IGNORECASE: case EQUALS:
if (val.equalsIgnoreCase(filter)) if (val.equals(filter))
{ {
return true; return true;
} }
break; break;
case ENDSWITH: case EQUALS_IGNORECASE:
if (val.endsWith(filter)) if (val.equalsIgnoreCase(filter))
{ {
return true; return true;
} }
break; break;
case ENDSWITH_IGNORECASE: case ENDSWITH:
if (val.toLowerCase().endsWith(filter.toLowerCase())) if (val.endsWith(filter))
{ {
return true; return true;
} }
break; break;
case MATCHES: case ENDSWITH_IGNORECASE:
if (val.matches(filter)) if (val.toLowerCase().endsWith(filter.toLowerCase()))
{ {
return true; return true;
} }
break; break;
case MATCHES_IGNORECASE: case MATCHES:
if (val.toLowerCase().matches(filter.toLowerCase())) if (val.matches(filter))
{ {
return true; return true;
} }
break; break;
default: case MATCHES_IGNORECASE:
if (val.toLowerCase().matches(filter.toLowerCase()))
{
return true;
}
break;
default:
} }
} }
} }
if ((filterProp instanceof FilterPropBoolean) && (propVal instanceof Boolean)) if ((filterProp instanceof FilterPropBoolean) && (propVal instanceof Boolean))
{ {
Boolean val = (Boolean)propVal; Boolean val = (Boolean) propVal;
Boolean filter = (Boolean)filterProp.getPropVal(); Boolean filter = (Boolean) filterProp.getPropVal();
return (val == filter); return (val == filter);
} }
@@ -649,7 +646,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (start != null) if (start != null)
{ {
logger.debug("Post-query perms: "+ret.size()+" in "+(System.currentTimeMillis()-start)+" msecs"); logger.debug("Post-query perms: " + ret.size() + " in " + (System.currentTimeMillis() - start) + " msecs");
} }
return ret; return ret;
@@ -663,7 +660,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (start != null) if (start != null)
{ {
logger.trace("Pre-load: "+nodeRefs.size()+" in "+(System.currentTimeMillis()-start)+" msecs"); logger.trace("Pre-load: " + nodeRefs.size() + " in " + (System.currentTimeMillis() - start) + " msecs");
} }
} }
@@ -697,7 +694,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
@Override @Override
public boolean handle(FilterSortNode node) public boolean handle(FilterSortNode node)
{ {
if(include(node)) if (include(node))
{ {
children.add(node); children.add(node);
} }
@@ -709,7 +706,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
protected boolean include(FilterSortNode node) protected boolean include(FilterSortNode node)
{ {
// filter, if needed // filter, if needed
return(!applyFilter || includeFilter(node.getPropVals(), filterProps)) && includeAspects(node.getNodeRef(), inclusiveAspects, exclusiveAspects); return (!applyFilter || includeFilter(node.getPropVals(), filterProps)) && includeAspects(node.getNodeRef(), inclusiveAspects, exclusiveAspects);
} }
} }
@@ -731,7 +728,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
@Override @Override
public boolean handle(NodeRef nodeRef) public boolean handle(NodeRef nodeRef)
{ {
if(include(nodeRef)) if (include(nodeRef))
{ {
rawResult.add(tenantService.getBaseName(nodeRef)); rawResult.add(tenantService.getBaseName(nodeRef));
} }
@@ -777,7 +774,8 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (results.size() >= BATCH_SIZE) if (results.size() >= BATCH_SIZE)
{ {
// batch // batch
preloadFilterSort(); preloadNodes();
filterSort();
} }
results.add(result); results.add(result);
@@ -790,24 +788,27 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (results.size() >= 0) if (results.size() >= 0)
{ {
// finish batch // finish batch
preloadFilterSort(); preloadNodes();
filterSort();
} }
} }
private void preloadFilterSort() private void preloadNodes()
{ {
List<NodeRef> nodeRefs = new ArrayList<>(results.size()); List<NodeRef> nodeRefs = new ArrayList<>(results.size());
for (FilterSortNodeEntity result : results) for (FilterSortNodeEntity result : results)
{ {
nodeRefs.add(result.getNode().getNodeRef()); nodeRefs.add(result.createNodeRef());
} }
preload(nodeRefs); preload(nodeRefs);
}
private void filterSort()
{
for (FilterSortNodeEntity result : results) for (FilterSortNodeEntity result : results)
{ {
Node node = result.getNode(); NodeRef nodeRef = result.createNodeRef();
NodeRef nodeRef = node.getNodeRef();
Map<NodePropertyKey, NodePropertyValue> propertyValues = new HashMap<NodePropertyKey, NodePropertyValue>(3); Map<NodePropertyKey, NodePropertyValue> propertyValues = new HashMap<NodePropertyKey, NodePropertyValue>(3);
@@ -832,7 +833,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
Map<QName, Serializable> propVals = nodePropertyHelper.convertToPublicProperties(propertyValues); Map<QName, Serializable> propVals = nodePropertyHelper.convertToPublicProperties(propertyValues);
// Add referenceable / spoofed properties (including spoofed name if null) // Add referenceable / spoofed properties (including spoofed name if null)
ReferenceablePropertiesEntity.addReferenceableProperties(node, propVals); ReferenceablePropertiesEntity.addReferenceableProperties(result.getId(), nodeRef, propVals);
// special cases // special cases
@@ -841,12 +842,12 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
{ {
if (entry.getValue() instanceof MLText) if (entry.getValue() instanceof MLText)
{ {
propVals.put(entry.getKey(), DefaultTypeConverter.INSTANCE.convert(String.class, (MLText)entry.getValue())); propVals.put(entry.getKey(), DefaultTypeConverter.INSTANCE.convert(String.class, (MLText) entry.getValue()));
} }
} }
// ContentData (eg. cm:content.size, cm:content.mimetype) // ContentData (eg. cm:content.size, cm:content.mimetype)
ContentData contentData = (ContentData)propVals.get(ContentModel.PROP_CONTENT); ContentData contentData = (ContentData) propVals.get(ContentModel.PROP_CONTENT);
if (contentData != null) if (contentData != null)
{ {
propVals.put(SORT_QNAME_CONTENT_SIZE, contentData.getSize()); propVals.put(SORT_QNAME_CONTENT_SIZE, contentData.getSize());
@@ -854,7 +855,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
} }
// Auditable props (eg. cm:creator, cm:created, cm:modifier, cm:modified, ...) // Auditable props (eg. cm:creator, cm:created, cm:modifier, cm:modified, ...)
AuditablePropertiesEntity auditableProps = node.getAuditableProperties(); AuditablePropertiesEntity auditableProps = result.getAuditablePropertiesEntity();
if (auditableProps != null) if (auditableProps != null)
{ {
for (Map.Entry<QName, Serializable> entry : auditableProps.getAuditableProperties().entrySet()) for (Map.Entry<QName, Serializable> entry : auditableProps.getAuditableProperties().entrySet())
@@ -864,7 +865,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
} }
// Node type // Node type
Long nodeTypeQNameId = node.getTypeQNameId(); Long nodeTypeQNameId = result.getTypeQNameId();
if (nodeTypeQNameId != null) if (nodeTypeQNameId != null)
{ {
Pair<Long, QName> pair = qnameDAO.getQName(nodeTypeQNameId); Pair<Long, QName> pair = qnameDAO.getQName(nodeTypeQNameId);

View File

@@ -133,6 +133,14 @@
<resultMap id="result_FilterSortNode" type="FilterSortNode"> <resultMap id="result_FilterSortNode" type="FilterSortNode">
<id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/> <id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<result property="nodeUuid" column="uuid" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="typeQNameId" column="type_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<result property="auditablePropertiesEntity.auditCreator" column="audit_creator" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="auditablePropertiesEntity.auditCreated" column="audit_created" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="auditablePropertiesEntity.auditModifier" column="audit_modifier" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="auditablePropertiesEntity.auditModified" column="audit_modified" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="auditablePropertiesEntity.auditAccessed" column="audit_accessed" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="prop1.nodeId" column="prop1_node_id" jdbcType="BIGINT" javaType="java.lang.Long"/> <result property="prop1.nodeId" column="prop1_node_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<result property="prop1.key.qnameId" column="prop1_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/> <result property="prop1.key.qnameId" column="prop1_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
@@ -170,7 +178,8 @@
<result property="prop3.value.doubleValue" column="prop3_double_value" jdbcType="FLOAT" javaType="java.lang.Double"/> <result property="prop3.value.doubleValue" column="prop3_double_value" jdbcType="FLOAT" javaType="java.lang.Double"/>
<result property="prop3.value.stringValue" column="prop3_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/> <result property="prop3.value.stringValue" column="prop3_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/>
<association property="node" resultMap="alfresco.node.result_Node"/> <result property="storeProtocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="storeIdentifier" column="identifier" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap> </resultMap>
@@ -972,8 +981,8 @@
</select> </select>
<!-- GetChildren - with explicit prop filtering and/or sorting --> <!-- GetChildren - with explicit prop filtering and/or sorting -->
<select id="select_GetChildrenCannedQueryWithProps" parameterType="FilterSortNode" resultMap="result_FilterSortNode"> <select id="select_GetChildrenCannedQueryWithProps" parameterType="FilterSortNode" resultMap="result_FilterSortNode" flushCache="true">
select select distinct
childNode.id as id, childNode.id as id,
childNode.version as version, childNode.version as version,
childStore.id as store_id, childStore.id as store_id,
@@ -989,7 +998,7 @@
childNode.audit_created as audit_created, childNode.audit_created as audit_created,
childNode.audit_modifier as audit_modifier, childNode.audit_modifier as audit_modifier,
childNode.audit_modified as audit_modified, childNode.audit_modified as audit_modified,
childNode.audit_accessed as audit_accessed childNode.audit_accessed as audit_accessed
<if test="prop1qnameId != null"> <if test="prop1qnameId != null">
, prop1.node_id as prop1_node_id, , prop1.node_id as prop1_node_id,
prop1.qname_id as prop1_qname_id, prop1.qname_id as prop1_qname_id,
@@ -1067,9 +1076,6 @@
#{item} #{item}
</foreach> </foreach>
</if> </if>
<if test="prop1qnameId == null and auditableProps == false">
<include refid="alfresco.node.select_ChildAssoc_OrderBy"/>
</if>
</select> </select>
<!-- GetChildren - with no explicit sorting (or prop filtering) - note: still filtered by child type (and optionally primary or secondary) --> <!-- GetChildren - with no explicit sorting (or prop filtering) - note: still filtered by child type (and optionally primary or secondary) -->