func (this *IndexNest) fetch(entries []*datastore.IndexEntry, context *Context) ( []interface{}, bool) { // Build list of keys var keys []string if len(entries) <= 16 { keys = _NEST_INDEX_STRING_POOL.Get() defer _NEST_INDEX_STRING_POOL.Put(keys) } else { keys = make([]string, 0, len(entries)) } for _, e := range entries { keys = append(keys, e.PrimaryKey) } // Fetch pairs, errs := this.plan.Keyspace().Fetch(keys) fetchOk := true for _, err := range errs { context.Error(err) if err.IsFatal() { fetchOk = false } } if len(pairs) == 0 { return nil, fetchOk } projection := this.plan.Term().Projection() nvs := make([]interface{}, 0, len(pairs)) for _, pair := range pairs { nestItem := pair.Value var nv value.AnnotatedValue // Apply projection, if any if projection != nil { projectedItem, e := projection.Evaluate(nestItem, context) if e != nil { context.Error(errors.NewEvaluationError(e, "nest path")) return nil, false } if projectedItem.Type() == value.MISSING { continue } nv = value.NewAnnotatedValue(projectedItem) nv.SetAnnotations(nestItem) } else { nv = nestItem } nvs = append(nvs, nv) } return nvs, fetchOk }
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.NewEvaluationError(e, "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) } } timer := time.Now() // Fetch pairs, errs := this.plan.Keyspace().Fetch(keys) this.duration += time.Since(timer) fetchOk := true for _, err := range errs { context.Error(err) if err.IsFatal() { fetchOk = 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.NewEvaluationError(e, "join path")) return false } jv = value.NewAnnotatedValue(projectedItem) jv.SetAnnotations(joinItem) } else { jv = joinItem } 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)) && fetchOk }
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 *Nest) processItem(item value.AnnotatedValue, context *Context) bool { kv, e := this.plan.Term().Keys().Evaluate(item, context) if e != nil { context.Error(errors.NewEvaluationError(e, "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) } } timer := time.Now() // Fetch pairs, errs := this.plan.Keyspace().Fetch(keys) this.duration += time.Since(timer) fetchOk := true for _, err := range errs { context.Error(err) if err.IsFatal() { fetchOk = false } } found := len(pairs) > 0 if !found && !this.plan.Outer() { return true } nvs := make([]interface{}, 0, len(pairs)) for _, 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.NewEvaluationError(e, "nest path")) return false } if projectedItem.Type() == value.MISSING { continue } nv = value.NewAnnotatedValue(projectedItem) nv.SetAnnotations(nestItem) } else { nv = nestItem } nvs = append(nvs, nv) } // Attach and send item.SetField(this.plan.Term().Alias(), nvs) return this.sendItem(item) && fetchOk }