[SQL] Rework the implementation of SAFE_CAST #5428
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #5378
Fixes #5389
Fixes #5390
Fixes #5391
Most changes in this PR are due to automatic refactoring. I split the code to implement complex casts into two classes, handling safe and unsafe casts separately (they were unified, which made everything unreadable).
I have also cut the Gordian knot and removed from our SQL dialect (in the documentation and validation) several kinds of operations, including creating MAP values with MAP keys or using SAFE_CAST on ROW values. This bounded the implementation effort; we can bring these back later if anyone asks.
SAFE_CASTs are supposed to attempt a conversion and return NULL if the conversion fails. This is easy for scalar values, but gets trickier for nested objects like MAP, ARRAY, and ROW, or, if you like, MAP<ARRAY, ROW>. This is now implemented by essentially using the
SqlResulttype (which is just an instance of Rust'sResulttype) to signal errors in cast expression evaluation, and handling these errors at the appropriate place (the outermost scope).The compiler now distinguishes between two kinds of casts: high-level SQL casts, and low-level Rust casts. (They are represented by the same Java class, with different flags.) They used to be conflated previously, which made things REALLY confusing. (Note to self: don't do this again.)