This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch sidx/query
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git

commit 30a037098e4adb20cc3f5384e907eeb43d1671a8
Author: Gao Hongtao <[email protected]>
AuthorDate: Thu Aug 28 07:40:04 2025 +0800

    Refactor tag structure and update field names: Change tag field names to 
use exported formats (e.g., name to Name) for consistency across the codebase. 
Introduce a new Tag struct with methods for creation, resetting, and copying. 
Update related tests to reflect these changes, ensuring proper functionality 
and clarity in tag handling.
---
 banyand/internal/sidx/element.go           |   8 +-
 banyand/internal/sidx/interfaces.go        |  82 +++-
 banyand/internal/sidx/query_result.go      |  12 +-
 banyand/internal/sidx/query_result_test.go | 114 +++---
 banyand/internal/sidx/sidx_test.go         |  10 +-
 banyand/internal/sidx/snapshot_test.go     |  20 +-
 banyand/internal/sidx/tag_test.go          | 635 ++++-------------------------
 7 files changed, 226 insertions(+), 655 deletions(-)

diff --git a/banyand/internal/sidx/element.go b/banyand/internal/sidx/element.go
index 7985b575..9ca5e253 100644
--- a/banyand/internal/sidx/element.go
+++ b/banyand/internal/sidx/element.go
@@ -167,10 +167,10 @@ func (e *elements) mustAppend(seriesID common.SeriesID, 
userKey int64, data []by
        elementTags := make([]*tag, 0, len(tags))
        for _, t := range tags {
                newTag := generateTag()
-               newTag.name = t.name
-               newTag.value = append([]byte(nil), t.value...)
-               newTag.valueType = t.valueType
-               newTag.indexed = t.indexed
+               newTag.name = t.Name
+               newTag.value = append([]byte(nil), t.Value...)
+               newTag.valueType = t.ValueType
+               newTag.indexed = t.Indexed
                elementTags = append(elementTags, newTag)
        }
        e.tags = append(e.tags, elementTags)
diff --git a/banyand/internal/sidx/interfaces.go 
b/banyand/internal/sidx/interfaces.go
index e9970141..91b2bb61 100644
--- a/banyand/internal/sidx/interfaces.go
+++ b/banyand/internal/sidx/interfaces.go
@@ -26,6 +26,7 @@ import (
 
        "github.com/apache/skywalking-banyandb/api/common"
        "github.com/apache/skywalking-banyandb/pkg/index"
+       pbv1 "github.com/apache/skywalking-banyandb/pkg/pb/v1"
        "github.com/apache/skywalking-banyandb/pkg/query/model"
 )
 
@@ -190,7 +191,7 @@ func (qr *QueryResponse) Validate() error {
                }
                for i, tagGroup := range qr.Tags {
                        for j, tag := range tagGroup {
-                               if tag.name == "" {
+                               if tag.Name == "" {
                                        return fmt.Errorf("tags[%d][%d] name 
cannot be empty", i, j)
                                }
                        }
@@ -231,10 +232,10 @@ func (qr *QueryResponse) CopyFrom(other *QueryResponse) {
                        qr.Tags[i] = qr.Tags[i][:len(tagGroup)]
                }
                for j, tag := range tagGroup {
-                       qr.Tags[i][j].name = tag.name
-                       qr.Tags[i][j].value = append(qr.Tags[i][j].value[:0], 
tag.value...)
-                       qr.Tags[i][j].valueType = tag.valueType
-                       qr.Tags[i][j].indexed = tag.indexed
+                       qr.Tags[i][j].Name = tag.Name
+                       qr.Tags[i][j].Value = append(qr.Tags[i][j].Value[:0], 
tag.Value...)
+                       qr.Tags[i][j].ValueType = tag.ValueType
+                       qr.Tags[i][j].Indexed = tag.Indexed
                }
        }
 
@@ -308,8 +309,71 @@ func (rm *ResponseMetadata) Validate() error {
 }
 
 // Tag represents an individual tag for WriteRequest.
-// This uses the existing tag structure from the sidx package.
-type Tag = tag
+// This is an exported type that can be used outside the package.
+type Tag struct {
+       Name      string
+       Value     []byte
+       ValueType pbv1.ValueType
+       Indexed   bool
+}
+
+// NewTag creates a new Tag instance with the given values.
+func NewTag(name string, value []byte, valueType pbv1.ValueType, indexed bool) 
Tag {
+       return Tag{
+               Name:      name,
+               Value:     value,
+               ValueType: valueType,
+               Indexed:   indexed,
+       }
+}
+
+// Reset resets the Tag to its zero state for reuse.
+func (t *Tag) Reset() {
+       t.Name = ""
+       t.Value = nil
+       t.ValueType = pbv1.ValueTypeUnknown
+       t.Indexed = false
+}
+
+// Size returns the size of the tag in bytes.
+func (t *Tag) Size() int {
+       return len(t.Name) + len(t.Value) + 1 // +1 for valueType
+}
+
+// Copy creates a deep copy of the Tag.
+func (t *Tag) Copy() Tag {
+       var valueCopy []byte
+       if t.Value != nil {
+               valueCopy = make([]byte, len(t.Value))
+               copy(valueCopy, t.Value)
+       }
+       return Tag{
+               Name:      t.Name,
+               Value:     valueCopy,
+               ValueType: t.ValueType,
+               Indexed:   t.Indexed,
+       }
+}
+
+// toInternalTag converts the exported Tag to an internal tag for use with the 
pooling system.
+func (t *Tag) toInternalTag() *tag {
+       return &tag{
+               name:      t.Name,
+               value:     t.Value,
+               valueType: t.ValueType,
+               indexed:   t.Indexed,
+       }
+}
+
+// fromInternalTag creates a Tag from an internal tag.
+func fromInternalTag(t *tag) Tag {
+       return Tag{
+               Name:      t.name,
+               Value:     t.value,
+               ValueType: t.valueType,
+               Indexed:   t.indexed,
+       }
+}
 
 // Validate validates a WriteRequest for correctness.
 func (wr WriteRequest) Validate() error {
@@ -324,10 +388,10 @@ func (wr WriteRequest) Validate() error {
        }
        // Validate tags if present
        for i, tag := range wr.Tags {
-               if tag.name == "" {
+               if tag.Name == "" {
                        return fmt.Errorf("tag[%d] name cannot be empty", i)
                }
-               if len(tag.value) == 0 {
+               if len(tag.Value) == 0 {
                        return fmt.Errorf("tag[%d] value cannot be empty", i)
                }
        }
diff --git a/banyand/internal/sidx/query_result.go 
b/banyand/internal/sidx/query_result.go
index 4f8b3b6e..87154640 100644
--- a/banyand/internal/sidx/query_result.go
+++ b/banyand/internal/sidx/query_result.go
@@ -376,9 +376,9 @@ func (qr *queryResult) extractElementTags(block *block, 
elemIndex int) []Tag {
                        for _, tagName := range proj.Names {
                                if tagData, exists := block.tags[tagName]; 
exists && elemIndex < len(tagData.values) {
                                        elementTags = append(elementTags, Tag{
-                                               name:      tagName,
-                                               value:     
tagData.values[elemIndex],
-                                               valueType: tagData.valueType,
+                                               Name:      tagName,
+                                               Value:     
tagData.values[elemIndex],
+                                               ValueType: tagData.valueType,
                                        })
                                }
                        }
@@ -389,9 +389,9 @@ func (qr *queryResult) extractElementTags(block *block, 
elemIndex int) []Tag {
                for tagName, tagData := range block.tags {
                        if elemIndex < len(tagData.values) {
                                elementTags = append(elementTags, Tag{
-                                       name:      tagName,
-                                       value:     tagData.values[elemIndex],
-                                       valueType: tagData.valueType,
+                                       Name:      tagName,
+                                       Value:     tagData.values[elemIndex],
+                                       ValueType: tagData.valueType,
                                })
                        }
                }
diff --git a/banyand/internal/sidx/query_result_test.go 
b/banyand/internal/sidx/query_result_test.go
index 357d733f..7c8e1ab0 100644
--- a/banyand/internal/sidx/query_result_test.go
+++ b/banyand/internal/sidx/query_result_test.go
@@ -154,9 +154,9 @@ func TestQueryResponseHeap_MergeWithHeapAscending(t 
*testing.T) {
                Keys: []int64{1, 5, 9},
                Data: [][]byte{[]byte("a1"), []byte("a5"), []byte("a9")},
                Tags: [][]Tag{
-                       {{name: "tag1", value: []byte("val1"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag1", value: []byte("val5"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag1", value: []byte("val9"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val1"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val5"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val9"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{1, 1, 1},
        }
@@ -164,9 +164,9 @@ func TestQueryResponseHeap_MergeWithHeapAscending(t 
*testing.T) {
                Keys: []int64{2, 6, 10},
                Data: [][]byte{[]byte("b2"), []byte("b6"), []byte("b10")},
                Tags: [][]Tag{
-                       {{name: "tag2", value: []byte("val2"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag2", value: []byte("val6"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag2", value: []byte("val10"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val2"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val6"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val10"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{2, 2, 2},
        }
@@ -174,8 +174,8 @@ func TestQueryResponseHeap_MergeWithHeapAscending(t 
*testing.T) {
                Keys: []int64{3, 7},
                Data: [][]byte{[]byte("c3"), []byte("c7")},
                Tags: [][]Tag{
-                       {{name: "tag3", value: []byte("val3"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag3", value: []byte("val7"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag3", Value: []byte("val3"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag3", Value: []byte("val7"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{3, 3},
        }
@@ -230,9 +230,9 @@ func TestQueryResponseHeap_MergeWithHeapDescending(t 
*testing.T) {
                Keys: []int64{1, 5, 9}, // Will be accessed backwards: 9, 5, 1
                Data: [][]byte{[]byte("a1"), []byte("a5"), []byte("a9")},
                Tags: [][]Tag{
-                       {{name: "tag1", value: []byte("val1"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag1", value: []byte("val5"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag1", value: []byte("val9"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val1"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val5"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val9"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{1, 1, 1},
        }
@@ -240,9 +240,9 @@ func TestQueryResponseHeap_MergeWithHeapDescending(t 
*testing.T) {
                Keys: []int64{2, 6, 10}, // Will be accessed backwards: 10, 6, 2
                Data: [][]byte{[]byte("b2"), []byte("b6"), []byte("b10")},
                Tags: [][]Tag{
-                       {{name: "tag2", value: []byte("val2"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag2", value: []byte("val6"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag2", value: []byte("val10"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val2"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val6"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val10"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{2, 2, 2},
        }
@@ -292,9 +292,9 @@ func TestQueryResponseHeap_MergeWithLimit(t *testing.T) {
                Keys: []int64{1, 3, 5},
                Data: [][]byte{[]byte("a1"), []byte("a3"), []byte("a5")},
                Tags: [][]Tag{
-                       {{name: "tag1", value: []byte("val1"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag1", value: []byte("val3"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag1", value: []byte("val5"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val1"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val3"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag1", Value: []byte("val5"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{1, 1, 1},
        }
@@ -302,9 +302,9 @@ func TestQueryResponseHeap_MergeWithLimit(t *testing.T) {
                Keys: []int64{2, 4, 6},
                Data: [][]byte{[]byte("b2"), []byte("b4"), []byte("b6")},
                Tags: [][]Tag{
-                       {{name: "tag2", value: []byte("val2"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag2", value: []byte("val4"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "tag2", value: []byte("val6"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val2"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val4"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "tag2", Value: []byte("val6"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{2, 2, 2},
        }
@@ -345,7 +345,7 @@ func TestQueryResponseHeap_EdgeCases(t *testing.T) {
                response := &QueryResponse{
                        Keys: []int64{42},
                        Data: [][]byte{[]byte("single")},
-                       Tags: [][]Tag{{{name: "tag", value: []byte("value"), 
valueType: pbv1.ValueTypeStr}}},
+                       Tags: [][]Tag{{{Name: "tag", Value: []byte("value"), 
ValueType: pbv1.ValueTypeStr}}},
                        SIDs: []common.SeriesID{1},
                }
 
@@ -371,9 +371,9 @@ func TestQueryResponseHeap_EdgeCases(t *testing.T) {
                        Keys: []int64{1, 2, 3},
                        Data: [][]byte{[]byte("a"), []byte("b"), []byte("c")},
                        Tags: [][]Tag{
-                               {{name: "tag", value: []byte("val1"), 
valueType: pbv1.ValueTypeStr}},
-                               {{name: "tag", value: []byte("val2"), 
valueType: pbv1.ValueTypeStr}},
-                               {{name: "tag", value: []byte("val3"), 
valueType: pbv1.ValueTypeStr}},
+                               {{Name: "tag", Value: []byte("val1"), 
ValueType: pbv1.ValueTypeStr}},
+                               {{Name: "tag", Value: []byte("val2"), 
ValueType: pbv1.ValueTypeStr}},
+                               {{Name: "tag", Value: []byte("val3"), 
ValueType: pbv1.ValueTypeStr}},
                        },
                        SIDs: []common.SeriesID{1, 1, 1},
                }
@@ -398,7 +398,7 @@ func TestQueryResponseHeap_EdgeCases(t *testing.T) {
                normalResponse := &QueryResponse{
                        Keys: []int64{5},
                        Data: [][]byte{[]byte("normal")},
-                       Tags: [][]Tag{{{name: "tag", value: []byte("value"), 
valueType: pbv1.ValueTypeStr}}},
+                       Tags: [][]Tag{{{Name: "tag", Value: []byte("value"), 
ValueType: pbv1.ValueTypeStr}}},
                        SIDs: []common.SeriesID{1},
                }
 
@@ -425,9 +425,9 @@ func TestMergeQueryResponseShardsAsc(t *testing.T) {
                Keys: []int64{1, 5, 9},
                Data: [][]byte{[]byte("s1_1"), []byte("s1_5"), []byte("s1_9")},
                Tags: [][]Tag{
-                       {{name: "shard1", value: []byte("val1"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard1", value: []byte("val5"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard1", value: []byte("val9"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard1", Value: []byte("val1"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard1", Value: []byte("val5"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard1", Value: []byte("val9"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{1, 1, 1},
        }
@@ -435,9 +435,9 @@ func TestMergeQueryResponseShardsAsc(t *testing.T) {
                Keys: []int64{2, 6, 10},
                Data: [][]byte{[]byte("s2_2"), []byte("s2_6"), []byte("s2_10")},
                Tags: [][]Tag{
-                       {{name: "shard2", value: []byte("val2"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard2", value: []byte("val6"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard2", value: []byte("val10"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard2", Value: []byte("val2"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard2", Value: []byte("val6"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard2", Value: []byte("val10"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{2, 2, 2},
        }
@@ -445,8 +445,8 @@ func TestMergeQueryResponseShardsAsc(t *testing.T) {
                Keys: []int64{3, 7},
                Data: [][]byte{[]byte("s3_3"), []byte("s3_7")},
                Tags: [][]Tag{
-                       {{name: "shard3", value: []byte("val3"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard3", value: []byte("val7"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard3", Value: []byte("val3"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard3", Value: []byte("val7"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{3, 3},
        }
@@ -472,9 +472,9 @@ func TestMergeQueryResponseShardsDesc(t *testing.T) {
                Keys: []int64{9, 5, 1},
                Data: [][]byte{[]byte("s1_9"), []byte("s1_5"), []byte("s1_1")},
                Tags: [][]Tag{
-                       {{name: "shard1", value: []byte("val9"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard1", value: []byte("val5"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard1", value: []byte("val1"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard1", Value: []byte("val9"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard1", Value: []byte("val5"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard1", Value: []byte("val1"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{1, 1, 1},
        }
@@ -482,9 +482,9 @@ func TestMergeQueryResponseShardsDesc(t *testing.T) {
                Keys: []int64{10, 6, 2},
                Data: [][]byte{[]byte("s2_10"), []byte("s2_6"), []byte("s2_2")},
                Tags: [][]Tag{
-                       {{name: "shard2", value: []byte("val10"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard2", value: []byte("val6"), valueType: 
pbv1.ValueTypeStr}},
-                       {{name: "shard2", value: []byte("val2"), valueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard2", Value: []byte("val10"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard2", Value: []byte("val6"), ValueType: 
pbv1.ValueTypeStr}},
+                       {{Name: "shard2", Value: []byte("val2"), ValueType: 
pbv1.ValueTypeStr}},
                },
                SIDs: []common.SeriesID{2, 2, 2},
        }
@@ -539,8 +539,8 @@ func TestMergeQueryResponseShards_EmptyShards(t *testing.T) 
{
                                Keys: []int64{5, 10},
                                Data: [][]byte{[]byte("a"), []byte("b")},
                                Tags: [][]Tag{
-                                       {{name: "mixed", value: []byte("val5"), 
valueType: pbv1.ValueTypeStr}},
-                                       {{name: "mixed", value: 
[]byte("val10"), valueType: pbv1.ValueTypeStr}},
+                                       {{Name: "mixed", Value: []byte("val5"), 
ValueType: pbv1.ValueTypeStr}},
+                                       {{Name: "mixed", Value: 
[]byte("val10"), ValueType: pbv1.ValueTypeStr}},
                                },
                                SIDs: []common.SeriesID{1, 1},
                        },
@@ -619,7 +619,7 @@ func createBenchmarkResponse(size int, offset, step int64) 
*QueryResponse {
                key := offset + int64(i)*step
                response.Keys[i] = key
                response.Data[i] = []byte("benchmark_data")
-               response.Tags[i] = []Tag{{name: "benchmark", value: 
[]byte("value"), valueType: pbv1.ValueTypeStr}}
+               response.Tags[i] = []Tag{{Name: "benchmark", Value: 
[]byte("value"), ValueType: pbv1.ValueTypeStr}}
                response.SIDs[i] = common.SeriesID(offset)
        }
 
@@ -638,7 +638,7 @@ func createBenchmarkResponseDesc(size int, offset, step 
int64) *QueryResponse {
                key := offset + int64(size-1-i)*step
                response.Keys[i] = key
                response.Data[i] = []byte("benchmark_data")
-               response.Tags[i] = []Tag{{name: "benchmark", value: 
[]byte("value"), valueType: pbv1.ValueTypeStr}}
+               response.Tags[i] = []Tag{{Name: "benchmark", Value: 
[]byte("value"), ValueType: pbv1.ValueTypeStr}}
                response.SIDs[i] = common.SeriesID(offset)
        }
 
@@ -802,14 +802,14 @@ func TestQueryResult_Pull_SingleMemPart(t *testing.T) {
 
                for j, tag := range tags {
                        expectedTag := expected.tags[j]
-                       if tag.name != expectedTag.name {
-                               t.Errorf("At position %d, tag %d: expected name 
%s, got %s", i, j, expectedTag.name, tag.name)
+                       if tag.Name != expectedTag.name {
+                               t.Errorf("At position %d, tag %d: expected name 
%s, got %s", i, j, expectedTag.name, tag.Name)
                        }
-                       if !bytes.Equal(tag.value, expectedTag.value) {
-                               t.Errorf("At position %d, tag %d: expected 
value %s, got %s", i, j, string(expectedTag.value), string(tag.value))
+                       if !bytes.Equal(tag.Value, expectedTag.value) {
+                               t.Errorf("At position %d, tag %d: expected 
value %s, got %s", i, j, string(expectedTag.value), string(tag.Value))
                        }
-                       if tag.valueType != expectedTag.valueType {
-                               t.Errorf("At position %d, tag %d: expected 
valueType %v, got %v", i, j, expectedTag.valueType, tag.valueType)
+                       if tag.ValueType != expectedTag.valueType {
+                               t.Errorf("At position %d, tag %d: expected 
valueType %v, got %v", i, j, expectedTag.valueType, tag.ValueType)
                        }
                }
        }
@@ -968,14 +968,14 @@ func TestQueryResult_Pull_MultipleMemParts(t *testing.T) {
 
                for j, tag := range tags {
                        expectedTag := expected.tags[j]
-                       if tag.name != expectedTag.name {
-                               t.Errorf("At position %d, tag %d: expected name 
%s, got %s", i, j, expectedTag.name, tag.name)
+                       if tag.Name != expectedTag.name {
+                               t.Errorf("At position %d, tag %d: expected name 
%s, got %s", i, j, expectedTag.name, tag.Name)
                        }
-                       if !bytes.Equal(tag.value, expectedTag.value) {
-                               t.Errorf("At position %d, tag %d: expected 
value %s, got %s", i, j, string(expectedTag.value), string(tag.value))
+                       if !bytes.Equal(tag.Value, expectedTag.value) {
+                               t.Errorf("At position %d, tag %d: expected 
value %s, got %s", i, j, string(expectedTag.value), string(tag.Value))
                        }
-                       if tag.valueType != expectedTag.valueType {
-                               t.Errorf("At position %d, tag %d: expected 
valueType %v, got %v", i, j, expectedTag.valueType, tag.valueType)
+                       if tag.ValueType != expectedTag.valueType {
+                               t.Errorf("At position %d, tag %d: expected 
valueType %v, got %v", i, j, expectedTag.valueType, tag.ValueType)
                        }
                }
        }
@@ -1088,8 +1088,8 @@ func TestQueryResult_Pull_WithTagProjection(t *testing.T) 
{
        // Note: The actual tag filtering logic needs to be verified based on 
implementation
        for i, tagGroup := range response.Tags {
                for _, tag := range tagGroup {
-                       if tag.name != "service" && tag.name != "environment" {
-                               t.Errorf("Unexpected tag '%s' found at position 
%d, should only have projected tags", tag.name, i)
+                       if tag.Name != "service" && tag.Name != "environment" {
+                               t.Errorf("Unexpected tag '%s' found at position 
%d, should only have projected tags", tag.Name, i)
                        }
                }
        }
diff --git a/banyand/internal/sidx/sidx_test.go 
b/banyand/internal/sidx/sidx_test.go
index ef9324e4..7741a1dd 100644
--- a/banyand/internal/sidx/sidx_test.go
+++ b/banyand/internal/sidx/sidx_test.go
@@ -59,11 +59,11 @@ func createTestSIDX(t *testing.T) SIDX {
 }
 
 func createTestTag(name, value string) Tag {
-       return tag{
-               name:      name,
-               value:     []byte(value),
-               valueType: pbv1.ValueTypeStr,
-               indexed:   true,
+       return Tag{
+               Name:      name,
+               Value:     []byte(value),
+               ValueType: pbv1.ValueTypeStr,
+               Indexed:   true,
        }
 }
 
diff --git a/banyand/internal/sidx/snapshot_test.go 
b/banyand/internal/sidx/snapshot_test.go
index efea64d5..bcdfd1fe 100644
--- a/banyand/internal/sidx/snapshot_test.go
+++ b/banyand/internal/sidx/snapshot_test.go
@@ -425,7 +425,7 @@ func TestSnapshotReplacement_Basic(t *testing.T) {
                        SeriesID: common.SeriesID(i + 1),
                        Key:      int64(i),
                        Data:     []byte(fmt.Sprintf("test-data-%d", i)),
-                       Tags:     []Tag{{name: "test", value: 
[]byte("snapshot-replacement")}},
+                       Tags:     []Tag{{Name: "test", Value: 
[]byte("snapshot-replacement")}},
                }
 
                if err := sidx.Write(ctx, []WriteRequest{req}); err != nil {
@@ -512,8 +512,8 @@ func 
TestSnapshotReplacement_ConcurrentReadsConsistentData(t *testing.T) {
                                Key:      int64(1000 + i),
                                Data:     
[]byte(fmt.Sprintf("replacement-data-%d", i)),
                                Tags: []Tag{
-                                       {name: "test", value: 
[]byte("replacement")},
-                                       {name: "sequence", value: 
[]byte(fmt.Sprintf("%d", i))},
+                                       {Name: "test", Value: 
[]byte("replacement")},
+                                       {Name: "sequence", Value: 
[]byte(fmt.Sprintf("%d", i))},
                                },
                        },
                }
@@ -601,8 +601,8 @@ func TestSnapshotReplacement_NoDataRacesDuringReplacement(t 
*testing.T) {
                                                        Key:      int64(id*1000 
+ j),
                                                        Data:     
[]byte(fmt.Sprintf("race-test-%d-%d", id, j)),
                                                        Tags: []Tag{
-                                                               {name: 
"goroutine", value: []byte(fmt.Sprintf("%d", id))},
-                                                               {name: 
"operation", value: []byte(fmt.Sprintf("%d", j))},
+                                                               {Name: 
"goroutine", Value: []byte(fmt.Sprintf("%d", id))},
+                                                               {Name: 
"operation", Value: []byte(fmt.Sprintf("%d", j))},
                                                        },
                                                },
                                        }
@@ -658,9 +658,9 @@ func TestSnapshotReplacement_MemoryLeaksPrevention(t 
*testing.T) {
                                        Key:      int64(i*100 + j),
                                        Data:     
[]byte(fmt.Sprintf("leak-test-batch-%d-write-%d", i, j)),
                                        Tags: []Tag{
-                                               {name: "batch", value: 
[]byte(fmt.Sprintf("%d", i))},
-                                               {name: "write", value: 
[]byte(fmt.Sprintf("%d", j))},
-                                               {name: "test", value: 
[]byte("memory-leak-prevention")},
+                                               {Name: "batch", Value: 
[]byte(fmt.Sprintf("%d", i))},
+                                               {Name: "write", Value: 
[]byte(fmt.Sprintf("%d", j))},
+                                               {Name: "test", Value: 
[]byte("memory-leak-prevention")},
                                        },
                                },
                        }
@@ -720,8 +720,8 @@ func TestSnapshotReplacement_MemoryLeaksPrevention(t 
*testing.T) {
                                                Key:      int64(writerID*1000 + 
j + 5000),
                                                Data:     
[]byte(fmt.Sprintf("concurrent-leak-test-%d-%d", writerID, j)),
                                                Tags: []Tag{
-                                                       {name: "writer", value: 
[]byte(fmt.Sprintf("%d", writerID))},
-                                                       {name: "concurrent", 
value: []byte("true")},
+                                                       {Name: "writer", Value: 
[]byte(fmt.Sprintf("%d", writerID))},
+                                                       {Name: "concurrent", 
Value: []byte("true")},
                                                },
                                        },
                                }
diff --git a/banyand/internal/sidx/tag_test.go 
b/banyand/internal/sidx/tag_test.go
index 4104459e..9bc500bf 100644
--- a/banyand/internal/sidx/tag_test.go
+++ b/banyand/internal/sidx/tag_test.go
@@ -18,597 +18,104 @@
 package sidx
 
 import (
-       "bytes"
-       "encoding/binary"
        "testing"
 
        "github.com/stretchr/testify/assert"
-       "github.com/stretchr/testify/require"
 
-       "github.com/apache/skywalking-banyandb/pkg/filter"
        pbv1 "github.com/apache/skywalking-banyandb/pkg/pb/v1"
 )
 
-const testTagName = "test_tag"
-
-func TestTagValueMarshaling(t *testing.T) {
-       tests := []struct {
-               name   string
-               values [][]byte
-               want   bool // whether marshaling should succeed
-       }{
-               {
-                       name:   "empty values",
-                       values: [][]byte{},
-                       want:   true,
-               },
-               {
-                       name:   "single value",
-                       values: [][]byte{[]byte("test")},
-                       want:   true,
-               },
-               {
-                       name: "multiple values",
-                       values: [][]byte{
-                               []byte("value1"),
-                               []byte("value2"),
-                               []byte("value3"),
-                       },
-                       want: true,
-               },
-               {
-                       name: "values with different lengths",
-                       values: [][]byte{
-                               []byte("a"),
-                               []byte("longer_value"),
-                               []byte(""),
-                               []byte("medium"),
-                       },
-                       want: true,
-               },
+func TestTagExportedFields(t *testing.T) {
+       // Test that Tag can be created and used outside the package
+       tag := Tag{
+               Name:      "test-tag",
+               Value:     []byte("test-value"),
+               ValueType: pbv1.ValueTypeStr,
+               Indexed:   true,
        }
 
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       // Marshal values using shared encoding (default to 
string type for basic marshaling test)
-                       data, err := encodeTagValues(tt.values, 
pbv1.ValueTypeStr)
-                       if tt.want {
-                               require.NoError(t, err)
-                       } else {
-                               require.Error(t, err)
-                               return
-                       }
-
-                       // Unmarshal and verify
-                       unmarshaled, err := decodeTagValues(data, 
pbv1.ValueTypeStr, len(tt.values))
-                       require.NoError(t, err)
-                       assert.Equal(t, len(tt.values), len(unmarshaled))
-
-                       for i, expected := range tt.values {
-                               switch {
-                               case expected == nil:
-                                       assert.Nil(t, unmarshaled[i])
-                               case len(expected) == 0:
-                                       // Handle empty byte slices - encoding 
may return nil for empty values
-                                       assert.True(t, len(unmarshaled[i]) == 
0, "Expected empty value at index %d", i)
-                               default:
-                                       assert.Equal(t, expected, 
unmarshaled[i])
-                               }
-                       }
-               })
-       }
+       // Test that exported fields are accessible
+       assert.Equal(t, "test-tag", tag.Name)
+       assert.Equal(t, []byte("test-value"), tag.Value)
+       assert.Equal(t, pbv1.ValueTypeStr, tag.ValueType)
+       assert.Equal(t, true, tag.Indexed)
 }
 
-func TestTagValueEncoding(t *testing.T) {
-       tests := []struct {
-               name      string
-               values    [][]byte
-               valueType pbv1.ValueType
-               wantErr   bool
-       }{
-               {
-                       name:      "int64 values",
-                       values:    [][]byte{{0x39, 0x30, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00}}, // int64(12345) encoded
-                       valueType: pbv1.ValueTypeInt64,
-                       wantErr:   false,
-               },
-               {
-                       name:      "string values",
-                       values:    [][]byte{[]byte("test string"), 
[]byte("another string")},
-                       valueType: pbv1.ValueTypeStr,
-                       wantErr:   false,
-               },
-               {
-                       name:      "binary data",
-                       values:    [][]byte{{0x01, 0x02, 0x03, 0x04}, {0xFF, 
0xFE}},
-                       valueType: pbv1.ValueTypeBinaryData,
-                       wantErr:   false,
-               },
-       }
-
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       encoded, err := encodeTagValues(tt.values, tt.valueType)
-                       if tt.wantErr {
-                               assert.Error(t, err)
-                               return
-                       }
+func TestNewTag(t *testing.T) {
+       // Test the NewTag constructor function
+       tag := NewTag("service", []byte("order-service"), pbv1.ValueTypeStr, 
true)
 
-                       require.NoError(t, err)
-                       assert.NotNil(t, encoded)
-
-                       // Decode and verify round-trip
-                       decoded, err := decodeTagValues(encoded, tt.valueType, 
len(tt.values))
-                       require.NoError(t, err)
-                       assert.Equal(t, len(tt.values), len(decoded))
-                       for i, expected := range tt.values {
-                               assert.Equal(t, expected, decoded[i])
-                       }
-               })
-       }
+       assert.Equal(t, "service", tag.Name)
+       assert.Equal(t, []byte("order-service"), tag.Value)
+       assert.Equal(t, pbv1.ValueTypeStr, tag.ValueType)
+       assert.Equal(t, true, tag.Indexed)
 }
 
-func TestTagFilterGeneration(t *testing.T) {
-       tests := []struct {
-               name             string
-               values           [][]byte
-               expectedElements int
-               wantNil          bool
-       }{
-               {
-                       name:             "empty values",
-                       values:           [][]byte{},
-                       expectedElements: 10,
-                       wantNil:          true,
-               },
-               {
-                       name: "single value",
-                       values: [][]byte{
-                               []byte("value1"),
-                       },
-                       expectedElements: 10,
-                       wantNil:          false,
-               },
-               {
-                       name: "multiple values",
-                       values: [][]byte{
-                               []byte("value1"),
-                               []byte("value2"),
-                               []byte("value3"),
-                       },
-                       expectedElements: 10,
-                       wantNil:          false,
-               },
+func TestTagReset(t *testing.T) {
+       tag := Tag{
+               Name:      "test-tag",
+               Value:     []byte("test-value"),
+               ValueType: pbv1.ValueTypeStr,
+               Indexed:   true,
        }
 
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       filter := generateTagFilter(tt.values, 
tt.expectedElements)
-                       if tt.wantNil {
-                               assert.Nil(t, filter)
-                               return
-                       }
-
-                       require.NotNil(t, filter)
-
-                       // Test that all added values might be contained
-                       for _, value := range tt.values {
-                               assert.True(t, filter.MightContain(value))
-                       }
-
-                       // Test that a non-added value might not be contained
-                       // (this could return true due to false positives, but 
we test anyway)
-                       nonExistent := []byte("non_existent_value_12345")
-                       // We can't assert false here due to possible false 
positives
-                       filter.MightContain(nonExistent)
-               })
-       }
-}
-
-func TestTagDataOperations(t *testing.T) {
-       t.Run("add and check values", func(t *testing.T) {
-               td := generateTagData()
-               defer releaseTagData(td)
-
-               td.name = testTagName
-               td.valueType = pbv1.ValueTypeStr
-               td.indexed = true
-               td.filter = generateTagFilter([][]byte{}, 10) // Start with 
empty filter
-
-               // Add values
-               values := [][]byte{
-                       []byte("value1"),
-                       []byte("value2"),
-                       []byte("value3"),
-               }
-
-               for _, value := range values {
-                       td.addValue(value)
-               }
-
-               // Check that all values are present
-               for _, value := range values {
-                       assert.True(t, td.hasValue(value))
-               }
-
-               // Check that a non-existent value might not be present
-               assert.False(t, td.hasValue([]byte("non_existent")))
-       })
-
-       t.Run("update min max for int64", func(t *testing.T) {
-               td := generateTagData()
-               defer releaseTagData(td)
-
-               td.name = "int_tag"
-               td.valueType = pbv1.ValueTypeInt64
-
-               // Add int64 values (encoded as bytes)
-               values := []int64{100, -50, 200, 0, 150}
-               for _, v := range values {
-                       encoded := make([]byte, 8)
-                       binary.LittleEndian.PutUint64(encoded, uint64(v))
-                       td.values = append(td.values, encoded)
-               }
-
-               td.updateMinMax()
-
-               // Verify min and max
-               assert.NotNil(t, td.min)
-               assert.NotNil(t, td.max)
-
-               // Decode and verify values
-               minVal := int64(binary.LittleEndian.Uint64(td.min))
-               assert.Equal(t, int64(-50), minVal)
-
-               maxVal := int64(binary.LittleEndian.Uint64(td.max))
-               assert.Equal(t, int64(200), maxVal)
-       })
-
-       t.Run("reset functionality", func(t *testing.T) {
-               td := generateTagData()
-
-               // Set up tag data
-               td.name = testTagName
-               td.valueType = pbv1.ValueTypeStr
-               td.indexed = true
-               td.values = [][]byte{[]byte("value1"), []byte("value2")}
-               td.filter = generateTagFilter(td.values, 10)
-               td.min = []byte("min")
-               td.max = []byte("max")
-
-               // Reset
-               td.reset()
-
-               // Verify reset
-               assert.Equal(t, "", td.name)
-               assert.Equal(t, pbv1.ValueTypeUnknown, td.valueType)
-               assert.False(t, td.indexed)
-               assert.Equal(t, 0, len(td.values))
-               assert.Nil(t, td.filter)
-               assert.Nil(t, td.min)
-               assert.Nil(t, td.max)
-
-               releaseTagData(td)
-       })
-}
-
-func TestTagMetadataOperations(t *testing.T) {
-       t.Run("marshal and unmarshal", func(t *testing.T) {
-               original := generateTagMetadata()
-               defer releaseTagMetadata(original)
-
-               // Set up metadata
-               original.name = "test_tag"
-               original.valueType = pbv1.ValueTypeInt64
-               original.indexed = true
-               original.dataBlock = dataBlock{offset: 100, size: 500}
-               original.filterBlock = dataBlock{offset: 600, size: 200}
-               original.min = []byte{0x01, 0x02}
-               original.max = []byte{0xFF, 0xFE}
-
-               // Marshal
-               data := original.marshal(nil)
-               assert.NotNil(t, data)
-
-               // Unmarshal
-               unmarshaled, err := unmarshalTagMetadata(data)
-               require.NoError(t, err)
-               defer releaseTagMetadata(unmarshaled)
-
-               // Verify fields
-               assert.Equal(t, original.name, unmarshaled.name)
-               assert.Equal(t, original.valueType, unmarshaled.valueType)
-               assert.Equal(t, original.indexed, unmarshaled.indexed)
-               assert.Equal(t, original.dataBlock, unmarshaled.dataBlock)
-               assert.Equal(t, original.filterBlock, unmarshaled.filterBlock)
-               assert.Equal(t, original.min, unmarshaled.min)
-               assert.Equal(t, original.max, unmarshaled.max)
-       })
-
-       t.Run("marshal empty metadata", func(t *testing.T) {
-               tm := generateTagMetadata()
-               defer releaseTagMetadata(tm)
-
-               tm.name = "empty_tag"
-               tm.valueType = pbv1.ValueTypeStr
-
-               data := tm.marshal(nil)
-
-               unmarshaled, err := unmarshalTagMetadata(data)
-               require.NoError(t, err)
-               defer releaseTagMetadata(unmarshaled)
+       tag.Reset()
 
-               assert.Equal(t, tm.name, unmarshaled.name)
-               assert.Equal(t, tm.valueType, unmarshaled.valueType)
-               assert.False(t, unmarshaled.indexed)
-               assert.Nil(t, unmarshaled.min)
-               assert.Nil(t, unmarshaled.max)
-       })
-
-       t.Run("reset functionality", func(t *testing.T) {
-               tm := generateTagMetadata()
-
-               // Set up metadata
-               tm.name = "test_tag"
-               tm.valueType = pbv1.ValueTypeInt64
-               tm.indexed = true
-               tm.dataBlock = dataBlock{offset: 100, size: 500}
-               tm.filterBlock = dataBlock{offset: 600, size: 200}
-               tm.min = []byte("min")
-               tm.max = []byte("max")
-
-               // Reset
-               tm.reset()
-
-               // Verify reset
-               assert.Equal(t, "", tm.name)
-               assert.Equal(t, pbv1.ValueTypeUnknown, tm.valueType)
-               assert.False(t, tm.indexed)
-               assert.Equal(t, dataBlock{}, tm.dataBlock)
-               assert.Equal(t, dataBlock{}, tm.filterBlock)
-               assert.Nil(t, tm.min)
-               assert.Nil(t, tm.max)
-
-               releaseTagMetadata(tm)
-       })
-}
-
-func TestTagPooling(t *testing.T) {
-       t.Run("tagData pooling", func(t *testing.T) {
-               // Get from pool
-               td1 := generateTagData()
-               assert.NotNil(t, td1)
-
-               // Use and release
-               td1.name = "test"
-               releaseTagData(td1)
-
-               // Get again - should be reset
-               td2 := generateTagData()
-               assert.NotNil(t, td2)
-               assert.Equal(t, "", td2.name) // Should be reset
-
-               releaseTagData(td2)
-       })
-
-       t.Run("tagMetadata pooling", func(t *testing.T) {
-               // Get from pool
-               tm1 := generateTagMetadata()
-               assert.NotNil(t, tm1)
-
-               // Use and release
-               tm1.name = "test"
-               releaseTagMetadata(tm1)
-
-               // Get again - should be reset
-               tm2 := generateTagMetadata()
-               assert.NotNil(t, tm2)
-               assert.Equal(t, "", tm2.name) // Should be reset
-
-               releaseTagMetadata(tm2)
-       })
-
-       t.Run("bloomFilter pooling", func(t *testing.T) {
-               // Generate bloom filter
-               bf1 := generateBloomFilter(100)
-               assert.NotNil(t, bf1)
-               assert.Equal(t, 100, bf1.N())
-
-               // Add some data
-               bf1.Add([]byte("test1"))
-               bf1.Add([]byte("test2"))
-               assert.True(t, bf1.MightContain([]byte("test1")))
-
-               // Release to pool
-               releaseBloomFilter(bf1)
-
-               // Get from pool again
-               bf2 := generateBloomFilter(50)
-               assert.NotNil(t, bf2)
-               assert.Equal(t, 50, bf2.N())                       // Should be 
reset to new size
-               assert.False(t, bf2.MightContain([]byte("test1"))) // Should 
not contain old data
-
-               releaseBloomFilter(bf2)
-       })
+       assert.Equal(t, "", tag.Name)
+       assert.Nil(t, tag.Value)
+       assert.Equal(t, pbv1.ValueTypeUnknown, tag.ValueType)
+       assert.Equal(t, false, tag.Indexed)
 }
 
-func TestEdgeCases(t *testing.T) {
-       t.Run("invalid int64 length", func(t *testing.T) {
-               // The shared encoding module panics on invalid data (fail fast)
-               assert.Panics(t, func() {
-                       invalidValues := [][]byte{{0x01, 0x02, 0x03}} // Only 3 
bytes, not 8
-                       _, _ = encodeTagValues(invalidValues, 
pbv1.ValueTypeInt64)
-               })
-       })
-
-       t.Run("marshal nil values", func(t *testing.T) {
-               data, err := encodeTagValues(nil, pbv1.ValueTypeStr)
-               require.NoError(t, err)
-               assert.Nil(t, data)
-
-               values, err := decodeTagValues(nil, pbv1.ValueTypeStr, 0)
-               require.NoError(t, err)
-               assert.Nil(t, values)
-       })
-
-       t.Run("updateMinMax with empty values", func(t *testing.T) {
-               td := generateTagData()
-               defer releaseTagData(td)
-
-               td.valueType = pbv1.ValueTypeInt64
-               td.values = [][]byte{} // empty
-
-               td.updateMinMax()
-               assert.Nil(t, td.min)
-               assert.Nil(t, td.max)
-       })
-
-       t.Run("updateMinMax with non-int64 type", func(t *testing.T) {
-               td := generateTagData()
-               defer releaseTagData(td)
-
-               td.valueType = pbv1.ValueTypeStr
-               td.values = [][]byte{[]byte("test")}
-
-               td.updateMinMax()
-               assert.Nil(t, td.min)
-               assert.Nil(t, td.max)
-       })
-
-       t.Run("hasValue with non-indexed tag", func(t *testing.T) {
-               td := generateTagData()
-               defer releaseTagData(td)
-
-               td.indexed = false
-               td.values = [][]byte{[]byte("value1"), []byte("value2")}
-
-               // Should use linear search
-               assert.True(t, td.hasValue([]byte("value1")))
-               assert.True(t, td.hasValue([]byte("value2")))
-               assert.False(t, td.hasValue([]byte("value3")))
-       })
-}
-
-func TestRoundTripIntegrity(t *testing.T) {
-       t.Run("complete round trip", func(t *testing.T) {
-               // Create original tag metadata
-               original := generateTagMetadata()
-               defer releaseTagMetadata(original)
-
-               original.name = "integration_tag"
-               original.valueType = pbv1.ValueTypeInt64
-               original.indexed = true
-               original.dataBlock = dataBlock{offset: 1000, size: 2000}
-               original.filterBlock = dataBlock{offset: 3000, size: 500}
-
-               // Create some int64 values
-               int64Values := []int64{-100, 0, 100, 200, 50}
-               var encodedValues [][]byte
-               for _, v := range int64Values {
-                       encoded := make([]byte, 8)
-                       binary.LittleEndian.PutUint64(encoded, uint64(v))
-                       encodedValues = append(encodedValues, encoded)
-               }
-
-               // Marshal values using shared encoding
-               marshaledValues, err := encodeTagValues(encodedValues, 
pbv1.ValueTypeInt64)
-               require.NoError(t, err)
-
-               // Marshal metadata
-               marshaledMetadata := original.marshal(nil)
-
-               // Unmarshal metadata
-               unmarshaledMetadata, err := 
unmarshalTagMetadata(marshaledMetadata)
-               require.NoError(t, err)
-               defer releaseTagMetadata(unmarshaledMetadata)
-
-               // Unmarshal values using shared encoding
-               unmarshaledValues, err := decodeTagValues(marshaledValues, 
pbv1.ValueTypeInt64, len(encodedValues))
-               require.NoError(t, err)
-
-               // Verify metadata integrity
-               assert.Equal(t, original.name, unmarshaledMetadata.name)
-               assert.Equal(t, original.valueType, 
unmarshaledMetadata.valueType)
-               assert.Equal(t, original.indexed, unmarshaledMetadata.indexed)
-
-               // Verify values integrity
-               assert.Equal(t, len(encodedValues), len(unmarshaledValues))
-               for i, original := range encodedValues {
-                       assert.True(t, bytes.Equal(original, 
unmarshaledValues[i]))
-               }
+func TestTagSize(t *testing.T) {
+       tag := Tag{
+               Name:      "test",
+               Value:     []byte("value"),
+               ValueType: pbv1.ValueTypeStr,
+               Indexed:   true,
+       }
 
-               // Decode and verify int64 values
-               for i, expected := range int64Values {
-                       decoded := 
int64(binary.LittleEndian.Uint64(unmarshaledValues[i]))
-                       assert.Equal(t, expected, decoded)
-               }
-       })
+       // Size should be len(name) + len(value) + 1 (for valueType)
+       expectedSize := len("test") + len("value") + 1
+       assert.Equal(t, expectedSize, tag.Size())
 }
 
-func TestBloomFilterEncoding(t *testing.T) {
-       t.Run("encode and decode bloom filter", func(t *testing.T) {
-               // Create a bloom filter and add some data
-               bf := generateBloomFilter(100)
-               defer releaseBloomFilter(bf)
-
-               testValues := [][]byte{
-                       []byte("value1"),
-                       []byte("value2"),
-                       []byte("value3"),
-               }
-
-               for _, value := range testValues {
-                       bf.Add(value)
-               }
-
-               // Encode the bloom filter
-               var encoded []byte
-               encoded = encodeBloomFilter(encoded, bf)
-               assert.NotEmpty(t, encoded)
-
-               // Decode the bloom filter
-               decodedBf, err := decodeBloomFilter(encoded)
-               require.NoError(t, err)
-               defer releaseBloomFilter(decodedBf)
-
-               // Verify the decoded filter contains the same data
-               assert.Equal(t, bf.N(), decodedBf.N())
-               for _, value := range testValues {
-                       assert.True(t, decodedBf.MightContain(value))
-               }
-       })
+func TestTagCopy(t *testing.T) {
+       original := Tag{
+               Name:      "original",
+               Value:     []byte("original-value"),
+               ValueType: pbv1.ValueTypeStr,
+               Indexed:   true,
+       }
 
-       t.Run("encode empty bloom filter", func(t *testing.T) {
-               var encoded []byte
-               encoded = encodeBloomFilter(encoded, nil)
-               assert.Empty(t, encoded)
-       })
+       copied := original.Copy()
 
-       t.Run("decode invalid data", func(t *testing.T) {
-               // Test with data too short
-               invalidData := []byte{0x01, 0x02}
-               _, err := decodeBloomFilter(invalidData)
-               assert.Error(t, err)
-               assert.Contains(t, err.Error(), "too short")
+       // Test that copied tag has same values
+       assert.Equal(t, original.Name, copied.Name)
+       assert.Equal(t, original.Value, copied.Value)
+       assert.Equal(t, original.ValueType, copied.ValueType)
+       assert.Equal(t, original.Indexed, copied.Indexed)
 
-               // Test with empty data
-               _, err = decodeBloomFilter([]byte{})
-               assert.Error(t, err)
-               assert.Contains(t, err.Error(), "too short")
-       })
+       // Test that modifying original doesn't affect copy
+       original.Name = "modified"
+       original.Value = []byte("modified-value")
+       assert.Equal(t, "original", copied.Name)
+       assert.Equal(t, []byte("original-value"), copied.Value)
 }
 
-// generateTagFilter creates a bloom filter for indexed tags.
-func generateTagFilter(values [][]byte, expectedElements int) 
*filter.BloomFilter {
-       if len(values) == 0 {
-               return nil
-       }
-
-       bloomFilter := generateBloomFilter(expectedElements)
-
-       for _, value := range values {
-               bloomFilter.Add(value)
+func TestTagInWriteRequest(t *testing.T) {
+       // Test that Tag can be used in WriteRequest
+       req := WriteRequest{
+               SeriesID: 123,
+               Key:      456,
+               Data:     []byte("test-data"),
+               Tags: []Tag{
+                       {Name: "service", Value: []byte("order-service"), 
ValueType: pbv1.ValueTypeStr, Indexed: true},
+                       {Name: "environment", Value: []byte("prod"), ValueType: 
pbv1.ValueTypeStr, Indexed: false},
+               },
        }
 
-       return bloomFilter
+       assert.Equal(t, 2, len(req.Tags))
+       assert.Equal(t, "service", req.Tags[0].Name)
+       assert.Equal(t, "environment", req.Tags[1].Name)
 }


Reply via email to