fix(postgres): use pg_catalog instead of information_schema for table/schema listing

information_schema views apply permission filtering that causes empty
results on openGauss/GaussDB for non-owner users. Switching to pg_catalog
(pg_class + pg_namespace) matches the behavior of Navicat and DataGrip.
This commit is contained in:
t8y2
2026-05-14 15:14:07 +08:00
parent a0bcb1d889
commit 1e8ce6673f
2 changed files with 30 additions and 19 deletions
+16 -9
View File
@@ -171,20 +171,27 @@ impl AppState {
let con = db::duckdb_driver::connect_path(&expand_tilde(&db_config.host))?;
PoolKind::DuckDb(con)
}
DatabaseType::MongoDb => match db::mongo_driver::connect(&url).await {
Ok(client) => {
db::mongo_driver::test_connection(&client).await?;
PoolKind::MongoDb(client)
}
Err(e) if e.contains("wire version") => {
log::info!("Native MongoDB driver failed ({e}), falling back to agent driver");
DatabaseType::MongoDb => {
let native_err = match db::mongo_driver::connect(&url).await {
Ok(client) => match db::mongo_driver::test_connection(&client).await {
Ok(()) => {
self.connections.write().await.insert(pool_key.clone(), PoolKind::MongoDb(client));
return Ok(pool_key);
}
Err(e) => e,
},
Err(e) => e,
};
if native_err.contains("wire version") {
log::info!("Native MongoDB driver failed ({native_err}), falling back to agent driver");
let connect_params = serde_json::json!({ "connection": agent_connect_params(&db_config, &host, port, db_config.effective_database().unwrap_or("")) });
let mut client = self.agent_manager.spawn(&DatabaseType::MongoDb, None).await?;
client.call::<serde_json::Value>("connect", connect_params).await?;
PoolKind::Agent(Arc::new(tokio::sync::Mutex::new(client)))
} else {
return Err(native_err);
}
Err(e) => return Err(e),
},
}
DatabaseType::ClickHouse => {
let username = if db_config.username.is_empty() { None } else { Some(db_config.username.clone()) };
let password = if db_config.password.is_empty() { None } else { Some(db_config.password.clone()) };
+14 -10
View File
@@ -201,11 +201,15 @@ pub async fn list_databases(pool: &PgPool) -> Result<Vec<DatabaseInfo>, String>
pub async fn list_tables(pool: &PgPool, schema: &str) -> Result<Vec<TableInfo>, String> {
let rows: Vec<PgRow> = sqlx::query(
"SELECT t.table_name, t.table_type, obj_description(c.oid) AS table_comment \
FROM information_schema.tables t \
LEFT JOIN pg_catalog.pg_class c ON c.relname = t.table_name \
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND n.nspname = t.table_schema \
WHERE t.table_schema = $1 ORDER BY t.table_name",
"SELECT c.relname AS table_name, \
CASE c.relkind WHEN 'r' THEN 'BASE TABLE' WHEN 'v' THEN 'VIEW' \
WHEN 'm' THEN 'MATERIALIZED VIEW' WHEN 'f' THEN 'FOREIGN TABLE' \
WHEN 'p' THEN 'BASE TABLE' END AS table_type, \
obj_description(c.oid) AS table_comment \
FROM pg_catalog.pg_class c \
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \
WHERE n.nspname = $1 AND c.relkind IN ('r','v','m','f','p') \
ORDER BY c.relname",
)
.bind(schema)
.fetch_all(pool)
@@ -224,11 +228,11 @@ pub async fn list_tables(pool: &PgPool, schema: &str) -> Result<Vec<TableInfo>,
pub async fn list_schemas(pool: &PgPool) -> Result<Vec<String>, String> {
let rows: Vec<PgRow> = sqlx::query(
"SELECT schema_name FROM information_schema.schemata \
WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast') \
AND schema_name NOT LIKE 'pg_toast_temp_%' \
AND schema_name NOT LIKE 'pg_temp_%' \
ORDER BY schema_name",
"SELECT n.nspname AS schema_name FROM pg_catalog.pg_namespace n \
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",
)
.fetch_all(pool)
.await