Fix issue deleting CodeSystem resources (#1316)
* Fix deleting CodeSystem resources * Test fixes * Address review comments
This commit is contained in:
parent
004f42cdcc
commit
6f44d7c360
|
@ -35,8 +35,11 @@ public interface ITermCodeSystemVersionDao extends JpaRepository<TermCodeSystemV
|
||||||
@Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myCodeSystem = :cs")
|
@Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myCodeSystem = :cs")
|
||||||
void deleteForCodeSystem(@Param("cs") TermCodeSystem theCodeSystem);
|
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")
|
@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")
|
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemHavingThisVersionAsCurrentVersionIfAny.myResource.myId = :resource_id")
|
||||||
TermCodeSystemVersion findCurrentVersionForCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid);
|
TermCodeSystemVersion findCurrentVersionForCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid);
|
||||||
|
|
|
@ -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"))
|
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
|
||||||
private ResourceTable myResource;
|
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)
|
@Column(name = "CS_VERSION_ID", nullable = true, updatable = false, length = MAX_VERSION_LENGTH)
|
||||||
private String myCodeSystemVersionId;
|
private String myCodeSystemVersionId;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -295,7 +295,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
myCodeSystemDao.flush();
|
myCodeSystemDao.flush();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (TermCodeSystemVersion next : myCodeSystemVersionDao.findByCodeSystemResource(theCodeSystem.getPid())) {
|
List<TermCodeSystemVersion> codeSystemVersions = myCodeSystemVersionDao.findByCodeSystemPid(theCodeSystem.getPid());
|
||||||
|
for (TermCodeSystemVersion next : codeSystemVersions) {
|
||||||
deleteCodeSystemVersion(next.getPid());
|
deleteCodeSystemVersion(next.getPid());
|
||||||
}
|
}
|
||||||
myCodeSystemVersionDao.deleteForCodeSystem(theCodeSystem);
|
myCodeSystemVersionDao.deleteForCodeSystem(theCodeSystem);
|
||||||
|
@ -1647,7 +1648,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
ValidateUtil.isNotBlankOrThrowInvalidRequest(theSystemUri, "No system URI supplied");
|
ValidateUtil.isNotBlankOrThrowInvalidRequest(theSystemUri, "No system URI supplied");
|
||||||
|
|
||||||
// Grab the existing versions so we can delete them later
|
// 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.
|
* For now we always delete old versions. At some point it would be nice to allow configuration to keep old versions.
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.dao.*;
|
||||||
import ca.uhn.fhir.jpa.dao.data.*;
|
import ca.uhn.fhir.jpa.dao.data.*;
|
||||||
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
|
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
|
||||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
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.ModelConfig;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
@ -105,6 +106,8 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||||
@Qualifier("myConceptMapDaoDstu3")
|
@Qualifier("myConceptMapDaoDstu3")
|
||||||
protected IFhirResourceDaoConceptMap<ConceptMap> myConceptMapDao;
|
protected IFhirResourceDaoConceptMap<ConceptMap> myConceptMapDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
protected ITermConceptDao myConceptDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myConditionDaoDstu3")
|
@Qualifier("myConditionDaoDstu3")
|
||||||
protected IFhirResourceDao<Condition> myConditionDao;
|
protected IFhirResourceDao<Condition> myConditionDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
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 java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
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.AfterClass;
|
||||||
import org.junit.Test;
|
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());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest;
|
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.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
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
|
@Test
|
||||||
public void testLookupOperationByCodeAndSystemBuiltInCode() {
|
public void testLookupOperationByCodeAndSystemBuiltInCode() {
|
||||||
Parameters respParam = ourClient
|
Parameters respParam = ourClient
|
||||||
|
|
|
@ -298,7 +298,7 @@ public class InterceptorDstu3Test {
|
||||||
@Create()
|
@Create()
|
||||||
public MethodOutcome create(@ResourceParam Patient theResource) {
|
public MethodOutcome create(@ResourceParam Patient theResource) {
|
||||||
ourLastPatient = theResource;
|
ourLastPatient = theResource;
|
||||||
return new MethodOutcome();
|
return new MethodOutcome().setCreated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name="$postOperation")
|
@Operation(name="$postOperation")
|
||||||
|
|
|
@ -7,7 +7,7 @@ import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||||
import ca.uhn.fhir.tinder.model.*;
|
import ca.uhn.fhir.tinder.model.*;
|
||||||
import ca.uhn.fhir.tinder.util.XMLUtils;
|
import ca.uhn.fhir.tinder.util.XMLUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
|
|
@ -89,6 +89,11 @@
|
||||||
The informational message returned in an OperationOutcome when a delete failed due to cascades not being enabled
|
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.
|
contained an incorrect example. This has been corrected.
|
||||||
</action>
|
</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">
|
<action type="change">
|
||||||
Two foreign keys have been dropped from the HFJ_SEARCH_RESULT table used by the FHIR search query cache. These
|
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.
|
constraints did not add value and caused unneccessary contention when used under high load.
|
||||||
|
|
Loading…
Reference in New Issue