AS OF Quick Reference Guide
AS OF Quick Reference Guide
Usage Examples
Basic Time-Travel Queries
use heliosdb_nano::sql::{LogicalPlan, AsOfClause};use std::sync::Arc;
// AS OF TIMESTAMPlet plan = LogicalPlan::Scan { table_name: "orders".to_string(), schema: Arc::new(schema), projection: None, as_of: Some(AsOfClause::Timestamp("2025-11-19 12:00:00".to_string())),};
// AS OF TRANSACTIONlet plan = LogicalPlan::Scan { table_name: "orders".to_string(), schema: Arc::new(schema), projection: None, as_of: Some(AsOfClause::Transaction(12345)),};
// AS OF SCNlet plan = LogicalPlan::Scan { table_name: "orders".to_string(), schema: Arc::new(schema), projection: None, as_of: Some(AsOfClause::Scn(67890)),};
// AS OF NOWlet plan = LogicalPlan::Scan { table_name: "orders".to_string(), schema: Arc::new(schema), projection: None, as_of: Some(AsOfClause::Now),};
// Executelet mut executor = Executor::with_storage(&engine);let results = executor.execute(&plan)?;SQL Syntax (Future Parser Integration)
-- Timestamp-basedSELECT * FROM orders AS OF TIMESTAMP '2025-11-19 12:00:00';
-- Transaction-basedSELECT * FROM orders AS OF TRANSACTION 12345;
-- SCN-basedSELECT * FROM orders AS OF SCN 67890;
-- Current timeSELECT * FROM orders AS OF NOW;AsOfClause Definition
pub enum AsOfClause { /// AS OF NOW - current time Now, /// AS OF TIMESTAMP '2025-11-15 06:00:00' Timestamp(String), /// AS OF TRANSACTION 987654 Transaction(u64), /// AS OF SCN 123456789 (System Change Number) Scn(u64),}Resolution Flow
AsOfClause ↓SnapshotManager::resolve_as_of() ↓ ├─ Timestamp → resolve_timestamp() → u64 (snapshot_ts) ├─ Transaction → resolve_transaction() → u64 (snapshot_ts) └─ Scn → resolve_scn() → u64 (snapshot_ts) ↓StorageEngine::scan_table_at_snapshot(table_name, snapshot_ts) ↓Vec<Tuple> (historical data)Error Handling
// Invalid timestamp formatAsOfClause::Timestamp("invalid")// → Error: "Invalid timestamp format: ..."
// Non-existent transactionAsOfClause::Transaction(99999)// → Error: "Transaction 99999 not found or has been garbage collected"
// Non-existent SCNAsOfClause::Scn(99999)// → Error: "SCN 99999 not found or has been garbage collected"
// No snapshot at timestampAsOfClause::Timestamp("1970-01-01 00:00:00")// → Error: "No snapshot found for timestamp '1970-01-01 00:00:00'"Timestamp Formats Supported
// PostgreSQL format"2025-11-19 12:00:00"
// ISO 8601 format"2025-11-19T12:00:00"Complex Query Examples
With Filter
let scan_plan = LogicalPlan::Scan { table_name: "orders".to_string(), schema: Arc::new(schema), projection: None, as_of: Some(AsOfClause::Transaction(100)),};
let filter_plan = LogicalPlan::Filter { input: Box::new(scan_plan), predicate: LogicalExpr::BinaryExpr { left: Box::new(LogicalExpr::Column { name: "customer".to_string() }), op: BinaryOperator::Eq, right: Box::new(LogicalExpr::Literal(Value::String("Alice".to_string()))), },};With Join
let orders_scan = LogicalPlan::Scan { table_name: "orders".to_string(), schema: Arc::new(orders_schema), projection: None, as_of: Some(AsOfClause::Scn(5000)),};
let customers_scan = LogicalPlan::Scan { table_name: "customers".to_string(), schema: Arc::new(customers_schema), projection: None, as_of: Some(AsOfClause::Scn(5000)), // Same snapshot for consistency};
let join_plan = LogicalPlan::Join { left: Box::new(orders_scan), right: Box::new(customers_scan), join_type: JoinType::Inner, on: Some(join_condition),};Getting Snapshot Information
// Get snapshot managerlet snapshot_mgr = engine.snapshot_manager();
// Get snapshot by timestamplet metadata = snapshot_mgr.get_snapshot_metadata(timestamp_value)?;println!("Transaction ID: {}", metadata.transaction_id);println!("SCN: {}", metadata.scn);println!("Wall clock time: {}", metadata.wall_clock_time);
// Get current SCNlet current_scn = snapshot_mgr.current_scn();
// Get current transaction IDlet current_txn = snapshot_mgr.current_transaction_id();
// Get snapshot countlet count = snapshot_mgr.snapshot_count();Creating Versioned Data
// Insert with automatic versioninglet row_id = engine.insert_tuple_versioned("orders", tuple)?;// This automatically:// 1. Creates a new snapshot// 2. Assigns transaction ID and SCN// 3. Stores versioned copy for time-travelPerformance Tips
- Use SCN or Transaction ID when possible - Faster than timestamp parsing
- Coordinate AS OF across tables in JOINs - Ensures consistent snapshot view
- Normal queries have zero overhead - Don’t use AS OF if not needed
- Monitor snapshot count - Large retention can increase memory usage
- Use AS OF NOW for explicit current-time semantics
Debugging
Enable tracing to see AS OF resolution:
tracing::subscriber::set_global_default( tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .finish()).unwrap();Output:
DEBUG Time-travel query on table 'orders' with AS OF clause: Transaction(12345)DEBUG Resolved AS OF clause to snapshot timestamp 100 for table 'orders'DEBUG Time-travel scan returned 42 tuples from table 'orders' at snapshot 100Testing
# Run all AS OF testscargo test test_executor_as_of -- --nocapture
# Run specific AS OF testcargo test test_executor_as_of_timestamp -- --nocapture
# Run integration testscargo test --test time_travel_integration_tests -- --nocaptureCommon Pitfalls
- Different snapshots in JOIN - Use same AS OF for all tables
- Garbage collected snapshots - Old snapshots may be removed
- Timestamp precision - Only second-level granularity
- Memory usage - Large retention policies increase memory
API Reference
Executor Methods
impl Executor { // Execute plan with AS OF support pub fn execute(&mut self, plan: &LogicalPlan) -> Result<Vec<Tuple>>;}SnapshotManager Methods
impl SnapshotManager { // Resolve AS OF clause to snapshot timestamp pub fn resolve_as_of(&self, as_of: &AsOfClause) -> Result<u64>;
// Get snapshot metadata pub fn get_snapshot_metadata(&self, timestamp: u64) -> Option<SnapshotMetadata>;
// Get current SCN pub fn current_scn(&self) -> Scn;
// Get current transaction ID pub fn current_transaction_id(&self) -> TransactionId;
// Get snapshot count pub fn snapshot_count(&self) -> usize;}StorageEngine Methods
impl StorageEngine { // Get snapshot manager pub fn snapshot_manager(&self) -> &SnapshotManager;
// Scan table at historical snapshot pub fn scan_table_at_snapshot(&self, table_name: &str, snapshot_ts: u64) -> Result<Vec<Tuple>>;
// Insert versioned tuple pub fn insert_tuple_versioned(&self, table_name: &str, tuple: Tuple) -> Result<u64>;}Quick Links:
- Full Implementation: AS_OF_EXECUTOR_IMPLEMENTATION.md
- Time-Travel Guide: TIME_TRAVEL_QUICK_REFERENCE.md
- Architecture: docs/architecture/TIME_TRAVEL_ARCHITECTURE.md