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.Collection; 033import java.util.Date; 034import java.util.List; 035import java.util.Optional; 036 037@Repository 038public interface IMdmLinkJpaRepository 039 extends RevisionRepository<MdmLink, Long, Long>, JpaRepository<MdmLink, Long>, IHapiFhirJpaRepository { 040 @Modifying 041 @Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid = :pid OR mySourcePid = :pid") 042 int deleteWithAnyReferenceToPid(@Param("pid") Long thePid); 043 044 @Modifying 045 @Query( 046 "DELETE FROM MdmLink f WHERE (myGoldenResourcePid = :pid OR mySourcePid = :pid) AND myMatchResult <> :matchResult") 047 int deleteWithAnyReferenceToPidAndMatchResultNot( 048 @Param("pid") Long thePid, @Param("matchResult") MdmMatchResultEnum theMatchResult); 049 050 @Modifying 051 @Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid IN (:goldenPids) OR mySourcePid IN (:goldenPids)") 052 void deleteLinksWithAnyReferenceToPids(@Param("goldenPids") List<Long> theResourcePids); 053 054 @Modifying 055 @Query( 056 value = 057 "DELETE FROM MPI_LINK_AUD WHERE GOLDEN_RESOURCE_PID IN (:goldenPids) OR TARGET_PID IN (:goldenPids)", 058 nativeQuery = true) 059 void deleteLinksHistoryWithAnyReferenceToPids(@Param("goldenPids") List<Long> theResourcePids); 060 061 // TODO: LD: the calling code in JpaBulkExportProcessor doesn't yet leverage the partition IDs, but maybe it 062 // should? 063 @Query( 064 "SELECT lookup_links.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_links.mySourcePid as sourcePid, lookup_links.myPartitionIdValue as sourcePartitionId " 065 + "FROM MdmLink lookup_links " 066 + "INNER JOIN ResourceTable gld_rt " 067 + "on lookup_links.myGoldenResourcePid=gld_rt.myId " 068 + "WHERE lookup_links.myMatchResult=:matchResult " 069 + "AND lookup_links.myGoldenResourcePid IN (" 070 + "SELECT inner_mdm_link.myGoldenResourcePid FROM MdmLink inner_mdm_link " 071 + "INNER JOIN ResourceLink inner_res_link " 072 + "ON inner_res_link.myTargetResourcePid=inner_mdm_link.mySourcePid " 073 + "AND inner_res_link.mySourceResourcePid=:groupPid " 074 + "AND inner_res_link.mySourcePath='Group.member.entity' " 075 + "AND inner_res_link.myTargetResourceType='Patient'" 076 + ")") 077 List<MdmPidTuple> expandPidsFromGroupPidGivenMatchResult( 078 @Param("groupPid") Long theGroupPid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 079 080 @Query("SELECT ml FROM MdmLink ml WHERE ml.mySourcePid = :sourcePid AND ml.myMatchResult = :matchResult") 081 Optional<MdmLink> findBySourcePidAndMatchResult( 082 @Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMatch); 083 084 interface MdmPidTuple { 085 Long getGoldenPid(); 086 087 Integer getGoldenPartitionId(); 088 089 Long getSourcePid(); 090 091 Integer getSourcePartitionId(); 092 } 093 094 @Query( 095 "SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId " 096 + "FROM MdmLink lookup_link " 097 + "INNER JOIN MdmLink gld_link " 098 + "on lookup_link.myGoldenResourcePid=gld_link.myGoldenResourcePid " 099 + "INNER JOIN ResourceTable gld_rt " 100 + "on gld_link.myGoldenResourcePid=gld_rt.myId " 101 + "WHERE gld_link.mySourcePid=:sourcePid " 102 + "AND gld_link.myMatchResult=:matchResult " 103 + "AND lookup_link.myMatchResult=:matchResult") 104 List<MdmPidTuple> expandPidsBySourcePidAndMatchResult( 105 @Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 106 107 @Query("SELECT ml " + "FROM MdmLink ml " 108 + "INNER JOIN MdmLink ml2 " 109 + "on ml.myGoldenResourcePid=ml2.myGoldenResourcePid " 110 + "WHERE ml2.mySourcePid=:sourcePid " 111 + "AND ml2.myMatchResult!=:matchResult") 112 List<MdmLink> findLinksAssociatedWithGoldenResourceOfSourceResourceExcludingMatchResult( 113 @Param("sourcePid") Long theSourcePid, 114 @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnumToExclude); 115 116 @Query( 117 "SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId " 118 + "FROM MdmLink lookup_link " 119 + "INNER JOIN ResourceTable gld_rt " 120 + "on lookup_link.myGoldenResourcePid=gld_rt.myId " 121 + "WHERE lookup_link.myGoldenResourcePid = :goldenPid " 122 + "AND lookup_link.myMatchResult = :matchResult") 123 List<MdmPidTuple> expandPidsByGoldenResourcePidAndMatchResult( 124 @Param("goldenPid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 125 126 @Query( 127 "SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId " 128 + "FROM MdmLink lookup_link " 129 + "INNER JOIN ResourceTable gld_rt " 130 + "on lookup_link.myGoldenResourcePid=gld_rt.myId " 131 + "WHERE " 132 + " (lookup_link.myGoldenResourcePid IN (:pids) " 133 + " OR" 134 + " lookup_link.mySourcePid IN (:pids))" 135 + "AND lookup_link.myMatchResult = :matchResult") 136 List<MdmPidTuple> expandPidsByGoldenResourcePidsOrSourcePidsAndMatchResult( 137 @Param("pids") Collection<Long> theSourcePid, 138 @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum); 139 140 @Query( 141 "SELECT ml.myId FROM MdmLink ml WHERE ml.myMdmSourceType = :resourceName AND ml.myCreated <= :highThreshold ORDER BY ml.myCreated DESC") 142 List<Long> findPidByResourceNameAndThreshold( 143 @Param("resourceName") String theResourceName, 144 @Param("highThreshold") Date theHighThreshold, 145 Pageable thePageable); 146 147 @Query( 148 "SELECT ml.myId FROM MdmLink ml WHERE ml.myMdmSourceType = :resourceName AND ml.myCreated <= :highThreshold AND ml.myPartitionIdValue IN :partitionId ORDER BY ml.myCreated DESC") 149 List<Long> findPidByResourceNameAndThresholdAndPartitionId( 150 @Param("resourceName") String theResourceName, 151 @Param("highThreshold") Date theHighThreshold, 152 @Param("partitionId") List<Integer> thePartitionIds, 153 Pageable thePageable); 154}