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 *KeyJoin) 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] newItem := baseItem.Duplicate() if item == nil { if this.Type == "LEFT" { this.Base.SendItem(newItem) } continue } 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 { newItem.SetPath(this.As, projectedVal) } } else { newItem.SetPath(this.As, item) } this.Base.SendItem(newItem) this.rowsFetched += 1 } } return true }
func TestParserASTOutput(t *testing.T) { tests := []struct { input string output ast.Statement }{ {"SELECT * FROM test WHERE true", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewStarResultExpression(), }, Distinct: false, From: &ast.From{Projection: ast.NewProperty("test")}, Where: ast.NewLiteralBool(true), Limit: -1, }, }, {"SELECT * FROM :apool.test WHERE true", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewStarResultExpression(), }, Distinct: false, From: &ast.From{Pool: "apool", Projection: ast.NewProperty("test")}, Where: ast.NewLiteralBool(true), Limit: -1, }, }, {"SELECT * FROM test ORDER BY foo", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewStarResultExpression(), }, Distinct: false, From: &ast.From{Projection: ast.NewProperty("test")}, Where: nil, OrderBy: []*ast.SortExpression{ ast.NewSortExpression(ast.NewProperty("foo"), true), }, Limit: -1, }, }, {"SELECT * FROM test LIMIT 10 OFFSET 3", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewStarResultExpression(), }, Distinct: false, From: &ast.From{Projection: ast.NewProperty("test")}, Where: nil, Limit: 10, Offset: 3, }, }, {"SELECT a FROM test", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewResultExpression(ast.NewProperty("a")), }, Distinct: false, From: &ast.From{Projection: ast.NewProperty("test")}, Where: nil, Limit: -1, }, }, {"SELECT a FROM test t2", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewResultExpression(ast.NewProperty("a")), }, Distinct: false, From: &ast.From{Projection: ast.NewProperty("test"), As: "t2"}, Where: nil, Limit: -1, }, }, {"SELECT 1+1*30 as steve", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewResultExpressionWithAlias(ast.NewPlusOperator(ast.NewLiteralNumber(1.0), ast.NewMultiplyOperator(ast.NewLiteralNumber(1.0), ast.NewLiteralNumber(30.0))), "steve"), }, Distinct: false, From: nil, Where: nil, Limit: -1, }, }, {"SELECT 1+1*30 steve", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewResultExpressionWithAlias(ast.NewPlusOperator(ast.NewLiteralNumber(1.0), ast.NewMultiplyOperator(ast.NewLiteralNumber(1.0), ast.NewLiteralNumber(30.0))), "steve"), }, Distinct: false, From: nil, Where: nil, Limit: -1, }, }, {"SELECT DISTINCT 1+1*30 as steve", &ast.SelectStatement{ Select: ast.ResultExpressionList{ ast.NewResultExpressionWithAlias(ast.NewPlusOperator(ast.NewLiteralNumber(1.0), ast.NewMultiplyOperator(ast.NewLiteralNumber(1.0), ast.NewLiteralNumber(30.0))), "steve"), }, Distinct: true, From: nil, Where: nil, Limit: -1, }, }, {"CREATE INDEX abv_idx ON beer-sample(abv) USING VIEW", &ast.CreateIndexStatement{ Method: "view", Bucket: "beer-sample", Name: "abv_idx", On: ast.ExpressionList{ast.NewProperty("abv")}, }, }, {"CREATE INDEX abv_idx ON beer-sample(abv) USING magic", &ast.CreateIndexStatement{ Method: "magic", Bucket: "beer-sample", Name: "abv_idx", On: ast.ExpressionList{ast.NewProperty("abv")}, }, }, {"CREATE INDEX abv_idx ON beer-sample(abv)", &ast.CreateIndexStatement{ Method: "", Bucket: "beer-sample", Name: "abv_idx", On: ast.ExpressionList{ast.NewProperty("abv")}, }, }, {"CREATE INDEX abv_idx ON :apool.beer-sample(abv) USING VIEW", &ast.CreateIndexStatement{ Method: "view", Pool: "apool", Bucket: "beer-sample", Name: "abv_idx", On: ast.ExpressionList{ast.NewProperty("abv")}, }, }, {"CREATE INDEX abv_idx ON :apool.beer-sample(abv) USING magic", &ast.CreateIndexStatement{ Method: "magic", Pool: "apool", Bucket: "beer-sample", Name: "abv_idx", On: ast.ExpressionList{ast.NewProperty("abv")}, }, }, {"CREATE INDEX abv_idx ON :apool.beer-sample(abv)", &ast.CreateIndexStatement{ Method: "", Pool: "apool", Bucket: "beer-sample", Name: "abv_idx", On: ast.ExpressionList{ast.NewProperty("abv")}, }, }, {"DROP INDEX beer-sample.abv", &ast.DropIndexStatement{ Bucket: "beer-sample", Name: "abv", }, }, {"DROP INDEX :apool.beer-sample.abv", &ast.DropIndexStatement{ Pool: "apool", Bucket: "beer-sample", Name: "abv", }, }, } n1qlParser := NewN1qlParser() for _, v := range tests { query, err := n1qlParser.Parse(v.input) if err != nil { t.Errorf("Valid Query Parse Failed: %v - %v", v, err) } if !reflect.DeepEqual(query, v.output) { t.Errorf("Expected %v, got %v", v.output, query) js, err := json.MarshalIndent(v.output, "", " ") if err == nil { t.Logf("Expected %v", string(js)) } js, err = json.MarshalIndent(query, "", " ") if err == nil { t.Logf("Got %v", string(js)) } } } }
func (this *Fetch) flushBatch() bool { defer func() { // no matter what hapens in this function // clear out the batch and start a new one this.batch = make(dparval.ValueCollection, 0, FETCH_BATCH_SIZE) }() // gather the ids ids := make([]string, 0, FETCH_BATCH_SIZE) for _, v := range this.batch { meta := v.GetAttachment("meta") if meta != nil { id, ok := meta.(map[string]interface{})["id"] if !ok { return this.Base.SendError(query.NewError(nil, "asked to fetch an item without a key")) } else { ids = append(ids, id.(string)) //FIXME assert ids always strings } } else { return this.Base.SendError(query.NewError(nil, "asked to fetch an item without a meta")) } } // now do a bulk fetch 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 { if this.as != "" { this.Base.SendItem(dparval.NewValue(map[string]interface{}{this.as: projectedVal})) } else { this.Base.SendItem(projectedVal) } } } else { if this.as != "" { this.Base.SendItem(dparval.NewValue(map[string]interface{}{this.as: item})) } else { this.Base.SendItem(item) } } this.rowsFetched += 1 } } return true }