Support '=' condition for int/decimal fields

This commit is contained in:
Kuba Podgórski 2020-06-26 01:08:30 +02:00
parent 079bee5711
commit 3782c3ac14
2 changed files with 142 additions and 9 deletions

View file

@ -2427,18 +2427,11 @@ func (e *executor) executeRowShard(ctx context.Context, index string, c *pql.Cal
if err != nil {
return nil, errors.New("Row() argument required: field")
}
f := e.Holder.Field(index, fieldName)
f := idx.Field(fieldName)
if f == nil {
return nil, ErrFieldNotFound
}
rowID, rowOK, rowErr := c.UintArg(fieldName)
if rowErr != nil {
return nil, fmt.Errorf("Row() error with arg for row: %v", rowErr)
} else if !rowOK {
return nil, fmt.Errorf("Row() must specify %v", rowLabel)
}
// Parse "from" time, if set.
var fromTime time.Time
if v, ok := c.Args["from"]; ok {
@ -2455,8 +2448,33 @@ func (e *executor) executeRowShard(ctx context.Context, index string, c *pql.Cal
}
}
timeNotSet := fromTime.IsZero() && toTime.IsZero()
// This is workaround to support pql.ASSIGN ('=') as condition ('==') for int and decimal fields
if c.Name == "Row" && timeNotSet &&
(f.Type() == FieldTypeInt || f.Type() == FieldTypeDecimal) {
// re-write args as conditions for fieldName
for k, v := range c.Args {
if _, ok := v.(*pql.Condition); k == fieldName && !ok {
c.Args[k] = &pql.Condition{
Op: pql.EQ,
Value: v,
}
return e.executeRowBSIGroupShard(ctx, index, c, shard)
}
}
}
rowID, rowOK, rowErr := c.UintArg(fieldName)
if rowErr != nil {
return nil, fmt.Errorf("Row() error with arg for row: %v", rowErr)
} else if !rowOK {
return nil, fmt.Errorf("Row() must specify %v", rowLabel)
}
// Simply return row if times are not set.
if c.Name == "Row" && fromTime.IsZero() && toTime.IsZero() {
if c.Name == "Row" && timeNotSet {
frag := e.Holder.fragment(index, fieldName, viewStandard, shard)
if frag == nil {
return NewRow(), nil

View file

@ -3027,6 +3027,121 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) {
test.CheckGroupBy(t, expected, results)
}
})
t.Run("Row on ints with ASSIGN condition", func(t *testing.T) {
_, err := c[0].API.CreateIndex(context.Background(), "intidx", pilosa.IndexOptions{})
if err != nil {
t.Fatalf("creating index: %v", err)
}
_, err = c[0].API.CreateField(context.Background(), "intidx", "gint", pilosa.OptFieldTypeInt(-1000, 1000))
if err != nil {
t.Fatalf("creating field: %v", err)
}
if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "intidx", Query: `
Set(1000, gint=1)
Set(2000, gint=2)
Set(3000, gint=3)
`}); err != nil {
t.Fatalf("querying remote: %v", err)
}
if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{
Index: "intidx",
Query: `Row(gint=2)Row(gint==1)`,
}); err != nil {
t.Fatalf("Row querying: %v", err)
} else {
row0, row1 := res.Results[0].(*pilosa.Row), res.Results[1].(*pilosa.Row)
if len(row0.Columns()) != 1 || len(row1.Columns()) != 1 {
t.Fatalf(`Expected: []uint64{2000} []uint64{1000}, Got: %+v %+v`, row0.Columns(), row1.Columns())
}
if row0.Columns()[0] != 2000 || row1.Columns()[0] != 1000 {
t.Fatalf(`Expected: []uint64{2000} []uint64{1000}, Got: %+v %+v`, row0.Columns(), row1.Columns())
}
}
})
t.Run("Row on decimals with ASSIGN condition", func(t *testing.T) {
_, err := c[0].API.CreateIndex(context.Background(), "decidx", pilosa.IndexOptions{})
if err != nil {
t.Fatalf("creating index: %v", err)
}
_, err = c[0].API.CreateField(context.Background(), "decidx", "fdec", pilosa.OptFieldTypeDecimal(0))
if err != nil {
t.Fatalf("creating field: %v", err)
}
if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "decidx", Query: `
Set(11, fdec=1.1)
Set(22, fdec=2.2)
Set(33, fdec=3.3)
`}); err != nil {
t.Fatalf("querying remote: %v", err)
}
if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{
Index: "decidx",
Query: `Row(fdec=2.2)Row(fdec==1.1)`,
}); err != nil {
t.Fatalf("Row querying: %v", err)
} else {
row0, row1 := res.Results[0].(*pilosa.Row), res.Results[1].(*pilosa.Row)
if len(row0.Columns()) != 1 || len(row1.Columns()) != 1 {
t.Fatalf(`Expected: []uint64{22} []uint64{11}, Got: %+v %+v`, row0.Columns(), row1.Columns())
}
if row0.Columns()[0] != 22 || row1.Columns()[0] != 11 {
t.Fatalf(`Expected: []uint64{22} []uint64{11}, Got: %+v %+v`, row0.Columns(), row1.Columns())
}
}
})
t.Run("Row on foreign key with ASSIGN condition", func(t *testing.T) {
_, err := c[0].API.CreateIndex(context.Background(), "parent", pilosa.IndexOptions{Keys: true})
if err != nil {
t.Fatalf("creating index: %v", err)
}
_, err = c[0].API.CreateField(context.Background(), "parent", "general", pilosa.OptFieldTypeSet(pilosa.DefaultCacheType, pilosa.DefaultCacheSize))
if err != nil {
t.Fatalf("creating field: %v", err)
}
_, err = c[0].API.CreateIndex(context.Background(), "child", pilosa.IndexOptions{Keys: false})
if err != nil {
t.Fatalf("creating index: %v", err)
}
_, err = c[0].API.CreateField(context.Background(), "child", "parentid",
pilosa.OptFieldForeignIndex("parent"),
pilosa.OptFieldTypeInt(-9223372036854775808, 9223372036854775807),
)
if err != nil {
t.Fatalf("creating field: %v", err)
}
if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "child", Query: `
Set(1, parentid="one")
Set(2, parentid="two")
Set(3, parentid="three")
`}); err != nil {
t.Fatalf("querying remote: %v", err)
}
if res, err := c[1].API.Query(context.Background(), &pilosa.QueryRequest{
Index: "child",
Query: `Row(parentid="two")Row(parentid=="one")`,
}); err != nil {
t.Fatalf("Row querying: %v", err)
} else {
row0, row1 := res.Results[0].(*pilosa.Row), res.Results[1].(*pilosa.Row)
if len(row0.Columns()) != 1 || len(row1.Columns()) != 1 {
t.Fatalf(`Expected: []uint64{1} []uint64{0}, Got: %+v %+v`, row0.Columns(), row1.Columns())
}
if row0.Columns()[0] != 2 || row1.Columns()[0] != 1 {
t.Fatalf(`Expected: []uint64{1} []uint64{0}, Got: %+v %+v`, row0.Columns(), row1.Columns())
}
}
})
}
// Ensure executor returns an error if too many writes are in a single request.