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.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
030@Service
031public class ResourceTableFKProvider {
032        @Autowired(required = false)
033        IMdmSettings myMdmSettings;
034
035        @Nonnull
036        public List<ResourceForeignKey> getResourceForeignKeys() {
037                List<ResourceForeignKey> retval = new ArrayList<>();
038
039                // To find all the FKs that need to be included here, run the following SQL in the INFORMATION_SCHEMA:
040                // SELECT FKTABLE_NAME, FKCOLUMN_NAME FROM CROSS_REFERENCES WHERE PKTABLE_NAME = 'HFJ_RESOURCE'
041
042                // Add some secondary related records that don't have foreign keys
043                retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", "RES_ID")); // NOT covered by index.
044                retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", "RES_PID"));
045
046                // These have the possibility of touching all resource types.
047                retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", "RES_ID"));
048                retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", "RES_ID"));
049                retval.add(new ResourceForeignKey("HFJ_RES_LINK", "SRC_RESOURCE_ID"));
050                retval.add(new ResourceForeignKey("HFJ_RES_LINK", "TARGET_RESOURCE_ID"));
051                retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", "RES_ID"));
052                retval.add(new ResourceForeignKey("HFJ_RES_TAG", "RES_ID"));
053                retval.add(new ResourceForeignKey("HFJ_RES_VER", "RES_ID"));
054                retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", "RES_ID"));
055                retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", "RES_ID"));
056                retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", "RES_ID"));
057                retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", "RES_ID"));
058                retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", "RES_ID"));
059                retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", "RES_ID"));
060                retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", "RES_ID"));
061                retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", "RES_ID"));
062                retval.add(new ResourceForeignKey("MPI_LINK", "GOLDEN_RESOURCE_PID"));
063                retval.add(new ResourceForeignKey("MPI_LINK", "TARGET_PID"));
064                retval.add(new ResourceForeignKey("MPI_LINK", "PERSON_PID"));
065
066                // These only touch certain resource types.
067                retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", "RES_ID"));
068                retval.add(new ResourceForeignKey("TRM_CODESYSTEM", "RES_ID"));
069                retval.add(new ResourceForeignKey("TRM_VALUESET", "RES_ID"));
070                retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", "RES_ID"));
071                retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", "BINARY_RES_ID"));
072                retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", "BINARY_RES_ID"));
073
074                retval.add(new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", "RES_ID"));
075
076                return retval;
077        }
078
079        @Nonnull
080        public List<ResourceForeignKey> getResourceForeignKeysByResourceType(String theResourceType) {
081                List<ResourceForeignKey> retval = new ArrayList<>();
082                // These have the possibility of touching all resource types.
083                retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", "RES_ID"));
084                retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", "RES_PID"));
085                retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", "RES_ID"));
086                retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", "RES_ID"));
087                retval.add(new ResourceForeignKey("HFJ_RES_LINK", "SRC_RESOURCE_ID"));
088                retval.add(new ResourceForeignKey("HFJ_RES_LINK", "TARGET_RESOURCE_ID"));
089                retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", "RES_ID"));
090                retval.add(new ResourceForeignKey("HFJ_RES_TAG", "RES_ID")); // TODO GGG: Res_ID + TAG_ID? is that enough?
091                retval.add(new ResourceForeignKey("HFJ_RES_VER", "RES_ID")); // TODO GGG: RES_ID + updated? is that enough?
092                retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", "RES_ID"));
093                retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", "RES_ID"));
094                retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", "RES_ID"));
095                retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", "RES_ID"));
096                retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", "RES_ID"));
097                retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", "RES_ID"));
098                retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", "RES_ID"));
099                retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", "RES_ID"));
100
101                if (myMdmSettings != null && myMdmSettings.isEnabled()) {
102                        retval.add(new ResourceForeignKey("MPI_LINK", "GOLDEN_RESOURCE_PID")); // NOT covered by index.
103                        retval.add(new ResourceForeignKey("MPI_LINK", "TARGET_PID")); // Possibly covered, partial index
104                        retval.add(new ResourceForeignKey(
105                                        "MPI_LINK",
106                                        "PERSON_PID")); // TODO GGG: I don't even think we need this... this field is deprecated, and the
107                        // deletion is covered by GOLDEN_RESOURCE_PID
108                }
109
110                switch (theResourceType.toLowerCase()) {
111                        case "binary":
112                                retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", "BINARY_RES_ID")); // Not covered
113                                retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", "BINARY_RES_ID")); // Not covered
114                                break;
115                        case "subscription":
116                                retval.add(new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", "RES_ID")); // Covered by index.
117                                break;
118                        case "codesystem":
119                                retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", "RES_ID")); // Not covered
120                                retval.add(new ResourceForeignKey("TRM_CODESYSTEM", "RES_ID")); // Not covered
121                                break;
122                        case "valueset":
123                                retval.add(new ResourceForeignKey("TRM_VALUESET", "RES_ID")); // Not covered
124                                break;
125                        case "conceptmap":
126                                retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", "RES_ID")); // Not covered
127                                break;
128                        default:
129                }
130                return retval;
131        }
132}