Fix issue deleting CodeSystem resources ()

* 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
hapi-fhir-jpaserver-base/src
hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server
hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/parser
src/changes

View File

@ -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);

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")) @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;
/** /**

View File

@ -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.

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.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

View File

@ -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());
});
}
} }

View File

@ -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

View File

@ -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")

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.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;

View File

@ -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.