Skip to content

Commit

Permalink
change variant to dynamic
Browse files Browse the repository at this point in the history
This commit changes our terminology for a top-level dynamic
type to "Dynamic" from "Variant".  The term "variant" has been
corrupted by the industry to mean efficiently-encoded
semi-structured data when the traditional meaning from
programming languages is a tagged union.  To avoid this
confusion, we're following clickhouse's terminology and using
the term dynamic instead.  This change is internal to the code
only and does not affect any user-facing documentation as
the super-structured data model is strongly typed throughout
and does not expose the implied top-level dynamic type as
a user-visible type.
  • Loading branch information
mccanne committed Sep 25, 2024
1 parent 961e86b commit 09f1fb5
Show file tree
Hide file tree
Showing 24 changed files with 166 additions and 166 deletions.
8 changes: 4 additions & 4 deletions runtime/vam/expr/function/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (b *Base64) Call(args ...vector.Any) vector.Any {
out.Append(base64.StdEncoding.EncodeToString(bytes))
}
err := vector.NewStringError(b.zctx, "base64: illegal null argument", errcnt)
return vector.NewVariant(tags, []vector.Any{out, err})
return vector.NewDynamic(tags, []vector.Any{out, err})
case zed.IDString:
errvals := vector.NewStringEmpty(0, nil)
tags := make([]uint32, val.Len())
Expand All @@ -49,7 +49,7 @@ func (b *Base64) Call(args ...vector.Any) vector.Any {
out.Append(bytes)
}
err := vector.NewWrappedError(b.zctx, "base64: string argument is not base64", errvals)
return vector.NewVariant(tags, []vector.Any{out, err})
return vector.NewDynamic(tags, []vector.Any{out, err})
default:
return vector.NewWrappedError(b.zctx, "base64: argument must a bytes or string type", val)
}
Expand Down Expand Up @@ -77,7 +77,7 @@ func (h *Hex) Call(args ...vector.Any) vector.Any {
out.Append(hex.EncodeToString(bytes))
}
err := vector.NewStringError(h.zctx, "hex: illegal null argument", errcnt)
return vector.NewVariant(tags, []vector.Any{out, err})
return vector.NewDynamic(tags, []vector.Any{out, err})
case zed.IDString:
errvals := vector.NewStringEmpty(0, nil)
tags := make([]uint32, val.Len())
Expand All @@ -96,7 +96,7 @@ func (h *Hex) Call(args ...vector.Any) vector.Any {
out.Append(bytes)
}
err := vector.NewWrappedError(h.zctx, "hex: string argument is not hexidecimal", errvals)
return vector.NewVariant(tags, []vector.Any{out, err})
return vector.NewDynamic(tags, []vector.Any{out, err})
default:
return vector.NewWrappedError(h.zctx, "hex: argument must a bytes or string type", val)
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/vam/expr/function/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (r *Replace) Call(args ...vector.Any) vector.Any {
out.Append(strings.ReplaceAll(s, old, new))
}
errval := vector.NewStringError(r.zctx, "replace: an input arg is null", errcnt)
return vector.NewVariant(tags, []vector.Any{out, errval})
return vector.NewDynamic(tags, []vector.Any{out, errval})
}

// https://github.com/brimdata/zed/blob/main/docs/language/functions.md#run_len
Expand Down
2 changes: 1 addition & 1 deletion runtime/vam/expr/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ func indexRecord(zctx *zed.Context, record *vector.Record, index vector.Any) vec
for i, field := range record.Fields {
out[i] = vector.NewView(viewIndexes[i], field)
}
return vector.NewVariant(tags, out)
return vector.NewDynamic(tags, out)
}
10 changes: 5 additions & 5 deletions runtime/vam/expr/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func NewLogicalOr(zctx *zed.Context, lhs, rhs Evaluator) *Or {
}

func (a *And) Eval(val vector.Any) vector.Any {
//XXX change this logic to handle variant instead of simple ok decision,
//XXX change this logic to handle dynamic instead of simple ok decision,
// if there are any valid bools then we need to and them together
lhs, ok := EvalBool(a.zctx, val, a.lhs)
if !ok {
Expand Down Expand Up @@ -102,15 +102,15 @@ func (o *Or) Eval(val vector.Any) vector.Any {
// slot and they are returned as an error. If all of the value slots are errors,
// then the return value is nil.
func EvalBool(zctx *zed.Context, val vector.Any, e Evaluator) (vector.Any, bool) {
//XXX Eval could return a variant of errors and bools and we should
//XXX Eval could return a dynamic vector of errors and bools and we should
// handle this correctly so the logic above is really the fast path
// and a slower path will handle picking apart the variant.
// maybe we could have a generic way to traverse variants for
// and a slower path will handle picking apart the dynamic vector.
// maybe we could have a generic way to traverse dynamics for
// appliers doing their thing along the slow path
if val, ok := vector.Under(e.Eval(val)).(*vector.Bool); ok {
return val, true
}
//XXX need to implement a sparse variant (vector.Collection?)
//XXX need to implement a sparse dynamic (vector.Collection?)
// and check for that here.
// for now, if the vector is not uniformly boolean, we return error.
// XXX example is a field ref a union of structs where the type of
Expand Down
8 changes: 4 additions & 4 deletions runtime/vam/materialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ func (m *Materializer) Pull(done bool) (zbuf.Batch, error) {
if vec == nil || err != nil {
return nil, err
}
variant, _ := vec.(*vector.Variant)
d, _ := vec.(*vector.Dynamic)
var typ zed.Type
if variant == nil {
if d == nil {
typ = vec.Type()
}
builder := zcode.NewBuilder()
var vals []zed.Value
n := vec.Len()
for slot := uint32(0); slot < n; slot++ {
vec.Serialize(builder, slot)
if variant != nil {
typ = variant.TypeOf(slot)
if d != nil {
typ = d.TypeOf(slot)
}
val := zed.NewValue(typ, bytes.Clone(builder.Bytes().Body()))
vals = append(vals, val)
Expand Down
4 changes: 2 additions & 2 deletions runtime/vam/op/agg.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (c *CountByString) Pull(done bool) (vector.Any, error) {
}

func (c *CountByString) update(val vector.Any) {
if val, ok := val.(*vector.Variant); ok {
if val, ok := val.(*vector.Dynamic); ok {
for _, val := range val.Values {
c.update(val)
}
Expand Down Expand Up @@ -183,7 +183,7 @@ func (c *Sum) Pull(done bool) (vector.Any, error) {
}

func (c *Sum) update(vec vector.Any) {
if vec, ok := vec.(*vector.Variant); ok {
if vec, ok := vec.(*vector.Dynamic); ok {
for _, vec := range vec.Values {
c.update(vec)
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/vam/op/yield.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func filterQuiet(val vector.Any) vector.Any {
return val
}

// XXX should work for input variants
// XXX should work for vector.Dynamic
func interleave(vals []vector.Any) vector.Any {
if len(vals) < 2 {
panic("interleave requires two or more vals")
Expand All @@ -61,5 +61,5 @@ func interleave(vals []vector.Any) vector.Any {
tags[k] = k % nvals

}
return vector.NewVariant(tags, vals)
return vector.NewDynamic(tags, vals)
}
2 changes: 1 addition & 1 deletion runtime/vam/op/ztests/arith.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Test that arithmetic works on union and variant vectors.
# Test that arithmetic works on union and dynamic vectors.

script: |
zq -o t.vng -f vng -
Expand Down
2 changes: 1 addition & 1 deletion runtime/vam/op/ztests/compare.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Test that comparison works on union and variant vectors.
# Test that comparison works on union and dynamic vectors.

script: |
zq -o t.vng -f vng -
Expand Down
6 changes: 3 additions & 3 deletions runtime/vcache/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (l *loader) load(paths Path, s shadow) (vector.Any, error) {

func (l *loader) loadVector(g *errgroup.Group, paths Path, s shadow) {
switch s := s.(type) {
case *variant:
case *dynamic:
//XXX we need an ordered option to load tags only when needed
l.loadUint32(g, &s.mu, &s.tags, s.loc)
for _, m := range s.vals {
Expand Down Expand Up @@ -476,7 +476,7 @@ func (l *loader) loadOffsets(g *errgroup.Group, mu *sync.Mutex, slice *[]uint32,

func (l *loader) fetchNulls(g *errgroup.Group, paths Path, s shadow) {
switch s := s.(type) {
case *variant:
case *dynamic:
for _, m := range s.vals {
l.fetchNulls(g, paths, m)
}
Expand Down Expand Up @@ -533,7 +533,7 @@ func (l *loader) fetchNulls(g *errgroup.Group, paths Path, s shadow) {

func flattenNulls(paths Path, s shadow, parent *vector.Bool) {
switch s := s.(type) {
case *variant:
case *dynamic:
for _, m := range s.vals {
flattenNulls(paths, m, nil)
}
Expand Down
8 changes: 4 additions & 4 deletions runtime/vcache/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (

func project(zctx *zed.Context, paths Path, s shadow) vector.Any {
switch s := s.(type) {
case *variant:
return projectVariant(zctx, paths, s)
case *dynamic:
return projectDynamic(zctx, paths, s)
case *record:
return projectRecord(zctx, paths, s)
case *array:
Expand Down Expand Up @@ -54,12 +54,12 @@ func project(zctx *zed.Context, paths Path, s shadow) vector.Any {
}
}

func projectVariant(zctx *zed.Context, paths Path, s *variant) vector.Any {
func projectDynamic(zctx *zed.Context, paths Path, s *dynamic) vector.Any {
vals := make([]vector.Any, 0, len(s.vals))
for _, m := range s.vals {
vals = append(vals, project(zctx, paths, m))
}
return vector.NewVariant(s.tags, vals)
return vector.NewDynamic(s.tags, vals)
}

func projectRecord(zctx *zed.Context, paths Path, s *record) vector.Any {
Expand Down
12 changes: 6 additions & 6 deletions runtime/vcache/shadow.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ type shadow interface {
length() uint32
}

type variant struct {
type dynamic struct {
mu sync.Mutex
len uint32
tags []uint32 // need not be loaded for unordered variants
tags []uint32 // need not be loaded for unordered dynamics
loc vng.Segment
vals []shadow
}

func (v *variant) length() uint32 {
return v.len
func (d *dynamic) length() uint32 {
return d.len
}

type record struct {
Expand Down Expand Up @@ -133,12 +133,12 @@ func (c count) length() uint32 {
// by the runtime.
func newShadow(m vng.Metadata, n *vng.Nulls, nullsCnt uint32) shadow {
switch m := m.(type) {
case *vng.Variant:
case *vng.Dynamic:
vals := make([]shadow, 0, len(m.Values))
for _, val := range m.Values {
vals = append(vals, newShadow(val, nil, 0))
}
return &variant{
return &dynamic{
vals: vals,
len: m.Len(),
loc: m.Tags,
Expand Down
8 changes: 4 additions & 4 deletions vector/any.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ type Builder func(*zcode.Builder) bool
func Combine(vec Any, index []uint32, add Any) Any {
var vecs []Any
tags := make([]uint32, int(vec.Len())+len(index))
if variant, ok := vec.(*Variant); ok {
vecs = variant.Values
varTags := variant.Tags
if d, ok := vec.(*Dynamic); ok {
vecs = d.Values
varTags := d.Tags
n := uint32(len(vecs))
for i := uint32(0); i < uint32(len(tags)); i++ {
if len(index) > 0 && i == index[0] {
Expand All @@ -44,5 +44,5 @@ func Combine(vec Any, index []uint32, add Any) Any {
tags[k] = 1
}
}
return NewVariant(tags, append(vecs, add))
return NewDynamic(tags, append(vecs, add))
}
28 changes: 14 additions & 14 deletions vector/apply.go
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
package vector

// Apply applies eval to vecs. If any element of vecs is a Variant, Apply rips
// Apply applies eval to vecs. If any element of vecs is a Dynamic, Apply rips
// vecs accordingly, applies eval to the ripped vectors, and stitches the
// results together into a Variant. If ripUnions is true, Apply also rips
// results together into a Dynamic. If ripUnions is true, Apply also rips
// Unions.
func Apply(ripUnions bool, eval func(...Any) Any, vecs ...Any) Any {
if ripUnions {
for k, vec := range vecs {
if union, ok := Under(vec).(*Union); ok {
vecs[k] = union.Variant
vecs[k] = union.Dynamic
}
}
}
variant, ok := findVariant(vecs)
d, ok := findDynamic(vecs)
if !ok {
return eval(vecs...)
}
var results []Any
for _, ripped := range rip(vecs, variant) {
for _, ripped := range rip(vecs, d) {
results = append(results, Apply(ripUnions, eval, ripped...))
}
// Stitch results together by creating a Variant.
return NewVariant(variant.Tags, results)
// Stitch results together in a new Dynamic.
return NewDynamic(d.Tags, results)
}

func findVariant(vecs []Any) (*Variant, bool) {
func findDynamic(vecs []Any) (*Dynamic, bool) {
for _, vec := range vecs {
if variant, ok := vec.(*Variant); ok {
return variant, true
if d, ok := vec.(*Dynamic); ok {
return d, true
}
}
return nil, false
}

func rip(vecs []Any, variant *Variant) [][]Any {
func rip(vecs []Any, d *Dynamic) [][]Any {
var ripped [][]Any
for j, rev := range variant.TagMap.Reverse {
for j, rev := range d.TagMap.Reverse {
var newVecs []Any
for _, vec := range vecs {
if vec == variant {
newVecs = append(newVecs, variant.Values[j])
if vec == d {
newVecs = append(newVecs, d.Values[j])
} else {
newVecs = append(newVecs, NewView(rev, vec))
}
Expand Down
2 changes: 1 addition & 1 deletion vector/bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func BoolValue(vec Any, slot uint32) bool {
return vec.Value().Ptr().AsBool()
case *Dict:
return BoolValue(vec.Any, uint32(vec.Index[slot]))
case *Variant:
case *Dynamic:
tag := vec.Tags[slot]
return BoolValue(vec.Values[tag], vec.TagMap.Forward[slot])
case *View:
Expand Down
47 changes: 47 additions & 0 deletions vector/dynamic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package vector

import (
"github.com/brimdata/zed"
"github.com/brimdata/zed/zcode"
)

// Dynamic is an ordered sequence of values taken from one or more
// hetereogenously-typed vectors.
type Dynamic struct {
Tags []uint32
Values []Any
TagMap *TagMap
}

var _ Any = (*Dynamic)(nil)

func NewDynamic(tags []uint32, values []Any) *Dynamic {
return &Dynamic{Tags: tags, Values: values, TagMap: NewTagMap(tags, values)}
}

func (*Dynamic) Type() zed.Type {
panic("can't call Type() on a vector.Dynamic")
}

func (d *Dynamic) TypeOf(slot uint32) zed.Type {
vals := d.Values[d.Tags[slot]]
if v2, ok := vals.(*Dynamic); ok {
return v2.TypeOf(d.TagMap.Forward[slot])
}
return vals.Type()
}

func (d *Dynamic) Len() uint32 {
if d.Tags != nil {
return uint32(len(d.Tags))
}
var length uint32
for _, val := range d.Values {
length += val.Len()
}
return length
}

func (d *Dynamic) Serialize(b *zcode.Builder, slot uint32) {
d.Values[d.Tags[slot]].Serialize(b, d.TagMap.Forward[slot])
}
2 changes: 1 addition & 1 deletion vector/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func IntValue(vec Any, slot uint32) (int64, bool) {
return vec.Value().Ptr().AsInt(), vec.Nulls.Value(slot)
case *Dict:
return IntValue(vec.Any, uint32(vec.Index[slot]))
case *Variant:
case *Dynamic:
tag := vec.Tags[slot]
return IntValue(vec.Values[tag], vec.TagMap.Forward[slot])
case *View:
Expand Down
2 changes: 1 addition & 1 deletion vector/tagmap.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package vector

// TagMap is used by variants and unions to map slots between parent and child in
// TagMap is used by dynamics and unions to map slots between parent and child in
// both the forward and reverse directions. We need this because vectors are stored
// in a dense format where different types hold only the values needed for that type.
// If we stored vectors in a sparse format, the amount of overhead would increase
Expand Down
Loading

0 comments on commit 09f1fb5

Please sign in to comment.