Merge pull request #8838 from influxdata/js-uint-literal-support
Support uint64 literals in the parserpull/8843/head
commit
6bd2ae05d4
|
|
@ -190,6 +190,7 @@ func (*Dimension) node() {}
|
|||
func (Dimensions) node() {}
|
||||
func (*DurationLiteral) node() {}
|
||||
func (*IntegerLiteral) node() {}
|
||||
func (*UnsignedLiteral) node() {}
|
||||
func (*Field) node() {}
|
||||
func (Fields) node() {}
|
||||
func (*Measurement) node() {}
|
||||
|
|
@ -323,6 +324,7 @@ func (*Call) expr() {}
|
|||
func (*Distinct) expr() {}
|
||||
func (*DurationLiteral) expr() {}
|
||||
func (*IntegerLiteral) expr() {}
|
||||
func (*UnsignedLiteral) expr() {}
|
||||
func (*NilLiteral) expr() {}
|
||||
func (*NumberLiteral) expr() {}
|
||||
func (*ParenExpr) expr() {}
|
||||
|
|
@ -344,6 +346,7 @@ type Literal interface {
|
|||
func (*BooleanLiteral) literal() {}
|
||||
func (*DurationLiteral) literal() {}
|
||||
func (*IntegerLiteral) literal() {}
|
||||
func (*UnsignedLiteral) literal() {}
|
||||
func (*NilLiteral) literal() {}
|
||||
func (*NumberLiteral) literal() {}
|
||||
func (*RegexLiteral) literal() {}
|
||||
|
|
@ -3284,6 +3287,15 @@ type IntegerLiteral struct {
|
|||
// String returns a string representation of the literal.
|
||||
func (l *IntegerLiteral) String() string { return fmt.Sprintf("%d", l.Val) }
|
||||
|
||||
// UnsignedLiteral represents an unsigned literal. The parser will only use an unsigned literal if the parsed
|
||||
// integer is greater than math.MaxInt64.
|
||||
type UnsignedLiteral struct {
|
||||
Val uint64
|
||||
}
|
||||
|
||||
// String returns a string representation of the literal.
|
||||
func (l *UnsignedLiteral) String() string { return strconv.FormatUint(l.Val, 10) }
|
||||
|
||||
// BooleanLiteral represents a boolean literal.
|
||||
type BooleanLiteral struct {
|
||||
Val bool
|
||||
|
|
|
|||
|
|
@ -2603,6 +2603,11 @@ func (p *Parser) parseUnaryExpr() (Expr, error) {
|
|||
case INTEGER:
|
||||
v, err := strconv.ParseInt(lit, 10, 64)
|
||||
if err != nil {
|
||||
// The literal may be too large to fit into an int64. If it is, use an unsigned integer.
|
||||
// The check for negative numbers is handled somewhere else so this should always be a positive number.
|
||||
if v, err := strconv.ParseUint(lit, 10, 64); err == nil {
|
||||
return &UnsignedLiteral{Val: v}, nil
|
||||
}
|
||||
return nil, &ParseError{Message: "unable to parse integer", Pos: pos}
|
||||
}
|
||||
return &IntegerLiteral{Val: v}, nil
|
||||
|
|
@ -2679,6 +2684,16 @@ func (p *Parser) parseUnaryExpr() (Expr, error) {
|
|||
lit.Val *= float64(mul)
|
||||
case *IntegerLiteral:
|
||||
lit.Val *= int64(mul)
|
||||
case *UnsignedLiteral:
|
||||
if tok == SUB {
|
||||
// Because of twos-complement integers and the method we parse, math.MinInt64 will be parsed
|
||||
// as an UnsignedLiteral because it overflows an int64, but it fits into int64 if it were parsed
|
||||
// as a negative number instead.
|
||||
if lit.Val == uint64(math.MaxInt64+1) {
|
||||
return &IntegerLiteral{Val: int64(-lit.Val)}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("constant -%d underflows int64", lit.Val)
|
||||
}
|
||||
case *DurationLiteral:
|
||||
lit.Val *= time.Duration(mul)
|
||||
case *VarRef, *Call, *ParenExpr:
|
||||
|
|
|
|||
|
|
@ -3075,6 +3075,9 @@ func TestParser_ParseExpr(t *testing.T) {
|
|||
// Primitives
|
||||
{s: `100.0`, expr: &influxql.NumberLiteral{Val: 100}},
|
||||
{s: `100`, expr: &influxql.IntegerLiteral{Val: 100}},
|
||||
{s: `9223372036854775808`, expr: &influxql.UnsignedLiteral{Val: 9223372036854775808}},
|
||||
{s: `-9223372036854775808`, expr: &influxql.IntegerLiteral{Val: -9223372036854775808}},
|
||||
{s: `-9223372036854775809`, err: `constant -9223372036854775809 underflows int64`},
|
||||
{s: `-100.0`, expr: &influxql.NumberLiteral{Val: -100}},
|
||||
{s: `-100`, expr: &influxql.IntegerLiteral{Val: -100}},
|
||||
{s: `100.`, expr: &influxql.NumberLiteral{Val: 100}},
|
||||
|
|
|
|||
Loading…
Reference in New Issue