// N1QLTransform will use compile list of expression from N1QL's DDL // statement and evaluate a document using them to return a secondary // key as JSON object. func N1QLTransform(document []byte, cExprs []interface{}) ([]byte, error) { arrValue := make([]*dparval.Value, 0, len(cExprs)) for _, cExpr := range cExprs { expr := cExpr.(ast.Expression) // TODO: CBIDXT-133: needs to send nil secondary keys to indexer key, err := expr.Evaluate(dparval.NewValueFromBytes(document)) if err != nil { return nil, nil } arrValue = append(arrValue, key) } if len(arrValue) > 1 { secKey := dparval.NewValue(make([]interface{}, len(cExprs))) for i, key := range arrValue { secKey.SetIndex(i, key) } return secKey.Bytes(), nil // [ seckey1, seckey2, ... ] } else if len(arrValue) == 1 { return arrValue[0].Bytes(), nil // seckey1 } return nil, ErrorEmptyN1QLExpression }
func (b *bucket) BulkFetch(ids []string) (map[string]*dparval.Value, query.Error) { rv := make(map[string]*dparval.Value, 0) bulkResponse, err := b.cbbucket.GetBulk(ids) if err != nil { return nil, query.NewError(err, "Error doing bulk get") } for k, v := range bulkResponse { doc := dparval.NewValueFromBytes(v.Body) meta_flags := (v.Extras[0]&0xff)<<24 | (v.Extras[1]&0xff)<<16 | (v.Extras[2]&0xff)<<8 | (v.Extras[3] & 0xff) meta_type := "json" if doc.Type() == dparval.NOT_JSON { meta_type = "base64" } doc.SetAttachment("meta", map[string]interface{}{ "id": k, "cas": float64(v.Cas), "type": meta_type, "flags": float64(meta_flags), }) rv[k] = doc } return rv, nil }
func fetch(path string) (item *dparval.Value, e query.Error) { bytes, err := ioutil.ReadFile(path) if err != nil { if os.IsNotExist(err) { // file doesn't exist should simply return nil,nil return } return nil, query.NewError(err, "") } doc := dparval.NewValueFromBytes(bytes) doc.SetAttachment("meta", map[string]interface{}{"id": documentPathToId(path)}) item = doc return }
func (this *Explain) Run(stopChannel misc.StopChannel) { defer close(this.itemChannel) defer close(this.supportChannel) // this MUST be here so that it runs before the channels are closed defer this.RecoverPanic() this.downstreamStopChannel = stopChannel clog.To(CHANNEL, "explain operator starting") item := dparval.NewValue(map[string]interface{}{}) planBytes, err := json.Marshal(this.Plan) if err != nil { this.SendError(query.NewError(err, "error serializing plan to JSON")) } else { projection := dparval.NewValueFromBytes(planBytes) item.SetAttachment("projection", projection) this.SendItem(item) } clog.To(CHANNEL, "explain operator finished") }