drop float/decimal distinction in PQL

PQL always produces decimals, which have effectively-arbitrary range,
but can convert them to floats when required; the executor then requests
this conversion in the handful of cases (SetRowAttrs and SetColumnAttrs)
where it wants floats rather than decimals.

Not yet fixed: The "Range" call may also be wrong now. It was specifying
an "fvalue" but is now effectively getting what used to be called a
"dvalue". However, so far as I can tell, that didn't work before either.
This commit is contained in:
Seebs 2020-10-07 16:11:47 -05:00
parent b8bb438b69
commit 18ed02d7fb
4 changed files with 1405 additions and 1812 deletions

View file

@ -4286,7 +4286,7 @@ func (e *executor) executeSetRowAttrs(ctx context.Context, qcx *Qcx, index strin
}
// Copy args and remove reserved fields.
attrs := pql.CopyArgs(c.Args)
attrs := pql.CopyArgsDecimalToFloat(c.Args)
delete(attrs, "_field")
delete(attrs, "_"+rowLabel)
@ -4353,7 +4353,7 @@ func (e *executor) executeBulkSetRowAttrs(ctx context.Context, qcx *Qcx, index s
}
// Copy args and remove reserved fields.
attrs := pql.CopyArgs(c.Args)
attrs := pql.CopyArgsDecimalToFloat(c.Args)
delete(attrs, "_field")
delete(attrs, "_"+rowLabel)
@ -4437,7 +4437,7 @@ func (e *executor) executeSetColumnAttrs(ctx context.Context, qcx *Qcx, index st
}
// Copy args and remove reserved fields.
attrs := pql.CopyArgs(c.Args)
attrs := pql.CopyArgsDecimalToFloat(c.Args)
delete(attrs, "_"+columnLabel)
delete(attrs, "field")

View file

@ -60,7 +60,7 @@ func (q *Query) lastCallStackElem() *callStackElem {
func (q *Query) addPosNum(key, value string) {
q.addField(key)
q.addNumVal(value, false)
q.addNumVal(value)
}
func (q *Query) addPosStr(key, value string) {
@ -85,9 +85,9 @@ func (q *Query) endConditional() {
if len(q.conditional) != 5 {
panic(fmt.Sprintf("conditional of wrong length: %#v", q.conditional))
}
low := parseNum(q.conditional[0], false)
low := parseNum(q.conditional[0])
field := q.conditional[2]
high := parseNum(q.conditional[4], false)
high := parseNum(q.conditional[4])
var op Token
switch q.conditional[1] + q.conditional[3] {
@ -162,12 +162,12 @@ func (q *Query) addVal(val interface{}) {
elem.lastCond = ILLEGAL
}
func (q *Query) addNumVal(val string, asFloat bool) {
func (q *Query) addNumVal(val string) {
elem := q.lastCallStackElem()
if elem == nil || elem.lastField == "" {
panic(fmt.Sprintf("addIntVal called with '%s' when lastField is empty", val))
}
ival := parseNum(val, asFloat)
ival := parseNum(val)
if elem.inList {
if elem.lastCond != ILLEGAL {
list := elem.call.Args[elem.lastField].(*Condition).Value.([]interface{})
@ -991,6 +991,20 @@ func CopyArgs(m map[string]interface{}) map[string]interface{} {
return other
}
// CopyArgsDecimalToFloat makes a copy of m, but in the process,
// replaces any Decimal values with Float64 values.
func CopyArgsDecimalToFloat(m map[string]interface{}) map[string]interface{} {
other := make(map[string]interface{}, len(m))
for k, v := range m {
if dec, ok := v.(Decimal); ok {
other[k] = dec.Float64()
} else {
other[k] = v
}
}
return other
}
func joinInterfaceSlice(a []interface{}) string {
other := make([]string, len(a))
for i := range a {
@ -1012,15 +1026,11 @@ func joinUint64Slice(a []uint64) string {
return "[" + strings.Join(other, ",") + "]"
}
func parseNum(val string, asFloat bool) interface{} {
func parseNum(val string) interface{} {
var ival interface{}
var err error
if strings.Contains(val, ".") {
if asFloat {
ival, err = strconv.ParseFloat(val, 64)
} else {
ival, err = ParseDecimal(val)
}
ival, err = ParseDecimal(val)
} else {
ival, err = strconv.ParseInt(val, 10, 64)
}

View file

@ -6,24 +6,20 @@ type PQL Peg {
Calls <- sp (Call sp)* !.
Call <- 'Set' {p.startCall("Set")} open col comma dargs (comma timestamp)? close {p.endCall()}
/ 'SetRowAttrs' {p.startCall("SetRowAttrs")} open posfield comma row comma fargs close {p.endCall()}
/ 'SetColumnAttrs' {p.startCall("SetColumnAttrs")} open col comma fargs close {p.endCall()}
/ 'Clear' {p.startCall("Clear")} open col comma dargs close {p.endCall()}
/ 'ClearRow' {p.startCall("ClearRow")} open darg close {p.endCall()}
/ 'Store' {p.startCall("Store")} open Call comma darg close {p.endCall()}
Call <- 'Set' {p.startCall("Set")} open col comma args (comma timestamp)? close {p.endCall()}
/ 'SetRowAttrs' {p.startCall("SetRowAttrs")} open posfield comma row comma args close {p.endCall()}
/ 'SetColumnAttrs' {p.startCall("SetColumnAttrs")} open col comma args close {p.endCall()}
/ 'Clear' {p.startCall("Clear")} open col comma args close {p.endCall()}
/ 'ClearRow' {p.startCall("ClearRow")} open arg close {p.endCall()}
/ 'Store' {p.startCall("Store")} open Call comma arg close {p.endCall()}
/ 'TopN' {p.startCall("TopN")} open posfield (comma allargs)? close {p.endCall()}
/ 'Rows' {p.startCall("Rows")} open posfield (comma allargs)? close {p.endCall()}
/ 'Range' {p.startCall("Range")} open field sp '=' sp fvalue comma 'from='? {p.addField("from")} timestampfmt {p.addVal(text)} comma 'to='? sp {p.addField("to")} timestampfmt {p.addVal(text)} close {p.endCall()}
/ 'Range' {p.startCall("Range")} open field sp '=' sp value comma 'from='? {p.addField("from")} timestampfmt {p.addVal(text)} comma 'to='? sp {p.addField("to")} timestampfmt {p.addVal(text)} close {p.endCall()}
/ < IDENT > { p.startCall(text ) } open allargs comma? close { p.endCall() }
allargs <- Call (comma Call)* (comma dargs)? / dargs / sp
fargs <- farg (comma fargs)? sp
farg <- field sp '=' sp fvalue
/ field sp COND sp fvalue
/ conditional
dargs <- darg (comma dargs)? sp
darg <- field sp '=' sp dvalue
/ field sp COND sp dvalue
allargs <- Call (comma Call)* (comma args)? / args / sp
args <- arg (comma args)? sp
arg <- field sp '=' sp value
/ field sp COND sp value
/ conditional
COND <- '><' { p.addBTWN() }
/ '<=' { p.addLTE() }
@ -38,30 +34,19 @@ condint <- < '-'? [0-9]* '.' [0-9]+ / '0' / '-'? [1-9] [0-9]* > sp {p.condAdd(te
condLT <- <('<=' / '<')> sp {p.condAdd(text)}
condfield <- <fieldExpr> sp {p.condAdd(text)}
dvalue <- ditem
/ lbrack { p.startList() } dlist rbrack { p.endList() }
fvalue <- fitem
/ lbrack { p.startList() } flist rbrack { p.endList() }
dlist <- ditem (comma dlist)?
flist <- fitem (comma flist)?
ditem <- itema
/ decimal
/ itemb
fitem <- itema
/ float
/ itemb
itema <- 'null' &(comma / sp close) { p.addVal(nil) }
value <- item
/ lbrack { p.startList() } list rbrack { p.endList() }
list <- item (comma list)?
item <- 'null' &(comma / sp close) { p.addVal(nil) }
/ 'true' &(comma / sp close) { p.addVal(true) }
/ 'false' &(comma / sp close) { p.addVal(false) }
/ timestampfmt { p.addVal(text) }
itemb <- < IDENT > { p.startCall(text) } open allargs comma? close { p.addVal(p.endCall()) }
/ < '-'? [0-9]+ ('.'[0-9]*)? > { p.addNumVal(text) }
/ < '-'? '.'[0-9]+ > { p.addNumVal(text) }
/ < IDENT > { p.startCall(text) } open allargs comma? close { p.addVal(p.endCall()) }
/ < ([[A-Z]] / [0-9] / '-' / '_' / ':')+ > { p.addVal(text) }
/ < '"' doublequotedstring '"' > { p.addVal(text) }
/ < '\'' singlequotedstring '\'' > { p.addVal(text) }
float <- < '-'? [0-9]+ ('.'[0-9]*)? > { p.addNumVal(text, true) }
/ < '-'? '.'[0-9]+ > { p.addNumVal(text, true) }
decimal <- < '-'? [0-9]+ ('.'[0-9]*)? > { p.addNumVal(text, false) }
/ < '-'? '.'[0-9]+ > { p.addNumVal(text, false) }
doublequotedstring <- ( '\\"' / '\\\\' / '\\n' / '\\t' / [^"\\] )*
singlequotedstring <- ( '\\\'' / '\\\\' / '\\n' / '\\t' / [^'\\] )*

File diff suppressed because it is too large Load diff