func (this *IntersectScan) processKey(item value.AnnotatedValue, context *Context) bool { m := item.GetAttachment("meta") meta, ok := m.(map[string]interface{}) if !ok { context.Error(errors.NewError(nil, fmt.Sprintf("Missing or invalid meta %v of type %T.", m, m))) return false } k := meta["id"] key, ok := k.(string) if !ok { context.Error(errors.NewError(nil, fmt.Sprintf("Missing or invalid primary key %v of type %T.", k, k))) return false } count := this.counts[key] this.counts[key] = count + 1 if count+1 == len(this.scans) { delete(this.values, key) return this.sendItem(item) } if count == 0 { this.values[key] = item } return true }
func (this *Clone) processItem(item value.AnnotatedValue, context *Context) bool { target, ok := item.GetAttachment("target").(value.Value) if !ok { target = item } item.SetAttachment("clone", target.CopyForUpdate()) return this.sendItem(item) }
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) }
func (this *Distinct) processItem(item value.AnnotatedValue, context *Context) bool { p := item.GetAttachment("projection") if p == nil { p = item } this.set.Put(p.(value.Value), item) return true }
func (this *Collect) processItem(item value.AnnotatedValue, context *Context) bool { if len(this.values) == cap(this.values) { values := make([]interface{}, len(this.values), len(this.values)<<1) copy(values, this.values) this.values = values } this.values = append(this.values, item.Actual()) return true }
// The item may have been wrapped in a top-level object by a previous // operator (key scan, primary scan) - take the inner value if so, as // we do not want to write the top-level value to the datastore func (this *SendUpdate) unwrapTop(item value.AnnotatedValue) value.Value { top := this.plan.Alias() value := item.GetValue() inner_value, ok := value.Field(top) if ok { return inner_value } return item }
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 }
func (this *Unset) processItem(item value.AnnotatedValue, context *Context) bool { clone, ok := item.GetAttachment("clone").(value.AnnotatedValue) if !ok { context.Error(errors.NewError(nil, fmt.Sprintf("Invalid UPDATE clone of type %T.", clone))) return false } for _, t := range this.plan.Node().Terms() { unsetPath(t, clone, context) } return this.sendItem(item) }
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) }
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) } }
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) }
func (this *Set) processItem(item value.AnnotatedValue, context *Context) bool { clone, ok := item.GetAttachment("clone").(value.AnnotatedValue) if !ok { context.Error(errors.NewError(nil, fmt.Sprintf("Invalid UPDATE clone of type %T.", clone))) return false } var e error for _, t := range this.plan.Node().Terms() { clone, e = setPath(t, clone, item, context) if e != nil { context.Error(errors.NewError(e, "Error evaluating SET clause.")) return false } } item.SetAttachment("clone", clone) return this.sendItem(item) }
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 }
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 } }
func (this *UnionScan) processKey(item value.AnnotatedValue, context *Context) bool { m := item.GetAttachment("meta") meta, ok := m.(map[string]interface{}) if !ok { context.Error(errors.NewError(nil, fmt.Sprintf("Missing or invalid meta %v of type %T.", m, m))) return false } k := meta["id"] key, ok := k.(string) if !ok { context.Error(errors.NewError(nil, fmt.Sprintf("Missing or invalid primary key %v of type %T.", k, k))) return false } if this.values[key] != nil { return true } this.values[key] = item return this.sendItem(item) }
func (this *base) requireKey(item value.AnnotatedValue, context *Context) (string, bool) { mv := item.GetAttachment("meta") if mv == nil { context.Error(errors.NewError(nil, "Unable to find meta.")) return "", false } meta := mv.(map[string]interface{}) key, ok := meta["id"] if !ok { context.Error(errors.NewError(nil, "Unable to find key.")) return "", false } act := value.NewValue(key).Actual() switch act := act.(type) { case string: return act, true default: e := errors.NewError(nil, fmt.Sprintf("Unable to process non-string key %v of type %T.", act, act)) context.Error(e) return "", false } }
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 }
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) }
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) }
func (this *Join) 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 JOIN 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 join 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 // Attach and send for i, pair := range pairs { joinItem := pair.Value var jv value.AnnotatedValue // Apply projection, if any projection := this.plan.Term().Projection() if projection != nil { projectedItem, e := projection.Evaluate(joinItem, context) if e != nil { context.Error(errors.NewError(e, "Error evaluating join path.")) return false } jv = value.NewAnnotatedValue(projectedItem) } else { jv = value.NewAnnotatedValue(joinItem) } jv.SetAttachment("meta", map[string]interface{}{"id": keys[i]}) var av value.AnnotatedValue if i < len(pairs)-1 { av = value.NewAnnotatedValue(item.Copy()) } else { av = item } av.SetField(this.plan.Term().Alias(), jv) if !this.sendItem(av) { return false } } return found || !this.plan.Outer() || this.sendItem(item) }