-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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: Implement Summer, a smarter typing system #6358
sql: Implement Summer, a smarter typing system #6358
Conversation
Reviewed the first commit. Reviewed 39 of 39 files at r1. sql/group.go, line 98 [r1] (raw file): sql/index_selection.go, line 781 [r1] (raw file): sql/pgwire_test.go, line 222 [r1] (raw file): sql/pgwire_test.go, line 226 [r1] (raw file): sql/select_qvalue.go, line 111 [r1] (raw file): sql/select_qvalue.go, line 268 [r1] (raw file): sql/sort.go, line 122 [r1] (raw file): sql/subquery.go, line 62 [r1] (raw file): sql/table.go, line 198 [r1] (raw file): sql/parser/datum.go, line 69 [r1] (raw file): sql/parser/datum.go, line 1154 [r1] (raw file): sql/parser/eval.go, line 990 [r1] (raw file): sql/parser/eval.go, line 1200 [r1] (raw file): If we need a call to TypeCheck to ensure that the functions are memoized then I would recommend specifying so in Expr's interface: that the caller of Eval() should always ensure TypeCheck() has been called first. sql/parser/eval.go, line 1510 [r1] (raw file): sql/parser/eval.go, line 1782 [r1] (raw file): sql/parser/eval.go, line 1820 [r1] (raw file): sql/parser/eval_test.go, line 93 [r1] (raw file): sql/parser/eval_test.go, line 377 [r1] (raw file): sql/parser/expr.go, line 312 [r1] (raw file): sql/parser/normalize.go, line 453 [r1] (raw file): sql/parser/normalize.go, line 543 [r1] (raw file): sql/parser/type_check.go, line 378 [r1] (raw file): sql/parser/type_check.go, line 444 [r1] (raw file): sql/parser/type_check.go, line 507 [r1] (raw file): sql/parser/type_check.go, line 581 [r1] (raw file): sql/parser/type_check.go, line 614 [r1] (raw file): sql/parser/type_check.go, line 739 [r1] (raw file): sql/parser/type_check.go, line 758 [r1] (raw file): sql/parser/type_check_test.go, line 116 [r1] (raw file): sql/parser/type_check_test.go, line 117 [r1] (raw file): sql/testdata/select_index, line 245 [r1] (raw file): sql/testdata/select_index, line 279 [r1] (raw file): Comments from Reviewable |
Looked at r1 so far, LGTM (though I don't pretend to understand all the details). Feel free to ignore nits and handle any comments in separate commits or PRs or however it's easiest. Review status: 10 of 55 files reviewed at latest revision, 43 unresolved discussions, all commit checks successful. sql/analyze_test.go, line 73 [r1] (raw file): sql/group.go, line 69 [r1] (raw file): sql/insert.go, line 53 [r1] (raw file): sql/parser/builtins.go, line 57 [r1] (raw file): sql/parser/builtins.go, line 58 [r1] (raw file): sql/parser/builtins.go, line 150 [r1] (raw file): sql/parser/expr.go, line 291 [r1] (raw file): sql/parser/parse.go, line 87 [r1] (raw file): sql/parser/type_check.go, line 104 [r1] (raw file): sql/parser/type_check.go, line 849 [r1] (raw file): sql/parser/type_check.go, line 868 [r1] (raw file): sql/parser/type_check.go, line 871 [r1] (raw file): sql/parser/type_check_test.go, line 135 [r1] (raw file): sql/testdata/select_index, line 279 [r1] (raw file): Comments from Reviewable |
Reviewed r2. Reviewed 38 of 38 files at r2. sql/executor.go, line 582 [r2] (raw file): sql/insert.go, line 486 [r2] (raw file): sql/limit.go, line 48 [r2] (raw file): sql/pgwire_test.go, line 228 [r2] (raw file): sql/parser/eval.go, line 1200 [r1] (raw file): sql/parser/eval.go, line 1820 [r1] (raw file): sql/parser/normalize.go, line 453 [r1] (raw file): sql/parser/normalize.go, line 334 [r2] (raw file): In any case the comment above must be updated. sql/parser/normalize.go, line 403 [r2] (raw file): sql/parser/type_check.go, line 507 [r1] (raw file): Comments from Reviewable |
e8da1a6
to
c3eb7d2
Compare
Reviewed r3. Reviewed 20 of 20 files at r3. sql/parser/normalize_test.go, line 184 [r3] (raw file): sql/parser/set.go, line 68 [r3] (raw file): Comments from Reviewable |
Reviewed r4. Reviewed 2 of 2 files at r4. Comments from Reviewable |
Reviewed r5. Reviewed 2 of 2 files at r5. sql/parser/normalize_test.go, line 98 [r5] (raw file): Comments from Reviewable |
Review status: 9 of 55 files reviewed at latest revision, 52 unresolved discussions, all commit checks successful. sql/analyze_test.go, line 73 [r1] (raw file): sql/executor.go, line 582 [r2] (raw file): sql/group.go, line 69 [r1] (raw file): sql/group.go, line 98 [r1] (raw file): sql/index_selection.go, line 781 [r1] (raw file): sql/insert.go, line 53 [r1] (raw file): sql/insert.go, line 486 [r2] (raw file): sql/pgwire_test.go, line 222 [r1] (raw file): sql/pgwire_test.go, line 226 [r1] (raw file): sql/pgwire_test.go, line 228 [r2] (raw file): sql/select_qvalue.go, line 111 [r1] (raw file): sql/select_qvalue.go, line 268 [r1] (raw file): sql/sort.go, line 122 [r1] (raw file): sql/subquery.go, line 62 [r1] (raw file): sql/table.go, line 198 [r1] (raw file): sql/parser/builtins.go, line 57 [r1] (raw file): sql/parser/builtins.go, line 150 [r1] (raw file): sql/parser/datum.go, line 69 [r1] (raw file): sql/parser/datum.go, line 1154 [r1] (raw file): sql/parser/eval.go, line 990 [r1] (raw file): sql/parser/eval.go, line 1510 [r1] (raw file): sql/parser/eval.go, line 1782 [r1] (raw file): sql/parser/eval_test.go, line 93 [r1] (raw file): sql/parser/eval_test.go, line 377 [r1] (raw file): We also do have NaN exclusively defined for sql/parser/expr.go, line 291 [r1] (raw file): sql/parser/expr.go, line 312 [r1] (raw file): Regardless, a lot of this code is ripe for performance gains, but that should almost certainly come in a later PR. sql/parser/normalize.go, line 453 [r1] (raw file): sql/parser/normalize.go, line 543 [r1] (raw file): sql/parser/normalize.go, line 334 [r2] (raw file): sql/parser/normalize.go, line 403 [r2] (raw file): sql/parser/normalize_test.go, line 98 [r5] (raw file): sql/parser/parse.go, line 87 [r1] (raw file): sql/parser/type_check.go, line 378 [r1] (raw file): sql/parser/type_check.go, line 444 [r1] (raw file): sql/parser/type_check.go, line 507 [r1] (raw file): sql/parser/type_check.go, line 581 [r1] (raw file): sql/parser/type_check.go, line 614 [r1] (raw file): sql/parser/type_check.go, line 739 [r1] (raw file): sql/parser/type_check.go, line 758 [r1] (raw file): sql/parser/type_check.go, line 868 [r1] (raw file): sql/parser/type_check.go, line 871 [r1] (raw file): sql/parser/type_check_test.go, line 116 [r1] (raw file): sql/testdata/select_index, line 279 [r1] (raw file): Comments from Reviewable |
Reviewed r6-r11. Reviewed 1 of 7 files at r6, 1 of 46 files at r9, 24 of 38 files at r10, 17 of 20 files at r11, 2 of 2 files at r12, 2 of 2 files at r13. Comments from Reviewable |
Review status: 35 of 55 files reviewed at latest revision, 39 unresolved discussions, all commit checks successful. sql/limit.go, line 48 [r2] (raw file): sql/parser/normalize_test.go, line 184 [r3] (raw file): sql/parser/set.go, line 68 [r3] (raw file): Comments from Reviewable |
Review status: 35 of 55 files reviewed at latest revision, 39 unresolved discussions, all commit checks successful. sql/pgwire_test.go, line 226 [r1] (raw file): Does Comments from Reviewable |
Review status: 35 of 55 files reviewed at latest revision, 35 unresolved discussions, all commit checks successful. sql/parser/builtins.go, line 58 [r1] (raw file): Comments from Reviewable |
Looked over r2. I love the distinction between Expr and TypedExpr Review status: 35 of 55 files reviewed at latest revision, 44 unresolved discussions, all commit checks successful. sql/executor.go, line 582 [r2] (raw file): sql/expr_filter.go, line 243 [r2] (raw file): sql/group.go, line 104 [r2] (raw file): sql/limit.go, line 58 [r2] (raw file):
sql/select.go, line 480 [r2] (raw file): sql/update.go, line 429 [r2] (raw file): sql/parser/eval.go, line 1989 [r2] (raw file): sql/parser/expr.go, line 38 [r2] (raw file): sql/parser/overload.go, line 160 [r2] (raw file): sql/parser/walk.go, line 61 [r2] (raw file): Comments from Reviewable |
Reviewed 1 of 38 files at r10, 1 of 7 files at r14, 1 of 7 files at r15, 17 of 17 files at r16. sql/pgwire_test.go, line 226 [r1] (raw file): sql/parser/constant_test.go, line 59 [r16] (raw file): sql/parser/constant_test.go, line 92 [r16] (raw file): sql/parser/constant_test.go, line 196 [r16] (raw file): sql/parser/constant_test.go, line 254 [r16] (raw file): sql/parser/expr.go, line 312 [r1] (raw file): sql/parser/normalize.go, line 543 [r1] (raw file): sql/parser/normalize_test.go, line 184 [r3] (raw file): sql/parser/normalize_test.go, line 98 [r5] (raw file): sql/parser/overload.go, line 313 [r16] (raw file): sql/parser/type_check.go, line 581 [r1] (raw file): sql/parser/type_check.go, line 614 [r1] (raw file): Comments from Reviewable |
Reviewed to r16. Review status: all files reviewed at latest revision, 43 unresolved discussions, all commit checks successful. Comments from Reviewable |
Review status: all files reviewed at latest revision, 42 unresolved discussions, all commit checks successful. sql/parser/constant.go, line 1 [r3] (raw file): sql/parser/constant.go, line 32 [r3] (raw file): sql/parser/constant.go, line 41 [r3] (raw file): sql/parser/constant.go, line 74 [r3] (raw file): sql/parser/constant.go, line 173 [r3] (raw file): Comments from Reviewable |
Review status: all files reviewed at latest revision, 41 unresolved discussions, all commit checks successful. sql/parser/type_check.go, line 59 [r12] (raw file): Comments from Reviewable |
Review status: all files reviewed at latest revision, 41 unresolved discussions, all commit checks successful. sql/executor.go, line 582 [r2] (raw file): sql/limit.go, line 48 [r2] (raw file): sql/testdata/select_index, line 279 [r1] (raw file): Comments from Reviewable |
sql/executor.go, line 582 [r2] (raw file): Comments from Reviewable |
Review status: all files reviewed at latest revision, 44 unresolved discussions, all commit checks successful. sql/parser/constant.go, line 136 [r14] (raw file): sql/parser/eval.go, line 1983 [r15] (raw file): sql/parser/type_check.go, line 545 [r15] (raw file): Comments from Reviewable |
Reviewed 9 of 39 files at r1, 1 of 46 files at r9, 21 of 38 files at r10, 5 of 20 files at r11, 1 of 7 files at r14, 1 of 7 files at r15, 17 of 17 files at r16. sql/limit.go, line 48 [r2] (raw file): sql/parser/constant.go, line 84 [r16] (raw file): sql/parser/constant_test.go, line 59 [r16] (raw file): sql/parser/constant_test.go, line 77 [r16] (raw file): Comments from Reviewable |
c3eb7d2
to
1a2d043
Compare
Thanks for the reviews @RaduBerinde and @knz! Review status: 32 of 55 files reviewed at latest revision, 35 unresolved discussions, some commit checks pending. sql/executor.go, line 582 [r2] (raw file): Correct me if I'm wrong, but the deep copying that the Walk infrastructure does will make a copy of the entire parent expression tree above the changed node. If that's true, then I fear the overhead of typing constants would be far too high, because you could all but guarantee that every statement tree would need to be copied in its entirety. At that point, it might just be better to preserve an "original" copy of the tree for each retry to start with. On the other hand, making sure constant literals, once folded and resolved to concrete datum types, print to the same string sounds like a fraught effort. It seems to me that a folded and type checked expression tree (with constants resolved in-place) would be completely safe for a retry. These resolved constant expressions would never change between retries so I can't see a reason why keeping them folded would mess anything up. That said, this of course would mess up the string comparison, so I'm wondering if we might want to explore other ways of making this safety equality check to give us a bit more flexibility. (@knz This also made me realize though that I think we should always populate parameters after type checking, to guarantee that the type checking during prepare and execute always resolve constants the same way. What do you think? I could just be overthinking things, because having the populated parameters with the previously inferred types might guarantee that we always type check the same.) sql/expr_filter.go, line 243 [r2] (raw file): sql/group.go, line 104 [r2] (raw file): sql/pgwire_test.go, line 226 [r1] (raw file): sql/select.go, line 480 [r2] (raw file): sql/update.go, line 429 [r2] (raw file): sql/parser/constant.go, line 1 [r3] (raw file): sql/parser/constant.go, line 32 [r3] (raw file): sql/parser/constant.go, line 41 [r3] (raw file): sql/parser/constant.go, line 173 [r3] (raw file): sql/parser/constant.go, line 136 [r14] (raw file): sql/parser/constant_test.go, line 59 [r16] (raw file): sql/parser/constant_test.go, line 77 [r16] (raw file): sql/parser/constant_test.go, line 92 [r16] (raw file): sql/parser/constant_test.go, line 196 [r16] (raw file): sql/parser/constant_test.go, line 254 [r16] (raw file): sql/parser/eval.go, line 1989 [r2] (raw file): sql/parser/eval.go, line 1983 [r15] (raw file): sql/parser/expr.go, line 38 [r2] (raw file): sql/parser/normalize.go, line 543 [r1] (raw file): sql/parser/normalize_test.go, line 184 [r3] (raw file): sql/parser/normalize_test.go, line 98 [r5] (raw file): sql/parser/overload.go, line 160 [r2] (raw file): sql/parser/overload.go, line 313 [r16] (raw file): sql/parser/type_check.go, line 545 [r15] (raw file): sql/parser/walk.go, line 61 [r2] (raw file): Comments from Reviewable |
Review status: 32 of 55 files reviewed at latest revision, 35 unresolved discussions, all commit checks successful. sql/executor.go, line 582 [r2] (raw file):
I don't get the overhead argument, the former is still cheaper than the latter (at least you don't copy all the unrelated leaves etc). In any case, there is no facility for deep copying an entire expression.. I tried to do that a while back and it was a can of worms (see #4418). Also people seemed to think a full deep copy was a bit much (#4418 (comment)) The problem is not just retries - given that the visitor/walk infrastructure is based on sharing unchanged nodes between the input and the output expression, any time you make an in-place modification, you have to make sure it doesn't screw up some other expression that is using that node. It's hard to track and reason about all the ways in which this could happen. Can you explain exactly what we are modifying in place and/or point me to the code that actually modifies things in place? AFAICT the constant folding code does not modify anything in-place (it generates new nodes, and the walk infrastructure will automatically make copies of the changed parents). If we are just setting type annotations in nodes that is probably fine (but in that case wouldn't it be easy to write a visitor that clears all that stuff from the tree before the string check?). Even if everything we are doing is ok, I am very hesitant to remove the entire check (which could allow future subtle bugs).. I'm ok with finding a way to relax the check though (maybe a visitor that generates a string representation with less info?) Comments from Reviewable |
Reviewed 1 of 20 files at r17, 1 of 7 files at r20, 1 of 7 files at r21, 20 of 20 files at r22. sql/executor.go, line 582 [r2] (raw file): sql/limit.go, line 48 [r2] (raw file): sql/parser/overload.go, line 313 [r16] (raw file):
(then before each code blocks below, add a comment summarizing the rule that the block implements.) Comments from Reviewable |
Review status: all files reviewed at latest revision, 28 unresolved discussions, all commit checks successful. sql/limit.go, line 48 [r2] (raw file): Comments from Reviewable |
This PR is very large, which makes it difficult to review, even when reviewed commit-by-commit. Are there particularly areas that you think deserve special attention? Seeing all of the Review status: 10 of 55 files reviewed at latest revision, 34 unresolved discussions, all commit checks successful. sql/sort.go, line 75 [r30] (raw file): sql/parser/constant.go, line 273 [r30] (raw file): sql/parser/eval.go, line 156 [r30] (raw file): sql/parser/eval.go, line 160 [r30] (raw file): sql/parser/eval.go, line 172 [r30] (raw file): sql/parser/eval.go, line 1868 [r30] (raw file): sql/parser/eval.go, line 1879 [r30] (raw file): sql/parser/expr.go, line 44 [r30] (raw file): sql/parser/overload_test.go, line 76 [r30] (raw file): sql/parser/sql.y, line 1206 [r30] (raw file): sql/parser/type_check.go, line 59 [r12] (raw file): Comments from Reviewable |
Thanks for the review Peter, and I apologize for the size of the PR. It grew as a result of me not feeling 100% confident about the design until I had iterated a few times on it and was able to see the full picture unroll. For future changes I'll be more conscious about rebasing as I go to avoid the need for a huge PR with entangled commits. I will also look into building up new systems beside their current counterpart over time before switching everything over. I agree with your second point, and I think there's actually a TODO at the top of
In terms of places to focus on, I think the biggest area that I would appreciate your input is on the Review status: 10 of 55 files reviewed at latest revision, 34 unresolved discussions, all commit checks successful. Comments from Reviewable |
Review status: 10 of 55 files reviewed at latest revision, 34 unresolved discussions, all commit checks successful. sql/parser/type_check.go, line 59 [r12] (raw file): The "unless it makes it less readable" exception in the code style applies to things like string literals, test case definitions, etc where wrapping would make things significantly less readable. This is not the case here, and it's not the case for function definitions (the code style document explicitly describes how those should be wrapped). The fact that there are many existing violations should be an incentive for us to be more careful, not less. These are brand new lines you are adding, not existing lines which happened to be long already.. Finally, your 1899 count I'm includes generated files (like Comments from Reviewable |
f868aa0
to
80449ec
Compare
Review status: 10 of 55 files reviewed at latest revision, 34 unresolved discussions, some commit checks pending. sql/sort.go, line 75 [r30] (raw file): sql/parser/constant.go, line 273 [r30] (raw file): sql/parser/eval.go, line 156 [r30] (raw file): sql/parser/eval.go, line 160 [r30] (raw file): sql/parser/eval.go, line 172 [r30] (raw file): sql/parser/eval.go, line 1868 [r30] (raw file): sql/parser/eval.go, line 1879 [r30] (raw file): sql/parser/expr.go, line 44 [r30] (raw file): There are also a number of expression types that do not implement sql/parser/sql.y, line 1206 [r30] (raw file): sql/parser/type_check.go, line 59 [r12] (raw file): Comments from Reviewable |
Review status: 10 of 55 files reviewed at latest revision, 34 unresolved discussions, all commit checks successful. sql/parser/type_check.go, line 59 [r12] (raw file): Comments from Reviewable |
Review status: 10 of 55 files reviewed at latest revision, 33 unresolved discussions, all commit checks successful. sql/parser/walk.go, line 61 [r2] (raw file): Comments from Reviewable |
Review status: 10 of 55 files reviewed at latest revision, 19 unresolved discussions, all commit checks successful. sql/parser/constant.go, line 32 [r3] (raw file): Comments from Reviewable |
Review status: 10 of 55 files reviewed at latest revision, 18 unresolved discussions, all commit checks successful. sql/parser/type_check.go, line 59 [r12] (raw file): sql/parser/walk.go, line 61 [r2] (raw file): Comments from Reviewable |
80449ec
to
30708f2
Compare
Reviewed 3 of 45 files at r23, 16 of 38 files at r24, 3 of 20 files at r25, 14 of 20 files at r30, 9 of 9 files at r31. sql/parser/eval.go, line 1879 [r30] (raw file): Comments from Reviewable |
This is one of the cornerstones of the Summer typing algorithm. Type checking now takes a "desired" type, which is a hint to `Expr`s to resolve themselves as the type, if possible. It it up to the caller to assert that the type returned if correct, if it is actually required.
This commit adds a `TypedExpr` interface which is a superset of Expr but can also perform expression evaluation and can return type annotations.
This change creates the types `NumVal` and `StrVal`, which both implement the new `Constant` interface. The interface is a super-set of `Expr`, but includes extra methods for literal values.
This commit creates a new error type to hold commonly seen errors. It then uses this error in a few previously ambiguous situations.
Previously `(1) + 2` would not have folded to `3`, now it does.
This change pulls the constant related visitors into constant.go and cleans up a few tests.
Review status: 52 of 55 files reviewed at latest revision, 17 unresolved discussions, all commit checks successful. sql/parser/eval.go, line 1879 [r30] (raw file): Comments from Reviewable |
This change creates the types `unaryOpOverload`, `binOpOverload`, and `cmpOpOverload`, each with a lookup method for an overload implementation for a given set of argument types. It also changes `ComparisonOp` to `ComparisonOperator` to stay consistent.
30708f2
to
6c01a3a
Compare
This commit cleans up a number of uses of the new `TypedExpr` interface, improves the type checking system, added new test cases, and adds in a few TODOs for future work.
6c01a3a
to
ad3d609
Compare
See #6189 for the updated RFC design doc on this typing system.
This change implements the new typing system in a few stages:
TypedExpr
interface to split pre and post-type checked expressionsThe commits should be read in order to gain insight into the design process and goals.
However, a good amount of polishing/refactoring is done in a few later commits, so it's
probably better to critique code with all commits considered.
This change is