Example #1
0
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
}
Example #2
0
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
}
Example #3
0
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))
			}

		}
	}

}
Example #4
0
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
}