Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#1803] Fix NPE caused by wrong order by expression during criteria builder copying #1804

Merged
merged 1 commit into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Changes that happened in releases
* Fix dropping of embeddable group by expression when nested property has same name as parent property
* Fix SQL generation for lateral subqueries when correlated path has `@Where` predicate
* Fix `ConcurrentModificationException` during metamodel determination for special Hibernate Envers mappings
* Fix NPE caused by wrong order by expression during criteria builder copying

### Backwards-incompatible changes

Expand Down
4 changes: 2 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export MAVEN_OPTS="$MAVEN_OPTS -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli
# Increase retry count and reduce TTL for connections: https://github.com/actions/virtual-environments/issues/1499#issuecomment-718396233
export MAVEN_OPTS="$MAVEN_OPTS -Dmaven.wagon.httpconnectionManager.ttlSeconds=25 -Dmaven.wagon.http.retryHandler.count=3"
if [[ "$JDK" != "" ]]; then
export MAVEN_OPTS="-Xmx1280m -XX:MaxMetaspaceSize=512m $MAVEN_OPTS"
export MAVEN_OPTS="-Xmx1536m -XX:MaxMetaspaceSize=512m $MAVEN_OPTS"
else
export MAVEN_OPTS="-Xmx1280m -XX:MaxPermSize=512m $MAVEN_OPTS"
export MAVEN_OPTS="-Xmx1536m -XX:MaxPermSize=512m $MAVEN_OPTS"
fi

$DIR/mvnw -version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ public void collectConstantifiedJoinNodeAttributes(CompoundPredicate rootPredica
rootPredicate.accept(this);
}

public AliasManager getAliasManager() {
return aliasManager;
}

public Map<Object, Map<String, Boolean>> getConstantifiedJoinNodeAttributes() {
return constantifiedJoinNodeAttributes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,17 @@ private static boolean isNullable(EntityMetamodel metamodel, ConstantifiedJoinNo
return true;
}
int size = expressions.size();
if (rootTypes == null) {
if (size == 1 && constantifiedJoinNodeAttributeCollector != null) {
// In this case, the expression could be an alias referring to a non-path select item
AliasInfo aliasInfo = constantifiedJoinNodeAttributeCollector.getAliasManager().getAliasInfo(((PropertyExpression) expression).getProperty());
if (aliasInfo instanceof SelectInfo) {
return isNullable(metamodel, constantifiedJoinNodeAttributeCollector, ((SelectInfo) aliasInfo).getExpression());
}
}
// Not sure if this case is possible, but let's play defensive and return that this is nullable
return true;
}
Type<?> baseType = rootTypes.get(((PropertyExpression) expression).getProperty());
int i = 0;
if (baseType != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ String[] applyFrom(OrderByManager orderByManager, Map<String, Integer> identifie
if (selectInfo.getExpression() instanceof PathExpression) {
expression = copiedSelectExpression;
} else {
String alias = aliasManager.generateRootAlias("_generated_alias");
selectManager.select(copiedSelectExpression, alias);
String alias = aliasManager.generateRootAlias("bp_generated_alias");
List<Expression> args = new ArrayList<>(2);
args.add(new PathExpression(new PropertyExpression(alias)));
args.add(copiedSelectExpression);
args.add(new StringLiteral(alias));
expression = new FunctionExpression(AliasFunction.FUNCTION_NAME, args);
selectManager.select(new FunctionExpression(AliasFunction.FUNCTION_NAME, args), alias);
expression = new PathExpression(new PropertyExpression(alias));
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2014 - 2023 Blazebit.
*
* 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.
*/

package com.blazebit.persistence.view.testsuite.pagination;

import com.blazebit.persistence.PaginatedCriteriaBuilder;
import com.blazebit.persistence.testsuite.base.jpa.category.NoDatanucleus;
import com.blazebit.persistence.testsuite.base.jpa.category.NoEclipselink;
import com.blazebit.persistence.testsuite.base.jpa.category.NoOpenJPA;
import com.blazebit.persistence.testsuite.entity.Document;
import com.blazebit.persistence.testsuite.entity.Person;
import com.blazebit.persistence.testsuite.tx.TxVoidWork;
import com.blazebit.persistence.view.EntityView;
import com.blazebit.persistence.view.EntityViewManager;
import com.blazebit.persistence.view.EntityViewSetting;
import com.blazebit.persistence.view.FetchStrategy;
import com.blazebit.persistence.view.Mapping;
import com.blazebit.persistence.view.Sorters;
import com.blazebit.persistence.view.testsuite.AbstractEntityViewTest;
import com.blazebit.persistence.view.testsuite.basic.model.IdHolderView;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Set;

import static org.junit.Assert.assertEquals;

/**
*
* @author Christian Beikov
* @since 1.6.10
*/
public class PaginationTest extends AbstractEntityViewTest {

protected EntityViewManager evm;

@Before
public void initEvm() {
evm = build(DocumentViewInterface.class, PersonIdView.class);
}

@Override
public void setUpOnce() {
cleanDatabase();
transactional(new TxVoidWork() {
@Override
public void work(EntityManager em) {
doc1 = new Document("doc1");
Person o1 = new Person("pers1");

doc1.setAge(10);
doc1.setOwner(o1);

doc1.getContacts().put(1, o1);
doc1.getContacts2().put(2, o1);

em.persist(o1);
em.persist(doc1);
em.persist(new Document("doc2", o1));
}
});
}

@Before
public void setUp() {
doc1 = cbf.create(em, Document.class).where("name").eq("doc1").getSingleResult();
}

private Document doc1;

@Test
@Category({ NoEclipselink.class, NoDatanucleus.class, NoOpenJPA.class })
// TODO: report eclipselink does not support subqueries in functions
public void testPagination() {
EntityViewSetting<DocumentViewInterface, PaginatedCriteriaBuilder<DocumentViewInterface>> settings = EntityViewSetting.create(DocumentViewInterface.class, 0, 1)
.withAttributeSorter("number", Sorters.ascending())
.withAttributeSorter("id", Sorters.ascending());
List<DocumentViewInterface> page = evm.applySetting(settings, cbf.create(em, Document.class)).getResultList();
assertEquals(1, page.size());
}

@EntityView(Document.class)
public interface DocumentViewInterface extends IdHolderView<Long> {

public String getName();

@Mapping("COALESCE(FUNCTION('cast_long', idx), id)")
public Long getNumber();

@Mapping(fetch = FetchStrategy.SUBSELECT)
Set<PersonIdView> getContacts();

}
@EntityView(Person.class)
public interface PersonIdView extends IdHolderView<Long> {

}
}
Loading