Skip to content

agtype: return an empty list from tail() for empty and singleton lists#2399

Merged
MuhammadTahaNaveed merged 1 commit intoapache:masterfrom
SAY-5:fix/tail-returns-empty-list-2384
Apr 20, 2026
Merged

agtype: return an empty list from tail() for empty and singleton lists#2399
MuhammadTahaNaveed merged 1 commit intoapache:masterfrom
SAY-5:fix/tail-returns-empty-list-2384

Conversation

@SAY-5
Copy link
Copy Markdown
Contributor

@SAY-5 SAY-5 commented Apr 20, 2026

Fixes #2384.

age_tail() in src/backend/utils/adt/agtype.c had an explicit early return that mapped both the empty-list and the singleton-list cases to SQL NULL:

count = AGT_ROOT_COUNT(agt_arg);
/* if we have an empty list or only one element in the list, return null */
if (count <= 1)
{
    PG_RETURN_NULL();
}

The Cypher specification — and Neo4j / Memgraph, as shown in the issue — both define tail(list) as "the list without its first element". For a zero-or-one-element input that is an empty list [], not null. Differential tests against Neo4j surface this divergence immediately.

Removing the early return is enough: the loop below already iterates from i = 1, so it naturally emits [] for count <= 1 and emits the correct tail for the general case. No behaviour change for count >= 2.

Regression tests and expected output are updated accordingly — the two "should return null" cases at the end of the tail() section now expect [] and the comment is corrected.

SELECT * FROM cypher('list', $$ RETURN tail([1]) $$) AS (tail agtype);   -- []
SELECT * FROM cypher('list', $$ RETURN tail([])  $$) AS (tail agtype);   -- []

…gleton lists

age_tail() in src/backend/utils/adt/agtype.c had an explicit early return
that mapped both the empty-list and the singleton-list cases to SQL NULL:

    count = AGT_ROOT_COUNT(agt_arg);
    /* if we have an empty list or only one element in the list, return null */
    if (count <= 1)
    {
        PG_RETURN_NULL();
    }

The Cypher specification (and Neo4j / Memgraph, as shown in apache#2384) both
define tail(list) as "the list without its first element". For a
zero-or-one-element input that is an empty list [], not null. Differential
tests against Neo4j surface this divergence immediately.

Remove the early return. The loop below already iterates from i=1 so it
naturally emits [] for count <= 1 and emits the correct tail for the
general case. No behaviour change for count >= 2. Tests and expected
output are updated to match the new, spec-correct result.

Fixes apache#2384
@MuhammadTahaNaveed MuhammadTahaNaveed merged commit 908d7b2 into apache:master Apr 20, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tail() may return null on Apache AGE when the input list has length 0 or 1.

2 participants