टाइम ट्रैवल क्वेरी
PyroSQL maintains a complete history of every row that has ever existed in the database. Time travel queries let you read data as it appeared at any previous point in time by appending an AS OF clause to the FROM clause of a SELECT statement. This is useful for audit log replay, point-in-time recovery, compliance reports, and debugging data mutations.
How it works
A time travel query replaces the normal FROM table alias clause with:
FROM orders e AS OF TIMESTAMP '2024-01-01 12:00:00'
-- or
FROM orders e AS OF LSN 12345
PyroSQL intercepts the AS OF modifier and reads row versions from its WAL-backed history store instead of the current live data. The rest of the query — WHERE, ORDER BY, LIMIT, joins, aggregates — works identically to a normal query.
TimeTravelQueryBuilder
TimeTravelQueryBuilder is a decorator around EntityQueryBuilder that injects the AS OF clause at execution time. All standard query-builder methods (where, orderBy, limit, etc.) are proxied to the inner builder unchanged.
Getting a builder from a repository
The easiest way to obtain a TimeTravelQueryBuilder is through PyroQueryBuilderExtension::queryAsOf(). This creates a builder already scoped to the given timestamp:
use App\Repository\OrderRepository;
$orders = $orderRepo->queryAsOf(new \DateTimeImmutable('2024-01-01 12:00:00'))
->where('status', 'active')
->orderBy('created_at', 'DESC')
->get();
You can also construct TimeTravelQueryBuilder directly if you need more control:
use Weaver\ORM\PyroSQL\Query\TimeTravelQueryBuilder;
use Weaver\ORM\Query\EntityQueryBuilder;
$inner = new EntityQueryBuilder(/* ... */);
$ttqb = new TimeTravelQueryBuilder($inner, 'orders');
->asOf(DateTimeImmutable $timestamp)
Query data as it existed at a specific wall-clock time.
$snapshot = $orderRepo
->queryAsOf(new \DateTimeImmutable('2024-06-15 09:00:00'))
->where('customer_id', 42)
->get();
Generates:
SELECT e.* FROM orders e AS OF TIMESTAMP '2024-06-15 09:00:00'
WHERE e.customer_id = 42
->asOfVersion(int $lsn)
Query data as it existed at a specific WAL Log Sequence Number (LSN). LSNs are monotonically increasing integers that identify exact positions in the replication log. Use this when you need sub-second precision or when you captured the LSN at the time of a specific transaction.
$snapshot = $orderRepo
->queryAsOf(new \DateTimeImmutable('now')) // start fresh
->asOfVersion(98765432)
->where('status', 'pending')
->get();
Generates:
SELECT e.* FROM orders e AS OF LSN 98765432
WHERE e.status = 'pending'
->current()
Remove any AS OF clause and return to querying live data. Useful when you have a shared builder instance and want to reset it:
$ttqb = $orderRepo->queryAsOf(new \DateTimeImmutable('2023-01-01'));
// Query historical data
$historical = $ttqb->where('status', 'shipped')->get();
// Reset to live data
$live = $ttqb->current()->where('status', 'pending')->get();