From eb8b20586bc11517513bfae500e6037dab79f3fe Mon Sep 17 00:00:00 2001 From: Siyuan Huang <73871299+kysshsy@users.noreply.github.com> Date: Fri, 20 Dec 2024 00:10:20 +0800 Subject: [PATCH] feat: add a duckdb_extensions() shows duckdb extension details (#183) * feat: add a duckdb_extensions() shows duckdb extension details * test: add duckdb_extensions() test * test: fix test azure is installed during execution --- src/api/duckdb.rs | 70 +++++++++++++++++++++++++++++++++++++++++ tests/tests/settings.rs | 10 ++++++ 2 files changed, 80 insertions(+) diff --git a/src/api/duckdb.rs b/src/api/duckdb.rs index 6f220816..1ae90cae 100644 --- a/src/api/duckdb.rs +++ b/src/api/duckdb.rs @@ -11,6 +11,18 @@ type DuckdbSettingsRow = ( Option, ); +type DuckdbExtensionsRow = ( + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, +); + #[pg_extern] pub fn duckdb_execute(query: &str) { connection::execute(query, []).unwrap_or_else(|err| panic!("error executing query: {err:?}")); @@ -52,3 +64,61 @@ fn duckdb_settings_impl() -> Result> { .map(|row| row.unwrap()) .collect::>()) } + +#[allow(clippy::type_complexity)] +#[pg_extern] +pub fn duckdb_extensions() -> iter::TableIterator< + 'static, + ( + name!(extension_name, Option), + name!(loaded, Option), + name!(installed, Option), + name!(install_path, Option), + name!(description, Option), + name!(aliases, Option), + name!(extension_version, Option), + name!(install_mode, Option), + name!(installed_from, Option), + ), +> { + let rows = duckdb_extensions_impl().unwrap_or_else(|e| { + panic!("{}", e); + }); + iter::TableIterator::new(rows) +} + +#[inline] +fn duckdb_extensions_impl() -> Result> { + let conn = unsafe { &*connection::get_global_connection().get() }; + let mut stmt = conn.prepare( + "SELECT + extension_name, + loaded, + installed, + install_path, + description, + aliases::varchar, + extension_version, + install_mode, + installed_from + FROM + duckdb_extensions();", + )?; + + Ok(stmt + .query_map([], |row| { + Ok(( + row.get::<_, Option>(0)?, + row.get::<_, Option>(1)?, + row.get::<_, Option>(2)?, + row.get::<_, Option>(3)?, + row.get::<_, Option>(4)?, + row.get::<_, Option>(5)?, + row.get::<_, Option>(6)?, + row.get::<_, Option>(7)?, + row.get::<_, Option>(8)?, + )) + })? + .map(|row| row.unwrap()) + .collect::>()) +} diff --git a/tests/tests/settings.rs b/tests/tests/settings.rs index 6bb8c197..d87d121a 100644 --- a/tests/tests/settings.rs +++ b/tests/tests/settings.rs @@ -15,3 +15,13 @@ async fn test_duckdb_settings(mut conn: PgConnection) -> Result<()> { Ok(()) } + +#[rstest] +async fn test_duckdb_extensions(mut conn: PgConnection) -> Result<()> { + let azure_extension: (Option,) = + "SELECT extension_name FROM duckdb_extensions() WHERE extension_name = 'azure'" + .fetch_one(&mut conn); + assert!(azure_extension.0.is_some()); + + Ok(()) +}