001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.dao.data; 021 022import ca.uhn.fhir.jpa.entity.MdmLink; 023import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; 024import org.springframework.data.domain.Pageable; 025import org.springframework.data.jpa.repository.JpaRepository; 026import org.springframework.data.jpa.repository.Modifying; 027import org.springframework.data.jpa.repository.Query; 028import org.springframework.data.repository.history.RevisionRepository; 029import org.springframework.data.repository.query.Param; 030import org.springframework.stereotype.Repository; 031 032import java.util.Date; 033import java.util.List; 034import java.util.Optional; 035 036@Repository 037public interface IMdmLinkJpaRepository 038 extends RevisionRepository<MdmLink, Long, Long>, JpaRepository<MdmLink, Long>, IHapiFhirJpaRepository { 039 @Modifying 040 @Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid = :pid OR mySourcePid = :pid") 041 int deleteWithAnyReferenceToPid(@Param("pid") Long thePid); 042 043 @Modifying 044 @Query( 045 "DELETE FROM MdmLink f WHERE (myGoldenResourcePid = :pid OR mySourcePid = :pid) AND myMatchResult <> :matchResult") 046 int deleteWithAnyReferenceToPidAndMatchResultNot( 047 @Param("pid") Long thePid, @Param("matchResult") MdmMatchResultEnum theMatchResult); 048 049 @Modifying 050 @Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid IN (:goldenPids) OR mySourcePid IN (:goldenPids)") 051 void deleteLinksWithAnyReferenceToPids(@Param("goldenPids") List<Long> theResourcePids); 052 053 @Modifying 054 @Query( 055 value = 056 "DELETE FROM MPI_LINK_AUD WHERE GOLDEN_RESOURCE_PID IN (:goldenPids) OR TARGET_PID IN (:goldenPids)", 057 nativeQuery = true) 058 void deleteLinksHistoryWithAnyReferenceToPids(@Param("goldenPids") List<Long> theResourcePids); 059 060 // TODO: LD: the calling code in JpaBulkExportProcessor doesn't yet leverage the partition IDs, but maybe it 061 // should? 062 @Query( 063 "SELECT lookup_links.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_links.mySourcePid as sourcePid, lookup_links.myPartitionIdValue as sourcePartitionId " 064 + "FROM MdmLink lookup_links " 065 + "INNER JOIN ResourceTable gld_rt " 066 + "on lookup_links.myGoldenResourcePid=gld_rt.myId " 067 + "WHERE lookup_links.myMatchResult=:matchResult " 068 + "AND lookup_links.myGoldenResourcePid IN (" 069 + "SELECT inner_mdm_link.myGoldenResourcePid FROM MdmLink inner_mdm_link " 070 + "INNER JOIN ResourceLink inner_res_link " 071 + "ON inner_res_link.myTargetResourcePid=inner_mdm_link.mySourcePid " 072 + "AND inner_res_link.mySourceResourcePid=:groupPid " 073 + "AND inner_res_link.mySourcePath='Group.member.entity' " 074 + "AND inner_res_link.myTargetResourceType='Patient'" 075 + ")") 076 List<MdmPidTuple> expandPidsFromGroupPidGivenMatchResult( 077 @Param("groupPid") Long theGroupPid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 078 079 @Query("SELECT ml FROM MdmLink ml WHERE ml.mySourcePid = :sourcePid AND ml.myMatchResult = :matchResult") 080 Optional<MdmLink> findBySourcePidAndMatchResult( 081 @Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMatch); 082 083 interface MdmPidTuple { 084 Long getGoldenPid(); 085 086 Integer getGoldenPartitionId(); 087 088 Long getSourcePid(); 089 090 Integer getSourcePartitionId(); 091 } 092 093 @Query( 094 "SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId " 095 + "FROM MdmLink lookup_link " 096 + "INNER JOIN MdmLink gld_link " 097 + "on lookup_link.myGoldenResourcePid=gld_link.myGoldenResourcePid " 098 + "INNER JOIN ResourceTable gld_rt " 099 + "on gld_link.myGoldenResourcePid=gld_rt.myId " 100 + "WHERE gld_link.mySourcePid=:sourcePid " 101 + "AND gld_link.myMatchResult=:matchResult " 102 + "AND lookup_link.myMatchResult=:matchResult") 103 List<MdmPidTuple> expandPidsBySourcePidAndMatchResult( 104 @Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 105 106 @Query("SELECT ml " + "FROM MdmLink ml " 107 + "INNER JOIN MdmLink ml2 " 108 + "on ml.myGoldenResourcePid=ml2.myGoldenResourcePid " 109 + "WHERE ml2.mySourcePid=:sourcePid " 110 + "AND ml2.myMatchResult!=:matchResult") 111 List<MdmLink> findLinksAssociatedWithGoldenResourceOfSourceResourceExcludingMatchResult( 112 @Param("sourcePid") Long theSourcePid, 113 @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnumToExclude); 114 115 @Query( 116 "SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId " 117 + "FROM MdmLink lookup_link " 118 + "INNER JOIN ResourceTable gld_rt " 119 + "on lookup_link.myGoldenResourcePid=gld_rt.myId " 120 + "WHERE lookup_link.myGoldenResourcePid = :goldenPid " 121 + "AND lookup_link.myMatchResult = :matchResult") 122 List<MdmPidTuple> expandPidsByGoldenResourcePidAndMatchResult( 123 @Param("goldenPid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 124 125 @Query( 126 "SELECT ml.myId FROM MdmLink ml WHERE ml.myMdmSourceType = :resourceName AND ml.myCreated <= :highThreshold ORDER BY ml.myCreated DESC") 127 List<Long> findPidByResourceNameAndThreshold( 128 @Param("resourceName") String theResourceName, 129 @Param("highThreshold") Date theHighThreshold, 130 Pageable thePageable); 131 132 @Query( 133 "SELECT ml.myId FROM MdmLink ml WHERE ml.myMdmSourceType = :resourceName AND ml.myCreated <= :highThreshold AND ml.myPartitionIdValue IN :partitionId ORDER BY ml.myCreated DESC") 134 List<Long> findPidByResourceNameAndThresholdAndPartitionId( 135 @Param("resourceName") String theResourceName, 136 @Param("highThreshold") Date theHighThreshold, 137 @Param("partitionId") List<Integer> thePartitionIds, 138 Pageable thePageable); 139}