func (this *Order) processItem(item *dparval.Value) bool { if this.explicitAliases != nil { projection := item.GetAttachment("projection") projectionValue, ok := projection.(*dparval.Value) if ok { for _, explicitAlias := range this.explicitAliases { // put the explicit alias values from the projection into the item aliasedProjectedValue, err := projectionValue.Path(explicitAlias) if err == nil { item.SetPath(explicitAlias, aliasedProjectedValue) } } } } this.buffer = append(this.buffer, item) return true }
func (this *KeyNest) flushBatch(baseItem *dparval.Value, ids []string) bool { bulkResponse, err := this.bucket.BulkFetch(ids) if err != nil { return this.Base.SendError(query.NewError(err, "error getting bulk response")) } // now we need to emit the bulk fetched items in the correct order (from the id list) for _, v := range ids { item, ok := bulkResponse[v] if ok { if this.Projection != nil { projectedVal, err := this.Base.projectedValueOfResultExpression(item, ast.NewResultExpression(this.Projection)) if err != nil { switch err := err.(type) { case *dparval.Undefined: // undefined contributes nothing to the result map continue default: return this.Base.SendError(query.NewError(err, "unexpected error projecting fetch expression")) } } else { this.Right = append(this.Right, projectedVal) } } else { this.Right = append(this.Right, item) } this.rowsFetched += 1 } } if len(this.Right) > 0 { baseItem.SetPath(this.As, this.Right) } // if the lenght of the array is 0 and the type of join is not LEFT // then we return an empty result for this evaluation if len(this.Right) == 0 && this.Type != "LEFT" { return true } this.Base.SendItem(baseItem) return true }
func (this *KeyNest) processItem(item *dparval.Value) bool { if item == nil { return true } this.Right = make([]interface{}, 0) newItem := item.Duplicate() val, err := this.Base.Evaluate(this.Keys.Expr, item) if err != nil { switch err := err.(type) { case *dparval.Undefined: if this.Type == "LEFT" { this.Base.SendItem(newItem) return true } return true default: return this.Base.SendError(query.NewError(err, "Internal error in KeyNest")) } } if val.Type() == dparval.STRING { if this.Keys.Type == "KEYS" { this.Base.SendError(query.NewError(fmt.Errorf("KEYS expression should evaluate to an array"), "")) return false } if val.Value() == nil { if this.Type == "LEFT" { return this.Base.SendItem(item) } return true } fetch_id := val.Value().(string) keyitem, err := this.bucket.Fetch(fetch_id) if err != nil { this.Base.SendError(query.NewError(err, "Unable to fetch key")) return false } if keyitem != nil { if this.Projection != nil { keyproj, Error := this.Base.Evaluate(this.Projection, keyitem) if Error != nil { switch err := Error.(type) { case *dparval.Undefined: return true default: return this.Base.SendError(query.NewError(err, "Internal error in KeyNest")) } } this.Right = append(this.Right, keyproj) } else { this.Right = append(this.Right, keyitem) } newItem.SetPath(this.As, this.Right) this.Base.SendItem(newItem) } else if this.Type == "LEFT" { newItem.SetPath(this.As, this.Right) this.Base.SendItem(newItem) } this.rowsFetched += 1 } else if val.Type() == dparval.ARRAY { ok := true index := 0 ids := make([]string, 0, FETCH_BATCH_SIZE) if this.Keys.Type == "KEY" { this.Base.SendError(query.NewError(fmt.Errorf("KEY used with an array argument"), "")) return false } for ok { id, err := val.Index(index) index = index + 1 array_len := len(val.Value().([]interface{})) if array_len == 0 { if this.Type == "LEFT" { item.SetPath(this.As, this.Right) this.Base.SendItem(item) } return true } if err != nil { if len(ids) != 0 { return this.flushBatch(item, ids) } return true } fetch_id := id.Value() switch fetch_id.(type) { case string: default: item.SetPath(this.As, this.Right) this.Base.SendItem(item) return false } if fetch_id != nil { ids = append(ids, fetch_id.(string)) } else if this.Type == "LEFT" { this.Base.SendItem(item) continue } if this.rowsFetched != 0 && index%FETCH_BATCH_SIZE == 0 { // do a bulk fetch err := this.flushBatch(newItem, ids) if err != true { return false } ids = make([]string, 0, FETCH_BATCH_SIZE) } } newItem.SetPath(this.As, this.Right) this.Base.SendItem(newItem) } else if this.Type == "LEFT" { this.Base.SendItem(newItem) } return true }