From 22b8ba17bb997871338ca256332d2afb067fe726 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 17 Jun 2026 19:28:53 +0800 Subject: [PATCH] fix(schema): handle view DDL object types --- .../src/components/objects/ObjectBrowser.vue | 2 +- .../src/components/sidebar/TreeItem.vue | 2 +- apps/desktop/src/lib/http.ts | 8 +- apps/desktop/src/lib/tauri.ts | 8 +- apps/desktop/src/stores/connectionStore.ts | 2 +- crates/dbx-core/src/agent_loop.rs | 1 + crates/dbx-core/src/agent_tools.rs | 1 + crates/dbx-core/src/connection.rs | 5 +- crates/dbx-core/src/database_export.rs | 2 + crates/dbx-core/src/schema.rs | 159 +++++++++++++++--- crates/dbx-core/src/transfer.rs | 2 + crates/dbx-web/src/routes/schema.rs | 12 +- src-tauri/src/commands/mcp_bridge.rs | 2 +- src-tauri/src/commands/schema.rs | 17 +- 14 files changed, 175 insertions(+), 48 deletions(-) diff --git a/apps/desktop/src/components/objects/ObjectBrowser.vue b/apps/desktop/src/components/objects/ObjectBrowser.vue index 554977eb0..819337014 100644 --- a/apps/desktop/src/components/objects/ObjectBrowser.vue +++ b/apps/desktop/src/components/objects/ObjectBrowser.vue @@ -728,7 +728,7 @@ async function confirmBatchDropTables() { async function exportStructure(row: ObjectBrowserRow) { try { const schema = row.schema || selectedSchema.value || props.database; - const ddl = await api.getTableDdl(props.connection.id, props.database, schema, row.name); + const ddl = await api.getTableDdl(props.connection.id, props.database, schema, row.name, row.type === "VIEW" ? "VIEW" : undefined); await saveFileContent(ddl + "\n", `${row.name}.sql`, "SQL", "sql"); } catch (e: any) { console.error("Export structure failed:", e); diff --git a/apps/desktop/src/components/sidebar/TreeItem.vue b/apps/desktop/src/components/sidebar/TreeItem.vue index 497bdb9cd..9fdb18f86 100644 --- a/apps/desktop/src/components/sidebar/TreeItem.vue +++ b/apps/desktop/src/components/sidebar/TreeItem.vue @@ -2096,7 +2096,7 @@ async function exportStructure() { const parts: string[] = []; for (const target of targets) { await connectionStore.ensureConnected(target.connectionId); - const ddl = await api.getTableDdl(target.connectionId, target.database, target.schema || target.database, target.label); + const ddl = await api.getTableDdl(target.connectionId, target.database, target.schema || target.database, target.label, target.type === "view" ? "VIEW" : undefined); parts.push(ddl.trim()); } structurePreviewSql.value = `${parts.filter(Boolean).join("\n\n")}\n`; diff --git a/apps/desktop/src/lib/http.ts b/apps/desktop/src/lib/http.ts index dc34e1400..1fe21a273 100644 --- a/apps/desktop/src/lib/http.ts +++ b/apps/desktop/src/lib/http.ts @@ -408,8 +408,8 @@ export async function listSchemas(connectionId: string, database: string): Promi return get(`/api/schema/schemas?${qs({ connection_id: connectionId, database })}`); } -export async function listTables(connectionId: string, database: string, schema: string, filter?: string, limit?: number, offset?: number): Promise { - return get(`/api/schema/tables?${qs({ connection_id: connectionId, database, schema, filter, limit, offset })}`); +export async function listTables(connectionId: string, database: string, schema: string, filter?: string, limit?: number, offset?: number, objectTypes?: SidebarObjectKind[]): Promise { + return get(`/api/schema/tables?${qs({ connection_id: connectionId, database, schema, filter, limit, offset, object_types: objectTypes?.join(",") })}`); } export async function listObjects(connectionId: string, database: string, schema: string, objectTypes?: SidebarObjectKind[]): Promise { @@ -447,8 +447,8 @@ export async function listTriggers(connectionId: string, database: string, schem return get(`/api/schema/triggers?${qs({ connection_id: connectionId, database, schema, table })}`); } -export async function getTableDdl(connectionId: string, database: string, schema: string, table: string): Promise { - return get(`/api/schema/ddl?${qs({ connection_id: connectionId, database, schema, table })}`); +export async function getTableDdl(connectionId: string, database: string, schema: string, table: string, objectType?: ObjectSourceKind): Promise { + return get(`/api/schema/ddl?${qs({ connection_id: connectionId, database, schema, table, object_type: objectType })}`); } export async function prepareSchemaDiff(options: SchemaDiffPreparationOptions): Promise { diff --git a/apps/desktop/src/lib/tauri.ts b/apps/desktop/src/lib/tauri.ts index a1d82cd15..62228798a 100644 --- a/apps/desktop/src/lib/tauri.ts +++ b/apps/desktop/src/lib/tauri.ts @@ -486,8 +486,8 @@ export async function deleteSchemaCachePrefix(prefix: string): Promise { return invoke("delete_schema_cache_prefix", { prefix }); } -export async function listTables(connectionId: string, database: string, schema: string, filter?: string, limit?: number, offset?: number): Promise { - return invoke("list_tables", { connectionId, database, schema, filter, limit, offset }); +export async function listTables(connectionId: string, database: string, schema: string, filter?: string, limit?: number, offset?: number, objectTypes?: SidebarObjectKind[]): Promise { + return invoke("list_tables", { connectionId, database, schema, filter, limit, offset, objectTypes }); } export async function listObjects(connectionId: string, database: string, schema: string, objectTypes?: SidebarObjectKind[]): Promise { @@ -787,8 +787,8 @@ export async function listTriggers(connectionId: string, database: string, schem return invoke("list_triggers", { connectionId, database, schema, table }); } -export async function getTableDdl(connectionId: string, database: string, schema: string, table: string): Promise { - return invoke("get_table_ddl", { connectionId, database, schema, table }); +export async function getTableDdl(connectionId: string, database: string, schema: string, table: string, objectType?: ObjectSourceKind): Promise { + return invoke("get_table_ddl", { connectionId, database, schema, table, objectType }); } export async function prepareSchemaDiff(options: SchemaDiffPreparationOptions): Promise { diff --git a/apps/desktop/src/stores/connectionStore.ts b/apps/desktop/src/stores/connectionStore.ts index 87e129468..f3a7f4a4b 100644 --- a/apps/desktop/src/stores/connectionStore.ts +++ b/apps/desktop/src/stores/connectionStore.ts @@ -466,7 +466,7 @@ export const useConnectionStore = defineStore("connection", () => { // When searching, fetch all matching tables (no pagination) — backend filter // already narrows the result set, so client-side filtering is not needed. const fetchLimit = searchFilter ? undefined : options.pageSize + 1; - const tables = await api.listTables(options.node.connectionId, options.node.database, options.querySchema, searchFilter, fetchLimit, searchFilter ? undefined : options.offset); + const tables = await api.listTables(options.node.connectionId, options.node.database, options.querySchema, searchFilter, fetchLimit, searchFilter ? undefined : options.offset, options.objectTypes); const hasMore = searchFilter ? false : tables.length > options.pageSize; const pageTables = hasMore ? tables.slice(0, options.pageSize) : tables; const objects = mergeTableInfosIntoObjects([], pageTables, options.effectiveSchema); diff --git a/crates/dbx-core/src/agent_loop.rs b/crates/dbx-core/src/agent_loop.rs index 6d6cfd6dc..57f9c16ab 100644 --- a/crates/dbx-core/src/agent_loop.rs +++ b/crates/dbx-core/src/agent_loop.rs @@ -370,6 +370,7 @@ async fn build_schema_prompt(agent_ctx: &AgentLoopContext, system_prompt: &str) None, Some(50), // smaller limit for prompt injection None, + None, ) .await; diff --git a/crates/dbx-core/src/agent_tools.rs b/crates/dbx-core/src/agent_tools.rs index 6e72462a7..fc9b289ab 100644 --- a/crates/dbx-core/src/agent_tools.rs +++ b/crates/dbx-core/src/agent_tools.rs @@ -241,6 +241,7 @@ async fn execute_list_tables( None, Some(LIST_TABLES_LIMIT + 1), None, + None, ) .await .map_err(|e| format!("Failed to list tables: {e}"))?; diff --git a/crates/dbx-core/src/connection.rs b/crates/dbx-core/src/connection.rs index fc1e6152b..8085edf01 100644 --- a/crates/dbx-core/src/connection.rs +++ b/crates/dbx-core/src/connection.rs @@ -2715,8 +2715,9 @@ mod tests { let schemas = schema::list_schemas_core(&state, "kwdb-live", &database).await.unwrap(); assert!(schemas.iter().any(|schema| schema == test_schema)); - let tables = - schema::list_tables_core(&state, "kwdb-live", &database, test_schema, None, None, None).await.unwrap(); + let tables = schema::list_tables_core(&state, "kwdb-live", &database, test_schema, None, None, None, None) + .await + .unwrap(); assert!(tables.iter().any(|table| table.name == "devices" && table.table_type == "BASE TABLE")); let columns = schema::get_columns_core(&state, "kwdb-live", &database, test_schema, "devices").await.unwrap(); let id_column = columns.iter().find(|column| column.name == "id").expect("id column should be listed"); diff --git a/crates/dbx-core/src/database_export.rs b/crates/dbx-core/src/database_export.rs index a0e3d704d..316b7cdf1 100644 --- a/crates/dbx-core/src/database_export.rs +++ b/crates/dbx-core/src/database_export.rs @@ -383,6 +383,7 @@ pub async fn export_database_sql_core( None, None, None, + None, ) .await?; let all_tables = filter_selected_table_infos(all_tables, &request.selected_tables); @@ -476,6 +477,7 @@ pub async fn export_database_sql_core( &request.database, &request.schema, table_name, + None, ) .await { diff --git a/crates/dbx-core/src/schema.rs b/crates/dbx-core/src/schema.rs index a3c771840..7c3314b86 100644 --- a/crates/dbx-core/src/schema.rs +++ b/crates/dbx-core/src/schema.rs @@ -423,9 +423,10 @@ pub async fn list_tables_core( filter: Option<&str>, limit: Option, offset: Option, + object_types: Option<&[String]>, ) -> Result, String> { retry_metadata_connection(state, connection_id, Some(database), || { - list_tables_once(state, connection_id, database, schema, filter, limit, offset) + list_tables_once(state, connection_id, database, schema, filter, limit, offset, object_types) }) .await } @@ -438,6 +439,7 @@ async fn list_tables_once( filter: Option<&str>, limit: Option, offset: Option, + object_types: Option<&[String]>, ) -> Result, String> { let pool_key = state.get_or_create_pool(connection_id, Some(database)).await?; #[cfg(feature = "duckdb-bundled")] @@ -456,7 +458,7 @@ async fn list_tables_once( }) .await .map_err(|e| e.to_string())? - .map(|tables| filter_table_infos(tables, filter, limit, offset)); + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)); } if let Some(PoolKind::ExternalDriver { config, session, .. }) = connections.get(&pool_key) { let config = config.clone(); @@ -468,26 +470,35 @@ async fn list_tables_once( serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }), ) .await - .map(|tables| filter_table_infos(tables, filter, limit, offset)); + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)); } #[cfg(feature = "duckdb-bundled")] if let Some(con) = extract_pool!(&connections, &pool_key, DuckDb) { drop(connections); let con = con.lock().map_err(|e| e.to_string())?; return duckdb_query_tables_in_database_with_attached(&con, database, schema, &duckdb_attached_names) - .map(|tables| filter_table_infos(tables, filter, limit, offset)); + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)); } if let Some(client) = extract_pool!(&connections, &pool_key, ClickHouse) { drop(connections); return db::clickhouse_driver::list_tables(&client, clickhouse_metadata_database(database, schema)) .await - .map(|tables| filter_table_infos(tables, filter, limit, offset)); + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)); } if let Some(client) = extract_pool!(&connections, &pool_key, InfluxDb) { drop(connections); return db::influxdb_driver::list_tables(&client, database) .await - .map(|tables| filter_table_infos(tables, filter, limit, offset)); + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)); + } + if object_types.is_some() { + if let Some(client) = extract_pool!(&connections, &pool_key, SqlServer) { + drop(connections); + let mut client = client.lock().await; + return db::sqlserver::list_tables(&mut client, schema, filter, None, None) + .await + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)); + } } try_sqlserver!(connections, &pool_key, list_tables, schema, filter, limit, offset); if let Some(client) = extract_pool!(&connections, &pool_key, Agent) { @@ -495,14 +506,22 @@ async fn list_tables_once( drop(connections); let mut client = client.lock().await; match client.list_tables::>(database, schema).await { - Ok(tables) if !tables.is_empty() => return Ok(filter_table_infos(tables, filter, limit, offset)), + Ok(tables) if !tables.is_empty() => { + return Ok(filter_table_infos(tables, filter, limit, offset, object_types)) + } Ok(tables) => { if let Some(config) = fallback_config.as_ref() { match native_postgres_metadata_pool(state, connection_id, database, config).await { Ok(Some(pool)) => { - return db::postgres::list_tables_filtered(&pool, schema, filter, limit, offset).await; + return if object_types.is_some() { + db::postgres::list_tables_filtered(&pool, schema, filter, None, None) + .await + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)) + } else { + db::postgres::list_tables_filtered(&pool, schema, filter, limit, offset).await + }; } - Ok(None) => return Ok(filter_table_infos(tables, filter, limit, offset)), + Ok(None) => return Ok(filter_table_infos(tables, filter, limit, offset, object_types)), Err(error) => { log::warn!( "[schema][agent:list_tables:fallback-failed] connection_id={} database={} schema={} error={}", @@ -514,20 +533,23 @@ async fn list_tables_once( } } } - return Ok(filter_table_infos(tables, filter, limit, offset)); + return Ok(filter_table_infos(tables, filter, limit, offset, object_types)); } Err(agent_error) => { if let Some(config) = fallback_config.as_ref() { if let Some(pool) = native_postgres_metadata_pool(state, connection_id, database, config).await? { - return db::postgres::list_tables_filtered(&pool, schema, filter, limit, offset) - .await - .map_err(|fallback_error| { - format!( - "{agent_error}\n\nNative PostgreSQL metadata fallback failed: {fallback_error}" - ) - }); + let result = if object_types.is_some() { + db::postgres::list_tables_filtered(&pool, schema, filter, None, None) + .await + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)) + } else { + db::postgres::list_tables_filtered(&pool, schema, filter, limit, offset).await + }; + return result.map_err(|fallback_error| { + format!("{agent_error}\n\nNative PostgreSQL metadata fallback failed: {fallback_error}") + }); } } return Err(agent_error); @@ -543,30 +565,40 @@ async fn list_tables_once( PoolKind::Mysql(p, _) if db_config.as_ref().is_some_and(is_doris_family_config) => { db::mysql::list_tables_show(p, database) .await - .map(|tables| filter_table_infos(tables, filter, limit, offset)) + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)) } PoolKind::Mysql(p, mode) => { dispatch_mysql!(p, mode, db::mysql::list_tables, db::ob_oracle::list_tables, schema) - .map(|tables| filter_table_infos(tables, filter, limit, offset)) + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)) } PoolKind::Postgres(p) if db_config.as_ref().is_some_and(is_questdb_config) => { - db::questdb::list_tables(p, schema).await.map(|tables| filter_table_infos(tables, filter, limit, offset)) + db::questdb::list_tables(p, schema) + .await + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)) } - PoolKind::Postgres(p) => db::postgres::list_tables_filtered(p, schema, filter, limit, offset).await, - PoolKind::Sqlite(p) => { - db::sqlite::list_tables(p, schema).await.map(|tables| filter_table_infos(tables, filter, limit, offset)) + PoolKind::Postgres(p) => { + if object_types.is_some() { + db::postgres::list_tables_filtered(p, schema, filter, None, None) + .await + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)) + } else { + db::postgres::list_tables_filtered(p, schema, filter, limit, offset).await + } } + PoolKind::Sqlite(p) => db::sqlite::list_tables(p, schema) + .await + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)), PoolKind::Rqlite(client) => db::rqlite_driver::list_tables(client, schema) .await - .map(|tables| filter_table_infos(tables, filter, limit, offset)), + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)), PoolKind::MongoDb(client) => db::mongo_driver::list_collections(client, database) .await .map(|names| collection_names_to_tables(names, "COLLECTION")) - .map(|tables| filter_table_infos(tables, filter, limit, offset)), + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)), PoolKind::Elasticsearch(client) => db::elasticsearch_driver::list_indices(client) .await .map(|names| collection_names_to_tables(names, "INDEX")) - .map(|tables| filter_table_infos(tables, filter, limit, offset)), + .map(|tables| filter_table_infos(tables, filter, limit, offset, object_types)), _ => Ok(vec![]), } } @@ -589,6 +621,7 @@ fn filter_table_infos( filter: Option<&str>, limit: Option, offset: Option, + object_types: Option<&[String]>, ) -> Vec { let filter = filter.unwrap_or("").to_lowercase(); let limit = limit.unwrap_or(usize::MAX); @@ -596,11 +629,40 @@ fn filter_table_infos( tables .into_iter() .filter(|table| filter.is_empty() || table.name.to_lowercase().contains(&filter)) + .filter(|table| table_info_matches_object_types(table, object_types)) .skip(offset) .take(limit) .collect() } +fn table_info_matches_object_types(table: &db::TableInfo, object_types: Option<&[String]>) -> bool { + let Some(object_types) = object_types else { + return true; + }; + if object_types.is_empty() { + return true; + } + let table_type = normalize_table_info_object_type(&table.table_type); + object_types.iter().any(|object_type| normalize_table_info_object_type(object_type) == table_type) +} + +fn normalize_table_info_object_type(value: &str) -> String { + let upper = value.to_ascii_uppercase().replace(' ', "_"); + if upper.contains("MATERIALIZED") && upper.contains("VIEW") { + return "MATERIALIZED_VIEW".to_string(); + } + if upper.contains("VIEW") { + return "VIEW".to_string(); + } + if upper.contains("COLLECTION") { + return "COLLECTION".to_string(); + } + if upper.contains("INDEX") { + return "INDEX".to_string(); + } + "TABLE".to_string() +} + #[cfg(test)] mod tests { use super::{ @@ -738,12 +800,40 @@ mod tests { test_table_info("users"), ]; - let filtered = filter_table_infos(tables, Some("audit"), Some(1), Some(1)); + let filtered = filter_table_infos(tables, Some("audit"), Some(1), Some(1), None); assert_eq!(filtered.len(), 1); assert_eq!(filtered[0].name, "audit_record"); } + #[test] + fn filter_table_infos_filters_object_type_before_offset_and_limit() { + let tables = vec![ + test_table_info("orders"), + super::db::TableInfo { + name: "active_orders".to_string(), + table_type: "VIEW".to_string(), + comment: None, + parent_schema: None, + parent_name: None, + }, + test_table_info("users"), + super::db::TableInfo { + name: "active_users".to_string(), + table_type: "VIEW".to_string(), + comment: None, + parent_schema: None, + parent_name: None, + }, + ]; + let object_types = vec!["VIEW".to_string()]; + + let filtered = filter_table_infos(tables, None, Some(1), Some(1), Some(&object_types)); + + assert_eq!(filtered.len(), 1); + assert_eq!(filtered[0].name, "active_users"); + } + #[cfg(feature = "duckdb-bundled")] #[test] fn duckdb_list_databases_includes_attached_database() { @@ -954,7 +1044,7 @@ async fn list_objects_once( PoolKind::Postgres(p) => db::postgres::list_objects(p, schema).await, _ => { drop(connections); - Ok(list_tables_core(state, connection_id, database, schema, None, None, None) + Ok(list_tables_core(state, connection_id, database, schema, None, None, None, None) .await? .into_iter() .map(|table| db::ObjectInfo { @@ -1473,7 +1563,20 @@ pub async fn get_table_ddl_core( database: &str, schema: &str, table: &str, + object_type: Option, ) -> Result { + if matches!(object_type, Some(db::ObjectSourceKind::View)) { + let source = + get_object_source_core(state, connection_id, database, schema, table, db::ObjectSourceKind::View).await?; + let database_type = connection_config(state, connection_id).await.map(|config| config.db_type); + return Ok(crate::object_source_sql::build_view_ddl_sql(crate::object_source_sql::BuildViewDdlInput { + database_type, + schema: if schema.trim().is_empty() { None } else { Some(schema.to_string()) }, + name: table.to_string(), + source: source.source, + })); + } + let pool_key = state.get_or_create_pool(connection_id, Some(database)).await?; { diff --git a/crates/dbx-core/src/transfer.rs b/crates/dbx-core/src/transfer.rs index 1c0539340..0d7a2930e 100644 --- a/crates/dbx-core/src/transfer.rs +++ b/crates/dbx-core/src/transfer.rs @@ -2746,6 +2746,7 @@ where Some(table), Some(1), None, + None, ) .await .unwrap_or_default() @@ -2761,6 +2762,7 @@ where Some(table), Some(1), None, + None, ) .await .map(|tables| !tables.is_empty()) diff --git a/crates/dbx-web/src/routes/schema.rs b/crates/dbx-web/src/routes/schema.rs index 3b03337a7..a9a96d917 100644 --- a/crates/dbx-web/src/routes/schema.rs +++ b/crates/dbx-web/src/routes/schema.rs @@ -17,6 +17,7 @@ pub struct SchemaQuery { pub limit: Option, pub offset: Option, pub object_type: Option, + pub object_types: Option, } pub async fn list_databases( @@ -42,6 +43,9 @@ pub async fn list_tables( ) -> Result, AppError> { let database = q.database.as_deref().unwrap_or(""); let schema = q.schema.as_deref().unwrap_or(""); + let object_types = q.object_types.as_ref().map(|value| { + value.split(',').map(str::trim).filter(|value| !value.is_empty()).map(str::to_string).collect::>() + }); let result = dbx_core::schema::list_tables_core( &state.app, &q.connection_id, @@ -50,6 +54,7 @@ pub async fn list_tables( q.filter.as_deref(), q.limit, q.offset, + object_types.as_deref(), ) .await .map_err(AppError)?; @@ -153,9 +158,10 @@ pub async fn get_ddl( let database = q.database.as_deref().unwrap_or(""); let schema = q.schema.as_deref().unwrap_or(""); let table = q.table.as_deref().unwrap_or(""); - let result = dbx_core::schema::get_table_ddl_core(&state.app, &q.connection_id, database, schema, table) - .await - .map_err(AppError)?; + let result = + dbx_core::schema::get_table_ddl_core(&state.app, &q.connection_id, database, schema, table, q.object_type) + .await + .map_err(AppError)?; Ok(Json(result)) } diff --git a/src-tauri/src/commands/mcp_bridge.rs b/src-tauri/src/commands/mcp_bridge.rs index b6ad60a93..3526f8484 100644 --- a/src-tauri/src/commands/mcp_bridge.rs +++ b/src-tauri/src/commands/mcp_bridge.rs @@ -327,7 +327,7 @@ async fn handle_list_tables_data(state: &Arc, body: &str, stream: &mut respond_error(stream, "403 Forbidden", &e).await; return; } - match dbx_core::schema::list_tables_core(state, &config.id, &database, &schema, None, None, None).await { + match dbx_core::schema::list_tables_core(state, &config.id, &database, &schema, None, None, None, None).await { Ok(tables) => respond_json(stream, &tables).await, Err(e) => respond_error(stream, "500 Internal Server Error", &e).await, } diff --git a/src-tauri/src/commands/schema.rs b/src-tauri/src/commands/schema.rs index fe10c4ea0..50da1448b 100644 --- a/src-tauri/src/commands/schema.rs +++ b/src-tauri/src/commands/schema.rs @@ -30,9 +30,19 @@ pub async fn list_tables( filter: Option, limit: Option, offset: Option, + object_types: Option>, ) -> Result, String> { - dbx_core::schema::list_tables_core(&state, &connection_id, &database, &schema, filter.as_deref(), limit, offset) - .await + dbx_core::schema::list_tables_core( + &state, + &connection_id, + &database, + &schema, + filter.as_deref(), + limit, + offset, + object_types.as_deref(), + ) + .await } #[tauri::command] @@ -118,8 +128,9 @@ pub async fn get_table_ddl( database: String, schema: String, table: String, + object_type: Option, ) -> Result { - dbx_core::schema::get_table_ddl_core(&state, &connection_id, &database, &schema, &table).await + dbx_core::schema::get_table_ddl_core(&state, &connection_id, &database, &schema, &table, object_type).await } #[tauri::command]