diff --git a/crates/catalog/glue/src/catalog.rs b/crates/catalog/glue/src/catalog.rs index c589cc79da..9b383df2b1 100644 --- a/crates/catalog/glue/src/catalog.rs +++ b/crates/catalog/glue/src/catalog.rs @@ -20,6 +20,7 @@ use std::fmt::Debug; use anyhow::anyhow; use async_trait::async_trait; +use aws_sdk_glue::operation::create_table::CreateTableError; use aws_sdk_glue::operation::update_table::UpdateTableError; use aws_sdk_glue::types::TableInput; use iceberg::io::{ @@ -700,15 +701,67 @@ impl Catalog for GlueCatalog { } } + /// registers an existing table into the Glue Catalog. + /// + /// Converts the provided table identifier and metadata location into a + /// Glue-compatible table representation, and attempts to create the + /// corresponding table in the Glue Catalog. + /// + /// # Returns + /// Returns `Ok(Table)` if the table is successfully registered and loaded. + /// If the registration fails due to validation issues, existing table conflicts, + /// metadata problems, or errors during the registration or loading process, + /// an `Err(...)` is returned. async fn register_table( &self, - _table_ident: &TableIdent, - _metadata_location: String, + table_ident: &TableIdent, + metadata_location: String, ) -> Result { - Err(Error::new( - ErrorKind::FeatureUnsupported, - "Registering a table is not supported yet", - )) + let db_name = validate_namespace(table_ident.namespace())?; + let table_name = table_ident.name(); + let metadata = TableMetadata::read_from(&self.file_io, &metadata_location).await?; + + let table_input = convert_to_glue_table( + table_name, + metadata_location.clone(), + &metadata, + metadata.properties(), + None, + )?; + + let builder = self + .client + .0 + .create_table() + .database_name(&db_name) + .table_input(table_input); + let builder = with_catalog_id!(builder, self.config); + + builder.send().await.map_err(|e| { + let error = e.into_service_error(); + match error { + CreateTableError::EntityNotFoundException(_) => Error::new( + ErrorKind::NamespaceNotFound, + format!("Database {db_name} does not exist"), + ), + CreateTableError::AlreadyExistsException(_) => Error::new( + ErrorKind::TableAlreadyExists, + format!("Table {table_ident} already exists"), + ), + _ => Error::new( + ErrorKind::Unexpected, + format!("Failed to register table {table_ident} due to AWS SDK error"), + ), + } + .with_source(anyhow!("aws sdk error: {:?}", error)) + })?; + + Ok(Table::builder() + .identifier(table_ident.clone()) + .metadata_location(metadata_location) + .metadata(metadata) + .file_io(self.file_io()) + .build()?) } async fn update_table(&self, commit: TableCommit) -> Result
{ diff --git a/crates/catalog/glue/tests/glue_catalog_test.rs b/crates/catalog/glue/tests/glue_catalog_test.rs index 3141a2712d..548fc4f0f3 100644 --- a/crates/catalog/glue/tests/glue_catalog_test.rs +++ b/crates/catalog/glue/tests/glue_catalog_test.rs @@ -469,3 +469,35 @@ async fn test_update_table() -> Result<()> { Ok(()) } + +#[tokio::test] +async fn test_register_table() -> Result<()> { + let catalog = get_catalog().await; + let namespace = NamespaceIdent::new("test_register_table".into()); + set_test_namespace(&catalog, &namespace).await?; + + let creation = set_table_creation( + Some("s3a://warehouse/hive/test_register_table".into()), + "my_table", + )?; + let table = catalog.create_table(&namespace, creation).await?; + let metadata_location = table + .metadata_location() + .expect("Expected metadata location to be set") + .to_string(); + + catalog.drop_table(table.identifier()).await?; + let ident = TableIdent::new(namespace.clone(), "my_table".to_string()); + + let registered = catalog + .register_table(&ident, metadata_location.clone()) + .await?; + + assert_eq!(registered.identifier(), &ident); + assert_eq!( + registered.metadata_location(), + Some(metadata_location.as_str()) + ); + + Ok(()) +}