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:
StevenXLi 2023-01-11 08:03:51 -05:00 committed by GitHub
parent 8c48a6fb91
commit 920755427b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 10 deletions

View File

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

View File

@ -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.util.JpaConstants;
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.PersistedJpaBundleProviderFactory;
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.SimplePreResourceAccessDetails;
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.IResourcePersistentId;
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();
List<ResourceTable> deletedResources = new ArrayList<>();
for (P pid : theResourceIds) {
JpaPid jpaPid = (JpaPid)pid;
JpaPid jpaPid = (JpaPid) pid;
ResourceTable entity = myEntityManager.find(ResourceTable.class, jpaPid.getId());
deletedResources.add(entity);
@ -1039,11 +1039,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
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);
} else {
doMetaDelete(theMetaDel, latestVersion, theRequest, transactionDetails);
// Also update history entry
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(entity.getId(), entity.getVersion());
doMetaDelete(theMetaDel, history, theRequest, transactionDetails);
@ -1123,7 +1123,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Transactional
public T readByPid(IResourcePersistentId thePid, boolean theDeletedOk) {
StopWatch w = new StopWatch();
JpaPid jpaPid = (JpaPid)thePid;
JpaPid jpaPid = (JpaPid) thePid;
Optional<ResourceTable> entity = myResourceTableDao.findById(jpaPid.getId());
if (!entity.isPresent()) {
@ -1219,7 +1219,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@SuppressWarnings("unchecked")
@Override
public void reindex(IResourcePersistentId thePid, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
JpaPid jpaPid = (JpaPid)thePid;
JpaPid jpaPid = (JpaPid) thePid;
Optional<ResourceTable> entityOpt = myResourceTableDao.findById(jpaPid.getId());
if (!entityOpt.isPresent()) {
ourLog.warn("Unable to find entity with PID: {}", jpaPid.getId());
@ -1312,7 +1312,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override
protected IBasePersistedResource readEntityLatestVersion(IResourcePersistentId thePersistentId, RequestDetails theRequestDetails, TransactionDetails theTransactionDetails) {
JpaPid jpaPid = (JpaPid)thePersistentId;
JpaPid jpaPid = (JpaPid) thePersistentId;
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);
}
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
if (outcome.getPersistentId() != null) {
myMatchResourceUrlService.matchUrlResolved(theTransactionDetails, getResourceName(), theMatchUrl, (JpaPid)outcome.getPersistentId());
myMatchResourceUrlService.matchUrlResolved(theTransactionDetails, getResourceName(), theMatchUrl, (JpaPid) outcome.getPersistentId());
}
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.
*

View File

@ -427,6 +427,51 @@ public class FhirResourceDaoR4TagsTest extends BaseResourceProviderR4Test {
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
public void testInlineTags_Search_Profile() {
myDaoConfig.setTagStorageMode(DaoConfig.TagStorageModeEnum.INLINE);