Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 103 additions & 2 deletions crates/dbflux_driver_mssql/src/driver.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::sync::LazyLock;
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -1850,10 +1850,15 @@ impl Connection for MssqlConnection {
total_start.elapsed().as_secs_f64() * 1000.0
);

let schemas = match &current_database {
Some(db) => self.fetch_db_schemas(db).unwrap_or_default(),
None => Vec::new(),
};

Ok(SchemaSnapshot::relational(RelationalSchema {
databases,
current_database,
schemas: Vec::new(),
schemas,
tables: Vec::new(),
views: Vec::new(),
}))
Expand Down Expand Up @@ -3085,6 +3090,102 @@ impl MssqlConnection {

Ok(builder.build_sorted())
}

fn fetch_db_schemas(&self, database: &str) -> Result<Vec<DbSchemaInfo>, DbError> {
let escaped_db = database.replace(']', "]]");
let qualified = format!("[{}]", escaped_db);

let tables_sql = format!(
"SELECT s.name AS schema_name, t.name AS table_name \
FROM {qualified}.sys.tables t \
JOIN {qualified}.sys.schemas s ON s.schema_id = t.schema_id \
WHERE t.is_ms_shipped = 0 \
ORDER BY s.name, t.name",
qualified = qualified
);

let table_rows = self.execute_simple(&tables_sql)?;
let mut schema_tables: BTreeMap<String, Vec<TableInfo>> = BTreeMap::new();

for row in table_rows.rows {
let mut iter = row.into_iter();
let schema_name = match iter.next() {
Some(Value::Text(s)) => s,
_ => continue,
};
let table_name = match iter.next() {
Some(Value::Text(s)) => s,
_ => continue,
};

schema_tables
.entry(schema_name.clone())
.or_default()
.push(TableInfo {
name: table_name,
schema: Some(schema_name),
columns: None,
indexes: None,
foreign_keys: None,
constraints: None,
sample_fields: None,
presentation: dbflux_core::CollectionPresentation::DataGrid,
child_items: None,
});
}

let views_sql = format!(
"SELECT s.name AS schema_name, v.name AS view_name \
FROM {qualified}.sys.views v \
JOIN {qualified}.sys.schemas s ON s.schema_id = v.schema_id \
WHERE v.is_ms_shipped = 0 \
ORDER BY s.name, v.name",
qualified = qualified
);

let view_rows = self.execute_simple(&views_sql)?;
let mut schema_views: BTreeMap<String, Vec<ViewInfo>> = BTreeMap::new();

for row in view_rows.rows {
let mut iter = row.into_iter();
let schema_name = match iter.next() {
Some(Value::Text(s)) => s,
_ => continue,
};
let view_name = match iter.next() {
Some(Value::Text(s)) => s,
_ => continue,
};

schema_views
.entry(schema_name.clone())
.or_default()
.push(ViewInfo {
name: view_name,
schema: Some(schema_name),
});
}

let mut all_schema_names: BTreeSet<String> = BTreeSet::new();
all_schema_names.extend(schema_tables.keys().cloned());
all_schema_names.extend(schema_views.keys().cloned());

let schemas: Vec<DbSchemaInfo> = all_schema_names
.into_iter()
.map(|name| {
let tables = schema_tables.remove(&name).unwrap_or_default();
let views = schema_views.remove(&name).unwrap_or_default();
DbSchemaInfo {
name,
tables,
views,
custom_types: None,
}
})
.collect();

Ok(schemas)
}
}

// Local indexmap usage so we don't depend on dbflux_core's indexmap re-export.
Expand Down
14 changes: 14 additions & 0 deletions crates/dbflux_ui_sidebar/src/tree_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,20 @@ fn resolve_db_children(
// Route through the time-series builder the same way document
// databases route through build_document_db_content.
Sidebar::build_time_series_db_content(profile_id, db_name, schema)
} else if !schema.schemas().is_empty() {
Sidebar::build_schema_children(
profile_id,
db_name,
Some(db_name),
schema,
&connected.table_details,
&connected.schema_types,
&connected.schema_indexes,
&connected.schema_foreign_keys,
&connected.schema_routines,
supports_routines,
&connected.dependents_cache,
)
} else {
Sidebar::build_db_schema_content(
profile_id,
Expand Down
Loading