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.NewInvalidValueError( 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.NewInvalidValueError( 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 *IntermediateGroup) processItem(item value.AnnotatedValue, context *Context) bool { // Generate the group key var gk string if len(this.plan.Keys()) > 0 { var e error gk, e = groupKey(item, this.plan.Keys(), context) if e != nil { context.Fatal(errors.NewEvaluationError(e, "GROUP key")) return false } } // Get or seed the group value gv := this.groups[gk] if gv == nil { gv = item this.groups[gk] = gv return true } // Cumulate aggregates part, ok := item.GetAttachment("aggregates").(map[string]value.Value) if !ok { context.Fatal(errors.NewInvalidValueError( fmt.Sprintf("Invalid partial aggregates %v of type %T", part, part))) return false } cumulative := gv.GetAttachment("aggregates").(map[string]value.Value) if !ok { context.Fatal(errors.NewInvalidValueError( fmt.Sprintf("Invalid cumulative aggregates %v of type %T", cumulative, cumulative))) return false } for _, agg := range this.plan.Aggregates() { a := agg.String() v, e := agg.CumulateIntermediate(part[a], cumulative[a], context) if e != nil { context.Fatal(errors.NewGroupUpdateError( e, "Error updating intermediate GROUP value.")) return false } cumulative[a] = v } return true }
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.NewEvaluationError(e, "MERGE key")) return false } ka := kv.Actual() k, ok := ka.(string) if !ok { context.Error(errors.NewInvalidValueError( fmt.Sprintf("Invalid MERGE key %v of type %T.", ka, ka))) return false } timer := time.Now() fetchOk := true bvs, errs := this.plan.Keyspace().Fetch([]string{k}) this.duration += time.Since(timer) for _, err := range errs { context.Error(err) if err.IsFatal() { fetchOk = false } } if len(bvs) > 0 { bv := bvs[0] item.SetField(this.plan.KeyspaceRef().Alias(), bv.Value) // 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 fetchOk }
func (this *Unset) processItem(item value.AnnotatedValue, context *Context) bool { clone, ok := item.GetAttachment("clone").(value.AnnotatedValue) if !ok { context.Error(errors.NewInvalidValueError( 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 *UnionScan) processKey(item value.AnnotatedValue, context *Context) bool { m := item.GetAttachment("meta") meta, ok := m.(map[string]interface{}) if !ok { context.Error(errors.NewInvalidValueError( 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.NewInvalidValueError( 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 *InitialGroup) processItem(item value.AnnotatedValue, context *Context) bool { // Generate the group key var gk string if len(this.plan.Keys()) > 0 { var e error gk, e = groupKey(item, this.plan.Keys(), context) if e != nil { context.Fatal(errors.NewEvaluationError(e, "GROUP key")) return false } } // Get or seed the group value gv := this.groups[gk] if gv == nil { gv = item this.groups[gk] = gv aggregates := make(map[string]value.Value, len(this.plan.Aggregates())) gv.SetAttachment("aggregates", aggregates) for _, agg := range this.plan.Aggregates() { aggregates[agg.String()] = agg.Default() } } // Cumulate aggregates aggregates, ok := gv.GetAttachment("aggregates").(map[string]value.Value) if !ok { context.Fatal(errors.NewInvalidValueError( fmt.Sprintf("Invalid aggregates %v of type %T", aggregates, aggregates))) return false } for _, agg := range this.plan.Aggregates() { v, e := agg.CumulateInitial(item, aggregates[agg.String()], context) if e != nil { context.Fatal(errors.NewGroupUpdateError(e, "Error updating initial GROUP value.")) return false } aggregates[agg.String()] = v } return true }
func (this *FinalGroup) processItem(item value.AnnotatedValue, context *Context) bool { // Generate the group key var gk string if len(this.plan.Keys()) > 0 { var e error gk, e = groupKey(item, this.plan.Keys(), context) if e != nil { context.Fatal(errors.NewEvaluationError(e, "GROUP key")) return false } } // Get or seed the group value gv := this.groups[gk] if gv != nil { context.Fatal(errors.NewDuplicateFinalGroupError()) return false } gv = item this.groups[gk] = gv // Compute final aggregates aggregates := gv.GetAttachment("aggregates") switch aggregates := aggregates.(type) { case map[string]value.Value: for _, agg := range this.plan.Aggregates() { v, e := agg.ComputeFinal(aggregates[agg.String()], context) if e != nil { context.Fatal(errors.NewGroupUpdateError( e, "Error updating final GROUP value.")) return false } aggregates[agg.String()] = v } return true default: context.Fatal(errors.NewInvalidValueError(fmt.Sprintf( "Invalid or missing aggregates of type %T.", aggregates))) return false } }
func (this *Limit) beforeItems(context *Context, parent value.Value) bool { val, e := this.plan.Expression().Evaluate(parent, context) if e != nil { context.Error(errors.NewEvaluationError(e, "LIMIT")) return false } actual := val.Actual() switch actual := actual.(type) { case float64: if math.Trunc(actual) == actual { this.limit = int64(actual) return true } } context.Error(errors.NewInvalidValueError( fmt.Sprintf("Invalid LIMIT value %v.", actual))) return false }
func (this *SendUpdate) beforeItems(context *Context, parent value.Value) bool { if this.plan.Limit() == nil { return true } limit, err := this.plan.Limit().Evaluate(parent, context) if err != nil { context.Error(errors.NewError(err, "")) return false } switch l := limit.Actual().(type) { case float64: this.limit = int64(l) default: context.Error(errors.NewInvalidValueError(fmt.Sprintf("Invalid LIMIT %v of type %T.", l, l))) return false } return true }
func (this *Fetch) flushBatch(context *Context) bool { defer this.releaseBatch() if len(this.batch) == 0 { return true } keys := _STRING_POOL.Get() defer _STRING_POOL.Put(keys) batchMap := _STRING_ANNOTATED_POOL.Get() defer _STRING_ANNOTATED_POOL.Put(batchMap) for _, 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 = append(keys, act) batchMap[act] = av default: context.Error(errors.NewInvalidValueError(fmt.Sprintf( "Missing or invalid primary key %v of type %T.", act, act))) return false } default: context.Error(errors.NewInvalidValueError( "Missing or invalid meta for primary key.")) return false } } timer := time.Now() // Fetch pairs, errs := this.plan.Keyspace().Fetch(keys) context.AddPhaseTime("fetch", time.Since(timer)) fetchOk := true for _, err := range errs { context.Error(err) if err.IsFatal() { fetchOk = false } } fetchMap := _STRING_ANNOTATED_POOL.Get() defer _STRING_ANNOTATED_POOL.Put(fetchMap) // Attach meta for _, pair := range pairs { pv, ok := pair.Value.(value.AnnotatedValue) if !ok { context.Fatal(errors.NewInvalidValueError(fmt.Sprintf( "Invalid fetch value %v of type %T", pair.Value))) return false } var fv value.AnnotatedValue // Apply projection, if any projection := this.plan.Term().Projection() if projection != nil { projectedItem, e := projection.Evaluate(pv, context) if e != nil { context.Error(errors.NewEvaluationError(e, "fetch path")) return false } if projectedItem.Type() == value.MISSING { continue } fv = value.NewAnnotatedValue(projectedItem) fv.SetAnnotations(pv) } else { fv = pv } fetchMap[pair.Key] = fv } // Preserve order of keys for _, key := range keys { fv := fetchMap[key] if fv == nil { continue } item := batchMap[key] item.SetField(this.plan.Term().Alias(), fv) if !this.sendItem(item) { return false } } return fetchOk }
func (this *SendUpdate) flushBatch(context *Context) bool { defer this.releaseBatch() if len(this.batch) == 0 { return true } pairs := _UPDATE_POOL.Get() defer _UPDATE_POOL.Put(pairs) for i, item := range this.batch { uv, ok := item.Field(this.plan.Alias()) if !ok { context.Error(errors.NewUpdateAliasMissingError(this.plan.Alias())) return false } av, ok := uv.(value.AnnotatedValue) if !ok { context.Error(errors.NewUpdateAliasMetadataError(this.plan.Alias())) return false } key, ok := this.requireKey(av, context) if !ok { return false } pairs = pairs[0 : i+1] pairs[i].Key = key clone := item.GetAttachment("clone") switch clone := clone.(type) { case value.AnnotatedValue: cv, ok := clone.Field(this.plan.Alias()) if !ok { context.Error(errors.NewUpdateAliasMissingError(this.plan.Alias())) return false } pairs[i].Value = cv item.SetField(this.plan.Alias(), cv) default: context.Error(errors.NewInvalidValueError(fmt.Sprintf( "Invalid UPDATE value of type %T.", clone))) return false } } timer := time.Now() pairs, e := this.plan.Keyspace().Update(pairs) context.AddPhaseTime("update", time.Since(timer)) // Update mutation count with number of updated docs context.AddMutationCount(uint64(len(pairs))) if e != nil { context.Error(e) } for _, item := range this.batch { if !this.sendItem(item) { return false } } return true }