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}