コード例 #1
0
ファイル: build_delete.go プロジェクト: mschoch/query
func (this *builder) VisitDelete(stmt *algebra.Delete) (interface{}, error) {
	this.cover = stmt
	this.where = stmt.Where()

	ksref := stmt.KeyspaceRef()
	keyspace, err := this.getNameKeyspace(ksref.Namespace(), ksref.Keyspace())
	if err != nil {
		return nil, err
	}

	err = this.beginMutate(keyspace, ksref, stmt.Keys(), stmt.Indexes(), stmt.Limit())
	if err != nil {
		return nil, err
	}

	subChildren := this.subChildren
	subChildren = append(subChildren, plan.NewSendDelete(keyspace, ksref.Alias(), stmt.Limit()))

	if stmt.Returning() != nil {
		subChildren = append(subChildren, plan.NewInitialProject(stmt.Returning()), plan.NewFinalProject())
	}

	parallel := plan.NewParallel(plan.NewSequence(subChildren...), this.maxParallelism)
	this.children = append(this.children, parallel)

	if stmt.Limit() != nil {
		this.children = append(this.children, plan.NewLimit(stmt.Limit()))
	}

	if stmt.Returning() == nil {
		this.children = append(this.children, plan.NewDiscard())
	}

	return plan.NewSequence(this.children...), nil
}
コード例 #2
0
ファイル: build_select_sub.go プロジェクト: jmptrader/query
func (this *builder) visitGroup(group *algebra.Group, aggs map[string]algebra.Aggregate) {
	aggn := make(sort.StringSlice, 0, len(aggs))
	for n, _ := range aggs {
		aggn = append(aggn, n)
	}

	aggn.Sort()
	aggv := make(algebra.Aggregates, len(aggs))
	for i, n := range aggn {
		aggv[i] = aggs[n]
	}

	this.subChildren = append(this.subChildren, plan.NewInitialGroup(group.By(), aggv))
	this.children = append(this.children, plan.NewParallel(plan.NewSequence(this.subChildren...), this.maxParallelism))
	this.children = append(this.children, plan.NewIntermediateGroup(group.By(), aggv))
	this.children = append(this.children, plan.NewFinalGroup(group.By(), aggv))
	this.subChildren = make([]plan.Operator, 0, 8)

	letting := group.Letting()
	if letting != nil {
		this.subChildren = append(this.subChildren, plan.NewLet(letting))
	}

	having := group.Having()
	if having != nil {
		this.subChildren = append(this.subChildren, plan.NewFilter(having))
	}
}
コード例 #3
0
ファイル: build.go プロジェクト: pkdevboxy/query
func Build(stmt algebra.Statement, datastore, systemstore datastore.Datastore,
	namespace string, subquery bool) (plan.Operator, error) {
	builder := newBuilder(datastore, systemstore, namespace, subquery)
	o, err := stmt.Accept(builder)

	if err != nil {
		return nil, err
	}

	op := o.(plan.Operator)
	_, is_prepared := o.(*plan.Prepared)

	if !subquery && !is_prepared {
		privs, er := stmt.Privileges()
		if er != nil {
			return nil, er
		}

		if len(privs) > 0 {
			op = plan.NewAuthorize(privs, op)
		}

		return plan.NewSequence(op, plan.NewStream()), nil
	} else {
		return op, nil
	}
}
コード例 #4
0
ファイル: build_upsert.go プロジェクト: pkdevboxy/query
func (this *builder) VisitUpsert(stmt *algebra.Upsert) (interface{}, error) {
	ksref := stmt.KeyspaceRef()
	ksref.SetDefaultNamespace(this.namespace)

	keyspace, err := this.getNameKeyspace(ksref.Namespace(), ksref.Keyspace())
	if err != nil {
		return nil, err
	}

	children := make([]plan.Operator, 0, 4)

	if stmt.Values() != nil {
		children = append(children, plan.NewValueScan(stmt.Values()))
		this.maxParallelism = util.MaxInt(1, len(stmt.Values()))
	} else if stmt.Select() != nil {
		sel, err := stmt.Select().Accept(this)
		if err != nil {
			return nil, err
		}

		children = append(children, sel.(plan.Operator))
	} else {
		return nil, fmt.Errorf("UPSERT missing both VALUES and SELECT.")
	}

	subChildren := make([]plan.Operator, 0, 4)
	subChildren = append(subChildren, plan.NewSendUpsert(keyspace, ksref.Alias(), stmt.Key(), stmt.Value()))

	if stmt.Returning() != nil {
		subChildren = append(subChildren, plan.NewInitialProject(stmt.Returning()), plan.NewFinalProject())
	} else {
		subChildren = append(subChildren, plan.NewDiscard())
	}

	parallel := plan.NewParallel(plan.NewSequence(subChildren...), this.maxParallelism)
	children = append(children, parallel)
	return plan.NewSequence(children...), nil
}
コード例 #5
0
ファイル: build_set_op.go プロジェクト: pkdevboxy/query
func (this *builder) VisitUnion(node *algebra.Union) (interface{}, error) {
	// Inject DISTINCT into both terms
	distinct := this.distinct
	this.distinct = true
	defer func() { this.distinct = distinct }()

	this.order = nil             // Disable aggregates from ORDER BY
	this.delayProjection = false // Disable ORDER BY non-projected expressions
	this.limit = nil

	first, err := node.First().Accept(this)
	if err != nil {
		return nil, err
	}

	second, err := node.Second().Accept(this)
	if err != nil {
		return nil, err
	}

	this.maxParallelism = 0
	unionAll := plan.NewUnionAll(first.(plan.Operator), second.(plan.Operator))
	return plan.NewSequence(unionAll, plan.NewDistinct()), nil
}
コード例 #6
0
ファイル: build_select_sub.go プロジェクト: jmptrader/query
func (this *builder) VisitSubselect(node *algebra.Subselect) (interface{}, error) {
	prevCover := this.cover
	prevCorrelated := this.correlated
	defer func() {
		this.cover = prevCover
		this.correlated = prevCorrelated
	}()

	this.correlated = node.IsCorrelated()

	if this.cover == nil {
		this.cover = node
	}

	aggs, err := allAggregates(node, this.order)
	if err != nil {
		return nil, err
	}

	this.where = node.Where()

	group := node.Group()
	if group == nil && len(aggs) > 0 {
		group = algebra.NewGroup(nil, nil, nil)
		this.where = constrainAggregate(this.where, aggs)
	}

	this.children = make([]plan.Operator, 0, 16)    // top-level children, executed sequentially
	this.subChildren = make([]plan.Operator, 0, 16) // sub-children, executed across data-parallel streams

	err = this.visitFrom(node, group)
	if err != nil {
		return nil, err
	}

	if this.coveringScan != nil {
		coverer := expression.NewCoverer(this.coveringScan.Covers())
		err = this.cover.MapExpressions(coverer)
		if err != nil {
			return nil, err
		}

		if this.where != nil {
			this.where, err = coverer.Map(this.where)
			if err != nil {
				return nil, err
			}
		}
	}

	if node.Let() != nil {
		this.subChildren = append(this.subChildren, plan.NewLet(node.Let()))
	}

	if node.Where() != nil {
		this.subChildren = append(this.subChildren, plan.NewFilter(node.Where()))
	}

	if group != nil {
		this.visitGroup(group, aggs)
	}

	projection := node.Projection()
	this.subChildren = append(this.subChildren, plan.NewInitialProject(projection))

	// Initial DISTINCT (parallel)
	if projection.Distinct() || this.distinct {
		this.subChildren = append(this.subChildren, plan.NewDistinct())
	}

	if !this.delayProjection {
		// Perform the final projection if there is no subsequent ORDER BY
		this.subChildren = append(this.subChildren, plan.NewFinalProject())
	}

	// Parallelize the subChildren
	this.children = append(this.children, plan.NewParallel(plan.NewSequence(this.subChildren...), this.maxParallelism))

	// Final DISTINCT (serial)
	if projection.Distinct() || this.distinct {
		this.children = append(this.children, plan.NewDistinct())
	}

	// Serialize the top-level children
	return plan.NewSequence(this.children...), nil
}
コード例 #7
0
ファイル: build_select.go プロジェクト: jmptrader/query
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
}
コード例 #8
0
ファイル: build_merge.go プロジェクト: pkdevboxy/query
func (this *builder) VisitMerge(stmt *algebra.Merge) (interface{}, error) {
	children := make([]plan.Operator, 0, 8)
	subChildren := make([]plan.Operator, 0, 8)
	source := stmt.Source()

	if source.Select() != nil {
		sel, err := source.Select().Accept(this)
		if err != nil {
			return nil, err
		}

		children = append(children, sel.(plan.Operator))
	} else {
		if source.From() == nil {
			return nil, fmt.Errorf("MERGE missing source.")
		}

		_, err := source.From().Accept(this)
		if err != nil {
			return nil, err
		}

		// Update local operator slices with results of building From:
		children = append(children, this.children...)
		subChildren = append(subChildren, this.subChildren...)

	}

	if source.As() != "" {
		subChildren = append(subChildren, plan.NewAlias(source.As()))
	}

	ksref := stmt.KeyspaceRef()
	ksref.SetDefaultNamespace(this.namespace)

	keyspace, err := this.getNameKeyspace(ksref.Namespace(), ksref.Keyspace())
	if err != nil {
		return nil, err
	}

	actions := stmt.Actions()
	var update, delete, insert plan.Operator

	if actions.Update() != nil {
		act := actions.Update()
		ops := make([]plan.Operator, 0, 5)

		if act.Where() != nil {
			ops = append(ops, plan.NewFilter(act.Where()))
		}

		ops = append(ops, plan.NewClone(ksref.Alias()))

		if act.Set() != nil {
			ops = append(ops, plan.NewSet(act.Set()))
		}

		if act.Unset() != nil {
			ops = append(ops, plan.NewUnset(act.Unset()))
		}

		ops = append(ops, plan.NewSendUpdate(keyspace, ksref.Alias(), stmt.Limit()))
		update = plan.NewSequence(ops...)
	}

	if actions.Delete() != nil {
		act := actions.Delete()
		ops := make([]plan.Operator, 0, 4)

		if act.Where() != nil {
			ops = append(ops, plan.NewFilter(act.Where()))
		}

		ops = append(ops, plan.NewSendDelete(keyspace, ksref.Alias(), stmt.Limit()))
		delete = plan.NewSequence(ops...)
	}

	if actions.Insert() != nil {
		act := actions.Insert()
		ops := make([]plan.Operator, 0, 4)

		if act.Where() != nil {
			ops = append(ops, plan.NewFilter(act.Where()))
		}

		ops = append(ops, plan.NewSendInsert(keyspace, ksref.Alias(), stmt.Key(), act.Value(), stmt.Limit()))
		insert = plan.NewSequence(ops...)
	}

	merge := plan.NewMerge(keyspace, ksref, stmt.Key(), update, delete, insert)
	subChildren = append(subChildren, merge)

	if stmt.Returning() != nil {
		subChildren = append(subChildren, plan.NewInitialProject(stmt.Returning()), plan.NewFinalProject())
	}

	parallel := plan.NewParallel(plan.NewSequence(subChildren...), this.maxParallelism)
	children = append(children, parallel)

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

	if stmt.Returning() == nil {
		children = append(children, plan.NewDiscard())
	}

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