Exemple #1
0
func (this *builder) VisitSelect(stmt *algebra.Select) (interface{}, error) {
	// Restore previous values when exiting. VisitSelect()
	// can be called multiple times by set operators
	prevCover := this.cover
	prevOrder := this.order
	prevLimit := this.limit
	prevProjection := this.delayProjection
	defer func() {
		this.cover = prevCover
		this.order = prevOrder
		this.limit = prevLimit
		this.delayProjection = prevProjection
	}()

	order := stmt.Order()
	offset := stmt.Offset()
	limit := stmt.Limit()

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

	if order != nil || offset != nil {
		this.limit = nil
	} else if limit != nil {
		this.limit = limit
	}

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

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

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

	if order != nil {
		children = append(children, plan.NewOrder(order))
	}

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

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

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

	return plan.NewSequence(children...), nil
}