From 7fd71f5bd31fa0e4faf07cd296be665017a59c77 Mon Sep 17 00:00:00 2001 From: danielhanrahan Date: Tue, 2 May 2023 20:01:34 +0100 Subject: Fix and refactor query across anchors (CPS-1664 #3) - Fix CPS-1580: Query Across All Anchors Does NOT Filter on Dataspace - Fix CPS-1582: NullPointerException in queryDataNodesAcrossAnchors - Improve performance of queryDataNodesAcrossAnchors - Refactor queryDataNodes - Refactor FragmentQueryBuilder Issue-ID: CPS-1580 Signed-off-by: danielhanrahan Change-Id: I8b83d4c580280d8719ab2ac33f3914f53e798774 --- cps-ri/pom.xml | 2 +- .../cps/spi/entities/FragmentEntityArranger.java | 18 +++++ .../org/onap/cps/spi/entities/FragmentExtract.java | 4 +- .../spi/impl/CpsDataPersistenceServiceImpl.java | 47 +++++++---- .../cps/spi/repository/FragmentQueryBuilder.java | 94 +++++++++++++++------- .../cps/spi/repository/FragmentRepository.java | 37 +++++---- .../repository/FragmentRepositoryCpsPathQuery.java | 8 +- .../FragmentRepositoryCpsPathQueryImpl.java | 14 ++-- .../CpsQueryServiceIntegrationSpec.groovy | 4 - .../performance/cps/QueryPerfTest.groovy | 3 +- 10 files changed, 156 insertions(+), 75 deletions(-) diff --git a/cps-ri/pom.xml b/cps-ri/pom.xml index c38c13b7b..ea1efcb3e 100644 --- a/cps-ri/pom.xml +++ b/cps-ri/pom.xml @@ -33,7 +33,7 @@ cps-ri - 0.80 + 0.79 diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntityArranger.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntityArranger.java index 55d3c7e87..49e2dd253 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntityArranger.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentEntityArranger.java @@ -47,6 +47,24 @@ public class FragmentEntityArranger { return reuniteChildrenWithTheirParents(fragmentEntityPerId); } + /** + * Convert a collection of (related) FragmentExtracts into FragmentEntities (trees) with descendants. + * + * @param anchorEntityPerId the anchor(entities) the fragments belong to + * @param fragmentExtracts FragmentExtracts to convert + * @return a collection of FragmentEntities (trees) with descendants. + */ + public static Collection toFragmentEntityTreesAcrossAnchors( + final Map anchorEntityPerId, final Collection fragmentExtracts) { + final Map fragmentEntityPerId = new HashMap<>(); + for (final FragmentExtract fragmentExtract : fragmentExtracts) { + final AnchorEntity anchorEntity = anchorEntityPerId.get(fragmentExtract.getAnchorId()); + final FragmentEntity fragmentEntity = toFragmentEntity(anchorEntity, fragmentExtract); + fragmentEntityPerId.put(fragmentEntity.getId(), fragmentEntity); + } + return reuniteChildrenWithTheirParents(fragmentEntityPerId); + } + private static FragmentEntity toFragmentEntity(final AnchorEntity anchorEntity, final FragmentExtract fragmentExtract) { final FragmentEntity fragmentEntity = new FragmentEntity(); diff --git a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentExtract.java b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentExtract.java index 52c1a603b..3aa19e670 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentExtract.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/entities/FragmentExtract.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022-2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ public interface FragmentExtract { Long getId(); - Long getAnchorId(); + Integer getAnchorId(); String getXpath(); diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index 3a1588a59..be5c66db9 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -36,6 +36,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -316,8 +317,9 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService description = "Time taken to query data nodes") public List queryDataNodes(final String dataspaceName, final String anchorName, final String cpsPath, final FetchDescendantsOption fetchDescendantsOption) { - final AnchorEntity anchorEntity = (Strings.isNullOrEmpty(anchorName)) ? ALL_ANCHORS - : getAnchorEntity(dataspaceName, anchorName); + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final AnchorEntity anchorEntity = Strings.isNullOrEmpty(anchorName) ? ALL_ANCHORS + : anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName); final CpsPathQuery cpsPathQuery; try { cpsPathQuery = CpsPathUtil.getCpsPathQuery(cpsPath); @@ -327,21 +329,30 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService Collection fragmentEntities; if (canUseRegexQuickFind(fetchDescendantsOption, cpsPathQuery)) { - return getDataNodesUsingRegexQuickFind(fetchDescendantsOption, anchorEntity, cpsPathQuery); + return getDataNodesUsingRegexQuickFind(fetchDescendantsOption, dataspaceEntity, anchorEntity, cpsPathQuery); + } + + if (anchorEntity == ALL_ANCHORS) { + fragmentEntities = fragmentRepository.findByDataspaceAndCpsPath(dataspaceEntity, cpsPathQuery); + } else { + fragmentEntities = fragmentRepository.findByAnchorAndCpsPath(anchorEntity, cpsPathQuery); } - fragmentEntities = (anchorEntity == ALL_ANCHORS) ? fragmentRepository.findByCpsPath(cpsPathQuery) - : fragmentRepository.findByAnchorAndCpsPath(anchorEntity.getId(), cpsPathQuery); + if (cpsPathQuery.hasAncestorAxis()) { final Collection ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); - fragmentEntities = (anchorEntity == ALL_ANCHORS) ? getAncestorFragmentEntitiesAcrossAnchors(cpsPathQuery, - fragmentEntities) : getFragmentEntities(anchorEntity, ancestorXpaths, fetchDescendantsOption); + if (anchorEntity == ALL_ANCHORS) { + fragmentEntities = fragmentRepository.findByDataspaceAndXpathIn(dataspaceEntity, ancestorXpaths); + } else { + fragmentEntities = fragmentRepository.findByAnchorAndXpathIn(anchorEntity, ancestorXpaths); + } } + return createDataNodesFromProxiedFragmentEntities(fetchDescendantsOption, anchorEntity, fragmentEntities); } @Override public List queryDataNodesAcrossAnchors(final String dataspaceName, final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { + final FetchDescendantsOption fetchDescendantsOption) { return queryDataNodes(dataspaceName, QUERY_ACROSS_ANCHORS, cpsPath, fetchDescendantsOption); } @@ -355,21 +366,29 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } private List getDataNodesUsingRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption, + final DataspaceEntity dataspaceEntity, final AnchorEntity anchorEntity, final CpsPathQuery cpsPathQuery) { final String xpathRegex = FragmentQueryBuilder.getXpathSqlRegexForQuickFindWithDescendants(cpsPathQuery); final List fragmentExtracts = (anchorEntity == ALL_ANCHORS) - ? fragmentRepository.quickFindWithDescendantsAcrossAnchors(xpathRegex) + ? fragmentRepository.quickFindWithDescendantsAcrossAnchors(dataspaceEntity.getId(), xpathRegex) : fragmentRepository.quickFindWithDescendants(anchorEntity.getId(), xpathRegex); final Collection fragmentEntities = - FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts); + createFragmentEntitiesFromFragmentExtracts(anchorEntity, fragmentExtracts); return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities); } - private Collection getAncestorFragmentEntitiesAcrossAnchors(final CpsPathQuery cpsPathQuery, - final Collection fragmentEntities) { - final Collection ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); - return ancestorXpaths.isEmpty() ? Collections.emptyList() : fragmentRepository.findAllByXpathIn(ancestorXpaths); + private Collection createFragmentEntitiesFromFragmentExtracts( + final AnchorEntity anchorEntity, final Collection fragmentExtracts) { + if (anchorEntity == ALL_ANCHORS) { + final Collection anchorIds = fragmentExtracts.stream() + .map(FragmentExtract::getAnchorId).collect(Collectors.toSet()); + final List anchorEntities = anchorRepository.findAllById(anchorIds); + final Map anchorEntityPerId = anchorEntities.stream() + .collect(Collectors.toMap(AnchorEntity::getId, Function.identity())); + return FragmentEntityArranger.toFragmentEntityTreesAcrossAnchors(anchorEntityPerId, fragmentExtracts); + } + return FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts); } private List createDataNodesFromProxiedFragmentEntities( diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java index 013487334..515bbd616 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +33,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.cpspath.parser.CpsPathPrefixType; import org.onap.cps.cpspath.parser.CpsPathQuery; +import org.onap.cps.spi.entities.AnchorEntity; +import org.onap.cps.spi.entities.DataspaceEntity; import org.onap.cps.spi.entities.FragmentEntity; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Component; @@ -45,6 +47,7 @@ public class FragmentQueryBuilder { private static final String REGEX_DESCENDANT_PATH_PREFIX = "^.*\\/"; private static final String REGEX_OPTIONAL_LIST_INDEX_POSTFIX = "(\\[@(?!.*\\[).*?])?$"; private static final String REGEX_FOR_QUICK_FIND_WITH_DESCENDANTS = "(\\[@.*?])?(\\/.*)?$"; + private static final AnchorEntity ACROSS_ALL_ANCHORS = null; @PersistenceContext private EntityManager entityManager; @@ -54,28 +57,24 @@ public class FragmentQueryBuilder { /** * Create a sql query to retrieve by anchor(id) and cps path. * - * @param anchorId the id of the anchor + * @param anchorEntity the anchor * @param cpsPathQuery the cps path query to be transformed into a sql query * @return a executable query object */ - public Query getQueryForAnchorAndCpsPath(final int anchorId, final CpsPathQuery cpsPathQuery) { - final StringBuilder sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT WHERE anchor_id = :anchorId"); - final Map queryParameters = new HashMap<>(); - queryParameters.put("anchorId", anchorId); - sqlStringBuilder.append(" AND xpath ~ :xpathRegex"); - return getQuery(cpsPathQuery, sqlStringBuilder, queryParameters); + public Query getQueryForAnchorAndCpsPath(final AnchorEntity anchorEntity, final CpsPathQuery cpsPathQuery) { + return getQueryForDataspaceOrAnchorAndCpsPath(anchorEntity.getDataspace(), anchorEntity, cpsPathQuery); } /** * Create a sql query to retrieve by cps path. * + * @param dataspaceEntity the dataspace * @param cpsPathQuery the cps path query to be transformed into a sql query * @return a executable query object */ - public Query getQueryForCpsPath(final CpsPathQuery cpsPathQuery) { - final StringBuilder sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT WHERE xpath ~ :xpathRegex"); - final Map queryParameters = new HashMap<>(); - return getQuery(cpsPathQuery, sqlStringBuilder, queryParameters); + public Query getQueryForDataspaceAndCpsPath(final DataspaceEntity dataspaceEntity, + final CpsPathQuery cpsPathQuery) { + return getQueryForDataspaceOrAnchorAndCpsPath(dataspaceEntity, ACROSS_ALL_ANCHORS, cpsPathQuery); } /** @@ -103,31 +102,45 @@ public class FragmentQueryBuilder { return xpathRegexBuilder.toString(); } - private Query getQuery(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder, - final Map queryParameters) { - final String xpathRegex = getXpathSqlRegex(cpsPathQuery); - queryParameters.put("xpathRegex", xpathRegex); - final List queryBooleanOperatorsType = cpsPathQuery.getBooleanOperatorsType(); - if (cpsPathQuery.hasLeafConditions()) { - sqlStringBuilder.append(" AND ("); - final Queue booleanOperatorsQueue = (queryBooleanOperatorsType == null) ? null : new LinkedList<>( - queryBooleanOperatorsType); - cpsPathQuery.getLeavesData().entrySet().forEach(entry -> { - sqlStringBuilder.append(" attributes @> "); - sqlStringBuilder.append("'" + jsonObjectMapper.asJsonString(entry) + "'"); - if (!(booleanOperatorsQueue == null || booleanOperatorsQueue.isEmpty())) { - sqlStringBuilder.append(" " + booleanOperatorsQueue.poll() + " "); - } - }); - sqlStringBuilder.append(")"); - } + private Query getQueryForDataspaceOrAnchorAndCpsPath(final DataspaceEntity dataspaceEntity, + final AnchorEntity anchorEntity, + final CpsPathQuery cpsPathQuery) { + final StringBuilder sqlStringBuilder = new StringBuilder(); + final Map queryParameters = new HashMap<>(); + + sqlStringBuilder.append("SELECT * FROM fragment WHERE "); + addDataspaceOrAnchor(sqlStringBuilder, queryParameters, dataspaceEntity, anchorEntity); + addXpathSearch(cpsPathQuery, sqlStringBuilder, queryParameters); + addLeafConditions(cpsPathQuery, sqlStringBuilder); addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters); addContainsFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters); + final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class); setQueryParameters(query, queryParameters); return query; } + private static void addDataspaceOrAnchor(final StringBuilder sqlStringBuilder, + final Map queryParameters, + final DataspaceEntity dataspaceEntity, + final AnchorEntity anchorEntity) { + if (anchorEntity == ACROSS_ALL_ANCHORS) { + sqlStringBuilder.append("dataspace_id = :dataspaceId"); + queryParameters.put("dataspaceId", dataspaceEntity.getId()); + } else { + sqlStringBuilder.append("anchor_id = :anchorId"); + queryParameters.put("anchorId", anchorEntity.getId()); + } + } + + private static void addXpathSearch(final CpsPathQuery cpsPathQuery, + final StringBuilder sqlStringBuilder, + final Map queryParameters) { + sqlStringBuilder.append(" AND xpath ~ :xpathRegex"); + final String xpathRegex = getXpathSqlRegex(cpsPathQuery); + queryParameters.put("xpathRegex", xpathRegex); + } + private static StringBuilder getRegexStringBuilderWithPrefix(final CpsPathQuery cpsPathQuery) { final StringBuilder xpathRegexBuilder = new StringBuilder(); if (CpsPathPrefixType.ABSOLUTE.equals(cpsPathQuery.getCpsPathPrefixType())) { @@ -153,6 +166,27 @@ public class FragmentQueryBuilder { } } + private void addLeafConditions(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder) { + if (cpsPathQuery.hasLeafConditions()) { + sqlStringBuilder.append(" AND ("); + final List queryBooleanOperatorsType = cpsPathQuery.getBooleanOperatorsType(); + final Queue booleanOperatorsQueue = (queryBooleanOperatorsType == null) ? null : new LinkedList<>( + queryBooleanOperatorsType); + cpsPathQuery.getLeavesData().entrySet().forEach(entry -> { + sqlStringBuilder.append(" attributes @> "); + sqlStringBuilder.append("'"); + sqlStringBuilder.append(jsonObjectMapper.asJsonString(entry)); + sqlStringBuilder.append("'"); + if (!(booleanOperatorsQueue == null || booleanOperatorsQueue.isEmpty())) { + sqlStringBuilder.append(" "); + sqlStringBuilder.append(booleanOperatorsQueue.poll()); + sqlStringBuilder.append(" "); + } + }); + sqlStringBuilder.append(")"); + } + } + private static void addTextFunctionCondition(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder, final Map queryParameters) { diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java index f389467a5..d20e4d35a 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java @@ -27,6 +27,7 @@ import java.util.Collection; import java.util.List; import java.util.Optional; import org.onap.cps.spi.entities.AnchorEntity; +import org.onap.cps.spi.entities.DataspaceEntity; import org.onap.cps.spi.entities.FragmentEntity; import org.onap.cps.spi.entities.FragmentExtract; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; @@ -46,18 +47,25 @@ public interface FragmentRepository extends JpaRepository, new DataNodeNotFoundException(anchorEntity.getDataspace().getName(), anchorEntity.getName(), xpath)); } - boolean existsByAnchorId(int anchorId); + List findByAnchorIdAndXpathIn(int anchorId, String[] xpaths); - @Query("SELECT f FROM FragmentEntity f WHERE anchor = :anchor") - List findAllExtractsByAnchor(@Param("anchor") AnchorEntity anchorEntity); + default List findByAnchorAndXpathIn(final AnchorEntity anchorEntity, + final Collection xpaths) { + return findByAnchorIdAndXpathIn(anchorEntity.getId(), xpaths.toArray(new String[0])); + } - @Query(value = "SELECT * FROM fragment WHERE xpath = ANY (:xpaths)", nativeQuery = true) - List findAllByXpathIn(@Param("xpaths") String[] xpath); + List findByDataspaceIdAndXpathIn(int dataspaceId, String[] xpaths); - default List findAllByXpathIn(final Collection xpaths) { - return findAllByXpathIn(xpaths.toArray(new String[0])); + default List findByDataspaceAndXpathIn(final DataspaceEntity dataspaceEntity, + final Collection xpaths) { + return findByDataspaceIdAndXpathIn(dataspaceEntity.getId(), xpaths.toArray(new String[0])); } + boolean existsByAnchorId(int anchorId); + + @Query("SELECT f FROM FragmentEntity f WHERE anchor = :anchor") + List findAllExtractsByAnchor(@Param("anchor") AnchorEntity anchorEntity); + @Modifying @Query(value = "DELETE FROM fragment WHERE anchor_id = ANY (:anchorIds)", nativeQuery = true) void deleteByAnchorIdIn(@Param("anchorIds") int[] anchorIds); @@ -92,12 +100,18 @@ public interface FragmentRepository extends JpaRepository, @Query(value = "SELECT id, anchor_id AS anchorId, xpath, parent_id AS parentId," + " CAST(attributes AS TEXT) AS attributes" - + " FROM FRAGMENT WHERE anchor_id = :anchorId" - + " AND xpath ~ :xpathRegex", + + " FROM FRAGMENT WHERE anchor_id = :anchorId AND xpath ~ :xpathRegex", nativeQuery = true) List quickFindWithDescendants(@Param("anchorId") int anchorId, @Param("xpathRegex") String xpathRegex); + @Query(value = "SELECT id, anchor_id AS anchorId, xpath, parent_id AS parentId," + + " CAST(attributes AS TEXT) AS attributes" + + " FROM FRAGMENT WHERE dataspace_id = :dataspaceId AND xpath ~ :xpathRegex", + nativeQuery = true) + List quickFindWithDescendantsAcrossAnchors(@Param("dataspaceId") int dataspaceId, + @Param("xpathRegex") String xpathRegex); + @Query(value = "SELECT xpath FROM fragment WHERE anchor_id = :anchorId AND xpath = ANY (:xpaths)", nativeQuery = true) List findAllXpathByAnchorIdAndXpathIn(@Param("anchorId") int anchorId, @@ -136,9 +150,4 @@ public interface FragmentRepository extends JpaRepository, return findExtractsWithDescendants(anchorId, xpaths.toArray(new String[0]), maxDepth); } - @Query(value = "SELECT id, anchor_id AS anchorId, xpath, parent_id AS parentId," - + " CAST(attributes AS TEXT) AS attributes" - + " FROM FRAGMENT WHERE xpath ~ :xpathRegex", - nativeQuery = true) - List quickFindWithDescendantsAcrossAnchors(@Param("xpathRegex") String xpathRegex); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQuery.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQuery.java index 32041e7d5..de0c06014 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQuery.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQuery.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. + * Copyright (C) 2021-2023 Nordix Foundation. * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,10 +23,12 @@ package org.onap.cps.spi.repository; import java.util.List; import org.onap.cps.cpspath.parser.CpsPathQuery; +import org.onap.cps.spi.entities.AnchorEntity; +import org.onap.cps.spi.entities.DataspaceEntity; import org.onap.cps.spi.entities.FragmentEntity; public interface FragmentRepositoryCpsPathQuery { - List findByAnchorAndCpsPath(int anchorId, CpsPathQuery cpsPathQuery); + List findByAnchorAndCpsPath(AnchorEntity anchorEntity, CpsPathQuery cpsPathQuery); - List findByCpsPath(CpsPathQuery cpsPathQuery); + List findByDataspaceAndCpsPath(DataspaceEntity dataspaceEntity, CpsPathQuery cpsPathQuery); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQueryImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQueryImpl.java index b95491cd3..6cc6495b8 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQueryImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryCpsPathQueryImpl.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation. + * Copyright (C) 2021-2023 Nordix Foundation. * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,6 +29,8 @@ import javax.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.cpspath.parser.CpsPathQuery; +import org.onap.cps.spi.entities.AnchorEntity; +import org.onap.cps.spi.entities.DataspaceEntity; import org.onap.cps.spi.entities.FragmentEntity; @RequiredArgsConstructor @@ -42,8 +44,9 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps @Override @Transactional - public List findByAnchorAndCpsPath(final int anchorId, final CpsPathQuery cpsPathQuery) { - final Query query = fragmentQueryBuilder.getQueryForAnchorAndCpsPath(anchorId, cpsPathQuery); + public List findByAnchorAndCpsPath(final AnchorEntity anchorEntity, + final CpsPathQuery cpsPathQuery) { + final Query query = fragmentQueryBuilder.getQueryForAnchorAndCpsPath(anchorEntity, cpsPathQuery); final List fragmentEntities = query.getResultList(); log.debug("Fetched {} fragment entities by anchor and cps path.", fragmentEntities.size()); return fragmentEntities; @@ -51,8 +54,9 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps @Override @Transactional - public List findByCpsPath(final CpsPathQuery cpsPathQuery) { - final Query query = fragmentQueryBuilder.getQueryForCpsPath(cpsPathQuery); + public List findByDataspaceAndCpsPath(final DataspaceEntity dataspaceEntity, + final CpsPathQuery cpsPathQuery) { + final Query query = fragmentQueryBuilder.getQueryForDataspaceAndCpsPath(dataspaceEntity, cpsPathQuery); final List fragmentEntities = query.getResultList(); log.debug("Fetched {} fragment entities by cps path across all anchors.", fragmentEntities.size()); return fragmentEntities; diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy index 4e596da14..d64617caf 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy @@ -25,7 +25,6 @@ import org.onap.cps.api.CpsQueryService import org.onap.cps.integration.base.FunctionalSpecBase import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.exceptions.CpsPathException -import spock.lang.Ignore import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS @@ -235,7 +234,6 @@ class CpsQueryServiceIntegrationSpec extends FunctionalSpecBase { thrown(CpsPathException) } - @Ignore def 'Cps Path query across anchors with #scenario.'() { when: 'a query is executed to get a data nodes across anchors by the given CpsPath' def result = objectUnderTest.queryDataNodesAcrossAnchors(FUNCTIONAL_TEST_DATASPACE_1, cpsPath, OMIT_DESCENDANTS) @@ -261,7 +259,6 @@ class CpsQueryServiceIntegrationSpec extends FunctionalSpecBase { 'ancestor combined with text condition' | '//books/title[text()="Matilda"]/ancestor::bookstore' || ["/bookstore"] } - @Ignore def 'Cps Path query across anchors with #scenario descendants.'() { when: 'a query is executed to get a data node by the given cps path' def result = objectUnderTest.queryDataNodesAcrossAnchors(FUNCTIONAL_TEST_DATASPACE_1, '/bookstore', fetchDescendantsOption) @@ -276,7 +273,6 @@ class CpsQueryServiceIntegrationSpec extends FunctionalSpecBase { 'all' | INCLUDE_ALL_DESCENDANTS || 17 } - @Ignore def 'Cps Path query across anchors with ancestors and #scenario descendants.'() { when: 'a query is executed to get a data node by the given cps path' def result = objectUnderTest.queryDataNodesAcrossAnchors(FUNCTIONAL_TEST_DATASPACE_1, '//books/ancestor::bookstore', fetchDescendantsOption) diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/QueryPerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/QueryPerfTest.groovy index 065365748..0af01ac77 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/QueryPerfTest.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/QueryPerfTest.groovy @@ -63,8 +63,7 @@ class QueryPerfTest extends CpsPerfTestBase { recordAndAssertPerformance("Query across anchors ${scenario}", durationLimit, durationInMillis) where: 'the following parameters are used' scenario | cpspath || durationLimit | expectedNumberOfDataNodes - // FIXME Current implementation of queryDataNodesAcrossAnchors throws NullPointerException for next case. Uncomment after CPS-1582 is done. - // 'top element' | '/openroadm-devices' || 1 | 5 * (50 * 86 + 1) + 'top element' | '/openroadm-devices' || 1 | 5 * (50 * 86 + 1) 'leaf condition' | '//openroadm-device[@ne-state="inservice"]' || 2500 | 5 * (50 * 86) 'ancestors' | '//openroadm-device/ancestor::openroadm-devices' || 12000 | 5 * (50 * 86 + 1) 'leaf condition + ancestors' | '//openroadm-device[@status="success"]/ancestor::openroadm-devices' || 1000 | 5 * (50 * 86 + 1) -- cgit 1.2.3-korg