Update path when updating resource links (#2007)
* fix resource link index reuse bug * Resolve merge conflicts Co-authored-by: Ken Stevens <khstevens@gmail.com>
This commit is contained in:
parent
6a8e09addf
commit
3098affccb
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 2006
|
||||||
|
title: "When updating a resource with links that change, to reduce database operations, hapi-fhir reuses link index records.
|
||||||
|
However, all the columns were being properly updated except for the source path column which was accidentally missed and
|
||||||
|
continued to hold the previous value. This resulted in mismatched source paths and values. This has been corrected."
|
|
@ -19,19 +19,75 @@ import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||||
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
|
import ca.uhn.fhir.rest.param.HasAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.HasOrListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.HasParam;
|
||||||
|
import ca.uhn.fhir.rest.param.NumberParam;
|
||||||
|
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||||
|
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||||
|
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.ReferenceOrListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||||
|
import ca.uhn.fhir.rest.param.UriParam;
|
||||||
|
import ca.uhn.fhir.rest.param.UriParamQualifierEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
import org.hl7.fhir.dstu3.model.Appointment;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||||
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
|
import org.hl7.fhir.dstu3.model.Condition;
|
||||||
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
|
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.DateType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Device;
|
||||||
|
import org.hl7.fhir.dstu3.model.DiagnosticReport;
|
||||||
|
import org.hl7.fhir.dstu3.model.Encounter;
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
||||||
|
import org.hl7.fhir.dstu3.model.Group;
|
||||||
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Immunization;
|
||||||
|
import org.hl7.fhir.dstu3.model.ImmunizationRecommendation;
|
||||||
|
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Location;
|
||||||
|
import org.hl7.fhir.dstu3.model.Medication;
|
||||||
|
import org.hl7.fhir.dstu3.model.MedicationAdministration;
|
||||||
|
import org.hl7.fhir.dstu3.model.MedicationRequest;
|
||||||
|
import org.hl7.fhir.dstu3.model.Observation;
|
||||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.Organization;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.Period;
|
||||||
|
import org.hl7.fhir.dstu3.model.Practitioner;
|
||||||
|
import org.hl7.fhir.dstu3.model.ProcedureRequest;
|
||||||
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
|
import org.hl7.fhir.dstu3.model.Range;
|
||||||
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
|
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
||||||
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Subscription;
|
||||||
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
|
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
|
||||||
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
|
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.Substance;
|
||||||
|
import org.hl7.fhir.dstu3.model.Task;
|
||||||
|
import org.hl7.fhir.dstu3.model.Timing;
|
||||||
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -63,6 +119,7 @@ import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.hasItems;
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
@ -3622,6 +3679,37 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
||||||
assertThat(ids.toString(), ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB"));
|
assertThat(ids.toString(), ids, contains("Patient/AA", "Patient/AB", "Patient/BA", "Patient/BB"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReplaceLinkSearchIndex() {
|
||||||
|
Patient pt = new Patient();
|
||||||
|
IIdType ptId = myPatientDao.create(pt).getId().toVersionless();
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.setSubject(new Reference(ptId));
|
||||||
|
IIdType obsId = myObservationDao.create(obs).getId().toVersionless();
|
||||||
|
|
||||||
|
Practitioner pr = new Practitioner();
|
||||||
|
IIdType prId = myPractitionerDao.create(pr).getId().toVersionless();
|
||||||
|
|
||||||
|
obs.setId(obsId);
|
||||||
|
obs.setSubject(null);
|
||||||
|
obs.addPerformer(new Reference(prId));
|
||||||
|
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
myObservationDao.update(obs);
|
||||||
|
|
||||||
|
assertEquals(2, myCaptureQueriesListener.countUpdateQueries());
|
||||||
|
String unformattedSql = myCaptureQueriesListener.getUpdateQueriesForCurrentThread().get(0).getSql(true, false);
|
||||||
|
assertThat(unformattedSql, stringContainsInOrder(
|
||||||
|
"SRC_PATH='Observation.performer'",
|
||||||
|
"SRC_RESOURCE_ID='" + obsId.getIdPart() + "'",
|
||||||
|
"TARGET_RESOURCE_ID='" + prId.getIdPart() + "'",
|
||||||
|
"TARGET_RESOURCE_TYPE='Practitioner'"
|
||||||
|
));
|
||||||
|
myCaptureQueriesListener.logUpdateQueriesForCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private String toStringMultiline(List<?> theResults) {
|
private String toStringMultiline(List<?> theResults) {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
for (Object next : theResults) {
|
for (Object next : theResults) {
|
||||||
|
|
|
@ -26,7 +26,21 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.hibernate.search.annotations.Field;
|
import org.hibernate.search.annotations.Field;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.ForeignKey;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.SequenceGenerator;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
import javax.persistence.Transient;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
@ -118,6 +132,7 @@ public class ResourceLink extends BaseResourceIndex {
|
||||||
@Override
|
@Override
|
||||||
public <T extends BaseResourceIndex> void copyMutableValuesFrom(T theSource) {
|
public <T extends BaseResourceIndex> void copyMutableValuesFrom(T theSource) {
|
||||||
ResourceLink source = (ResourceLink) theSource;
|
ResourceLink source = (ResourceLink) theSource;
|
||||||
|
mySourcePath = source.getSourcePath();
|
||||||
myTargetResource = source.getTargetResource();
|
myTargetResource = source.getTargetResource();
|
||||||
myTargetResourceId = source.getTargetResourceId();
|
myTargetResourceId = source.getTargetResourceId();
|
||||||
myTargetResourcePid = source.getTargetResourcePid();
|
myTargetResourcePid = source.getTargetResourcePid();
|
||||||
|
|
Loading…
Reference in New Issue