Skip to content

AS OF SYSTEM TIME NULL combined with any WHERE predicate returns zero rows #170

Description

@mkhairi

Tested against: origin/main @ 8e84501a (post-v0.3.0 main head, 2026-07-07)

Severity: High — per-record history reads are the primary query shape on
a BITEMPORAL collection; every such read silently returns empty, making the
audit surface unusable while writes keep succeeding.

Summary

On a BITEMPORAL document_strict collection, a version-history scan
(AS OF SYSTEM TIME NULL) that also carries a WHERE predicate
returns 0 rows silently. The bare AS OF SYSTEM TIME NULL scan on
the same collection returns the full version set with correct
_ts_system / _ts_valid_from / _ts_valid_until projections, so the
versioned store itself is intact — only the predicate-carrying scan
path drops everything. ORDER BY makes no difference. The result also
comes back with a placeholder result column header instead of the
collection's columns, suggesting the query resolves to an empty
synthetic result rather than a filtered scan.

Regression relative to 67c4572d, where AS OF SYSTEM TIME NULL WHERE id = ... returned that record's versions; plausibly fallout of the
recent unification of bitemporal document scans onto a shared pipeline.

Repro

CREATE COLLECTION asof_repro (id TEXT PRIMARY KEY, v TEXT, BITEMPORAL) ENGINE = document_strict;
INSERT INTO asof_repro (id, v) VALUES ('a','one');
UPDATE asof_repro SET v = 'two' WHERE id = 'a';

SELECT * FROM asof_repro AS OF SYSTEM TIME NULL;
--  id | _ts_system    | _ts_valid_from       | _ts_valid_until     | v
--  a  | 1783400895366 | -9223372036854775808 | 9223372036854775807 | one
--  a  | 1783400895370 | -9223372036854775808 | 9223372036854775807 | two
-- (2 rows)                          -- full history, correct

SELECT * FROM asof_repro AS OF SYSTEM TIME NULL WHERE id = 'a';
--  result
-- (0 rows)                          -- WRONG: expected the same 2 versions

SELECT * FROM asof_repro AS OF SYSTEM TIME NULL WHERE id = 'a' ORDER BY _ts_system;
-- (0 rows)                          -- WRONG

Expected

  1. AS OF SYSTEM TIME NULL + WHERE returns the version rows matching
    the predicate — filtering a history scan must not differ semantically
    from filtering a plain scan.
  2. The result carries the collection's real column set (as the bare
    scan already does), not a placeholder result column.

Files (best-guess)

  • nodedb/src/data/executor/handlers/document/read/fetch.rs — new
    shared fetch pipeline; the predicate path appears not to be wired for
    all-versions scans.
  • nodedb/src/data/executor/dispatch/document.rs — dispatch may route
    predicate-carrying AS OF reads to a path that ignores the version
    store.

Operational context

The whole point of a BITEMPORAL collection is answering "what did this
record look like over time" — i.e. AS OF SYSTEM TIME NULL WHERE <key>.
With that shape returning empty, audit-trail consumers must scan the
entire history of every record and filter client-side, which is
unbounded on a growing audit log.

Activity

  1. added
    type:bugA defect — broken, incorrect, or lost data
    sev:2-highMajor functionality broken; no acceptable workaround
    engine:documentDocument engine (schemaless + strict)
    area:bitemporalSystem/valid time, AS OF queries
    regressionWorked on an earlier build; broke since
    on Jul 8, 2026
  2. farhan-syah commented on Jul 19, 2026

    @farhan-syah
    Member

    Fixed on main (commit c2dbbd30), shipping in v0.4.0.

    Root cause: the AS OF SYSTEM TIME NULL audit-scan path applied the WHERE predicate against the raw stored body using the MessagePack matcher. For a document_strict collection that body is a Binary Tuple, which the MessagePack matcher silently never matches — so every version was filtered out (0 rows, and the placeholder result column because there were no rows to derive real columns from). The sibling point-in-time AS OF arm already used the schema-aware matcher; the all-versions arm missed it during the shared-pipeline unification.

    Fix: the all-versions predicate path now uses matches_with_resolved_schema, identical to the AS OF path — it decodes the Binary Tuple via the schema before matching. Schemaless behaviour is unchanged.

    Regression test: added to nodedb/tests/bitemporal_asof_scan_parity.rs (strict bitemporal collection; AS OF SYSTEM TIME NULL WHERE id='a' returns the matching versions with real columns). Verified green.

  3. added a commit that references this issue on Jul 19, 2026
    c2dbbd3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:bitemporalSystem/valid time, AS OF queriesengine:documentDocument engine (schemaless + strict)regressionWorked on an earlier build; broke sincesev:2-highMajor functionality broken; no acceptable workaroundtype:bugA defect — broken, incorrect, or lost data

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions