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::{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    /// Override the table name. Default is a no-op for backends that
17    /// don't honor it; the REST API driver overrides it to swap a
18    /// canonical endpoint for a per-reference URI template at
19    /// traversal time.
20    fn set_table_name(&mut self, _name: String) {}
21
22    /// Name of the column flagged as the id field, if any.
23    fn id_field_name(&self) -> Option<String> {
24        None
25    }
26
27    /// Names of columns flagged as `TitleField`.
28    fn title_field_names(&self) -> Vec<String> {
29        Vec::new()
30    }
31
32    /// Map of column name -> original Rust type name. Backends that
33    /// preserve type metadata (e.g. `Column::get_type()`) override this
34    /// so generic UIs can drive type-aware rendering without poking at
35    /// concrete column types.
36    fn column_types(&self) -> IndexMap<String, &'static str> {
37        IndexMap::new()
38    }
39
40    /// Names of relations traversable via `get_ref`.
41    fn get_ref_names(&self) -> Vec<String> {
42        Vec::new()
43    }
44
45    /// Add a condition to this table using a type-erased expression
46    /// The expression must be of type T::Expr for the underlying table's TableSource
47    fn add_condition(&mut self, condition: Box<dyn std::any::Any + Send + Sync>) -> Result<()>;
48
49    /// Add a permanent equality condition expressed as raw strings.
50    ///
51    /// Generic CLIs (and other type-erased callers) work with
52    /// `field=value` text and cannot reach into `T::Condition`. Each
53    /// backend that supports textual eq filtering overrides this; the
54    /// default returns an error.
55    fn add_condition_eq(&mut self, field: &str, value: &str) -> Result<()> {
56        let _ = (field, value);
57        Err(vantage_core::error!(
58            "add_condition_eq not supported on this TableLike"
59        ))
60    }
61
62    /// Add a temporary condition using AnyExpression that can be removed later
63    fn temp_add_condition(&mut self, condition: AnyExpression) -> Result<ConditionHandle>;
64
65    /// Remove a temporary condition by its handle
66    fn temp_remove_condition(&mut self, handle: ConditionHandle) -> Result<()>;
67
68    /// Create a search expression for this table
69    fn search_expression(&self, search_value: &str) -> Result<AnyExpression>;
70
71    /// Clone into a Box for object-safe cloning
72    fn clone_box(&self) -> Box<dyn TableLike<Value = Self::Value, Id = Self::Id>>;
73
74    /// Convert to Any for downcasting
75    fn into_any(self: Box<Self>) -> Box<dyn std::any::Any>;
76    fn as_any_ref(&self) -> &dyn std::any::Any;
77
78    /// Set pagination for this table
79    fn set_pagination(&mut self, pagination: Option<Pagination>);
80
81    /// Get pagination for this table
82    fn get_pagination(&self) -> Option<&Pagination>;
83
84    /// Get count of records in the table
85    async fn get_count(&self) -> Result<i64>;
86}