-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
opt: pass Const type explicitly #48652
Conversation
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.
Nice. Did you check if this solves #48563?
@@ -1425,7 +1425,7 @@ full-join (cross) | |||
expr | |||
(SemiJoin | |||
(Values | |||
[ (Tuple [ (Const 1) (Const 2) ] "tuple{int}" ) ] | |||
[ (Tuple [ (Const 1 "int") (Const 2 "int") ] "tuple{int}" ) ] |
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.
Could these be MakeIntConst?
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.
No, there are no custom functions in exprgen
❌ The GitHub CI (Cockroach) build has failed on 3eedae63. 🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is otan. |
Hm, I haven't. I assumed we'd need some other fixes from your PR (maybe not?) |
pkg/sql/opt/xform/custom_funcs.go
Outdated
@@ -1388,11 +1388,13 @@ func (c *CustomFuncs) GenerateLookupJoins( | |||
constFilters = make(memo.FiltersExpr, 0, numIndexKeyCols-j) | |||
} | |||
|
|||
foundValType := foundVal.ResolvedType() |
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 probably not right, but no worse than it was before, so I guess we just leave for now...
Once we actually fix the typing, we should add a lint rule to the optimizer tree to not allow calling ResolvedType
. It's just not safe if we care about OIDs.
pkg/sql/opt/norm/custom_funcs.go
Outdated
@@ -60,6 +60,11 @@ func (c *CustomFuncs) DerefOrderingChoice(result *physical.OrderingChoice) physi | |||
return *result | |||
} | |||
|
|||
// MakeIntConst constructs a Const holding a DInt. | |||
func (c *CustomFuncs) MakeIntConst(d *tree.DInt) opt.ScalarExpr { |
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.
Maybe just IntConst
?
pkg/sql/opt/norm/custom_funcs.go
Outdated
@@ -2348,7 +2353,7 @@ func (c *CustomFuncs) CastToCollatedString(str opt.ScalarExpr, locale string) op | |||
if err != nil { | |||
panic(err) | |||
} | |||
return c.f.ConstructConst(d) | |||
return c.f.ConstructConst(d, d.ResolvedType()) |
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 isn't quite right, since you can have CollatedString{Char}
, CollatedString{NVarChar}
, etc, and they're different OIDs. I think should be:
return c.f.ConstructConst(d, types.MakeCollated(str.DataType(), locale)
This subtlety shows what we're up against. ResolvedType
can't be relied upon anywhere if OID's matter, unless we're always careful to use DoidWrapper
(but we're not careful). For us to truly fix the typing, we'd need to audit all of the optbuilder/optimizer code.
@@ -340,5 +340,5 @@ func (f *Factory) ConstructConstVal(d tree.Datum, t *types.T) opt.ScalarExpr { | |||
} | |||
return memo.FalseSingleton | |||
} | |||
return f.ConstructConst(d) | |||
return f.ConstructConst(d, t) |
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.
Should we just kill this method altogether, and then add a couple rules for converting (Const Null)
to (Null)
, (Const True)
to (True)
, etc?
The `Const` operator infers its type using `Datum.ResolvedType()`. The Datum's type loses information in some cases (e.g. see cockroachdb#48563). We now pass the type explicitly to `ConstructConst`, similar to the `Null` operator. Since Const already had a private member, optgen needed to be modified to tolerate a Typ field in this case (only allowed for Scalars). Note that this field was already special - for any Scalar that doesn't have a `Typ` field, one is added automatically and `InferType` is used to populate it. Release note: None
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.
How can I check if this fixes #48563? Or @rafiss maybe you can check if you already have wireshark or whatnot set up?
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @andy-kimball and @jordanlewis)
pkg/sql/opt/norm/custom_funcs.go, line 64 at r1 (raw file):
Previously, andy-kimball (Andy Kimball) wrote…
Maybe just
IntConst
?
Done.
pkg/sql/opt/norm/custom_funcs.go, line 2356 at r1 (raw file):
Previously, andy-kimball (Andy Kimball) wrote…
This isn't quite right, since you can have
CollatedString{Char}
,CollatedString{NVarChar}
, etc, and they're different OIDs. I think should be:return c.f.ConstructConst(d, types.MakeCollated(str.DataType(), locale)
This subtlety shows what we're up against.
ResolvedType
can't be relied upon anywhere if OID's matter, unless we're always careful to useDoidWrapper
(but we're not careful). For us to truly fix the typing, we'd need to audit all of the optbuilder/optimizer code.
Done.
pkg/sql/opt/norm/factory.go, line 343 at r1 (raw file):
Previously, andy-kimball (Andy Kimball) wrote…
Should we just kill this method altogether, and then add a couple rules for converting
(Const Null)
to(Null)
,(Const True)
to(True)
, etc?
Not sure. I like it in principle, one downside is that it would be visible in the expressions in the optbuilder
tests (build
). They would probably also need to be "mandatory" rules because I assume some xform/exec code would break if we have a null Const.
Perhaps we do more generally want to be able to tag a subset of rules so that they are always applied, even in build
mode and don't show up as a step during optsteps
. A lot of simple scalar rules would be candidates.
pkg/sql/opt/xform/custom_funcs.go, line 1391 at r1 (raw file):
Previously, andy-kimball (Andy Kimball) wrote…
This is probably not right, but no worse than it was before, so I guess we just leave for now...
Once we actually fix the typing, we should add a lint rule to the optimizer tree to not allow calling
ResolvedType
. It's just not safe if we care about OIDs.
Yeah, I meant this PR to be used as a "base" on top of which to make some of these fixes (which I don't understand well enough yet). I fixed this one by using the type of the table column (though this column never exists outside of the lookup join so I don't think it matters in practice).
This test should work, add it to
|
Thanks, I'll try it. But I think we do want the change to pass types to the exec factory for projections (instead of that code using ResolvedType) in any case. |
Oh yeah, I didn't realize you didn't include that one. |
@RaduBerinde, I may be mis-understanding, but I don't think we should set types on every Render. Instead, we should be setting types on the final result of the plan (somehow). The problem with render is that it just handles a subset of cases we care about. What if |
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 don't think it should be special. Every planNode should have ResultColumns with types that match the optimizer operators. We should audit all nodes, but for most of them it is already the case - for scans the types match the table column types, for most other operators the types are inherited from the input node(s). Projections are one of the very few places where we actually create new kinds of values (along with Values but we already pass the types for that one).
If we want to make doubly sure, we can make sure to always apply a final renderNode if the types don't match exactly (just like we do if the presentation doesn't match).
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @andy-kimball and @jordanlewis)
How come it isn't sufficient to only apply the final renderNode? Why do the full static types matter for intermediate execution results? |
I think it's technically sufficient, but why not make everything consistent? Also, the types produced by each node will show up in EXPLAIN (TYPES). |
I checked and the renderNode is the only usage of This PR was intended as just an optgen improvement to allow the Type to be specified without needing a |
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.
Reviewed 18 of 23 files at r1, 7 of 7 files at r2.
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @andy-kimball and @jordanlewis)
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.
bors r+
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @andy-kimball and @jordanlewis)
Build failed (retrying...) |
Build succeeded |
The
Const
operator infers its type usingDatum.ResolvedType()
. The Datum'stype loses information in some cases (e.g. see #48563). We now pass the type
explicitly to
ConstructConst
, similar to theNull
operator.Since Const already had a private member, optgen needed to be modified to
tolerate a Typ field in this case (only allowed for Scalars). Note that this
field was already special - for any Scalar that doesn't have a
Typ
field, oneis added automatically and
InferType
is used to populate it.Release note: None