Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Add GroupByBase method which takes function options #261

Merged
merged 2 commits into from
Nov 21, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions orm.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,93 @@ func (idx *Index) Options(row *PQLRowQuery, opts ...OptionsOption) *PQLBaseQuery
return NewPQLBaseQuery(text, idx, nil)
}

type groupByBuilder struct {
rows []*PQLRowsQuery
limit int64
filter *PQLRowQuery
aggregate *PQLBaseQuery
}

// groupByBuilderOption is a functional option type for index.GroupBy
type groupByBuilderOption func(g *groupByBuilder) error

// OptGroupByBuilderRows is a functional option on groupByBuilder
// used to set the rows.
func OptGroupByBuilderRows(rows ...*PQLRowsQuery) groupByBuilderOption {
return func(g *groupByBuilder) error {
g.rows = rows
return nil
}
}

// OptGroupByBuilderLimit is a functional option on groupByBuilder
// used to set the limit.
func OptGroupByBuilderLimit(l int64) groupByBuilderOption {
return func(g *groupByBuilder) error {
g.limit = l
return nil
}
}

// OptGroupByBuilderFilter is a functional option on groupByBuilder
// used to set the filter.
func OptGroupByBuilderFilter(q *PQLRowQuery) groupByBuilderOption {
return func(g *groupByBuilder) error {
g.filter = q
return nil
}
}

// OptGroupByBuilderAggregate is a functional option on groupByBuilder
// used to set the aggregate.
func OptGroupByBuilderAggregate(agg *PQLBaseQuery) groupByBuilderOption {
return func(g *groupByBuilder) error {
g.aggregate = agg
return nil
}
}

// GroupByBase creates a GroupBy query with the given functional options.
func (idx *Index) GroupByBase(opts ...groupByBuilderOption) *PQLBaseQuery {
bldr := &groupByBuilder{}
for _, opt := range opts {
err := opt(bldr)
if err != nil {
return NewPQLBaseQuery("", idx, errors.Wrap(err, "applying option"))
}
}

if len(bldr.rows) < 1 {
return NewPQLBaseQuery("", idx, errors.New("there should be at least one rows query"))
}
if bldr.limit < 0 {
return NewPQLBaseQuery("", idx, errors.New("limit must be non-negative"))
}

// rows
text := fmt.Sprintf("GroupBy(%s", strings.Join(serializeGroupBy(bldr.rows...), ","))

// limit
if bldr.limit > 0 {
text += fmt.Sprintf(",limit=%d", bldr.limit)
}

// filter
if bldr.filter != nil {
filterText := bldr.filter.serialize().String()
text += fmt.Sprintf(",filter=%s", filterText)
}

// aggregate
if bldr.aggregate != nil {
aggregateText := bldr.aggregate.Serialize().String()
text += fmt.Sprintf(",aggregate=%s", aggregateText)
}

text += ")"
return NewPQLBaseQuery(text, idx, nil)
}

// GroupBy creates a GroupBy query with the given Rows queries
func (idx *Index) GroupBy(rowsQueries ...*PQLRowsQuery) *PQLBaseQuery {
if len(rowsQueries) < 1 {
Expand Down
72 changes: 72 additions & 0 deletions orm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,78 @@ func TestGroupByLimitFilter(t *testing.T) {
}
}

func TestGroupByBase(t *testing.T) {
field := sampleIndex.Field("test")
comparePQL(t,
"GroupBy(Rows(field='collaboration'))",
sampleIndex.GroupByBase(
OptGroupByBuilderRows(collabField.Rows()),
),
)
comparePQL(t,
"GroupBy(Rows(field='collaboration'),Rows(field='test'))",
sampleIndex.GroupByBase(
OptGroupByBuilderRows(collabField.Rows(), field.Rows()),
),
)

comparePQL(t,
"GroupBy(Rows(field='collaboration'),limit=10)",
sampleIndex.GroupByBase(
OptGroupByBuilderLimit(10),
OptGroupByBuilderRows(collabField.Rows()),
),
)
comparePQL(t,
"GroupBy(Rows(field='collaboration'),Rows(field='test'),limit=10)",
sampleIndex.GroupByBase(
OptGroupByBuilderLimit(10),
OptGroupByBuilderRows(collabField.Rows(), field.Rows()),
),
)

comparePQL(t,
"GroupBy(Rows(field='collaboration'),filter=Row(test=5))",
sampleIndex.GroupByBase(
OptGroupByBuilderFilter(field.Row(5)),
OptGroupByBuilderRows(collabField.Rows()),
),
)
comparePQL(t,
"GroupBy(Rows(field='collaboration'),Rows(field='test'),filter=Row(test=5))",
sampleIndex.GroupByBase(
OptGroupByBuilderFilter(field.Row(5)),
OptGroupByBuilderRows(collabField.Rows(), field.Rows()),
),
)

comparePQL(t,
"GroupBy(Rows(field='collaboration'),limit=10,filter=Row(test=5))",
sampleIndex.GroupByBase(
OptGroupByBuilderLimit(10),
OptGroupByBuilderFilter(field.Row(5)),
OptGroupByBuilderRows(collabField.Rows()),
),
)
comparePQL(t,
"GroupBy(Rows(field='collaboration'),Rows(field='test'),limit=10,filter=Row(test=5))",
sampleIndex.GroupByBase(
OptGroupByBuilderLimit(10),
OptGroupByBuilderFilter(field.Row(5)),
OptGroupByBuilderRows(collabField.Rows(), field.Rows()),
),
)

field2 := sampleIndex.Field("age")
comparePQL(t,
"GroupBy(Rows(field='collaboration'),Rows(field='test'),aggregate=Sum(Row(age=20),field='age'))",
sampleIndex.GroupByBase(
OptGroupByBuilderRows(collabField.Rows(), field.Rows()),
OptGroupByBuilderAggregate(field2.Sum(field2.Row(20))),
),
)
}

func TestFieldOptions(t *testing.T) {
field := sampleIndex.Field("foo", OptFieldKeys(true))
if true != field.Opts().Keys() {
Expand Down