-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
Use case expression type inference logic similar to annotate middleware in MLv2 #47902
Conversation
2c7e06e
to
ac675d0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks correct. Let's add tests and merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, this means that we are saying that all operations that are valid for :type/Date
are valid for a case expression containing a :type/DateTime
value. If that's true, then :type/Date
should be an ancestor of :type/DateTime
, and this hack is not needed. If that's not true, then this invites trouble.
I have the feeling we are expecting too much from a single type hierarchy.
ac675d0
to
7a2b818
Compare
7a2b818
to
c8f06e9
Compare
}); | ||
|
||
it("Case expression with type/Date default value and type/DateTime case value has Date filter popover enabled (metabase#47887)", () => { | ||
visitQuestionAdhoc({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure whether this is the right approach here. Would welcome FE eyes on this.
I guess this comment was about a previous iteration of this PR, but overall agree. Maybe now it's even more lax since IIUC the temporal type of the case expression now depends on the order of the clauses, so we're saying any temporal type should be equivalent? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved since it fixes customer issues and it's reasonable to have the QP and schema agree on how to type the expressions, but also agree with @metamben's comment.
I would suggest to update that linked Notion doc under the temporal types heading with a link pointing to this issue.
;; Following logic for picking a type is taken from | ||
;; the [[metabase.query-processor.middleware.annotate/infer-expression-type]]. | ||
(loop [[cond-or-else expr & rezt*] rezt] | ||
(when (and expr (not= :else cond-or-else)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this exclude the :else
clause?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the way annotate/infer-expression-type
operates currently.
(mt/test-driver | ||
:bigquery-cloud-sdk | ||
(testing "Query with case expression with default Date and case DateTime is executable (#47888)" | ||
(is (=? {:status :completed} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it make sense to check the result rows here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rows are empty in this case. Point of that test is to show whether query executes without underlying jdbc driver throwing an exception. I'll add the comment about that.
…re in MLv2 (#47902) * Use type date for case expression when there are Date and DateTime args * Use logic for getting case expr type from annotate middleware * Add e2e test * Add bigquery test * Update test * cljfmt and comment * Adjust e2e test
@metabase-bot backport release-x.50.x |
…re in MLv2 (#47902) * Use type date for case expression when there are Date and DateTime args * Use logic for getting case expr type from annotate middleware * Add e2e test * Add bigquery test * Update test * cljfmt and comment * Adjust e2e test
…re in MLv2 (#47902) (#48893) * Use type date for case expression when there are Date and DateTime args * Use logic for getting case expr type from annotate middleware * Add e2e test * Add bigquery test * Update test * cljfmt and comment * Adjust e2e test Co-authored-by: lbrdnk <lbrdnk@users.noreply.github.com>
…re in MLv2 (#47902) * Use type date for case expression when there are Date and DateTime args * Use logic for getting case expr type from annotate middleware * Add e2e test * Add bigquery test * Update test * cljfmt and comment * Adjust e2e test
…otate middleware in MLv2 (#47902) (#48923) * Use case expression type inference logic similar to annotate middleware in MLv2 (#47902) * Use type date for case expression when there are Date and DateTime args * Use logic for getting case expr type from annotate middleware * Add e2e test * Add bigquery test * Update test * cljfmt and comment * Adjust e2e test * Adjust e2e test
Closes #47887
Closes #48010
Closes #47888
Initial description (not actual anymore)
The issue is that we infer return type forcase
expression as most specific common ancestor. If the arguments are:type/Date
and:type/DateTime
the ancestor is:type/Temporal
. That results in limited filter picker options.This PR adds special case for arguments of aforemementioned types. The:type/Date
is picked as the expression type.The question is however, whether the current behavior is really erroneous. To the best of my knowledge there's no way to decide correct argument type in this case, and picking the:type/Date
is best effort, that could enable some cases, but may result in error in others.Following stack (in reverse) is significant for the context (ie. if you are interested in how I got to this specific change):Description
This PR solves multiple problems.
Generic filter picker
We stopped checking for the type
Temporal
when selecting a appropriate filter picker, and switched toDate
orDateTime
. The case expression in #47887 is a bit tricky. It returnsDateTime
value when condition is met andDate
value in default case. The MLv2 expression inference code was returning most specific common ancestor in this case -Temporal
.This PR changes the MLv2 case expression inference code to follow the logic in
metabase.query-processor.middleware.annotate/infer-expression-type
.Bigquery error
Bigquery bugs have a different cause. Something changed in a way we compute expressions. In older version that was done in subquery. But in the current version, the expression from reproduction is computed on the same level. The Bigquery logic for appropriate database type inference is now presented with the case expression instead of reference to field from subquery.
This PR adds
metabase.driver.bigquery-cloud-sdk.query-processor/temporal-type
implementation for:case
expression, that follows same logic laid out in theannotate/infer-expression-type
.Long story short, that results in appropriate type reconciliation by means of
metabase.driver.bigquery-cloud-sdk.query-processor/reconcile-temporal-types
.Is that a right decision to model inference by
annotate/infer-expression-type
?Depends on context. Yes in short term. Those 2 bugs are recent regressions and this PR addresses them in relatively non-invasive manner, expanding approach that is taken already in neighboring part of the code base.
In long term, when looking for general right solution to Type system issues mentioned by Ranquild, we should keep in mind this case.
Maybe that would entail creating new type hierarchies for different contexts as noted by Metamben.