Fix issue deleting CodeSystem resources (#1316)

* Fix deleting CodeSystem resources

* Test fixes

* Address review comments
This commit is contained in:
James Agnew 2019-09-23 15:58:57 -04:00 committed by GitHub
parent 004f42cdcc
commit 6f44d7c360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 110 additions and 7 deletions

View File

@ -35,8 +35,11 @@ public interface ITermCodeSystemVersionDao extends JpaRepository<TermCodeSystemV
@Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myCodeSystem = :cs")
void deleteForCodeSystem(@Param("cs") TermCodeSystem theCodeSystem);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myResourcePid = :resource_id")
List<TermCodeSystemVersion> findByCodeSystemPid(@Param("resource_id") Long theCodeSystemResourcePid);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myResource.myId = :resource_id")
List<TermCodeSystemVersion> findByCodeSystemResource(@Param("resource_id") Long theCodeSystemResourcePid);
List<TermCodeSystemVersion> findByCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemHavingThisVersionAsCurrentVersionIfAny.myResource.myId = :resource_id")
TermCodeSystemVersion findCurrentVersionForCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid);

View File

@ -53,6 +53,9 @@ public class TermCodeSystemVersion implements Serializable {
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid;
@Column(name = "CS_VERSION_ID", nullable = true, updatable = false, length = MAX_VERSION_LENGTH)
private String myCodeSystemVersionId;
/**

View File

@ -295,7 +295,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
myCodeSystemDao.flush();
int i = 0;
for (TermCodeSystemVersion next : myCodeSystemVersionDao.findByCodeSystemResource(theCodeSystem.getPid())) {
List<TermCodeSystemVersion> codeSystemVersions = myCodeSystemVersionDao.findByCodeSystemPid(theCodeSystem.getPid());
for (TermCodeSystemVersion next : codeSystemVersions) {
deleteCodeSystemVersion(next.getPid());
}
myCodeSystemVersionDao.deleteForCodeSystem(theCodeSystem);
@ -1647,7 +1648,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
ValidateUtil.isNotBlankOrThrowInvalidRequest(theSystemUri, "No system URI supplied");
// Grab the existing versions so we can delete them later
List<TermCodeSystemVersion> existing = myCodeSystemVersionDao.findByCodeSystemResource(theCodeSystemResourcePid);
List<TermCodeSystemVersion> existing = myCodeSystemVersionDao.findByCodeSystemResourcePid(theCodeSystemResourcePid);
/*
* For now we always delete old versions. At some point it would be nice to allow configuration to keep old versions.

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -105,6 +106,8 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
@Qualifier("myConceptMapDaoDstu3")
protected IFhirResourceDaoConceptMap<ConceptMap> myConceptMapDao;
@Autowired
protected ITermConceptDao myConceptDao;
@Autowired
@Qualifier("myConditionDaoDstu3")
protected IFhirResourceDao<Condition> myConditionDao;
@Autowired

View File

@ -1,12 +1,16 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import static org.junit.Assert.assertNotEquals;
import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.*;
import java.nio.charset.StandardCharsets;
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.Enumerations;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Test;
@ -39,5 +43,41 @@ public class FhirResourceDaoDstu3CodeSystemTest extends BaseJpaDstu3Test {
}
@Test
public void testDeleteCodeSystemComplete() {
BaseHapiTerminologySvcImpl.setForceSaveDeferredAlwaysForUnitTest(false);
// Create the code system
CodeSystem cs = new CodeSystem();
cs.setUrl("http://foo");
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setStatus(Enumerations.PublicationStatus.ACTIVE);
cs.addConcept().setCode("A");
IIdType id = myCodeSystemDao.create(cs, mySrd).getId().toUnqualifiedVersionless();
runInTransaction(()->{
assertEquals(1, myConceptDao.count());
});
// Update the code system
cs = new CodeSystem();
cs.setId(id);
cs.setUrl("http://foo");
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setStatus(Enumerations.PublicationStatus.ACTIVE);
cs.addConcept().setCode("A");
cs.addConcept().setCode("B");
myCodeSystemDao.update(cs, mySrd);
runInTransaction(()->{
assertEquals(2, myConceptDao.count());
});
// Delete the code system
myCodeSystemDao.delete(id);
runInTransaction(()->{
assertEquals(0L, myConceptDao.count());
});
}
}

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest;
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.TestUtil;
@ -86,6 +87,53 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
}
@Test
public void testDeleteCodeSystemComplete2() {
BaseHapiTerminologySvcImpl.setForceSaveDeferredAlwaysForUnitTest(false);
String input = "{\n" +
" \"resourceType\": \"CodeSystem\",\n" +
" \"id\": \"CDRTestCodeSystem\",\n" +
" \"url\": \"http://fkcfhir.org/fhir/cs/CDRTestCodeSystem\",\n" +
" \"identifier\": {\n" +
" \"value\": \"CDRTestCodeSystem\"\n" +
" },\n" +
" \"name\": \"CDRTestCodeSystem\",\n" +
" \"status\": \"retired\",\n" +
" \"publisher\": \"FMCNA\",\n" +
" \"description\": \"Smile CDR Test Code System \",\n" +
" \"hierarchyMeaning\": \"grouped-by\",\n" +
" \"content\": \"complete\",\n" +
" \"concept\": [\n" +
" {\n" +
" \"code\": \"IHD\",\n" +
" \"display\": \"IHD\"\n" +
" },\n" +
" {\n" +
" \"code\": \"HHD\",\n" +
" \"display\": \"HHD\"\n" +
" }\n" +
" ]\n" +
"}";
// Create the code system
CodeSystem cs = (CodeSystem) myFhirCtx.newJsonParser().parseResource(input);
ourClient.update().resource(cs).execute();
runInTransaction(()->{
assertEquals(26, myConceptDao.count());
});
// Delete the code system
ourClient.delete().resource(cs).execute();
runInTransaction(()->{
assertEquals(24L, myConceptDao.count());
});
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInCode() {
Parameters respParam = ourClient

View File

@ -298,7 +298,7 @@ public class InterceptorDstu3Test {
@Create()
public MethodOutcome create(@ResourceParam Patient theResource) {
ourLastPatient = theResource;
return new MethodOutcome();
return new MethodOutcome().setCreated(true);
}
@Operation(name="$postOperation")

View File

@ -7,7 +7,7 @@ import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.tinder.model.*;
import ca.uhn.fhir.tinder.util.XMLUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.apache.commons.text.WordUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.w3c.dom.Document;

View File

@ -89,6 +89,11 @@
The informational message returned in an OperationOutcome when a delete failed due to cascades not being enabled
contained an incorrect example. This has been corrected.
</action>
<action type="fix">
In some cases, deleting a CodeSystem resource would fail because the underlying
codes were not correctly deleted from the terminology service tables. This is
fixed.
</action>
<action type="change">
Two foreign keys have been dropped from the HFJ_SEARCH_RESULT table used by the FHIR search query cache. These
constraints did not add value and caused unneccessary contention when used under high load.