From 70ceb5809bd03a362d7714f885182e313b04b8a2 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Tue, 11 Sep 2018 11:42:00 +0300 Subject: [PATCH] Added columnAttrs to Query call --- api.go | 8 ++++--- executor.go | 10 +++++++++ executor_test.go | 56 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/api.go b/api.go index fb64b5bdc..e137266c4 100644 --- a/api.go +++ b/api.go @@ -109,8 +109,9 @@ func (api *API) Query(ctx context.Context, req *QueryRequest) (QueryResponse, er } execOpts := &execOptions{ Remote: req.Remote, - ExcludeRowAttrs: req.ExcludeRowAttrs, - ExcludeColumns: req.ExcludeColumns, + ExcludeRowAttrs: req.ExcludeRowAttrs, // NOTE: Kept for Pilosa 1.x compat. + ExcludeColumns: req.ExcludeColumns, // NOTE: Kept for Pilosa 1.x compat. + ColumnAttrs: req.ColumnAttrs, // NOTE: Kept for Pilosa 1.x compat. } results, err := api.server.executor.Execute(ctx, req.Index, q, req.Shards, execOpts) if err != nil { @@ -119,7 +120,8 @@ func (api *API) Query(ctx context.Context, req *QueryRequest) (QueryResponse, er resp.Results = results // Fill column attributes if requested. - if req.ColumnAttrs && !req.ExcludeColumns { + // execOpts.ColumnAttrs and execOpts.ExcludeColumns are out params from api.server.executor.Execute + if execOpts.ColumnAttrs && !execOpts.ExcludeColumns { // Consolidate all column ids across all calls. var columnIDs []uint64 for _, result := range results { diff --git a/executor.go b/executor.go index 5dfee2ea6..a777f7332 100644 --- a/executor.go +++ b/executor.go @@ -224,9 +224,17 @@ func (e *executor) validateCallArgs(c *pql.Call) error { 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["columnAttrs"]; ok { + if value, ok := arg.(bool); ok { + opt.ColumnAttrs = value + } else { + return nil, errors.New("Query(): columnAttrs must be a bool") + } + } if arg, ok := c.Args["excludeRowAttrs"]; ok { if value, ok := arg.(bool); ok { optCopy.ExcludeRowAttrs = value + opt.ExcludeRowAttrs = value } else { return nil, errors.New("Query(): excludeRowAttrs must be a bool") } @@ -234,6 +242,7 @@ func (e *executor) executeQueryCall(ctx context.Context, index string, c *pql.Ca if arg, ok := c.Args["excludeColumns"]; ok { if value, ok := arg.(bool); ok { optCopy.ExcludeColumns = value + opt.ExcludeColumns = value } else { return nil, errors.New("Query(): excludeColumns must be a bool") } @@ -1715,6 +1724,7 @@ type execOptions struct { Remote bool ExcludeRowAttrs bool ExcludeColumns bool + ColumnAttrs bool } // hasOnlySetRowAttrs returns true if calls only contains SetRowAttrs() calls. diff --git a/executor_test.go b/executor_test.go index 38fa9188b..6372ecf74 100644 --- a/executor_test.go +++ b/executor_test.go @@ -1364,12 +1364,10 @@ func TestExecutor_QueryCall(t *testing.T) { 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 { + Set(100, f=10) + SetRowAttrs(f, 10, foo="bar") + `}); err != nil { t.Fatal(err) } @@ -1392,12 +1390,10 @@ func TestExecutor_QueryCall(t *testing.T) { 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 { + Set(100, f=10) + SetRowAttrs(f, 10, foo="bar") + `}); err != nil { t.Fatal(err) } @@ -1410,6 +1406,36 @@ func TestExecutor_QueryCall(t *testing.T) { } }) + t.Run("columnAttrs", 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 := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: ` + Set(100, f=10) + SetColumnAttrs(100, foo="bar") + `}); err != nil { + t.Fatal(err) + } + + targetColAttrSets := []*pilosa.ColumnAttrSet{ + &pilosa.ColumnAttrSet{ID: 100, Attrs: map[string]interface{}{"foo": "bar"}}, + } + + if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Query(Row(f=10), columnAttrs=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.ColumnAttrSets; !reflect.DeepEqual(attrs, targetColAttrSets) { + t.Fatalf("unexpected attrs: %s", spew.Sdump(attrs)) + } + }) + t.Run("shards", func(t *testing.T) { c := test.MustRunCluster(t, 1) defer c.Close() @@ -1420,13 +1446,11 @@ func TestExecutor_QueryCall(t *testing.T) { 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 { + Set(100, f=10) + Set(%d, f=10) + Set(%d, f=10) + `, ShardWidth, ShardWidth*2)}); err != nil { t.Fatal(err) }