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

sql/parser: support nullable arguments in builtin functions #17264

Merged
merged 3 commits into from
Jul 31, 2017

Conversation

justinj
Copy link
Contributor

@justinj justinj commented Jul 27, 2017

Was a mostly mechanical rebase of #13031. Healthy amounts of 🔬🐶 here.

Also simplified checkReturn a little to return the typedExprs instead of s.

@justinj justinj requested review from jordanlewis and knz July 27, 2017 19:29
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@justinj
Copy link
Contributor Author

justinj commented Jul 28, 2017

Hold off on reviewing this for now, actually, I have some stuff to figure out.

@justinj justinj force-pushed the nathan-null-overloads branch 2 times, most recently from 02bbf54 to f63d0e1 Compare July 28, 2017 14:03
@justinj
Copy link
Contributor Author

justinj commented Jul 28, 2017

OK, after sleeping on this a bit and discussing it with Jordan, I have a better understanding and I've updated it a bit, please take a look when you get a chance.

@jordanlewis
Copy link
Member

Review status: 0 of 8 files reviewed at latest revision, 1 unresolved discussion, all commit checks successful.


pkg/sql/parser/overload.go, line 541 at r2 (raw file):

func checkReturn(
	ctx *SemaContext, s typeCheckOverloadState,
) ([]TypedExpr, []overloadImpl, bool, error) {

Hmm I'm surprised this works. Although this function doesn't mutate s, defaultTypeCheck does - and since we don't return the resultant s, I think the caller of this function will lose the modifications potentially made to it by defaultTypeCheck if you don't either return s or change everything to pass it as a pointer. It's suspicious that there's no tests that notice this behavior so maybe I'm wrong.


Comments from Reviewable

@knz
Copy link
Contributor

knz commented Jul 28, 2017

LGTM modulo resolution of the open question


Reviewed 8 of 8 files at r1, 1 of 1 files at r2, 1 of 1 files at r3, 2 of 2 files at r4.
Review status: all files reviewed at latest revision, 1 unresolved discussion, all commit checks successful.


pkg/sql/parser/overload.go, line 541 at r2 (raw file):

Previously, jordanlewis (Jordan Lewis) wrote…

Hmm I'm surprised this works. Although this function doesn't mutate s, defaultTypeCheck does - and since we don't return the resultant s, I think the caller of this function will lose the modifications potentially made to it by defaultTypeCheck if you don't either return s or change everything to pass it as a pointer. It's suspicious that there's no tests that notice this behavior so maybe I'm wrong.

same question here


Comments from Reviewable

@justinj
Copy link
Contributor Author

justinj commented Jul 28, 2017

Review status: all files reviewed at latest revision, 1 unresolved discussion, all commit checks successful.


pkg/sql/parser/overload.go, line 541 at r2 (raw file):

Previously, knz (kena) wrote…

same question here

Any time checkReturn returns true (which it does in both paths where s is mutated) it's a signal to typeCheckOverloadedExprs to return immediately (which it does, and so s is discarded). So while this is correct, it's certainly a bit confusing. I'm not sure how to improve it without a larger scale refactoring, since checkReturn uses a lot of info from s. I could add a comment but I'm not sure that that would improve the clarity unless you're comparing this to the previous revision (but I might be blinded by having spent a couple days in this code).

One option might be to do the switch outside the calls to this function and then it can be clearer in which cases it's causing a return and in which cases it's not, but this would make the calling function a bit noisy. I don't want to revert this to pass s around, because I think that just obscures what's going on here.


Comments from Reviewable

@knz
Copy link
Contributor

knz commented Jul 29, 2017

Review status: all files reviewed at latest revision, 1 unresolved discussion, all commit checks successful.


pkg/sql/parser/overload.go, line 541 at r2 (raw file):

Previously, justinj (Justin Jaffray) wrote…

Any time checkReturn returns true (which it does in both paths where s is mutated) it's a signal to typeCheckOverloadedExprs to return immediately (which it does, and so s is discarded). So while this is correct, it's certainly a bit confusing. I'm not sure how to improve it without a larger scale refactoring, since checkReturn uses a lot of info from s. I could add a comment but I'm not sure that that would improve the clarity unless you're comparing this to the previous revision (but I might be blinded by having spent a couple days in this code).

One option might be to do the switch outside the calls to this function and then it can be clearer in which cases it's causing a return and in which cases it's not, but this would make the calling function a bit noisy. I don't want to revert this to pass s around, because I think that just obscures what's going on here.

Can you extend the comment of this function with your explanation, then we're probably good to go.


Comments from Reviewable

@justinj justinj force-pushed the nathan-null-overloads branch 2 times, most recently from c907da2 to e5c046b Compare July 30, 2017 17:58
@justinj
Copy link
Contributor Author

justinj commented Jul 30, 2017

Review status: 5 of 8 files reviewed at latest revision, 1 unresolved discussion.


pkg/sql/parser/overload.go, line 541 at r2 (raw file):

Previously, knz (kena) wrote…

Can you extend the comment of this function with your explanation, then we're probably good to go.

Ok, done. I spent some time yesterday trying to figure out a more holistic change, but I think this will do for now.


Comments from Reviewable

@jordanlewis
Copy link
Member

:lgtm:


Reviewed 5 of 8 files at r1, 3 of 3 files at r5, 1 of 1 files at r6, 2 of 2 files at r7.
Review status: all files reviewed at latest revision, 1 unresolved discussion, all commit checks successful.


Comments from Reviewable

Fixes cockroachdb#12968.
Fixes cockroachdb#9920.

This change reworks how NULL arguments are handled during type checking
for `FuncExprs`, `UnaryOps`, `CmpOps`, and `BinOps`. In doing so, it
also fixes a latent bug we had where the latter two expressions would
return NULL when given a NULL argument even when no candidate overload
would be possible. For instance: `'hello' + NULL` returned NULL, even
though we had no `<string> + <T>` operator. We were actually testing
this behavior in `TestTypeCheck`, so those tests had to change.

It does addresses this by returning all compatible candidate functions from
`typeCheckOverloadedExprs`. This improvement to the function's interface
allows us to distinguish impossible overload resolution from ambiguous
resolution. We then return NULL if **1 or more** candidates are possible
and there is a NULL argument.

To compliment this, we add a `nullableArgs` flag on the `Builtin` struct
so that the few implementations that want a chance to see the NULL
values can. This means that we can selectively disable the NULL
fast-path for certain builtins.

Please note that I'm not currently satisfied with the structure of
`typeCheckOverloadedExprs` or its conflation of the terms `overload` and
`candidate`. I plan to address these in a later change though that will
pull the operations of `typeCheckOverloadedExprs` into an
`overloadResolver` type.
This change cleans up `TestTypeCheckOverloadedExprs`, testing the
different error cases:
- returning an ambiguous candidates result
- returning an unsupported candidates result
- returning an error

This also gets rid of the `PlaceholderTypes` field in the `testData`
struct, which was never used.
@justinj
Copy link
Contributor Author

justinj commented Jul 31, 2017

Thanks for the reviews!

@justinj justinj merged commit 90aa58f into cockroachdb:master Jul 31, 2017
@justinj justinj deleted the nathan-null-overloads branch July 31, 2017 13:54
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