mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
add tests, fix tests, fix bugs
This commit is contained in:
parent
4b856bea55
commit
23bca175ae
4 changed files with 617 additions and 294 deletions
|
|
@ -135,7 +135,7 @@ func TestParser_Parse(t *testing.T) {
|
|||
|
||||
// Parse with both child calls and arguments.
|
||||
t.Run("ChildrenAndArguments", func(t *testing.T) {
|
||||
q, err := pql.ParseString(`TopN(Bitmap(id=100, field=other), field=f, n=3)`)
|
||||
q, err := pql.ParseString(`TopN(f, Bitmap(id=100, field=other), n=3)`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(q.Calls[0],
|
||||
|
|
@ -145,7 +145,7 @@ func TestParser_Parse(t *testing.T) {
|
|||
Name: "Bitmap",
|
||||
Args: map[string]interface{}{"id": int64(100), "field": "other"},
|
||||
}},
|
||||
Args: map[string]interface{}{"n": int64(3), "field": "f"},
|
||||
Args: map[string]interface{}{"n": int64(3), "_field": "f"},
|
||||
},
|
||||
) {
|
||||
t.Fatalf("unexpected call: %#v", q.Calls[0])
|
||||
|
|
@ -154,15 +154,15 @@ func TestParser_Parse(t *testing.T) {
|
|||
|
||||
// Parse a list argument.
|
||||
t.Run("ListArgument", func(t *testing.T) {
|
||||
q, err := pql.ParseString(`TopN(field="f", ids=[0,10,30])`)
|
||||
q, err := pql.ParseString(`TopN(f, ids=[0,10,30])`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(q.Calls[0],
|
||||
&pql.Call{
|
||||
Name: "TopN",
|
||||
Args: map[string]interface{}{
|
||||
"field": "f",
|
||||
"ids": []interface{}{int64(0), int64(10), int64(30)},
|
||||
"_field": "f",
|
||||
"ids": []interface{}{int64(0), int64(10), int64(30)},
|
||||
},
|
||||
},
|
||||
) {
|
||||
|
|
|
|||
10
pql/pql.peg
10
pql/pql.peg
|
|
@ -9,11 +9,11 @@ Calls <- whitesp (Call whitesp)* !.
|
|||
Call <- 'Set' {p.startCall("Set")} open uintcol comma args (comma timestamp)? close {p.endCall()}
|
||||
/ 'SetRowAttrs' {p.startCall("SetRowAttrs")} open posfield comma uintrow comma args close {p.endCall()}
|
||||
/ 'SetColAttrs' {p.startCall("SetColAttrs")} open posfield comma uintcol comma args close {p.endCall()}
|
||||
/ 'ClearBit' {p.startCall("ClearBit")} open uintcol comma args close {p.endCall()}
|
||||
/ 'TopN' {p.startCall("TopN")} open posfield (comma args)? close {p.endCall()}
|
||||
/ 'Clear' {p.startCall("Clear")} open uintcol comma args close {p.endCall()}
|
||||
/ 'TopN' {p.startCall("TopN")} open posfield (comma allargs)? close {p.endCall()}
|
||||
/ 'Range' {p.startCall("Range")} open (arg / conditional) close {p.endCall()}
|
||||
/ < IDENT > { p.startCall(buffer[begin:end] ) } open allargs comma? close { p.endCall() }
|
||||
allargs <- Call (comma Call)* (comma args)? / comma? args / sp
|
||||
allargs <- Call (comma Call)* (comma args)? / args / sp
|
||||
args <- arg (comma args)? sp
|
||||
arg <- ( field sp '=' sp value
|
||||
/ field sp COND sp value
|
||||
|
|
@ -27,7 +27,6 @@ COND <- ( '><' { p.addBTWN() }
|
|||
/ '>' { p.addGT() }
|
||||
)
|
||||
conditional <- {p.startConditional()} int ('<=' / '<') fieldExpr ('<=' / '<') int {p.endConditional()}
|
||||
open <- '(' sp
|
||||
value <- ( item
|
||||
/ lbrack { p.startList() } list rbrack { p.endList() }
|
||||
)
|
||||
|
|
@ -53,12 +52,13 @@ int <- '-'? [1-9] [0-9]* / '0'
|
|||
uintrow <- <uint>{p.addPosNum("_row", buffer[begin:end])}
|
||||
uintcol <- <uint>{p.addPosNum("_col", buffer[begin:end])}
|
||||
|
||||
open <- '(' sp
|
||||
close <- ')' sp
|
||||
sp <- ( ' ' / '\t' )*
|
||||
comma <- sp ',' whitesp
|
||||
lbrack <- '[' sp
|
||||
rbrack <- sp ']' sp
|
||||
whitesp <- ( ' ' / '\t' / '\n' )*
|
||||
IDENT <- [[A-Z]] ([[A-Z]] / [0-9] / '-' / '_' / '.')*
|
||||
IDENT <- !('Set(' / 'SetRowAttrs(' / 'SetColAttrs(' / 'Clear(' / 'TopN(' / 'Range(') [[A-Z]] ([[A-Z]] / [0-9])*
|
||||
|
||||
timestamp <- <[0-9][0-9][0-9][0-9]'-'[01][0-9]'-'[0-3][0-9]'T'[0-9][0-9]':'[0-9][0-9]> {p.addPosStr("_timestamp", buffer[begin:end])}
|
||||
733
pql/pql.peg.go
733
pql/pql.peg.go
File diff suppressed because it is too large
Load diff
|
|
@ -1,12 +1,13 @@
|
|||
package pql
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPEG(t *testing.T) {
|
||||
p := PQL{Buffer: `
|
||||
SetBit(Union(Zitmap(row==4), Intersect(Qitmap(blah>4), Ritmap(field="http://zoo9.com=\\'hello' and \"hello\"")), Hitmap(row=ag-bee)), a="4z", b=5) Count(Union(Witmap(row=5.73, frame=.10), Range(zztop><[2, 9]))) TopN(fields=["hello", "goodbye", "zero"])`[1:]}
|
||||
SetBit(Union(Zitmap(row==4), Intersect(Qitmap(blah>4), Ritmap(field="http://zoo9.com=\\'hello' and \"hello\"")), Hitmap(row=ag-bee)), a="4z", b=5) Count(Union(Witmap(row=5.73, frame=.10), Range(zztop><[2, 9]))) TopN(blah, fields=["hello", "goodbye", "zero"])`[1:]}
|
||||
p.Init()
|
||||
err := p.Parse()
|
||||
if err != nil {
|
||||
|
|
@ -21,11 +22,11 @@ SetBit(Union(Zitmap(row==4), Intersect(Qitmap(blah>4), Ritmap(field="http://zoo9
|
|||
t.Fatalf("should have been an error because of the interior unescaped double quote")
|
||||
}
|
||||
|
||||
q, err := ParseString("TopN(Bitmap(id==other), field=f, n=0)")
|
||||
q, err := ParseString("TopN(blah, Bitmap(id==other), field=f, n=0)")
|
||||
if err != nil {
|
||||
t.Fatalf("should have parsed: %v", err)
|
||||
}
|
||||
if q.String() != `TopN(Bitmap(id == "other"), field="f", n=0)` {
|
||||
if q.String() != `TopN(Bitmap(id == "other"), _field="blah", field="f", n=0)` {
|
||||
t.Fatalf("Failed, got: %s", q)
|
||||
}
|
||||
|
||||
|
|
@ -44,3 +45,154 @@ SetBit(Union(Zitmap(row==4), Intersect(Qitmap(blah>4), Ritmap(field="http://zoo9
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestPEGWorking(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
ncalls int
|
||||
}{
|
||||
{
|
||||
name: "Empty",
|
||||
input: "",
|
||||
ncalls: 0},
|
||||
{
|
||||
name: "Set",
|
||||
input: "Set(1, a=4)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "DoubleSet",
|
||||
input: "Set(1, a=4)Set(2, a=4)",
|
||||
ncalls: 2},
|
||||
{
|
||||
name: "DoubleSetSpc",
|
||||
input: "Set(1, a=4) Set(2, a=4)",
|
||||
ncalls: 2},
|
||||
{
|
||||
name: "DoubleSetNewline",
|
||||
input: "Set(1, a=4) \n Set(2, a=4)",
|
||||
ncalls: 2},
|
||||
{
|
||||
name: "SetWithArbCall",
|
||||
input: "Set(1, a=4)Blerg(z=ha)",
|
||||
ncalls: 2},
|
||||
{
|
||||
name: "SetArbSet",
|
||||
input: "Set(1, a=4)Blerg(z=ha)Set(2, z=99)",
|
||||
ncalls: 3},
|
||||
{
|
||||
name: "ArbSetArb",
|
||||
input: "Arb(q=1, a=4)Set(1, z=9)Arb(z=99)",
|
||||
ncalls: 3},
|
||||
{
|
||||
name: "SetStringArg",
|
||||
input: "Set(1, a=zoom)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "SetManyArgs",
|
||||
input: "Set(1, a=4, b=5)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "SetManyMixedArgs",
|
||||
input: "Set(1, a=4, bsd=haha)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "SetTimestamp",
|
||||
input: "Set(1, a=4, 2017-04-03T19:34)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "Union()",
|
||||
input: "Union()",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "UnionOneRow",
|
||||
input: "Union(Row(a=1))",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "UnionTwoRows",
|
||||
input: "Union(Row(a=1), Row(z=44))",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "UnionNested",
|
||||
input: "Union(Intersect(Row(), Union(Row(), Row())), Row())",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "TopN no args",
|
||||
input: "TopN(boondoggle)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "TopN with args",
|
||||
input: "TopN(boon, doggle=9)",
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "double quoted args",
|
||||
input: `B(a="zm''e")`,
|
||||
ncalls: 1},
|
||||
{
|
||||
name: "single quoted args",
|
||||
input: `B(a='zm""e')`,
|
||||
ncalls: 1},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(test.name+strconv.Itoa(i), func(t *testing.T) {
|
||||
q, err := ParseString(test.input)
|
||||
if err != nil {
|
||||
t.Fatalf("parsing query '%s': %v", test.input, err)
|
||||
}
|
||||
if len(q.Calls) != test.ncalls {
|
||||
t.Fatalf("wrong number of calls for '%s': %#v", test.input, q.Calls)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPEGErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
}{
|
||||
{
|
||||
name: "SetEmpty",
|
||||
input: "Set()"},
|
||||
{
|
||||
name: "SetNoCol",
|
||||
input: "Set(a=4)"},
|
||||
{
|
||||
name: "SetNoParens",
|
||||
input: "Set"},
|
||||
{
|
||||
name: "SetBadTimestamp",
|
||||
input: "Set(1, a=4, 2017-94-03T19:34)"},
|
||||
{
|
||||
name: "SetTimestampNoArg",
|
||||
input: "Set(1, 2017-04-03T19:34)"},
|
||||
{
|
||||
name: "SetRowAttrsNoField",
|
||||
input: "SetRowAttrs(a=4)"},
|
||||
{
|
||||
name: "SetColAttrsNoField",
|
||||
input: "SetColAttrs(a=4)"},
|
||||
{
|
||||
name: "ClearNoCol",
|
||||
input: "Clear(a=4)"},
|
||||
{
|
||||
name: "SetStartingComma",
|
||||
input: "Set(, 1, a=4)"},
|
||||
{
|
||||
name: "StartinCommaArb",
|
||||
input: "Zeeb(, a=4)"},
|
||||
{
|
||||
name: "TopN No Field",
|
||||
input: "TopN(a=77)"},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(test.name+strconv.Itoa(i), func(t *testing.T) {
|
||||
q, err := ParseString(test.input)
|
||||
if err == nil {
|
||||
t.Fatalf("parsing query '%s' - expected error, got: %s", test.input, q)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue