diff --git a/metacat-client/src/main/java/com/netflix/metacat/client/api/ParentChildRelV1.java b/metacat-client/src/main/java/com/netflix/metacat/client/api/ParentChildRelV1.java index 546030f69..b946c50c4 100644 --- a/metacat-client/src/main/java/com/netflix/metacat/client/api/ParentChildRelV1.java +++ b/metacat-client/src/main/java/com/netflix/metacat/client/api/ParentChildRelV1.java @@ -7,7 +7,8 @@ import javax.ws.rs.PathParam; import javax.ws.rs.core.MediaType; -import com.netflix.metacat.common.dto.notifications.ChildInfoDto; +import com.netflix.metacat.common.dto.ChildInfoDto; +import com.netflix.metacat.common.dto.ParentInfoDto; import java.util.Set; @@ -40,4 +41,24 @@ Set getChildren( @PathParam("table-name") String tableName ); + + /** + * Return the list of parent. + * @param catalogName catalogName + * @param databaseName databaseName + * @param tableName tableName + * @return list of parent info dtos + */ + @GET + @Path("parents/catalog/{catalog-name}/database/{database-name}/table/{table-name}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + Set getParents( + @PathParam("catalog-name") + String catalogName, + @PathParam("database-name") + String databaseName, + @PathParam("table-name") + String tableName + ); } diff --git a/metacat-common-server/src/main/java/com/netflix/metacat/common/server/converter/ConverterUtil.java b/metacat-common-server/src/main/java/com/netflix/metacat/common/server/converter/ConverterUtil.java index 5ad54ace8..9307a7602 100644 --- a/metacat-common-server/src/main/java/com/netflix/metacat/common/server/converter/ConverterUtil.java +++ b/metacat-common-server/src/main/java/com/netflix/metacat/common/server/converter/ConverterUtil.java @@ -33,7 +33,8 @@ import com.netflix.metacat.common.dto.Sort; import com.netflix.metacat.common.dto.StorageDto; import com.netflix.metacat.common.dto.TableDto; -import com.netflix.metacat.common.dto.notifications.ChildInfoDto; +import com.netflix.metacat.common.dto.ChildInfoDto; +import com.netflix.metacat.common.dto.ParentInfoDto; import com.netflix.metacat.common.server.connectors.ConnectorRequestContext; import com.netflix.metacat.common.server.connectors.model.AuditInfo; import com.netflix.metacat.common.server.connectors.model.CatalogInfo; @@ -48,6 +49,7 @@ import com.netflix.metacat.common.server.connectors.model.StorageInfo; import com.netflix.metacat.common.server.connectors.model.TableInfo; import com.netflix.metacat.common.server.model.ChildInfo; +import com.netflix.metacat.common.server.model.ParentInfo; import lombok.NonNull; import org.dozer.CustomConverter; import org.dozer.DozerBeanMapper; @@ -287,4 +289,14 @@ public PartitionsSaveResponseDto toPartitionsSaveResponseDto(final PartitionsSav public ChildInfoDto toChildInfoDto(final ChildInfo childInfo) { return mapper.map(childInfo, ChildInfoDto.class); } + + /** + * Convert ParentInfo to ParentInfoDto. + * + * @param parentInfo parentInfo + * @return parentInfo dto + */ + public ParentInfoDto toParentInfoDto(final ParentInfo parentInfo) { + return mapper.map(parentInfo, ParentInfoDto.class); + } } diff --git a/metacat-common-server/src/main/java/com/netflix/metacat/common/server/usermetadata/ParentChildRelMetadataService.java b/metacat-common-server/src/main/java/com/netflix/metacat/common/server/usermetadata/ParentChildRelMetadataService.java index 3488478ee..8fbc66826 100644 --- a/metacat-common-server/src/main/java/com/netflix/metacat/common/server/usermetadata/ParentChildRelMetadataService.java +++ b/metacat-common-server/src/main/java/com/netflix/metacat/common/server/usermetadata/ParentChildRelMetadataService.java @@ -1,6 +1,7 @@ package com.netflix.metacat.common.server.usermetadata; import com.netflix.metacat.common.QualifiedName; -import com.netflix.metacat.common.dto.notifications.ChildInfoDto; +import com.netflix.metacat.common.dto.ChildInfoDto; +import com.netflix.metacat.common.dto.ParentInfoDto; import com.netflix.metacat.common.server.model.ChildInfo; import com.netflix.metacat.common.server.model.ParentInfo; @@ -98,12 +99,19 @@ Set getChildren( /** * get the set of children dto for the input name. * @param name name - * @return a set of ChildInfo + * @return a set of ChildInfo dto */ Set getChildrenDto( QualifiedName name ); + /** + * get the set of parent dto for the input name. + * @param name name + * @return a set of parentInfo dto + */ + Set getParentsDto(QualifiedName name); + /** * return whether the table is a parent. * @param tableName tableName diff --git a/metacat-common/src/main/java/com/netflix/metacat/common/dto/notifications/ChildInfoDto.java b/metacat-common/src/main/java/com/netflix/metacat/common/dto/ChildInfoDto.java similarity index 85% rename from metacat-common/src/main/java/com/netflix/metacat/common/dto/notifications/ChildInfoDto.java rename to metacat-common/src/main/java/com/netflix/metacat/common/dto/ChildInfoDto.java index bf150c4af..faadfdcdf 100644 --- a/metacat-common/src/main/java/com/netflix/metacat/common/dto/notifications/ChildInfoDto.java +++ b/metacat-common/src/main/java/com/netflix/metacat/common/dto/ChildInfoDto.java @@ -1,6 +1,5 @@ -package com.netflix.metacat.common.dto.notifications; +package com.netflix.metacat.common.dto; -import com.netflix.metacat.common.dto.BaseDto; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; @@ -9,7 +8,7 @@ import lombok.NoArgsConstructor; /** - * ChildInfo information. + * ChildInfo dto information. */ @SuppressWarnings("unused") @Data diff --git a/metacat-common/src/main/java/com/netflix/metacat/common/dto/ParentInfoDto.java b/metacat-common/src/main/java/com/netflix/metacat/common/dto/ParentInfoDto.java new file mode 100644 index 000000000..e917eb2c1 --- /dev/null +++ b/metacat-common/src/main/java/com/netflix/metacat/common/dto/ParentInfoDto.java @@ -0,0 +1,30 @@ +package com.netflix.metacat.common.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * ParentInfo dto information. + */ +@SuppressWarnings("unused") +@Data +@EqualsAndHashCode(callSuper = false) +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ParentInfoDto extends BaseDto { + private static final long serialVersionUID = 8121239864203088788L; + /* Name of the parent */ + @ApiModelProperty(value = "name of the child") + private String name; + /* Type of the relation */ + @ApiModelProperty(value = "type of the relation") + private String relationType; + /* uuid of the table */ + @ApiModelProperty(value = "uuid of the table") + private String uuid; +} diff --git a/metacat-functional-tests/src/functionalTest/groovy/com/netflix/metacat/MetacatSmokeSpec.groovy b/metacat-functional-tests/src/functionalTest/groovy/com/netflix/metacat/MetacatSmokeSpec.groovy index ebe615575..c7193abd6 100644 --- a/metacat-functional-tests/src/functionalTest/groovy/com/netflix/metacat/MetacatSmokeSpec.groovy +++ b/metacat-functional-tests/src/functionalTest/groovy/com/netflix/metacat/MetacatSmokeSpec.groovy @@ -24,7 +24,6 @@ import com.netflix.metacat.client.api.PartitionV1 import com.netflix.metacat.client.api.TagV1 import com.netflix.metacat.common.QualifiedName import com.netflix.metacat.common.dto.* -import com.netflix.metacat.common.dto.notifications.ChildInfoDto import com.netflix.metacat.common.exception.MetacatAlreadyExistsException import com.netflix.metacat.common.exception.MetacatBadRequestException import com.netflix.metacat.common.exception.MetacatNotFoundException @@ -2050,6 +2049,7 @@ class MetacatSmokeSpec extends Specification { // Test Parent 1 parentChildInfo assert parent1Table.definitionMetadata.get("parentChildRelationInfo").get("isParent").booleanValue() assert parentChildRelV1.getChildren(catalogName, databaseName, parent1) == [new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid")] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2057,6 +2057,7 @@ class MetacatSmokeSpec extends Specification { JSONAssert.assertEquals(child11Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE", "uuid":"p1_uuid"}]}', false) + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() /* @@ -2078,6 +2079,7 @@ class MetacatSmokeSpec extends Specification { assert parentChildRelV1.getChildren(catalogName, databaseName, parent1) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid"), ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") assert child11Table.definitionMetadata.get("random_key").asText() == "random_value" @@ -2085,6 +2087,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE", "uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set /* Step 3: create another table with the same child1 name but different uuid under the same parent should fail @@ -2146,6 +2149,7 @@ class MetacatSmokeSpec extends Specification { // Test Parent 1 parentChildInfo assert parent1Table.definitionMetadata.get("parentChildRelationInfo").get("isParent").booleanValue() assert parentChildRelV1.getChildren(catalogName, databaseName, parent1) == [new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid")] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2154,6 +2158,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE", "uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set /* @@ -2174,6 +2179,7 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent1).isEmpty() // Test Child12 parentChildInfo assert !child12Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2181,6 +2187,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child12).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child12) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set /* Step 8: create a parent table on top of another parent table should fail @@ -2229,12 +2236,14 @@ class MetacatSmokeSpec extends Specification { assert parentChildRelV1.getChildren(catalogName, databaseName, parent2) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child21", "CLONE", "c21_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent2).isEmpty() // Test Child21 parentChildInfo JSONAssert.assertEquals(child21Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent2","relationType":"CLONE","uuid":"p2_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child21).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child21) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent2", "CLONE", "p2_uuid")] as Set /* Step 11: Create a table newParent1 without any parent child rel info @@ -2261,6 +2270,7 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") assert child11Table.definitionMetadata.get("random_key").asText() == "random_value" @@ -2268,12 +2278,14 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE", "uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set // Test Child12 parentChildInfo assert !child12Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child12Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child12).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child12) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set /* Step 12: Attempt to rename parent1 to parent2 which has parent child relationship and should fail @@ -2298,6 +2310,7 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") assert child11Table.definitionMetadata.get("random_key").asText() == "random_value" @@ -2305,6 +2318,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent1","relationType":"CLONE", "uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set // Test Child12 parentChildInfo assert !child12Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child12Table.definitionMetadata.get("parentChildRelationInfo").toString(), @@ -2321,6 +2335,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent2","relationType":"CLONE","uuid":"p2_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child21).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child12) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent1", "CLONE", "p1_uuid")] as Set /* @@ -2341,12 +2356,14 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child11Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set // Test Child12 parentChildInfo assert !child12Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2354,6 +2371,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child12).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child12) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set //get the parent oldName should fail as it no longer exists when: @@ -2387,12 +2405,14 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child11", "CLONE", "c11_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child11Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set // Test Child12 parentChildInfo assert !child12Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2400,6 +2420,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child12).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child12) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set /* Step 15: Create a table renameChild11 with parent childInfo and then try to rename child11 to renameChild11, which should fail @@ -2430,24 +2451,28 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_child11", "CLONE", "random_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() // Test Child11 parentChildInfo assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child11Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set // Test Child12 parentChildInfo assert !child12Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child12Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child12).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child12) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set // Test renameChild11Table parentChildInfo assert !renameChild11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(renameChild11Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, renameChild11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, renameChild11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set /* @@ -2466,6 +2491,7 @@ class MetacatSmokeSpec extends Specification { new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_child11", "CLONE", "c11_uuid"), new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() // Test Child11 parentChildInfo with newName assert !child11Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") assert child11Table.definitionMetadata.get("random_key").asText() == "random_value" @@ -2473,6 +2499,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/rename_parent1","relationType":"CLONE","uuid":"p1_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, renameChild11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, renameChild11) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/rename_parent1", "CLONE", "p1_uuid")] as Set //get the child oldName should fail as it no longer exists when: @@ -2504,6 +2531,7 @@ class MetacatSmokeSpec extends Specification { assert parentChildRelV1.getChildren(catalogName, databaseName, renameParent1) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() /* Step 19: Create renameChild11 and should expect random_key should appear at it is reattached @@ -2518,13 +2546,14 @@ class MetacatSmokeSpec extends Specification { then: assert !child11Table.definitionMetadata.has("parentChildRelationInfo") assert child11Table.definitionMetadata.get("random_key").asText() == "random_value" - assert parentChildRelV1.getChildren(catalogName, databaseName, child11).isEmpty() - + assert parentChildRelV1.getChildren(catalogName, databaseName, renameChild11).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, renameChild11).isEmpty() // Test parent1 Table still only have child12 assert parent1Table.definitionMetadata.get("parentChildRelationInfo").get("isParent").booleanValue() assert parentChildRelV1.getChildren(catalogName, databaseName, renameParent1) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child12", "CLONE", "c12_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() /* Step 20: Drop child12 should succeed @@ -2535,6 +2564,7 @@ class MetacatSmokeSpec extends Specification { then: assert !parent1Table.definitionMetadata.has("parentChildRelationInfo") assert parentChildRelV1.getChildren(catalogName, databaseName, renameParent1).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() /* Step 21: Drop renameParent1 should succeed as there is no more child under it @@ -2545,6 +2575,9 @@ class MetacatSmokeSpec extends Specification { child21Table = api.getTable(catalogName, databaseName, child21, true, true, false) then: + //Since renameParent1 table is dropped + assert parentChildRelV1.getChildren(catalogName, databaseName, renameParent1).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, renameParent1).isEmpty() // Since all the operations above are on the first connected relationship, the second connected relationship // should remain the same // Test Parent 2 parentChildInfo @@ -2552,6 +2585,7 @@ class MetacatSmokeSpec extends Specification { assert parentChildRelV1.getChildren(catalogName, databaseName, parent2) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child21", "CLONE", "c21_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent2).isEmpty() // Test Child21 parentChildInfo assert !child21Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2559,6 +2593,7 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent2","relationType":"CLONE","uuid":"p2_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child21).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child21) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent2", "CLONE", "p2_uuid")] as Set /* Step 22: update parent2 with random parentChildRelationInfo to test immutability @@ -2575,13 +2610,14 @@ class MetacatSmokeSpec extends Specification { assert parentChildRelV1.getChildren(catalogName, databaseName, parent2) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child21", "CLONE", "c21_uuid") ] as Set - + assert parentChildRelV1.getParents(catalogName, databaseName, parent2).isEmpty() // Test Child21 parentChildInfo assert !child21Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") JSONAssert.assertEquals(child21Table.definitionMetadata.get("parentChildRelationInfo").toString(), '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent2","relationType":"CLONE","uuid":"p2_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child21).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child21) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent2", "CLONE", "p2_uuid")] as Set /* Step 23: update child21 with random parentChildRelationInfo to test immutability @@ -2599,6 +2635,7 @@ class MetacatSmokeSpec extends Specification { assert parentChildRelV1.getChildren(catalogName, databaseName, parent2) == [ new ChildInfoDto("embedded-fast-hive-metastore/iceberg_db/child21", "CLONE", "c21_uuid") ] as Set + assert parentChildRelV1.getParents(catalogName, databaseName, parent2).isEmpty() // Test Child21 parentChildInfo assert !child21Table.definitionMetadata.get("parentChildRelationInfo").has("isParent") @@ -2606,5 +2643,6 @@ class MetacatSmokeSpec extends Specification { '{"parentInfos":[{"name":"embedded-fast-hive-metastore/iceberg_db/parent2","relationType":"CLONE","uuid":"p2_uuid"}]}', false) assert parentChildRelV1.getChildren(catalogName, databaseName, child21).isEmpty() + assert parentChildRelV1.getParents(catalogName, databaseName, child21) == [new ParentInfoDto("embedded-fast-hive-metastore/iceberg_db/parent2", "CLONE", "p2_uuid")] as Set } } diff --git a/metacat-main/src/main/java/com/netflix/metacat/main/api/v1/ParentChildRelController.java b/metacat-main/src/main/java/com/netflix/metacat/main/api/v1/ParentChildRelController.java index 6a43a70d2..6eff65f48 100644 --- a/metacat-main/src/main/java/com/netflix/metacat/main/api/v1/ParentChildRelController.java +++ b/metacat-main/src/main/java/com/netflix/metacat/main/api/v1/ParentChildRelController.java @@ -1,7 +1,8 @@ package com.netflix.metacat.main.api.v1; import com.netflix.metacat.common.QualifiedName; -import com.netflix.metacat.common.dto.notifications.ChildInfoDto; +import com.netflix.metacat.common.dto.ChildInfoDto; +import com.netflix.metacat.common.dto.ParentInfoDto; import com.netflix.metacat.common.server.usermetadata.ParentChildRelMetadataService; import com.netflix.metacat.main.api.RequestWrapper; import io.swagger.annotations.Api; @@ -72,4 +73,35 @@ public Set getChildren( ) ); } + + /** + * Return the list of children for a given table. + * @param catalogName catalogName + * @param databaseName databaseName + * @param tableName tableName + * @return list of childInfoDto + */ + @RequestMapping(method = RequestMethod.GET, + path = "/parents/catalog/{catalog-name}/database/{database-name}/table/{table-name}") + @ResponseStatus(HttpStatus.OK) + @ApiOperation( + position = 1, + value = "Returns the parents", + notes = "Returns the parents" + ) + public Set getParents( + @ApiParam(value = "The name of the catalog", required = true) + @PathVariable("catalog-name") final String catalogName, + @ApiParam(value = "The name of the database", required = true) + @PathVariable("database-name") final String databaseName, + @ApiParam(value = "The name of the table", required = true) + @PathVariable("table-name") final String tableName + ) { + return this.requestWrapper.processRequest( + "ParentChildRelV1Resource.getParents", + () -> this.parentChildRelMetadataService.getParentsDto( + QualifiedName.ofTable(catalogName, databaseName, tableName) + ) + ); + } } diff --git a/metacat-metadata-mysql/src/main/java/com/netflix/metacat/metadata/mysql/MySqlParentChildRelMetaDataService.java b/metacat-metadata-mysql/src/main/java/com/netflix/metacat/metadata/mysql/MySqlParentChildRelMetaDataService.java index ee333abab..69f9224b6 100644 --- a/metacat-metadata-mysql/src/main/java/com/netflix/metacat/metadata/mysql/MySqlParentChildRelMetaDataService.java +++ b/metacat-metadata-mysql/src/main/java/com/netflix/metacat/metadata/mysql/MySqlParentChildRelMetaDataService.java @@ -1,7 +1,8 @@ package com.netflix.metacat.metadata.mysql; import com.netflix.metacat.common.QualifiedName; -import com.netflix.metacat.common.dto.notifications.ChildInfoDto; +import com.netflix.metacat.common.dto.ChildInfoDto; +import com.netflix.metacat.common.dto.ParentInfoDto; import com.netflix.metacat.common.server.converter.ConverterUtil; import com.netflix.metacat.common.server.model.ChildInfo; import com.netflix.metacat.common.server.model.ParentInfo; @@ -293,6 +294,12 @@ public Set getChildrenDto(final QualifiedName name) { .map(converterUtil::toChildInfoDto).collect(Collectors.toSet()); } + @Override + public Set getParentsDto(final QualifiedName name) { + return getParents(name).stream() + .map(converterUtil::toParentInfoDto).collect(Collectors.toSet()); + } + @Override public boolean isParentTable(final QualifiedName tableName) { return tableExist(tableName.toString(), SQL_IS_PARENT_TABLE);