|
1 | 1 | package vector |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "slices" |
| 5 | + |
4 | 6 | "github.com/brimdata/super" |
5 | 7 | "github.com/brimdata/super/scode" |
6 | 8 | ) |
@@ -49,3 +51,41 @@ func Deunion(vec Any) Any { |
49 | 51 | } |
50 | 52 | return vec |
51 | 53 | } |
| 54 | + |
| 55 | +// FlattenUnions takes a Dynamic and recursively replaces any Union values |
| 56 | +// with their inner values, rewriting tags so that each slot points directly |
| 57 | +// to the leaf value vector. |
| 58 | +func FlattenUnions(d *Dynamic) *Dynamic { |
| 59 | + hasUnion := slices.ContainsFunc(d.Values, func(vec Any) bool { |
| 60 | + _, ok := vec.(*Union) |
| 61 | + return ok |
| 62 | + }) |
| 63 | + if !hasUnion { |
| 64 | + return d |
| 65 | + } |
| 66 | + bases := make([]uint32, len(d.Values)) |
| 67 | + unions := make([]*Dynamic, len(d.Values)) |
| 68 | + var newValues []Any |
| 69 | + for i, val := range d.Values { |
| 70 | + bases[i] = uint32(len(newValues)) |
| 71 | + if u, ok := val.(*Union); ok { |
| 72 | + flat := FlattenUnions(u.Dynamic) |
| 73 | + unions[i] = flat |
| 74 | + newValues = append(newValues, flat.Values...) |
| 75 | + } else { |
| 76 | + newValues = append(newValues, val) |
| 77 | + } |
| 78 | + } |
| 79 | + forward := d.ForwardTagMap() |
| 80 | + newTags := make([]uint32, len(d.Tags)) |
| 81 | + for slot, oldTag := range d.Tags { |
| 82 | + base := bases[oldTag] |
| 83 | + if d := unions[oldTag]; d != nil { |
| 84 | + innerSlot := forward[slot] |
| 85 | + newTags[slot] = base + d.Tags[innerSlot] |
| 86 | + } else { |
| 87 | + newTags[slot] = base |
| 88 | + } |
| 89 | + } |
| 90 | + return NewDynamic(newTags, newValues) |
| 91 | +} |
0 commit comments