From d15c6aed7c9b53052907538454f65c92a31842cb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 19:59:22 +0000 Subject: [PATCH 1/4] Initial plan From 5c9e116ce91dfee3c1783118f0688af2650269d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:16:33 +0000 Subject: [PATCH 2/4] Create test to reproduce aggregation parent reference issue Co-authored-by: hmottestad <797185+hmottestad@users.noreply.github.com> --- .../impl/AggregationParentReferenceTest.java | 44 +++ initial-evidence.txt | 261 ++++++++++++++++++ 2 files changed, 305 insertions(+) create mode 100644 core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java create mode 100644 initial-evidence.txt diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java new file mode 100644 index 0000000000..c7b8af45b7 --- /dev/null +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2025 Eclipse RDF4J contributors. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + *******************************************************************************/ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.algebra.TupleExpr; +import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker; +import org.eclipse.rdf4j.query.impl.EmptyBindingSet; +import org.eclipse.rdf4j.query.impl.SimpleDataset; +import org.eclipse.rdf4j.query.parser.sparql.SPARQLParser; +import org.junit.jupiter.api.Test; + +/** + * Test to reproduce and fix the parent reference issue with aggregation queries. + */ +public class AggregationParentReferenceTest { + + @Test + public void testAggregationParentReferences() { + String query = "SELECT (COUNT(?s) AS ?count) WHERE { ?s ?p ?o }"; + + TupleExpr expr = new SPARQLParser().parseQuery(query, null).getTupleExpr(); + + // This should not throw an AssertionError about parent references + new ParentReferenceChecker(null).optimize(expr, new SimpleDataset(), new EmptyBindingSet()); + } + + @Test + public void testComplexAggregationParentReferences() { + String query = "SELECT (COUNT(?s)/30 AS ?count) WHERE { ?s ?p ?o }"; + + TupleExpr expr = new SPARQLParser().parseQuery(query, null).getTupleExpr(); + + // This should not throw an AssertionError about parent references + new ParentReferenceChecker(null).optimize(expr, new SimpleDataset(), new EmptyBindingSet()); + } +} \ No newline at end of file diff --git a/initial-evidence.txt b/initial-evidence.txt new file mode 100644 index 0000000000..268ec20979 --- /dev/null +++ b/initial-evidence.txt @@ -0,0 +1,261 @@ +------------------------------------------------------------------------------- +Test set: org.eclipse.rdf4j.query.algebra.evaluation.impl.AggregationParentReferenceTest +------------------------------------------------------------------------------- +Tests run: 2, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.349 s <<< FAILURE! -- in org.eclipse.rdf4j.query.algebra.evaluation.impl.AggregationParentReferenceTest +org.eclipse.rdf4j.query.algebra.evaluation.impl.AggregationParentReferenceTest.testComplexAggregationParentReferences -- Time elapsed: 0.314 s <<< FAILURE! +java.lang.AssertionError: +After query parsing there was an unexpected parent for node +StatementPattern + Var (name=s) + Var (name=p) + Var (name=o) + +with parent: +Extension + StatementPattern + Var (name=s) + Var (name=p) + Var (name=o) + ExtensionElem (_anon_443008fec316472691878a307fd510ef1) + Count + Var (name=s) + +expected: +Group () + StatementPattern + Var (name=s) + Var (name=p) + Var (name=o) + GroupElem (_anon_443008fec316472691878a307fd510ef1) + Count + Var (name=s) + + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:110) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:458) + at org.eclipse.rdf4j.query.algebra.StatementPattern.visit(StatementPattern.java:311) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.Group.visitChildren(Group.java:138) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryTupleOperator(AbstractQueryModelVisitor.java:595) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:248) + at org.eclipse.rdf4j.query.algebra.Group.visit(Group.java:133) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.Extension.visitChildren(Extension.java:99) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryTupleOperator(AbstractQueryModelVisitor.java:595) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:223) + at org.eclipse.rdf4j.query.algebra.Extension.visit(Extension.java:94) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.Projection.visitChildren(Projection.java:86) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryTupleOperator(AbstractQueryModelVisitor.java:595) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:403) + at org.eclipse.rdf4j.query.algebra.Projection.visit(Projection.java:80) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:418) + at org.eclipse.rdf4j.query.algebra.QueryRoot.visit(QueryRoot.java:41) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker.optimize(ParentReferenceChecker.java:59) + at org.eclipse.rdf4j.query.algebra.evaluation.impl.AggregationParentReferenceTest.testComplexAggregationParentReferences(AggregationParentReferenceTest.java:42) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) + at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) + +org.eclipse.rdf4j.query.algebra.evaluation.impl.AggregationParentReferenceTest.testAggregationParentReferences -- Time elapsed: 0.009 s <<< FAILURE! +java.lang.AssertionError: +After query parsing there was an unexpected parent for node +Count + Var (name=s) + +with parent: +ExtensionElem (count) + Count + Var (name=s) + +expected: +GroupElem (count) + Count + Var (name=s) + + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:110) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryValueOperator(AbstractQueryModelVisitor.java:605) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:183) + at org.eclipse.rdf4j.query.algebra.Count.visit(Count.java:29) + at org.eclipse.rdf4j.query.algebra.GroupElem.visitChildren(GroupElem.java:69) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:258) + at org.eclipse.rdf4j.query.algebra.GroupElem.visit(GroupElem.java:64) + at org.eclipse.rdf4j.query.algebra.Group.visitChildren(Group.java:141) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryTupleOperator(AbstractQueryModelVisitor.java:595) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:248) + at org.eclipse.rdf4j.query.algebra.Group.visit(Group.java:133) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.Extension.visitChildren(Extension.java:99) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryTupleOperator(AbstractQueryModelVisitor.java:595) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:223) + at org.eclipse.rdf4j.query.algebra.Extension.visit(Extension.java:94) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.Projection.visitChildren(Projection.java:86) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetUnaryTupleOperator(AbstractQueryModelVisitor.java:595) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:403) + at org.eclipse.rdf4j.query.algebra.Projection.visit(Projection.java:80) + at org.eclipse.rdf4j.query.algebra.UnaryTupleOperator.visitChildren(UnaryTupleOperator.java:72) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meetNode(AbstractQueryModelVisitor.java:575) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker$ParentCheckingVisitor.meetNode(ParentReferenceChecker.java:114) + at org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor.meet(AbstractQueryModelVisitor.java:418) + at org.eclipse.rdf4j.query.algebra.QueryRoot.visit(QueryRoot.java:41) + at org.eclipse.rdf4j.query.algebra.evaluation.optimizer.ParentReferenceChecker.optimize(ParentReferenceChecker.java:59) + at org.eclipse.rdf4j.query.algebra.evaluation.impl.AggregationParentReferenceTest.testAggregationParentReferences(AggregationParentReferenceTest.java:32) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) + at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) + From 18dc8e40f3d323421c132f8f921a95e3ee1cb489 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:24:36 +0000 Subject: [PATCH 3/4] Attempt to fix aggregation parent reference issue with cloning Co-authored-by: hmottestad <797185+hmottestad@users.noreply.github.com> --- .../impl/AggregationParentReferenceTest.java | 3 +++ .../rdf4j/query/parser/sparql/TupleExprBuilder.java | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java index c7b8af45b7..36426abd21 100644 --- a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java @@ -28,6 +28,9 @@ public void testAggregationParentReferences() { TupleExpr expr = new SPARQLParser().parseQuery(query, null).getTupleExpr(); + // Print the structure before parent reference check + System.out.println("Structure: " + expr); + // This should not throw an AssertionError about parent references new ParentReferenceChecker(null).optimize(expr, new SimpleDataset(), new EmptyBindingSet()); } diff --git a/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java b/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java index a52d72d887..a271420853 100644 --- a/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java +++ b/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java @@ -568,20 +568,27 @@ public TupleExpr visit(ASTSelect node, Object data) throws VisitorException { } if (operator.equals(valueExpr)) { - group.addGroupElement(new GroupElem(alias, operator)); + AggregateOperator clonedOperator = operator.clone(); + group.addGroupElement(new GroupElem(alias, clonedOperator)); extension.setArg(group); + System.out.println("Original operator ID: " + System.identityHashCode(operator)); + System.out.println("Cloned operator ID: " + System.identityHashCode(clonedOperator)); } else { ValueExpr expr = (ValueExpr) operator.getParentNode(); Extension anonymousExtension = new Extension(); Var anonVar = createAnonVar(); expr.replaceChildNode(operator, anonVar); - anonymousExtension.addElement(new ExtensionElem(operator, anonVar.getName())); + anonymousExtension.addElement(new ExtensionElem(operator.clone(), anonVar.getName())); anonymousExtension.setArg(result); result = anonymousExtension; group.addGroupElement(new GroupElem(anonVar.getName(), operator)); - + + // Update the group's argument to point to the new result structure + if (!isExistingGroup) { + group.setArg(result); + } } if (!isExistingGroup) { From 265e27cda878c14879f0626950a0ac182b760193 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:29:14 +0000 Subject: [PATCH 4/4] Fix aggregation parent reference issue by cloning operators Co-authored-by: hmottestad <797185+hmottestad@users.noreply.github.com> --- .../impl/AggregationParentReferenceTest.java | 3 --- .../query/parser/sparql/TupleExprBuilder.java | 14 ++++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java index 36426abd21..c7b8af45b7 100644 --- a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AggregationParentReferenceTest.java @@ -28,9 +28,6 @@ public void testAggregationParentReferences() { TupleExpr expr = new SPARQLParser().parseQuery(query, null).getTupleExpr(); - // Print the structure before parent reference check - System.out.println("Structure: " + expr); - // This should not throw an AssertionError about parent references new ParentReferenceChecker(null).optimize(expr, new SimpleDataset(), new EmptyBindingSet()); } diff --git a/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java b/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java index a271420853..f24c954810 100644 --- a/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java +++ b/core/queryparser/sparql/src/main/java/org/eclipse/rdf4j/query/parser/sparql/TupleExprBuilder.java @@ -568,23 +568,23 @@ public TupleExpr visit(ASTSelect node, Object data) throws VisitorException { } if (operator.equals(valueExpr)) { - AggregateOperator clonedOperator = operator.clone(); - group.addGroupElement(new GroupElem(alias, clonedOperator)); + // For simple aggregations like COUNT(?s), clone the operator to avoid + // parent reference conflicts when it's added to both GroupElem and ExtensionElem + group.addGroupElement(new GroupElem(alias, operator.clone())); extension.setArg(group); - System.out.println("Original operator ID: " + System.identityHashCode(operator)); - System.out.println("Cloned operator ID: " + System.identityHashCode(clonedOperator)); } else { ValueExpr expr = (ValueExpr) operator.getParentNode(); Extension anonymousExtension = new Extension(); Var anonVar = createAnonVar(); expr.replaceChildNode(operator, anonVar); + // Clone the operator for the ExtensionElem to avoid parent reference conflicts anonymousExtension.addElement(new ExtensionElem(operator.clone(), anonVar.getName())); anonymousExtension.setArg(result); result = anonymousExtension; group.addGroupElement(new GroupElem(anonVar.getName(), operator)); - + // Update the group's argument to point to the new result structure if (!isExistingGroup) { group.setArg(result); @@ -600,7 +600,9 @@ public TupleExpr visit(ASTSelect node, Object data) throws VisitorException { // SELECT expressions need to be captured as an extension, so that original and alias are // available for the ORDER BY clause (which gets applied _before_ projection). See GH-4066 // and https://www.w3.org/TR/sparql11-query/#sparqlSolMod . - ExtensionElem extElem = new ExtensionElem(valueExpr, alias); + // Clone valueExpr if it contains aggregates to avoid parent reference conflicts + ValueExpr extValueExpr = !collector.getOperators().isEmpty() ? valueExpr.clone() : valueExpr; + ExtensionElem extElem = new ExtensionElem(extValueExpr, alias); extension.addElement(extElem); elem.setSourceExpression(extElem); } else if (child instanceof ASTVar) {