diff --git a/aws/src/integration/java/org/apache/iceberg/aws/dynamodb/TestDynamoDbCatalog.java b/aws/src/integration/java/org/apache/iceberg/aws/dynamodb/TestDynamoDbCatalog.java index 94f19a3a2eee..1eade371831c 100644 --- a/aws/src/integration/java/org/apache/iceberg/aws/dynamodb/TestDynamoDbCatalog.java +++ b/aws/src/integration/java/org/apache/iceberg/aws/dynamodb/TestDynamoDbCatalog.java @@ -27,8 +27,10 @@ import java.util.stream.IntStream; import org.apache.iceberg.AssertHelpers; import org.apache.iceberg.CatalogProperties; +import org.apache.iceberg.HasTableOperations; import org.apache.iceberg.Schema; import org.apache.iceberg.Table; +import org.apache.iceberg.TableOperations; import org.apache.iceberg.aws.AwsClientFactories; import org.apache.iceberg.aws.AwsClientFactory; import org.apache.iceberg.aws.AwsIntegTestUtil; @@ -42,6 +44,7 @@ import org.apache.iceberg.relocated.com.google.common.collect.Maps; import org.apache.iceberg.relocated.com.google.common.collect.Sets; import org.apache.iceberg.types.Types; +import org.assertj.core.api.Assertions; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -295,6 +298,37 @@ public void testDropNamespace() { Assert.assertFalse("namespace must not exist", response.hasItem()); } + @Test + public void testRegisterTable() { + Namespace namespace = Namespace.of(genRandomName()); + catalog.createNamespace(namespace); + TableIdentifier identifier = TableIdentifier.of(namespace, catalogTableName); + catalog.createTable(identifier, SCHEMA); + Table registeringTable = catalog.loadTable(identifier); + Assertions.assertThat(catalog.dropTable(identifier, false)).isTrue(); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((DynamoDbTableOperations) ops).currentMetadataLocation(); + Assertions.assertThat(catalog.registerTable(identifier, metadataLocation)).isNotNull(); + Assertions.assertThat(catalog.loadTable(identifier)).isNotNull(); + Assertions.assertThat(catalog.dropTable(identifier, true)).isTrue(); + Assertions.assertThat(catalog.dropNamespace(namespace)).isTrue(); + } + + @Test + public void testRegisterExistingTable() { + Namespace namespace = Namespace.of(genRandomName()); + catalog.createNamespace(namespace); + TableIdentifier identifier = TableIdentifier.of(namespace, catalogTableName); + catalog.createTable(identifier, SCHEMA); + Table registeringTable = catalog.loadTable(identifier); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((DynamoDbTableOperations) ops).currentMetadataLocation(); + Assertions.assertThatThrownBy(() -> catalog.registerTable(identifier, metadataLocation)) + .isInstanceOf(AlreadyExistsException.class); + Assertions.assertThat(catalog.dropTable(identifier, true)).isTrue(); + Assertions.assertThat(catalog.dropNamespace(namespace)).isTrue(); + } + private static String genRandomName() { return UUID.randomUUID().toString().replace("-", ""); } diff --git a/aws/src/integration/java/org/apache/iceberg/aws/glue/TestGlueCatalogTable.java b/aws/src/integration/java/org/apache/iceberg/aws/glue/TestGlueCatalogTable.java index 92b906a44944..5a057c4e6146 100644 --- a/aws/src/integration/java/org/apache/iceberg/aws/glue/TestGlueCatalogTable.java +++ b/aws/src/integration/java/org/apache/iceberg/aws/glue/TestGlueCatalogTable.java @@ -25,6 +25,7 @@ import java.util.stream.Collectors; import org.apache.iceberg.AssertHelpers; import org.apache.iceberg.BaseMetastoreTableOperations; +import org.apache.iceberg.BaseTable; import org.apache.iceberg.DataFile; import org.apache.iceberg.DataFiles; import org.apache.iceberg.PartitionSpec; @@ -42,6 +43,7 @@ import org.apache.iceberg.relocated.com.google.common.collect.Maps; import org.apache.iceberg.types.Types; import org.apache.iceberg.types.Types.NestedField; +import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Test; import software.amazon.awssdk.services.glue.model.Column; @@ -433,4 +435,33 @@ public void testTablePropsDefinedAtCatalogLevel() { "table-key5", table.properties().get("key5")); } + + @Test + public void testRegisterTable() { + String namespace = createNamespace(); + String tableName = getRandomName(); + createTable(namespace, tableName); + TableIdentifier identifier = TableIdentifier.of(namespace, tableName); + Table table = glueCatalog.loadTable(identifier); + String metadataLocation = ((BaseTable) table).operations().current().metadataFileLocation(); + Assertions.assertThat(glueCatalog.dropTable(identifier, false)).isTrue(); + Assertions.assertThat(glueCatalog.registerTable(identifier, metadataLocation)).isNotNull(); + Assertions.assertThat(glueCatalog.loadTable(identifier)).isNotNull(); + Assertions.assertThat(glueCatalog.dropTable(identifier, true)).isTrue(); + Assertions.assertThat(glueCatalog.dropNamespace(Namespace.of(namespace))).isTrue(); + } + + @Test + public void testRegisterTableAlreadyExists() { + String namespace = createNamespace(); + String tableName = getRandomName(); + createTable(namespace, tableName); + TableIdentifier identifier = TableIdentifier.of(namespace, tableName); + Table table = glueCatalog.loadTable(identifier); + String metadataLocation = ((BaseTable) table).operations().current().metadataFileLocation(); + Assertions.assertThatThrownBy(() -> glueCatalog.registerTable(identifier, metadataLocation)) + .isInstanceOf(AlreadyExistsException.class); + Assertions.assertThat(glueCatalog.dropTable(identifier, true)).isTrue(); + Assertions.assertThat(glueCatalog.dropNamespace(Namespace.of(namespace))).isTrue(); + } } diff --git a/core/src/main/java/org/apache/iceberg/BaseMetastoreCatalog.java b/core/src/main/java/org/apache/iceberg/BaseMetastoreCatalog.java index f2dc97129bee..7527bb7b58e2 100644 --- a/core/src/main/java/org/apache/iceberg/BaseMetastoreCatalog.java +++ b/core/src/main/java/org/apache/iceberg/BaseMetastoreCatalog.java @@ -25,6 +25,7 @@ import org.apache.iceberg.exceptions.AlreadyExistsException; import org.apache.iceberg.exceptions.CommitFailedException; import org.apache.iceberg.exceptions.NoSuchTableException; +import org.apache.iceberg.io.InputFile; import org.apache.iceberg.relocated.com.google.common.base.MoreObjects; import org.apache.iceberg.relocated.com.google.common.base.Preconditions; import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap; @@ -65,6 +66,26 @@ public Table loadTable(TableIdentifier identifier) { return result; } + @Override + public Table registerTable(TableIdentifier identifier, String metadataFileLocation) { + Preconditions.checkArgument( + identifier != null && isValidIdentifier(identifier), "Invalid identifier: %s", identifier); + Preconditions.checkArgument(metadataFileLocation != null && !metadataFileLocation.isEmpty(), + "Cannot register an empty metadata file location as a table"); + + // Throw an exception if this table already exists in the catalog. + if (tableExists(identifier)) { + throw new AlreadyExistsException("Table already exists: %s", identifier); + } + + TableOperations ops = newTableOps(identifier); + InputFile metadataFile = ops.io().newInputFile(metadataFileLocation); + TableMetadata metadata = TableMetadataParser.read(ops.io(), metadataFile); + ops.commit(null, metadata); + + return new BaseTable(ops, identifier.toString()); + } + @Override public TableBuilder buildTable(TableIdentifier identifier, Schema schema) { return new BaseMetastoreCatalogTableBuilder(identifier, schema); diff --git a/core/src/test/java/org/apache/iceberg/hadoop/TestHadoopCatalog.java b/core/src/test/java/org/apache/iceberg/hadoop/TestHadoopCatalog.java index 889cf2b2b449..ad696bb5a2d0 100644 --- a/core/src/test/java/org/apache/iceberg/hadoop/TestHadoopCatalog.java +++ b/core/src/test/java/org/apache/iceberg/hadoop/TestHadoopCatalog.java @@ -30,12 +30,15 @@ import org.apache.iceberg.CatalogProperties; import org.apache.iceberg.DataFile; import org.apache.iceberg.DataFiles; +import org.apache.iceberg.HasTableOperations; import org.apache.iceberg.PartitionSpec; import org.apache.iceberg.SortOrder; import org.apache.iceberg.Table; +import org.apache.iceberg.TableOperations; import org.apache.iceberg.Transaction; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.TableIdentifier; +import org.apache.iceberg.exceptions.AlreadyExistsException; import org.apache.iceberg.exceptions.NamespaceNotEmptyException; import org.apache.iceberg.exceptions.NoSuchNamespaceException; import org.apache.iceberg.exceptions.NoSuchTableException; @@ -47,6 +50,7 @@ import org.apache.iceberg.transforms.Transform; import org.apache.iceberg.transforms.Transforms; import org.apache.iceberg.types.Types; +import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Test; @@ -589,4 +593,33 @@ public void testTablePropsDefinedAtCatalogLevel() throws IOException { "table-key5", table.properties().get("key5")); } + + @Test + public void testRegisterTable() throws IOException { + TableIdentifier identifier = TableIdentifier.of("a", "t1"); + TableIdentifier identifier2 = TableIdentifier.of("a", "t2"); + HadoopCatalog catalog = hadoopCatalog(); + catalog.createTable(identifier, SCHEMA); + Table registeringTable = catalog.loadTable(identifier); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((HadoopTableOperations) ops).current().metadataFileLocation(); + Assertions.assertThat(catalog.registerTable(identifier2, metadataLocation)).isNotNull(); + Assertions.assertThat(catalog.loadTable(identifier2)).isNotNull(); + Assertions.assertThat(catalog.dropTable(identifier)).isTrue(); + Assertions.assertThat(catalog.dropTable(identifier2)).isTrue(); + } + + @Test + public void testRegisterExistingTable() throws IOException { + TableIdentifier identifier = TableIdentifier.of("a", "t1"); + HadoopCatalog catalog = hadoopCatalog(); + catalog.createTable(identifier, SCHEMA); + Table registeringTable = catalog.loadTable(identifier); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((HadoopTableOperations) ops).current().metadataFileLocation(); + Assertions.assertThatThrownBy(() -> catalog.registerTable(identifier, metadataLocation)) + .isInstanceOf(AlreadyExistsException.class) + .hasMessage("Table already exists: a.t1"); + Assertions.assertThat(catalog.dropTable(identifier)).isTrue(); + } } diff --git a/core/src/test/java/org/apache/iceberg/jdbc/TestJdbcCatalog.java b/core/src/test/java/org/apache/iceberg/jdbc/TestJdbcCatalog.java index ec8c3671aae4..42fd769d2090 100644 --- a/core/src/test/java/org/apache/iceberg/jdbc/TestJdbcCatalog.java +++ b/core/src/test/java/org/apache/iceberg/jdbc/TestJdbcCatalog.java @@ -37,10 +37,12 @@ import org.apache.iceberg.CatalogProperties; import org.apache.iceberg.DataFile; import org.apache.iceberg.DataFiles; +import org.apache.iceberg.HasTableOperations; import org.apache.iceberg.PartitionSpec; import org.apache.iceberg.Schema; import org.apache.iceberg.SortOrder; import org.apache.iceberg.Table; +import org.apache.iceberg.TableOperations; import org.apache.iceberg.Transaction; import org.apache.iceberg.catalog.CatalogTests; import org.apache.iceberg.catalog.Namespace; @@ -58,6 +60,7 @@ import org.apache.iceberg.transforms.Transform; import org.apache.iceberg.transforms.Transforms; import org.apache.iceberg.types.Types; +import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -639,4 +642,29 @@ public void testConversions() { Assert.assertEquals(ns, JdbcUtil.stringToNamespace(nsString)); } + @Test + public void testRegisterTable() { + TableIdentifier identifier = TableIdentifier.of("a", "t1"); + catalog.createTable(identifier, SCHEMA); + Table registeringTable = catalog.loadTable(identifier); + catalog.dropTable(identifier, false); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((JdbcTableOperations) ops).currentMetadataLocation(); + Assertions.assertThat(catalog.registerTable(identifier, metadataLocation)).isNotNull(); + Assertions.assertThat(catalog.loadTable(identifier)).isNotNull(); + Assertions.assertThat(catalog.dropTable(identifier)).isTrue(); + } + + @Test + public void testRegisterExistingTable() { + TableIdentifier identifier = TableIdentifier.of("a", "t1"); + catalog.createTable(identifier, SCHEMA); + Table registeringTable = catalog.loadTable(identifier); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((JdbcTableOperations) ops).currentMetadataLocation(); + Assertions.assertThatThrownBy(() -> catalog.registerTable(identifier, metadataLocation)) + .isInstanceOf(AlreadyExistsException.class) + .hasMessage("Table already exists: a.t1"); + Assertions.assertThat(catalog.dropTable(identifier)).isTrue(); + } } diff --git a/dell/src/test/java/org/apache/iceberg/dell/ecs/TestEcsCatalog.java b/dell/src/test/java/org/apache/iceberg/dell/ecs/TestEcsCatalog.java index 919af4449d9d..28c9836d8e9c 100644 --- a/dell/src/test/java/org/apache/iceberg/dell/ecs/TestEcsCatalog.java +++ b/dell/src/test/java/org/apache/iceberg/dell/ecs/TestEcsCatalog.java @@ -23,10 +23,14 @@ import java.util.Map; import org.apache.iceberg.AssertHelpers; import org.apache.iceberg.CatalogProperties; +import org.apache.iceberg.HasTableOperations; import org.apache.iceberg.Schema; +import org.apache.iceberg.Table; +import org.apache.iceberg.TableOperations; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.TableIdentifier; import org.apache.iceberg.dell.mock.ecs.EcsS3MockRule; +import org.apache.iceberg.exceptions.AlreadyExistsException; import org.apache.iceberg.exceptions.NamespaceNotEmptyException; import org.apache.iceberg.exceptions.NoSuchNamespaceException; import org.apache.iceberg.exceptions.NoSuchTableException; @@ -35,6 +39,7 @@ import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet; import org.apache.iceberg.relocated.com.google.common.collect.Maps; import org.apache.iceberg.types.Types; +import org.assertj.core.api.Assertions; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -170,4 +175,30 @@ public void testRenameTable() { Assert.assertFalse("Old table does not exist", ecsCatalog.tableExists(TableIdentifier.of("a", "t1"))); Assert.assertTrue("New table exists", ecsCatalog.tableExists(TableIdentifier.of("b", "t2"))); } + + @Test + public void testRegisterTable() { + TableIdentifier identifier = TableIdentifier.of("a", "t1"); + ecsCatalog.createTable(identifier, SCHEMA); + Table registeringTable = ecsCatalog.loadTable(identifier); + ecsCatalog.dropTable(identifier, false); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((EcsTableOperations) ops).currentMetadataLocation(); + Assertions.assertThat(ecsCatalog.registerTable(identifier, metadataLocation)).isNotNull(); + Assertions.assertThat(ecsCatalog.loadTable(identifier)).isNotNull(); + Assertions.assertThat(ecsCatalog.dropTable(identifier, true)).isTrue(); + } + + @Test + public void testRegisterExistingTable() { + TableIdentifier identifier = TableIdentifier.of("a", "t1"); + ecsCatalog.createTable(identifier, SCHEMA); + Table registeringTable = ecsCatalog.loadTable(identifier); + TableOperations ops = ((HasTableOperations) registeringTable).operations(); + String metadataLocation = ((EcsTableOperations) ops).currentMetadataLocation(); + Assertions.assertThatThrownBy(() -> ecsCatalog.registerTable(identifier, metadataLocation)) + .isInstanceOf(AlreadyExistsException.class) + .hasMessage("Table already exists: a.t1"); + Assertions.assertThat(ecsCatalog.dropTable(identifier, true)).isTrue(); + } } diff --git a/hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java b/hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java index 62c70438e6c9..4fae9ca878c8 100644 --- a/hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java +++ b/hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java @@ -36,12 +36,10 @@ import org.apache.hadoop.hive.metastore.api.UnknownDBException; import org.apache.iceberg.BaseMetastoreCatalog; import org.apache.iceberg.BaseMetastoreTableOperations; -import org.apache.iceberg.BaseTable; import org.apache.iceberg.CatalogProperties; import org.apache.iceberg.CatalogUtil; import org.apache.iceberg.ClientPool; import org.apache.iceberg.TableMetadata; -import org.apache.iceberg.TableMetadataParser; import org.apache.iceberg.TableOperations; import org.apache.iceberg.catalog.Namespace; import org.apache.iceberg.catalog.SupportsNamespaces; @@ -51,7 +49,6 @@ import org.apache.iceberg.exceptions.NoSuchTableException; import org.apache.iceberg.hadoop.HadoopFileIO; import org.apache.iceberg.io.FileIO; -import org.apache.iceberg.io.InputFile; import org.apache.iceberg.relocated.com.google.common.annotations.VisibleForTesting; import org.apache.iceberg.relocated.com.google.common.base.MoreObjects; import org.apache.iceberg.relocated.com.google.common.base.Preconditions; @@ -234,23 +231,6 @@ public void renameTable(TableIdentifier from, TableIdentifier originalTo) { } } - @Override - public org.apache.iceberg.Table registerTable(TableIdentifier identifier, String metadataFileLocation) { - Preconditions.checkArgument(isValidIdentifier(identifier), "Invalid identifier: %s", identifier); - - // Throw an exception if this table already exists in the catalog. - if (tableExists(identifier)) { - throw new org.apache.iceberg.exceptions.AlreadyExistsException("Table already exists: %s", identifier); - } - - TableOperations ops = newTableOps(identifier); - InputFile metadataFile = fileIO.newInputFile(metadataFileLocation); - TableMetadata metadata = TableMetadataParser.read(ops.io(), metadataFile); - ops.commit(null, metadata); - - return new BaseTable(ops, identifier.toString()); - } - @Override public void createNamespace(Namespace namespace, Map meta) { Preconditions.checkArgument( diff --git a/nessie/src/main/java/org/apache/iceberg/nessie/NessieTableOperations.java b/nessie/src/main/java/org/apache/iceberg/nessie/NessieTableOperations.java index b169f6e2e45c..2cbe974bdd1a 100644 --- a/nessie/src/main/java/org/apache/iceberg/nessie/NessieTableOperations.java +++ b/nessie/src/main/java/org/apache/iceberg/nessie/NessieTableOperations.java @@ -152,7 +152,8 @@ protected void doCommit(TableMetadata base, TableMetadata metadata) { } } - String newMetadataLocation = writeNewMetadata(metadata, currentVersion() + 1); + String newMetadataLocation = (base == null) && (metadata.metadataFileLocation() != null) ? + metadata.metadataFileLocation() : writeNewMetadata(metadata, currentVersion() + 1); boolean delete = true; try { diff --git a/nessie/src/test/java/org/apache/iceberg/nessie/TestNessieTable.java b/nessie/src/test/java/org/apache/iceberg/nessie/TestNessieTable.java index f46fd68247bb..9f8bda77580f 100644 --- a/nessie/src/test/java/org/apache/iceberg/nessie/TestNessieTable.java +++ b/nessie/src/test/java/org/apache/iceberg/nessie/TestNessieTable.java @@ -39,7 +39,9 @@ import org.apache.iceberg.TableOperations; import org.apache.iceberg.avro.AvroSchemaUtil; import org.apache.iceberg.catalog.TableIdentifier; +import org.apache.iceberg.exceptions.AlreadyExistsException; import org.apache.iceberg.exceptions.CommitFailedException; +import org.apache.iceberg.exceptions.NotFoundException; import org.apache.iceberg.relocated.com.google.common.collect.Lists; import org.apache.iceberg.types.Types; import org.assertj.core.api.Assertions; @@ -56,6 +58,7 @@ import org.projectnessie.model.ImmutableTableReference; import org.projectnessie.model.LogResponse.LogEntry; import org.projectnessie.model.Operation; +import org.projectnessie.model.Tag; import static org.apache.iceberg.TableMetadataParser.getFileExtension; import static org.apache.iceberg.types.Types.NestedField.optional; @@ -385,6 +388,89 @@ public void testDropTable() throws IOException { verifyCommitMetadata(); } + private void validateRegister(TableIdentifier identifier, String metadataVersionFiles) { + Assertions.assertThat(catalog.registerTable(identifier, "file:" + metadataVersionFiles)).isNotNull(); + Table newTable = catalog.loadTable(identifier); + Assertions.assertThat(newTable).isNotNull(); + TableOperations ops = ((HasTableOperations) newTable).operations(); + String metadataLocation = ((NessieTableOperations) ops).currentMetadataLocation(); + Assertions.assertThat("file:" + metadataVersionFiles).isEqualTo(metadataLocation); + Assertions.assertThat(catalog.dropTable(identifier, false)).isTrue(); + } + + @Test + public void testRegisterTableWithGivenBranch() { + List metadataVersionFiles = metadataVersionFiles(TABLE_NAME); + Assertions.assertThat(1).isEqualTo(metadataVersionFiles.size()); + ImmutableTableReference tableReference = + ImmutableTableReference.builder().reference("main").name(TABLE_NAME).build(); + TableIdentifier identifier = TableIdentifier.of(DB_NAME, tableReference.toString()); + validateRegister(identifier, metadataVersionFiles.get(0)); + } + + @Test + public void testRegisterTableFailureScenarios() throws NessieConflictException, NessieNotFoundException { + List metadataVersionFiles = metadataVersionFiles(TABLE_NAME); + Assertions.assertThat(1).isEqualTo(metadataVersionFiles.size()); + // Case 1: Branch does not exist + ImmutableTableReference defaultTableReference = + ImmutableTableReference.builder().reference("default").name(TABLE_NAME).build(); + TableIdentifier defaultIdentifier = TableIdentifier.of(DB_NAME, defaultTableReference.toString()); + Assertions.assertThatThrownBy( + () -> catalog.registerTable( + defaultIdentifier, "file:" + metadataVersionFiles.get(0))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Nessie ref 'default' does not exist"); + // Case 2: Table Already Exists + Assertions.assertThatThrownBy(() -> catalog.registerTable(TABLE_IDENTIFIER, "file:" + metadataVersionFiles.get(0))) + .isInstanceOf(AlreadyExistsException.class) + .hasMessage("Table already exists: db.tbl"); + // Case 3: Registering using a tag + ImmutableTableReference branchTableReference = + ImmutableTableReference.builder().reference(BRANCH).name(TABLE_NAME).build(); + TableIdentifier branchIdentifier = TableIdentifier.of(DB_NAME, branchTableReference.toString()); + Assertions.assertThat(catalog.dropTable(branchIdentifier, false)).isTrue(); + String hash = api.getReference().refName(BRANCH).get().getHash(); + api.createReference().sourceRefName(BRANCH).reference(Tag.of("tag_1", hash)).create(); + ImmutableTableReference tagTableReference = + ImmutableTableReference.builder().reference("tag_1").name(TABLE_NAME).build(); + TableIdentifier tagIdentifier = TableIdentifier.of(DB_NAME, tagTableReference.toString()); + Assertions.assertThatThrownBy( + () -> catalog.registerTable( + tagIdentifier, "file:" + metadataVersionFiles.get(0))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("You can only mutate tables when using a branch without a hash or timestamp."); + // Case 4: non-null metadata path with null metadata location + Assertions.assertThatThrownBy( + () -> catalog.registerTable(TABLE_IDENTIFIER, "file:" + metadataVersionFiles.get(0) + "invalidName")) + .isInstanceOf(NotFoundException.class); + // Case 5: null identifier + Assertions.assertThatThrownBy( + () -> catalog.registerTable(null, "file:" + metadataVersionFiles.get(0) + "invalidName")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Invalid identifier: null"); + } + + @Test + public void testRegisterTableWithDefaultBranch() { + List metadataVersionFiles = metadataVersionFiles(TABLE_NAME); + Assertions.assertThat(1).isEqualTo(metadataVersionFiles.size()); + Assertions.assertThat(catalog.dropTable(TABLE_IDENTIFIER, false)).isTrue(); + validateRegister(TABLE_IDENTIFIER, metadataVersionFiles.get(0)); + } + + @Test + public void testRegisterTableMoreThanOneBranch() { + List metadataVersionFiles = metadataVersionFiles(TABLE_NAME); + Assertions.assertThat(1).isEqualTo(metadataVersionFiles.size()); + ImmutableTableReference tableReference = + ImmutableTableReference.builder().reference("main").name(TABLE_NAME).build(); + TableIdentifier identifier = TableIdentifier.of(DB_NAME, tableReference.toString()); + validateRegister(identifier, metadataVersionFiles.get(0)); + Assertions.assertThat(catalog.dropTable(TABLE_IDENTIFIER, false)).isTrue(); + validateRegister(TABLE_IDENTIFIER, metadataVersionFiles.get(0)); + } + @Test public void testExistingTableUpdate() { Table icebergTable = catalog.loadTable(TABLE_IDENTIFIER);