-
-
Notifications
You must be signed in to change notification settings - Fork 235
truncation refactoring and partial decimal truncation implementation #3230
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
Conversation
0d48a93
to
2908281
Compare
19f8a82
to
2be88fd
Compare
a4d9bd8
to
a94f999
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.
Overall this looks pretty good, new interfaces and methods are fine.
My main comment is that you appear to have changed the error handling semantics in calls to type.Convert()
at many call sites, and this is probably pretty bad. I'm guessing this doesn't show up in practice because the current implementations don't produce errors in almost any case, but there's no guarantee that remains the case (esp with Doltgres types and future extensions). Nothing for it but to go through each call site and make sure you're keeping the same semantics for the non-truncation error cases.
enginetest/queries/queries.go
Outdated
Expected: []sql.Row{ | ||
{1, "ab"}, | ||
{2, "4"}, | ||
{1.0, "ab"}, |
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 would call this a regression
mysql> create table types1 as select * from (values row(1+1,2+2), row(floor(1.5),concat("a","b"))) a (c,d) order by 1;
Query OK, 2 rows affected (0.03 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> show create table types1;
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
| types1 | CREATE TABLE `types1` (
`c` bigint NOT NULL DEFAULT '0',
`d` varchar(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
sql/core.go
Outdated
|
||
// TruncateStringToInt trims any whitespace from s, then truncates the string to the left most characters that make | ||
// up a valid integer. Empty strings are converted "0". Additionally, returns a flag indicating if truncation occurred. | ||
func TruncateStringToInt(s string) (string, bool) { |
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.
These probably don't belong in core.go. Maybe type.go would be better.
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 agree, but we unfortunately use these functions in sql.ConvertToBool
and sql.EvaluateCondition
, which are referenced in many, many places. sql
can't import types
because import cycles.
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.
type.go in the sql package
sql/core.go
Outdated
|
||
// TruncateStringToDouble trims any whitespace from s, then truncates the string to the left most characters that make | ||
// up a valid double. Empty strings are converted "0". Additionally, returns a flag indicating if truncation occurred. | ||
func TruncateStringToDouble(s string) (string, bool) { |
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.
Probably good to whip up a few basic unit tests for these, they're easy to screw up.
{"Input value is valid float32", types.Float32, sql.NewRow(float32(6)), float64(1.791759469228055), nil}, | ||
{"Input value is valid int64", types.Int64, sql.NewRow(int64(8)), float64(2.0794415416798357), nil}, | ||
{"Input value is valid int32", types.Int32, sql.NewRow(int32(10)), float64(2.302585092994046), nil}, | ||
{"Input value is valid string", types.Float64, sql.NewRow("2"), 0.6931471805599453, nil}, |
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.
These tests are fine but I would write some targeted to the new parsing functions you added directly
sql/expression/function/math.go
Outdated
seed = e.(int64) | ||
} | ||
e, _, err = types.Int64.Convert(ctx, e) | ||
if err != nil && sql.ErrTruncatedIncorrect.Is(err) { |
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.
Same issue about error dropping
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 applies in many other places, I'll stop mentioning it. Here the issue is that if conversion fails for any reason other than truncation, e will not necessarily be an int64 (note the err == nil handling in the original).
In other places, it seems like you're making an assumption about the error handling semantics of Convert
which might be true now but are certainly not guaranteed by the interface and may not hold in the future. Gotta handle errors correctly everywhere they might occur.
} | ||
} | ||
|
||
leftLit := NewLiteral(originalLeft, in.Left().Type()) |
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 seems pointless, only used once and ever reassigned
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.
It's used in a for loop to determine comparison types between each of the elements in the right tuple.
However, the logic should match HashInTuple
, so I refactored them both here: #3237
sql/types/number.go
Outdated
} | ||
|
||
func convertToInt64(t NumberTypeImpl_, v interface{}) (int64, sql.ConvertInRange, error) { | ||
func convertToInt64(t NumberTypeImpl_, v interface{}, round bool) (int64, sql.ConvertInRange, error) { |
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.
Would be better to define a RoundingBehavior type alias here, always irritating to have random boolean flags at the end of a method signature like this
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.
What does this mean?
inRange sql.ConvertInRange | ||
}{ | ||
// Boolean, Int8, Uint8, ... all use convertToInt64 | ||
{ |
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.
These could use some more variety, more edge cases (leading decimal points, multiple decimal points, mix in other symbols, etc)
52814bb
to
f01c6db
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.
LGTM
sql/core.go
Outdated
signIndex := 0 | ||
|
||
for i := 0; i < len(s); i++ { | ||
var i 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.
This function and the constants above belong in type.go, in the same package.
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.
Also give it a method doc while you're in there.
f01c6db
to
c4ffba6
Compare
changes:
IN
operatorfixes:
double
dolt#7128log
function doesn't handle strings the same as MySql dolt#9735partially addresses: dolthub/dolt#9739