github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/aggregations/evalaggs.go (about)

     1  /*
     2  Copyright 2023.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package aggregations
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"sort"
    23  	"strings"
    24  
    25  	"github.com/siglens/siglens/pkg/segment/structs"
    26  	"github.com/siglens/siglens/pkg/segment/utils"
    27  )
    28  
    29  func ComputeAggEvalForMinOrMax(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure, isMin bool) error {
    30  	fields := measureAgg.ValueColRequest.GetFields()
    31  	if len(fields) != 1 {
    32  		return fmt.Errorf("ComputeAggEvalForMinOrMax: Incorrect number of fields for aggCol: %v", measureAgg.String())
    33  	}
    34  
    35  	sst, ok := sstMap[fields[0]]
    36  	if !ok {
    37  		return fmt.Errorf("ComputeAggEvalForMinOrMax: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
    38  	}
    39  	fieldToValue := make(map[string]utils.CValueEnclosure)
    40  
    41  	edgeValue := -1.7976931348623157e+308
    42  	if isMin {
    43  		edgeValue = math.MaxFloat64
    44  	}
    45  
    46  	for _, eVal := range sst.Records {
    47  		fieldToValue[fields[0]] = *eVal
    48  		boolResult, err := measureAgg.ValueColRequest.BooleanExpr.Evaluate(fieldToValue)
    49  		if err != nil {
    50  			return fmt.Errorf("ComputeAggEvalForMinOrMax: there are some errors in the eval function that is inside the min/max function: %v", err)
    51  		}
    52  
    53  		if boolResult {
    54  			eValFloat, err := eVal.GetFloatValue()
    55  			if err != nil {
    56  				return fmt.Errorf("ComputeAggEvalForMinOrMax: can not get the float value: %v", err)
    57  			}
    58  			// Keep maximum and minimum values
    59  			if (isMin && eValFloat < edgeValue) || (!isMin && eValFloat > edgeValue) {
    60  				edgeValue = eValFloat
    61  			}
    62  		}
    63  	}
    64  	enclosure, exists := measureResults[measureAgg.String()]
    65  	if !exists {
    66  
    67  		cVal := -1.7976931348623157e+308
    68  		if isMin {
    69  			cVal = math.MaxFloat64
    70  		}
    71  
    72  		enclosure = utils.CValueEnclosure{
    73  			Dtype: utils.SS_DT_FLOAT,
    74  			CVal:  cVal,
    75  		}
    76  		measureResults[measureAgg.String()] = enclosure
    77  	}
    78  
    79  	eValFloat, err := enclosure.GetFloatValue()
    80  	if err != nil {
    81  		return fmt.Errorf("ComputeAggEvalForMinOrMax: Attempted to perform aggregate min(), but the column %s is not a float value", fields[0])
    82  	}
    83  
    84  	if (isMin && eValFloat > edgeValue) || (!isMin && eValFloat < edgeValue) {
    85  		enclosure.CVal = edgeValue
    86  		measureResults[measureAgg.String()] = enclosure
    87  	}
    88  	return nil
    89  }
    90  
    91  func ComputeAggEvalForRange(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure, runningEvalStats map[string]interface{}) error {
    92  	fields := measureAgg.ValueColRequest.GetFields()
    93  	if len(fields) != 1 {
    94  		return fmt.Errorf("ComputeAggEvalForRange: Incorrect number of fields for aggCol: %v", measureAgg.String())
    95  	}
    96  
    97  	sst, ok := sstMap[fields[0]]
    98  	if !ok {
    99  		return fmt.Errorf("ComputeAggEvalForRange: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   100  	}
   101  	fieldToValue := make(map[string]utils.CValueEnclosure)
   102  
   103  	maxVal := -1.7976931348623157e+308
   104  	minVal := math.MaxFloat64
   105  
   106  	for _, eVal := range sst.Records {
   107  		fieldToValue[fields[0]] = *eVal
   108  		boolResult, err := measureAgg.ValueColRequest.BooleanExpr.Evaluate(fieldToValue)
   109  		if err != nil {
   110  			return fmt.Errorf("ComputeAggEvalForRange: there are some errors in the eval function that is inside the range function: %v", err)
   111  		}
   112  
   113  		if boolResult {
   114  			eValFloat, err := eVal.GetFloatValue()
   115  			if err != nil {
   116  				return fmt.Errorf("ComputeAggEvalForRange: can not get the float value: %v", err)
   117  			}
   118  			// Keep maximum and minimum values
   119  			if eValFloat < minVal {
   120  				minVal = eValFloat
   121  			}
   122  			if eValFloat > maxVal {
   123  				maxVal = eValFloat
   124  			}
   125  		}
   126  	}
   127  
   128  	rangeStat := &structs.RangeStat{}
   129  	rangeStatVal, exists := runningEvalStats[measureAgg.String()]
   130  	if !exists {
   131  		rangeStat.Min = minVal
   132  		rangeStat.Max = maxVal
   133  	} else {
   134  		rangeStat = rangeStatVal.(*structs.RangeStat)
   135  		if rangeStat.Min > minVal {
   136  			rangeStat.Min = minVal
   137  		}
   138  		if rangeStat.Max < maxVal {
   139  			rangeStat.Max = maxVal
   140  		}
   141  	}
   142  	runningEvalStats[measureAgg.String()] = rangeStat
   143  	rangeVal := rangeStat.Max - rangeStat.Min
   144  
   145  	enclosure, exists := measureResults[measureAgg.String()]
   146  	if !exists {
   147  		enclosure = utils.CValueEnclosure{
   148  			Dtype: utils.SS_DT_FLOAT,
   149  			CVal:  rangeVal,
   150  		}
   151  		measureResults[measureAgg.String()] = enclosure
   152  	}
   153  
   154  	eValFloat, err := enclosure.GetFloatValue()
   155  	if err != nil {
   156  		return fmt.Errorf("ComputeAggEvalForRange: Attempted to perform aggregate min(), but the column %s is not a float value", fields[0])
   157  	}
   158  
   159  	if eValFloat < rangeVal {
   160  		enclosure.CVal = rangeVal
   161  		measureResults[measureAgg.String()] = enclosure
   162  	}
   163  	return nil
   164  }
   165  
   166  func ComputeAggEvalForSum(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure) error {
   167  	fields := measureAgg.ValueColRequest.GetFields()
   168  	if len(fields) != 1 {
   169  		return fmt.Errorf("ComputeAggEvalForSum: Incorrect number of fields for aggCol: %v", measureAgg.String())
   170  	}
   171  
   172  	sst, ok := sstMap[fields[0]]
   173  	if !ok {
   174  		return fmt.Errorf("ComputeAggEvalForSum: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   175  	}
   176  	fieldToValue := make(map[string]utils.CValueEnclosure)
   177  
   178  	sumVal := float64(0)
   179  
   180  	for _, eVal := range sst.Records {
   181  		fieldToValue[fields[0]] = *eVal
   182  		boolResult, err := measureAgg.ValueColRequest.BooleanExpr.Evaluate(fieldToValue)
   183  		if err != nil {
   184  			return fmt.Errorf("ComputeAggEvalForSum: there are some errors in the eval function that is inside the sum function: %v", err)
   185  		}
   186  
   187  		if boolResult {
   188  			eValFloat, err := eVal.GetFloatValue()
   189  			if err != nil {
   190  				return fmt.Errorf("ComputeAggEvalForSum: can not get the float value: %v", err)
   191  			}
   192  			sumVal += eValFloat
   193  		}
   194  	}
   195  	enclosure, exists := measureResults[measureAgg.String()]
   196  	if !exists {
   197  		enclosure = utils.CValueEnclosure{
   198  			Dtype: utils.SS_DT_FLOAT,
   199  			CVal:  float64(0),
   200  		}
   201  		measureResults[measureAgg.String()] = enclosure
   202  	}
   203  
   204  	eValFloat, err := enclosure.GetFloatValue()
   205  	if err != nil {
   206  		return fmt.Errorf("ComputeAggEvalForSum: Attempted to perform aggregate min(), but the column %s is not a float value", fields[0])
   207  	}
   208  
   209  	enclosure.CVal = eValFloat + sumVal
   210  	measureResults[measureAgg.String()] = enclosure
   211  
   212  	return nil
   213  }
   214  
   215  func ComputeAggEvalForCount(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure) error {
   216  
   217  	countVal := int64(0)
   218  	fields := measureAgg.ValueColRequest.GetFields()
   219  	if len(fields) == 0 {
   220  		return fmt.Errorf("ComputeAggEvalForCount: Incorrect number of fields for aggCol: %v", measureAgg.String())
   221  	}
   222  
   223  	sst, ok := sstMap[fields[0]]
   224  	if !ok {
   225  		return fmt.Errorf("ComputeAggEvalForCount: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   226  	}
   227  
   228  	length := len(sst.Records)
   229  	for i := 0; i < length; i++ {
   230  		fieldToValue := make(map[string]utils.CValueEnclosure)
   231  		// Initialize fieldToValue
   232  		for _, field := range fields {
   233  			sst, ok := sstMap[field]
   234  			if !ok {
   235  				return fmt.Errorf("ComputeAggEvalForCount: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   236  			}
   237  
   238  			if i >= len(sst.Records) {
   239  				return fmt.Errorf("ComputeAggEvalForCount: Incorrect length of field: %v for aggCol: %v", field, measureAgg.String())
   240  			}
   241  			fieldToValue[field] = *sst.Records[i]
   242  		}
   243  
   244  		boolResult, err := measureAgg.ValueColRequest.BooleanExpr.Evaluate(fieldToValue)
   245  		if err != nil {
   246  			return fmt.Errorf("ComputeAggEvalForCount: there are some errors in the eval function that is inside the count function: %v", err)
   247  		}
   248  
   249  		if boolResult {
   250  			countVal++
   251  		}
   252  	}
   253  
   254  	enclosure, exists := measureResults[measureAgg.String()]
   255  	if !exists {
   256  		enclosure = utils.CValueEnclosure{
   257  			Dtype: utils.SS_DT_SIGNED_NUM,
   258  			CVal:  int64(0),
   259  		}
   260  		measureResults[measureAgg.String()] = enclosure
   261  	}
   262  
   263  	eVal, err := enclosure.GetValue()
   264  	if err != nil {
   265  		return fmt.Errorf("ComputeAggEvalForCount: Attempted to perform aggregate min(), but the column %s is not a float value", fields[0])
   266  	}
   267  
   268  	enclosure.CVal = eVal.(int64) + countVal
   269  	measureResults[measureAgg.String()] = enclosure
   270  
   271  	return nil
   272  }
   273  
   274  func ComputeAggEvalForAvg(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure, runningEvalStats map[string]interface{}) error {
   275  	fields := measureAgg.ValueColRequest.GetFields()
   276  	if len(fields) != 1 {
   277  		return fmt.Errorf("ComputeAggEvalForAvg: Incorrect number of fields for aggCol: %v", measureAgg.String())
   278  	}
   279  
   280  	sst, ok := sstMap[fields[0]]
   281  	if !ok {
   282  		return fmt.Errorf("ComputeAggEvalForAvg: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   283  	}
   284  	fieldToValue := make(map[string]utils.CValueEnclosure)
   285  
   286  	sumVal := float64(0)
   287  	countVal := int64(0)
   288  	for _, eVal := range sst.Records {
   289  		fieldToValue[fields[0]] = *eVal
   290  		boolResult, err := measureAgg.ValueColRequest.BooleanExpr.Evaluate(fieldToValue)
   291  		if err != nil {
   292  			return fmt.Errorf("ComputeAggEvalForAvg: there are some errors in the eval function that is inside the avg function: %v", err)
   293  		}
   294  
   295  		if boolResult {
   296  			eValFloat, err := eVal.GetFloatValue()
   297  			if err != nil {
   298  				return fmt.Errorf("ComputeAggEvalForAvg: can not get the float value: %v", err)
   299  			}
   300  			sumVal += eValFloat
   301  			countVal++
   302  		}
   303  	}
   304  
   305  	avgStat := &structs.AvgStat{}
   306  	avgStatVal, exists := runningEvalStats[measureAgg.String()]
   307  	if !exists {
   308  		avgStat.Sum = sumVal
   309  		avgStat.Count = countVal
   310  	} else {
   311  		avgStat = avgStatVal.(*structs.AvgStat)
   312  		avgStat.Sum += sumVal
   313  		avgStat.Count += countVal
   314  	}
   315  	runningEvalStats[measureAgg.String()] = avgStat
   316  
   317  	measureResults[measureAgg.String()] = utils.CValueEnclosure{
   318  		Dtype: utils.SS_DT_FLOAT,
   319  		CVal:  avgStat.Sum / float64(avgStat.Count),
   320  	}
   321  
   322  	return nil
   323  }
   324  
   325  func ComputeAggEvalForCardinality(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure, runningEvalStats map[string]interface{}) error {
   326  	fields := measureAgg.ValueColRequest.GetFields()
   327  	if len(fields) == 0 {
   328  		return fmt.Errorf("ComputeAggEvalForCount: Incorrect number of fields for aggCol: %v", measureAgg.String())
   329  	}
   330  
   331  	sst, ok := sstMap[fields[0]]
   332  	if !ok {
   333  		return fmt.Errorf("ComputeAggEvalForCount: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   334  	}
   335  
   336  	strSet := make(map[string]struct{}, 0)
   337  	valuesStrSetVal, exists := runningEvalStats[measureAgg.String()]
   338  	if !exists {
   339  		runningEvalStats[measureAgg.String()] = make(map[string]struct{}, 0)
   340  	} else {
   341  		strSet, ok = valuesStrSetVal.(map[string]struct{})
   342  		if !ok {
   343  			return fmt.Errorf("ComputeAggEvalForCardinality: can not convert strSet for aggCol: %v", measureAgg.String())
   344  		}
   345  	}
   346  
   347  	length := len(sst.Records)
   348  	for i := 0; i < length; i++ {
   349  		fieldToValue := make(map[string]utils.CValueEnclosure)
   350  		// Initialize fieldToValue
   351  		for _, field := range fields {
   352  			sst, ok := sstMap[field]
   353  			if !ok {
   354  				return fmt.Errorf("ComputeAggEvalForCount: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   355  			}
   356  
   357  			if i >= len(sst.Records) {
   358  				return fmt.Errorf("ComputeAggEvalForCount: Incorrect length of field: %v for aggCol: %v", field, measureAgg.String())
   359  			}
   360  			fieldToValue[field] = *sst.Records[i]
   361  		}
   362  
   363  		cellValueStr, err := measureAgg.ValueColRequest.EvaluateToString(fieldToValue)
   364  		if err != nil {
   365  			return fmt.Errorf("ComputeAggEvalForCount: there are some errors in the eval function that is inside the cardinality function: %v", err)
   366  		}
   367  
   368  		strSet[cellValueStr] = struct{}{}
   369  	}
   370  
   371  	measureResults[measureAgg.String()] = utils.CValueEnclosure{
   372  		Dtype: utils.SS_DT_SIGNED_NUM,
   373  		CVal:  int64(len(strSet)),
   374  	}
   375  
   376  	return nil
   377  }
   378  
   379  func ComputeAggEvalForValues(measureAgg *structs.MeasureAggregator, sstMap map[string]*structs.SegStats, measureResults map[string]utils.CValueEnclosure, strSet map[string]struct{}) error {
   380  	fields := measureAgg.ValueColRequest.GetFields()
   381  	if len(fields) == 0 {
   382  		return fmt.Errorf("ComputeAggEvalForValues: Incorrect number of fields for aggCol: %v", measureAgg.String())
   383  	}
   384  
   385  	sst, ok := sstMap[fields[0]]
   386  	if !ok {
   387  		return fmt.Errorf("ComputeAggEvalForValues: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   388  	}
   389  
   390  	length := len(sst.Records)
   391  	for i := 0; i < length; i++ {
   392  		fieldToValue := make(map[string]utils.CValueEnclosure)
   393  		// Initialize fieldToValue
   394  		for _, field := range fields {
   395  			sst, ok := sstMap[field]
   396  			if !ok {
   397  				return fmt.Errorf("ComputeAggEvalForValues: applyAggOpOnSegments sstMap was nil for aggCol %v", measureAgg.MeasureCol)
   398  			}
   399  
   400  			if i >= len(sst.Records) {
   401  				return fmt.Errorf("ComputeAggEvalForValues: Incorrect length of field: %v for aggCol: %v", field, measureAgg.String())
   402  			}
   403  			fieldToValue[field] = *sst.Records[i]
   404  		}
   405  
   406  		cellValueStr, err := measureAgg.ValueColRequest.EvaluateToString(fieldToValue)
   407  		if err != nil {
   408  			return fmt.Errorf("ComputeAggEvalForValues: there are some errors in the eval function that is inside the values function: %v", err)
   409  		}
   410  
   411  		strSet[cellValueStr] = struct{}{}
   412  	}
   413  
   414  	uniqueStrings := make([]string, 0)
   415  	for str := range strSet {
   416  		uniqueStrings = append(uniqueStrings, str)
   417  	}
   418  	sort.Strings(uniqueStrings)
   419  
   420  	strVal := strings.Join(uniqueStrings, "&nbsp")
   421  	measureResults[measureAgg.String()] = utils.CValueEnclosure{
   422  		Dtype: utils.SS_DT_STRING,
   423  		CVal:  strVal,
   424  	}
   425  
   426  	return nil
   427  }
   428  
   429  func AddMeasureAggInRunningStatsForCount(m *structs.MeasureAggregator, allConvertedMeasureOps *[]*structs.MeasureAggregator, allReverseIndex *[]int, colToIdx map[string][]int, idx int) (int, error) {
   430  
   431  	fields := m.ValueColRequest.GetFields()
   432  	if len(fields) == 0 {
   433  		return idx, fmt.Errorf("AddMeasureAggInRunningStatsForCount: Incorrect number of fields for aggCol: %v", m.String())
   434  	}
   435  
   436  	// Use the index of agg to map to the corresponding index of the runningStats result, so that we can determine which index of the result set contains the result we need.
   437  	*allReverseIndex = append(*allReverseIndex, idx)
   438  	for _, field := range fields {
   439  		if _, ok := colToIdx[field]; !ok {
   440  			colToIdx[field] = make([]int, 0)
   441  		}
   442  		colToIdx[field] = append(colToIdx[field], idx)
   443  		*allConvertedMeasureOps = append(*allConvertedMeasureOps, &structs.MeasureAggregator{
   444  			MeasureCol:      field,
   445  			MeasureFunc:     utils.Count,
   446  			ValueColRequest: m.ValueColRequest,
   447  			StrEnc:          m.StrEnc,
   448  		})
   449  		idx++
   450  	}
   451  	return idx, nil
   452  }
   453  
   454  func AddMeasureAggInRunningStatsForAvg(m *structs.MeasureAggregator, allConvertedMeasureOps *[]*structs.MeasureAggregator, allReverseIndex *[]int, colToIdx map[string][]int, idx int) (int, error) {
   455  
   456  	fields := m.ValueColRequest.GetFields()
   457  	if len(fields) != 1 {
   458  		return idx, fmt.Errorf("AddMeasureAggInRunningStatsForAvg: Incorrect number of fields for aggCol: %v", m.String())
   459  	}
   460  	field := fields[0]
   461  
   462  	if _, ok := colToIdx[field]; !ok {
   463  		colToIdx[field] = make([]int, 0)
   464  	}
   465  
   466  	// We need to use sum() and count() to calculate the avg()
   467  	*allReverseIndex = append(*allReverseIndex, idx)
   468  	colToIdx[field] = append(colToIdx[field], idx)
   469  	*allConvertedMeasureOps = append(*allConvertedMeasureOps, &structs.MeasureAggregator{
   470  		MeasureCol:      field,
   471  		MeasureFunc:     utils.Sum,
   472  		ValueColRequest: m.ValueColRequest,
   473  		StrEnc:          m.StrEnc,
   474  	})
   475  	idx++
   476  
   477  	*allReverseIndex = append(*allReverseIndex, idx)
   478  	colToIdx[field] = append(colToIdx[field], idx)
   479  	*allConvertedMeasureOps = append(*allConvertedMeasureOps, &structs.MeasureAggregator{
   480  		MeasureCol:      field,
   481  		MeasureFunc:     utils.Count,
   482  		ValueColRequest: m.ValueColRequest,
   483  		StrEnc:          m.StrEnc,
   484  	})
   485  	idx++
   486  	return idx, nil
   487  }
   488  
   489  // Record the index of range() in runningStats; the index is idx
   490  // To calculate the range(), we need both the min() and max(), which require two columns to store them
   491  // Since it is the runningStats not the stats for results, we can use one extra col to store the min/max
   492  // idx stores the result of min, and idx+1 stores the result of max.
   493  func AddMeasureAggInRunningStatsForRange(m *structs.MeasureAggregator, allConvertedMeasureOps *[]*structs.MeasureAggregator, allReverseIndex *[]int, colToIdx map[string][]int, idx int) (int, error) {
   494  
   495  	measureCol := m.MeasureCol
   496  	if m.ValueColRequest != nil {
   497  		fields := m.ValueColRequest.GetFields()
   498  		if len(fields) != 1 {
   499  			return idx, fmt.Errorf("AddMeasureAggInRunningStatsForRange: Incorrect number of fields for aggCol: %v", m.String())
   500  		}
   501  		measureCol = fields[0]
   502  	}
   503  
   504  	if _, ok := colToIdx[measureCol]; !ok {
   505  		colToIdx[measureCol] = make([]int, 0)
   506  	}
   507  	*allReverseIndex = append(*allReverseIndex, idx)
   508  	colToIdx[measureCol] = append(colToIdx[measureCol], idx)
   509  	*allConvertedMeasureOps = append(*allConvertedMeasureOps, &structs.MeasureAggregator{
   510  		MeasureCol:      measureCol,
   511  		MeasureFunc:     utils.Min,
   512  		ValueColRequest: m.ValueColRequest,
   513  		StrEnc:          m.StrEnc,
   514  	})
   515  	idx++
   516  
   517  	*allReverseIndex = append(*allReverseIndex, idx)
   518  	colToIdx[measureCol] = append(colToIdx[measureCol], idx)
   519  	*allConvertedMeasureOps = append(*allConvertedMeasureOps, &structs.MeasureAggregator{
   520  		MeasureCol:      measureCol,
   521  		MeasureFunc:     utils.Max,
   522  		ValueColRequest: m.ValueColRequest,
   523  		StrEnc:          m.StrEnc,
   524  	})
   525  	idx++
   526  
   527  	return idx, nil
   528  }
   529  
   530  func AddMeasureAggInRunningStatsForValuesOrCardinality(m *structs.MeasureAggregator, allConvertedMeasureOps *[]*structs.MeasureAggregator, allReverseIndex *[]int, colToIdx map[string][]int, idx int) (int, error) {
   531  
   532  	fields := m.ValueColRequest.GetFields()
   533  	if len(fields) == 0 {
   534  		return idx, fmt.Errorf("AddMeasureAggInRunningStatsForValuesOrCardinality: Incorrect number of fields for aggCol: %v", m.String())
   535  	}
   536  
   537  	// Use the index of agg to map to the corresponding index of the runningStats result, so that we can determine which index of the result set contains the result we need.
   538  	*allReverseIndex = append(*allReverseIndex, idx)
   539  	for _, field := range fields {
   540  		if _, ok := colToIdx[field]; !ok {
   541  			colToIdx[field] = make([]int, 0)
   542  		}
   543  		colToIdx[field] = append(colToIdx[field], idx)
   544  		*allConvertedMeasureOps = append(*allConvertedMeasureOps, &structs.MeasureAggregator{
   545  			MeasureCol:      field,
   546  			MeasureFunc:     utils.Values,
   547  			ValueColRequest: m.ValueColRequest,
   548  			StrEnc:          m.StrEnc,
   549  		})
   550  		idx++
   551  	}
   552  	return idx, nil
   553  }
   554  
   555  // Determine if cols used by eval statements or not
   556  func DetermineAggColUsage(measureAgg *structs.MeasureAggregator, aggCols map[string]bool, aggColUsage map[string]utils.AggColUsageMode, valuesUsage map[string]bool) {
   557  	if measureAgg.ValueColRequest != nil {
   558  		for _, field := range measureAgg.ValueColRequest.GetFields() {
   559  			aggCols[field] = true
   560  			colUsage, exists := aggColUsage[field]
   561  			if exists {
   562  				if colUsage == utils.NoEvalUsage {
   563  					aggColUsage[field] = utils.BothUsage
   564  				}
   565  			} else {
   566  				aggColUsage[field] = utils.WithEvalUsage
   567  			}
   568  		}
   569  		measureAgg.MeasureCol = measureAgg.StrEnc
   570  	} else {
   571  		aggCols[measureAgg.MeasureCol] = true
   572  		if measureAgg.MeasureFunc == utils.Values {
   573  			valuesUsage[measureAgg.MeasureCol] = true
   574  		}
   575  
   576  		colUsage, exists := aggColUsage[measureAgg.MeasureCol]
   577  		if exists {
   578  			if colUsage == utils.WithEvalUsage {
   579  				aggColUsage[measureAgg.MeasureCol] = utils.BothUsage
   580  			}
   581  		} else {
   582  			aggColUsage[measureAgg.MeasureCol] = utils.NoEvalUsage
   583  		}
   584  	}
   585  }