nryanov opened a new issue, #13263: URL: https://github.com/apache/iceberg/issues/13263
### Proposed Change Not sure that i've chose a category correctly but this issue with spec doesn't seem like a bug. ### Motivation Current generated server-side code seems to be hard to use because existing components for TableUpdate & ViewUpdate do not use it's discriminator as they should. ### Current behavior Currently in openapi spec there is three components for updates: - table update - view update - base update ``` TableUpdate: anyOf: - $ref: '#/components/schemas/AssignUUIDUpdate' - ... ViewUpdate: anyOf: - $ref: '#/components/schemas/AssignUUIDUpdate' - ... BaseUpdate: discriminator: propertyName: action mapping: assign-uuid: '#/components/schemas/AssignUUIDUpdate' upgrade-format-version: '#/components/schemas/UpgradeFormatVersionUpdate' add-schema: '#/components/schemas/AddSchemaUpdate' set-current-schema: '#/components/schemas/SetCurrentSchemaUpdate' add-spec: '#/components/schemas/AddPartitionSpecUpdate' set-default-spec: '#/components/schemas/SetDefaultSpecUpdate' add-sort-order: '#/components/schemas/AddSortOrderUpdate' set-default-sort-order: '#/components/schemas/SetDefaultSortOrderUpdate' add-snapshot: '#/components/schemas/AddSnapshotUpdate' set-snapshot-ref: '#/components/schemas/SetSnapshotRefUpdate' remove-snapshots: '#/components/schemas/RemoveSnapshotsUpdate' remove-snapshot-ref: '#/components/schemas/RemoveSnapshotRefUpdate' set-location: '#/components/schemas/SetLocationUpdate' set-properties: '#/components/schemas/SetPropertiesUpdate' remove-properties: '#/components/schemas/RemovePropertiesUpdate' add-view-version: '#/components/schemas/AddViewVersionUpdate' set-current-view-version: '#/components/schemas/SetCurrentViewVersionUpdate' set-statistics: '#/components/schemas/SetStatisticsUpdate' remove-statistics: '#/components/schemas/RemoveStatisticsUpdate' set-partition-statistics: '#/components/schemas/SetPartitionStatisticsUpdate' remove-partition-statistics: '#/components/schemas/RemovePartitionStatisticsUpdate' remove-partition-specs: '#/components/schemas/RemovePartitionSpecsUpdate' enable-row-lineage: '#/components/schemas/EnableRowLineageUpdate' type: object required: - action properties: action: type: string ``` When server side code is generated using this spec then, for example, TableUpdate class will look like this: ``` @org.eclipse.microprofile.openapi.annotations.media.Schema(description="") @JsonTypeName("TableUpdate") @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen", comments = "Generator version: 7.12.0") public class IcebergTableUpdateDto { private String action; private Integer formatVersion; private IcebergSchemaDto schema; private Integer lastColumnId; private Integer schemaId; private IcebergPartitionSpecDto spec; private Integer specId; private IcebergSortOrderDto sortOrder; private Integer sortOrderId; private IcebergSnapshotDto snapshot; private String refName; private TypeEnum type; private Long snapshotId; private Long maxRefAgeMs; private Long maxSnapshotAgeMs; private Integer minSnapshotsToKeep; private List<Long> snapshotIds = new ArrayList<>(); private String location; private Map<String, String> updates = new HashMap<>(); private List<String> removals = new ArrayList<>(); private IcebergStatisticsFileDto statistics; private List<Integer> specIds = new ArrayList<>(); /* other methods */ } ``` The issue here is that it seems not possible to use this class to correctly handle TableUpdates in `CommitTableRequest` because this class doesn't use discriminator (`action` field as it should). In the meantime, there is `TableRequirement` (and `ViewRequirement`) which looks like: ``` TableRequirement: type: object discriminator: propertyName: type mapping: assert-create: '#/components/schemas/AssertCreate' assert-table-uuid: '#/components/schemas/AssertTableUUID' assert-ref-snapshot-id: '#/components/schemas/AssertRefSnapshotId' assert-last-assigned-field-id: '#/components/schemas/AssertLastAssignedFieldId' assert-current-schema-id: '#/components/schemas/AssertCurrentSchemaId' assert-last-assigned-partition-id: '#/components/schemas/AssertLastAssignedPartitionId' assert-default-spec-id: '#/components/schemas/AssertDefaultSpecId' assert-default-sort-order-id: '#/components/schemas/AssertDefaultSortOrderId' properties: type: type: string required: - type ``` and generated class will be: ``` @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = IcebergAssertCreateDto.class, name = "assert-create"), @JsonSubTypes.Type(value = IcebergAssertCurrentSchemaIdDto.class, name = "assert-current-schema-id"), @JsonSubTypes.Type(value = IcebergAssertDefaultSortOrderIdDto.class, name = "assert-default-sort-order-id"), @JsonSubTypes.Type(value = IcebergAssertDefaultSpecIdDto.class, name = "assert-default-spec-id"), @JsonSubTypes.Type(value = IcebergAssertLastAssignedFieldIdDto.class, name = "assert-last-assigned-field-id"), @JsonSubTypes.Type(value = IcebergAssertLastAssignedPartitionIdDto.class, name = "assert-last-assigned-partition-id"), @JsonSubTypes.Type(value = IcebergAssertRefSnapshotIdDto.class, name = "assert-ref-snapshot-id"), @JsonSubTypes.Type(value = IcebergAssertTableUUIDDto.class, name = "assert-table-uuid"), }) @org.eclipse.microprofile.openapi.annotations.media.Schema(description="") @JsonTypeName("TableRequirement") @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen", comments = "Generator version: 7.12.0") public class IcebergTableRequirementDto { private String type; /* other stuff */ } ``` And there will be some subclasses of `IcebergTableRequirementDto` which can be determined using `type` field. ### Desired behavior Desired behavior is to get almost the same result as if it was `TableRequirement`. If this part of spec will be changed then it will give these benefits: - Generated classes will be possible to use in a generic way to determine which action should be applied - ViewUpdate and TableUpdate will not share same parts like it is now in BaseUpdate (there are components which applied either to view or table only) Final result for the `TableUpdate` may look like this: ``` TableUpdate: discriminator: propertyName: action mapping: assign-uuid: '#/components/schemas/AssignTableUUIDUpdate' ... // other update types type: object required: - action properties: action: type: string ``` and the result class: ``` @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "action", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = IcebergAddTableSchemaUpdateDto.class, name = "add-schema"), @JsonSubTypes.Type(value = IcebergAddTableSnapshotUpdateDto.class, name = "add-snapshot"), @JsonSubTypes.Type(value = IcebergAddTableSortOrderUpdateDto.class, name = "add-sort-order"), ... }) @org.eclipse.microprofile.openapi.annotations.media.Schema(description="") @JsonTypeName("TableUpdate") @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen", comments = "Generator version: 7.12.0") public class IcebergTableUpdateDto { private String action; /* other stuff */ } ``` ### Possible implementation Implementation is simple enough in terms of changes: - Remove BaseUpdate - Refactor ViewUpdate & TableUpdate using separate components for each action In the end, final endpoints which use these components, will not be affected in terms of structure of these endpoints, classes which they use and naming of these classes. Only internal structure of TableUpdate/ViewUpdate will be affected. ### Breaking changes/incompatibilities Possibly it may affect already existing implementations of rest catalog during update spec in the next releases / iterations ### How to reproduce Currently i were able to reproduce it using: - "org.openapi.generator" version "7.12.0" - iceberg spec: 1.7.1 / 1.8.1 / 1.9.1 - Generator settings: ``` openApiGenerate { var properties = new HashMap<String, String>() properties.put("supportAsync", "false") properties.put("useMutiny", "false") properties.put("useMicroProfileOpenAPIAnnotations", "true") properties.put("useBeanValidation", "false") properties.put("hideGenerationTimestamp", "true") properties.put("library", "quarkus") properties.put("dateLibrary", "java8") properties.put("interfaceOnly", "true") properties.put("returnResponse", "false") properties.put("useOneOfInterfaces", "false") // true will not help in this case properties.put("generateBuilders", "true") properties.put("generatePom", "false") properties.put("apiPackage", "iceberg.rest.api") properties.put("modelPackage", "iceberg.rest.api.dto") properties.put("modelNamePrefix", "Iceberg") properties.put("modelNameSuffix", "Dto") properties.put("generateApiTests", "false") properties.put("useJakartaEe", "true") properties.put("generateConstructorWithAllArgs", "true") properties.put("generateJsonCreator", "false") properties.put("cleanupOutput", "true") generatorName.set("jaxrs-spec") additionalProperties.putAll(properties) inputSpec.set("$projectDir/src/main/resources/openapi/openapi.yaml") outputDir.set("$buildDir/generated") } ``` ### Proposal document _No response_ ### Specifications - [ ] Table - [ ] View - [x] REST - [ ] Puffin - [ ] Encryption - [ ] Other -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org For additional commands, e-mail: issues-h...@iceberg.apache.org