Extract methods for populating indices/views from schema

This commit is contained in:
Jussi Saurio
2025-09-11 09:51:46 +03:00
parent 07944e23b5
commit f17997fc5d
2 changed files with 25 additions and 83 deletions

View File

@@ -362,6 +362,21 @@ impl Schema {
pager.end_read_tx()?;
self.populate_indices(from_sql_indexes, automatic_indices)?;
self.populate_materialized_views(materialized_view_info, dbsp_state_roots)?;
Ok(())
}
/// Populate indices parsed from the schema.
/// from_sql_indexes: indices explicitly created with CREATE INDEX
/// automatic_indices: indices created automatically for primary key and unique constraints
pub fn populate_indices(
&mut self,
from_sql_indexes: Vec<UnparsedFromSqlIndex>,
automatic_indices: std::collections::HashMap<String, Vec<(String, usize)>>,
) -> Result<()> {
for unparsed_sql_from_index in from_sql_indexes {
if !self.indexes_enabled() {
self.table_set_has_index(&unparsed_sql_from_index.table_name);
@@ -392,8 +407,15 @@ impl Schema {
}
}
}
Ok(())
}
// Third pass: Create materialized views now that we have both root pages
/// Populate materialized views parsed from the schema.
pub fn populate_materialized_views(
&mut self,
materialized_view_info: std::collections::HashMap<String, (String, usize)>,
dbsp_state_roots: std::collections::HashMap<String, usize>,
) -> Result<()> {
for (view_name, (sql, main_root)) in materialized_view_info {
// Look up the DBSP state root for this view - must exist for materialized views
let dbsp_state_root = dbsp_state_roots.get(&view_name).ok_or_else(|| {
@@ -425,7 +447,6 @@ impl Schema {
self.add_materialized_view_dependency(&table_name, &view_name);
}
}
Ok(())
}

View File

@@ -196,88 +196,9 @@ pub fn parse_schema_rows(
StepResult::Busy => break,
}
}
for unparsed_sql_from_index in from_sql_indexes {
if !schema.indexes_enabled() {
schema.table_set_has_index(&unparsed_sql_from_index.table_name);
} else {
let table = schema
.get_btree_table(&unparsed_sql_from_index.table_name)
.unwrap();
let index = schema::Index::from_sql(
&unparsed_sql_from_index.sql,
unparsed_sql_from_index.root_page,
table.as_ref(),
)?;
schema.add_index(Arc::new(index));
}
}
for automatic_index in automatic_indices {
if !schema.indexes_enabled() {
schema.table_set_has_index(&automatic_index.0);
} else {
let table = schema.get_btree_table(&automatic_index.0).unwrap();
let ret_index = schema::Index::automatic_from_primary_key_and_unique(
table.as_ref(),
automatic_index.1,
)?;
for index in ret_index {
schema.add_index(Arc::new(index));
}
}
}
// Third pass: Create materialized views now that we have both root pages
for (view_name, (sql, main_root)) in materialized_view_info {
// Look up the DBSP state root for this view - must exist for materialized views
let dbsp_state_root = dbsp_state_roots.get(&view_name).ok_or_else(|| {
LimboError::InternalError(format!(
"Materialized view {view_name} is missing its DBSP state table"
))
})?;
// Check if we can reuse the existing view
let mut reuse_view = false;
if let Some(existing_view_mutex) = schema.get_materialized_view(&view_name) {
let existing_view = existing_view_mutex.lock().unwrap();
if let Some(existing_sql) = schema.materialized_view_sql.get(&view_name) {
if existing_sql == &sql {
reuse_view = true;
}
}
}
if reuse_view {
// View already exists with same SQL, just update dependencies
let existing_view_mutex = schema.get_materialized_view(&view_name).unwrap();
let existing_view = existing_view_mutex.lock().unwrap();
let referenced_tables = existing_view.get_referenced_table_names();
drop(existing_view); // Release lock before modifying schema
for table_name in referenced_tables {
schema.add_materialized_view_dependency(&table_name, &view_name);
}
} else {
// Create new IncrementalView with both root pages
let incremental_view =
IncrementalView::from_sql(&sql, schema, main_root, *dbsp_state_root)?;
let referenced_tables = incremental_view.get_referenced_table_names();
// Create a Table for the materialized view
let table = Arc::new(schema::Table::BTree(Arc::new(schema::BTreeTable {
root_page: main_root,
name: view_name.clone(),
columns: incremental_view.columns.clone(), // Use the view's columns, not the base table's
primary_key_columns: vec![],
has_rowid: true,
is_strict: false,
unique_sets: None,
})));
schema.add_materialized_view(incremental_view, table, sql.clone());
for table_name in referenced_tables {
schema.add_materialized_view_dependency(&table_name, &view_name);
}
}
}
schema.populate_indices(from_sql_indexes, automatic_indices)?;
schema.populate_materialized_views(materialized_view_info, dbsp_state_roots)?;
Ok(())
}