mirror of
https://github.com/MontFerret/ferret.git
synced 2025-08-15 20:02:56 +02:00
Refactor FOR-WHILE
loop compilation to ensure proper LoopKind
handling and value/key resolution, update map operations, and add integration tests for COLLECT
scenarios.
This commit is contained in:
@@ -53,6 +53,11 @@ func (c *LoopCollectCompiler) compileCollect(ctx fql.ICollectClauseContext, aggr
|
||||
|
||||
c.finalizeCollector(loop, collectorType, kv)
|
||||
|
||||
// If we are using a projection, we need to ensure the loop is set to ForInLoop
|
||||
if loop.Kind != core.ForInLoop {
|
||||
loop.Kind = core.ForInLoop
|
||||
}
|
||||
|
||||
// If the projection is used, we allocate a new register for the variable and put the iterator's value into it
|
||||
if projectionVarName != "" {
|
||||
// Now we need to expand group variables from the dataset
|
||||
@@ -84,7 +89,12 @@ func (c *LoopCollectCompiler) initializeCollector(grouping fql.ICollectGroupingC
|
||||
|
||||
// Setup value register and emit value from current loop
|
||||
kv.Value = c.ctx.Registers.Allocate(core.Temp)
|
||||
loop.EmitValue(kv.Value, c.ctx.Emitter)
|
||||
|
||||
if loop.Kind == core.ForInLoop {
|
||||
loop.EmitValue(kv.Value, c.ctx.Emitter)
|
||||
} else {
|
||||
loop.EmitKey(kv.Value, c.ctx.Emitter)
|
||||
}
|
||||
|
||||
return kv, groupSelectors
|
||||
}
|
||||
@@ -222,8 +232,14 @@ func (c *LoopCollectCompiler) compileDefaultGroupProjection(loop *core.Loop, kv
|
||||
|
||||
// TODO: Review this. It's quite a questionable ArrangoDB feature of wrapping group items by a nested object
|
||||
// We will keep it for now for backward compatibility.
|
||||
loadConstantTo(c.ctx, runtime.String(loop.ValueName), seq[0]) // Map key
|
||||
c.ctx.Emitter.EmitAB(vm.OpMove, seq[1], kv.Value) // Map value
|
||||
|
||||
if loop.Kind == core.ForInLoop {
|
||||
loadConstantTo(c.ctx, runtime.String(loop.ValueName), seq[0]) // Map key
|
||||
} else {
|
||||
loadConstantTo(c.ctx, runtime.String(loop.KeyName), seq[0]) // Map key
|
||||
}
|
||||
|
||||
c.ctx.Emitter.EmitAB(vm.OpMove, seq[1], kv.Value) // Map value
|
||||
c.ctx.Emitter.EmitAs(vm.OpMap, kv.Value, seq)
|
||||
|
||||
c.ctx.Registers.FreeSequence(seq)
|
||||
|
959
test/integration/vm/vm_for_while_collect_test.go
Normal file
959
test/integration/vm/vm_for_while_collect_test.go
Normal file
@@ -0,0 +1,959 @@
|
||||
package vm_test
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/vm"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestForWhileCollect(t *testing.T) {
|
||||
RunUseCases(t, []UseCase{
|
||||
SkipCaseCompilationError(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 31,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 25,
|
||||
gender: "f"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 36,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
married: true,
|
||||
age: 69,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 45,
|
||||
gender: "f"
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender
|
||||
RETURN {
|
||||
user: users[i],
|
||||
gender: gender
|
||||
}
|
||||
`, "Should not have access to initial variables"),
|
||||
SkipCaseCompilationError(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 31,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 25,
|
||||
gender: "f"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 36,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
married: true,
|
||||
age: 69,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 45,
|
||||
gender: "f"
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET x = "foo"
|
||||
COLLECT gender = users[i].gender
|
||||
RETURN {x, gender}
|
||||
`, "Should not have access to variables defined before COLLECT"),
|
||||
CaseArray(`
|
||||
LET users = []
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender
|
||||
RETURN gender
|
||||
`,
|
||||
[]any{},
|
||||
"Should handle empty arrays gracefully"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 31,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 25,
|
||||
gender: "f"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 36,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
married: true,
|
||||
age: 69,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 45,
|
||||
gender: "f"
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender
|
||||
RETURN gender
|
||||
`, []any{"f", "m"}, "Should group result by a single key"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 31,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 25,
|
||||
gender: "f"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 36,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
married: true,
|
||||
age: 69,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 45,
|
||||
gender: "f"
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT ageGroup = FLOOR(users[i].age / 5)
|
||||
RETURN { ageGroup }
|
||||
`, []any{
|
||||
map[string]int{"ageGroup": 5},
|
||||
map[string]int{"ageGroup": 6},
|
||||
map[string]int{"ageGroup": 7},
|
||||
map[string]int{"ageGroup": 9},
|
||||
map[string]int{"ageGroup": 13},
|
||||
}, "Should group result by a single key expression"),
|
||||
Case(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 31,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 25,
|
||||
gender: "f"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 36,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
married: true,
|
||||
age: 69,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 45,
|
||||
gender: "f"
|
||||
}
|
||||
]
|
||||
LET grouped = (FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender
|
||||
RETURN gender)
|
||||
RETURN grouped[0]
|
||||
`, "f", "Should return correct group key by an index"),
|
||||
CaseArray(
|
||||
`LET users = [
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 31,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 25,
|
||||
gender: "f"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: false,
|
||||
age: 36,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
married: true,
|
||||
age: 69,
|
||||
gender: "m"
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
married: true,
|
||||
age: 45,
|
||||
gender: "f"
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender, age = users[i].age
|
||||
RETURN {age, gender}
|
||||
`, []any{
|
||||
map[string]any{"age": 25, "gender": "f"},
|
||||
map[string]any{"age": 45, "gender": "f"},
|
||||
map[string]any{"age": 31, "gender": "m"},
|
||||
map[string]any{"age": 36, "gender": "m"},
|
||||
map[string]any{"age": 69, "gender": "m"},
|
||||
}, "Should group result by multiple keys"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender INTO genders
|
||||
RETURN {
|
||||
gender,
|
||||
values: genders
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{
|
||||
"i": 1,
|
||||
},
|
||||
map[string]any{
|
||||
"i": 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{
|
||||
"i": 0,
|
||||
},
|
||||
map[string]any{
|
||||
"i": 2,
|
||||
},
|
||||
map[string]any{
|
||||
"i": 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection"),
|
||||
CaseArray(`
|
||||
LET users = []
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender INTO genders
|
||||
RETURN {
|
||||
gender,
|
||||
values: genders
|
||||
}
|
||||
`, []any{}, "COLLECT gender = i.gender INTO genders: should return an empty array when source is empty"),
|
||||
CaseArray(
|
||||
`LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender INTO genders = { active: users[i].active }
|
||||
RETURN {
|
||||
gender,
|
||||
values: genders
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"active": true},
|
||||
map[string]any{"active": true},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"active": true},
|
||||
map[string]any{"active": true},
|
||||
map[string]any{"active": false},
|
||||
},
|
||||
},
|
||||
}, "Should create custom projection"),
|
||||
CaseArray(
|
||||
`LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender, age = users[i].age INTO genders = { active: users[i].active }
|
||||
RETURN {
|
||||
age,
|
||||
gender,
|
||||
values: genders
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"age": 25,
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"active": true},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"age": 45,
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"active": true},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"age": 31,
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"active": true},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"age": 36,
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"active": true},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"age": 69,
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"active": false},
|
||||
},
|
||||
},
|
||||
}, "Should create custom projection grouped by multiple keys"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET married = users[i].married
|
||||
COLLECT gender = users[i].gender INTO genders KEEP married
|
||||
RETURN {
|
||||
gender,
|
||||
values: genders
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"married": false},
|
||||
map[string]any{"married": true},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"married": true},
|
||||
map[string]any{"married": false},
|
||||
map[string]any{"married": true},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection with default KEEP"),
|
||||
CaseArray(`
|
||||
LET users = []
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET married = users[i].married
|
||||
COLLECT gender = users[i].gender INTO genders KEEP married
|
||||
RETURN {
|
||||
gender,
|
||||
values: genders
|
||||
}
|
||||
`, []any{}, "COLLECT gender = i.gender INTO genders KEEP married: Should return an empty array when source is empty"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET married = users[i].married
|
||||
LET age = users[i].age
|
||||
COLLECT gender = users[i].gender INTO values KEEP married, age
|
||||
RETURN {
|
||||
gender,
|
||||
values
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{
|
||||
"married": false,
|
||||
"age": 25,
|
||||
},
|
||||
map[string]any{
|
||||
"married": true,
|
||||
"age": 45,
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{
|
||||
"married": true,
|
||||
"age": 31,
|
||||
},
|
||||
map[string]any{
|
||||
"married": false,
|
||||
"age": 36,
|
||||
},
|
||||
map[string]any{
|
||||
"married": true,
|
||||
"age": 69,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection with default KEEP using multiple keys"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET married = "foo"
|
||||
COLLECT gender = users[i].gender INTO values KEEP married
|
||||
RETURN {
|
||||
gender,
|
||||
values
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"married": "foo"},
|
||||
map[string]any{"married": "foo"},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"married": "foo"},
|
||||
map[string]any{"married": "foo"},
|
||||
map[string]any{"married": "foo"},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection with custom KEEP"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET married = "foo"
|
||||
LET age = "bar"
|
||||
COLLECT gender = users[i].gender INTO values KEEP married, age
|
||||
RETURN {
|
||||
gender,
|
||||
values
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{
|
||||
"married": "foo",
|
||||
"age": "bar",
|
||||
},
|
||||
map[string]any{
|
||||
"married": "foo",
|
||||
"age": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{
|
||||
"married": "foo",
|
||||
"age": "bar",
|
||||
},
|
||||
map[string]any{
|
||||
"married": "foo",
|
||||
"age": "bar",
|
||||
},
|
||||
map[string]any{
|
||||
"married": "foo",
|
||||
"age": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection with custom KEEP using multiple keys"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET bar = "foo"
|
||||
COLLECT gender = users[i].gender INTO values KEEP bar
|
||||
RETURN {
|
||||
gender,
|
||||
values
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"bar": "foo"},
|
||||
map[string]any{"bar": "foo"},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"bar": "foo"},
|
||||
map[string]any{"bar": "foo"},
|
||||
map[string]any{"bar": "foo"},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection with custom KEEP with custom name"),
|
||||
CaseArray(`
|
||||
LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
LET bar = "foo"
|
||||
LET baz = "bar"
|
||||
COLLECT gender = users[i].gender INTO values KEEP bar, baz
|
||||
RETURN {
|
||||
gender,
|
||||
values
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": []any{
|
||||
map[string]any{"bar": "foo", "baz": "bar"},
|
||||
map[string]any{"bar": "foo", "baz": "bar"},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": []any{
|
||||
map[string]any{"bar": "foo", "baz": "bar"},
|
||||
map[string]any{"bar": "foo", "baz": "bar"},
|
||||
map[string]any{"bar": "foo", "baz": "bar"},
|
||||
},
|
||||
},
|
||||
}, "Should create default projection with custom KEEP with multiple custom names"),
|
||||
CaseArray(
|
||||
`LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender WITH COUNT INTO numberOfUsers
|
||||
RETURN {
|
||||
gender,
|
||||
values: numberOfUsers
|
||||
}
|
||||
`, []any{
|
||||
map[string]any{
|
||||
"gender": "f",
|
||||
"values": 2,
|
||||
},
|
||||
map[string]any{
|
||||
"gender": "m",
|
||||
"values": 3,
|
||||
},
|
||||
}, "Should group and count result by a single key"),
|
||||
|
||||
CaseArray(
|
||||
`
|
||||
LET users = []
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT gender = users[i].gender WITH COUNT INTO numberOfUsers
|
||||
RETURN {
|
||||
gender,
|
||||
values: numberOfUsers
|
||||
}
|
||||
`, []any{}, "COLLECT gender = i.gender WITH COUNT INTO numberOfUsers: Should return empty array when source is empty"),
|
||||
CaseArray(
|
||||
`LET users = [
|
||||
{
|
||||
active: true,
|
||||
age: 31,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 25,
|
||||
gender: "f",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 36,
|
||||
gender: "m",
|
||||
married: false
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
age: 69,
|
||||
gender: "m",
|
||||
married: true
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
age: 45,
|
||||
gender: "f",
|
||||
married: true
|
||||
}
|
||||
]
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT WITH COUNT INTO numberOfUsers
|
||||
RETURN numberOfUsers
|
||||
`, []any{
|
||||
5,
|
||||
}, "Should just count the number of items in the source"),
|
||||
CaseArray(
|
||||
`
|
||||
LET users = []
|
||||
FOR i WHILE UNTIL(LENGTH(users))
|
||||
COLLECT WITH COUNT INTO numberOfUsers
|
||||
RETURN numberOfUsers
|
||||
`, []any{
|
||||
0,
|
||||
}, "Should return 0 when there are no items in the source"),
|
||||
}, vm.WithFunctions(ForWhileHelpers()))
|
||||
}
|
Reference in New Issue
Block a user