feat(metadata): honor system schema visibility
This commit is contained in:
1 parent
a07def6042
commit
820b8cd26f
44 files changed
+422
-47
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user