in query/common/hll.go [1028:1126]
func traverseRecursive(dimIdx int, curr interface{}, dimDataTypes []memCom.DataType, enumDicts map[int]map[string]int, hllVector, countVector *[]byte, dimVectors, validityVectors [][]byte) (size int, err error) {
switch v := curr.(type) {
case map[string]interface{}:
dimDataType := dimDataTypes[dimIdx]
dimValueBytes := memCom.DataTypeBytes(dimDataType)
// iterate map in order
keys := make([]string, len(v))
kidx := 0
for k, _ := range v {
keys[kidx] = k
kidx++
}
sort.Strings(keys)
for _, k := range keys {
v := v[k]
// visit child first
var childSize int
childSize, err = traverseRecursive(dimIdx+1, v, dimDataTypes, enumDicts, hllVector, countVector, dimVectors, validityVectors)
if err != nil {
return
}
// convert dimension
var (
dataVal memCom.DataValue
isValid uint8 = 1
)
if NULLString == k {
isValid = 0
} else {
if enumDict, ok := enumDicts[dimIdx]; ok {
enumVal := enumDict[k]
if dimValueBytes == 1 {
ui8 := uint8(enumVal)
dataVal = memCom.DataValue{
Valid: true,
OtherVal: unsafe.Pointer(&ui8),
}
} else if dimValueBytes == 2 {
ui16 := uint16(enumVal)
dataVal = memCom.DataValue{
Valid: true,
OtherVal: unsafe.Pointer(&ui16),
}
} else {
err = utils.StackError(nil, "data width %d doesn't match any enum", dimValueBytes)
}
} else {
dataVal, err = memCom.ValueFromString(k, dimDataType)
if err != nil {
return
}
}
}
var bs []byte
if dataVal.Valid {
byteVal := dataVal.OtherVal
switch dimValueBytes {
case 8:
bs = (*[8]byte)(byteVal)[:]
case 4:
bs = (*[4]byte)(byteVal)[:]
case 2:
bs = (*[2]byte)(byteVal)[:]
case 1:
bs = (*[1]byte)(byteVal)[:]
}
} else {
bs = make([]byte, dimValueBytes)
}
for i := 0; i < childSize; i++ {
dimVectors[dimIdx] = append(dimVectors[dimIdx], bs...)
validityVectors[dimIdx] = append(validityVectors[dimIdx], byte(isValid))
}
size += childSize
}
case HLL:
count := v.NonZeroRegisters
if count < DenseThreshold {
if !v.ConvertToSparse() {
err = utils.StackError(nil, "Failed to convert HLL to sparse %+v", v)
return
}
} else {
v.ConvertToDense()
}
bs := v.EncodeBinary()
*hllVector = append(*hllVector, bs...)
*countVector = append(*countVector, (*((*[2]byte)(unsafe.Pointer(&count))))[:]...)
size = 1
default:
err = utils.StackError(nil, "unknown type %+v", curr)
}
return
}