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

Apply SQL 9.3 typing rules for CASE-WHEN #1391

Merged
merged 8 commits into from
Mar 19, 2024
Merged

Apply SQL 9.3 typing rules for CASE-WHEN #1391

merged 8 commits into from
Mar 19, 2024

Conversation

RCHowell
Copy link
Member

@RCHowell RCHowell commented Mar 14, 2024

Relevant Issues

#1390

Description

This PR introduces the typing rules of a CASE-WHEN which types branches to the minimum common supertype. In the case of types from different sub-type families (STF) then we go up to the ANY type (known now as dynamic).

Other Information

  • Updated Unreleased Section in CHANGELOG: [YES/NO]
    No

  • Any backward-incompatible changes? [YES/NO]
    This is a behavioral change due to a bug.

  • Any new external dependencies? [YES/NO]
    No

  • Do your changes comply with the Contributing Guidelines
    and Code Style Guidelines? [YES/NO]

License Information

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link

github-actions bot commented Mar 14, 2024

Conformance comparison report

Base (6634bc0) f57111f +/-
% Passing 92.54% 92.54% 0.00%
✅ Passing 5384 5384 0
❌ Failing 434 434 0
🔶 Ignored 0 0 0
Total Tests 5818 5818 0

Number passing in both: 5384

Number failing in both: 434

Number passing in Base (6634bc0) but now fail: 0

Number failing in Base (6634bc0) but now pass: 0

@codecov-commenter
Copy link

codecov-commenter commented Mar 15, 2024

Codecov Report

Attention: Patch coverage is 0% with 7 lines in your changes are missing coverage. Please review.

Project coverage is 73.14%. Comparing base (6634bc0) to head (6bb0cb6).
Report is 1 commits behind head on main.

Files Patch % Lines
...artiql-cli/src/main/kotlin/org/partiql/cli/Main.kt 0.00% 7 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1391      +/-   ##
============================================
- Coverage     73.17%   73.14%   -0.03%     
  Complexity     2393     2393              
============================================
  Files           247      247              
  Lines         17616    17623       +7     
  Branches       3175     3176       +1     
============================================
  Hits          12890    12890              
- Misses         3849     3856       +7     
  Partials        877      877              
Flag Coverage Δ
CLI 11.82% <0.00%> (-0.05%) ⬇️
EXAMPLES 80.07% <ø> (ø)
LANG 81.04% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines 701 to 702
when (boolOrNull(condition.op)) {
true -> return branch.rex // fold
Copy link
Member

Choose a reason for hiding this comment

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

I think there's a bug here. Let's say a CASE has three branches (the first two being booleans (but not constants) and the third being a boolean of literal true). With this logic, it seems like we'd accumulate the first two visited branches, but for the third, we'd immediately return it's result.

Copy link
Member

Choose a reason for hiding this comment

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

Seems like we can only constant fold and return early if it's the first boolean and it's the boolean literal true.

Also wondering if we should still check the other branches to report any incompatible types (i.e. non-boolean WHEN branches).

Copy link
Member Author

@RCHowell RCHowell Mar 18, 2024

Choose a reason for hiding this comment

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

I'm going to leave constant folding true out of this considering the urgency. The task of constant folding (which would include branches) is much larger than this PR.

Copy link
Contributor

@yliuuuu yliuuuu left a comment

Choose a reason for hiding this comment

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

Had a high level question:

Consider: a: unionOf(int2, int4, null).

Given a query:

Case when a IS NULL then a
ELSE a END;

Should the common super type be
unionOf(int2, int4, null) // a dynamic with constraint being int2, int4 and null
or
unionOf(int4, null). // a dynamic with constraint being int4, and null

If the later, should the query a also has the type unionOf(int4, null)?

I understand that the common super type rules applied for an aggregation over values of compatible data types.

We might need to clarify what is an aggregation in PartiQL. That is: one can argue that a simple project is an aggregation. In SQL that is an aggregation over values of same data type, in PartiQL it might be an aggregation over any possible data type.

Comment on lines 103 to 109
val type = supertype.toNonNullStaticType()
val mapping = args.map { it to supertype }
return if (modifiers.isEmpty()) {
type to mapping
} else {
StaticType.unionOf(setOf(type) + modifiers).flatten() to mapping
}
Copy link
Contributor

Choose a reason for hiding this comment

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

If one would keep accumulating MISSING, does not seem like the NULL type will be dropped.

Copy link
Member Author

Choose a reason for hiding this comment

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

Could you please elaborate more?

Copy link
Contributor

Choose a reason for hiding this comment

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

val typer = DynamicTyper() // at this stage, super Type is NULL
typer.accumulate(MISSING) // no touch on super type, missable is true

// modifier contains missing, 
// type is supertype.toNonNullStaticType() -> NULL
// return is StaticType.unionOf(setOf(type) + modifiers).flatten() to mapping
typer.mapping() // UnionOf( NULL, MISSING) 

partiql-cli/src/main/kotlin/org/partiql/cli/Main.kt Outdated Show resolved Hide resolved
Comment on lines 701 to 702
when (boolOrNull(condition.op)) {
true -> return branch.rex // fold
Copy link
Member

Choose a reason for hiding this comment

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

Seems like we can only constant fold and return early if it's the first boolean and it's the boolean literal true.

Also wondering if we should still check the other branches to report any incompatible types (i.e. non-boolean WHEN branches).

Comment on lines +206 to +211
-- type: (int32|int64|string)
CASE t_item.t_string
WHEN 'a' THEN t_item.t_int32
WHEN 'b' THEN t_item.t_int64
ELSE 'default'
END;
Copy link
Member

Choose a reason for hiding this comment

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

So for the heterogeneous cases, we're opting to keep all of the return types in the minimal common subtype and not doing any sort of "flattening" (for this case, returning (int64, string))?

Copy link
Member Author

Choose a reason for hiding this comment

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

Exactly. Once the minimal common supertype hits the top ie dynamic, we don't coerce/cast and branches. We carry all types to the result.

alancai98
alancai98 previously approved these changes Mar 18, 2024
Copy link
Contributor

@yliuuuu yliuuuu left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks.

@RCHowell RCHowell merged commit f42e74f into main Mar 19, 2024
10 checks passed
@RCHowell RCHowell deleted the case-when-typing branch March 19, 2024 21:02
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.

5 participants