From ff5aaf39ad616cb231c5e23e771bb31dbb5368a4 Mon Sep 17 00:00:00 2001 From: Hassan Shah Date: Wed, 30 Oct 2024 09:27:48 +0100 Subject: [PATCH] added incomplete test for drop constraint from existing table --- catalog/resource_sql_table_test.go | 151 +++++++++++++++++++++++++++++ catalog/utils.go | 42 ++++++++ 2 files changed, 193 insertions(+) diff --git a/catalog/resource_sql_table_test.go b/catalog/resource_sql_table_test.go index 851abbf397..4b93d10001 100644 --- a/catalog/resource_sql_table_test.go +++ b/catalog/resource_sql_table_test.go @@ -996,6 +996,13 @@ type resourceSqlTableUpdateColumnTestMetaData struct { expectedErrorMsg string } +type resourceSqlTableUpdateKeyConstraintTestMetaData struct { + oldKeyConstraints []SqlKeyConstraintInfo + newKeyConstraints []SqlKeyConstraintInfo + allowedCommands []string + expectedErrorMsg string +} + func resourceSqlTableUpdateColumnHelper(t *testing.T, testMetaData resourceSqlTableUpdateColumnTestMetaData) { newColumnsTemplate := GetSqlColumnInfoHCL(testMetaData.newColumns) instanceStateMap := map[string]string{ @@ -1070,6 +1077,111 @@ func resourceSqlTableUpdateColumnHelper(t *testing.T, testMetaData resourceSqlTa } } +func resourceSqlTableUpdateKeyConstraintHelper(t *testing.T, testMetaData resourceSqlTableUpdateKeyConstraintTestMetaData) { + newKeyConstraintsTemplate := GetSqlKeyConstraintInfoHCL(testMetaData.newKeyConstraints) + instanceStateMap := map[string]string{ + "name": "bar", + "catalog_name": "main", + "schema_name": "foo", + "table_type": "EXTERNAL", + "data_source_format": "DELTA", + "storage_location": "s3://ext-main/foo/bar1", + "comment": "terraform managed", + "key_constraint.#": strconv.Itoa(len(testMetaData.oldKeyConstraints)), + } + for k, v := range getKeyConstraintsInstanceState(testMetaData.oldKeyConstraints) { + instanceStateMap[k] = v + } + d, err := qa.ResourceFixture{ + CommandMock: func(commandStr string) common.CommandResults { + assert.True(t, slices.Contains(testMetaData.allowedCommands, commandStr)) + return common.CommandResults{ + ResultType: "", + Data: nil, + } + }, + HCL: fmt.Sprintf(` + name = "bar" + catalog_name = "main" + schema_name = "foo" + table_type = "EXTERNAL" + data_source_format = "DELTA" + storage_location = "s3://ext-main/foo/bar1" + comment = "terraform managed" + cluster_id = "gone" + %s + `, newKeyConstraintsTemplate), + InstanceState: instanceStateMap, + Fixtures: append([]qa.HTTPFixture{ + { + Method: "GET", + Resource: "/api/2.1/unity-catalog/tables/main.foo.bar", + ReuseRequest: true, + Response: SqlTableInfo{ + Name: "bar", + CatalogName: "main", + SchemaName: "foo", + TableType: "EXTERNAL", + DataSourceFormat: "DELTA", + StorageLocation: "s3://ext-main/foo/bar1", + StorageCredentialName: "somecred", + Comment: "terraform managed", + KeyConstraintInfos: testMetaData.oldKeyConstraints, + }, + }, + { + Method: "POST", + Resource: "/api/2.0/clusters/start", + ExpectedRequest: clusters.ClusterID{ + ClusterID: "gone", + }, + Status: 404, + }, + }, createClusterForSql...), + Resource: ResourceSqlTable(), + ID: "main.foo.bar", + Update: true, + }.Apply(t) + + if testMetaData.expectedErrorMsg != "" { + assert.EqualError(t, err, testMetaData.expectedErrorMsg) + } else { + assert.NoError(t, err) + assert.Equal(t, "bar", d.Get("name")) + } +} + +func getKeyConstraintsInstanceState(keyConstraints []SqlKeyConstraintInfo) map[string]string { + res := make(map[string]string) + for i, kci := range keyConstraints { + switch kci.SqlKeyConstraint.(type) { + case SqlPrimaryKeyConstraint: + var pkci = kci.SqlKeyConstraint.(SqlPrimaryKeyConstraint) + name := fmt.Sprintf("key_constraint.%d.name", i) + primaryKey := fmt.Sprintf("key_constraint.%d.primary_key", i) + rely := fmt.Sprintf("key_constraint.%d.rely", i) + res[name] = pkci.Name + res[primaryKey] = pkci.PrimaryKey + res[rely] = strconv.FormatBool(pkci.Rely) + case SqlForeignKeyConstraint: + var fkci = kci.SqlKeyConstraint.(SqlForeignKeyConstraint) + name := fmt.Sprintf("key_constraint.%d.name", i) + referencedKey := fmt.Sprintf("key_constraint.%d.referenced_key", i) + referencedCatalog := fmt.Sprintf("key_constraint.%d.referenced_catalog", i) + referencedSchema := fmt.Sprintf("key_constraint.%d.referenced_schema", i) + referencedTable := fmt.Sprintf("key_constraint.%d.referenced_table", i) + referencedForeignKey := fmt.Sprintf("key_constraint.%d.referenced_foreign_key", i) + res[name] = fkci.Name + res[referencedKey] = fkci.ReferencedKey + res[referencedCatalog] = fkci.ReferencedCatalog + res[referencedSchema] = fkci.ReferencedSchema + res[referencedTable] = fkci.ReferencedTable + res[referencedForeignKey] = fkci.ReferencedForeignKey + } + } + return res +} + func TestResourceSqlTableUpdateTable_Columns(t *testing.T) { resourceSqlTableUpdateColumnHelper(t, resourceSqlTableUpdateColumnTestMetaData{ @@ -1109,6 +1221,45 @@ func TestResourceSqlTableUpdateTable_Columns(t *testing.T) { ) } +func TestResourceSqlTableUpdateTable_KeyConstraints(t *testing.T) { + resourceSqlTableUpdateKeyConstraintHelper(t, + resourceSqlTableUpdateKeyConstraintTestMetaData{ + oldKeyConstraints: []SqlKeyConstraintInfo{ + { + SqlPrimaryKeyConstraint{ + Name: "pk", + PrimaryKey: "id", + Rely: true, + }, + }, + { + SqlForeignKeyConstraint{ + Name: "external_id_fk", + ReferencedKey: "external_id", + ReferencedCatalog: "somecatalog", + ReferencedSchema: "someschema", + ReferencedTable: "someothertable", + ReferencedForeignKey: "id", + }, + }, + }, + newKeyConstraints: []SqlKeyConstraintInfo{ + { + SqlPrimaryKeyConstraint{ + Name: "pk", + PrimaryKey: "id", + Rely: true, + }, + }, + }, + allowedCommands: []string{ + "ALTER TABLE bar DROP CONSTRAINT `external_id_fk`", + }, + expectedErrorMsg: "", + }, + ) +} + func TestResourceSqlTableUpdateTable_ColumnsTypeThrowsError(t *testing.T) { resourceSqlTableUpdateColumnHelper(t, resourceSqlTableUpdateColumnTestMetaData{ diff --git a/catalog/utils.go b/catalog/utils.go index f71edba30e..920ebaf255 100644 --- a/catalog/utils.go +++ b/catalog/utils.go @@ -48,6 +48,48 @@ func GetSqlColumnInfoHCL(columnInfos []SqlColumnInfo) string { return columnsTemplate } +// Given a slice of SqlKeyConstraintInfo, construct the corresponding HCL string. +func GetSqlKeyConstraintInfoHCL(keyConstraintInfos []SqlKeyConstraintInfo) string { + keyConstraintsTemplate := "" + + for _, kci := range keyConstraintInfos { + switch kci.SqlKeyConstraint.(type) { + case SqlPrimaryKeyConstraint: + pkci := kci.SqlKeyConstraint.(SqlPrimaryKeyConstraint) + pkciTemplate := fmt.Sprintf( + ` + { + key_constraint { + name = "%s" + primary_key = "%s" + rely = %t + } + } + `, pkci.Name, pkci.PrimaryKey, pkci.Rely, + ) + keyConstraintsTemplate += pkciTemplate + case SqlForeignKeyConstraint: + fkci := kci.SqlKeyConstraint.(SqlForeignKeyConstraint) + fkciTemplate := fmt.Sprintf( + ` + { + key_constraint { + name = "%s" + referenced_key = "%s" + referenced_catalog = "%s" + referenced_schema = "%s" + referenced_table = "%s" + referenced_foreign_key = "%s" + } + } + `, fkci.Name, fkci.ReferencedKey, fkci.ReferencedCatalog, fkci.ReferencedSchema, fkci.ReferencedTable, fkci.ReferencedForeignKey, + ) + keyConstraintsTemplate += fkciTemplate + } + } + return keyConstraintsTemplate +} + // check if a UC resource needs the additional update call during create operation func updateRequired(d *schema.ResourceData, updateOnly []string) bool { for _, key := range updateOnly {