Repository: apache/iceberg-go
Pull request #312 (2025-02-20 21:44:48)

feat(catalog/glue): add checkNamespaceExist
Hi team,
Its a smaller PR this time round. I did a check in the https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/glue but couldnt find any method to directly check namespace's existance. Hence, I borrow similar logic from `DropNamespace` where we also check if a namespace exists before deleting it


Patch:
diff --git a/README.md b/README.md
index 90a3b20..4a5fe13 100644
--- a/README.md
+++ b/README.md
@@ -72,7 +72,7 @@ $ cd iceberg-go/cmd/iceberg && go build .
 | Alter Table              |      |      |          |      |  X  |
 | Set Table Properties     |  X   |      |          |      |  X  |
 | Create Namespace         |  X   |      |          |  X   |  X  |
-| Check Namespace Exists   |  X   |      |          |      |  X  |
+| Check Namespace Exists   |  X   |      |          |  X   |  X  |
 | Drop Namespace           |  X   |      |          |  X   |  X  |
 | Set Namespace Properties |  X   |      |          |  X   |  X  |
 | List View                |  X   |      |          |      |     |
diff --git a/catalog/glue/glue.go b/catalog/glue/glue.go
index a94aa1c..5b9cb0e 100644
--- a/catalog/glue/glue.go
+++ b/catalog/glue/glue.go
@@ -365,6 +365,19 @@ func (c *Catalog) CreateNamespace(ctx context.Context, namespace table.Identifie
 	return nil
 }
 
+func (c *Catalog) CheckNamespaceExists(ctx context.Context, namespace table.Identifier) (bool, error) {
+	databaseName, err := identifierToGlueDatabase(namespace)
+	if err != nil {
+		return false, err
+	}
+
+	_, err = c.getDatabase(ctx, databaseName)
+	if err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
 // DropNamespace deletes an Iceberg namespace from the Glue catalog.
 func (c *Catalog) DropNamespace(ctx context.Context, namespace table.Identifier) error {
 	databaseName, err := identifierToGlueDatabase(namespace)


Test patch:
diff --git a/catalog/glue/glue_test.go b/catalog/glue/glue_test.go
index d8afd1e..2c6516f 100644
--- a/catalog/glue/glue_test.go
+++ b/catalog/glue/glue_test.go
@@ -396,6 +396,47 @@ func TestGlueDropNamespace(t *testing.T) {
 	assert.NoError(err)
 }
 
+func TestGlueCheckNamespaceExists(t *testing.T) {
+	assert := require.New(t)
+	mockGlueSvc := &mockGlueClient{}
+	mockGlueSvc.On("GetDatabase", mock.Anything, &glue.GetDatabaseInput{
+		Name: aws.String("test_namespace"),
+	}, mock.Anything).Return(&glue.GetDatabaseOutput{
+		Database: &types.Database{
+			Name: aws.String("test_namespace"),
+			Parameters: map[string]string{
+				"database_type": "ICEBERG",
+			},
+		},
+	}, nil).Once()
+	glueCatalog := &Catalog{
+		glueSvc: mockGlueSvc,
+	}
+	exists, err := glueCatalog.CheckNamespaceExists(context.TODO(), DatabaseIdentifier("test_namespace"))
+	assert.NoError(err)
+	assert.True(exists)
+
+}
+
+func TestGlueCheckNamespaceNotExists(t *testing.T) {
+	assert := require.New(t)
+	mockGlueSvc := &mockGlueClient{}
+
+	mockGlueSvc.On("GetDatabase", mock.Anything, &glue.GetDatabaseInput{
+		Name: aws.String("nonexistent_namespace"),
+	}, mock.Anything).Return(&glue.GetDatabaseOutput{},
+		&types.EntityNotFoundException{Message: aws.String("Database not found")}).Once()
+
+	glueCatalog := &Catalog{
+		glueSvc: mockGlueSvc,
+	}
+
+	exists, err := glueCatalog.CheckNamespaceExists(context.TODO(), DatabaseIdentifier("nonexistent_namespace"))
+	assert.Error(err)
+	assert.False(exists)
+	assert.ErrorContains(err, "Database not found")
+}
+
 func TestGlueUpdateNamespaceProperties(t *testing.T) {
 	tests := []struct {
 		name        string