001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2025 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.expunge; 021 022import ca.uhn.fhir.mdm.api.IMdmSettings; 023import jakarta.annotation.Nonnull; 024import org.springframework.beans.factory.annotation.Autowired; 025import org.springframework.stereotype.Service; 026 027import java.util.ArrayList; 028import java.util.List; 029 030import static ca.uhn.fhir.jpa.entity.MdmLink.GOLDEN_RESOURCE_PARTITION_ID; 031import static ca.uhn.fhir.jpa.entity.MdmLink.GOLDEN_RESOURCE_PID; 032import static ca.uhn.fhir.jpa.entity.MdmLink.PERSON_PARTITION_ID; 033import static ca.uhn.fhir.jpa.entity.MdmLink.PERSON_PID; 034import static ca.uhn.fhir.jpa.entity.MdmLink.TARGET_PARTITION_ID; 035import static ca.uhn.fhir.jpa.entity.MdmLink.TARGET_PID; 036import static ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId.PARTITION_ID; 037import static ca.uhn.fhir.jpa.model.entity.ResourceLink.TARGET_RESOURCE_ID; 038import static ca.uhn.fhir.jpa.model.entity.ResourceLink.TARGET_RES_PARTITION_ID; 039 040@Service 041public class ResourceTableFKProvider { 042 @Autowired(required = false) 043 IMdmSettings myMdmSettings; 044 045 @Nonnull 046 public List<ResourceForeignKey> getResourceForeignKeys() { 047 List<ResourceForeignKey> retval = new ArrayList<>(); 048 049 // To find all the FKs that need to be included here, run the following SQL in the INFORMATION_SCHEMA: 050 // SELECT FKTABLE_NAME, FKCOLUMN_NAME FROM CROSS_REFERENCES WHERE PKTABLE_NAME = 'HFJ_RESOURCE' 051 052 // Add some secondary related records that don't have foreign keys 053 retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", PARTITION_ID, "RES_ID")); // NOT covered by index. 054 retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", PARTITION_ID, "RES_PID")); 055 056 // These have the possibility of touching all resource types. 057 retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", PARTITION_ID, "RES_ID")); 058 retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", PARTITION_ID, "RES_ID")); 059 retval.add(new ResourceForeignKey("HFJ_RES_LINK", PARTITION_ID, "SRC_RESOURCE_ID")); 060 retval.add(new ResourceForeignKey("HFJ_RES_LINK", TARGET_RES_PARTITION_ID, TARGET_RESOURCE_ID)); 061 retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", PARTITION_ID, "RES_ID")); 062 retval.add(new ResourceForeignKey("HFJ_RES_TAG", PARTITION_ID, "RES_ID")); 063 retval.add(new ResourceForeignKey("HFJ_RES_VER", PARTITION_ID, "RES_ID")); 064 retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", PARTITION_ID, "RES_ID")); 065 retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", PARTITION_ID, "RES_ID")); 066 retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", PARTITION_ID, "RES_ID")); 067 retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", PARTITION_ID, "RES_ID")); 068 retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", PARTITION_ID, "RES_ID")); 069 retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", PARTITION_ID, "RES_ID")); 070 retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", PARTITION_ID, "RES_ID")); 071 retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", PARTITION_ID, "RES_ID")); 072 retval.add(new ResourceForeignKey("MPI_LINK", GOLDEN_RESOURCE_PARTITION_ID, GOLDEN_RESOURCE_PID)); 073 retval.add(new ResourceForeignKey("MPI_LINK", TARGET_PARTITION_ID, TARGET_PID)); 074 retval.add(new ResourceForeignKey("MPI_LINK", PERSON_PARTITION_ID, PERSON_PID)); 075 076 // These only touch certain resource types. 077 retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", PARTITION_ID, "RES_ID")); 078 retval.add(new ResourceForeignKey("TRM_CODESYSTEM", PARTITION_ID, "RES_ID")); 079 retval.add(new ResourceForeignKey("TRM_VALUESET", PARTITION_ID, "RES_ID")); 080 retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", PARTITION_ID, "RES_ID")); 081 retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", PARTITION_ID, "BINARY_RES_ID")); 082 retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", PARTITION_ID, "BINARY_RES_ID")); 083 084 retval.add(new ResourceForeignKey("HFJ_RES_SEARCH_URL", PARTITION_ID, "RES_ID")); 085 086 return retval; 087 } 088 089 @Nonnull 090 public List<ResourceForeignKey> getResourceForeignKeysByResourceType(String theResourceType) { 091 List<ResourceForeignKey> retval = new ArrayList<>(); 092 // These have the possibility of touching all resource types. 093 retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", PARTITION_ID, "RES_ID")); 094 retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", PARTITION_ID, "RES_PID")); 095 retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", PARTITION_ID, "RES_ID")); 096 retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", PARTITION_ID, "RES_ID")); 097 retval.add(new ResourceForeignKey("HFJ_RES_LINK", PARTITION_ID, "SRC_RESOURCE_ID")); 098 retval.add(new ResourceForeignKey("HFJ_RES_LINK", TARGET_PARTITION_ID, TARGET_RESOURCE_ID)); 099 retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", PARTITION_ID, "RES_ID")); 100 retval.add(new ResourceForeignKey( 101 "HFJ_RES_TAG", PARTITION_ID, "RES_ID")); // TODO GGG: Res_ID + TAG_ID? is that enough? 102 retval.add(new ResourceForeignKey( 103 "HFJ_RES_VER", PARTITION_ID, "RES_ID")); // TODO GGG: RES_ID + updated? is that enough? 104 retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", PARTITION_ID, "RES_ID")); 105 retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", PARTITION_ID, "RES_ID")); 106 retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", PARTITION_ID, "RES_ID")); 107 retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", PARTITION_ID, "RES_ID")); 108 retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", PARTITION_ID, "RES_ID")); 109 retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", PARTITION_ID, "RES_ID")); 110 retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", PARTITION_ID, "RES_ID")); 111 retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", PARTITION_ID, "RES_ID")); 112 113 if (myMdmSettings != null && myMdmSettings.isEnabled()) { 114 retval.add(new ResourceForeignKey( 115 "MPI_LINK", GOLDEN_RESOURCE_PARTITION_ID, GOLDEN_RESOURCE_PID)); // NOT covered by index. 116 retval.add(new ResourceForeignKey( 117 "MPI_LINK", TARGET_PARTITION_ID, TARGET_PID)); // Possibly covered, partial index 118 retval.add(new ResourceForeignKey( 119 "MPI_LINK", 120 PERSON_PARTITION_ID, 121 PERSON_PID)); // TODO GGG: I don't even think we need this... this field is deprecated, and the 122 // deletion is covered by GOLDEN_RESOURCE_PID 123 } 124 125 switch (theResourceType.toLowerCase()) { 126 case "binary": 127 retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", PARTITION_ID, "BINARY_RES_ID")); // Not covered 128 retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", PARTITION_ID, "BINARY_RES_ID")); // Not covered 129 break; 130 case "subscription": 131 retval.add( 132 new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", PARTITION_ID, "RES_ID")); // Covered by index. 133 break; 134 case "codesystem": 135 retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", PARTITION_ID, "RES_ID")); // Not covered 136 retval.add(new ResourceForeignKey("TRM_CODESYSTEM", PARTITION_ID, "RES_ID")); // Not covered 137 break; 138 case "valueset": 139 retval.add(new ResourceForeignKey("TRM_VALUESET", PARTITION_ID, "RES_ID")); // Not covered 140 break; 141 case "conceptmap": 142 retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", PARTITION_ID, "RES_ID")); // Not covered 143 break; 144 default: 145 } 146 return retval; 147 } 148}