Skip to content

Conversation

@pengpeng-lu
Copy link
Contributor

@pengpeng-lu pengpeng-lu commented Oct 2, 2025

Modify TypeRepository to allow registering 2 types (only different in nullability) in the same schema template.
Use Case:
If we have struct A, and array of A in the same template, A is nullable, while A in the array is non-nullable. This should be allowed.

@pengpeng-lu pengpeng-lu added the enhancement New feature or request label Oct 16, 2025
@github-actions
Copy link

📊 Metrics Diff Analysis Report

Summary

  • New queries: 5
  • Dropped queries: 0
  • Plan changed + metrics changed: 0
  • Plan unchanged + metrics changed: 0
ℹ️ About this analysis

This automated analysis compares query planner metrics between the base branch and this PR. It categorizes changes into:

  • New queries: Queries added in this PR
  • Dropped queries: Queries removed in this PR. These should be reviewed to ensure we are not losing coverage.
  • Plan changed + metrics changed: The query plan has changed along with planner metrics.
  • Metrics only changed: Same plan but different metrics

The last category in particular may indicate planner regressions that should be investigated.

New Queries

Count of new queries by file:

  • yaml-tests/src/test/resources/struct-type-nullability-variants.metrics.yaml: 5

Comment on lines +436 to +437
private @Nonnull final Map<Type, String> typeToNameMap;
private @Nonnull final Map<String, Type> nameToCanonicalTypeMap;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the idea here that previously, we had a one-to-one mapping between Type and String names, whereas now, there can be multiple Types that all map to the same String name (as long as the Types are equal ignoring nullability)? And that's why you need to break out the BiMap into two maps?

@Nonnull
public Optional<Type> getTypeByName(@Nonnull final String name) {
return Optional.ofNullable(typeToNameMap.inverse().get(name));
return Optional.ofNullable(nameToCanonicalTypeMap.get(name));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method is unused within the code base. Should we just get rid of it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure 👍

*/
@Nullable
private Type findCanonicalTypeForStructure(@Nonnull final Type type) {
for (Map.Entry<Type, String> entry : typeToNameMap.entrySet()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now introduces an Θ(n) step into creating the type repository, which would mean that creating a repository with n) types is now Θ(n2).

Did you consider an alternative design where we enforce that only the notNullable (or nullable--it doesn't matter except for certain edge cases like Type.Null) variants of each type are kept in the TypeRepository? From my reading of the type repository, we don't actually need to keep both the nullable and non-nullable variants of the type at all, as we only use it to associate a type to a Protobuf descriptor, and those are the same for the two different variants.

I think the basic shape of the solution would look something like:

  1. Modify the builder to store only the (non) nullable version of each type
  2. Wrap the access paths to the typeToName bi-map with logic to first transform the type to its (non) nullable variant

Comment on lines +48 to +49
headquarters Address,
branch_offices Address array,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it I take it, the reason this covers the new logic is that the Address array will be an array of non-nullable Address structs, whereas the headquarters Address will be a nullable type. It might make sense to add an explicit table here where there is both an Address column and an Address NOT NULL column.

#
# This source file is part of the FoundationDB open source project
#
# Copyright 2021-2024 Apple Inc. and the FoundationDB project authors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Copyright 2021-2024 Apple Inc. and the FoundationDB project authors
# Copyright 2016-2025 Apple Inc. and the FoundationDB project authors

}

@TestTemplate
public void structTypeVariants(YamlTest.Runner runner) throws Exception {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, I believe that since the PR was first created, we've sorted the test names in this file in order to decrease the number of conflicts at the end of the file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants