sdd commented on code in PR #534: URL: https://github.com/apache/iceberg-rust/pull/534#discussion_r1714277890
########## crates/catalog/sql/src/catalog.rs: ########## @@ -167,43 +177,344 @@ impl SqlCatalog { .await .map_err(from_sqlx_error) } + + /// Execute statements in a transaction, provided or not + pub async fn execute( + &self, + query: &str, + args: Vec<Option<&str>>, + transaction: Option<&mut Transaction<'_, Any>>, + ) -> Result<AnyQueryResult> { + let query_with_placeholders = self.replace_placeholders(query); + + let mut sqlx_query = sqlx::query(&query_with_placeholders); + for arg in args { + sqlx_query = sqlx_query.bind(arg); + } + + match transaction { + Some(t) => sqlx_query.execute(&mut **t).await.map_err(from_sqlx_error), + None => { + let mut tx = self.connection.begin().await.map_err(from_sqlx_error)?; + let result = sqlx_query.execute(&mut *tx).await.map_err(from_sqlx_error); + let _ = tx.commit().await.map_err(from_sqlx_error); + result + } + } + } } #[async_trait] impl Catalog for SqlCatalog { async fn list_namespaces( &self, - _parent: Option<&NamespaceIdent>, + parent: Option<&NamespaceIdent>, ) -> Result<Vec<NamespaceIdent>> { - todo!() + let table_namespaces_stmt = format!( + "SELECT {CATALOG_FIELD_TABLE_NAMESPACE} + FROM {CATALOG_TABLE_NAME} + WHERE {CATALOG_FIELD_CATALOG_NAME} = ?" + ); + let namespaces_stmt = format!( + "SELECT {NAMESPACE_FIELD_NAME} + FROM {NAMESPACE_TABLE_NAME} + WHERE {CATALOG_FIELD_CATALOG_NAME} = ?" + ); + + match parent { + Some(parent) => match self.namespace_exists(parent).await? { + true => { + let parent_str = parent.join("."); + let parent_table_namespaces_stmt = format!( + "{table_namespaces_stmt} AND {CATALOG_FIELD_TABLE_NAMESPACE} LIKE CONCAT(?, '%')" + ); + let parent_namespaces_stmt = + format!("{namespaces_stmt} AND {NAMESPACE_FIELD_NAME} LIKE CONCAT(?, '%')"); + + let namespace_rows = self + .fetch_rows( + &format!( + "{parent_namespaces_stmt} UNION {parent_table_namespaces_stmt}" + ), + vec![ + Some(&self.name), + Some(&parent_str), + Some(&self.name), + Some(&parent_str), + ], + ) + .await?; + + Ok(namespace_rows + .iter() + .filter_map(|r| { + let nsp = r.try_get::<String, _>(0).ok(); Review Comment: Is this the behaviour we want? using `.ok()` suppresses any error that might get raised in `r.try_get()`. Would we not want to bail out of `list_namespaces` with the error instead? Using `filter_map` can make this harder to do. We could make the error-handling behaviour easier to implement by using a for loop instead as we stay inside the context of `list_namespaces` rather than traversing into a closure where we can't use `?`. If you initialize a `Vec` for the results using `Vec::with_capacity(namespace_rows.len())` then you still only have one heap allocation, as you would have here from the `collect()` call anyway. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org For additional commands, e-mail: issues-h...@iceberg.apache.org