コード例 #1
0
ファイル: build_select.go プロジェクト: amarantha-k/query
func (this *builder) VisitSelect(stmt *algebra.Select) (interface{}, error) {
	order := stmt.Order()
	offset := stmt.Offset()
	limit := stmt.Limit()
	delayProjection := this.delayProjection

	// If there is an ORDER BY, delay the final projection
	if order != nil {
		this.order = order
		this.delayProjection = true
	}

	sub, err := stmt.Subresult().Accept(this)
	if err != nil {
		return nil, err
	}

	if order == nil && offset == nil && limit == nil {
		return sub, nil
	}

	children := make([]Operator, 0, 5)
	children = append(children, sub.(Operator))

	if order != nil {
		if this.order == nil {
			// Disallow aggregates in ORDER BY
			aggs := make(map[string]algebra.Aggregate)
			for _, term := range order.Terms() {
				collectAggregates(aggs, term.Expression())
				if len(aggs) > 0 {
					return nil, fmt.Errorf("Aggregates not available for this ORDER BY.")
				}
			}
		}

		children = append(children, NewOrder(order))
	}

	if offset != nil {
		children = append(children, NewOffset(offset))
	}

	if limit != nil {
		children = append(children, NewLimit(limit))
	}

	// Perform the delayed final projection now, after the ORDER BY
	if this.delayProjection {
		children = append(children, NewParallel(NewFinalProject()))
		this.delayProjection = delayProjection
	}

	return NewSequence(children...), nil
}