From c17ececedbce23ac8d86816295b2a20e26ccce66 Mon Sep 17 00:00:00 2001 From: Noah Treuhaft Date: Wed, 14 Oct 2026 14:07:15 -0400 Subject: [PATCH] vector/vbuild: fix DynamicBuilder bug on same-type dynamic A vector.Dynamic containing multiple vectors with the same type can reorder their values because the vectors are written to a single vbuild.Builder. Fix this by calling MergeSameTypesInDynamic. The test added in bsup/ztests/dynamic-same-type.yaml is unfortunately oblique because ztests don't offer a way to create a vector with a prescribed structure. --- bsup/ztests/dynamic-same-type.yaml | 17 +++++++++++++++++ bsup/ztests/pushdown.yaml | 8 ++++---- vector/vbuild/dynamic.go | 5 +++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 bsup/ztests/dynamic-same-type.yaml diff --git a/bsup/ztests/dynamic-same-type.yaml b/bsup/ztests/dynamic-same-type.yaml new file mode 100644 index 0000000000..ee8aceb982 --- /dev/null +++ b/bsup/ztests/dynamic-same-type.yaml @@ -0,0 +1,17 @@ +# This previously output values in the wrong order due to a +# vector/vbuild.DynamicBuilder bug in handling a vector.Dyanmic +# containing same-type vectors. +script: | + super -f bsup -c 'from in.sup | fuse' | super -i bsup -s - + +inputs: + - name: in.sup + data: &in_sup | + "a" + 1 + "b" + 2 + +outputs: + - name: stdout + data: *in_sup diff --git a/bsup/ztests/pushdown.yaml b/bsup/ztests/pushdown.yaml index 6e7df18712..eaa58bbd9e 100644 --- a/bsup/ztests/pushdown.yaml +++ b/bsup/ztests/pushdown.yaml @@ -19,10 +19,10 @@ outputs: - name: stderr data: | === x > 51 === - {bytes_scanned:10768,values_scanned:49,frames_scanned:10,frames_skipped_search_filter:0,frames_skipped_meta_filter:5,frames_skipped_data_filter:0,values_skipped_data_filter:41,meta_bytes_loaded:8066,data_bytes_loaded:1072,type_bytes_loaded:0} + {bytes_scanned:10777,values_scanned:49,frames_scanned:10,frames_skipped_search_filter:0,frames_skipped_meta_filter:5,frames_skipped_data_filter:0,values_skipped_data_filter:41,meta_bytes_loaded:8066,data_bytes_loaded:1076,type_bytes_loaded:0} === tag='foo18' === - {bytes_scanned:10768,values_scanned:1,frames_scanned:10,frames_skipped_search_filter:9,frames_skipped_meta_filter:0,frames_skipped_data_filter:0,values_skipped_data_filter:9,meta_bytes_loaded:8066,data_bytes_loaded:856,type_bytes_loaded:0} + {bytes_scanned:10777,values_scanned:1,frames_scanned:10,frames_skipped_search_filter:9,frames_skipped_meta_filter:0,frames_skipped_data_filter:0,values_skipped_data_filter:9,meta_bytes_loaded:8066,data_bytes_loaded:865,type_bytes_loaded:0} === count() === - {bytes_scanned:10768,values_scanned:100,frames_scanned:10,frames_skipped_search_filter:0,frames_skipped_meta_filter:0,frames_skipped_data_filter:0,values_skipped_data_filter:0,meta_bytes_loaded:8066,data_bytes_loaded:0,type_bytes_loaded:0} + {bytes_scanned:10777,values_scanned:100,frames_scanned:10,frames_skipped_search_filter:0,frames_skipped_meta_filter:0,frames_skipped_data_filter:0,values_skipped_data_filter:0,meta_bytes_loaded:8066,data_bytes_loaded:0,type_bytes_loaded:0} === values tag | this='foo18' | count() === - {bytes_scanned:10768,values_scanned:100,frames_scanned:10,frames_skipped_search_filter:0,frames_skipped_meta_filter:0,frames_skipped_data_filter:0,values_skipped_data_filter:0,meta_bytes_loaded:8066,data_bytes_loaded:712,type_bytes_loaded:0} + {bytes_scanned:10777,values_scanned:100,frames_scanned:10,frames_skipped_search_filter:0,frames_skipped_meta_filter:0,frames_skipped_data_filter:0,values_skipped_data_filter:0,meta_bytes_loaded:8066,data_bytes_loaded:721,type_bytes_loaded:0} diff --git a/vector/vbuild/dynamic.go b/vector/vbuild/dynamic.go index 9fe6ae80f0..2eb4e5c20b 100644 --- a/vector/vbuild/dynamic.go +++ b/vector/vbuild/dynamic.go @@ -16,6 +16,11 @@ func NewDynamicBuilder() *DynamicBuilder { } func (d *DynamicBuilder) Write(vec vector.Any) { + if dynamic, ok := vec.(*vector.Dynamic); ok { + // There's one Builder per type so merge same-type vectors to + // preserve order. + vec = MergeSameTypesInDynamic(dynamic) + } if dynamic, ok := vec.(*vector.Dynamic); ok { tagMap := make([]uint32, len(dynamic.Values)) for i, vec := range dynamic.Values {