pub struct FactTableDetector;Expand description
Detects and introspects fact tables
Implementations§
Source§impl FactTableDetector
impl FactTableDetector
Sourcepub fn is_fact_table(table_name: &str) -> bool
pub fn is_fact_table(table_name: &str) -> bool
Detect if a table name follows the fact table pattern.
Fact tables must follow the naming convention: tf_<table_name>
where the table name contains only lowercase letters, numbers, and underscores.
§Arguments
table_name- Table name to check
§Returns
true if the table name starts with tf_ and follows naming conventions,
false otherwise.
§Notes
- The check is strict:
tf_is required as a prefix - Table names like
TF_sales(uppercase prefix) are NOT recognized as fact tables - Empty strings and tables named just
tf_without additional suffix are not valid
§Examples
use fraiseql_core::compiler::fact_table::FactTableDetector;
assert!(FactTableDetector::is_fact_table("tf_sales"));
assert!(FactTableDetector::is_fact_table("tf_events"));
assert!(FactTableDetector::is_fact_table("tf_page_views_daily"));
assert!(!FactTableDetector::is_fact_table("ta_sales_by_day"));
assert!(!FactTableDetector::is_fact_table("v_user"));
assert!(!FactTableDetector::is_fact_table("TF_sales")); // uppercase prefix not recognized
assert!(!FactTableDetector::is_fact_table("tf_")); // incomplete nameSourcepub async fn introspect(
introspector: &impl DatabaseIntrospector,
table_name: &str,
) -> Result<FactTableMetadata>
pub async fn introspect( introspector: &impl DatabaseIntrospector, table_name: &str, ) -> Result<FactTableMetadata>
Introspect a fact table from the database
Queries the database schema to extract:
- Measures (numeric columns)
- Dimensions (JSONB/JSON columns)
- Denormalized filters (indexed columns)
§Arguments
introspector- Database introspection implementationtable_name- Fact table name (must start with “tf_”)
§Errors
Returns error if:
- Table is not a fact table (doesn’t start with “tf_”)
- Database query fails
- Table structure is invalid
§Example
use fraiseql_core::compiler::fact_table::{FactTableDetector, DatabaseIntrospector};
let metadata = FactTableDetector::introspect(&db, "tf_sales").await?;
println!("Found {} measures", metadata.measures.len());Sourcepub fn validate(metadata: &FactTableMetadata) -> Result<()>
pub fn validate(metadata: &FactTableMetadata) -> Result<()>
Validate fact table structure
§Errors
Returns error if:
- No measures found
- No dimension column found
- Measures are not numeric types
Sourcepub fn extract_dimension_paths(
sample: &Value,
column_name: &str,
db_type: DatabaseType,
) -> Vec<DimensionPath>
pub fn extract_dimension_paths( sample: &Value, column_name: &str, db_type: DatabaseType, ) -> Vec<DimensionPath>
Extract dimension paths from a sample JSON value
Walks through the JSON structure and extracts top-level keys as dimension paths. Nested objects are represented with dot notation (e.g., “customer.region”).
§Arguments
sample- Sample JSON value from the dimension columncolumn_name- Name of the JSONB column (e.g., “dimensions”)db_type- Database type for generating correct JSON path syntax
§Returns
Vec of DimensionPath extracted from the sample data
Sourcepub fn from_columns(
table_name: String,
columns: Vec<(&str, SqlType, bool)>,
) -> Result<FactTableMetadata>
pub fn from_columns( table_name: String, columns: Vec<(&str, SqlType, bool)>, ) -> Result<FactTableMetadata>
Create metadata from column definitions (for testing)
§Errors
Returns FraiseQLError::Validation if no time dimension column is found.
Auto Trait Implementations§
impl Freeze for FactTableDetector
impl RefUnwindSafe for FactTableDetector
impl Send for FactTableDetector
impl Sync for FactTableDetector
impl Unpin for FactTableDetector
impl UnsafeUnpin for FactTableDetector
impl UnwindSafe for FactTableDetector
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more