func (this *builder) fastCount(node *algebra.Subselect) (bool, error) { if node.From() == nil || node.Where() != nil || node.Group() != nil { return false, nil } from, ok := node.From().(*algebra.KeyspaceTerm) if !ok { return false, nil } from.SetDefaultNamespace(this.namespace) keyspace, err := this.getTermKeyspace(from) if err != nil { return false, err } for _, term := range node.Projection().Terms() { count, ok := term.Expression().(*algebra.Count) if !ok || count.Operand() != nil { return false, nil } } scan := NewCountScan(keyspace, from) this.children = append(this.children, scan) return true, nil }
func (this *builder) VisitSubselect(node *algebra.Subselect) (interface{}, error) { this.where = node.Where() this.children = make([]Operator, 0, 16) // top-level children, executed sequentially this.subChildren = make([]Operator, 0, 16) // sub-children, executed across data-parallel streams count, err := this.fastCount(node) if err != nil { return nil, err } if count { // do nothing } else if node.From() != nil { _, err := node.From().Accept(this) if err != nil { return nil, err } } else { // No FROM clause scan := NewDummyScan() this.children = append(this.children, scan) } aggs := make(map[string]algebra.Aggregate) if node.Let() != nil { for _, binding := range node.Let() { collectAggregates(aggs, binding.Expression()) if len(aggs) > 0 { return nil, fmt.Errorf("Aggregates not allowed in LET.") } } this.subChildren = append(this.subChildren, NewLet(node.Let())) } if node.Where() != nil { collectAggregates(aggs, node.Where()) if len(aggs) > 0 { return nil, fmt.Errorf("Aggregates not allowed in WHERE.") } this.subChildren = append(this.subChildren, NewFilter(node.Where())) } // Check for aggregates projection := node.Projection() if projection != nil { for _, term := range projection.Terms() { if term.Expression() != nil { collectAggregates(aggs, term.Expression()) } } } group := node.Group() if this.order != nil && (group != nil || len(aggs) > 0) { // Grouping -- include aggregates from ORDER BY for _, term := range this.order.Terms() { if term.Expression() != nil { collectAggregates(aggs, term.Expression()) } } } else { // Not grouping -- disallow aggregates in ORDER BY this.order = nil } if group == nil && len(aggs) > 0 { group = algebra.NewGroup(nil, nil, nil) } if group != nil { this.visitGroup(group, aggs) } this.subChildren = append(this.subChildren, NewInitialProject(projection)) // Initial DISTINCT (parallel) if projection.Distinct() || this.distinct { this.subChildren = append(this.subChildren, NewDistinct()) } if !this.delayProjection { // Perform the final projection if there is no subsequent ORDER BY this.subChildren = append(this.subChildren, NewFinalProject()) } // Parallelize the subChildren this.children = append(this.children, NewParallel(NewSequence(this.subChildren...))) // Final DISTINCT (serial) if projection.Distinct() || this.distinct { this.children = append(this.children, NewDistinct()) } // Serialize the top-level children return NewSequence(this.children...), nil }