mirror of
https://github.com/minio/minio.git
synced 2024-12-26 07:05:55 -05:00
fix: sql cast function when converting to float (#11817)
This commit is contained in:
parent
b5dcaaccb4
commit
27eb4ae3bc
@ -378,6 +378,31 @@ func TestJSONQueries(t *testing.T) {
|
|||||||
query: `SELECT date_diff(day, '2010-01-01T23:00:00Z', '2010-01-02T23:00:00Z') FROM S3Object LIMIT 1`,
|
query: `SELECT date_diff(day, '2010-01-01T23:00:00Z', '2010-01-02T23:00:00Z') FROM S3Object LIMIT 1`,
|
||||||
wantResult: `{"_1":1}`,
|
wantResult: `{"_1":1}`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "cast_from_int_to_float",
|
||||||
|
query: `SELECT cast(1 as float) FROM S3Object LIMIT 1`,
|
||||||
|
wantResult: `{"_1":1}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cast_from_float_to_float",
|
||||||
|
query: `SELECT cast(1.0 as float) FROM S3Object LIMIT 1`,
|
||||||
|
wantResult: `{"_1":1}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "arithmetic_integer_operand",
|
||||||
|
query: `SELECT 1 / 2 FROM S3Object LIMIT 1`,
|
||||||
|
wantResult: `{"_1":0}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "arithmetic_float_operand",
|
||||||
|
query: `SELECT 1.0 / 2.0 * .3 FROM S3Object LIMIT 1`,
|
||||||
|
wantResult: `{"_1":0.15}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "arithmetic_integer_float_operand",
|
||||||
|
query: `SELECT 3.0 / 2, 5 / 2.0 FROM S3Object LIMIT 1`,
|
||||||
|
wantResult: `{"_1":1.5,"_2":2.5}`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
defRequest := `<?xml version="1.0" encoding="UTF-8"?>
|
defRequest := `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
@ -476,8 +476,13 @@ func (e *FuncExpr) evalNode(r Record) (res *Value, err error) {
|
|||||||
// aggregation or a row function - it always returns a value.
|
// aggregation or a row function - it always returns a value.
|
||||||
func (e *LitValue) evalNode(_ Record) (res *Value, err error) {
|
func (e *LitValue) evalNode(_ Record) (res *Value, err error) {
|
||||||
switch {
|
switch {
|
||||||
case e.Number != nil:
|
case e.Int != nil:
|
||||||
return floatToValue(*e.Number), nil
|
if *e.Int < math.MaxInt64 && *e.Int > math.MinInt64 {
|
||||||
|
return FromInt(int64(*e.Int)), nil
|
||||||
|
}
|
||||||
|
return FromFloat(*e.Int), nil
|
||||||
|
case e.Float != nil:
|
||||||
|
return FromFloat(*e.Float), nil
|
||||||
case e.String != nil:
|
case e.String != nil:
|
||||||
return FromString(string(*e.String)), nil
|
return FromString(string(*e.String)), nil
|
||||||
case e.Boolean != nil:
|
case e.Boolean != nil:
|
||||||
|
@ -492,7 +492,7 @@ func floatCast(v *Value) (float64, error) {
|
|||||||
switch x := v.value.(type) {
|
switch x := v.value.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
return x, nil
|
return x, nil
|
||||||
case int:
|
case int64:
|
||||||
return float64(x), nil
|
return float64(x), nil
|
||||||
case string:
|
case string:
|
||||||
f, err := strconv.ParseFloat(strings.TrimSpace(x), 64)
|
f, err := strconv.ParseFloat(strings.TrimSpace(x), 64)
|
||||||
|
@ -107,7 +107,7 @@ type TableExpression struct {
|
|||||||
// JSONPathElement represents a keypath component
|
// JSONPathElement represents a keypath component
|
||||||
type JSONPathElement struct {
|
type JSONPathElement struct {
|
||||||
Key *ObjectKey `parser:" @@"` // ['name'] and .name forms
|
Key *ObjectKey `parser:" @@"` // ['name'] and .name forms
|
||||||
Index *int `parser:"| \"[\" @Number \"]\""` // [3] form
|
Index *int `parser:"| \"[\" @Int \"]\""` // [3] form
|
||||||
ObjectWildcard bool `parser:"| @\".*\""` // .* form
|
ObjectWildcard bool `parser:"| @\".*\""` // .* form
|
||||||
ArrayWildcard bool `parser:"| @\"[*]\""` // [*] form
|
ArrayWildcard bool `parser:"| @\"[*]\""` // [*] form
|
||||||
}
|
}
|
||||||
@ -333,7 +333,8 @@ type DateDiffFunc struct {
|
|||||||
|
|
||||||
// LitValue represents a literal value parsed from the sql
|
// LitValue represents a literal value parsed from the sql
|
||||||
type LitValue struct {
|
type LitValue struct {
|
||||||
Number *float64 `parser:"( @Number"`
|
Float *float64 `parser:"( @Float"`
|
||||||
|
Int *float64 `parser:" | @Int"` // To avoid value out of range, use float64 instead
|
||||||
String *LiteralString `parser:" | @LitString"`
|
String *LiteralString `parser:" | @LitString"`
|
||||||
Boolean *Boolean `parser:" | @(\"TRUE\" | \"FALSE\")"`
|
Boolean *Boolean `parser:" | @(\"TRUE\" | \"FALSE\")"`
|
||||||
Null bool `parser:" | @\"NULL\")"`
|
Null bool `parser:" | @\"NULL\")"`
|
||||||
@ -351,7 +352,8 @@ var (
|
|||||||
`|(?P<Keyword>(?i)\b(?:SELECT|FROM|TOP|DISTINCT|ALL|WHERE|GROUP|BY|HAVING|UNION|MINUS|EXCEPT|INTERSECT|ORDER|LIMIT|OFFSET|TRUE|FALSE|NULL|IS|NOT|ANY|SOME|BETWEEN|AND|OR|LIKE|ESCAPE|AS|IN|BOOL|INT|INTEGER|STRING|FLOAT|DECIMAL|NUMERIC|TIMESTAMP|AVG|COUNT|MAX|MIN|SUM|COALESCE|NULLIF|CAST|DATE_ADD|DATE_DIFF|EXTRACT|TO_STRING|TO_TIMESTAMP|UTCNOW|CHAR_LENGTH|CHARACTER_LENGTH|LOWER|SUBSTRING|TRIM|UPPER|LEADING|TRAILING|BOTH|FOR)\b)` +
|
`|(?P<Keyword>(?i)\b(?:SELECT|FROM|TOP|DISTINCT|ALL|WHERE|GROUP|BY|HAVING|UNION|MINUS|EXCEPT|INTERSECT|ORDER|LIMIT|OFFSET|TRUE|FALSE|NULL|IS|NOT|ANY|SOME|BETWEEN|AND|OR|LIKE|ESCAPE|AS|IN|BOOL|INT|INTEGER|STRING|FLOAT|DECIMAL|NUMERIC|TIMESTAMP|AVG|COUNT|MAX|MIN|SUM|COALESCE|NULLIF|CAST|DATE_ADD|DATE_DIFF|EXTRACT|TO_STRING|TO_TIMESTAMP|UTCNOW|CHAR_LENGTH|CHARACTER_LENGTH|LOWER|SUBSTRING|TRIM|UPPER|LEADING|TRAILING|BOTH|FOR)\b)` +
|
||||||
`|(?P<Ident>[a-zA-Z_][a-zA-Z0-9_]*)` +
|
`|(?P<Ident>[a-zA-Z_][a-zA-Z0-9_]*)` +
|
||||||
`|(?P<QuotIdent>"([^"]*("")?)*")` +
|
`|(?P<QuotIdent>"([^"]*("")?)*")` +
|
||||||
`|(?P<Number>\d*\.?\d+([eE][-+]?\d+)?)` +
|
`|(?P<Float>\d*\.\d+([eE][-+]?\d+)?)` +
|
||||||
|
`|(?P<Int>\d+)` +
|
||||||
`|(?P<LitString>'([^']*('')?)*')` +
|
`|(?P<LitString>'([^']*('')?)*')` +
|
||||||
`|(?P<Operators><>|!=|<=|>=|\.\*|\[\*\]|[-+*/%,.()=<>\[\]])`,
|
`|(?P<Operators><>|!=|<=|>=|\.\*|\[\*\]|[-+*/%,.()=<>\[\]])`,
|
||||||
))
|
))
|
||||||
|
@ -127,10 +127,10 @@ func parseLimit(v *LitValue) (int64, error) {
|
|||||||
switch {
|
switch {
|
||||||
case v == nil:
|
case v == nil:
|
||||||
return -1, nil
|
return -1, nil
|
||||||
case v.Number == nil:
|
case v.Int == nil:
|
||||||
return -1, errBadLimitSpecified
|
return -1, errBadLimitSpecified
|
||||||
default:
|
default:
|
||||||
r := int64(*v.Number)
|
r := int64(*v.Int)
|
||||||
if r < 0 {
|
if r < 0 {
|
||||||
return -1, errBadLimitSpecified
|
return -1, errBadLimitSpecified
|
||||||
}
|
}
|
||||||
|
@ -306,15 +306,6 @@ func (v Value) CSVString() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// floatToValue converts a float into int representation if needed.
|
|
||||||
func floatToValue(f float64) *Value {
|
|
||||||
intPart, fracPart := math.Modf(f)
|
|
||||||
if fracPart == 0 && intPart < math.MaxInt64 && intPart > math.MinInt64 {
|
|
||||||
return FromInt(int64(intPart))
|
|
||||||
}
|
|
||||||
return FromFloat(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// negate negates a numeric value
|
// negate negates a numeric value
|
||||||
func (v *Value) negate() {
|
func (v *Value) negate() {
|
||||||
switch x := v.value.(type) {
|
switch x := v.value.(type) {
|
||||||
|
Loading…
Reference in New Issue
Block a user