feat(usable): integrate current dbtool implementation snapshot
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -102,23 +102,27 @@ impl DatabaseDriver for PostgresDriver {
|
||||
(None, None) => {
|
||||
let rows = client
|
||||
.query(
|
||||
"SELECT schema_name \
|
||||
FROM information_schema.schemata \
|
||||
WHERE schema_name NOT IN ('pg_catalog', 'information_schema') \
|
||||
ORDER BY schema_name",
|
||||
"SELECT n.nspname AS schema_name,
|
||||
has_schema_privilege(n.nspname, 'USAGE') AS has_usage
|
||||
FROM pg_namespace n
|
||||
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
||||
AND n.nspname NOT LIKE 'pg_toast%'
|
||||
AND n.nspname NOT LIKE 'pg_temp_%'
|
||||
ORDER BY n.nspname",
|
||||
&[],
|
||||
)
|
||||
.map_err(map_postgres_error)?;
|
||||
|
||||
Ok(InspectResult::Schemas(
|
||||
rows.into_iter()
|
||||
.map(|row| SchemaSummary {
|
||||
name: row.get::<_, String>(0),
|
||||
.map(|row| {
|
||||
postgres_schema_summary(row.get::<_, String>(0), row.get::<_, bool>(1))
|
||||
})
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
(Some(schema), None) => {
|
||||
ensure_postgres_schema_access(&mut client, schema)?;
|
||||
let rows = client
|
||||
.query(
|
||||
"SELECT table_schema, table_name, table_type \
|
||||
@@ -140,6 +144,7 @@ impl DatabaseDriver for PostgresDriver {
|
||||
))
|
||||
}
|
||||
(Some(schema), Some(table)) => {
|
||||
ensure_postgres_schema_access(&mut client, schema)?;
|
||||
let rows = client
|
||||
.query(
|
||||
"SELECT c.column_name,
|
||||
@@ -256,7 +261,7 @@ impl DatabaseDriver for MysqlDriver {
|
||||
|
||||
Ok(InspectResult::Schemas(
|
||||
rows.into_iter()
|
||||
.map(|(name,)| SchemaSummary { name })
|
||||
.map(|(name,)| SchemaSummary::ready(name))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
@@ -516,11 +521,7 @@ fn inspect_sqlite_schemas(connection: &SqliteConnection) -> Result<InspectResult
|
||||
.prepare("PRAGMA database_list")
|
||||
.map_err(map_sqlite_inspect_error)?;
|
||||
let schemas = statement
|
||||
.query_map([], |row| {
|
||||
Ok(SchemaSummary {
|
||||
name: row.get::<_, String>(1)?,
|
||||
})
|
||||
})
|
||||
.query_map([], |row| Ok(SchemaSummary::ready(row.get::<_, String>(1)?)))
|
||||
.map_err(map_sqlite_inspect_error)?
|
||||
.collect::<rusqlite::Result<Vec<_>>>()
|
||||
.map_err(map_sqlite_inspect_error)?;
|
||||
@@ -651,6 +652,41 @@ fn simple_query_result(client: &mut Client, sql: &str) -> Result<QueryResult, Dr
|
||||
}
|
||||
}
|
||||
|
||||
fn postgres_schema_summary(name: String, has_usage: bool) -> SchemaSummary {
|
||||
if has_usage {
|
||||
SchemaSummary::ready(name)
|
||||
} else {
|
||||
SchemaSummary::restricted(name.clone(), restricted_schema_message(&name))
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_postgres_schema_access(client: &mut Client, schema: &str) -> Result<(), DriverError> {
|
||||
let row = client
|
||||
.query_one(
|
||||
"SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_namespace
|
||||
WHERE nspname = $1
|
||||
) AS schema_exists,
|
||||
has_schema_privilege($1, 'USAGE') AS has_usage",
|
||||
&[&schema],
|
||||
)
|
||||
.map_err(map_postgres_error)?;
|
||||
|
||||
let schema_exists = row.get::<_, bool>(0);
|
||||
let has_usage = row.get::<_, bool>(1);
|
||||
|
||||
if schema_exists && !has_usage {
|
||||
return Err(DriverError::Inspect(restricted_schema_message(schema)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn restricted_schema_message(schema: &str) -> String {
|
||||
format!("schema access is restricted: {schema}")
|
||||
}
|
||||
|
||||
fn consume_mysql_query_result<T: MySqlProtocol>(
|
||||
mut result: MySqlQueryResult<'_, '_, '_, T>,
|
||||
) -> Result<QueryResult, DriverError> {
|
||||
@@ -964,6 +1000,27 @@ mod tests {
|
||||
assert_eq!(rendered, "张敏😀");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_schema_summary_marks_restricted_entries() {
|
||||
let schema = postgres_schema_summary(String::from("restricted_probe"), false);
|
||||
|
||||
assert_eq!(
|
||||
schema,
|
||||
SchemaSummary::restricted(
|
||||
"restricted_probe",
|
||||
"schema access is restricted: restricted_probe"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn restricted_schema_message_is_stable() {
|
||||
assert_eq!(
|
||||
restricted_schema_message("restricted_probe"),
|
||||
"schema access is restricted: restricted_probe"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqlite_driver_supports_connect_inspect_and_query() {
|
||||
let unique = SystemTime::now()
|
||||
@@ -995,9 +1052,7 @@ mod tests {
|
||||
.expect("sqlite schemas should load");
|
||||
assert_eq!(
|
||||
schemas,
|
||||
InspectResult::Schemas(vec![SchemaSummary {
|
||||
name: String::from("main"),
|
||||
}])
|
||||
InspectResult::Schemas(vec![SchemaSummary::ready("main")])
|
||||
);
|
||||
|
||||
let tables = DriverRegistry::inspect(
|
||||
|
||||
Reference in New Issue
Block a user