mirror of
https://github.com/MontFerret/ferret.git
synced 2025-08-13 19:52:52 +02:00
Refactor collect handling; restructure group and aggregation logic, unify loop operations, and improve method clarity
This commit is contained in:
@@ -18,27 +18,35 @@ func NewCollectCompiler(ctx *CompilerContext) *CollectCompiler {
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) Compile(ctx fql.ICollectClauseContext) {
|
||||
// TODO: Undefine original loop variables
|
||||
loop := cc.ctx.Loops.Current()
|
||||
aggregator := ctx.CollectAggregator()
|
||||
kvKeyReg, kvValReg, groupSelectors := cc.compileGrouping(ctx, aggregator != nil)
|
||||
|
||||
// We collect the aggregation keys
|
||||
// And wrap each loop element by a KeyValuePair
|
||||
// Where a key is either a single value or a list of values
|
||||
// These KeyValuePairs are then added to the dataset
|
||||
// Aggregation loop
|
||||
if aggregator != nil {
|
||||
cc.compileAggregation(aggregator, len(groupSelectors) > 0)
|
||||
}
|
||||
|
||||
if len(groupSelectors) > 0 {
|
||||
// Now we are defining new variables for the group selectors
|
||||
cc.compileGroupSelectorVariables(groupSelectors, kvKeyReg, kvValReg, aggregator != nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) compileGrouping(ctx fql.ICollectClauseContext, aggregation bool) (vm.Operand, vm.Operand, []fql.ICollectSelectorContext) {
|
||||
var kvKeyReg, kvValReg vm.Operand
|
||||
var groupSelectors []fql.ICollectSelectorContext
|
||||
var isGrouping bool
|
||||
grouping := ctx.CollectGrouping()
|
||||
counter := ctx.CollectCounter()
|
||||
aggregator := ctx.CollectAggregator()
|
||||
|
||||
isCollecting := grouping != nil || counter != nil
|
||||
if grouping == nil && counter == nil {
|
||||
return kvKeyReg, kvValReg, groupSelectors
|
||||
}
|
||||
|
||||
loop := cc.ctx.Loops.Current()
|
||||
|
||||
if isCollecting {
|
||||
if grouping != nil {
|
||||
isGrouping = true
|
||||
groupSelectors = grouping.AllCollectSelector()
|
||||
kvKeyReg = cc.compileCollectGroupKeySelectors(groupSelectors)
|
||||
kvKeyReg = cc.compileGroupSelectors(groupSelectors)
|
||||
}
|
||||
|
||||
kvValReg = cc.ctx.Registers.Allocate(core.Temp)
|
||||
@@ -60,7 +68,7 @@ func (cc *CollectCompiler) Compile(ctx fql.ICollectClauseContext) {
|
||||
} else if counter != nil {
|
||||
projectionVariableName = counter.Identifier().GetText()
|
||||
|
||||
if isGrouping {
|
||||
if grouping != nil {
|
||||
collectorType = core.CollectorTypeKeyCounter
|
||||
} else {
|
||||
collectorType = core.CollectorTypeCounter
|
||||
@@ -68,7 +76,7 @@ func (cc *CollectCompiler) Compile(ctx fql.ICollectClauseContext) {
|
||||
}
|
||||
|
||||
// If we use aggregators, we need to collect group items by key
|
||||
if aggregator != nil && collectorType != core.CollectorTypeKeyGroup {
|
||||
if aggregation && collectorType != core.CollectorTypeKeyGroup {
|
||||
// We need to patch the loop result to be a collector
|
||||
collectorType = core.CollectorTypeKeyGroup
|
||||
}
|
||||
@@ -100,28 +108,20 @@ func (cc *CollectCompiler) Compile(ctx fql.ICollectClauseContext) {
|
||||
loop.EmitKey(kvKeyReg, cc.ctx.Emitter)
|
||||
//loop.EmitValue(kvValReg, cc.ctx.Emitter)
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregation loop
|
||||
if aggregator != nil {
|
||||
cc.compileAggregation(aggregator, loop, isCollecting)
|
||||
}
|
||||
|
||||
if isCollecting && isGrouping {
|
||||
// Now we are defining new variables for the group selectors
|
||||
cc.compileCollectGroupKeySelectorVariables(groupSelectors, kvKeyReg, kvValReg, aggregator != nil)
|
||||
}
|
||||
return kvKeyReg, kvValReg, groupSelectors
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) compileAggregation(c fql.ICollectAggregatorContext, parentLoop *core.Loop, isCollected bool) {
|
||||
if isCollected {
|
||||
cc.compileGroupedAggregation(c, parentLoop)
|
||||
func (cc *CollectCompiler) compileAggregation(c fql.ICollectAggregatorContext, isGrouped bool) {
|
||||
if isGrouped {
|
||||
cc.compileGroupedAggregation(c)
|
||||
} else {
|
||||
cc.compileGlobalAggregation(c, parentLoop)
|
||||
cc.compileGlobalAggregation(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) compileGroupedAggregation(c fql.ICollectAggregatorContext, parentLoop *core.Loop) {
|
||||
func (cc *CollectCompiler) compileGroupedAggregation(c fql.ICollectAggregatorContext) {
|
||||
parentLoop := cc.ctx.Loops.Current()
|
||||
// We need to allocate a temporary accumulators to store aggregation results
|
||||
selectors := c.AllCollectAggregateSelector()
|
||||
accums := cc.initAggrAccumulators(selectors)
|
||||
@@ -164,7 +164,8 @@ func (cc *CollectCompiler) compileGroupedAggregation(c fql.ICollectAggregatorCon
|
||||
// cc.ctx.Registers.Free(aggrIterVal)
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) compileGlobalAggregation(c fql.ICollectAggregatorContext, parentLoop *core.Loop) {
|
||||
func (cc *CollectCompiler) compileGlobalAggregation(c fql.ICollectAggregatorContext) {
|
||||
parentLoop := cc.ctx.Loops.Current()
|
||||
loop := parentLoop
|
||||
// we create a custom collector for aggregators
|
||||
cc.ctx.Emitter.PatchSwapAx(loop.ResultPos, vm.OpDataSetCollector, loop.Result, int(core.CollectorTypeKeyGroup))
|
||||
@@ -269,7 +270,7 @@ func (cc *CollectCompiler) compileAggregationFuncCall(selectors []fql.ICollectAg
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) compileCollectGroupKeySelectors(selectors []fql.ICollectSelectorContext) vm.Operand {
|
||||
func (cc *CollectCompiler) compileGroupSelectors(selectors []fql.ICollectSelectorContext) vm.Operand {
|
||||
if len(selectors) == 0 {
|
||||
return vm.NoopOperand
|
||||
}
|
||||
@@ -298,7 +299,7 @@ func (cc *CollectCompiler) compileCollectGroupKeySelectors(selectors []fql.IColl
|
||||
return kvKeyReg
|
||||
}
|
||||
|
||||
func (cc *CollectCompiler) compileCollectGroupKeySelectorVariables(selectors []fql.ICollectSelectorContext, kvKeyReg, kvValReg vm.Operand, isAggregation bool) {
|
||||
func (cc *CollectCompiler) compileGroupSelectorVariables(selectors []fql.ICollectSelectorContext, kvKeyReg, kvValReg vm.Operand, isAggregation bool) {
|
||||
if len(selectors) > 1 {
|
||||
variables := make([]vm.Operand, len(selectors))
|
||||
|
||||
|
Reference in New Issue
Block a user