diff --git a/crates/catalog/glue/src/catalog.rs b/crates/catalog/glue/src/catalog.rs index fb4bd36b8d..f47d1d54ca 100644 --- a/crates/catalog/glue/src/catalog.rs +++ b/crates/catalog/glue/src/catalog.rs @@ -624,15 +624,75 @@ impl Catalog for GlueCatalog { } } + /// Asynchronously 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: &TableIdent, + metadata_location: String, ) -> Result { - Err(Error::new( - ErrorKind::FeatureUnsupported, - "Registering a table is not supported yet", - )) + let db_name = validate_namespace(table.namespace())?; + let table_name = table.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); + + let result = builder.send().await; + + match result { + Ok(_) => { + self.load_table(table).await.map_err(|e| { + Error::new( + ErrorKind::Unexpected, + format!( + "Table {}.{} created but failed to load: {e}", + db_name, table_name + ), + ) + }) + } + Err(err) => { + let service_err = err.as_service_error(); + + if service_err.map(|e| e.is_entity_not_found_exception()) == Some(true) { + Err(Error::new( + ErrorKind::NamespaceNotFound, + format!("Database {} does not exist", db_name), + )) + } else if service_err.map(|e| e.is_already_exists_exception()) == Some(true) { + Err(Error::new( + ErrorKind::TableAlreadyExists, + format!("Table {}.{} already exists", db_name, table_name), + )) + } else { + Err(from_aws_sdk_error(err)) + } + } + } } 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 bec9494fe9..60a998d010 100644 --- a/crates/catalog/glue/tests/glue_catalog_test.rs +++ b/crates/catalog/glue/tests/glue_catalog_test.rs @@ -367,3 +367,32 @@ async fn test_list_namespace() -> 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().as_deref(), + Some(metadata_location.as_str()) + ); + + Ok(()) +}