Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CALCITE-4603] Least restrictive for collections of collections #2413

Closed
wants to merge 8 commits into from

Conversation

snuyanzin
Copy link
Contributor

The PR implements least restrictive for collection of collections for instance

 select array[array['hello'], array['world'], array['!']] as "array"

and others mentioned in CALCITE-4603

}
if (sqlTypeName == SqlTypeName.MAP) {
RelDataType keyType = leastRestrictive(
Util.transform(types, t -> Objects.requireNonNull(t.getKeyType())));
Copy link
Contributor

@rubenada rubenada May 12, 2021

Choose a reason for hiding this comment

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

I have the impression that, with this code, when trying to calculate an "impossible" leastRestrictive (e.g. between MAP and ARRAY, or MULTISET and VARCHAR), instead of returning null (as it should per RelDataTypeFactory#leastRestrictive contract), it would get a NPE.
Maybe this method should add a pre-check to verify that all the types in the list have the "expected" SqlTypeName (either MAP or MULTISET or ARRAY), before going on (and if the pre-check fails, return null). WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for highlighting this.
Yes it definitely makes sense. The only thing is that it seems that casting from MULTISET to ARRAY and vice versa is allowed and even used in JdbcTest. So I would go with check that either all the types have non null component info or all the types have keytype and valuetype

Copy link
Contributor Author

Choose a reason for hiding this comment

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

just added the changes

Copy link
Contributor

@rubenada rubenada May 13, 2021

Choose a reason for hiding this comment

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

Ok, seems good.
nitpick:

  • I guess with the new code, the Objects.requireNonNull in the three Util.transform is not necessary, since the null case has been checked (and early-exited) before.
  • The isNullable |= type.isNullable(); computation could be integrated into the new "null key+value/component loop", to just have one "pre-computation loop" instead of two.
  • If keyType is null we could just return null without computing valueType
  • You could add final to keyType, valueType and type variables

Copy link
Contributor Author

@snuyanzin snuyanzin May 13, 2021

Choose a reason for hiding this comment

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

I guess with the new code, the Objects.requireNonNull in the three Util.transform is not necessary, since the null case has been checked (and early-exited) before.

Checkerframework says that it is required for Util.transform to have @NonNull RelDataType, that's why it still makes sense to have Objects.requireNonNull there, otherwise ./gradlew with Objects.requireNonNull will fail at these lines.

For others makes sense, thanks
I updated the code

Copy link
Contributor

Choose a reason for hiding this comment

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

The reason it complains is that RelDataType#getKeyType() is nullable, while MapSqlType#getKeyType() is non-nullable.
The checker is not sure if getKeyType() is guaranteed to return the same value every time.

If you cast t to MapSqlType, then it would work without requireNonNull.
An alternative approaches are:
a) Make leastRestrictive return null when null is among its arguments. Currently leastRestrictive would fail with NPE
b) Rework leastRestrictive into builder-like API, so it could indicate to the caller that no more types are needed. The user could instantiate a couple of builders (e.g. key builder, value builder), iterate over the types, and build the common type (e.g. right inside for (RelDataType type: types))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @vlsi
Do you think it makes to create a separate issue for an alternate approach?

Copy link
Contributor

Choose a reason for hiding this comment

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

That is up to you :)

A minor note on the current issue: what do you think of splitting leastRestrictiveCollectionType into leastRestrictiveMapType and leastRestrictiveArrayType ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, after moving of isNullable |= type.isNullable(); into key+value/component loop such splittiing becomes more logic

Copy link
Contributor Author

Choose a reason for hiding this comment

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

however it would be leastRestrictiveMapType and leastRestrictiveArrayMultisetType as the latest one is both for Array and Multiset

@rubenada
Copy link
Contributor

LGTM

…oryImpl.java

Co-authored-by: Vladimir Sitnikov <sitnikov.vladimir@gmail.com>
snuyanzin added a commit to snuyanzin/calcite that referenced this pull request May 16, 2021
snuyanzin added a commit to snuyanzin/calcite that referenced this pull request May 16, 2021
@snuyanzin snuyanzin closed this in 61f8faf May 16, 2021
XuQianJin-Stars pushed a commit to XuQianJin-Stars/calcite that referenced this pull request Jul 14, 2021
hannerwang pushed a commit to hannerwang/calcite that referenced this pull request Aug 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants