4420 tags are not included in search results after using $meta delete on one tag (#4421)
* added failing test * added a check for when the tag storage mode is non-versioned in meta delete to only check latest version of resource, added more test * added change log Co-authored-by: Steven Li <steven@smilecdr.com>
This commit is contained in:
parent
8c48a6fb91
commit
920755427b
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 4420
|
||||||
|
jira: SMILE-5734
|
||||||
|
title: "Fixed a bug with $meta-delete which will cause the resource, when included as part of a search result,
|
||||||
|
to have all its tags be missing."
|
|
@ -57,7 +57,6 @@ import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
||||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
|
||||||
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
|
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
|
||||||
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProviderFactory;
|
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProviderFactory;
|
||||||
import ca.uhn.fhir.jpa.search.cache.SearchCacheStatusEnum;
|
import ca.uhn.fhir.jpa.search.cache.SearchCacheStatusEnum;
|
||||||
|
@ -84,6 +83,7 @@ import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails;
|
import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
|
import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
|
||||||
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.IDeleteExpungeJobSubmitter;
|
import ca.uhn.fhir.rest.api.server.storage.IDeleteExpungeJobSubmitter;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
|
@ -663,7 +663,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
TransactionDetails transactionDetails = new TransactionDetails();
|
TransactionDetails transactionDetails = new TransactionDetails();
|
||||||
List<ResourceTable> deletedResources = new ArrayList<>();
|
List<ResourceTable> deletedResources = new ArrayList<>();
|
||||||
for (P pid : theResourceIds) {
|
for (P pid : theResourceIds) {
|
||||||
JpaPid jpaPid = (JpaPid)pid;
|
JpaPid jpaPid = (JpaPid) pid;
|
||||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
ResourceTable entity = myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
||||||
deletedResources.add(entity);
|
deletedResources.add(entity);
|
||||||
|
|
||||||
|
@ -1039,11 +1039,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequest, transactionDetails);
|
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequest, transactionDetails);
|
||||||
if (latestVersion.getVersion() != entity.getVersion()) {
|
boolean nonVersionedTags = myDaoConfig.getTagStorageMode() != DaoConfig.TagStorageModeEnum.VERSIONED;
|
||||||
|
if (latestVersion.getVersion() != entity.getVersion() || nonVersionedTags) {
|
||||||
doMetaDelete(theMetaDel, entity, theRequest, transactionDetails);
|
doMetaDelete(theMetaDel, entity, theRequest, transactionDetails);
|
||||||
} else {
|
} else {
|
||||||
doMetaDelete(theMetaDel, latestVersion, theRequest, transactionDetails);
|
doMetaDelete(theMetaDel, latestVersion, theRequest, transactionDetails);
|
||||||
|
|
||||||
// Also update history entry
|
// Also update history entry
|
||||||
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(entity.getId(), entity.getVersion());
|
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(entity.getId(), entity.getVersion());
|
||||||
doMetaDelete(theMetaDel, history, theRequest, transactionDetails);
|
doMetaDelete(theMetaDel, history, theRequest, transactionDetails);
|
||||||
|
@ -1123,7 +1123,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Transactional
|
@Transactional
|
||||||
public T readByPid(IResourcePersistentId thePid, boolean theDeletedOk) {
|
public T readByPid(IResourcePersistentId thePid, boolean theDeletedOk) {
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
JpaPid jpaPid = (JpaPid)thePid;
|
JpaPid jpaPid = (JpaPid) thePid;
|
||||||
|
|
||||||
Optional<ResourceTable> entity = myResourceTableDao.findById(jpaPid.getId());
|
Optional<ResourceTable> entity = myResourceTableDao.findById(jpaPid.getId());
|
||||||
if (!entity.isPresent()) {
|
if (!entity.isPresent()) {
|
||||||
|
@ -1219,7 +1219,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void reindex(IResourcePersistentId thePid, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
|
public void reindex(IResourcePersistentId thePid, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
|
||||||
JpaPid jpaPid = (JpaPid)thePid;
|
JpaPid jpaPid = (JpaPid) thePid;
|
||||||
Optional<ResourceTable> entityOpt = myResourceTableDao.findById(jpaPid.getId());
|
Optional<ResourceTable> entityOpt = myResourceTableDao.findById(jpaPid.getId());
|
||||||
if (!entityOpt.isPresent()) {
|
if (!entityOpt.isPresent()) {
|
||||||
ourLog.warn("Unable to find entity with PID: {}", jpaPid.getId());
|
ourLog.warn("Unable to find entity with PID: {}", jpaPid.getId());
|
||||||
|
@ -1312,7 +1312,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IBasePersistedResource readEntityLatestVersion(IResourcePersistentId thePersistentId, RequestDetails theRequestDetails, TransactionDetails theTransactionDetails) {
|
protected IBasePersistedResource readEntityLatestVersion(IResourcePersistentId thePersistentId, RequestDetails theRequestDetails, TransactionDetails theTransactionDetails) {
|
||||||
JpaPid jpaPid = (JpaPid)thePersistentId;
|
JpaPid jpaPid = (JpaPid) thePersistentId;
|
||||||
return myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
return myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1334,7 +1334,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
throw new ResourceNotFoundException(Msg.code(1997) + theId);
|
throw new ResourceNotFoundException(Msg.code(1997) + theId);
|
||||||
}
|
}
|
||||||
if (theTransactionDetails.hasResolvedResourceIds()) {
|
if (theTransactionDetails.hasResolvedResourceIds()) {
|
||||||
persistentId = (JpaPid)theTransactionDetails.getResolvedResourceId(theId);
|
persistentId = (JpaPid) theTransactionDetails.getResolvedResourceId(theId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,7 +1658,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
// Pre-cache the match URL
|
// Pre-cache the match URL
|
||||||
if (outcome.getPersistentId() != null) {
|
if (outcome.getPersistentId() != null) {
|
||||||
myMatchResourceUrlService.matchUrlResolved(theTransactionDetails, getResourceName(), theMatchUrl, (JpaPid)outcome.getPersistentId());
|
myMatchResourceUrlService.matchUrlResolved(theTransactionDetails, getResourceName(), theMatchUrl, (JpaPid) outcome.getPersistentId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return outcome;
|
return outcome;
|
||||||
|
@ -1703,7 +1703,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for updating the historical version of the resource when a history version id is included in the request.
|
* Method for updating the historical version of the resource when a history version id is included in the request.
|
||||||
*
|
*
|
||||||
|
|
|
@ -427,6 +427,51 @@ public class FhirResourceDaoR4TagsTest extends BaseResourceProviderR4Test {
|
||||||
validatePatientSearchResultsForInlineTags(outcome);
|
validatePatientSearchResultsForInlineTags(outcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaDelete_TagStorageModeNonVersioned_ShouldShowRemainingTagsInGetAllResources() {
|
||||||
|
myDaoConfig.setTagStorageMode(DaoConfig.TagStorageModeEnum.NON_VERSIONED);
|
||||||
|
Patient pt = new Patient();
|
||||||
|
Meta pMeta = new Meta();
|
||||||
|
pMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||||
|
pMeta.addTag().setSystem("urn:system2").setCode("urn:code2");
|
||||||
|
pt.setMeta(pMeta);
|
||||||
|
IIdType id = myClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Meta meta = myClient.meta().get(Meta.class).fromResource(id).execute();
|
||||||
|
assertEquals(2, meta.getTag().size());
|
||||||
|
|
||||||
|
Meta inMeta = new Meta();
|
||||||
|
inMeta.addTag().setSystem("urn:system2").setCode("urn:code2");
|
||||||
|
meta = myClient.meta().delete().onResource(id).meta(inMeta).execute();
|
||||||
|
assertEquals(1, meta.getTag().size());
|
||||||
|
|
||||||
|
Bundle patientBundle = myClient.search().forResource("Patient").returnBundle(Bundle.class).execute();
|
||||||
|
Patient patient = (Patient) patientBundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals(1, patient.getMeta().getTag().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaDelete_TagStorageModeVersioned_ShouldShowRemainingTagsInGetAllResources() {
|
||||||
|
Patient pt = new Patient();
|
||||||
|
Meta pMeta = new Meta();
|
||||||
|
pMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
|
||||||
|
pMeta.addTag().setSystem("urn:system2").setCode("urn:code2");
|
||||||
|
pt.setMeta(pMeta);
|
||||||
|
IIdType id = myClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Meta meta = myClient.meta().get(Meta.class).fromResource(id).execute();
|
||||||
|
assertEquals(2, meta.getTag().size());
|
||||||
|
|
||||||
|
Meta inMeta = new Meta();
|
||||||
|
inMeta.addTag().setSystem("urn:system2").setCode("urn:code2");
|
||||||
|
meta = myClient.meta().delete().onResource(id).meta(inMeta).execute();
|
||||||
|
assertEquals(1, meta.getTag().size());
|
||||||
|
|
||||||
|
Bundle patientBundle = myClient.search().forResource("Patient").returnBundle(Bundle.class).execute();
|
||||||
|
Patient patient = (Patient) patientBundle.getEntry().get(0).getResource();
|
||||||
|
assertEquals(1, patient.getMeta().getTag().size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInlineTags_Search_Profile() {
|
public void testInlineTags_Search_Profile() {
|
||||||
myDaoConfig.setTagStorageMode(DaoConfig.TagStorageModeEnum.INLINE);
|
myDaoConfig.setTagStorageMode(DaoConfig.TagStorageModeEnum.INLINE);
|
||||||
|
|
Loading…
Reference in New Issue