Skip to main content

vantage_table/traits/
table_like.rs

1use async_trait::async_trait;
2use indexmap::IndexMap;
3use vantage_core::Result;
4use vantage_dataset::prelude::{ReadableValueSet, WritableValueSet};
5use vantage_expressions::AnyExpression;
6
7use crate::{any::AnyTable, conditions::ConditionHandle, pagination::Pagination};
8
9/// Dyn-safe trait for table operations.
10#[async_trait]
11pub trait TableLike: ReadableValueSet + WritableValueSet + Send + Sync {
12    fn table_name(&self) -> &str;
13    fn table_alias(&self) -> &str;
14    fn column_names(&self) -> Vec<String>;
15
16    /// Name of the column flagged as the id field, if any.
17    fn id_field_name(&self) -> Option<String> {
18        None
19    }
20
21    /// Names of columns flagged as `TitleField`.
22    fn title_field_names(&self) -> Vec<String> {
23        Vec::new()
24    }
25
26    /// Map of column name -> original Rust type name. Backends that
27    /// preserve type metadata (e.g. `Column::get_type()`) override this
28    /// so generic UIs can drive type-aware rendering without poking at
29    /// concrete column types.
30    fn column_types(&self) -> IndexMap<String, &'static str> {
31        IndexMap::new()
32    }
33
34    /// Names of relations traversable via [`get_ref`].
35    fn get_ref_names(&self) -> Vec<String> {
36        Vec::new()
37    }
38
39    /// Add a condition to this table using a type-erased expression
40    /// The expression must be of type T::Expr for the underlying table's TableSource
41    fn add_condition(&mut self, condition: Box<dyn std::any::Any + Send + Sync>) -> Result<()>;
42
43    /// Add a permanent equality condition expressed as raw strings.
44    ///
45    /// Generic CLIs (and other type-erased callers) work with
46    /// `field=value` text and cannot reach into `T::Condition`. Each
47    /// backend that supports textual eq filtering overrides this; the
48    /// default returns an error.
49    fn add_condition_eq(&mut self, field: &str, value: &str) -> Result<()> {
50        let _ = (field, value);
51        Err(vantage_core::error!(
52            "add_condition_eq not supported on this TableLike"
53        ))
54    }
55
56    /// Add a temporary condition using AnyExpression that can be removed later
57    fn temp_add_condition(&mut self, condition: AnyExpression) -> Result<ConditionHandle>;
58
59    /// Remove a temporary condition by its handle
60    fn temp_remove_condition(&mut self, handle: ConditionHandle) -> Result<()>;
61
62    /// Create a search expression for this table
63    fn search_expression(&self, search_value: &str) -> Result<AnyExpression>;
64
65    /// Clone into a Box for object-safe cloning
66    fn clone_box(&self) -> Box<dyn TableLike<Value = Self::Value, Id = Self::Id>>;
67
68    /// Convert to Any for downcasting
69    fn into_any(self: Box<Self>) -> Box<dyn std::any::Any>;
70    fn as_any_ref(&self) -> &dyn std::any::Any;
71
72    /// Set pagination for this table
73    fn set_pagination(&mut self, pagination: Option<Pagination>);
74
75    /// Get pagination for this table
76    fn get_pagination(&self) -> Option<&Pagination>;
77
78    /// Get count of records in the table
79    async fn get_count(&self) -> Result<i64>;
80
81    /// Traverse a named reference and return the related table as `AnyTable`.
82    ///
83    /// Default impl returns an error so wrappers without ref support compile
84    /// unchanged. `Table<T, E>` overrides this to delegate to its inherent
85    /// `get_ref`; `AnyTable`, `CborAdapter` and `LiveTable` override to forward
86    /// through to the underlying table that holds the refs.
87    fn get_ref(&self, _relation: &str) -> Result<AnyTable> {
88        Err(vantage_core::error!(
89            "get_ref not supported on this TableLike"
90        ))
91    }
92}