reifydb_engine/table_virtual/
user.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4//! User-facing API for defining virtual tables.
5//!
6//! This module provides simplified traits for users to implement custom virtual tables.
7//! Users can choose between two levels of abstraction:
8//!
9//! - [`TableVirtualUser`]: Simple API for tables that can return all rows at once
10//! - [`TableVirtualUserIterator`]: Advanced API for streaming large datasets with optional pushdown
11//!
12//! # Example
13//!
14//! ```ignore
15//! use reifydb_engine::table_virtual::{TableVirtualUser, TableVirtualUserColumnDef};
16//! use reifydb_type::Type;
17//! use reifydb_core::value::Value;
18//!
19//! struct MyApiTable {
20//!     api_client: ApiClient,
21//! }
22//!
23//! impl TableVirtualUser for MyApiTable {
24//!     fn columns(&self) -> Vec<TableVirtualUserColumnDef> {
25//!         vec![
26//!             TableVirtualUserColumnDef::new("id", Type::Uint8),
27//!             TableVirtualUserColumnDef::new("name", Type::Utf8),
28//!         ]
29//!     }
30//!
31//!     fn rows(&self) -> Vec<Vec<Value>> {
32//!         self.api_client.fetch_data()
33//!             .map(|r| vec![Value::Uint8(r.id), Value::Utf8(r.name.into())])
34//!             .collect()
35//!     }
36//! }
37//! ```
38
39use async_trait::async_trait;
40use reifydb_type::{Type, Value};
41
42/// Column definition for user virtual tables.
43#[derive(Debug, Clone)]
44pub struct TableVirtualUserColumnDef {
45	/// Column name
46	pub name: String,
47	/// Column data type
48	pub data_type: Type,
49	/// Whether the column allows null values
50	pub nullable: bool,
51}
52
53impl TableVirtualUserColumnDef {
54	/// Create a new non-nullable column definition.
55	pub fn new(name: impl Into<String>, data_type: Type) -> Self {
56		Self {
57			name: name.into(),
58			data_type,
59			nullable: false,
60		}
61	}
62
63	/// Create a new nullable column definition.
64	pub fn nullable(name: impl Into<String>, data_type: Type) -> Self {
65		Self {
66			name: name.into(),
67			data_type,
68			nullable: true,
69		}
70	}
71}
72
73/// Simple trait for user-defined virtual tables.
74///
75/// Implement this trait when your virtual table can return all rows at once.
76/// For large datasets that should be streamed, implement [`TableVirtualUserIterator`] instead.
77///
78/// # Thread Safety
79///
80/// Implementations must be thread-safe (`Send + Sync`) as the same table instance
81/// may be queried concurrently from multiple transactions.
82pub trait TableVirtualUser: Send + Sync + 'static {
83	/// Return the column definitions for this table.
84	fn columns(&self) -> Vec<TableVirtualUserColumnDef>;
85
86	/// Generate all rows for the table.
87	///
88	/// Each inner `Vec<Value>` represents one row, with values in the same order
89	/// as the columns returned by [`columns()`](Self::columns).
90	fn rows(&self) -> Vec<Vec<Value>>;
91}
92
93/// Pushdown context for advanced virtual table implementations.
94///
95/// Contains optimization hints that can be used to reduce the amount of data
96/// generated by the virtual table.
97#[derive(Debug, Clone, Default)]
98pub struct TableVirtualUserPushdownContext {
99	/// Maximum number of rows to return (if set).
100	pub limit: Option<usize>,
101	// Future: filters, projections, etc.
102}
103
104/// Advanced trait for streaming virtual table implementations.
105///
106/// Implement this trait when your virtual table needs to:
107/// - Stream large datasets in batches
108/// - Take advantage of pushdown optimizations (limit, filters)
109///
110/// # Thread Safety
111///
112/// Unlike [`TableVirtualUser`], implementations of this trait are instantiated
113/// fresh for each query. The factory creates a new instance per query execution.
114#[async_trait]
115pub trait TableVirtualUserIterator: Send + Sync + 'static {
116	/// Return the column definitions for this table.
117	fn columns(&self) -> Vec<TableVirtualUserColumnDef>;
118
119	/// Initialize the iterator with optional pushdown context.
120	///
121	/// Called once before iteration begins. Use the pushdown context to
122	/// optimize data generation (e.g., limit the number of rows fetched).
123	async fn initialize(&mut self, ctx: Option<&TableVirtualUserPushdownContext>) -> crate::Result<()>;
124
125	/// Get the next batch of rows.
126	///
127	/// Returns `Ok(Some(rows))` with the next batch, or `Ok(None)` when exhausted.
128	/// Each inner `Vec<Value>` represents one row.
129	///
130	/// The `batch_size` parameter is a hint for how many rows to return.
131	async fn next_batch(&mut self, batch_size: usize) -> crate::Result<Option<Vec<Vec<Value>>>>;
132}