aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java12
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentQueryBuilder.java19
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQuery.java4
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQueryImpl.java9
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java16
-rw-r--r--cps-service/src/main/java/org/onap/cps/impl/CpsQueryServiceImpl.java18
-rw-r--r--cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java17
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/impl/CpsQueryServiceImplSpec.groovy19
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy13
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/QueryPerfTest.groovy1
10 files changed, 117 insertions, 11 deletions
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java
index ac6fe38ee7..e102765a64 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/CpsDataPersistenceServiceImpl.java
@@ -23,6 +23,7 @@
package org.onap.cps.ri;
+import static org.onap.cps.api.CpsQueryService.NO_LIMIT;
import static org.onap.cps.api.parameters.PaginationOption.NO_PAGINATION;
import com.google.common.collect.ImmutableSet;
@@ -223,10 +224,19 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
description = "Time taken to query data nodes")
public List<DataNode> queryDataNodes(final String dataspaceName, final String anchorName, final String cpsPath,
final FetchDescendantsOption fetchDescendantsOption) {
+ return queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption, NO_LIMIT);
+ }
+
+ @Override
+ public List<DataNode> queryDataNodes(final String dataspaceName,
+ final String anchorName,
+ final String cpsPath,
+ final FetchDescendantsOption fetchDescendantsOption,
+ final int queryResultLimit) {
final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName);
final CpsPathQuery cpsPathQuery = getCpsPathQuery(cpsPath);
final Collection<FragmentEntity> fragmentEntities =
- fragmentRepository.findByAnchorAndCpsPath(anchorEntity, cpsPathQuery);
+ fragmentRepository.findByAnchorAndCpsPath(anchorEntity, cpsPathQuery, queryResultLimit);
return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities);
}
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentQueryBuilder.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentQueryBuilder.java
index 3f3ca79900..bf354be024 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentQueryBuilder.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentQueryBuilder.java
@@ -51,13 +51,18 @@ public class FragmentQueryBuilder {
private EntityManager entityManager;
/**
- * Create a sql query to retrieve by anchor(id) and cps path.
+ * Create a sql query to retrieve by anchor(id) and cps path with an optional queryResultLimit on results.
*
* @param anchorEntity the anchor
* @param cpsPathQuery the cps path query to be transformed into a sql query
+ * @param queryResultLimit queryResultLimit number of returned entities
+ * (if the queryResultLimit is less than 1 the method returns all related entities)
+ *
* @return a executable query object
*/
- public Query getQueryForAnchorAndCpsPath(final AnchorEntity anchorEntity, final CpsPathQuery cpsPathQuery) {
+ public Query getQueryForAnchorAndCpsPath(final AnchorEntity anchorEntity,
+ final CpsPathQuery cpsPathQuery,
+ final int queryResultLimit) {
final StringBuilder sqlStringBuilder = new StringBuilder();
final Map<String, Object> queryParameters = new HashMap<>();
@@ -65,6 +70,7 @@ public class FragmentQueryBuilder {
addWhereClauseForAnchor(anchorEntity, sqlStringBuilder, queryParameters);
addNodeSearchConditions(cpsPathQuery, sqlStringBuilder, queryParameters, false);
addSearchSuffix(cpsPathQuery, sqlStringBuilder, queryParameters);
+ addLimitClause(sqlStringBuilder, queryParameters, queryResultLimit);
return getQuery(sqlStringBuilder.toString(), queryParameters, FragmentEntity.class);
}
@@ -219,6 +225,15 @@ public class FragmentQueryBuilder {
}
}
+ private static void addLimitClause(final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters,
+ final int queryResultLimit) {
+ if (queryResultLimit > 0) {
+ sqlStringBuilder.append(" LIMIT :queryResultLimit");
+ queryParameters.put("queryResultLimit", queryResultLimit);
+ }
+ }
+
private static Integer getTextValueAsInt(final CpsPathQuery cpsPathQuery) {
try {
return Integer.parseInt(cpsPathQuery.getTextFunctionConditionValue());
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQuery.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQuery.java
index 9c1929eaf7..4ee6555b79 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQuery.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQuery.java
@@ -29,7 +29,9 @@ import org.onap.cps.ri.models.DataspaceEntity;
import org.onap.cps.ri.models.FragmentEntity;
public interface FragmentRepositoryCpsPathQuery {
- List<FragmentEntity> findByAnchorAndCpsPath(AnchorEntity anchorEntity, CpsPathQuery cpsPathQuery);
+
+ List<FragmentEntity> findByAnchorAndCpsPath(AnchorEntity anchorEntity, CpsPathQuery cpsPathQuery,
+ int queryResultLimit);
List<FragmentEntity> findByDataspaceAndCpsPath(DataspaceEntity dataspaceEntity,
CpsPathQuery cpsPathQuery, List<Long> anchorIds);
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQueryImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQueryImpl.java
index e8c2725670..80fbe9b6cd 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQueryImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/FragmentRepositoryCpsPathQueryImpl.java
@@ -41,10 +41,15 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps
@Override
@Transactional
public List<FragmentEntity> findByAnchorAndCpsPath(final AnchorEntity anchorEntity,
- final CpsPathQuery cpsPathQuery) {
- final Query query = fragmentQueryBuilder.getQueryForAnchorAndCpsPath(anchorEntity, cpsPathQuery);
+ final CpsPathQuery cpsPathQuery,
+ final int queryResultLimit) {
+ final Query query = fragmentQueryBuilder
+ .getQueryForAnchorAndCpsPath(anchorEntity, cpsPathQuery, queryResultLimit);
final List<FragmentEntity> fragmentEntities = query.getResultList();
log.debug("Fetched {} fragment entities by anchor and cps path.", fragmentEntities.size());
+ if (queryResultLimit > 0) {
+ log.debug("Result limited to {} entries", queryResultLimit);
+ }
return fragmentEntities;
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java b/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java
index d783b9ed0e..3044fe0a90 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java
@@ -32,6 +32,8 @@ import org.onap.cps.api.parameters.PaginationOption;
*/
public interface CpsQueryService {
+ public static int NO_LIMIT = 0;
+
/**
* Get data nodes for the given dataspace and anchor by cps path.
*
@@ -45,6 +47,20 @@ public interface CpsQueryService {
Collection<DataNode> queryDataNodes(String dataspaceName, String anchorName,
String cpsPath, FetchDescendantsOption fetchDescendantsOption);
+ /**
+ * Retrieves a collection of data nodes based on the specified CPS path query.
+ *
+ * @param dataspaceName the name of the dataspace (must not be null or empty)
+ * @param anchorName the name of the anchor (must not be null or empty)
+ * @param cpsPath the CPS path used for querying (must not be null or empty)
+ * @param fetchDescendantsOption specifies whether to include descendant nodes in the output
+ * @param queryResultLimit the maximum number of data nodes to return; if less than 1, returns all matching nodes
+ *
+ * @return a collection of matching {@link DataNode} instances (can be empty if no nodes are found)
+ */
+ Collection<DataNode> queryDataNodes(String dataspaceName, String anchorName,
+ String cpsPath, FetchDescendantsOption fetchDescendantsOption,
+ int queryResultLimit);
/**
* Get data leaf for the given dataspace and anchor by cps path.
diff --git a/cps-service/src/main/java/org/onap/cps/impl/CpsQueryServiceImpl.java b/cps-service/src/main/java/org/onap/cps/impl/CpsQueryServiceImpl.java
index 508a1b2449..f27445f7c9 100644
--- a/cps-service/src/main/java/org/onap/cps/impl/CpsQueryServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/impl/CpsQueryServiceImpl.java
@@ -46,8 +46,22 @@ public class CpsQueryServiceImpl implements CpsQueryService {
public Collection<DataNode> queryDataNodes(final String dataspaceName, final String anchorName,
final String cpsPath,
final FetchDescendantsOption fetchDescendantsOption) {
- cpsValidator.validateNameCharacters(dataspaceName, anchorName);
- return cpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption);
+ return queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption, NO_LIMIT);
+ }
+
+ @Override
+ @Timed(value = "cps.data.service.datanode.query",
+ description = "Time taken to query data nodes with a limit on results")
+ public Collection<DataNode> queryDataNodes(final String dataSpaceName, final String anchorName,
+ final String cpsPath,
+ final FetchDescendantsOption fetchDescendantsOption,
+ final int queryResultLimit) {
+ cpsValidator.validateNameCharacters(dataSpaceName, anchorName);
+ return cpsDataPersistenceService.queryDataNodes(dataSpaceName,
+ anchorName,
+ cpsPath,
+ fetchDescendantsOption,
+ queryResultLimit);
}
@Override
diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
index a4f05cdb53..5be5fb0481 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
@@ -186,6 +186,23 @@ public interface CpsDataPersistenceService {
String cpsPath, FetchDescendantsOption fetchDescendantsOption);
/**
+ * Get a datanode by cps path.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorName anchor name
+ * @param cpsPath cps path
+ * @param fetchDescendantsOption defines whether the descendants of the node(s) found by the query should be
+ * included in the output
+ * @param queryResultLimit limits the number of returned entities (if less than 1 returns all)
+ *
+ * @return the data nodes found i.e. 0 or more data nodes
+ */
+ List<DataNode> queryDataNodes(String dataspaceName,
+ String anchorName,
+ String cpsPath, FetchDescendantsOption fetchDescendantsOption,
+ int queryResultLimit);
+
+ /**
* Get data leaf for the given dataspace and anchor by cps path.
*
* @param dataspaceName dataspace name
diff --git a/cps-service/src/test/groovy/org/onap/cps/impl/CpsQueryServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/impl/CpsQueryServiceImplSpec.groovy
index b15ee72370..9db4aa4c3e 100644
--- a/cps-service/src/test/groovy/org/onap/cps/impl/CpsQueryServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/impl/CpsQueryServiceImplSpec.groovy
@@ -21,7 +21,7 @@
package org.onap.cps.impl
-
+import org.onap.cps.api.CpsQueryService
import org.onap.cps.utils.CpsValidator
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.api.parameters.FetchDescendantsOption
@@ -42,7 +42,7 @@ class CpsQueryServiceImplSpec extends Specification {
when: 'queryDataNodes is invoked'
objectUnderTest.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption)
then: 'the persistence service is called once with the correct parameters'
- 1 * mockCpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption)
+ 1 * mockCpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption, CpsQueryService.NO_LIMIT)
and: 'the CpsValidator is called on the dataspaceName, schemaSetName and anchorName'
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'all fetch descendants options are supported'
@@ -50,6 +50,21 @@ class CpsQueryServiceImplSpec extends Specification {
FetchDescendantsOption.DIRECT_CHILDREN_ONLY, new FetchDescendantsOption(10)]
}
+ def 'Query data nodes by cps path with limit.'() {
+ given: 'a dataspace name, an anchor name and a cps path'
+ def dataspaceName = 'some-dataspace'
+ def anchorName = 'some-anchor'
+ def cpsPath = '/cps-path'
+ def fetchDescendantsOption = FetchDescendantsOption.OMIT_DESCENDANTS
+ def myLimit = 123
+ when: 'queryDataNodes (with limit) is invoked'
+ objectUnderTest.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption, myLimit)
+ then: 'the persistence service is called once with the correct parameters'
+ 1 * mockCpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption, myLimit)
+ and: 'the CpsValidator is called on the dataspaceName, schemaSetName and anchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
+ }
+
def 'Query data nodes across all anchors by cps path with #fetchDescendantsOption.'() {
given: 'a dataspace name, an anchor name and a cps path'
def dataspaceName = 'some-dataspace'
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
index d1b445f5a4..42fb964d52 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
@@ -457,4 +457,17 @@ class QueryServiceIntegrationSpec extends FunctionalSpecBase {
and: 'the queried nodes have expected bookstore names'
assert result.anchorName.toSet() == [BOOKSTORE_ANCHOR_1, BOOKSTORE_ANCHOR_2].toSet()
}
+
+ def 'Query with a limit of #limit.' () {
+ when:
+ def result = objectUnderTest.queryDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories', OMIT_DESCENDANTS, limit)
+ then: 'the expected number of nodes is returned'
+ assert countDataNodesInTree(result) == expectedNumberOfResults
+ where: 'the following parameters are used'
+ limit || expectedNumberOfResults
+ 1 || 1
+ 2 || 2
+ 0 || 5
+ -1 || 5
+ }
}
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 364127f388..acc95cab8d 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
@@ -103,5 +103,4 @@ class QueryPerfTest extends CpsPerfTestBase {
'direct descendants' | DIRECT_CHILDREN_ONLY || 0.11 | 8 | 1 + OPENROADM_DEVICES_PER_ANCHOR
'all descendants' | INCLUDE_ALL_DESCENDANTS || 1.34 | 400 | 1 + OPENROADM_DEVICES_PER_ANCHOR * OPENROADM_DATANODES_PER_DEVICE
}
-
}