From aa618c30d5797fcf2627352102eb34d143d35f1a Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Mon, 10 Sep 2018 17:29:55 +0300 Subject: [PATCH] Implements Query call excludeRowAttrs, excludeColumns and shards args --- executor.go | 38 +++++++++++++++++++++ executor_test.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++ pql/pqlpeg_test.go | 17 ++++++++++ 3 files changed, 140 insertions(+) diff --git a/executor.go b/executor.go index 6f17cd6a7..5dfee2ea6 100644 --- a/executor.go +++ b/executor.go @@ -194,6 +194,8 @@ func (e *executor) executeCall(ctx context.Context, index string, c *pql.Call, s case "TopN": e.Holder.Stats.CountWithCustomTags(c.Name, 1, 1.0, []string{indexTag}) return e.executeTopN(ctx, index, c, shards, opt) + case "Query": + return e.executeQueryCall(ctx, index, c, shards, opt) default: e.Holder.Stats.CountWithCustomTags(c.Name, 1, 1.0, []string{indexTag}) return e.executeBitmapCall(ctx, index, c, shards, opt) @@ -219,6 +221,42 @@ func (e *executor) validateCallArgs(c *pql.Call) error { return nil } +func (e *executor) executeQueryCall(ctx context.Context, index string, c *pql.Call, shards []uint64, opt *execOptions) (interface{}, error) { + optCopy := &execOptions{} + *optCopy = *opt + if arg, ok := c.Args["excludeRowAttrs"]; ok { + if value, ok := arg.(bool); ok { + optCopy.ExcludeRowAttrs = value + } else { + return nil, errors.New("Query(): excludeRowAttrs must be a bool") + } + } + if arg, ok := c.Args["excludeColumns"]; ok { + if value, ok := arg.(bool); ok { + optCopy.ExcludeColumns = value + } else { + return nil, errors.New("Query(): excludeColumns must be a bool") + } + } + if arg, ok := c.Args["shards"]; ok { + if optShards, ok := arg.([]interface{}); ok { + shards = []uint64{} + for _, s := range optShards { + if shard, ok := s.(int64); ok { + shards = append(shards, uint64(shard)) + } else { + return nil, errors.New("Query(): shards must be a list of unsigned integers") + } + + } + } else { + return nil, errors.New("Query(): shards must be a list of unsigned integers") + } + + } + return e.executeCall(ctx, index, c.Children[0], shards, optCopy) +} + // executeSum executes a Sum() call. func (e *executor) executeSum(ctx context.Context, index string, c *pql.Call, shards []uint64, opt *execOptions) (ValCount, error) { if field := c.Args["field"]; field == "" { diff --git a/executor_test.go b/executor_test.go index a04b5dba2..38fa9188b 100644 --- a/executor_test.go +++ b/executor_test.go @@ -1352,3 +1352,88 @@ func TestExecutor_Time_Clear_Quantums(t *testing.T) { } } + +func TestExecutor_QueryCall(t *testing.T) { + t.Run("excludeRowAttrs", func(t *testing.T) { + c := test.MustRunCluster(t, 1) + defer c.Close() + hldr := test.Holder{Holder: c[0].Server.Holder()} + + // Set columns for rows 0, 10, & 20 across two shards. + if idx, err := hldr.CreateIndex("i", pilosa.IndexOptions{}); err != nil { + t.Fatal(err) + } else if _, err := idx.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil { + t.Fatal(err) + } else if _, err := idx.CreateField("other", pilosa.OptFieldTypeDefault()); err != nil { + t.Fatal(err) + } else if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: ` + Set(100, f=10) + SetRowAttrs(f, 10, foo="bar") + `}); err != nil { + t.Fatal(err) + } + + if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Query(Row(f=10), excludeRowAttrs=true)`}); err != nil { + t.Fatal(err) + } else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{100}) { + t.Fatalf("unexpected columns: %+v", bits) + } else if attrs := res.Results[0].(*pilosa.Row).Attrs; !reflect.DeepEqual(attrs, map[string]interface{}{}) { + t.Fatalf("unexpected attrs: %s", spew.Sdump(attrs)) + } + }) + + t.Run("excludeColumns", func(t *testing.T) { + c := test.MustRunCluster(t, 1) + defer c.Close() + hldr := test.Holder{Holder: c[0].Server.Holder()} + + // Set columns for rows 0, 10, & 20 across two shards. + if idx, err := hldr.CreateIndex("i", pilosa.IndexOptions{}); err != nil { + t.Fatal(err) + } else if _, err := idx.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil { + t.Fatal(err) + } else if _, err := idx.CreateField("other", pilosa.OptFieldTypeDefault()); err != nil { + t.Fatal(err) + } else if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: ` + Set(100, f=10) + SetRowAttrs(f, 10, foo="bar") + `}); err != nil { + t.Fatal(err) + } + + if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Query(Row(f=10), excludeColumns=true)`}); err != nil { + t.Fatal(err) + } else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{}) { + t.Fatalf("unexpected columns: %+v", bits) + } else if attrs := res.Results[0].(*pilosa.Row).Attrs; !reflect.DeepEqual(attrs, map[string]interface{}{"foo": "bar"}) { + t.Fatalf("unexpected attrs: %s", spew.Sdump(attrs)) + } + }) + + t.Run("shards", func(t *testing.T) { + c := test.MustRunCluster(t, 1) + defer c.Close() + hldr := test.Holder{Holder: c[0].Server.Holder()} + + // Set columns for rows 0, 10, & 20 across two shards. + if idx, err := hldr.CreateIndex("i", pilosa.IndexOptions{}); err != nil { + t.Fatal(err) + } else if _, err := idx.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil { + t.Fatal(err) + } else if _, err := idx.CreateField("other", pilosa.OptFieldTypeDefault()); err != nil { + t.Fatal(err) + } else if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: fmt.Sprintf(` + Set(100, f=10) + Set(%d, f=10) + Set(%d, f=10) + `, ShardWidth, ShardWidth*2)}); err != nil { + t.Fatal(err) + } + + if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Query(Row(f=10), shards=[0, 2])`}); err != nil { + t.Fatal(err) + } else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{100, ShardWidth * 2}) { + t.Fatalf("unexpected columns: %+v", bits) + } + }) +} diff --git a/pql/pqlpeg_test.go b/pql/pqlpeg_test.go index fdcde382d..6f05fb402 100644 --- a/pql/pqlpeg_test.go +++ b/pql/pqlpeg_test.go @@ -595,6 +595,23 @@ func TestPQLDeepEquality(t *testing.T) { {Name: "Row"}, }, }}, + { + name: "QueryWrapper", + call: "Query(Row(f1=123), excludeRowAttrs=true)", + exp: &Call{ + Name: "Query", + Args: map[string]interface{}{ + "excludeRowAttrs": true, + }, + Children: []*Call{ + { + Name: "Row", + Args: map[string]interface{}{ + "f1": int64(123), + }, + }, + }, + }}, } for i, test := range tests {