diff options
3 files changed, 36 insertions, 17 deletions
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 74d04613d9..b9874484c0 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 @@ -76,8 +76,9 @@ public interface FragmentRepository extends JpaRepository<FragmentEntity, Long> List<FragmentEntity> getByAnchorAndXpathEndsInDescendantName(@Param("anchor") int anchorId,
@Param("descendantName") String descendantName);
- @Query(value = "SELECT * FROM FRAGMENT WHERE anchor_id = :anchor AND xpath LIKE CONCAT('%/',:descendantName) "
- + "AND attributes @> :leafDataAsJson\\:\\:jsonb", nativeQuery = true)
+ @Query(value = "SELECT * FROM FRAGMENT WHERE anchor_id = :anchor AND (xpath LIKE CONCAT('%/',:descendantName) OR "
+ + "xpath LIKE CONCAT('%/', :descendantName,'\\[@%]')) AND attributes @> :leafDataAsJson\\:\\:jsonb",
+ nativeQuery = true)
// Above query will match the anchor id, last descendant name and all parameters passed into leafDataASJson with the
// attribute values of the requested data node eg: {"leaf_name":"value", "another_leaf_name":"another value"}
List<FragmentEntity> getByAnchorAndDescendentNameAndLeafValues(@Param("anchor") int anchorId,
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy index bfc088db2a..8acfe783da 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceQueryDataNodeSpec.groovy @@ -76,7 +76,6 @@ class CpsDataPersistenceQueryDataNodeSpec extends CpsPersistenceSpecBase { return flatMap } - @Sql([CLEAR_DATA, SET_DATA]) def 'Cps Path query for single leaf value with type: #type.'() { when: 'a query is executed to get a data node by the given cps path' @@ -120,14 +119,14 @@ class CpsDataPersistenceQueryDataNodeSpec extends CpsPersistenceSpecBase { } @Sql([CLEAR_DATA, SET_DATA]) - def 'Cps Path query using descendant anywhere with %scenario '() { + def 'Cps Path query using descendant anywhere with #scenario '() { when: 'a query is executed to get a data node by the given cps path' def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS) then: 'the correct number of data nodes are retrieved' result.size() == expectedXPaths.size() and: 'xpaths of the retrieved data nodes are as expected' for(int i = 0; i<result.size(); i++) { - result[i].getXpath() == expectedXPaths[i] + assert result[i].getXpath() == expectedXPaths[i] } where: 'the following data is used' scenario | cpsPath || expectedXPaths @@ -136,32 +135,49 @@ class CpsDataPersistenceQueryDataNodeSpec extends CpsPersistenceSpecBase { } @Sql([CLEAR_DATA, SET_DATA]) - def 'Cps Path query using descendant anywhere ends with yang list containing %scenario '() { + def 'Cps Path query using descendant anywhere with #scenario condition(s) for a container element.'() { when: 'a query is executed to get a data node by the given cps path' def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS) then: 'the correct number of data nodes are retrieved' result.size() == expectedXPaths.size() and: 'xpaths of the retrieved data nodes are as expected' for(int i = 0; i<result.size(); i++) { - result[i].getXpath() == expectedXPaths[i] + assert result[i].getXpath() == expectedXPaths[i] } where: 'the following data is used' - scenario | cpsPath || expectedXPaths - 'one attribute' | '//child-202[@common-leaf-name-int=5]' || ['/parent-200/child-202','/parent-201/child-202'] - 'trailing "and" is ignored' | '//child-202[@common-leaf-name-int=5 and]' || ['/parent-200/child-202','/parent-201/child-202'] - 'more than one attribute' | '//child-202[@common-leaf-name-int=5 and @common-leaf-name="common-leaf value"]' || ['/parent-200/child-202'] - 'attributes reversed in order' | '//child-202[@common-leaf-name="common-leaf value" and @common-leaf-name-int=5]' || ['/parent-200/child-202'] + scenario | cpsPath || expectedXPaths + 'one leaf' | '//child-202[@common-leaf-name-int=5]' || ['/parent-200/child-202','/parent-201/child-202'] + 'trailing "and" is ignored' | '//child-202[@common-leaf-name-int=5 and]' || ['/parent-200/child-202','/parent-201/child-202'] + 'more than one leaf' | '//child-202[@common-leaf-name-int=5 and @common-leaf-name="common-leaf value"]' || ['/parent-200/child-202'] + 'leaves reversed in order' | '//child-202[@common-leaf-name="common-leaf value" and @common-leaf-name-int=5]' || ['/parent-200/child-202'] } @Sql([CLEAR_DATA, SET_DATA]) - def 'Cps Path query error scenario using descendant anywhere ends with yang list containing %scenario '() { + def 'Cps Path query using descendant anywhere with #scenario condition(s) for a list element.'() { when: 'a query is executed to get a data node by the given cps path' def result = objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS) + then: 'the correct number of data nodes are retrieved' + result.size() == expectedXPaths.size() + and: 'xpaths of the retrieved data nodes are as expected' + for(int i = 0; i<result.size(); i++) { + assert result[i].getXpath() == expectedXPaths[i] + } + where: 'the following data is used' + scenario | cpsPath || expectedXPaths + 'one partial key leaf' | '//child-203[@key1="A"]' || ['/parent-201/child-203[@key1="A" and @key2=1]','/parent-201/child-203[@key1="A" and @key2=2]'] + 'one non key leaf' | '//child-203[@other-leaf="other value"]' || ['/parent-201/child-203[@key1="A" and @key2=2]'] + 'mix of partial key and non key leaf' | '//child-203[@key1="A" and @other-leaf="leaf value"]' || ['/parent-201/child-203[@key1="A" and @key2=1]'] + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Cps Path query error scenario using descendant anywhere ends with yang list containing %scenario '() { + when: 'a query is executed to get a data node by the given cps path' + objectUnderTest.queryDataNodes(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, cpsPath, OMIT_DESCENDANTS) then: 'exception is thrown' thrown(CpsPathException) where: 'the following data is used' - scenario | cpsPath - 'one of the attributes without value' | '//child-202[@common-leaf-name-int=5 and @another-attribute"]' - 'more than one attribute separated by or' | '//child-202[@common-leaf-name-int=5 or @common-leaf-name="common-leaf value"]' + scenario | cpsPath + 'one of the leaf without value' | '//child-202[@common-leaf-name-int=5 and @another-attribute"]' + 'more than one leaf separated by or' | '//child-202[@common-leaf-name-int=5 or @common-leaf-name="common-leaf value"]' } } diff --git a/cps-ri/src/test/resources/data/fragment.sql b/cps-ri/src/test/resources/data/fragment.sql index d252fbbb59..3e2ae8157e 100755 --- a/cps-ri/src/test/resources/data/fragment.sql +++ b/cps-ri/src/test/resources/data/fragment.sql @@ -29,4 +29,6 @@ INSERT INTO FRAGMENT (ID, DATASPACE_ID, ANCHOR_ID, PARENT_ID, XPATH, ATTRIBUTES) (4204, 1001, 3003, 4201, '/parent-200/child-202', '{"common-leaf-name": "common-leaf value", "common-leaf-name-int" : 5}'), (4205, 1001, 3003, 4204, '/parent-200/child-202/grand-child-202', '{"common-leaf-name": "common-leaf value", "common-leaf-name-int" : 5}'), (4206, 1001, 3003, null, '/parent-201', '{"leaf-value": "original"}'), - (4207, 1001, 3003, 4201, '/parent-201/child-202', '{"common-leaf-name": "common-leaf other value", "common-leaf-name-int" : 5}');
\ No newline at end of file + (4207, 1001, 3003, 4206, '/parent-201/child-202', '{"common-leaf-name": "common-leaf other value", "common-leaf-name-int" : 5}'), + (4208, 1001, 3003, 4206, '/parent-201/child-203[@key1="A" and @key2=1]', '{"key1": "A", "key2" : 1, "other-leaf" : "leaf value"}'), + (4209, 1001, 3003, 4206, '/parent-201/child-203[@key1="A" and @key2=2]', '{"key1": "A", "key2" : 2, "other-leaf" : "other value"}');
\ No newline at end of file |