Skip to content

DROP + CREATE of a BITEMPORAL collection resurrects the old versioned-store history under the new collection #158

Description

@mkhairi

Tested against: origin/main @ 09b8d9de (post-v0.3.0 main head, 2026-07-05)

Severity: High — a freshly created, never-written collection contains a previous collection's data: DROP does not delete bitemporal state, and the stale current row rematerializes in plain reads.

Summary

Dropping a BITEMPORAL collection and creating a new one under the same name resurrects the old collection's versioned store wholesale: the brand-new, never-inserted collection immediately serves the dropped collection's last current row on plain SELECT, and its full version history on AS OF SYSTEM TIME NULL. The name stays poisoned — there is no statement that clears the old versioned store short of wiping the data directory.

Repro

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

CREATE COLLECTION r28 (id TEXT PRIMARY KEY, v TEXT, BITEMPORAL) ENGINE = document_strict;
SELECT id, v FROM r28;
--  a | two                        <- never inserted into THIS collection
SELECT id, _ts_system, v FROM r28 AS OF SYSTEM TIME NULL;
--  a | 1783183426802 | one        <- dropped collection's full history
--  a | 1783183426809 | two

Expected

  1. DROP COLLECTION deletes (or tombstones) the collection's versioned store along with its current-state data.
  2. A newly created collection starts empty — plain reads and AS OF SYSTEM TIME NULL both return zero rows until the first write.

Files (best-guess)

  • collection-drop path — current-state store removed, bitemporal versioned store keyed by collection name left intact
  • bitemporal read path — binds to the versioned store by name, happily re-adopting a predecessor's history

Operational context

Rebuilding a collection (schema change, test churn, bad deploy rollback) is routine; here it silently imports a ghost audit trail and a stale live row into what the user believes is a clean collection. For the engine whose purpose is trustworthy history, resurrected history is the worst failure mode.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions