diff options
author | seanbeirne <sean.beirne@est.tech> | 2022-12-15 16:06:20 +0000 |
---|---|---|
committer | seanbeirne <sean.beirne@est.tech> | 2023-01-11 13:45:36 +0000 |
commit | 9c56b3032222b57549aa17dd281e4794fd9e25b6 (patch) | |
tree | 5bb6dacf0c5c84463c4a8810609776069ce16d09 /cps-ri/src/main/java/org/onap | |
parent | b48469262c83dc1e88b12d162de88a05ce61159c (diff) |
Fetch CM handles by collection of xpaths
- Added FragmentRepositoryMultiPathQuery
- Removed Hibernate method for same
- Added perf. test
- Handle escaping of single qoutes in sql-data
- Increased timing for path paser performance test
Issue-ID: CPS-1422
Signed-off-by: seanbeirne <sean.beirne@est.tech>
Change-Id: Ibea12a44bffd29ed43cc1560b507d1fa7e968b8b
Diffstat (limited to 'cps-ri/src/main/java/org/onap')
5 files changed, 134 insertions, 14 deletions
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 3bd2994305..8293f642c7 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 @@ -256,6 +256,21 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService return toDataNode(fragmentEntity, fetchDescendantsOption); } + @Override + public Collection<DataNode> getDataNodes(final String dataspaceName, final String anchorName, + final Collection<String> xpaths, + final FetchDescendantsOption fetchDescendantsOption) { + final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName); + final AnchorEntity anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName); + final List<FragmentEntity> fragmentEntities = + fragmentRepository.findByAnchorAndMultipleCpsPaths(anchorEntity.getId(), xpaths); + final Collection<DataNode> dataNodesCollection = new ArrayList<>(fragmentEntities.size()); + for (final FragmentEntity fragmentEntity : fragmentEntities) { + dataNodesCollection.add(toDataNode(fragmentEntity, fetchDescendantsOption)); + } + return dataNodesCollection; + } + private FragmentEntity getFragmentWithoutDescendantsByXpath(final String dataspaceName, final String anchorName, final String xpath) { @@ -317,7 +332,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } fragmentEntities = fragmentRepository.findByAnchorAndCpsPath(anchorEntity.getId(), cpsPathQuery); if (cpsPathQuery.hasAncestorAxis()) { - fragmentEntities = getAncestorFragmentEntities(anchorEntity, cpsPathQuery, fragmentEntities); + fragmentEntities = getAncestorFragmentEntities(anchorEntity.getId(), cpsPathQuery, fragmentEntities); } return createDataNodesFromProxiedFragmentEntities(fetchDescendantsOption, anchorEntity, fragmentEntities); } @@ -338,18 +353,17 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService fragmentRepository.quickFindWithDescendants(anchorEntity.getId(), xpathRegex); fragmentEntities = FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts); if (cpsPathQuery.hasAncestorAxis()) { - fragmentEntities = getAncestorFragmentEntities(anchorEntity, cpsPathQuery, fragmentEntities); + fragmentEntities = getAncestorFragmentEntities(anchorEntity.getId(), cpsPathQuery, fragmentEntities); } return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities); } - private Collection<FragmentEntity> getAncestorFragmentEntities(final AnchorEntity anchorEntity, + private Collection<FragmentEntity> getAncestorFragmentEntities(final int anchorId, final CpsPathQuery cpsPathQuery, - Collection<FragmentEntity> fragmentEntities) { - final Set<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); - fragmentEntities = ancestorXpaths.isEmpty() ? Collections.emptyList() - : fragmentRepository.findAllByAnchorAndXpathIn(anchorEntity, ancestorXpaths); - return fragmentEntities; + final Collection<FragmentEntity> fragmentEntities) { + final Collection<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); + return ancestorXpaths.isEmpty() ? Collections.emptyList() + : fragmentRepository.findByAnchorAndMultipleCpsPaths(anchorId, ancestorXpaths); } private List<DataNode> createDataNodesFromProxiedFragmentEntities( 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 c9461bf062..4b42b2da8d 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 @@ -39,7 +39,8 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository;
@Repository
-public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>, FragmentRepositoryCpsPathQuery {
+public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>, FragmentRepositoryCpsPathQuery,
+ FragmentRepositoryMultiPathQuery {
Optional<FragmentEntity> findByDataspaceAndAnchorAndXpath(@NonNull DataspaceEntity dataspaceEntity,
@NonNull AnchorEntity anchorEntity,
@@ -80,9 +81,6 @@ public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>, return fragmentExtracts;
}
- List<FragmentEntity> findAllByAnchorAndXpathIn(@NonNull AnchorEntity anchorEntity,
- @NonNull Collection<String> xpath);
-
@Modifying
@Query("DELETE FROM FragmentEntity fe WHERE fe.anchor IN (:anchors)")
void deleteByAnchorIn(@NotNull @Param("anchors") Collection<AnchorEntity> anchorEntities);
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryMultiPathQuery.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryMultiPathQuery.java new file mode 100644 index 0000000000..9c34a459e9 --- /dev/null +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryMultiPathQuery.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.repository; + +import java.util.Collection; +import java.util.List; +import org.onap.cps.spi.entities.FragmentEntity; + +public interface FragmentRepositoryMultiPathQuery { + + List<FragmentEntity> findByAnchorAndMultipleCpsPaths(Integer anchorId, Collection<String> cpsPathQuery); + +} diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryMultiPathQueryImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryMultiPathQueryImpl.java new file mode 100644 index 0000000000..b936e5c762 --- /dev/null +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepositoryMultiPathQueryImpl.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.repository; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.transaction.Transactional; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.spi.entities.FragmentEntity; + + +@Slf4j +@AllArgsConstructor +public class FragmentRepositoryMultiPathQueryImpl implements FragmentRepositoryMultiPathQuery { + + @PersistenceContext + private EntityManager entityManager; + + private TempTableCreator tempTableCreator; + + @Override + @Transactional + public List<FragmentEntity> findByAnchorAndMultipleCpsPaths(final Integer anchorId, + final Collection<String> cpsPathQueryList) { + final Collection<List<String>> sqlData = new HashSet<>(cpsPathQueryList.size()); + for (final String query : cpsPathQueryList) { + final List<String> row = new ArrayList<>(1); + row.add(query); + sqlData.add(row); + } + + final String tempTableName = tempTableCreator.createTemporaryTable( + "xpathTemporaryTable", sqlData, "xpath"); + return selectMatchingFragments(anchorId, tempTableName); + } + + private List<FragmentEntity> selectMatchingFragments(final Integer anchorId, final String tempTableName) { + final String sql = String.format( + "SELECT * FROM FRAGMENT WHERE anchor_id = %d AND xpath IN (select xpath FROM %s);", + anchorId, tempTableName); + final List<FragmentEntity> fragmentEntities = entityManager.createNativeQuery(sql, FragmentEntity.class) + .getResultList(); + log.debug("Fetched {} fragment entities by anchor and cps path.", fragmentEntities.size()); + return fragmentEntities; + } +} diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/TempTableCreator.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/TempTableCreator.java index 8cad9f5e4c..d713746e45 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/TempTableCreator.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/TempTableCreator.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import lombok.AllArgsConstructor; @@ -82,8 +83,10 @@ public class TempTableCreator { final String[] columnNames, final Collection<List<String>> sqlData) { final Collection<String> sqlInserts = new HashSet<>(sqlData.size()); - for (final Collection<String> row : sqlData) { - sqlInserts.add("('" + String.join("','", row) + "')"); + for (final Collection<String> rowValues : sqlData) { + final Collection<String> escapedValues = + rowValues.stream().map(it -> escapeSingleQuotesByDoublingThem(it)).collect(Collectors.toList()); + sqlInserts.add("('" + String.join("','", escapedValues) + "')"); } sqlStringBuilder.append("INSERT INTO "); sqlStringBuilder.append(tempTableName); @@ -94,4 +97,8 @@ public class TempTableCreator { sqlStringBuilder.append(";"); } + private static String escapeSingleQuotesByDoublingThem(final String value) { + return value.replace("'", "''"); + } + } |