feat(metadata): honor system schema visibility

This commit is contained in:
amwps290 authored and GitHub committed 2026-07-29 03:23:04 +08:00
1 parent a07def6042
commit 820b8cd26f
44 files changed
+422 -47

No files matched your search

+1
View File
@@ -620,6 +620,7 @@ mod tests {
database: database.map(str::to_string),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+3
View File
@@ -1133,6 +1133,7 @@ mod tests {
database: Some("app_db".to_string()),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -1188,6 +1189,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -1280,6 +1282,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: Some("CREATE SECRET (TYPE quack, TOKEN 'token-value');".to_string()),
color: None,
+1
View File
@@ -3912,6 +3912,7 @@ mod tests {
database: database.map(str::to_string),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -750,6 +750,7 @@ mod tests {
database: Some("postgres".to_string()),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+5 -1
View File
@@ -1048,19 +1048,23 @@ impl AgentDriverClient {
database: &str,
timeout_duration: Option<Duration>,
) -> Result<T, String> {
self.list_schemas_filtered(database, None, timeout_duration).await
self.list_schemas_filtered(database, None, false, timeout_duration).await
}
pub async fn list_schemas_filtered<T: DeserializeOwned + Send + 'static>(
&mut self,
database: &str,
visible_schemas: Option<&[String]>,
show_system_schemas: bool,
timeout_duration: Option<Duration>,
) -> Result<T, String> {
let mut params = serde_json::json!({ "database": database });
if let Some(visible_schemas) = visible_schemas {
params["visible_schemas"] = serde_json::json!(visible_schemas);
}
if show_system_schemas {
params["show_system_schemas"] = serde_json::Value::Bool(true);
}
self.call_method_with_timeout(AgentMethod::ListSchemas, params, timeout_duration).await
}
+50 -17
View File
@@ -2504,27 +2504,49 @@ pub async fn list_object_statistics(pool: &Pool, schema: &str) -> Result<Vec<Obj
}
pub async fn list_schemas(pool: &Pool) -> Result<Vec<String>, String> {
Ok(list_schema_infos(pool).await?.into_iter().map(|schema| schema.name).collect())
list_schemas_with_system(pool, false).await
}
pub async fn list_schema_infos(pool: &Pool) -> Result<Vec<SchemaInfo>, String> {
list_schema_infos_with_system(pool, false).await
}
pub async fn list_schemas_with_system(pool: &Pool, show_system_schemas: bool) -> Result<Vec<String>, String> {
Ok(list_schema_infos_with_system(pool, show_system_schemas).await?.into_iter().map(|schema| schema.name).collect())
}
const POSTGRES_SCHEMA_INFOS_SQL: &str = "SELECT n.nspname AS schema_name, d.description AS schema_comment \
FROM pg_catalog.pg_namespace n \
LEFT JOIN pg_catalog.pg_description d \
ON d.objoid = n.oid \
AND d.objsubid = 0 \
AND d.classoid = 'pg_namespace'::regclass \
ORDER BY n.nspname";
const POSTGRES_SCHEMA_INFOS_HIDE_SYSTEM_SQL: &str = "SELECT n.nspname AS schema_name, d.description AS schema_comment \
FROM pg_catalog.pg_namespace n \
LEFT JOIN pg_catalog.pg_description d \
ON d.objoid = n.oid \
AND d.objsubid = 0 \
AND d.classoid = 'pg_namespace'::regclass \
WHERE n.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast') \
AND n.nspname NOT LIKE 'pg_toast_temp_%' \
AND n.nspname NOT LIKE 'pg_temp_%' \
ORDER BY n.nspname";
fn postgres_schema_infos_sql(show_system_schemas: bool) -> &'static str {
if show_system_schemas {
POSTGRES_SCHEMA_INFOS_SQL
} else {
POSTGRES_SCHEMA_INFOS_HIDE_SYSTEM_SQL
}
}
pub async fn list_schema_infos_with_system(pool: &Pool, show_system_schemas: bool) -> Result<Vec<SchemaInfo>, String> {
let client = checkout_postgres_client(pool, None, super::connection_timeout()).await?;
let rows = postgres_query_cached(
&client,
"SELECT n.nspname AS schema_name, d.description AS schema_comment \
FROM pg_catalog.pg_namespace n \
LEFT JOIN pg_catalog.pg_description d \
ON d.objoid = n.oid \
AND d.objsubid = 0 \
AND d.classoid = 'pg_namespace'::regclass \
WHERE n.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast') \
AND n.nspname NOT LIKE 'pg_toast_temp_%' \
AND n.nspname NOT LIKE 'pg_temp_%' \
ORDER BY n.nspname",
&[],
)
.await
.map_err(|e| e.to_string())?;
let rows = postgres_query_cached(&client, postgres_schema_infos_sql(show_system_schemas), &[])
.await
.map_err(|e| e.to_string())?;
Ok(rows
.iter()
@@ -5719,4 +5741,15 @@ mod tests {
assert!(postgres_completion_columns_sql().contains("a.attname ILIKE $3 ESCAPE '~'"));
assert!(postgres_visible_table_schema_sql().contains("pg_catalog.pg_table_is_visible(c.oid)"));
}
#[test]
fn postgres_schema_info_sql_only_filters_system_schemas_when_disabled() {
let hidden_sql = postgres_schema_infos_sql(false);
assert!(hidden_sql.contains("information_schema"));
assert!(hidden_sql.contains("pg_temp_%"));
let visible_sql = postgres_schema_infos_sql(true);
assert!(!visible_sql.contains("NOT IN"));
assert!(!visible_sql.contains("NOT LIKE"));
}
}
+1
View File
@@ -4643,6 +4643,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+6
View File
@@ -92,6 +92,8 @@ pub struct ConnectionConfig {
pub visible_databases: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub visible_schemas: Option<HashMap<String, Vec<String>>>,
#[serde(default, skip_serializing_if = "is_false")]
pub show_system_schemas: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attached_databases: Vec<AttachedDatabaseConfig>,
/// SQL statements executed right after the connection is established
@@ -561,6 +563,8 @@ struct ConnectionConfigData {
#[serde(default)]
pub visible_schemas: Option<HashMap<String, Vec<String>>>,
#[serde(default)]
pub show_system_schemas: bool,
#[serde(default)]
pub attached_databases: Vec<AttachedDatabaseConfig>,
#[serde(default)]
pub init_script: Option<String>,
@@ -650,6 +654,7 @@ impl From<ConnectionConfigData> for ConnectionConfig {
database: data.database,
visible_databases: data.visible_databases,
visible_schemas: data.visible_schemas,
show_system_schemas: data.show_system_schemas,
attached_databases: data.attached_databases,
init_script: data.init_script,
color: data.color,
@@ -2197,6 +2202,7 @@ mod tests {
database: database.map(str::to_string),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+1
View File
@@ -117,6 +117,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+1
View File
@@ -870,6 +870,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+1
View File
@@ -299,6 +299,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+2
View File
@@ -231,6 +231,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -301,6 +302,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+1
View File
@@ -653,6 +653,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: vec![],
init_script: None,
color: None,
+2
View File
@@ -3662,6 +3662,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -4786,6 +4787,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+11 -6
View File
@@ -1180,10 +1180,12 @@ async fn list_schema_infos_once(
database: &str,
) -> Result<Vec<db::SchemaInfo>, String> {
let pool_key = state.get_or_create_pool(connection_id, Some(database)).await?;
let db_config = connection_config(state, connection_id).await;
let show_system_schemas = db_config.as_ref().is_some_and(|config| config.show_system_schemas);
{
let connections = state.connections.read().await;
if let Some(PoolKind::Postgres(pool)) = connections.get(&pool_key) {
return db::postgres::list_schema_infos(pool).await;
return db::postgres::list_schema_infos_with_system(pool, show_system_schemas).await;
}
}
@@ -1250,6 +1252,7 @@ async fn list_schemas_once(
) -> Result<Vec<String>, String> {
let pool_key = state.get_or_create_pool(connection_id, Some(database)).await?;
let db_config = connection_config(state, connection_id).await;
let show_system_schemas = db_config.as_ref().is_some_and(|config| config.show_system_schemas);
let visible_schema_filter = visible_schema_filter(db_config.as_ref(), database, apply_visible_filter);
{
@@ -1275,6 +1278,7 @@ async fn list_schemas_once(
.list_schemas_filtered::<Vec<String>>(
database,
visible_schema_filter.as_deref(),
show_system_schemas,
agent_metadata_timeout(db_config.as_ref()),
)
.await
@@ -1286,9 +1290,9 @@ async fn list_schemas_once(
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_schemas(&pool).await.map(|schemas| {
filter_visible_schema_names(schemas, visible_schema_filter.as_deref())
})
return db::postgres::list_schemas_with_system(&pool, show_system_schemas).await.map(
|schemas| filter_visible_schema_names(schemas, visible_schema_filter.as_deref()),
)
}
Ok(None) => {
return Ok(filter_visible_schema_names(schemas, visible_schema_filter.as_deref()))
@@ -1310,7 +1314,7 @@ async fn list_schemas_once(
if let Some(pool) =
native_postgres_metadata_pool(state, connection_id, database, config).await?
{
return db::postgres::list_schemas(&pool)
return db::postgres::list_schemas_with_system(&pool, show_system_schemas)
.await
.map(|schemas| filter_visible_schema_names(schemas, visible_schema_filter.as_deref()))
.map_err(|fallback_error| {
@@ -1333,7 +1337,7 @@ async fn list_schemas_once(
PoolKind::Mysql(p, mode) if *mode == MysqlMode::OceanBaseOracle => db::ob_oracle::list_schemas(p)
.await
.map(|schemas| filter_visible_schema_names(schemas, visible_schema_filter.as_deref())),
PoolKind::Postgres(p) => db::postgres::list_schemas(p)
PoolKind::Postgres(p) => db::postgres::list_schemas_with_system(p, show_system_schemas)
.await
.map(|schemas| filter_visible_schema_names(schemas, visible_schema_filter.as_deref())),
#[cfg(feature = "duckdb-bundled")]
@@ -3034,6 +3038,7 @@ mod tests {
database: Some("demo".to_string()),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -159,6 +159,7 @@ mod tests {
database: Some("demo".to_string()),
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+2
View File
@@ -3791,6 +3791,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
@@ -3853,6 +3854,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,
+1
View File
@@ -4936,6 +4936,7 @@ mod tests {
database: None,
visible_databases: None,
visible_schemas: None,
show_system_schemas: false,
attached_databases: Vec::new(),
init_script: None,
color: None,