Merge branch 'master' into bnm-fix-1080

This commit is contained in:
nagamocha3000 2021-01-21 17:37:08 +03:00 committed by GitHub
commit 16b5fbe40b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 1067 additions and 735 deletions

2
api.go
View file

@ -161,7 +161,7 @@ func (api *API) Query(ctx context.Context, req *QueryRequest) (QueryResponse, er
}
if !req.Remote {
defer api.tracker.Finish(api.tracker.Start(req.Query, api.server.nodeID, req.Index, start))
defer api.tracker.Finish(api.tracker.Start(req.Query, req.SQLQuery, api.server.nodeID, req.Index, start))
}
// TODO can we get rid of exec options and pass the QueryRequest directly to executor?
execOpts := &execOptions{

View file

@ -536,7 +536,7 @@ func (s Serializer) encodeQueryResponse(m *pilosa.QueryResponse) *internal.Query
case pilosa.ExtractedIDMatrix:
pb.Results[i].Type = queryResultTypeExtractedIDMatrix
pb.Results[i].ExtractedIDMatrix = s.endcodeExtractedIDMatrix(result)
case []pilosa.GroupCount:
case *pilosa.GroupCounts:
pb.Results[i].Type = queryResultTypeGroupCounts
pb.Results[i].GroupCounts = s.encodeGroupCounts(result)
case pilosa.RowIdentifiers:
@ -1423,7 +1423,7 @@ func (s Serializer) decodeQueryResult(pb *internal.QueryResult) interface{} {
case queryResultTypeRowIdentifiers:
return s.decodeRowIdentifiers(pb.RowIdentifiers)
case queryResultTypeGroupCounts:
return s.decodeGroupCounts(pb.GroupCounts)
return s.decodeGroupCounts(pb.GroupCounts, pb.OldGroupCounts)
case queryResultTypePair:
return s.decodePair(pb.Pairs[0])
case queryResultTypePairField:
@ -1587,16 +1587,22 @@ func (s Serializer) decodeRowIdentifiers(a *internal.RowIdentifiers) *pilosa.Row
}
}
func (s Serializer) decodeGroupCounts(a []*internal.GroupCount) []pilosa.GroupCount {
other := make([]pilosa.GroupCount, len(a))
for i := range a {
func (s Serializer) decodeGroupCounts(a *internal.GroupCounts, b []*internal.GroupCount) *pilosa.GroupCounts {
// Workaround: If we get an old-style "[]*GroupCount", we translate it.
if a == nil {
a = &internal.GroupCounts{Aggregate: "", Groups: b}
}
other := make([]pilosa.GroupCount, len(a.Groups))
for i, gc := range a.Groups {
other[i] = pilosa.GroupCount{
Group: s.decodeFieldRows(a[i].Group),
Count: a[i].Count,
Sum: a[i].Sum,
Group: s.decodeFieldRows(gc.Group),
Count: gc.Count,
// note: not renaming the `internal` structure members now
// to avoid breaking protobuf interactions.
Agg: gc.Agg,
}
}
return other
return pilosa.NewGroupCounts(a.Aggregate, other...)
}
func (s Serializer) decodeFieldRows(a []*internal.FieldRow) []pilosa.FieldRow {
@ -1723,13 +1729,17 @@ func (s Serializer) encodeRowIdentifiers(r pilosa.RowIdentifiers) *internal.RowI
}
}
func (s Serializer) encodeGroupCounts(counts []pilosa.GroupCount) []*internal.GroupCount {
result := make([]*internal.GroupCount, len(counts))
for i := range counts {
result[i] = &internal.GroupCount{
Group: s.encodeFieldRows(counts[i].Group),
Count: counts[i].Count,
Sum: counts[i].Sum,
func (s Serializer) encodeGroupCounts(counts *pilosa.GroupCounts) *internal.GroupCounts {
groups := counts.Groups()
result := &internal.GroupCounts{
Groups: make([]*internal.GroupCount, len(groups)),
Aggregate: counts.AggregateColumn(),
}
for i, gc := range groups {
result.Groups[i] = &internal.GroupCount{
Group: s.encodeFieldRows(gc.Group),
Count: gc.Count,
Agg: gc.Agg,
}
}
return result

View file

@ -24,6 +24,7 @@ import (
"strings"
"sync"
"time"
"unsafe"
"github.com/pilosa/pilosa/v2/pql"
pb "github.com/pilosa/pilosa/v2/proto"
@ -312,6 +313,8 @@ func (e *executor) safeCopy(resp QueryResponse) (out QueryResponse) {
out.Results = append(out.Results, x)
case []GroupCount:
out.Results = append(out.Results, x)
case *GroupCounts:
out.Results = append(out.Results, x)
case ExtractedTable:
out.Results = append(out.Results, x)
case ExtractedIDMatrix:
@ -2653,10 +2656,10 @@ func (g *groupCountSorter) Less(i, j int) bool {
} else if gci.Count > gcj.Count {
return fieldOrder == desc
}
case -2: // aggregate/Sum
if gci.Sum < gcj.Sum {
case -2: // Aggregate
if gci.Agg < gcj.Agg {
return fieldOrder == asc
} else if gci.Sum > gcj.Sum {
} else if gci.Agg > gcj.Agg {
return fieldOrder == desc
}
default:
@ -2702,7 +2705,19 @@ func getSorter(sortSpec string) (*groupCountSorter, error) {
return gcs, nil
}
func (e *executor) executeGroupBy(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shards []uint64, opt *execOptions) ([]GroupCount, error) {
// findGroupCounts gets a safe-to-use but possibly empty []GroupCount from
// an interface which might be a *GroupCounts or a []GroupCount.
func findGroupCounts(v interface{}) []GroupCount {
switch gc := v.(type) {
case []GroupCount:
return gc
case *GroupCounts:
return gc.Groups()
}
return nil
}
func (e *executor) executeGroupBy(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shards []uint64, opt *execOptions) (*GroupCounts, error) {
span, ctx := tracing.StartSpanFromContext(ctx, "Executor.executeGroupBy")
defer span.Finish()
// validate call
@ -2787,7 +2802,7 @@ func (e *executor) executeGroupBy(ctx context.Context, qcx *Qcx, index string, c
return nil, errors.Wrap(err, "getting rows for ")
}
if len(childRows[i]) == 0 { // there are no results because this field has no values.
return []GroupCount{}, nil
return &GroupCounts{}, nil
}
}
}
@ -2798,11 +2813,11 @@ func (e *executor) executeGroupBy(ctx context.Context, qcx *Qcx, index string, c
}
// Merge returned results at coordinating node.
reduceFn := func(ctx context.Context, prev, v interface{}) interface{} {
other, _ := prev.([]GroupCount)
other := findGroupCounts(prev)
if err := ctx.Err(); err != nil {
return err
}
return mergeGroupCounts(other, v.([]GroupCount), limit)
return mergeGroupCounts(other, findGroupCounts(v), limit)
}
// Get full result set.
other, err := e.mapReduce(ctx, index, shards, c, opt, mapFn, reduceFn)
@ -2869,7 +2884,7 @@ func (e *executor) executeGroupBy(ctx context.Context, qcx *Qcx, index string, c
if err != nil {
return nil, err
}
results[n].Sum = int64(aggregateCount[0].(uint64))
results[n].Agg = int64(aggregateCount[0].(uint64))
}
}
@ -2907,7 +2922,16 @@ func (e *executor) executeGroupBy(ctx context.Context, qcx *Qcx, index string, c
}
return results, nil
aggType := ""
if aggregate != nil {
switch aggregate.Name {
case "Sum":
aggType = "sum"
case "Count":
aggType = "aggregate"
}
}
return NewGroupCounts(aggType, results...), nil
}
func applyLimitAndOffsetToGroupByResult(c *pql.Call, results []GroupCount) ([]GroupCount, error) {
@ -2992,17 +3016,70 @@ func (fr FieldRow) String() string {
return fmt.Sprintf("%s.%d.%s", fr.Field, fr.RowID, fr.RowKey)
}
type aggregateType int
const (
nilAggregate aggregateType = 0
sumAggregate aggregateType = 1
distinctAggregate aggregateType = 2
)
// GroupCounts is a list of GroupCount.
type GroupCounts []GroupCount
type GroupCounts struct {
groups []GroupCount
aggregateType aggregateType
}
// AggregateColumn gives the likely column name to use for aggregates, because
// for historical reasons we used "sum" when it was a sum, but don't want to
// use that when it's something else. This will likely get revisited.
func (g *GroupCounts) AggregateColumn() string {
switch g.aggregateType {
case sumAggregate:
return "sum"
case distinctAggregate:
return "aggregate"
default:
return ""
}
}
// Groups is a convenience method to let us not worry as much about the
// potentially-nil nature of a *GroupCounts.
func (g *GroupCounts) Groups() []GroupCount {
if g == nil {
return nil
}
return g.groups
}
// NewGroupCounts creates a GroupCounts with the given type and slice
// of GroupCount objects. There's intentionally no externally-accessible way
// to change the []GroupCount after creation.
func NewGroupCounts(agg string, groups ...GroupCount) *GroupCounts {
var aggType aggregateType
switch agg {
case "sum":
aggType = sumAggregate
case "aggregate":
aggType = distinctAggregate
case "":
aggType = nilAggregate
default:
panic(fmt.Sprintf("invalid aggregate type %q", agg))
}
return &GroupCounts{aggregateType: aggType, groups: groups}
}
// ToTable implements the ToTabler interface.
func (g GroupCounts) ToTable() (*pb.TableResponse, error) {
return pb.RowsToTable(&g, len(g))
func (g *GroupCounts) ToTable() (*pb.TableResponse, error) {
return pb.RowsToTable(g, len(g.Groups()))
}
// ToRows implements the ToRowser interface.
func (g GroupCounts) ToRows(callback func(*pb.RowResponse) error) error {
for i, gc := range g {
func (g *GroupCounts) ToRows(callback func(*pb.RowResponse) error) error {
agg := g.AggregateColumn()
for i, gc := range g.Groups() {
var ci []*pb.ColumnInfo
if i == 0 {
for _, fieldRow := range gc.Group {
@ -3015,7 +3092,10 @@ func (g GroupCounts) ToRows(callback func(*pb.RowResponse) error) error {
}
}
ci = append(ci, &pb.ColumnInfo{Name: "count", Datatype: "uint64"})
ci = append(ci, &pb.ColumnInfo{Name: "sum", Datatype: "int64"})
if agg != "" {
ci = append(ci, &pb.ColumnInfo{Name: agg, Datatype: "int64"})
}
}
rowResp := &pb.RowResponse{
Headers: ci,
@ -3032,9 +3112,11 @@ func (g GroupCounts) ToRows(callback func(*pb.RowResponse) error) error {
}
}
rowResp.Columns = append(rowResp.Columns,
&pb.ColumnResponse{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: gc.Count}},
&pb.ColumnResponse{ColumnVal: &pb.ColumnResponse_Int64Val{Int64Val: gc.Sum}},
)
&pb.ColumnResponse{ColumnVal: &pb.ColumnResponse_Uint64Val{Uint64Val: gc.Count}})
if agg != "" {
rowResp.Columns = append(rowResp.Columns,
&pb.ColumnResponse{ColumnVal: &pb.ColumnResponse_Int64Val{Int64Val: gc.Agg}})
}
if err := callback(rowResp); err != nil {
return errors.Wrap(err, "calling callback")
}
@ -3042,18 +3124,51 @@ func (g GroupCounts) ToRows(callback func(*pb.RowResponse) error) error {
return nil
}
// MarshalJSON makes GroupCounts satisfy interface json.Marshaler and
// customizes the JSON output of the aggregate field label.
func (g *GroupCounts) MarshalJSON() ([]byte, error) {
groups := g.Groups()
var counts interface{} = groups
if len(groups) == 0 {
return []byte("[]"), nil
}
switch g.aggregateType {
case sumAggregate:
counts = *(*[]groupCountSum)(unsafe.Pointer(&groups))
case distinctAggregate:
counts = *(*[]groupCountAggregate)(unsafe.Pointer(&groups))
}
return json.Marshal(counts)
}
// GroupCount represents a result item for a group by query.
type GroupCount struct {
Group []FieldRow `json:"group"`
Count uint64 `json:"count"`
Sum int64 `json:"sum"`
Agg int64 `json:"-"`
}
type groupCountSum struct {
Group []FieldRow `json:"group"`
Count uint64 `json:"count"`
Agg int64 `json:"sum"`
}
type groupCountAggregate struct {
Group []FieldRow `json:"group"`
Count uint64 `json:"count"`
Agg int64 `json:"aggregate"`
}
var _ GroupCount = GroupCount(groupCountSum{})
var _ GroupCount = GroupCount(groupCountAggregate{})
func (g *GroupCount) Clone() (r *GroupCount) {
r = &GroupCount{
Group: make([]FieldRow, len(g.Group)),
Count: g.Count,
Sum: g.Sum,
Agg: g.Agg,
}
for i := range g.Group {
r.Group[i] = *(g.Group[i].Clone())
@ -3077,7 +3192,7 @@ func mergeGroupCounts(a, b []GroupCount, limit int) []GroupCount {
i++
case 0:
a[i].Count += b[j].Count
a[i].Sum += b[j].Sum
a[i].Agg += b[j].Agg
ret = append(ret, a[i])
i++
j++
@ -3184,27 +3299,27 @@ func (g GroupCount) satisfiesCondition(subj string, cond *pql.Condition) bool {
return false
}
if cond.Op == pql.EQ {
if g.Sum == val {
if g.Agg == val {
return true
}
} else if cond.Op == pql.NEQ {
if g.Sum != val {
if g.Agg != val {
return true
}
} else if cond.Op == pql.LT {
if g.Sum < val {
if g.Agg < val {
return true
}
} else if cond.Op == pql.LTE {
if g.Sum <= val {
if g.Agg <= val {
return true
}
} else if cond.Op == pql.GT {
if g.Sum > val {
if g.Agg > val {
return true
}
} else if cond.Op == pql.GTE {
if g.Sum >= val {
if g.Agg >= val {
return true
}
}
@ -3214,19 +3329,19 @@ func (g GroupCount) satisfiesCondition(subj string, cond *pql.Condition) bool {
return false
}
if cond.Op == pql.BETWEEN {
if val[0] <= g.Sum && g.Sum <= val[1] {
if val[0] <= g.Agg && g.Agg <= val[1] {
return true
}
} else if cond.Op == pql.BTWN_LT_LTE {
if val[0] < g.Sum && g.Sum <= val[1] {
if val[0] < g.Agg && g.Agg <= val[1] {
return true
}
} else if cond.Op == pql.BTWN_LTE_LT {
if val[0] <= g.Sum && g.Sum < val[1] {
if val[0] <= g.Agg && g.Agg < val[1] {
return true
}
} else if cond.Op == pql.BTWN_LT_LT {
if val[0] < g.Sum && g.Sum < val[1] {
if val[0] < g.Agg && g.Agg < val[1] {
return true
}
}
@ -6497,10 +6612,11 @@ func (e *executor) translateResult(ctx context.Context, index string, idx *Index
}
}
case []GroupCount:
case *GroupCounts:
fieldIDs := make(map[*Field]map[uint64]struct{})
foreignIDs := make(map[*Field]map[uint64]struct{})
for _, gl := range result {
groups := result.Groups()
for _, gl := range groups {
for _, g := range gl.Group {
field := idx.Field(g.Field)
if field == nil {
@ -6511,7 +6627,7 @@ func (e *executor) translateResult(ctx context.Context, index string, idx *Index
if fi := field.ForeignIndex(); fi != "" {
m, ok := foreignIDs[field]
if !ok {
m = make(map[uint64]struct{}, len(result))
m = make(map[uint64]struct{}, len(groups))
foreignIDs[field] = m
}
@ -6522,7 +6638,7 @@ func (e *executor) translateResult(ctx context.Context, index string, idx *Index
m, ok := fieldIDs[field]
if !ok {
m = make(map[uint64]struct{}, len(result))
m = make(map[uint64]struct{}, len(groups))
fieldIDs[field] = m
}
@ -6549,8 +6665,11 @@ func (e *executor) translateResult(ctx context.Context, index string, idx *Index
foreignTranslations[field.Name()] = trans
}
other := make([]GroupCount, 0)
for _, gl := range result {
// We are reluctant to smash result, and I'm not sure we need
// to be but I'm not sure we don't need to be.
newGroups := make([]GroupCount, len(groups))
copy(newGroups, groups)
for gi, gl := range groups {
group := make([]FieldRow, len(gl.Group))
for i, g := range gl.Group {
@ -6563,15 +6682,15 @@ func (e *executor) translateResult(ctx context.Context, index string, idx *Index
group[i] = g
}
other = append(other, GroupCount{
Group: group,
Count: gl.Count,
Sum: gl.Sum,
})
// Replace with translated group.
newGroups[gi].Group = group
}
other := &GroupCounts{}
if result != nil {
other.aggregateType = result.aggregateType
}
other.groups = newGroups
return other, nil
case RowIDs:
fieldName := callArgString(call, "_field")
if fieldName == "" {
@ -7494,7 +7613,7 @@ func (gbi *groupByIterator) Next(ctx context.Context) (ret GroupCount, done bool
return ret, false, err
}
ret.Count = uint64(result.Count)
ret.Sum = result.Val
ret.Agg = result.Val
}
}
if ret.Count == 0 {

View file

@ -164,7 +164,7 @@ func TestExecutor_GroupCountCondition(t *testing.T) {
},
},
{
groupCount: GroupCount{Sum: 100},
groupCount: GroupCount{Agg: 100},
checks: []condCheck{
{cond: "sum == 99", exp: false},
{cond: "sum != 99", exp: true},
@ -196,7 +196,7 @@ func TestExecutor_GroupCountCondition(t *testing.T) {
},
},
{
groupCount: GroupCount{Sum: -100},
groupCount: GroupCount{Agg: -100},
checks: []condCheck{
{cond: "sum == -99", exp: false},
{cond: "sum != -99", exp: true},

View file

@ -3066,7 +3066,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "f", RowID: 7}}, Count: 1},
{Group: []pilosa.FieldRow{{Field: "f", RowID: 10}}, Count: 4},
}
results := res.Results[0].([]pilosa.GroupCount)
results := res.Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
}
})
@ -3108,7 +3108,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "fint", Value: &d}}, Count: 1},
}
results := res.Results[0].([]pilosa.GroupCount)
results := res.Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
}
})
@ -3139,7 +3139,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "hint", Value: &c}}, Count: 1},
}
results := res.Results[0].([]pilosa.GroupCount)
results := res.Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
}
})
@ -5074,20 +5074,20 @@ func TestExecutor_GroupByStrings(t *testing.T) {
{
query: "GroupBy(Rows(generals), aggregate=Sum(field=v))",
expected: []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 1, RowKey: "r1"}}, Count: 5, Sum: 25},
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 2, RowKey: "r2"}}, Count: 5, Sum: 30},
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 1, RowKey: "r1"}}, Count: 5, Agg: 25},
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 2, RowKey: "r2"}}, Count: 5, Agg: 30},
},
},
{
query: "GroupBy(Rows(generals), aggregate=Sum(field=v), having=Condition(sum>25))",
expected: []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 2, RowKey: "r2"}}, Count: 5, Sum: 30},
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 2, RowKey: "r2"}}, Count: 5, Agg: 30},
},
},
{
query: "GroupBy(Rows(generals), aggregate=Sum(field=v), having=Condition(-5<sum<27))",
expected: []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 1, RowKey: "r1"}}, Count: 5, Sum: 25},
{Group: []pilosa.FieldRow{{Field: "generals", RowID: 1, RowKey: "r1"}}, Count: 5, Agg: 25},
},
},
{
@ -5100,52 +5100,52 @@ func TestExecutor_GroupByStrings(t *testing.T) {
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v1}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v2}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v3}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v4}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v5}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v6}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v7}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v8}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v9}},
Count: 1,
Sum: 0,
Agg: 0,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "v", Value: &v10}},
Count: 1,
Sum: 0,
Agg: 0,
},
},
},
@ -5155,12 +5155,12 @@ func TestExecutor_GroupByStrings(t *testing.T) {
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "vv", Value: &v3}},
Count: 3,
Sum: 9,
Agg: 9,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "vv", Value: &v4}},
Count: 4,
Sum: 16,
Agg: 16,
},
},
},
@ -5170,12 +5170,12 @@ func TestExecutor_GroupByStrings(t *testing.T) {
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "nv", Value: &nv4}},
Count: 4,
Sum: -16,
Agg: -16,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "nv", Value: &nv3}},
Count: 3,
Sum: -9,
Agg: -9,
},
},
},
@ -5185,12 +5185,12 @@ func TestExecutor_GroupByStrings(t *testing.T) {
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "nv", Value: &nv4}},
Count: 4,
Sum: -16,
Agg: -16,
},
{
Group: []pilosa.FieldRow{pilosa.FieldRow{Field: "nv", Value: &nv3}},
Count: 3,
Sum: -9,
Agg: -9,
},
},
},
@ -5203,7 +5203,7 @@ func TestExecutor_GroupByStrings(t *testing.T) {
pilosa.FieldRow{Field: "nv", Value: &nv3},
},
Count: 3,
Sum: 9,
Agg: 9,
},
{
Group: []pilosa.FieldRow{
@ -5211,7 +5211,7 @@ func TestExecutor_GroupByStrings(t *testing.T) {
pilosa.FieldRow{Field: "nv", Value: &nv4},
},
Count: 4,
Sum: 16,
Agg: 16,
},
},
},
@ -5226,7 +5226,7 @@ func TestExecutor_GroupByStrings(t *testing.T) {
if err != nil {
t.Fatal(err)
}
results := r.Results[0].([]pilosa.GroupCount)
results := r.Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, tst.expected, results)
})
}
@ -5487,6 +5487,34 @@ func sameStringSlice(x, y []string) bool {
return len(diff) == 0
}
func TestExecutor_Execute_DistinctFailure(t *testing.T) {
c := test.MustRunCluster(t, 1)
defer c.Close()
c.CreateField(t, "i", pilosa.IndexOptions{}, "general")
c.CreateField(t, "i", pilosa.IndexOptions{}, "v", pilosa.OptFieldTypeInt(0, 1000))
c.ImportBits(t, "i", "general", [][2]uint64{
{10, 0},
{10, 1},
{10, ShardWidth + 1},
{11, 2},
{11, ShardWidth + 2},
{12, 2},
{12, ShardWidth + 2},
})
if _, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Set(0, v=10)`}); err != nil {
t.Fatal(err)
} else if _, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Set(1, v=100)`}); err != nil {
t.Fatal(err)
}
t.Run("BasicDistinct", func(t *testing.T) {
if _, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Distinct(field="v")`}); err != nil {
t.Fatalf("unexpected error: \"%v\"", err)
}
})
}
func TestExecutor_Execute_GroupBy(t *testing.T) {
groupByTest := func(t *testing.T, clusterSize int) {
c := test.MustRunCluster(t, 1)
@ -5547,7 +5575,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}, {Field: "sub", RowID: 110}}, Count: 1},
}
results := c.Query(t, "i", `GroupBy(Rows(field=general), Rows(sub))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(field=general), Rows(sub))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5559,7 +5587,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}, {Field: "sub", RowID: 110}}, Count: 1},
}
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5569,50 +5597,50 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1},
}
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), filter=Row(general=10))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), filter=Row(general=10))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
t.Run("Aggregate", func(t *testing.T) {
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 2, Sum: 110},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 10},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 2, Agg: 110},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 10},
}
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), aggregate=Sum(field=v))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), aggregate=Sum(field=v))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
t.Run("AggregateCountDistinct", func(t *testing.T) {
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 3, Sum: 2},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 1},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 11}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 3, Agg: 2},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 1},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 11}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 0},
}
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), aggregate=Count(Distinct(field=v)))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), aggregate=Count(Distinct(field=v)))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
t.Run("AggregateCountDistinctFilter", func(t *testing.T) {
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 1, Sum: 1},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 1, Agg: 1},
}
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), filter=Row(v > 10), aggregate=Count(Distinct(field=v)))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), filter=Row(v > 10), aggregate=Count(Distinct(field=v)))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
t.Run("AggregateCountDistinctFilterDistinct", func(t *testing.T) {
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 3, Sum: 1},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 11}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}, {Field: "sub", RowID: 110}}, Count: 1, Sum: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 100}}, Count: 3, Agg: 1},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 10}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 11}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 0},
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}, {Field: "sub", RowID: 110}}, Count: 1, Agg: 0},
}
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), aggregate=Count(Distinct(Row(v > 10), field=v)))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general), Rows(sub), aggregate=Count(Distinct(Row(v > 10), field=v)))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5622,7 +5650,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "general", RowID: 12}}, Count: 2},
}
results := c.Query(t, "i", `GroupBy(Rows(general, previous=10))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general, previous=10))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5631,7 +5659,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "general", RowID: 11}}, Count: 2},
}
results := c.Query(t, "i", `GroupBy(Rows(general, previous=10), limit=1)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(general, previous=10), limit=1)`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5652,7 +5680,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "a", RowID: 0}, {Field: "b", RowID: 1}}, Count: 1},
}
results := c.Query(t, "i", `GroupBy(Rows(a), Rows(b), limit=1)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(a), Rows(b), limit=1)`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5680,7 +5708,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
})
t.Run("test wrapping with previous", func(t *testing.T) {
results := c.Query(t, "i", `GroupBy(Rows(wa), Rows(wb), Rows(wc, previous=1), limit=3)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(wa), Rows(wb), Rows(wc, previous=1), limit=3)`).Results[0].(*pilosa.GroupCounts).Groups()
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "wa", RowID: 0}, {Field: "wb", RowID: 0}, {Field: "wc", RowID: 2}}, Count: 2},
{Group: []pilosa.FieldRow{{Field: "wa", RowID: 0}, {Field: "wb", RowID: 1}, {Field: "wc", RowID: 0}}, Count: 1},
@ -5690,14 +5718,14 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
})
t.Run("test previous is last result", func(t *testing.T) {
results := c.Query(t, "i", `GroupBy(Rows(wa, previous=3), Rows(wb, previous=3), Rows(wc, previous=3), limit=3)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(wa, previous=3), Rows(wb, previous=3), Rows(wc, previous=3), limit=3)`).Results[0].(*pilosa.GroupCounts).Groups()
if len(results) > 0 {
t.Fatalf("expected no results because previous specified last result")
}
})
t.Run("test wrapping multiple", func(t *testing.T) {
results := c.Query(t, "i", `GroupBy(Rows(wa), Rows(wb, previous=2), Rows(wc, previous=2), limit=1)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(wa), Rows(wb, previous=2), Rows(wc, previous=2), limit=1)`).Results[0].(*pilosa.GroupCounts).Groups()
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "wa", RowID: 1}, {Field: "wb", RowID: 0}, {Field: "wc", RowID: 0}}, Count: 1},
}
@ -5721,7 +5749,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{3, ShardWidth},
})
t.Run("distinct rows in different shards", func(t *testing.T) {
results := c.Query(t, "i", `GroupBy(Rows(ma), Rows(mb), limit=5)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(ma), Rows(mb), limit=5)`).Results[0].(*pilosa.GroupCounts).Groups()
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "ma", RowID: 0}, {Field: "mb", RowID: 0}}, Count: 1},
{Group: []pilosa.FieldRow{{Field: "ma", RowID: 0}, {Field: "mb", RowID: 2}}, Count: 1},
@ -5733,7 +5761,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
})
t.Run("distinct rows in different shards with row limit", func(t *testing.T) {
results := c.Query(t, "i", `GroupBy(Rows(ma), Rows(mb, limit=2), limit=5)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(ma), Rows(mb, limit=2), limit=5)`).Results[0].(*pilosa.GroupCounts).Groups()
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "ma", RowID: 0}, {Field: "mb", RowID: 0}}, Count: 1},
{Group: []pilosa.FieldRow{{Field: "ma", RowID: 1}, {Field: "mb", RowID: 1}}, Count: 1},
@ -5744,7 +5772,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
})
t.Run("distinct rows in different shards with column arg", func(t *testing.T) {
results := c.Query(t, "i", fmt.Sprintf(`GroupBy(Rows(ma), Rows(mb, column=%d), limit=5)`, ShardWidth)).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", fmt.Sprintf(`GroupBy(Rows(ma), Rows(mb, column=%d), limit=5)`, ShardWidth)).Results[0].(*pilosa.GroupCounts).Groups()
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "ma", RowID: 1}, {Field: "mb", RowID: 1}}, Count: 1},
{Group: []pilosa.FieldRow{{Field: "ma", RowID: 1}, {Field: "mb", RowID: 3}}, Count: 1},
@ -5769,7 +5797,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{1, ShardWidth},
})
t.Run("same rows in different shards", func(t *testing.T) {
results := c.Query(t, "i", `GroupBy(Rows(na), Rows(nb))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(na), Rows(nb))`).Results[0].(*pilosa.GroupCounts).Groups()
expected := []pilosa.GroupCount{
{Group: []pilosa.FieldRow{{Field: "na", RowID: 0}, {Field: "nb", RowID: 0}}, Count: 2},
{Group: []pilosa.FieldRow{{Field: "na", RowID: 0}, {Field: "nb", RowID: 1}}, Count: 2},
@ -5806,12 +5834,12 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
t.Run("test wrapping with previous", func(t *testing.T) {
totalResults := make([]pilosa.GroupCount, 0)
results := c.Query(t, "i", `GroupBy(Rows(ppa), Rows(ppb), Rows(ppc), limit=3)`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(ppa), Rows(ppb), Rows(ppc), limit=3)`).Results[0].(*pilosa.GroupCounts).Groups()
totalResults = append(totalResults, results...)
for len(totalResults) < 64 {
lastGroup := results[len(results)-1].Group
query := fmt.Sprintf("GroupBy(Rows(ppa, previous=%d), Rows(ppb, previous=%d), Rows(ppc, previous=%d), limit=3)", lastGroup[0].RowID, lastGroup[1].RowID, lastGroup[2].RowID)
results = c.Query(t, "i", query).Results[0].([]pilosa.GroupCount)
results = c.Query(t, "i", query).Results[0].(*pilosa.GroupCounts).Groups()
totalResults = append(totalResults, results...)
}
@ -5853,7 +5881,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "generalk", RowID: 3, RowKey: "twelve"}, {Field: "subk", RowID: 2, RowKey: "one-hundred-ten"}}, Count: 1},
}
results := c.Query(t, "i", `GroupBy(Rows(generalk), Rows(subk))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "i", `GroupBy(Rows(generalk), Rows(subk))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -5891,7 +5919,7 @@ func TestExecutor_Execute_GroupBy(t *testing.T) {
{Group: []pilosa.FieldRow{{Field: "child", RowID: 2, RowKey: "three"}}, Count: 2},
}
results := c.Query(t, "fic", `GroupBy(Rows(child))`).Results[0].([]pilosa.GroupCount)
results := c.Query(t, "fic", `GroupBy(Rows(child))`).Results[0].(*pilosa.GroupCounts).Groups()
test.CheckGroupBy(t, expected, results)
})
@ -6477,10 +6505,11 @@ func TestExecutor_Execute_CountDistinct(t *testing.T) {
if err != nil {
t.Fatal(err)
}
gc, ok := resp.Results[0].([]pilosa.GroupCount)
gcc, ok := resp.Results[0].(*pilosa.GroupCounts)
if !ok {
t.Fatalf("invalid response type, expected: []pilosa.GroupCount, got: %T", resp.Results[0])
}
gc := gcc.Groups()
if len(gc) != 2 {
t.Fatalf("invalid group count length, expected: 2, got: %v", len(gc))
}
@ -7095,13 +7124,13 @@ toronto,2,11
},
{
query: "GroupBy(Rows(field=likes))",
csvVerifier: `molecula,1,0
pilosa,1,0
pangolin,1,0
zebra,1,0
toucan,1,0
dog,1,0
icecream,6,0
csvVerifier: `molecula,1
pilosa,1
pangolin,1
zebra,1
toucan,1
dog,1
icecream,6
`,
},
{
@ -7112,15 +7141,15 @@ zebra,1,1000
},
{
query: "GroupBy(Rows(field=likes), having=Condition(count>5))",
csvVerifier: "icecream,6,0\n",
csvVerifier: "icecream,6\n",
},
{
query: "GroupBy(Rows(field=likes), filter=Row(affinity>-7))",
csvVerifier: `molecula,1,0
pangolin,1,0
zebra,1,0
toucan,1,0
icecream,4,0
csvVerifier: `molecula,1
pangolin,1
zebra,1
toucan,1
icecream,4
`,
},
{
@ -7160,13 +7189,13 @@ icecream,5,3
},
{
query: "GroupBy(Rows(field=likes), sort=\"count desc\")",
csvVerifier: `icecream,6,0
molecula,1,0
pilosa,1,0
pangolin,1,0
zebra,1,0
toucan,1,0
dog,1,0
csvVerifier: `icecream,6
molecula,1
pilosa,1
pangolin,1
zebra,1
toucan,1
dog,1
`,
},
{

View file

@ -29,6 +29,9 @@ type QueryRequest struct {
// The query string to parse and execute.
Query string
// The SQL source query, if applicable.
SQLQuery string
// The shards to include in the query execution.
// If empty, all shards are included.
Shards []uint64

View file

@ -1182,7 +1182,7 @@ func (h *Handler) handleGetActiveQueries(w http.ResponseWriter, r *http.Request)
}
}
for i, q := range queries {
_, err := fmt.Fprintf(w, "%*s%q\n", -(maxlen + 2), durations[i], q.Query)
_, err := fmt.Fprintf(w, "%*s%q\n", -(maxlen + 2), durations[i], q.PQL)
if err != nil {
h.logger.Printf("sending GetActiveQueries response: %s", err)
return

View file

@ -5620,10 +5620,7 @@ func (m *IndexMeta) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6028,10 +6025,7 @@ func (m *FieldOptions) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6114,10 +6108,7 @@ func (m *ImportResponse) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6302,10 +6293,7 @@ func (m *BlockDataRequest) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6508,10 +6496,7 @@ func (m *BlockDataResponse) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6638,10 +6623,7 @@ func (m *Cache) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6788,7 +6770,7 @@ func (m *MaxShards) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > postIndex {
@ -6805,10 +6787,7 @@ func (m *MaxShards) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -6942,10 +6921,7 @@ func (m *CreateShardMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7028,10 +7004,7 @@ func (m *DeleteIndexMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7169,10 +7142,7 @@ func (m *CreateIndexMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7342,10 +7312,7 @@ func (m *CreateFieldMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7460,10 +7427,7 @@ func (m *DeleteFieldMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7597,10 +7561,7 @@ func (m *DeleteAvailableShardMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7770,10 +7731,7 @@ func (m *Field) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7858,10 +7816,7 @@ func (m *Schema) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8033,10 +7988,7 @@ func (m *Index) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8170,10 +8122,7 @@ func (m *URI) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8380,10 +8329,7 @@ func (m *Node) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8498,10 +8444,7 @@ func (m *NodeStateMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8607,10 +8550,7 @@ func (m *NodeEventMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8767,10 +8707,7 @@ func (m *NodeStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8906,10 +8843,7 @@ func (m *IndexStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9087,10 +9021,7 @@ func (m *FieldStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9275,10 +9206,7 @@ func (m *ClusterStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9431,10 +9359,7 @@ func (m *BSIGroup) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9581,10 +9506,7 @@ func (m *CreateViewMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9731,10 +9653,7 @@ func (m *DeleteViewMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10016,10 +9935,7 @@ func (m *ResizeInstruction) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10221,10 +10137,7 @@ func (m *ResizeSource) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10362,10 +10275,7 @@ func (m *TranslationResizeSource) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10503,10 +10413,7 @@ func (m *ResizeInstructionComplete) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10593,10 +10500,7 @@ func (m *SetCoordinatorMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10683,10 +10587,7 @@ func (m *UpdateCoordinatorMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10801,10 +10702,7 @@ func (m *Topology) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10855,10 +10753,7 @@ func (m *RecalculateCaches) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10977,10 +10872,7 @@ func (m *TransactionMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11177,10 +11069,7 @@ func (m *Transaction) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11231,10 +11120,7 @@ func (m *TransactionStats) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {

File diff suppressed because it is too large Load diff

View file

@ -102,7 +102,7 @@ message FieldRow {
message GroupCount{
repeated FieldRow Group = 1;
uint64 Count = 2;
int64 Sum = 3;
int64 Agg = 3;
}
message ValCount {
@ -159,9 +159,15 @@ message QueryResult {
uint64 N = 2;
repeated Pair Pairs = 3;
bool Changed = 4;
ValCount ValCount = 5;
ValCount ValCount = 5;
repeated uint64 RowIDs = 7;
repeated GroupCount GroupCounts = 8;
// In the past, GroupCounts was a []GroupCount which did not indicate
// whether it had an aggregate, or which aggregate it had. We've
// updated this, but we keep this here so that messages using the old
// format can get a best-effort treatment rather than causing panics.
// Later this can almost certainly go away, but leave a comment warning
// people that 8 is Spoken For if you do that, please.
repeated GroupCount OldGroupCounts = 8;
RowIdentifiers RowIdentifiers = 9;
SignedRow SignedRow = 10;
PairsField PairsField = 11;
@ -169,6 +175,7 @@ message QueryResult {
ExtractedIDMatrix ExtractedIDMatrix = 13;
ExtractedTable ExtractedTable = 14;
RowMatrix RowMatrix = 15;
GroupCounts GroupCounts = 16;
}
message ImportRequest {
@ -254,3 +261,8 @@ message ImportColumnAttrsRequest {
repeated uint64 ColumnIDs = 5;
int64 IndexCreatedAt = 6;
}
message GroupCounts{
string Aggregate = 1;
repeated GroupCount Groups = 2;
}

View file

@ -1,7 +1,9 @@
name: "GitHub Import Load Testing (1 day)"
main: "pilosa server --data-dir ${TMPDIR} --txsrc ${TXSRC}"
load: "molecula-consumer-github -i events -d id --record-type event --batch-size=100000 --start-time 2020-01-01T00:00:00Z --end-time 2020-01-01T23:00:00Z --cache-dir .githubarchive"
load: "molecula-consumer-github -i events -d id --record-type event --batch-size=100000 --start-time 2020-01-01T00:00:00Z --end-time 2020-01-01T23:00:00Z --cache-dir ~/.githubarchive"
health_url: "http://localhost:10101/status"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars
- http://localhost:7070/debug/vars

View file

@ -1,7 +1,9 @@
name: "GitHub Import Load Testing (1 month)"
main: "pilosa server --data-dir ${TMPDIR} --txsrc ${TXSRC}"
load: "molecula-consumer-github -i events -d id --record-type event --batch-size=100000 --start-time 2020-01-01T00:00:00Z --end-time 2020-01-31T23:00:00Z --cache-dir .githubarchive"
load: "molecula-consumer-github -i events -d id --record-type event --batch-size=100000 --start-time 2020-01-01T00:00:00Z --end-time 2020-01-31T23:00:00Z --cache-dir ~/.githubarchive"
health_url: "http://localhost:10101/status"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars
- http://localhost:7070/debug/vars

View file

@ -1,7 +1,9 @@
name: "GitHub Import Load Testing (1 week)"
main: "pilosa server --data-dir ${TMPDIR} --txsrc ${TXSRC}"
load: "molecula-consumer-github -i events -d id --record-type event --batch-size=100000 --start-time 2020-01-01T00:00:00Z --end-time 2020-01-06T23:00:00Z --cache-dir .githubarchive"
load: "molecula-consumer-github -i events -d id --record-type event --batch-size=100000 --start-time 2020-01-01T00:00:00Z --end-time 2020-01-06T23:00:00Z --cache-dir ~/.githubarchive"
health_url: "http://localhost:10101/status"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars
- http://localhost:7070/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type count -rate 100 -n 3000"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type difference -rate 10 -n 300"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type groupby -rate 100 -n 3000"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type intersect -rate 100 -n 3000"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type row -rate 100 -n 3000"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type row-range -rate 10 -n 300 -from 2020-01-01T00:00:00Z -
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type row -rate 100 -n 3000"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type row-range -rate 10 -n 300 -from 2020-01-01T00:00:00Z -
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type union -rate 10 -n 300"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -6,4 +6,5 @@ load: "pilosa-bench -type xor -rate 10 -n 300"
health_url: "http://localhost:10101/status"
health_regexp: "NORMAL"
debug_url: "http://localhost:10101/debug"
vars_urls:
- http://localhost:10101/debug/vars

View file

@ -456,7 +456,8 @@ func ToTablerWrapper(result interface{}) (pb.ToTabler, error) {
if !ok {
switch v := result.(type) {
case []pilosa.GroupCount:
toTabler = pilosa.GroupCounts(v)
gc := pilosa.NewGroupCounts("", v...)
toTabler = gc
case uint64:
toTabler = ResultUint64(v)
case bool:
@ -477,7 +478,8 @@ func ToRowserWrapper(result interface{}) (pb.ToRowser, error) {
if !ok {
switch v := result.(type) {
case []pilosa.GroupCount:
toRowser = pilosa.GroupCounts(v)
gc := pilosa.NewGroupCounts("", v...)
toRowser = gc
case uint64:
toRowser = ResultUint64(v)
case bool:

View file

@ -138,7 +138,7 @@ func TestGRPC(t *testing.T) {
},
// []GroupCount (uint64)
{
[]pilosa.GroupCount{
pilosa.NewGroupCounts("", []pilosa.GroupCount{
pilosa.GroupCount{
Group: []pilosa.FieldRow{
{Field: "a", RowID: 10},
@ -160,22 +160,21 @@ func TestGRPC(t *testing.T) {
},
Count: 789,
},
},
}...),
[]expHeader{
{"a", "uint64"},
{"b", "uint64"},
{"count", "uint64"},
{"sum", "int64"},
},
[][]expColumn{
{uint64(10), uint64(11), uint64(123), int64(0)},
{uint64(10), uint64(12), uint64(456), int64(0)},
{int64(va), int64(vb), uint64(789), int64(0)},
{uint64(10), uint64(11), uint64(123)},
{uint64(10), uint64(12), uint64(456)},
{int64(va), int64(vb), uint64(789)},
},
},
// []GroupCount (string)
// []GroupCount (string) + sum
{
[]pilosa.GroupCount{
pilosa.NewGroupCounts("sum", []pilosa.GroupCount{
pilosa.GroupCount{
Group: []pilosa.FieldRow{
{Field: "a", RowKey: "ten"},
@ -190,7 +189,7 @@ func TestGRPC(t *testing.T) {
},
Count: 456,
},
},
}...),
[]expHeader{
{"a", "string"},
{"b", "string"},
@ -292,7 +291,12 @@ func TestGRPC(t *testing.T) {
}
// Ensure headers match.
for i, header := range table.GetHeaders() {
headers := table.GetHeaders()
if len(headers) < len(test.expHeaders) {
t.Fatalf("test %d expected %d headers, got %d, first missing header %q",
ti, len(test.expHeaders), len(headers), test.expHeaders[len(headers)].name)
}
for i, header := range headers {
if header.Name != test.expHeaders[i].name {
t.Fatalf("test %d expected header name: %s, but got: %s", ti, test.expHeaders[i].name, header.Name)
}
@ -303,7 +307,12 @@ func TestGRPC(t *testing.T) {
// Ensure column data matches.
for i, row := range table.GetRows() {
for j, column := range row.GetColumns() {
columns := row.GetColumns()
if len(columns) != len(test.expColumns[i]) {
t.Fatalf("test %d expected %d columns, got %d in row %d",
ti, len(test.expColumns[i]), len(columns), i)
}
for j, column := range columns {
switch v := test.expColumns[i][j].(type) {
case string:
val := column.GetStringVal()

View file

@ -37,6 +37,7 @@ import (
"github.com/pilosa/pilosa/v2/encoding/proto"
"github.com/pilosa/pilosa/v2/http"
"github.com/pilosa/pilosa/v2/pql"
pb "github.com/pilosa/pilosa/v2/proto"
"github.com/pilosa/pilosa/v2/server"
"github.com/pilosa/pilosa/v2/test"
)
@ -1502,6 +1503,16 @@ func TestQueryHistory(t *testing.T) {
test.Do(t, "POST", cmd.URL()+"/index/i0", "")
test.Do(t, "POST", cmd.URL()+"/index/i0/field/f0", "")
gh := server.NewGRPCHandler(cmd.API)
_, err = gh.QuerySQLUnary(context.Background(), &pb.QuerySQLRequest{
Sql: `select * from i0`,
})
if err != nil {
t.Fatalf("QuerySQLUnary failed: %v", err)
}
test.Do(t, "POST", cmd.URL()+"/index/i0/query", "Set(0, f0=0)")
test.Do(t, "POST", cmd.URL()+"/index/i0/query", "Set(3000000, f0=0)")
test.Do(t, "POST", cmd.URL()+"/index/i0/query", "TopN(f0)")
@ -1511,7 +1522,7 @@ func TestQueryHistory(t *testing.T) {
t.Fatalf("unexpected status code: %d", w.Code)
}
ret := make([]pilosa.PastQueryStatus, 3)
ret := make([]pilosa.PastQueryStatus, 4)
b, err := ioutil.ReadAll(w.Body)
if err != nil {
t.Fatalf("reading: %v", err)
@ -1522,10 +1533,10 @@ func TestQueryHistory(t *testing.T) {
}
// verify result length
if len(ret) != 3 {
if len(ret) != 4 {
// each set query executes on both nodes once
// topn query gets added to history on node0 once, node1 twice
t.Fatalf("expected list of length 3, got %d", len(ret))
t.Fatalf("expected list of length 4, got %d\n%+v", len(ret), ret)
}
// verify sort order
@ -1543,8 +1554,14 @@ func TestQueryHistory(t *testing.T) {
if ret[0].Node != cluster.GetNode(0).Server.NodeID() {
t.Fatalf("response value for 'Node' was '%s', expected '%s'", ret[0].Node, cluster.GetNode(0).Server.NodeID())
}
if ret[0].Query != "TopN(f0)" {
t.Fatalf("response value for 'Query' was '%s', expected 'TopN(f0)'", ret[0].Query)
if ret[3].PQL != "Extract(All(),Rows(f0))" {
t.Fatalf("response value for 'PQL' was '%s', expected 'Extract(All(),Rows(f0))'", ret[0].PQL)
}
if ret[3].SQL != "select * from i0" {
t.Fatalf("response value for 'SQL' was '%s', expected 'select * from i0'", ret[0].SQL)
}
if ret[0].PQL != "TopN(f0)" {
t.Fatalf("response value for 'PQL' was '%s', expected 'TopN(f0)'", ret[0].PQL)
}
}

View file

@ -252,27 +252,38 @@ func pgWriteExtractedTable(w pg.QueryResultWriter, tbl pilosa.ExtractedTable) er
return nil
}
func pgWriteGroupCount(w pg.QueryResultWriter, counts []pilosa.GroupCount) error {
if len(counts) == 0 {
func pgWriteGroupCount(w pg.QueryResultWriter, counts *pilosa.GroupCounts) error {
groups := counts.Groups()
if len(groups) == 0 {
// Not enough information is available to construct the header.
// This is a significant flaw in the data type.
return nil
}
expectedLen := len(groups[0].Group) + 1
headers := make([]pg.ColumnInfo, len(counts[0].Group)+2)
for i, g := range counts[0].Group {
agg := counts.AggregateColumn()
if agg != "" {
expectedLen++
}
headers := make([]pg.ColumnInfo, expectedLen)
for i, g := range groups[0].Group {
headers[i] = pg.ColumnInfo{
Name: g.Field,
Type: pg.TypeCharoid,
}
}
headers[len(headers)-2] = pg.ColumnInfo{
next := len(groups[0].Group)
headers[next] = pg.ColumnInfo{
Name: "count",
Type: pg.TypeCharoid,
}
headers[len(headers)-1] = pg.ColumnInfo{
Name: "sum",
Type: pg.TypeCharoid,
if agg != "" {
next++
headers[next] = pg.ColumnInfo{
Name: agg,
Type: pg.TypeCharoid,
}
}
err := w.WriteHeader(headers...)
if err != nil {
@ -280,8 +291,10 @@ func pgWriteGroupCount(w pg.QueryResultWriter, counts []pilosa.GroupCount) error
}
vals := make([]string, len(headers))
for _, gc := range counts {
for j, g := range gc.Group {
for _, gc := range groups {
var j int
var g pilosa.FieldRow
for j, g = range gc.Group {
var v string
switch {
case g.Value != nil:
@ -293,8 +306,12 @@ func pgWriteGroupCount(w pg.QueryResultWriter, counts []pilosa.GroupCount) error
}
vals[j] = v
}
vals[len(vals)-2] = strconv.FormatUint(gc.Count, 10)
vals[len(vals)-1] = strconv.FormatInt(gc.Sum, 10)
j++
vals[j] = strconv.FormatUint(gc.Count, 10)
if agg != "" {
j++
vals[j] = strconv.FormatInt(gc.Agg, 10)
}
err := w.WriteRowText(vals...)
if err != nil {
@ -370,6 +387,9 @@ func pgWriteResult(w pg.QueryResultWriter, result interface{}) error {
case pilosa.ExtractedTable:
return pgWriteExtractedTable(w, result)
case []pilosa.GroupCount:
gc := pilosa.NewGroupCounts("", result...)
return pgWriteGroupCount(w, gc)
case *pilosa.GroupCounts:
return pgWriteGroupCount(w, result)
case pb.ToRowser: // we should avoid protobuf where we can...
return pgWriteRowser(w, result)

View file

@ -169,11 +169,10 @@ func TestPostgresHandler(t *testing.T) {
Columns: []pg.ColumnInfo{
{Name: "set", Type: pg.TypeCharoid},
{Name: "count", Type: pg.TypeCharoid},
{Name: "sum", Type: pg.TypeCharoid},
},
Data: [][]string{
{"4", "3", "0"},
{"5", "3", "0"},
{"4", "3"},
{"5", "3"},
},
},
},

View file

@ -298,7 +298,7 @@ func TestMain_GroupBy(t *testing.T) {
if res, err := m.QueryProtobuf("i", `GroupBy(Rows(generalk), Rows(subk))`); err != nil {
t.Fatal(err)
} else {
test.CheckGroupBy(t, expected, res.Results[0].([]pilosa.GroupCount))
test.CheckGroupBy(t, expected, res.Results[0].(*pilosa.GroupCounts).Groups())
}
}

View file

@ -40,6 +40,7 @@ type MappedSQL struct {
Statement sqlparser.Statement
Mask QueryMask
Tables []string
SQL string
}
// Mapper is responsible for mapping a SQL query to structure representation
@ -109,5 +110,6 @@ func (m *Mapper) MapSQL(sql string) (*MappedSQL, error) {
Statement: stmt,
Mask: qm,
Tables: tableNames,
SQL: sql,
}, nil
}

View file

@ -43,6 +43,7 @@ func NewSelectHandler(api *pilosa.API) *SelectHandler {
// Handle executes mapped SQL
func (s *SelectHandler) Handle(ctx context.Context, mapped *MappedSQL) (pproto.ToRowser, error) {
stmt, ok := mapped.Statement.(*sqlparser.Select)
if !ok {
return nil, fmt.Errorf("statement is not type select: %T", mapped.Statement)
}
@ -50,7 +51,7 @@ func (s *SelectHandler) Handle(ctx context.Context, mapped *MappedSQL) (pproto.T
if err != nil {
return nil, errors.Wrap(err, "mapping select")
}
return s.execMappingResult(ctx, mr)
return s.execMappingResult(ctx, mr, mapped.SQL)
}
func (s *SelectHandler) mapSelect(ctx context.Context, selectStmt *sqlparser.Select, qm QueryMask) (*MappingResult, error) {
@ -74,12 +75,12 @@ func (s *SelectHandler) mapSelect(ctx context.Context, selectStmt *sqlparser.Sel
return mr, nil
}
func (s *SelectHandler) execMappingResult(ctx context.Context, mr *MappingResult) (pproto.ToRowser, error) {
func (s *SelectHandler) execMappingResult(ctx context.Context, mr *MappingResult, sql string) (pproto.ToRowser, error) {
if mr.Query == "" {
return nil, errors.New("no pql query created")
}
resp, err := s.api.Query(ctx, &pilosa.QueryRequest{Index: mr.IndexName, Query: mr.Query})
resp, err := s.api.Query(ctx, &pilosa.QueryRequest{Index: mr.IndexName, Query: mr.Query, SQLQuery: sql})
if err != nil {
return nil, errors.Wrap(err, "doing pql query")
}
@ -90,7 +91,7 @@ func (s *SelectHandler) execMappingResult(ctx context.Context, mr *MappingResult
case pproto.ToRowser:
result = res
case []pilosa.GroupCount:
result = pilosa.GroupCounts(res)
result = pilosa.NewGroupCounts("", res...)
case uint64:
result = pproto.ConstRowser{
{

View file

@ -21,14 +21,16 @@ import (
)
type ActiveQueryStatus struct {
Query string `json:"query"`
PQL string `json:"PQL"`
SQL string `json:"SQL,omitempty"`
Node string `json:"node"`
Index string `json:"index"`
Age time.Duration `json:"age"`
}
type PastQueryStatus struct {
Query string `json:"query"`
PQL string `json:"PQL"`
SQL string `json:"SQL,omitempty"`
Node string `json:"nodeID"`
Index string `json:"index"`
Start time.Time `json:"start"`
@ -36,14 +38,16 @@ type PastQueryStatus struct {
}
type activeQuery struct {
query string
PQL string
SQL string
node string
index string
started time.Time
}
type pastQuery struct {
query string
PQL string
SQL string
node string
index string
started time.Time
@ -123,7 +127,7 @@ func newQueryTracker(historyLength int) *queryTracker {
select {
case update := <-updates:
if update.end {
pq := pastQuery{update.q.query, update.q.node, update.q.index, update.q.started, update.endTime.Sub(update.q.started)}
pq := pastQuery{update.q.PQL, update.q.SQL, update.q.node, update.q.index, update.q.started, update.endTime.Sub(update.q.started)}
tracker.history.add(pq)
delete(activeQueries, update.q)
} else {
@ -146,8 +150,8 @@ func newQueryTracker(historyLength int) *queryTracker {
return tracker
}
func (t *queryTracker) Start(query, nodeID, index string, start time.Time) *activeQuery {
q := &activeQuery{query, nodeID, index, start}
func (t *queryTracker) Start(pql, sql, nodeID, index string, start time.Time) *activeQuery {
q := &activeQuery{pql, sql, nodeID, index, start}
t.updates <- queryStatusUpdate{q, false, time.Time{}}
return q
}
@ -166,9 +170,9 @@ func (t *queryTracker) ActiveQueries() []ActiveQueryStatus {
return true
case queries[i].started.After(queries[j].started):
return false
case queries[i].query < queries[j].query:
case queries[i].PQL < queries[j].PQL:
return true
case queries[i].query > queries[j].query:
case queries[i].PQL > queries[j].PQL:
return false
default:
return false
@ -177,7 +181,7 @@ func (t *queryTracker) ActiveQueries() []ActiveQueryStatus {
now := time.Now()
out := make([]ActiveQueryStatus, len(queries))
for i, v := range queries {
out[i] = ActiveQueryStatus{v.query, v.node, v.index, now.Sub(v.started)}
out[i] = ActiveQueryStatus{v.PQL, v.SQL, v.node, v.index, now.Sub(v.started)}
}
return out
}
@ -186,7 +190,7 @@ func (t *queryTracker) PastQueries() []PastQueryStatus {
queries := t.history.slice()
out := make([]PastQueryStatus, len(queries))
for i, v := range queries {
out[i] = PastQueryStatus{v.query, v.node, v.index, v.started, v.runtime}
out[i] = PastQueryStatus{v.PQL, v.SQL, v.node, v.index, v.started, v.runtime}
}
return out

View file

@ -47,11 +47,11 @@ func TestRingBuffer(t *testing.T) {
}
for n, q := range buffer.slice() {
if q.query != tests[k].queries[n] {
t.Fatalf("test[%d], buffer[%d] expected querystring '%s', found '%s'", k, n, tests[k].queries[n], q.query)
if q.PQL != tests[k].queries[n] {
t.Fatalf("test[%d], buffer[%d] expected querystring '%s', found '%s'", k, n, tests[k].queries[n], q.PQL)
}
}
buffer.add(pastQuery{query: fmt.Sprintf("%d", k)})
buffer.add(pastQuery{PQL: fmt.Sprintf("%d", k)})
}
}
@ -63,13 +63,13 @@ func TestQueryTracker(t *testing.T) {
t.Fatalf("expected no active queries; found %v", queries)
}
qs := tracker.Start("test query", "node0", "i", time.Now())
qs := tracker.Start("test query", "test SQL", "node0", "i", time.Now())
var queries []ActiveQueryStatus
for len(queries) < 1 {
queries = tracker.ActiveQueries()
}
if len(queries) > 1 || queries[0].Query != "test query" {
if len(queries) > 1 || queries[0].PQL != "test query" {
t.Fatalf("unexpected queries: %v", queries)
}