Skip to content

Correlated COLLECT { ... } subqueries with outer-variable access may evaluate as empty lists #4014

Description

@Silence6666668

ArcadeDB version
Observed on Docker images:

  • arcadedata/arcadedb:26.4.1-SNAPSHOT
  • arcadedata/arcadedb:26.4.2

Older lines also behave incorrectly, but differently:

  • arcadedata/arcadedb:latest
  • arcadedata/arcadedb:26.3.2

On those older lines, the same correlated form currently returns null instead of a list.
On the 26.4.x line, the subquery is accepted and typed as a list, but the list is incorrectly empty.

Environment

  • Host OS: Windows 10
  • Architecture: x86_64
  • Deployment: Docker
  • ArcadeDB endpoint: HTTP /api/v1/command/arcade
  • Request mode used for direct reproduction:
    • language: opencypher
    • serializer: studio
  • Differential comparison target: Neo4j Docker neo4j:latest

Describe the bug
On ArcadeDB 26.4.1-SNAPSHOT and 26.4.2, a correlated COLLECT { ... } subquery may evaluate as an empty list when the inner body reads an outer variable.

In the minimized repro below, the inner subquery clearly produces rows:

  • Alice should collect Charlie and Diana
  • Charlie should collect Diana
  • Diana should collect nothing

Neo4j returns the expected lists.
ArcadeDB instead returns [] for every row.

This does not look like a general COLLECT { ... } problem:

  • uncorrelated COLLECT { MATCH ... } works
  • the same logic expressed with ordinary OPTIONAL MATCH + collect(...) also works

So the boundary appears to be correlated outer-variable access inside the COLLECT body.

To Reproduce

Setup:

CREATE (:Person {name:'Alice', age:30}),
       (:Person {name:'Bob', age:25}),
       (:Person {name:'Charlie', age:35}),
       (:Person {name:'Diana', age:40});

Query:

MATCH (p:Person)
WHERE p.age > 25
RETURN p.name AS name,
       COLLECT {
         MATCH (p2:Person)
         WHERE p2.age > p.age
         RETURN p2.name
       } AS xs
ORDER BY name;

Expected behavior
Observed Neo4j result:

Alice,   ['Charlie', 'Diana']
Charlie, ['Diana']
Diana,   []

Actual behavior
Observed ArcadeDB 26.4.1-SNAPSHOT / 26.4.2 result:

Alice,   []
Charlie, []
Diana,   []

Observed ArcadeDB latest / 26.3.2 result:

Alice,   null
Charlie, null
Diana,   null

So the correlated COLLECT { ... } does not preserve the rows produced by the inner comparison.

Control cases

The same COLLECT { ... } structure works when the inner subquery is uncorrelated:

MATCH (p:Person)
WHERE p.age > 25
RETURN p.name AS name,
       COLLECT {
         MATCH (p2:Person)
         WHERE p2.age > 30
         RETURN p2.name
       } AS xs
ORDER BY name;

Observed result on Neo4j and ArcadeDB 26.4.1-SNAPSHOT / 26.4.2:

Alice,   ['Charlie', 'Diana']
Charlie, ['Charlie', 'Diana']
Diana,   ['Charlie', 'Diana']

So COLLECT { MATCH ... } itself is fine.

The same logical test also works when expressed without COLLECT { ... }:

MATCH (p:Person)
WHERE p.age > 25
OPTIONAL MATCH (p2:Person)
WHERE p2.age > p.age
RETURN p.name AS name,
       collect(p2.name) AS xs
ORDER BY name;

Observed result on Neo4j and ArcadeDB 26.4.1-SNAPSHOT / 26.4.2:

Alice,   ['Charlie', 'Diana']
Charlie, ['Diana']
Diana,   []

So the data and comparison itself are not the problem.

Aliasing the outer value also does not avoid the bug:

MATCH (p:Person)
WHERE p.age > 25
WITH p, p.age AS age
RETURN p.name AS name,
       COLLECT {
         MATCH (p2:Person)
         WHERE p2.age > age
         RETURN p2.name
       } AS xs
ORDER BY name;

Observed Neo4j result:

Alice,   ['Charlie', 'Diana']
Charlie, ['Diana']
Diana,   []

Observed ArcadeDB 26.4.1-SNAPSHOT / 26.4.2 result:

Alice,   []
Charlie, []
Diana,   []

This makes the boundary clearer:

  • uncorrelated COLLECT: correct
  • equivalent non-COLLECT logic: correct
  • correlated inner comparison against an outer value: incorrect

At the same time, the following still behaves correctly on both engines:

MATCH (p:Person)
RETURN p.name AS name,
       COLLECT {
         OPTIONAL MATCH (p)-[:KNOWS]->(q)
         RETURN q.name
       } AS xs
ORDER BY name;

Observed result:

Alice,   ['Bob']
Bob,     [null]
Charlie, [null]
Diana,   [null]

So this does not look like all correlated COLLECT subqueries fail.
It looks more like outer-variable access modes inside the subquery are mishandled:

  • uncorrelated inner match: correct
  • correlated OPTIONAL MATCH over the same node variable: correct
  • scalar comparison against an outer value: incorrect

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions