コード例 #1
0
ファイル: scan_key.go プロジェクト: amarantha-k/query
func (this *KeyScan) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped

		keys, e := this.plan.Keys().Evaluate(parent, context)
		if e != nil {
			context.Error(errors.NewError(e, "Error evaluating KEYS."))
			return
		}

		actuals := keys.Actual()
		switch actuals.(type) {
		case []interface{}:
		case nil:
			actuals = []interface{}(nil)
		default:
			actuals = []interface{}{actuals}
		}

		acts := actuals.([]interface{})

		for _, key := range acts {
			cv := value.NewScopeValue(make(map[string]interface{}), parent)
			av := value.NewAnnotatedValue(cv)
			av.SetAttachment("meta", map[string]interface{}{"id": key})
			if !this.sendItem(av) {
				return
			}
		}
	})
}
コード例 #2
0
ファイル: scan_primary.go プロジェクト: amarantha-k/query
func (this *PrimaryScan) scanPrimary(context *Context, parent value.Value) {
	conn := datastore.NewIndexConnection(context)
	defer notifyConn(conn) // Notify index that I have stopped

	go this.scanEntries(context, conn)

	var entry *datastore.IndexEntry
	ok := true
	for ok {
		select {
		case <-this.stopChannel:
			return
		default:
		}

		select {
		case entry, ok = <-conn.EntryChannel():
			if ok {
				cv := value.NewScopeValue(make(map[string]interface{}), parent)
				av := value.NewAnnotatedValue(cv)
				av.SetAttachment("meta", map[string]interface{}{"id": entry.PrimaryKey})
				ok = this.sendItem(av)
			}
		case <-this.stopChannel:
			return
		}
	}
}
コード例 #3
0
ファイル: scan_value.go プロジェクト: amarantha-k/query
func (this *ValueScan) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped

		pairs := this.plan.Values()
		for _, pair := range pairs {
			key, err := pair.Key.Evaluate(parent, context)
			if err != nil {
				context.Error(errors.NewError(err, "Error evaluating VALUES."))
				return
			}

			val, err := pair.Value.Evaluate(parent, context)
			if err != nil {
				context.Error(errors.NewError(err, "Error evaluating VALUES."))
				return
			}

			av := value.NewAnnotatedValue(nil)
			av.SetAttachment("key", key)
			av.SetAttachment("value", val)

			if !this.sendItem(av) {
				return
			}
		}
	})
}
コード例 #4
0
ファイル: scan_index.go プロジェクト: amarantha-k/query
func (this *spanScan) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped

		conn := datastore.NewIndexConnection(context)
		defer notifyConn(conn) // Notify index that I have stopped

		go this.scan(context, conn)

		var entry *datastore.IndexEntry
		ok := true
		for ok {
			select {
			case <-this.stopChannel:
				return
			default:
			}

			select {
			case entry, ok = <-conn.EntryChannel():
				if ok {
					cv := value.NewScopeValue(make(map[string]interface{}), parent)
					av := value.NewAnnotatedValue(cv)
					av.SetAttachment("meta", map[string]interface{}{"id": entry.PrimaryKey})
					ok = this.sendItem(av)
				}
			case <-this.stopChannel:
				return
			}
		}
	})
}
コード例 #5
0
ファイル: project_initial.go プロジェクト: amarantha-k/query
func (this *InitialProject) processItem(item value.AnnotatedValue, context *Context) bool {
	terms := this.plan.Terms()
	n := len(terms)

	if n > 1 {
		return this.processTerms(item, context)
	}

	if n == 0 {
		return this.sendItem(item)
	}

	// n == 1

	result := terms[0].Result()
	expr := result.Expression()

	if expr == nil {
		// Unprefixed star
		if item.Type() == value.OBJECT {
			return this.sendItem(item)
		} else {
			return this.sendItem(_EMPTY_ANNOTATED_VALUE)
		}
	} else if this.plan.Projection().Raw() {
		// Raw projection of an expression
		v, err := expr.Evaluate(item, context)
		if err != nil {
			context.Error(errors.NewError(err, "Error evaluating projection."))
			return false
		}

		if result.As() == "" {
			return this.sendItem(value.NewAnnotatedValue(v))
		}

		sv := value.NewScopeValue(make(map[string]interface{}, 1), item)
		sv.SetField(result.As(), v)
		av := value.NewAnnotatedValue(sv)
		av.SetAttachment("projection", v)
		return this.sendItem(av)
	} else {
		// Any other projection
		return this.processTerms(item, context)
	}
}
コード例 #6
0
ファイル: project_final.go プロジェクト: amarantha-k/query
func (this *FinalProject) processItem(item value.AnnotatedValue, context *Context) bool {
	pv := item.GetAttachment("projection")
	if pv != nil {
		v := pv.(value.Value)
		return this.sendItem(value.NewAnnotatedValue(v))
	}

	return this.sendItem(item)
}
コード例 #7
0
ファイル: project_initial.go プロジェクト: amarantha-k/query
func (this *InitialProject) processTerms(item value.AnnotatedValue, context *Context) bool {
	n := len(this.plan.Terms())

	var f map[string]interface{}
	if item.Type() == value.OBJECT {
		f = item.Copy().Fields()
	}

	if f == nil {
		f = make(map[string]interface{}, n)
	}

	pv := value.NewAnnotatedValue(f)
	pv.SetAttachments(item.Attachments())

	p := value.NewValue(make(map[string]interface{}, n+32))
	pv.SetAttachment("projection", p)

	for _, term := range this.plan.Terms() {
		if term.Result().Alias() != "" {
			v, err := term.Result().Expression().Evaluate(item, context)
			if err != nil {
				context.Error(errors.NewError(err, "Error evaluating projection."))
				return false
			}

			p.SetField(term.Result().Alias(), v)

			// Explicit aliases override data
			if term.Result().As() != "" {
				pv.SetField(term.Result().As(), v)
			}
		} else {
			// Star
			starval := item.GetValue()
			if term.Result().Expression() != nil {
				var err error
				starval, err = term.Result().Expression().Evaluate(item, context)
				if err != nil {
					context.Error(errors.NewError(err, "Error evaluating projection."))
					return false
				}
			}

			// Latest star overwrites previous star
			switch sa := starval.Actual().(type) {
			case map[string]interface{}:
				for k, v := range sa {
					p.SetField(k, v)
				}
			}
		}
	}

	return this.sendItem(pv)
}
コード例 #8
0
ファイル: prepare.go プロジェクト: amarantha-k/query
func (this *Prepare) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped
		value := value.NewAnnotatedValue(this.plan)
		this.sendItem(value)

	})
}
コード例 #9
0
func (b *storeKeyspace) fetchOne(key string) (value.AnnotatedValue, errors.Error) {
	if key == b.namespace.store.actualStore.Id() {
		doc := value.NewAnnotatedValue(map[string]interface{}{
			"id":  b.namespace.store.actualStore.Id(),
			"url": b.namespace.store.actualStore.URL(),
		})
		return doc, nil
	}
	return nil, errors.NewSystemDatastoreError(nil, "Key Not Found "+key)
}
コード例 #10
0
ファイル: mock.go プロジェクト: amarantha-k/query
// generate a mock document - used by fetchOne to mock a document in the keyspace
func genItem(i int, nitems int) (value.AnnotatedValue, errors.Error) {
	if i < 0 || i >= nitems {
		return nil, errors.NewOtherDatastoreError(nil,
			fmt.Sprintf("item out of mock range: %v [0,%v)", i, nitems))
	}
	id := strconv.Itoa(i)
	doc := value.NewAnnotatedValue(map[string]interface{}{"id": id, "i": float64(i)})
	doc.SetAttachment("meta", map[string]interface{}{"id": id})
	return doc, nil
}
コード例 #11
0
ファイル: scan_dummy.go プロジェクト: amarantha-k/query
func (this *DummyScan) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped

		cv := value.NewScopeValue(nil, parent)
		av := value.NewAnnotatedValue(cv)
		this.sendItem(av)
	})
}
コード例 #12
0
func (b *namespaceKeyspace) fetchOne(key string) (value.AnnotatedValue, errors.Error) {
	namespace, excp := b.namespace.store.actualStore.NamespaceById(key)
	if namespace != nil {
		doc := value.NewAnnotatedValue(map[string]interface{}{
			"id":           namespace.Id(),
			"name":         namespace.Name(),
			"datastore_id": b.namespace.store.actualStore.Id(),
		})
		return doc, nil
	}
	return nil, errors.NewSystemDatastoreError(excp, "Key Not Found "+key)
}
コード例 #13
0
ファイル: agg_util.go プロジェクト: amarantha-k/query
/*
Add input item to the cumulative set. Get the set. If
no errors enountered add the item to the set and return
it. If set has not been initialized yet, create a new set
with capacity _OBJECT_CAP and add the item. Return the
set value.
*/
func setAdd(item, cumulative value.Value) (value.Value, error) {
	set, e := getSet(cumulative)
	if e == nil {
		set.Add(item)
		return cumulative, nil
	}

	set = value.NewSet(_OBJECT_CAP)
	set.Add(item)
	av := value.NewAnnotatedValue(nil)
	av.SetAttachment("set", set)
	return av, nil
}
コード例 #14
0
ファイル: distinct.go プロジェクト: amarantha-k/query
func (this *Distinct) afterItems(context *Context) {
	if this.collect {
		return
	}

	for _, av := range this.set.Values() {
		if !this.sendItem(value.NewAnnotatedValue(av)) {
			return
		}
	}

	this.set = nil
}
コード例 #15
0
func (b *indexKeyspace) fetchOne(key string) ([]datastore.AnnotatedPair, errors.Error) {
	rv := make([]datastore.AnnotatedPair, 0, 2)
	ids := strings.SplitN(key, "/", 3)

	actualStore := b.namespace.store.actualStore
	namespace, err := actualStore.NamespaceById(ids[0])
	if err != nil {
		return nil, err
	}

	keyspace, err := namespace.KeyspaceById(ids[1])
	if err != nil {
		return nil, err
	}

	indexers, err := keyspace.Indexers()
	if err != nil {
		return nil, err
	}

	for _, indexer := range indexers {
		index, err := indexer.IndexById(ids[2])
		if err != nil {
			continue
		}

		state, msg, err := index.State()
		if err != nil {
			return nil, err
		}

		doc := value.NewAnnotatedValue(map[string]interface{}{
			"id":           index.Id(),
			"name":         index.Name(),
			"keyspace_id":  keyspace.Id(),
			"namespace_id": namespace.Id(),
			"datastore_id": actualStore.Id(),
			"index_key":    datastoreObjectToJSONSafe(indexKeyToIndexKeyStringArray(index.RangeKey())),
			"using":        datastoreObjectToJSONSafe(index.Type()),
			"state":        string(state),
		})

		if msg != "" {
			doc.SetField("message", msg)
		}

		rv = append(rv, datastore.AnnotatedPair{key, doc})
	}

	return rv, nil
}
コード例 #16
0
ファイル: merge.go プロジェクト: amarantha-k/query
func (this *Merge) processMatch(item value.AnnotatedValue,
	context *Context, update, delete, insert Operator) bool {
	kv, e := this.plan.Key().Evaluate(item, context)
	if e != nil {
		context.Error(errors.NewError(e, "Error evaluatating MERGE key."))
		return false
	}

	ka := kv.Actual()
	k, ok := ka.(string)
	if !ok {
		context.Error(errors.NewError(nil,
			fmt.Sprintf("Invalid MERGE key %v of type %T.", ka, ka)))
		return false
	}

	bvs, err := this.plan.Keyspace().Fetch([]string{k})
	if err != nil {
		context.Error(err)
		return false
	}

	if len(bvs) > 0 {
		bv := bvs[0].Value

		// Matched; join source and target
		if update != nil {
			item.SetAttachment("target", bv)
		}

		abv := value.NewAnnotatedValue(bv)
		item.SetField(this.plan.KeyspaceRef().Alias(), abv)

		// Perform UPDATE and/or DELETE
		if update != nil {
			update.Input().ItemChannel() <- item
		}

		if delete != nil {
			delete.Input().ItemChannel() <- item
		}
	} else {
		// Not matched; INSERT
		if insert != nil {
			insert.Input().ItemChannel() <- item
		}
	}

	return true
}
コード例 #17
0
ファイル: file.go プロジェクト: amarantha-k/query
func fetch(path string) (item value.AnnotatedValue, e errors.Error) {
	bytes, er := ioutil.ReadFile(path)
	if er != nil {
		if os.IsNotExist(er) {
			// file doesn't exist should simply return nil, nil
			return
		}
		return nil, errors.NewFileDatastoreError(er, "")
	}

	doc := value.NewAnnotatedValue(value.NewValue(bytes))
	doc.SetAttachment("meta", map[string]interface{}{"id": documentPathToId(path)})
	item = doc

	return
}
コード例 #18
0
ファイル: couchbase.go プロジェクト: amarantha-k/query
func (b *keyspace) Fetch(keys []string) ([]datastore.AnnotatedPair, errors.Error) {

	if len(keys) == 0 {
		return nil, errors.NewCbNoKeysFetchError(nil, ":(")
	}

	bulkResponse, err := b.cbbucket.GetBulk(keys)
	if err != nil {
		// Ignore "Not found" keys
		if !isNotFoundError(err) {
			return nil, errors.NewCbBulkGetError(err, "")
		}
	}

	i := 0
	rv := make([]datastore.AnnotatedPair, len(bulkResponse))
	for k, v := range bulkResponse {

		var doc datastore.AnnotatedPair
		doc.Key = k

		Value := value.NewAnnotatedValue(value.NewValue(v.Body))

		meta_flags := binary.BigEndian.Uint32(v.Extras[0:4])
		meta_type := "json"
		if Value.Type() == value.BINARY {
			meta_type = "base64"
		}
		Value.SetAttachment("meta", map[string]interface{}{
			"id":    k,
			"cas":   float64(v.Cas),
			"type":  meta_type,
			"flags": float64(meta_flags),
		})

		logging.Debugf("CAS Value for key %v is %v", k, float64(v.Cas))

		doc.Value = Value
		rv[i] = doc
		i++

	}

	logging.Debugf("Fetched %d keys ", i)

	return rv, nil
}
コード例 #19
0
ファイル: explain.go プロジェクト: amarantha-k/query
func (this *Explain) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped

		bytes, err := json.Marshal(this.plan)
		if err != nil {
			context.Fatal(errors.NewError(err, "Failed to marshal JSON."))
			return
		}

		value := value.NewAnnotatedValue(bytes)
		this.sendItem(value)

	})
}
コード例 #20
0
ファイル: scan_count.go プロジェクト: amarantha-k/query
func (this *CountScan) RunOnce(context *Context, parent value.Value) {
	this.once.Do(func() {
		defer context.Recover()       // Recover from any panic
		defer close(this.itemChannel) // Broadcast that I have stopped
		defer this.notify()           // Notify that I have stopped

		count, e := this.plan.Keyspace().Count()
		if e != nil {
			context.Error(e)
			return
		}

		cv := value.NewScopeValue(nil, parent)
		av := value.NewAnnotatedValue(cv)
		av.SetAttachment("count", value.NewValue(count))
		this.sendItem(av)
	})
}
コード例 #21
0
func (b *keyspaceKeyspace) fetchOne(key string) (value.AnnotatedValue, errors.Error) {
	ids := strings.SplitN(key, "/", 2)

	namespace, err := b.namespace.store.actualStore.NamespaceById(ids[0])
	if namespace != nil {
		keyspace, _ := namespace.KeyspaceById(ids[1])
		if keyspace != nil {
			doc := value.NewAnnotatedValue(map[string]interface{}{
				"id":           keyspace.Id(),
				"name":         keyspace.Name(),
				"namespace_id": namespace.Id(),
				"datastore_id": b.namespace.store.actualStore.Id(),
			})
			return doc, nil
		}
	}
	return nil, err
}
コード例 #22
0
ファイル: let.go プロジェクト: amarantha-k/query
func (this *Let) processItem(item value.AnnotatedValue, context *Context) bool {
	n := len(this.plan.Bindings())
	cv := value.NewScopeValue(make(map[string]interface{}, n), item)
	lv := value.NewAnnotatedValue(cv)
	lv.SetAttachments(item.Attachments())

	for _, b := range this.plan.Bindings() {
		v, e := b.Expression().Evaluate(item, context)
		if e != nil {
			context.Error(errors.NewError(e, "Error evaluating LET."))
			return false
		}

		lv.SetField(b.Variable(), v)
	}

	return this.sendItem(lv)
}
コード例 #23
0
ファイル: group_final.go プロジェクト: amarantha-k/query
func (this *FinalGroup) afterItems(context *Context) {
	if len(this.groups) > 0 {
		for _, av := range this.groups {
			if !this.sendItem(av) {
				return
			}
		}
	} else if this.plan.Keys() == nil {
		// Grouping over all inputs -- always send a result
		av := value.NewAnnotatedValue(nil)
		aggregates := make(map[string]value.Value, len(this.plan.Aggregates()))
		av.SetAttachment("aggregates", aggregates)

		for _, agg := range this.plan.Aggregates() {
			aggregates[agg.String()] = agg.Default()
		}

		this.sendItem(av)
	}
}
コード例 #24
0
ファイル: unnest.go プロジェクト: amarantha-k/query
func (this *Unnest) processItem(item value.AnnotatedValue, context *Context) bool {
	ev, err := this.plan.Term().Expression().Evaluate(item, context)
	if err != nil {
		context.Error(errors.NewError(err, "Error evaluating UNNEST path."))
		return false
	}

	actuals := ev.Actual()
	switch actuals.(type) {
	case []interface{}:
	case nil:
		actuals = []interface{}(nil)
	default:
		actuals = []interface{}{actuals}
	}

	acts := actuals.([]interface{})
	if len(acts) == 0 {
		// Outer unnest
		return !this.plan.Term().Outer() || this.sendItem(item)
	}

	// Attach and send
	for i, act := range acts {
		var av value.AnnotatedValue
		if i < len(acts)-1 {
			av = value.NewAnnotatedValue(item.Copy())
		} else {
			av = item
		}

		av.SetField(this.plan.Alias(), value.NewValue(act))

		if !this.sendItem(av) {
			return false
		}
	}

	return true
}
コード例 #25
0
ファイル: update_set.go プロジェクト: amarantha-k/query
func setPath(t *algebra.SetTerm, clone, item value.AnnotatedValue, context *Context) (value.AnnotatedValue, error) {
	if t.UpdateFor() != nil {
		return setFor(t, clone, item, context)
	}

	v, err := t.Value().Evaluate(item, context)
	if err != nil {
		return nil, err
	}

	if v.Type() == value.MISSING {
	}

	if t.Path() != nil {
		t.Path().Set(clone, v, context)
		return clone, nil
	} else {
		av := value.NewAnnotatedValue(v)
		av.SetAttachments(clone.Attachments())
		return av, nil
	}
}
コード例 #26
0
ファイル: alias.go プロジェクト: amarantha-k/query
func (this *Alias) processItem(item value.AnnotatedValue, context *Context) bool {
	av := value.NewAnnotatedValue(make(map[string]interface{}))
	av.SetAttachments(item.Attachments())
	av.SetField(this.plan.Alias(), item)
	return this.sendItem(av)
}
コード例 #27
0
ファイル: nest.go プロジェクト: amarantha-k/query
func (this *Nest) processItem(item value.AnnotatedValue, context *Context) bool {
	kv, e := this.plan.Term().Keys().Evaluate(item, context)
	if e != nil {
		context.Error(errors.NewError(e, "Error evaluating NEST keys."))
		return false
	}

	actuals := kv.Actual()
	switch actuals.(type) {
	case []interface{}:
	case nil:
		actuals = []interface{}(nil)
	default:
		actuals = []interface{}{actuals}
	}

	acts := actuals.([]interface{})
	if len(acts) == 0 {
		// Outer nest
		return !this.plan.Outer() || this.sendItem(item)
	}

	// Build list of keys
	keys := make([]string, 0, len(acts))
	for _, key := range acts {
		k := value.NewValue(key).Actual()
		switch k := k.(type) {
		case string:
			keys = append(keys, k)
		}
	}

	// Fetch
	pairs, err := this.plan.Keyspace().Fetch(keys)
	if err != nil {
		context.Error(err)
		return false
	}

	found := len(pairs) > 0

	if !found && !this.plan.Outer() {
		return true
	}

	nvs := make([]interface{}, 0, len(pairs))
	for i, pair := range pairs {
		nestItem := pair.Value
		var nv value.AnnotatedValue

		// Apply projection, if any
		projection := this.plan.Term().Projection()
		if projection != nil {
			projectedItem, e := projection.Evaluate(nestItem, context)
			if e != nil {
				context.Error(errors.NewError(e,
					"Error evaluating nest path."))
				return false
			}

			if projectedItem.Type() == value.MISSING {
				continue
			}
			nv = value.NewAnnotatedValue(projectedItem)
		} else {
			nv = value.NewAnnotatedValue(nestItem)
		}

		nv.SetAttachment("meta", map[string]interface{}{"id": keys[i]})
		nvs = append(nvs, nv)
	}

	// Attach and send
	item.SetField(this.plan.Term().Alias(), nvs)
	return this.sendItem(item)
}
コード例 #28
0
func (b *dualKeyspace) fetchOne(key string) (value.AnnotatedValue, errors.Error) {
	return value.NewAnnotatedValue(nil), nil
}
コード例 #29
0
ファイル: insert_send.go プロジェクト: amarantha-k/query
func (this *SendInsert) flushBatch(context *Context) bool {
	if len(this.batch) == 0 {
		return true
	}

	keyExpr := this.plan.Key()
	valExpr := this.plan.Value()
	dpairs := make([]datastore.Pair, len(this.batch))
	var key, val value.Value
	var err error
	var ok bool
	i := 0

	for _, av := range this.batch {
		dpair := &dpairs[i]

		if keyExpr != nil {
			// INSERT ... SELECT
			key, err = keyExpr.Evaluate(av, context)
			if err != nil {
				context.Error(errors.NewError(err,
					fmt.Sprintf("Error evaluating INSERT key for %v", av.GetValue())))
				continue
			}

			if valExpr != nil {
				val, err = valExpr.Evaluate(av, context)
				if err != nil {
					context.Error(errors.NewError(err,
						fmt.Sprintf("Error evaluating INSERT value for %v", av.GetValue())))
					continue
				}
			} else {
				val = av
			}
		} else {
			// INSERT ... VALUES
			key, ok = av.GetAttachment("key").(value.Value)
			if !ok {
				context.Error(errors.NewError(nil,
					fmt.Sprintf("No INSERT key for %v", av.GetValue())))
				continue
			}

			val, ok = av.GetAttachment("value").(value.Value)
			if !ok {
				context.Error(errors.NewError(nil,
					fmt.Sprintf("No INSERT value for %v", av.GetValue())))
				continue
			}
		}

		dpair.Key, ok = key.Actual().(string)
		if !ok {
			context.Error(errors.NewError(nil,
				fmt.Sprintf("Cannot INSERT non-string key %v of type %T.", key, key)))
			continue
		}

		dpair.Value = val
		i++
	}

	dpairs = dpairs[0:i]
	this.batch = nil

	// Perform the actual INSERT
	keys, e := this.plan.Keyspace().Insert(dpairs)

	// Update mutation count with number of inserted docs
	context.AddMutationCount(uint64(len(keys)))

	if e != nil {
		context.Error(e)
	}

	// Capture the inserted keys in case there is a RETURNING clause
	for i, k := range keys {
		av := value.NewAnnotatedValue(make(map[string]interface{}))
		av.SetAttachment("meta", map[string]interface{}{"id": k})
		av.SetField(this.plan.Alias(), dpairs[i].Value)
		if !this.sendItem(av) {
			return false
		}
	}

	return true
}
コード例 #30
0
ファイル: fetch.go プロジェクト: amarantha-k/query
func (this *Fetch) flushBatch(context *Context) bool {
	if len(this.batch) == 0 {
		return true
	}

	// Build list of keys
	keys := make([]string, len(this.batch))
	for i, av := range this.batch {
		meta := av.GetAttachment("meta")

		switch meta := meta.(type) {
		case map[string]interface{}:
			key := meta["id"]
			act := value.NewValue(key).Actual()
			switch act := act.(type) {
			case string:
				keys[i] = act
			default:
				context.Error(errors.NewError(nil, fmt.Sprintf(
					"Missing or invalid primary key %v of type %T.",
					act, act)))
				return false
			}
		default:
			context.Error(errors.NewError(nil,
				"Missing or invalid meta for primary key."))
			return false
		}
	}

	// Fetch
	pairs, err := this.plan.Keyspace().Fetch(keys)
	if err != nil {
		context.Error(err)
		return false
	}

	// Attach meta and send
	for i, pair := range pairs {
		item := pair.Value
		var fv value.AnnotatedValue

		// Apply projection, if any
		projection := this.plan.Term().Projection()
		if projection != nil {
			projectedItem, e := projection.Evaluate(item, context)
			if e != nil {
				context.Error(errors.NewError(e,
					"Error evaluating fetch path."))
				return false
			}

			if projectedItem.Type() == value.MISSING {
				continue
			}
			fv = value.NewAnnotatedValue(projectedItem)
		} else {

			fv = value.NewAnnotatedValue(item)
		}

		av := this.batch[i]
		switch item := item.(type) {
		case value.AnnotatedValue:
			meta := item.(value.AnnotatedValue).GetAttachment("meta")
			fv.SetAttachment("meta", meta)
		default:
			fv.SetAttachment("meta", av.GetAttachment("meta"))
		}
		av.SetField(this.plan.Term().Alias(), fv)

		if !this.sendItem(av) {
			return false
		}
	}

	return true
}