Skip to content

Commit

Permalink
Fix crash with unique search parameter updates in JPA
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesagnew committed Feb 16, 2018
1 parent 2847edd commit e89f8e5
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 22 deletions.
@@ -1,5 +1,25 @@
package ca.uhn.fhir.util;

/*-
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
Expand Down
Expand Up @@ -1694,27 +1694,31 @@ protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTa

for (ResourceIndexedSearchParamString next : removeCommon(existingStringParams, stringParams)) {
myEntityManager.remove(next);
theEntity.getParamsString().remove(next);
}
for (ResourceIndexedSearchParamString next : removeCommon(stringParams, existingStringParams)) {
myEntityManager.persist(next);
}

for (ResourceIndexedSearchParamToken next : removeCommon(existingTokenParams, tokenParams)) {
myEntityManager.remove(next);
theEntity.getParamsToken().remove(next);
}
for (ResourceIndexedSearchParamToken next : removeCommon(tokenParams, existingTokenParams)) {
myEntityManager.persist(next);
}

for (ResourceIndexedSearchParamNumber next : removeCommon(existingNumberParams, numberParams)) {
myEntityManager.remove(next);
theEntity.getParamsNumber().remove(next);
}
for (ResourceIndexedSearchParamNumber next : removeCommon(numberParams, existingNumberParams)) {
myEntityManager.persist(next);
}

for (ResourceIndexedSearchParamQuantity next : removeCommon(existingQuantityParams, quantityParams)) {
myEntityManager.remove(next);
theEntity.getParamsQuantity().remove(next);
}
for (ResourceIndexedSearchParamQuantity next : removeCommon(quantityParams, existingQuantityParams)) {
myEntityManager.persist(next);
Expand All @@ -1723,6 +1727,7 @@ protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTa
// Store date SP's
for (ResourceIndexedSearchParamDate next : removeCommon(existingDateParams, dateParams)) {
myEntityManager.remove(next);
theEntity.getParamsDate().remove(next);
}
for (ResourceIndexedSearchParamDate next : removeCommon(dateParams, existingDateParams)) {
myEntityManager.persist(next);
Expand All @@ -1731,6 +1736,7 @@ protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTa
// Store URI SP's
for (ResourceIndexedSearchParamUri next : removeCommon(existingUriParams, uriParams)) {
myEntityManager.remove(next);
theEntity.getParamsUri().remove(next);
}
for (ResourceIndexedSearchParamUri next : removeCommon(uriParams, existingUriParams)) {
myEntityManager.persist(next);
Expand All @@ -1739,6 +1745,7 @@ protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTa
// Store Coords SP's
for (ResourceIndexedSearchParamCoords next : removeCommon(existingCoordsParams, coordsParams)) {
myEntityManager.remove(next);
theEntity.getParamsCoords().remove(next);
}
for (ResourceIndexedSearchParamCoords next : removeCommon(coordsParams, existingCoordsParams)) {
myEntityManager.persist(next);
Expand All @@ -1747,6 +1754,7 @@ protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTa
// Store resource links
for (ResourceLink next : removeCommon(existingResourceLinks, links)) {
myEntityManager.remove(next);
theEntity.getResourceLinks().remove(next);
}
for (ResourceLink next : removeCommon(links, existingResourceLinks)) {
myEntityManager.persist(next);
Expand All @@ -1756,23 +1764,20 @@ protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTa

// Store composite string uniques
if (getConfig().isUniqueIndexesEnabled()) {
for (ResourceIndexedCompositeStringUnique next : existingCompositeStringUniques) {
if (!compositeStringUniques.contains(next)) {
ourLog.debug("Removing unique index: {}", next);
myEntityManager.remove(next);
}
for (ResourceIndexedCompositeStringUnique next : removeCommon(existingCompositeStringUniques, compositeStringUniques)) {
ourLog.info("Removing unique index: {}", next);
myEntityManager.remove(next);
theEntity.getParamsCompositeStringUnique().remove(next);
}
for (ResourceIndexedCompositeStringUnique next : compositeStringUniques) {
if (!existingCompositeStringUniques.contains(next)) {
if (myConfig.isUniqueIndexesCheckedBeforeSave()) {
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
if (existing != null) {
throw new PreconditionFailedException("Can not create resource of type " + theEntity.getResourceType() + " as it would create a duplicate index matching query: " + next.getIndexString() + " (existing index belongs to " + existing.getResource().getIdDt().toUnqualifiedVersionless().getValue() + ")");
}
for (ResourceIndexedCompositeStringUnique next : removeCommon(compositeStringUniques, existingCompositeStringUniques)) {
if (myConfig.isUniqueIndexesCheckedBeforeSave()) {
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
if (existing != null) {
throw new PreconditionFailedException("Can not create resource of type " + theEntity.getResourceType() + " as it would create a duplicate index matching query: " + next.getIndexString() + " (existing index belongs to " + existing.getResource().getIdDt().toUnqualifiedVersionless().getValue() + ")");
}
ourLog.debug("Persisting unique index: {}", next);
myEntityManager.persist(next);
}
ourLog.info("Persisting unique index: {}", next);
myEntityManager.persist(next);
}
}

Expand Down
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down
Expand Up @@ -337,6 +337,42 @@ public void testIndexTransactionWithMatchUrl2() {

}

@Test
public void testReplaceOneWithAnother() {
createUniqueBirthdateAndGenderSps();

Patient pt1 = new Patient();
pt1.setGender(Enumerations.AdministrativeGender.MALE);
pt1.setBirthDateElement(new DateType("2011-01-01"));
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualified();
assertNotNull(id1);

ourLog.info("** Replacing");

pt1 = new Patient();
pt1.setId(id1);
pt1.setGender(Enumerations.AdministrativeGender.FEMALE);
pt1.setBirthDateElement(new DateType("2011-01-01"));
id1 = myPatientDao.update(pt1).getId().toUnqualified();
assertNotNull(id1);
assertEquals("2", id1.getVersionIdPart());

Patient pt2 = new Patient();
pt2.setGender(Enumerations.AdministrativeGender.MALE);
pt2.setBirthDateElement(new DateType("2011-01-01"));
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();

SearchBuilder.resetLastHandlerMechanismForUnitTest();
SearchParameterMap params = new SearchParameterMap();
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
params.add("birthdate", new DateParam("2011-01-01"));
IBundleProvider results = myPatientDao.search(params);
String searchId = results.getUuid();
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id2.getValue()));
assertEquals(SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest());

}

@Test
public void testSearchSynchronousUsingUniqueComposite() {
createUniqueBirthdateAndGenderSps();
Expand Down
5 changes: 5 additions & 0 deletions src/changes/changes.xml
Expand Up @@ -135,6 +135,11 @@
Avoid refreshing the search parameter cache from an incoming client
request thread, which caused unneccesary delays for clients.
</action>
<action type="fix">
An occasional crash in the JPA was fixed when using unique search
parameters and updating a resource to no longer match
one of these search parameters.
</action>
</release>
<release version="3.2.0" date="2018-01-13">
<action type="add">
Expand Down

0 comments on commit e89f8e5

Please sign in to comment.