// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package queryutil

import (
	"context"
	"encoding/binary"
	"fmt"
	"math"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/milvus-io/milvus-proto/go-api/v3/commonpb"
	"github.com/milvus-io/milvus-proto/go-api/v3/schemapb"
	"github.com/milvus-io/milvus/pkg/v3/proto/internalpb"
)

// makeNullableSchema builds a minimal CollectionSchema marking the given
// fieldID as nullable with the specified DataType. For dense vectors, pass
// dim > 0; for sparse or scalars, pass dim = 0.
func makeNullableSchema(fieldID int64, dataType schemapb.DataType, dim int64) *schemapb.CollectionSchema {
	fs := &schemapb.FieldSchema{
		FieldID:  fieldID,
		DataType: dataType,
		Nullable: true,
	}
	if dim > 0 {
		fs.TypeParams = []*commonpb.KeyValuePair{
			{Key: "dim", Value: fmt.Sprintf("%d", dim)},
		}
	}
	return &schemapb.CollectionSchema{Fields: []*schemapb.FieldSchema{fs}}
}

func requireRangeSliceRetrieveResults(t *testing.T, result *internalpb.RetrieveResults, start, end int) *internalpb.RetrieveResults {
	t.Helper()
	sliced, err := rangeSliceRetrieveResults(result, start, end)
	require.NoError(t, err)
	return sliced
}

func requireRangeSliceFieldData(t *testing.T, fd *schemapb.FieldData, start, end int) *schemapb.FieldData {
	t.Helper()
	sliced, err := rangeSliceFieldData(fd, start, end)
	require.NoError(t, err)
	return sliced
}

func requireRangeSliceVectorField(t *testing.T, vf *schemapb.VectorField, start, end int, validData []bool) *schemapb.VectorField {
	t.Helper()
	sliced, err := rangeSliceVectorField(vf, start, end, validData)
	require.NoError(t, err)
	return sliced
}

func requireSliceFieldData(t *testing.T, fd *schemapb.FieldData, indices []int) *schemapb.FieldData {
	t.Helper()
	sliced, err := sliceFieldData(fd, indices)
	require.NoError(t, err)
	return sliced
}

func requireSliceVectorField(t *testing.T, vf *schemapb.VectorField, indices []int, validData []bool) *schemapb.VectorField {
	t.Helper()
	sliced, err := sliceVectorField(vf, indices, validData)
	require.NoError(t, err)
	return sliced
}

func TestGetRowCountNullableCompactVectorWithoutIDsUsesLogicalRows(t *testing.T) {
	result := &internalpb.RetrieveResults{
		FieldsData: []*schemapb.FieldData{
			{
				Type:      schemapb.DataType_FloatVector,
				FieldName: "nullable_vec",
				FieldId:   100,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: 2,
					Data: &schemapb.VectorField_FloatVector{
						FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}},
					},
				}},
				ValidData: []bool{true, false, true},
			},
		},
	}

	assert.Equal(t, 3, getRowCount(result))
}

// =========================================================================
// buildMergedFieldData: ValidData preservation
// =========================================================================

func TestBuildMergedFieldData_ValidData(t *testing.T) {
	// Two results with nullable int64 fields
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20}}},
				}},
				ValidData: []bool{true, false}, // row 0 valid, row 1 null
			},
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{3}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{30}}},
				}},
				ValidData: []bool{true},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1, r2}
	selectedRows := []rowRef{
		{resultIdx: 0, rowIdx: 0}, // r1 row 0 (valid)
		{resultIdx: 0, rowIdx: 1}, // r1 row 1 (null)
		{resultIdx: 1, rowIdx: 0}, // r2 row 0 (valid)
	}

	merged, err := buildMergedRetrieveResults(results, selectedRows, makeNullableSchema(100, schemapb.DataType_Int64, 0))
	require.NoError(t, err)
	require.Len(t, merged.FieldsData, 1)

	fd := merged.FieldsData[0]
	assert.Equal(t, []bool{true, false, true}, fd.ValidData)
	assert.Equal(t, []int64{10, 20, 30}, fd.GetScalars().GetLongData().GetData())
}

func TestBuildMergedFieldData_ValidData_MixedNullable(t *testing.T) {
	// r1 has ValidData (nullable), r2 has explicit ValidData=[true] (all valid)
	// This tests that explicit all-valid ValidData is preserved correctly.
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10}}},
				}},
				ValidData: []bool{false}, // null
			},
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{20}}},
				}},
				ValidData: []bool{true}, // explicit valid (segcore always includes ValidData for nullable fields)
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1, r2}
	selectedRows := []rowRef{
		{resultIdx: 0, rowIdx: 0}, // r1 (null)
		{resultIdx: 1, rowIdx: 0}, // r2 (valid=true)
	}

	merged, err := buildMergedRetrieveResults(results, selectedRows, makeNullableSchema(100, schemapb.DataType_Int64, 0))
	require.NoError(t, err)

	fd := merged.FieldsData[0]
	assert.Equal(t, []bool{false, true}, fd.ValidData)
}

// =========================================================================
// buildMergedScalarField: ArrayData ElementType preservation
// =========================================================================

func TestBuildMergedScalarField_ArrayElementType(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Array, FieldId: 200,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_ArrayData{ArrayData: &schemapb.ArrayArray{
						Data: []*schemapb.ScalarField{
							{Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.1, 2.2}}}},
							{Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{3.3}}}},
						},
						ElementType: schemapb.DataType_Float,
					}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	arrayField := merged.FieldsData[0].GetScalars().GetArrayData()
	assert.Equal(t, schemapb.DataType_Float, arrayField.GetElementType())
	assert.Len(t, arrayField.GetData(), 2)
}

// =========================================================================
// buildMergedScalarField: Geometry types
// =========================================================================

func TestBuildMergedScalarField_GeometryWktData(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Geometry, FieldId: 300,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{
						Data: []string{"POINT(0 0)", "POINT(1 1)"},
					}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	wktData := merged.FieldsData[0].GetScalars().GetGeometryWktData().GetData()
	assert.Equal(t, []string{"POINT(1 1)"}, wktData)
}

func TestBuildMergedScalarField_GeometryData(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Geometry, FieldId: 300,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{
						Data: [][]byte{{0x01, 0x02}, {0x03, 0x04}},
					}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	geoData := merged.FieldsData[0].GetScalars().GetGeometryData().GetData()
	assert.Equal(t, [][]byte{{0x01, 0x02}}, geoData)
}

// =========================================================================
// buildMergedScalarField: Timestamptz and Mol types
// =========================================================================

func TestBuildMergedScalarField_TimestamptzData(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Timestamptz, FieldId: 400,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_TimestamptzData{TimestamptzData: &schemapb.TimestamptzArray{
						Data: []int64{1000, 2000},
					}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	tsData := merged.FieldsData[0].GetScalars().GetTimestamptzData().GetData()
	assert.Equal(t, []int64{1000, 2000}, tsData)
}

func TestBuildMergedScalarField_MolData(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Mol, FieldId: 500,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_MolData{MolData: &schemapb.MolArray{
						Data: [][]byte{{0xAA, 0xBB}},
					}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	molData := merged.FieldsData[0].GetScalars().GetMolData().GetData()
	assert.Equal(t, [][]byte{{0xAA, 0xBB}}, molData)
}

// =========================================================================
// buildMergedVectorField: Int8Vector
// =========================================================================

func TestBuildMergedVectorField_Int8Vector(t *testing.T) {
	dim := 4
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int8Vector, FieldId: 600,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  int64(dim),
					Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}} // select row 1 only

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	vecData := merged.FieldsData[0].GetVectors().GetInt8Vector()
	assert.Equal(t, []byte{5, 6, 7, 8}, vecData)
}

// =========================================================================
// rangeSliceScalarField: new types
// =========================================================================

func TestRangeSliceScalarField_ArrayElementType(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Array, FieldId: 200,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_ArrayData{ArrayData: &schemapb.ArrayArray{
				Data: []*schemapb.ScalarField{
					{Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{1}}}},
					{Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{2}}}},
					{Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{3}}}},
				},
				ElementType: schemapb.DataType_Int32,
			}},
		}},
	}

	sliced := requireRangeSliceFieldData(t, fd, 1, 3)
	arrayField := sliced.GetScalars().GetArrayData()
	assert.Equal(t, schemapb.DataType_Int32, arrayField.GetElementType())
	assert.Len(t, arrayField.GetData(), 2)
}

func TestRangeSliceScalarField_GeometryWkt(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Geometry, FieldId: 300,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{
				Data: []string{"POINT(0 0)", "POINT(1 1)", "POINT(2 2)"},
			}},
		}},
	}

	sliced := requireRangeSliceFieldData(t, fd, 1, 3)
	assert.Equal(t, []string{"POINT(1 1)", "POINT(2 2)"}, sliced.GetScalars().GetGeometryWktData().GetData())
}

func TestRangeSliceScalarField_Timestamptz(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Timestamptz, FieldId: 400,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_TimestamptzData{TimestamptzData: &schemapb.TimestamptzArray{
				Data: []int64{100, 200, 300},
			}},
		}},
	}

	sliced := requireRangeSliceFieldData(t, fd, 0, 2)
	assert.Equal(t, []int64{100, 200}, sliced.GetScalars().GetTimestamptzData().GetData())
}

// =========================================================================
// sliceScalarField (index-based): new types
// =========================================================================

func TestSliceScalarField_ArrayElementType(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Array, FieldId: 200,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_ArrayData{ArrayData: &schemapb.ArrayArray{
				Data: []*schemapb.ScalarField{
					{Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10}}}},
					{Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{20}}}},
					{Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{30}}}},
				},
				ElementType: schemapb.DataType_Int64,
			}},
		}},
	}

	sliced := requireSliceFieldData(t, fd, []int{2, 0})
	arrayField := sliced.GetScalars().GetArrayData()
	assert.Equal(t, schemapb.DataType_Int64, arrayField.GetElementType())
	assert.Len(t, arrayField.GetData(), 2)
	assert.Equal(t, []int64{30}, arrayField.GetData()[0].GetLongData().GetData())
	assert.Equal(t, []int64{10}, arrayField.GetData()[1].GetLongData().GetData())
}

func TestSliceScalarField_GeometryWkt(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Geometry, FieldId: 300,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{
				Data: []string{"POINT(0 0)", "POINT(1 1)", "POINT(2 2)"},
			}},
		}},
	}

	sliced := requireSliceFieldData(t, fd, []int{2, 0})
	assert.Equal(t, []string{"POINT(2 2)", "POINT(0 0)"}, sliced.GetScalars().GetGeometryWktData().GetData())
}

// =========================================================================
// calcFieldElementSize: new types
// =========================================================================

func TestCalcFieldElementSize_Geometry(t *testing.T) {
	fd := &schemapb.FieldData{
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{
				Data: []string{"POINT(0 0)", "LINESTRING(0 0, 1 1)"},
			}},
		}},
	}
	assert.Equal(t, int64(len("POINT(0 0)")), calcFieldElementSize(fd, 0))
	assert.Equal(t, int64(len("LINESTRING(0 0, 1 1)")), calcFieldElementSize(fd, 1))
}

func TestCalcFieldElementSize_Timestamptz(t *testing.T) {
	fd := &schemapb.FieldData{
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_TimestamptzData{TimestamptzData: &schemapb.TimestamptzArray{
				Data: []int64{1000},
			}},
		}},
	}
	assert.Equal(t, int64(8), calcFieldElementSize(fd, 0))
}

func TestCalcFieldElementSize_Int8Vector(t *testing.T) {
	fd := &schemapb.FieldData{
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim:  128,
			Data: &schemapb.VectorField_Int8Vector{Int8Vector: make([]byte, 256)},
		}},
	}
	assert.Equal(t, int64(128), calcFieldElementSize(fd, 0))
}

// =========================================================================
// ElementIndices propagation through merge
// =========================================================================

func TestBuildMergedRetrieveResults_ElementIndices(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20}}},
				}},
			},
		},
		ElementLevel:   true,
		ElementIndices: []*internalpb.ElementIndices{{Indices: []int32{0, 1}}, {Indices: []int32{2}}},
	}

	results := []*internalpb.RetrieveResults{r1}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 0}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	assert.True(t, merged.GetElementLevel())
	require.Len(t, merged.GetElementIndices(), 2)
	assert.Equal(t, []int32{2}, merged.GetElementIndices()[0].GetIndices())
	assert.Equal(t, []int32{0, 1}, merged.GetElementIndices()[1].GetIndices())
}

// =========================================================================
// rangeSliceRetrieveResults: ElementIndices propagation
// =========================================================================

func TestRangeSliceRetrieveResults_ElementIndices(t *testing.T) {
	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20, 30}}},
				}},
			},
		},
		ElementLevel: true,
		ElementIndices: []*internalpb.ElementIndices{
			{Indices: []int32{0, 1}},
			{Indices: []int32{2}},
			{Indices: []int32{0}},
		},
	}

	sliced := requireRangeSliceRetrieveResults(t, result, 1, 3)
	assert.True(t, sliced.GetElementLevel())
	require.Len(t, sliced.GetElementIndices(), 2)
	assert.Equal(t, []int32{2}, sliced.GetElementIndices()[0].GetIndices())
	assert.Equal(t, []int32{0}, sliced.GetElementIndices()[1].GetIndices())
}

// =========================================================================
// ConcatAndCheckPKOperator
// =========================================================================

func TestConcatAndCheckPKOperator_NoDuplicate(t *testing.T) {
	op := NewConcatAndCheckPKOperator(nil)
	ctx := context.Background()

	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20}}},
				}},
			},
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{3, 4}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{30, 40}}},
				}},
			},
		},
	}

	outputs, err := op.Run(ctx, nil, []*internalpb.RetrieveResults{r1, r2})
	require.NoError(t, err)

	result := outputs[0].(*internalpb.RetrieveResults)
	ids := result.GetIds().GetIntId().GetData()
	// Concatenated in order: 1,2,3,4
	assert.Equal(t, []int64{1, 2, 3, 4}, ids)
}

func TestConcatAndCheckPKOperator_DuplicateFails(t *testing.T) {
	op := NewConcatAndCheckPKOperator(nil)
	ctx := context.Background()

	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20}}},
				}},
			},
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{2, 3}}}}, // PK=2 duplicate
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 100,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{21, 30}}},
				}},
			},
		},
	}

	_, err := op.Run(ctx, nil, []*internalpb.RetrieveResults{r1, r2})
	require.Error(t, err)
	assert.Contains(t, err.Error(), "duplicate PK")
}

// =========================================================================
// buildMergedRetrieveResults: common scalar types (LongData, DoubleData, StringData)
// =========================================================================

func TestBuildMergedFieldData_CommonScalarTypes(t *testing.T) {
	// Merge two results with Int64 + Double + String fields
	makeDoubleField := func(id int64, name string, vals []float64) *schemapb.FieldData {
		return &schemapb.FieldData{
			FieldId: id, FieldName: name, Type: schemapb.DataType_Double,
			Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: vals}},
			}},
		}
	}
	makeStringField := func(id int64, name string, vals []string) *schemapb.FieldData {
		return &schemapb.FieldData{
			FieldId: id, FieldName: name, Type: schemapb.DataType_VarChar,
			Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: vals}},
			}},
		}
	}

	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{FieldId: 100, Type: schemapb.DataType_Int64, Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20}}},
			}}},
			makeDoubleField(101, "price", []float64{1.1, 2.2}),
			makeStringField(102, "name", []string{"alice", "bob"}),
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{3}}}},
		FieldsData: []*schemapb.FieldData{
			{FieldId: 100, Type: schemapb.DataType_Int64, Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{30}}},
			}}},
			makeDoubleField(101, "price", []float64{3.3}),
			makeStringField(102, "name", []string{"charlie"}),
		},
	}

	selectedRows := []rowRef{{0, 0}, {1, 0}, {0, 1}} // r1[0], r2[0], r1[1]
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1, r2}, selectedRows, nil)
	require.NoError(t, err)

	assert.Equal(t, []int64{1, 3, 2}, merged.GetIds().GetIntId().GetData())
	assert.Equal(t, []int64{10, 30, 20}, merged.GetFieldsData()[0].GetScalars().GetLongData().GetData())
	assert.Equal(t, []float64{1.1, 3.3, 2.2}, merged.GetFieldsData()[1].GetScalars().GetDoubleData().GetData())
	assert.Equal(t, []string{"alice", "charlie", "bob"}, merged.GetFieldsData()[2].GetScalars().GetStringData().GetData())
}

// =========================================================================
// buildMergedRetrieveResults: FloatVector merge
// =========================================================================

func TestBuildMergedFieldData_FloatVector(t *testing.T) {
	dim := 4
	makeVecField := func(id int64, data []float32) *schemapb.FieldData {
		return &schemapb.FieldData{
			FieldId: id, Type: schemapb.DataType_FloatVector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  int64(dim),
				Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: data}},
			}},
		}
	}

	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			makeVecField(100, []float32{1, 2, 3, 4, 5, 6, 7, 8}), // 2 rows × dim=4
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{3}}}},
		FieldsData: []*schemapb.FieldData{
			makeVecField(100, []float32{9, 10, 11, 12}), // 1 row × dim=4
		},
	}

	selectedRows := []rowRef{{1, 0}, {0, 1}} // r2[0], r1[1]
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1, r2}, selectedRows, nil)
	require.NoError(t, err)

	vecData := merged.GetFieldsData()[0].GetVectors().GetFloatVector().GetData()
	assert.Equal(t, []float32{9, 10, 11, 12, 5, 6, 7, 8}, vecData)
}

// =========================================================================
// calcRowSize
// =========================================================================

func TestCalcRowSize_BasicTypes(t *testing.T) {
	r := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			// Int64: 8 bytes
			{FieldId: 100, Type: schemapb.DataType_Int64, Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{42}}},
			}}},
			// Double: 8 bytes
			{FieldId: 101, Type: schemapb.DataType_Double, Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: []float64{3.14}}},
			}}},
			// String: len("hello") = 5 bytes
			{FieldId: 102, Type: schemapb.DataType_VarChar, Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{"hello"}}},
			}}},
		},
	}

	size := calcRowSize(r, 0)
	assert.Equal(t, int64(8+8+5), size) // Int64(8) + Double(8) + String("hello"=5)
}

func TestCalcRowSize_EmptyString(t *testing.T) {
	r := &internalpb.RetrieveResults{
		FieldsData: []*schemapb.FieldData{
			{FieldId: 100, Type: schemapb.DataType_VarChar, Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{""}}},
			}}},
		},
	}
	size := calcRowSize(r, 0)
	assert.Equal(t, int64(0), size)
}

func TestCalcRowSize_FloatVector(t *testing.T) {
	dim := 8
	r := &internalpb.RetrieveResults{
		FieldsData: []*schemapb.FieldData{
			{
				FieldId: 100, Type: schemapb.DataType_FloatVector,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  int64(dim),
					Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: make([]float32, dim*2)}}, // 2 rows
				}},
			},
		},
	}
	// FloatVector: dim * 4 bytes per row = 8 * 4 = 32
	size := calcRowSize(r, 0)
	assert.Equal(t, int64(dim*4), size)
}

func TestCalcRowSize_NullableDenseVectorUsesLogicalValidity(t *testing.T) {
	tests := []struct {
		name     string
		field    *schemapb.FieldData
		wantSize int64
	}{
		{
			name: "float_vector",
			field: &schemapb.FieldData{
				Type:      schemapb.DataType_FloatVector,
				ValidData: []bool{false, true},
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}},
				}},
			},
			wantSize: 8,
		},
		{
			name: "binary_vector",
			field: &schemapb.FieldData{
				Type:      schemapb.DataType_BinaryVector,
				ValidData: []bool{false, true},
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  16,
					Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0x01, 0x02}},
				}},
			},
			wantSize: 2,
		},
		{
			name: "float16_vector",
			field: &schemapb.FieldData{
				Type:      schemapb.DataType_Float16Vector,
				ValidData: []bool{false, true},
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{0x01, 0x02, 0x03, 0x04}},
				}},
			},
			wantSize: 4,
		},
		{
			name: "bfloat16_vector",
			field: &schemapb.FieldData{
				Type:      schemapb.DataType_BFloat16Vector,
				ValidData: []bool{false, true},
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{0x01, 0x02, 0x03, 0x04}},
				}},
			},
			wantSize: 4,
		},
		{
			name: "int8_vector",
			field: &schemapb.FieldData{
				Type:      schemapb.DataType_Int8Vector,
				ValidData: []bool{false, true},
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  4,
					Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{0x01, 0x02, 0x03, 0x04}},
				}},
			},
			wantSize: 4,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			r := &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{tt.field}}
			assert.Equal(t, int64(0), calcRowSize(r, 0))
			assert.Equal(t, tt.wantSize, calcRowSize(r, 1))
		})
	}
}

func TestCalcRowSize_NullableSparseVectorUsesCompactMapping(t *testing.T) {
	rowA := makeTestSparseVec(1, 0.5)
	rowC := makeTestSparseVec(3, 1.5)

	tests := []struct {
		name      string
		validData []bool
		contents  [][]byte
		wantSizes []int64
	}{
		{
			name:      "null_before_valid",
			validData: []bool{false, true},
			contents:  [][]byte{rowA},
			wantSizes: []int64{0, int64(len(rowA))},
		},
		{
			name:      "valid_null_valid",
			validData: []bool{true, false, true},
			contents:  [][]byte{rowA, rowC},
			wantSizes: []int64{int64(len(rowA)), 0, int64(len(rowC))},
		},
		{
			name:      "all_null",
			validData: []bool{false, false},
			contents:  nil,
			wantSizes: []int64{0, 0},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			r := &internalpb.RetrieveResults{
				FieldsData: []*schemapb.FieldData{
					{
						Type:      schemapb.DataType_SparseFloatVector,
						ValidData: tt.validData,
						Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
							Dim: 4,
							Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
								Dim:      4,
								Contents: tt.contents,
							}},
						}},
					},
				},
			}
			for rowIdx, want := range tt.wantSizes {
				assert.Equal(t, want, calcRowSize(r, int64(rowIdx)))
			}
		})
	}
}

func TestCalcRowSize_MultipleFieldTypes(t *testing.T) {
	r := &internalpb.RetrieveResults{
		FieldsData: []*schemapb.FieldData{
			// Bool: 1 byte
			{
				FieldId: 100, Type: schemapb.DataType_Bool,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_BoolData{BoolData: &schemapb.BoolArray{Data: []bool{true}}},
				}},
			},
			// Float: 4 bytes
			{
				FieldId: 101, Type: schemapb.DataType_Float,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.0}}},
				}},
			},
			// Int32: 4 bytes
			{
				FieldId: 102, Type: schemapb.DataType_Int32,
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{42}}},
				}},
			},
		},
	}
	size := calcRowSize(r, 0)
	assert.Equal(t, int64(1+4+4), size) // Bool(1) + Float(4) + Int32(4)
}

// =========================================================================
// validateElementLevelConsistency
// =========================================================================

func TestValidateElementLevelConsistency_Consistent(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids:          &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		ElementLevel: true,
		ElementIndices: []*internalpb.ElementIndices{
			{Indices: []int32{0, 1}},
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids:          &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{2}}}},
		ElementLevel: true,
		ElementIndices: []*internalpb.ElementIndices{
			{Indices: []int32{3}},
		},
	}
	err := validateElementLevelConsistency([]*internalpb.RetrieveResults{r1, r2}, nil)
	assert.NoError(t, err)
}

// makeStructArrayFieldData creates a FieldData wrapping a StructArrayField with scalar sub-fields.
// Used by TestGetRowCount and slice/reconstruct tests below.
func makeStructArrayFieldData(fieldID int64, name string, subFields []*schemapb.FieldData) *schemapb.FieldData {
	return &schemapb.FieldData{
		Type:      schemapb.DataType_Array,
		FieldId:   fieldID,
		FieldName: name,
		Field: &schemapb.FieldData_StructArrays{
			StructArrays: &schemapb.StructArrayField{
				Fields: subFields,
			},
		},
	}
}

// =========================================================================
// rangeSliceStructArrayField
// =========================================================================

func TestRangeSliceStructArrayField(t *testing.T) {
	sa := &schemapb.StructArrayField{
		Fields: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 101, FieldName: "age",
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20, 30, 40}}},
				}},
			},
			{
				Type: schemapb.DataType_VarChar, FieldId: 102, FieldName: "name",
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{"a", "b", "c", "d"}}},
				}},
			},
		},
	}

	sliced, err := rangeSliceStructArrayField(sa, 1, 3)
	require.NoError(t, err)
	require.Len(t, sliced.GetFields(), 2)
	assert.Equal(t, []int64{20, 30}, sliced.GetFields()[0].GetScalars().GetLongData().GetData())
	assert.Equal(t, []string{"b", "c"}, sliced.GetFields()[1].GetScalars().GetStringData().GetData())
}

func TestRangeSliceStructArrayField_Nil(t *testing.T) {
	sliced, err := rangeSliceStructArrayField(nil, 0, 1)
	require.NoError(t, err)
	assert.Nil(t, sliced)
}

// =========================================================================
// sliceStructArrayField
// =========================================================================

func TestSliceStructArrayField(t *testing.T) {
	sa := &schemapb.StructArrayField{
		Fields: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_Int64, FieldId: 101, FieldName: "val",
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{100, 200, 300, 400}}},
				}},
			},
			{
				Type: schemapb.DataType_VarChar, FieldId: 102, FieldName: "tag",
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{"x", "y", "z", "w"}}},
				}},
			},
		},
	}

	// Select indices 3, 0, 2 (out of order)
	sliced, err := sliceStructArrayField(sa, []int{3, 0, 2})
	require.NoError(t, err)
	require.Len(t, sliced.GetFields(), 2)
	assert.Equal(t, []int64{400, 100, 300}, sliced.GetFields()[0].GetScalars().GetLongData().GetData())
	assert.Equal(t, []string{"w", "x", "z"}, sliced.GetFields()[1].GetScalars().GetStringData().GetData())
}

func TestSliceStructArrayField_Nil(t *testing.T) {
	sliced, err := sliceStructArrayField(nil, []int{0})
	require.NoError(t, err)
	assert.Nil(t, sliced)
}

// =========================================================================
// buildMergedVectorField: VectorArray (used in StructArray vector sub-fields)
// =========================================================================

func TestBuildMergedVectorField_VectorArray(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}
	v2 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3.0, 4.0}}}}
	v3 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{5.0, 6.0}}}}

	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_FloatVector, FieldId: 700,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						Data:        []*schemapb.VectorField{v1, v2},
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
			},
		},
	}
	r2 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{3}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_FloatVector, FieldId: 700,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						Data:        []*schemapb.VectorField{v3},
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
			},
		},
	}

	results := []*internalpb.RetrieveResults{r1, r2}
	selectedRows := []rowRef{{resultIdx: 1, rowIdx: 0}, {resultIdx: 0, rowIdx: 0}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, nil)
	require.NoError(t, err)

	va := merged.FieldsData[0].GetVectors().GetVectorArray()
	require.Len(t, va.GetData(), 2)
	assert.Equal(t, []float32{5.0, 6.0}, va.GetData()[0].GetFloatVector().GetData())
	assert.Equal(t, []float32{1.0, 2.0}, va.GetData()[1].GetFloatVector().GetData())
}

func TestBuildMergedVectorField_NullableStructVectorArray_AllNull(t *testing.T) {
	const fieldID = int64(700)
	dim := int64(2)
	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
				}},
				ValidData: []bool{false},
			},
		},
	}
	schema := &schemapb.CollectionSchema{
		StructArrayFields: []*schemapb.StructArrayFieldSchema{
			{
				Name:     "struct_field",
				Nullable: true,
				Fields: []*schemapb.FieldSchema{
					{
						FieldID:     fieldID,
						Name:        "struct_field[vec_array]",
						DataType:    schemapb.DataType_ArrayOfVector,
						ElementType: schemapb.DataType_FloatVector,
						Nullable:    true,
						TypeParams: []*commonpb.KeyValuePair{
							{Key: "dim", Value: "2"},
						},
					},
				},
			},
		},
	}

	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{result}, []rowRef{{resultIdx: 0, rowIdx: 0}}, schema)
	require.NoError(t, err)
	assert.Equal(t, []bool{false}, merged.FieldsData[0].GetValidData())
	va := merged.FieldsData[0].GetVectors().GetVectorArray()
	require.NotNil(t, va)
	assert.Equal(t, dim, va.GetDim())
	assert.Equal(t, schemapb.DataType_FloatVector, va.GetElementType())
	require.Len(t, va.GetData(), 1)
	assert.Empty(t, va.GetData()[0].GetFloatVector().GetData())
}

func TestBuildMergedVectorField_NullableStructVectorArray_AllNullWithEmptyVectorArray(t *testing.T) {
	const fieldID = int64(700)
	dim := int64(2)
	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
				ValidData: []bool{false, false},
			},
		},
	}
	schema := makeNullableSchema(fieldID, schemapb.DataType_ArrayOfVector, dim)
	schema.GetFields()[0].ElementType = schemapb.DataType_FloatVector

	merged, err := buildMergedRetrieveResults(
		[]*internalpb.RetrieveResults{result},
		[]rowRef{{resultIdx: 0, rowIdx: 1}},
		schema,
	)
	require.NoError(t, err)
	assert.Equal(t, []bool{false}, merged.FieldsData[0].GetValidData())
	va := merged.FieldsData[0].GetVectors().GetVectorArray()
	require.NotNil(t, va)
	assert.Equal(t, dim, va.GetDim())
	assert.Equal(t, schemapb.DataType_FloatVector, va.GetElementType())
	require.Len(t, va.GetData(), 1)
	assert.Empty(t, va.GetData()[0].GetFloatVector().GetData())
}

func TestBuildMergedVectorField_NullableArrayOfVector_RejectsEmptyValidData(t *testing.T) {
	const fieldID = int64(700)
	dim := int64(2)
	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						Data:        []*schemapb.VectorField{{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}},
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
			},
		},
	}
	schema := makeNullableSchema(fieldID, schemapb.DataType_ArrayOfVector, dim)
	schema.GetFields()[0].ElementType = schemapb.DataType_FloatVector

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{result}, []rowRef{{resultIdx: 0, rowIdx: 0}}, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "empty ValidData")
}

func TestBuildMergedVectorField_NullableArrayOfVector_RejectsValidDataRowOutOfRange(t *testing.T) {
	const fieldID = int64(700)
	dim := int64(2)
	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						Data:        []*schemapb.VectorField{{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}, {Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3.0, 4.0}}}}},
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
				ValidData: []bool{true},
			},
		},
	}
	schema := makeNullableSchema(fieldID, schemapb.DataType_ArrayOfVector, dim)
	schema.GetFields()[0].ElementType = schemapb.DataType_FloatVector

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{result}, []rowRef{{resultIdx: 0, rowIdx: 1}}, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "rowIdx=1")
	assert.Contains(t, err.Error(), "len(ValidData)=1")
}

func TestBuildMergedVectorField_NullableArrayOfVectorMixedAllNullSourceKeepsRowDense(t *testing.T) {
	const fieldID = int64(700)
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}

	allNullResult := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
				}},
				ValidData: []bool{false},
			},
		},
	}
	validResult := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						Data:        []*schemapb.VectorField{v1},
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
				ValidData: []bool{true},
			},
		},
	}
	schema := makeNullableSchema(fieldID, schemapb.DataType_ArrayOfVector, dim)
	schema.GetFields()[0].ElementType = schemapb.DataType_FloatVector

	merged, err := buildMergedRetrieveResults(
		[]*internalpb.RetrieveResults{allNullResult, validResult},
		[]rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 1, rowIdx: 0}},
		schema,
	)
	require.NoError(t, err)
	assert.Equal(t, []bool{false, true}, merged.FieldsData[0].GetValidData())
	va := merged.FieldsData[0].GetVectors().GetVectorArray()
	require.Len(t, va.GetData(), 2)
	assert.Empty(t, va.GetData()[0].GetFloatVector().GetData())
	assert.Equal(t, []float32{1.0, 2.0}, va.GetData()[1].GetFloatVector().GetData())
}

func TestBuildMergedVectorField_NullableArrayOfVectorUsesLogicalRowIndex(t *testing.T) {
	const fieldID = int64(700)
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}
	empty := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{}}}
	v3 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3.0, 4.0}}}}

	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3, 4}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type:    schemapb.DataType_ArrayOfVector,
				FieldId: fieldID,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: dim,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Dim:         dim,
						Data:        []*schemapb.VectorField{v1, empty, v3, empty},
						ElementType: schemapb.DataType_FloatVector,
					}},
				}},
				ValidData: []bool{true, false, true, false},
			},
		},
	}
	schema := makeNullableSchema(fieldID, schemapb.DataType_ArrayOfVector, dim)
	schema.GetFields()[0].ElementType = schemapb.DataType_FloatVector

	merged, err := buildMergedRetrieveResults(
		[]*internalpb.RetrieveResults{result},
		[]rowRef{{resultIdx: 0, rowIdx: 2}, {resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 0}},
		schema,
	)
	require.NoError(t, err)
	assert.Equal(t, []bool{true, false, true}, merged.FieldsData[0].GetValidData())

	va := merged.FieldsData[0].GetVectors().GetVectorArray()
	require.Len(t, va.GetData(), 3)
	assert.Equal(t, []float32{3.0, 4.0}, va.GetData()[0].GetFloatVector().GetData())
	assert.Empty(t, va.GetData()[1].GetFloatVector().GetData())
	assert.Equal(t, []float32{1.0, 2.0}, va.GetData()[2].GetFloatVector().GetData())
}

// =========================================================================
// sliceVectorField & rangeSliceVectorField: VectorArray branch
// =========================================================================

func TestSliceVectorField_VectorArray(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}
	v2 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3.0, 4.0}}}}
	v3 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{5.0, 6.0}}}}

	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			Data:        []*schemapb.VectorField{v1, v2, v3},
			ElementType: schemapb.DataType_FloatVector,
		}},
	}

	sliced := requireSliceVectorField(t, vf, []int{2, 0}, nil)
	va := sliced.GetVectorArray()
	require.Len(t, va.GetData(), 2)
	assert.Equal(t, []float32{5.0, 6.0}, va.GetData()[0].GetFloatVector().GetData())
	assert.Equal(t, []float32{1.0, 2.0}, va.GetData()[1].GetFloatVector().GetData())
	assert.Equal(t, schemapb.DataType_FloatVector, va.GetElementType())
}

func TestRangeSliceVectorField_VectorArray(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}}}}
	v2 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3.0, 4.0}}}}
	v3 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{5.0, 6.0}}}}

	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			Data:        []*schemapb.VectorField{v1, v2, v3},
			ElementType: schemapb.DataType_FloatVector,
		}},
	}

	sliced := requireRangeSliceVectorField(t, vf, 1, 3, nil)
	va := sliced.GetVectorArray()
	require.Len(t, va.GetData(), 2)
	assert.Equal(t, []float32{3.0, 4.0}, va.GetData()[0].GetFloatVector().GetData())
	assert.Equal(t, []float32{5.0, 6.0}, va.GetData()[1].GetFloatVector().GetData())
}

// =========================================================================
// comparePK: string PK
// =========================================================================

func TestComparePK_StringPK(t *testing.T) {
	assert.Equal(t, -1, comparePK("apple", "banana"))
	assert.Equal(t, 0, comparePK("same", "same"))
	assert.Equal(t, 1, comparePK("zebra", "alpha"))
}

func TestComparePK_Int64PK(t *testing.T) {
	assert.Equal(t, -1, comparePK(int64(1), int64(2)))
	assert.Equal(t, 0, comparePK(int64(5), int64(5)))
	assert.Equal(t, 1, comparePK(int64(10), int64(3)))
}

// =========================================================================
// buildMergedScalarField: additional type branches
// =========================================================================

func TestBuildMergedScalarField_BoolData(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_Bool, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_BoolData{BoolData: &schemapb.BoolArray{Data: []bool{true, false}}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 0}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []bool{false, true}, merged.FieldsData[0].GetScalars().GetBoolData().GetData())
}

func TestBuildMergedScalarField_IntData(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_Int32, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{10, 20}}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []int32{20}, merged.FieldsData[0].GetScalars().GetIntData().GetData())
}

func TestBuildMergedScalarField_FloatData(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1}, &schemapb.FieldData{
		Type: schemapb.DataType_Float, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.5, 2.5}}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []float32{1.5}, merged.FieldsData[0].GetScalars().GetFloatData().GetData())
}

func TestBuildMergedScalarField_DoubleData(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_Double, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: []float64{3.14, 2.71}}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []float64{2.71}, merged.FieldsData[0].GetScalars().GetDoubleData().GetData())
}

func TestBuildMergedScalarField_BytesData(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_BinaryVector, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_BytesData{BytesData: &schemapb.BytesArray{Data: [][]byte{{0x01}, {0x02}}}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, [][]byte{{0x01}, {0x02}}, merged.FieldsData[0].GetScalars().GetBytesData().GetData())
}

func TestBuildMergedScalarField_JsonData(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_JSON, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_JsonData{JsonData: &schemapb.JSONArray{Data: [][]byte{[]byte(`{"a":1}`), []byte(`{"b":2}`)}}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, [][]byte{[]byte(`{"b":2}`)}, merged.FieldsData[0].GetScalars().GetJsonData().GetData())
}

// =========================================================================
// buildMergedIDs: string PK
// =========================================================================

func TestBuildMergedIDs_StringPK(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_StrId{StrId: &schemapb.StringArray{Data: []string{"a", "b"}}}},
		FieldsData: []*schemapb.FieldData{
			makeStringField(100, "pk", []string{"a", "b"}),
		},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 0}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []string{"b", "a"}, merged.GetIds().GetStrId().GetData())
}

// =========================================================================
// buildMergedVectorField: additional vector type branches
// =========================================================================

func TestBuildMergedVectorField_BinaryVector(t *testing.T) {
	dim := 16 // 2 bytes per row
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_BinaryVector, FieldId: 100,
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim:  int64(dim),
			Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xAA, 0xBB, 0xCC, 0xDD}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []byte{0xCC, 0xDD}, merged.FieldsData[0].GetVectors().GetBinaryVector())
}

func TestBuildMergedVectorField_Float16Vector(t *testing.T) {
	dim := 2 // 4 bytes per row (dim*2)
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_Float16Vector, FieldId: 100,
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim:  int64(dim),
			Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []byte{5, 6, 7, 8}, merged.FieldsData[0].GetVectors().GetFloat16Vector())
}

func TestBuildMergedVectorField_BFloat16Vector(t *testing.T) {
	dim := 2
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_BFloat16Vector, FieldId: 100,
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim:  int64(dim),
			Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{10, 20, 30, 40, 50, 60, 70, 80}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, []byte{10, 20, 30, 40}, merged.FieldsData[0].GetVectors().GetBfloat16Vector())
}

func TestBuildMergedVectorField_SparseFloatVector(t *testing.T) {
	r1 := makeInternalResultIntPK([]int64{1, 2}, &schemapb.FieldData{
		Type: schemapb.DataType_SparseFloatVector, FieldId: 100,
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim: 100,
			Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
				Contents: [][]byte{{0x01, 0x02}, {0x03, 0x04}},
				Dim:      100,
			}},
		}},
	})
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.NoError(t, err)
	assert.Equal(t, [][]byte{{0x03, 0x04}}, merged.FieldsData[0].GetVectors().GetSparseFloatVector().GetContents())
}

// =========================================================================
// buildCompactIndices / getVecDataIdx: nullable vector
// =========================================================================

func TestBuildCompactIndices_NullableVector(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_FloatVector, FieldId: 100,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}}},
				}},
				ValidData: []bool{true, false, true}, // row0=valid(idx0), row1=null, row2=valid(idx1)
			},
		},
	}
	indices, err := buildCompactIndices([]*internalpb.RetrieveResults{r1}, 0, true)
	require.NoError(t, err)
	require.NotNil(t, indices)
	assert.Equal(t, []int{0, -1, 1}, indices[0])
}

func TestBuildCompactIndices_NonNullable(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_FloatVector, FieldId: 100,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}}},
				}},
				// No ValidData
			},
		},
	}
	indices, err := buildCompactIndices([]*internalpb.RetrieveResults{r1}, 0, false)
	require.NoError(t, err)
	assert.Nil(t, indices) // non-nullable → nil
}

func TestBuildCompactIndices_FailFast_EmptyValidData(t *testing.T) {
	// nullable field with numRows > 0 but empty ValidData → must error
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_SparseFloatVector, FieldId: 100,
				// ValidData intentionally empty — segcore contract violation
			},
		},
	}
	_, err := buildCompactIndices([]*internalpb.RetrieveResults{r1}, 0, true)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "empty ValidData")
}

func TestBuildCompactIndices_FailFast_LengthMismatch(t *testing.T) {
	// nullable field with len(ValidData) != numRows → must error
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_FloatVector, FieldId: 100,
				ValidData: []bool{true, false}, // 2 entries but 3 rows → mismatch
			},
		},
	}
	_, err := buildCompactIndices([]*internalpb.RetrieveResults{r1}, 0, true)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "len(ValidData)")
}

func TestGetVecDataIdx(t *testing.T) {
	// nil compactIndices → returns rowIdx directly
	assert.Equal(t, 3, getVecDataIdx(nil, rowRef{resultIdx: 0, rowIdx: 3}))

	// With compact indices
	compactIdx := [][]int{
		{0, -1, 1}, // result 0: row0=0, row1=null, row2=1
		nil,        // result 1: non-nullable
	}
	assert.Equal(t, 0, getVecDataIdx(compactIdx, rowRef{resultIdx: 0, rowIdx: 0}))
	assert.Equal(t, -1, getVecDataIdx(compactIdx, rowRef{resultIdx: 0, rowIdx: 1}))
	assert.Equal(t, 1, getVecDataIdx(compactIdx, rowRef{resultIdx: 0, rowIdx: 2}))
	assert.Equal(t, 5, getVecDataIdx(compactIdx, rowRef{resultIdx: 1, rowIdx: 5})) // nil slice → rowIdx

	// Out of range → panics (validated upstream by buildCompactIndices)
	assert.Panics(t, func() { getVecDataIdx(compactIdx, rowRef{resultIdx: 0, rowIdx: 10}) })
}

// =========================================================================
// buildMergedVectorField: truncated data error paths
// =========================================================================

func TestBuildMergedVectorField_FloatVector_TruncatedData(t *testing.T) {
	// FloatVector with dim=2 but only 2 floats (enough for 1 row, not 2)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_FloatVector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  2,
				Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}}, // only 1 row
			}},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}
	schema := &schemapb.CollectionSchema{Fields: []*schemapb.FieldSchema{
		{FieldID: 100, DataType: schemapb.DataType_FloatVector, TypeParams: []*commonpb.KeyValuePair{{Key: "dim", Value: "2"}}},
	}}

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

func TestBuildMergedVectorField_BinaryVector_TruncatedData(t *testing.T) {
	// BinaryVector with dim=16 (2 bytes/row) but only 2 bytes (1 row, not 2)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_BinaryVector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  16,
				Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xFF, 0x00}}, // 1 row
			}},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}
	schema := &schemapb.CollectionSchema{Fields: []*schemapb.FieldSchema{
		{FieldID: 100, DataType: schemapb.DataType_BinaryVector, TypeParams: []*commonpb.KeyValuePair{{Key: "dim", Value: "16"}}},
	}}

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

func TestBuildMergedVectorField_SparseVector_TruncatedContents(t *testing.T) {
	// Sparse with ValidData=[true, true] but Contents has only 1 entry
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_SparseFloatVector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
					Contents: [][]byte{makeTestSparseVec(1, 0.5)}, // only 1 content
				}},
			}},
			ValidData: []bool{true, true}, // claims 2 valid rows
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows,
		makeNullableSchema(100, schemapb.DataType_SparseFloatVector, 0))
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

func TestBuildMergedVectorField_NullableCompact_BinaryVector(t *testing.T) {
	// BinaryVector dim=8 (1 byte/row), nullable: row0=valid, row1=null, row2=valid
	// Compact data: 2 bytes (only valid rows)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_BinaryVector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  8,
				Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xAA, 0xBB}}, // 2 compact rows
			}},
			ValidData: []bool{true, false, true},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 2}, {resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows,
		makeNullableSchema(100, schemapb.DataType_BinaryVector, 8))
	require.NoError(t, err)

	// row2 → compact idx 1 → 0xBB, row0 → compact idx 0 → 0xAA, row1 → null (skipped)
	assert.Equal(t, []byte{0xBB, 0xAA}, merged.FieldsData[0].GetVectors().GetBinaryVector())
	assert.Equal(t, []bool{true, true, false}, merged.FieldsData[0].ValidData)
}

func TestBuildMergedVectorField_NullableCompact_Float16Vector(t *testing.T) {
	// Float16 dim=1 (2 bytes/row), nullable: row0=null, row1=valid
	// Compact data: 2 bytes (1 valid row)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_Float16Vector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  1,
				Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{0x01, 0x02}}, // 1 compact row
			}},
			ValidData: []bool{false, true},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 0}}

	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows,
		makeNullableSchema(100, schemapb.DataType_Float16Vector, 1))
	require.NoError(t, err)

	// row1 → compact idx 0 → [0x01, 0x02], row0 → null (skipped)
	assert.Equal(t, []byte{0x01, 0x02}, merged.FieldsData[0].GetVectors().GetFloat16Vector())
	assert.Equal(t, []bool{true, false}, merged.FieldsData[0].ValidData)
}

func TestBuildMergedVectorField_Float16Vector_TruncatedData(t *testing.T) {
	// Float16 dim=2 (4 bytes/row) but only 4 bytes provided (1 row, not 2)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_Float16Vector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  2,
				Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{0x01, 0x02, 0x03, 0x04}}, // 1 row
			}},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}
	schema := &schemapb.CollectionSchema{Fields: []*schemapb.FieldSchema{
		{FieldID: 100, DataType: schemapb.DataType_Float16Vector, TypeParams: []*commonpb.KeyValuePair{{Key: "dim", Value: "2"}}},
	}}

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

func TestBuildMergedVectorField_NullableCompact_BFloat16Vector(t *testing.T) {
	// BFloat16 dim=1 (2 bytes/row), nullable: row0=valid, row1=null, row2=valid
	// Compact data: 4 bytes (2 valid rows)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_BFloat16Vector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  1,
				Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{0xAA, 0xBB, 0xCC, 0xDD}},
			}},
			ValidData: []bool{true, false, true},
		}},
	}
	// Select row1(null), row2(valid), row0(valid)
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 2}, {resultIdx: 0, rowIdx: 0}}

	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows,
		makeNullableSchema(100, schemapb.DataType_BFloat16Vector, 1))
	require.NoError(t, err)

	// row1 → null (skipped), row2 → compact idx 1 → [0xCC,0xDD], row0 → compact idx 0 → [0xAA,0xBB]
	assert.Equal(t, []byte{0xCC, 0xDD, 0xAA, 0xBB}, merged.FieldsData[0].GetVectors().GetBfloat16Vector())
	assert.Equal(t, []bool{false, true, true}, merged.FieldsData[0].ValidData)
}

func TestBuildMergedVectorField_BFloat16Vector_TruncatedData(t *testing.T) {
	// BFloat16 dim=2 (4 bytes/row) but only 4 bytes (1 row, not 2)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_BFloat16Vector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  2,
				Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{0x01, 0x02, 0x03, 0x04}},
			}},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}
	schema := &schemapb.CollectionSchema{Fields: []*schemapb.FieldSchema{
		{FieldID: 100, DataType: schemapb.DataType_BFloat16Vector, TypeParams: []*commonpb.KeyValuePair{{Key: "dim", Value: "2"}}},
	}}

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

func TestBuildMergedVectorField_NullableCompact_Int8Vector(t *testing.T) {
	// Int8Vector dim=2 (2 bytes/row), nullable: row0=null, row1=valid
	// Compact data: 2 bytes (1 valid row)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_Int8Vector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  2,
				Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{0x11, 0x22}},
			}},
			ValidData: []bool{false, true},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows,
		makeNullableSchema(100, schemapb.DataType_Int8Vector, 2))
	require.NoError(t, err)

	// row0 → null (skipped), row1 → compact idx 0 → [0x11,0x22]
	assert.Equal(t, []byte{0x11, 0x22}, merged.FieldsData[0].GetVectors().GetInt8Vector())
	assert.Equal(t, []bool{false, true}, merged.FieldsData[0].ValidData)
}

func TestBuildMergedVectorField_Int8Vector_TruncatedData(t *testing.T) {
	// Int8Vector dim=3 (3 bytes/row) but only 3 bytes (1 row, not 2)
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_Int8Vector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  3,
				Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{0x01, 0x02, 0x03}},
			}},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}
	schema := &schemapb.CollectionSchema{Fields: []*schemapb.FieldSchema{
		{FieldID: 100, DataType: schemapb.DataType_Int8Vector, TypeParams: []*commonpb.KeyValuePair{{Key: "dim", Value: "3"}}},
	}}

	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, schema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

func TestBuildMergedVectorField_VectorArray_TruncatedData(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{
		FloatVector: &schemapb.FloatArray{Data: []float32{1.0, 2.0}},
	}}

	// Result has 2 IDs but VectorArray has only 1 entry
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100, Type: schemapb.DataType_FloatVector,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim: dim,
				Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
					Dim:         dim,
					Data:        []*schemapb.VectorField{v1}, // only 1 entry
					ElementType: schemapb.DataType_FloatVector,
				}},
			}},
		}},
	}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	// nil schema → fallback infers VectorArray from data
	_, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, nil)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "truncated data")
}

// =========================================================================
// rangeSlice / slice: string IDs
// =========================================================================

func TestRangeSliceIDs_StringID(t *testing.T) {
	ids := &schemapb.IDs{IdField: &schemapb.IDs_StrId{StrId: &schemapb.StringArray{Data: []string{"a", "b", "c", "d"}}}}
	sliced := rangeSliceIDs(ids, 1, 3)
	assert.Equal(t, []string{"b", "c"}, sliced.GetStrId().GetData())
}

func TestSliceIDs_StringID(t *testing.T) {
	ids := &schemapb.IDs{IdField: &schemapb.IDs_StrId{StrId: &schemapb.StringArray{Data: []string{"x", "y", "z"}}}}
	sliced := sliceIDs(ids, []int{2, 0})
	assert.Equal(t, []string{"z", "x"}, sliced.GetStrId().GetData())
}

// =========================================================================
// rangeSliceVectorField: additional vector types
// =========================================================================

func TestRangeSliceVectorField_FloatVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4, 5, 6}}},
	}
	sliced := requireRangeSliceVectorField(t, vf, 1, 3, nil)
	assert.Equal(t, []float32{3, 4, 5, 6}, sliced.GetFloatVector().GetData())
}

func TestRangeSliceVectorField_BinaryVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  16, // 2 bytes per row
		Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}},
	}
	sliced := requireRangeSliceVectorField(t, vf, 0, 2, nil)
	assert.Equal(t, []byte{0xAA, 0xBB, 0xCC, 0xDD}, sliced.GetBinaryVector())
}

func TestRangeSliceVectorField_Float16Vector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2, // 4 bytes per row
		Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
	}
	sliced := requireRangeSliceVectorField(t, vf, 1, 2, nil)
	assert.Equal(t, []byte{5, 6, 7, 8}, sliced.GetFloat16Vector())
}

func TestRangeSliceVectorField_SparseFloatVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim: 100,
		Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
			Contents: [][]byte{{0x01}, {0x02}, {0x03}},
			Dim:      100,
		}},
	}
	sliced := requireRangeSliceVectorField(t, vf, 1, 3, nil)
	assert.Equal(t, [][]byte{{0x02}, {0x03}}, sliced.GetSparseFloatVector().GetContents())
}

// =========================================================================
// sliceVectorField: additional vector types
// =========================================================================

func TestSliceVectorField_FloatVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4, 5, 6}}},
	}
	sliced := requireSliceVectorField(t, vf, []int{2, 0}, nil)
	assert.Equal(t, []float32{5, 6, 1, 2}, sliced.GetFloatVector().GetData())
}

func TestSliceVectorField_BinaryVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  16, // 2 bytes per row
		Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}},
	}
	sliced := requireSliceVectorField(t, vf, []int{2, 0}, nil)
	assert.Equal(t, []byte{0xEE, 0xFF, 0xAA, 0xBB}, sliced.GetBinaryVector())
}

func TestSliceVectorField_Float16Vector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2, // 4 bytes per row
		Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
	}
	sliced := requireSliceVectorField(t, vf, []int{1}, nil)
	assert.Equal(t, []byte{5, 6, 7, 8}, sliced.GetFloat16Vector())
}

func TestSliceVectorField_BFloat16Vector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2, // 4 bytes per row
		Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{10, 20, 30, 40, 50, 60, 70, 80}},
	}
	sliced := requireSliceVectorField(t, vf, []int{1, 0}, nil)
	assert.Equal(t, []byte{50, 60, 70, 80, 10, 20, 30, 40}, sliced.GetBfloat16Vector())
}

func TestSliceVectorField_Int8Vector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  3,
		Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3, 4, 5, 6}},
	}
	sliced := requireSliceVectorField(t, vf, []int{1}, nil)
	assert.Equal(t, []byte{4, 5, 6}, sliced.GetInt8Vector())
}

func TestSliceVectorField_SparseFloatVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim: 100,
		Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
			Contents: [][]byte{{0x01}, {0x02}, {0x03}},
			Dim:      100,
		}},
	}
	sliced := requireSliceVectorField(t, vf, []int{2, 0}, nil)
	assert.Equal(t, [][]byte{{0x03}, {0x01}}, sliced.GetSparseFloatVector().GetContents())
}

// =========================================================================
// rangeSliceFieldData: vector branch
// =========================================================================

func TestRangeSliceFieldData_Vector(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_FloatVector, FieldId: 100, FieldName: "vec",
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim:  2,
			Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4, 5, 6}}},
		}},
	}
	sliced := requireRangeSliceFieldData(t, fd, 1, 3)
	assert.Equal(t, []float32{3, 4, 5, 6}, sliced.GetVectors().GetFloatVector().GetData())
}

func TestRangeSliceFieldData_Nil(t *testing.T) {
	sliced := requireRangeSliceFieldData(t, nil, 0, 1)
	assert.Nil(t, sliced)
}

// =========================================================================
// calcFieldElementSize: various types
// =========================================================================

func TestCalcFieldElementSize(t *testing.T) {
	tests := []struct {
		name     string
		fd       *schemapb.FieldData
		rowIdx   int
		expected int64
	}{
		{
			name: "bool",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_BoolData{BoolData: &schemapb.BoolArray{Data: []bool{true}}},
			}}},
			expected: 1,
		},
		{
			name: "int32",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{42}}},
			}}},
			expected: 4,
		},
		{
			name: "int64",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{42}}},
			}}},
			expected: 8,
		},
		{
			name: "float32",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.0}}},
			}}},
			expected: 4,
		},
		{
			name: "float64",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: []float64{1.0}}},
			}}},
			expected: 8,
		},
		{
			name: "string",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{"hello"}}},
			}}},
			expected: 5,
		},
		{
			name: "json",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_JsonData{JsonData: &schemapb.JSONArray{Data: [][]byte{[]byte(`{"a":1}`)}}},
			}}},
			expected: 7,
		},
		{
			name: "bytes",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_BytesData{BytesData: &schemapb.BytesArray{Data: [][]byte{{0x01, 0x02, 0x03}}}},
			}}},
			expected: 3,
		},
		{
			name: "timestamptz",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_TimestamptzData{TimestamptzData: &schemapb.TimestamptzArray{Data: []int64{1000}}},
			}}},
			expected: 8,
		},
		{
			name: "float_vector",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  4,
				Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}}},
			}}},
			expected: 16, // 4 * 4
		},
		{
			name: "binary_vector",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  16,
				Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0, 0}},
			}}},
			expected: 2, // 16/8
		},
		{
			name: "float16_vector",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  4,
				Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{0, 0, 0, 0, 0, 0, 0, 0}},
			}}},
			expected: 8, // 4*2
		},
		{
			name: "int8_vector",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  3,
				Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3}},
			}}},
			expected: 3,
		},
		{
			name: "sparse_float_vector",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim: 100,
				Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
					Contents: [][]byte{{0x01, 0x02, 0x03, 0x04}},
					Dim:      100,
				}},
			}}},
			expected: 4,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.expected, calcFieldElementSize(tt.fd, tt.rowIdx))
		})
	}
}

// =========================================================================
// getFieldValue: various types
// =========================================================================

func TestGetFieldValue(t *testing.T) {
	tests := []struct {
		name     string
		fd       *schemapb.FieldData
		rowIdx   int
		expected any
		isNull   bool
	}{
		{
			name: "bool",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_BoolData{BoolData: &schemapb.BoolArray{Data: []bool{true, false}}},
			}}},
			rowIdx: 1, expected: false,
		},
		{
			name: "int32",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{10, 20}}},
			}}},
			rowIdx: 0, expected: int32(10),
		},
		{
			name: "float32",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.5}}},
			}}},
			rowIdx: 0, expected: float32(1.5),
		},
		{
			name: "float64",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: []float64{3.14}}},
			}}},
			rowIdx: 0, expected: float64(3.14),
		},
		{
			name: "nullable_null",
			fd: &schemapb.FieldData{
				Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{99}}},
				}},
				ValidData: []bool{false},
			},
			rowIdx: 0, expected: nil, isNull: true,
		},
		{
			name:   "nil_scalars",
			fd:     &schemapb.FieldData{},
			rowIdx: 0, expected: nil, isNull: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			val, isNull := getFieldValue(tt.fd, tt.rowIdx)
			assert.Equal(t, tt.isNull, isNull)
			if !tt.isNull {
				assert.Equal(t, tt.expected, val)
			}
		})
	}
}

// =========================================================================
// getRowCount: various types
// =========================================================================

func TestGetRowCount(t *testing.T) {
	tests := []struct {
		name     string
		result   *internalpb.RetrieveResults
		expected int
	}{
		{
			name:     "from IDs",
			result:   makeInternalResultIntPK([]int64{1, 2, 3}),
			expected: 3,
		},
		{
			name: "from bool field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_BoolData{BoolData: &schemapb.BoolArray{Data: []bool{true, false}}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "from int32 field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{1, 2, 3}}},
				}}},
			}},
			expected: 3,
		},
		{
			name: "from float field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.0}}},
				}}},
			}},
			expected: 1,
		},
		{
			name: "from double field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: []float64{1.0, 2.0}}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "from json field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_JsonData{JsonData: &schemapb.JSONArray{Data: [][]byte{[]byte(`{}`)}}},
				}}},
			}},
			expected: 1,
		},
		{
			name: "from float vector",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4, 5, 6}}},
				}}},
			}},
			expected: 3,
		},
		{
			name: "from binary vector",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  16,
					Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0, 0, 0, 0}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "from sparse float vector",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: 100,
					Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
						Contents: [][]byte{{0x01}, {0x02}},
					}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "from struct array",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				makeStructArrayFieldData(100, "info", []*schemapb.FieldData{
					makeInt64Field(101, "age", []int64{10, 20, 30}),
				}),
			}},
			expected: 3,
		},
		{
			name:     "empty",
			result:   &internalpb.RetrieveResults{},
			expected: 0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.expected, getRowCount(tt.result))
		})
	}
}

// =========================================================================
// compareValues: various types
// =========================================================================

func TestCompareValues(t *testing.T) {
	tests := []struct {
		name     string
		a, b     any
		dataType schemapb.DataType
		expected int
	}{
		{"bool_lt", false, true, schemapb.DataType_Bool, -1},
		{"bool_gt", true, false, schemapb.DataType_Bool, 1},
		{"bool_eq", true, true, schemapb.DataType_Bool, 0},
		{"int32_lt", int32(1), int32(2), schemapb.DataType_Int32, -1},
		{"int32_gt", int32(5), int32(3), schemapb.DataType_Int32, 1},
		{"int32_eq", int32(7), int32(7), schemapb.DataType_Int32, 0},
		{"int64_lt", int64(10), int64(20), schemapb.DataType_Int64, -1},
		{"int64_eq", int64(5), int64(5), schemapb.DataType_Int64, 0},
		{"float32_lt", float32(1.0), float32(2.0), schemapb.DataType_Float, -1},
		{"float32_gt", float32(3.0), float32(1.0), schemapb.DataType_Float, 1},
		{"float32_eq", float32(1.5), float32(1.5), schemapb.DataType_Float, 0},
		{"float64_lt", float64(1.0), float64(2.0), schemapb.DataType_Double, -1},
		{"float64_gt", float64(9.0), float64(1.0), schemapb.DataType_Double, 1},
		{"float64_eq", float64(3.14), float64(3.14), schemapb.DataType_Double, 0},
		{"string_lt", "apple", "banana", schemapb.DataType_VarChar, -1},
		{"string_gt", "zebra", "alpha", schemapb.DataType_VarChar, 1},
		{"string_eq", "same", "same", schemapb.DataType_VarChar, 0},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.expected, compareValues(tt.a, tt.b, tt.dataType))
		})
	}
}

// =========================================================================
// rangeSliceScalarField / sliceScalarField: more type branches
// =========================================================================

func TestRangeSliceScalarField_AllTypes(t *testing.T) {
	tests := []struct {
		name  string
		sf    *schemapb.ScalarField
		check func(t *testing.T, sf *schemapb.ScalarField)
	}{
		{
			name: "bool",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_BoolData{BoolData: &schemapb.BoolArray{Data: []bool{true, false, true}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, []bool{false}, sf.GetBoolData().GetData())
			},
		},
		{
			name: "int32",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{10, 20, 30}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, []int32{20}, sf.GetIntData().GetData())
			},
		},
		{
			name: "float",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_FloatData{FloatData: &schemapb.FloatArray{Data: []float32{1.0, 2.0, 3.0}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, []float32{2.0}, sf.GetFloatData().GetData())
			},
		},
		{
			name: "double",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_DoubleData{DoubleData: &schemapb.DoubleArray{Data: []float64{1.0, 2.0, 3.0}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, []float64{2.0}, sf.GetDoubleData().GetData())
			},
		},
		{
			name: "bytes",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_BytesData{BytesData: &schemapb.BytesArray{Data: [][]byte{{1}, {2}, {3}}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, [][]byte{{2}}, sf.GetBytesData().GetData())
			},
		},
		{
			name: "json",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_JsonData{JsonData: &schemapb.JSONArray{Data: [][]byte{[]byte(`{}`), []byte(`[]`), []byte(`""`)}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, [][]byte{[]byte(`[]`)}, sf.GetJsonData().GetData())
			},
		},
		{
			name: "timestamptz",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_TimestamptzData{TimestamptzData: &schemapb.TimestamptzArray{Data: []int64{100, 200, 300}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, []int64{200}, sf.GetTimestamptzData().GetData())
			},
		},
		{
			name: "mol",
			sf:   &schemapb.ScalarField{Data: &schemapb.ScalarField_MolData{MolData: &schemapb.MolArray{Data: [][]byte{{0xAA}, {0xBB}, {0xCC}}}}},
			check: func(t *testing.T, sf *schemapb.ScalarField) {
				assert.Equal(t, [][]byte{{0xBB}}, sf.GetMolData().GetData())
			},
		},
	}

	for _, tt := range tests {
		t.Run("rangeSlice_"+tt.name, func(t *testing.T) {
			sliced := rangeSliceScalarField(tt.sf, 1, 2)
			tt.check(t, sliced)
		})
		t.Run("slice_"+tt.name, func(t *testing.T) {
			sliced := sliceScalarField(tt.sf, []int{1})
			tt.check(t, sliced)
		})
	}
}

// =========================================================================
// rangeSliceVectorField: more vector types
// =========================================================================

func TestRangeSliceVectorField_BFloat16(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{10, 20, 30, 40, 50, 60, 70, 80}},
	}
	sliced := requireRangeSliceVectorField(t, vf, 1, 2, nil)
	assert.Equal(t, []byte{50, 60, 70, 80}, sliced.GetBfloat16Vector())
}

func TestRangeSliceVectorField_Int8(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  3,
		Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3, 4, 5, 6}},
	}
	sliced := requireRangeSliceVectorField(t, vf, 0, 1, nil)
	assert.Equal(t, []byte{1, 2, 3}, sliced.GetInt8Vector())
}

// =========================================================================
// getRowCount: additional vector + scalar types
// =========================================================================

func TestGetRowCount_AdditionalTypes(t *testing.T) {
	tests := []struct {
		name     string
		result   *internalpb.RetrieveResults
		expected int
	}{
		{
			name: "string field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{"a", "b"}}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "array field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_ArrayData{ArrayData: &schemapb.ArrayArray{Data: []*schemapb.ScalarField{nil, nil, nil}}},
				}}},
			}},
			expected: 3,
		},
		{
			name: "geometry wkt field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{Data: []string{"POINT(0 0)"}}},
				}}},
			}},
			expected: 1,
		},
		{
			name: "timestamptz field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_TimestamptzData{TimestamptzData: &schemapb.TimestamptzArray{Data: []int64{1, 2}}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "mol field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_MolData{MolData: &schemapb.MolArray{Data: [][]byte{{1}}}},
				}}},
			}},
			expected: 1,
		},
		{
			name: "float16 vector",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "bfloat16 vector",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{1, 2, 3, 4}},
				}}},
			}},
			expected: 1,
		},
		{
			name: "int8 vector",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  3,
					Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3, 4, 5, 6}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "vector array",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim: 2,
					Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
						Data: []*schemapb.VectorField{nil, nil},
					}},
				}}},
			}},
			expected: 2,
		},
		{
			name: "geometry field",
			result: &internalpb.RetrieveResults{FieldsData: []*schemapb.FieldData{
				{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
					Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{Data: [][]byte{{1}, {2}}}},
				}}},
			}},
			expected: 2,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.expected, getRowCount(tt.result))
		})
	}
}

// =========================================================================
// calcFieldElementSize: remaining branches (geometry, array, mol, vectorArray)
// =========================================================================

func TestCalcFieldElementSize_RemainingBranches(t *testing.T) {
	tests := []struct {
		name     string
		fd       *schemapb.FieldData
		rowIdx   int
		expected int64
	}{
		{
			name: "geometry_data",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{Data: [][]byte{{1, 2, 3}}}},
			}}},
			expected: 3,
		},
		{
			name: "geometry_wkt_data",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{Data: []string{"POINT(0 0)"}}},
			}}},
			expected: 10,
		},
		{
			name: "mol_data",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_MolData{MolData: &schemapb.MolArray{Data: [][]byte{{0xAA, 0xBB}}}},
			}}},
			expected: 2,
		},
		{
			name: "array_data",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
				Data: &schemapb.ScalarField_ArrayData{ArrayData: &schemapb.ArrayArray{
					Data: []*schemapb.ScalarField{
						{Data: &schemapb.ScalarField_IntData{IntData: &schemapb.IntArray{Data: []int32{1, 2}}}},
					},
					ElementType: schemapb.DataType_Int32,
				}},
			}}},
			expected: 10, // proto.Size of the ScalarField
		},
		{
			name: "bfloat16_vector",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim:  4,
				Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{0, 0, 0, 0, 0, 0, 0, 0}},
			}}},
			expected: 8, // 4*2
		},
		{
			name: "vector_array",
			fd: &schemapb.FieldData{Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Dim: 2,
				Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
					Data: []*schemapb.VectorField{
						{Dim: 2, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}}},
					},
				}},
			}}},
		},
		{
			name:     "nil_field",
			fd:       &schemapb.FieldData{},
			expected: 0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := calcFieldElementSize(tt.fd, tt.rowIdx)
			switch tt.name {
			case "vector_array":
				assert.True(t, result > 0, "vector_array size should be > 0")
			case "array_data":
				assert.True(t, result > 0, "array_data size should be > 0")
			default:
				assert.Equal(t, tt.expected, result)
			}
		})
	}
}

// =========================================================================
// sliceFieldData / rangeSliceFieldData: vector + structArray branches
// =========================================================================

func TestSliceFieldData_Vector(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_FloatVector, FieldId: 100,
		Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
			Dim:  2,
			Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4, 5, 6}}},
		}},
	}
	sliced := requireSliceFieldData(t, fd, []int{2, 0})
	assert.Equal(t, []float32{5, 6, 1, 2}, sliced.GetVectors().GetFloatVector().GetData())
}

func TestSliceFieldData_NilOrEmpty(t *testing.T) {
	sliced := requireSliceFieldData(t, nil, []int{0})
	assert.Nil(t, sliced)
	sliced = requireSliceFieldData(t, &schemapb.FieldData{}, nil)
	assert.Nil(t, sliced)
}

func TestSliceFieldData_ValidData(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Int64, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20, 30}}},
		}},
		ValidData: []bool{true, false, true},
	}
	sliced := requireSliceFieldData(t, fd, []int{2, 0})
	assert.Equal(t, []bool{true, true}, sliced.GetValidData())
}

func TestRangeSliceFieldData_ValidData(t *testing.T) {
	fd := &schemapb.FieldData{
		Type: schemapb.DataType_Int64, FieldId: 100,
		Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
			Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{10, 20, 30}}},
		}},
		ValidData: []bool{true, false, true},
	}
	sliced := requireRangeSliceFieldData(t, fd, 0, 2)
	assert.Equal(t, []bool{true, false}, sliced.GetValidData())
}

// =========================================================================
// sliceScalarField: remaining branches (geometry, geometryWkt)
// =========================================================================

func TestSliceScalarField_GeometryData(t *testing.T) {
	sf := &schemapb.ScalarField{
		Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{Data: [][]byte{{1}, {2}, {3}}}},
	}
	sliced := sliceScalarField(sf, []int{2, 0})
	assert.Equal(t, [][]byte{{3}, {1}}, sliced.GetGeometryData().GetData())
}

func TestSliceScalarField_GeometryWktData(t *testing.T) {
	sf := &schemapb.ScalarField{
		Data: &schemapb.ScalarField_GeometryWktData{GeometryWktData: &schemapb.GeometryWktArray{Data: []string{"P1", "P2", "P3"}}},
	}
	sliced := sliceScalarField(sf, []int{1})
	assert.Equal(t, []string{"P2"}, sliced.GetGeometryWktData().GetData())
}

// =========================================================================
// rangeSliceScalarField: remaining branches (geometry)
// =========================================================================

func TestRangeSliceScalarField_GeometryData(t *testing.T) {
	sf := &schemapb.ScalarField{
		Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{Data: [][]byte{{1}, {2}, {3}}}},
	}
	sliced := rangeSliceScalarField(sf, 0, 2)
	assert.Equal(t, [][]byte{{1}, {2}}, sliced.GetGeometryData().GetData())
}

// =========================================================================
// sliceVectorField / rangeSliceVectorField: nullable compact mode branches
// =========================================================================

func TestSliceVectorField_NullableCompact(t *testing.T) {
	// 3 logical rows, but only 2 valid rows in compact data
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}}}, // 2 valid rows
	}
	validData := []bool{true, false, true} // row0=valid(data0), row1=null, row2=valid(data1)

	sliced := requireSliceVectorField(t, vf, []int{2, 0}, validData)
	assert.Equal(t, []float32{3, 4, 1, 2}, sliced.GetFloatVector().GetData())
}

func TestSliceVectorField_NullableCompact_BinaryVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  16,                                                                               // 2 bytes per row
		Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xAA, 0xBB, 0xCC, 0xDD}}, // 2 valid rows
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{2, 0}, validData)
	assert.Equal(t, []byte{0xCC, 0xDD, 0xAA, 0xBB}, sliced.GetBinaryVector())
}

func TestSliceVectorField_NullableCompact_Float16(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2, // 4 bytes per row
		Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{0}, validData)
	assert.Equal(t, []byte{1, 2, 3, 4}, sliced.GetFloat16Vector())
}

func TestSliceVectorField_NullableCompact_BFloat16(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{10, 20, 30, 40, 50, 60, 70, 80}},
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{2}, validData)
	assert.Equal(t, []byte{50, 60, 70, 80}, sliced.GetBfloat16Vector())
}

func TestSliceVectorField_NullableCompact_Int8(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  3,
		Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3, 4, 5, 6}},
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{2}, validData)
	assert.Equal(t, []byte{4, 5, 6}, sliced.GetInt8Vector())
}

func TestSliceVectorField_NullableCompact_Sparse(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim: 100,
		Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
			Contents: [][]byte{{0x01}, {0x02}}, // 2 valid rows
			Dim:      100,
		}},
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{2}, validData)
	assert.Equal(t, [][]byte{{0x02}}, sliced.GetSparseFloatVector().GetContents())
}

func TestSliceVectorField_NullableRowDense_VectorArray_SelectValidRow(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}}}
	empty := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{}}}
	v2 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3, 4}}}}

	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			Data:        []*schemapb.VectorField{v1, empty, v2},
			ElementType: schemapb.DataType_FloatVector,
		}},
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{2}, validData)
	assert.Len(t, sliced.GetVectorArray().GetData(), 1)
	assert.Equal(t, []float32{3, 4}, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())
}

func TestSliceVectorField_NullableRowDense_VectorArray_PreservesNullPlaceholders(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}}}
	empty := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{}}}
	v3 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3, 4}}}}

	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			Data:        []*schemapb.VectorField{v1, empty, v3},
			ElementType: schemapb.DataType_FloatVector,
		}},
	}
	validData := []bool{true, false, true}

	sliced := requireSliceVectorField(t, vf, []int{2, 1, 0}, validData)
	require.Len(t, sliced.GetVectorArray().GetData(), 3)
	assert.Equal(t, []float32{3, 4}, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())
	assert.Empty(t, sliced.GetVectorArray().GetData()[1].GetFloatVector().GetData())
	assert.Equal(t, []float32{1, 2}, sliced.GetVectorArray().GetData()[2].GetFloatVector().GetData())
}

func TestSliceVectorField_NullableRowDense_VectorArray_AllNullNoData(t *testing.T) {
	dim := int64(2)
	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			ElementType: schemapb.DataType_FloatVector,
		}},
	}
	validData := []bool{false}

	sliced := requireSliceVectorField(t, vf, []int{0}, validData)
	require.Len(t, sliced.GetVectorArray().GetData(), 1)
	assert.Empty(t, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())
}

func TestSliceVectorField_NullableRowDense_VectorArray_UnsupportedElementTypeReturnsError(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim: 2,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         2,
			ElementType: schemapb.DataType_None,
		}},
	}

	sliced, err := sliceVectorField(vf, []int{0}, []bool{false})
	require.Error(t, err)
	require.Nil(t, sliced)
	assert.Contains(t, err.Error(), "unsupported ArrayOfVector element type")
}

func TestSliceVectorField_NullableCompact_SkipNull(t *testing.T) {
	// Select a null row — it should be skipped
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}},
	}
	validData := []bool{true, false}

	sliced := requireSliceVectorField(t, vf, []int{1}, validData) // row 1 is null
	assert.Empty(t, sliced.GetFloatVector().GetData())
}

func TestRangeSliceVectorField_NullableCompact(t *testing.T) {
	// 3 logical rows: valid, null, valid → 2 data entries in compact mode
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}}},
	}
	validData := []bool{true, false, true}

	// Range [0, 2) = logical row 0 and 1. Row 0 is valid(data0), row 1 is null → only data0
	sliced := requireRangeSliceVectorField(t, vf, 0, 2, validData)
	assert.Equal(t, []float32{1, 2}, sliced.GetFloatVector().GetData())
}

func TestRangeSliceVectorField_NullableCompact_BinaryVector(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  16,
		Data: &schemapb.VectorField_BinaryVector{BinaryVector: []byte{0xAA, 0xBB, 0xCC, 0xDD}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 0, 2, validData)
	assert.Equal(t, []byte{0xAA, 0xBB}, sliced.GetBinaryVector())
}

func TestRangeSliceVectorField_NullableCompact_Float16(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_Float16Vector{Float16Vector: []byte{1, 2, 3, 4, 5, 6, 7, 8}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 2, 3, validData)
	assert.Equal(t, []byte{5, 6, 7, 8}, sliced.GetFloat16Vector())
}

func TestRangeSliceVectorField_NullableCompact_BFloat16(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  2,
		Data: &schemapb.VectorField_Bfloat16Vector{Bfloat16Vector: []byte{10, 20, 30, 40, 50, 60, 70, 80}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 0, 1, validData)
	assert.Equal(t, []byte{10, 20, 30, 40}, sliced.GetBfloat16Vector())
}

func TestRangeSliceVectorField_NullableCompact_Int8(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim:  3,
		Data: &schemapb.VectorField_Int8Vector{Int8Vector: []byte{1, 2, 3, 4, 5, 6}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 2, 3, validData)
	assert.Equal(t, []byte{4, 5, 6}, sliced.GetInt8Vector())
}

func TestRangeSliceVectorField_NullableCompact_Sparse(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim: 100,
		Data: &schemapb.VectorField_SparseFloatVector{SparseFloatVector: &schemapb.SparseFloatArray{
			Contents: [][]byte{{0x01}, {0x02}},
			Dim:      100,
		}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 2, 3, validData)
	assert.Equal(t, [][]byte{{0x02}}, sliced.GetSparseFloatVector().GetContents())
}

func TestRangeSliceVectorField_NullableRowDense_VectorArray_SelectPrefix(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}}}
	empty := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{}}}
	v2 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3, 4}}}}

	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			Data:        []*schemapb.VectorField{v1, empty, v2},
			ElementType: schemapb.DataType_FloatVector,
		}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 0, 1, validData)
	assert.Len(t, sliced.GetVectorArray().GetData(), 1)
	assert.Equal(t, []float32{1, 2}, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())
}

func TestRangeSliceVectorField_NullableRowDense_VectorArray_PreservesNullPlaceholders(t *testing.T) {
	dim := int64(2)
	v1 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2}}}}
	empty := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{}}}
	v3 := &schemapb.VectorField{Dim: dim, Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{3, 4}}}}

	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			Data:        []*schemapb.VectorField{v1, empty, v3},
			ElementType: schemapb.DataType_FloatVector,
		}},
	}
	validData := []bool{true, false, true}

	sliced := requireRangeSliceVectorField(t, vf, 2, 3, validData)
	require.Len(t, sliced.GetVectorArray().GetData(), 1)
	assert.Equal(t, []float32{3, 4}, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())

	sliced = requireRangeSliceVectorField(t, vf, 0, 3, validData)
	require.Len(t, sliced.GetVectorArray().GetData(), 3)
	assert.Equal(t, []float32{1, 2}, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())
	assert.Empty(t, sliced.GetVectorArray().GetData()[1].GetFloatVector().GetData())
	assert.Equal(t, []float32{3, 4}, sliced.GetVectorArray().GetData()[2].GetFloatVector().GetData())
}

func TestRangeSliceVectorField_NullableRowDense_VectorArray_AllNullNoData(t *testing.T) {
	dim := int64(2)
	vf := &schemapb.VectorField{
		Dim: dim,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         dim,
			ElementType: schemapb.DataType_FloatVector,
		}},
	}
	validData := []bool{false, false}

	sliced := requireRangeSliceVectorField(t, vf, 0, 2, validData)
	require.Len(t, sliced.GetVectorArray().GetData(), 2)
	assert.Empty(t, sliced.GetVectorArray().GetData()[0].GetFloatVector().GetData())
	assert.Empty(t, sliced.GetVectorArray().GetData()[1].GetFloatVector().GetData())
}

func TestRangeSliceVectorField_NullableRowDense_VectorArray_UnsupportedElementTypeReturnsError(t *testing.T) {
	vf := &schemapb.VectorField{
		Dim: 2,
		Data: &schemapb.VectorField_VectorArray{VectorArray: &schemapb.VectorArray{
			Dim:         2,
			ElementType: schemapb.DataType_None,
		}},
	}

	sliced, err := rangeSliceVectorField(vf, 0, 1, []bool{false})
	require.Error(t, err)
	require.Nil(t, sliced)
	assert.Contains(t, err.Error(), "unsupported ArrayOfVector element type")
}

// =========================================================================
// buildMergedVectorField: nullable compact mode — null row skip
// =========================================================================

func TestBuildMergedVectorField_NullableCompact_FloatVector(t *testing.T) {
	// FloatVector dim=2, nullable: row0=valid(compact idx 0), row1=null, row2=valid(compact idx 1)
	// Compact data: [1,2, 3,4] — 2 valid rows only
	r1 := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		FieldsData: []*schemapb.FieldData{
			{
				Type: schemapb.DataType_FloatVector, FieldId: 100,
				Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
					Dim:  2,
					Data: &schemapb.VectorField_FloatVector{FloatVector: &schemapb.FloatArray{Data: []float32{1, 2, 3, 4}}},
				}},
				ValidData: []bool{true, false, true},
			},
		},
	}
	// Include the null row (row1) in selectedRows to exercise the di < 0 skip path
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 2}, {resultIdx: 0, rowIdx: 1}, {resultIdx: 0, rowIdx: 0}}
	merged, err := buildMergedRetrieveResults([]*internalpb.RetrieveResults{r1}, selectedRows, makeNullableSchema(100, schemapb.DataType_FloatVector, 2))
	require.NoError(t, err)
	// row2 → compact idx 1 → [3,4], row1 → null (skipped), row0 → compact idx 0 → [1,2]
	assert.Equal(t, []float32{3, 4, 1, 2}, merged.FieldsData[0].GetVectors().GetFloatVector().GetData())
	assert.Equal(t, []bool{true, false, true}, merged.FieldsData[0].ValidData)
}

// =========================================================================
// getFieldValue: remaining branches (string, out-of-range)
// =========================================================================

func TestGetFieldValue_String(t *testing.T) {
	fd := &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
		Data: &schemapb.ScalarField_StringData{StringData: &schemapb.StringArray{Data: []string{"hello", "world"}}},
	}}}
	val, isNull := getFieldValue(fd, 1)
	assert.False(t, isNull)
	assert.Equal(t, "world", val)
}

func TestGetFieldValue_OutOfRange(t *testing.T) {
	fd := &schemapb.FieldData{Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{
		Data: &schemapb.ScalarField_LongData{LongData: &schemapb.LongArray{Data: []int64{1}}},
	}}}
	_, isNull := getFieldValue(fd, 5) // out of range
	assert.True(t, isNull)
}

// =========================================================================
// rangeSliceRetrieveResults: element-level metadata propagation
// =========================================================================

func TestRangeSliceRetrieveResults_EmptyRange(t *testing.T) {
	result := &internalpb.RetrieveResults{
		Ids: &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
	}
	sliced := requireRangeSliceRetrieveResults(t, result, 1, 1) // start == end
	assert.Nil(t, sliced.GetIds())
}

func TestRangeSliceRetrieveResults_ElementLevel(t *testing.T) {
	result := &internalpb.RetrieveResults{
		Ids:          &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2, 3}}}},
		ElementLevel: true,
		ElementIndices: []*internalpb.ElementIndices{
			{Indices: []int32{0}},
			{Indices: []int32{1, 2}},
			{Indices: []int32{3}},
		},
		FieldsData: []*schemapb.FieldData{
			makeInt64Field(100, "val", []int64{10, 20, 30}),
		},
	}
	sliced := requireRangeSliceRetrieveResults(t, result, 1, 3)
	assert.True(t, sliced.GetElementLevel())
	assert.Len(t, sliced.GetElementIndices(), 2)
	assert.Equal(t, []int32{1, 2}, sliced.GetElementIndices()[0].GetIndices())
}

func TestValidateElementLevelConsistency_InconsistentFlag(t *testing.T) {
	r1 := &internalpb.RetrieveResults{
		ElementLevel:   true,
		Ids:            &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1}}}},
		ElementIndices: []*internalpb.ElementIndices{{Indices: []int32{0}}},
	}
	r2 := &internalpb.RetrieveResults{
		ElementLevel: false,
		Ids:          &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{2}}}},
	}
	err := validateElementLevelConsistency([]*internalpb.RetrieveResults{r1, r2}, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "inconsistent element-level flag")
}

func TestValidateElementLevelConsistency_LengthMismatch(t *testing.T) {
	r := &internalpb.RetrieveResults{
		Ids:            &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: []int64{1, 2}}}},
		ElementLevel:   true,
		ElementIndices: []*internalpb.ElementIndices{{Indices: []int32{0}}}, // 1 != 2 ids
	}
	err := validateElementLevelConsistency([]*internalpb.RetrieveResults{r}, nil)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "element_indices length")
}

// =========================================================================
// Nullable vector / scalar merge correctness tests
// =========================================================================

// makeTestIntIDs is a helper to build IDs for test results.
func makeTestIntIDs(ids ...int64) *schemapb.IDs {
	return &schemapb.IDs{IdField: &schemapb.IDs_IntId{IntId: &schemapb.LongArray{Data: ids}}}
}

// makeTestSparseVec builds a knowhere sparse vector binary: [dim uint32][val float32], little-endian.
func makeTestSparseVec(dim uint32, val float32) []byte {
	b := make([]byte, 8)
	binary.LittleEndian.PutUint32(b[0:4], dim)
	binary.LittleEndian.PutUint32(b[4:8], math.Float32bits(val))
	return b
}

// TestBuildMergedVectorField_NullableSparseVector_AllNull_EmptyValidData validates Bug 1 fix:
// when a nullable sparse vector field has empty ValidData + empty Contents, merge must not panic,
// and the merged output must correctly mark those rows as null (ValidData=false).
func TestBuildMergedVectorField_NullableSparse_RejectsEmptyValidData(t *testing.T) {
	sparseSchema := makeNullableSchema(100, schemapb.DataType_SparseFloatVector, 0)

	// rA: 1 row, has valid data
	rA := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(1),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{
						Contents: [][]byte{makeTestSparseVec(1, 0.5)},
					},
				},
			}},
			ValidData: []bool{true},
		}},
	}

	// rB: 1 row, ValidData absent, Contents absent (segcore get_vector early return).
	// This is now a contract violation: nullable field with numRows > 0 must have ValidData.
	// The old code silently treated this as "all null"; the new code fails fast.
	rB := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(2),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{Contents: nil},
				},
			}},
			ValidData: nil,
		}},
	}

	results := []*internalpb.RetrieveResults{rA, rB}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 1, rowIdx: 0}}

	_, err := buildMergedRetrieveResults(results, selectedRows, sparseSchema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "empty ValidData")
}

// TestBuildMergedVectorField_NullableSparse_RejectsMultipleRowsWithEmptyValidData validates that
// multiple rows from a result with absent ValidData trigger fail-fast error.
func TestBuildMergedVectorField_NullableSparse_RejectsMultipleRowsWithEmptyValidData(t *testing.T) {
	sparseSchema := makeNullableSchema(100, schemapb.DataType_SparseFloatVector, 0)

	rA := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(1),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{
						Contents: [][]byte{makeTestSparseVec(1, 0.1)},
					},
				},
			}},
			ValidData: []bool{true},
		}},
	}

	rB := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(2, 3),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{Contents: nil},
				},
			}},
			ValidData: nil,
		}},
	}

	results := []*internalpb.RetrieveResults{rA, rB}
	selectedRows := []rowRef{
		{resultIdx: 0, rowIdx: 0},
		{resultIdx: 1, rowIdx: 0},
		{resultIdx: 1, rowIdx: 1},
	}

	// rB has 2 rows but no ValidData → contract violation, must error
	_, err := buildMergedRetrieveResults(results, selectedRows, sparseSchema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "empty ValidData")
}

// TestBuildMergedVectorField_NullableSparseVector_AllNullWithValidData validates compact path
// when ValidData is present and all false (explicit all-null).
func TestBuildMergedVectorField_NullableSparseVector_AllNullWithValidData(t *testing.T) {
	sparseSchema := makeNullableSchema(100, schemapb.DataType_SparseFloatVector, 0)
	r := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(1, 2),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{Contents: nil},
				},
			}},
			ValidData: []bool{false, false},
		}},
	}
	results := []*internalpb.RetrieveResults{r}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, sparseSchema)
	require.NoError(t, err)
	assert.Equal(t, []bool{false, false}, merged.FieldsData[0].ValidData)
	assert.Empty(t, merged.FieldsData[0].GetVectors().GetSparseFloatVector().GetContents())
}

// TestBuildMergedVectorField_NullableSparseVector_Mixed validates compact index mapping when
// some rows are valid and some are null within the same result.
func TestBuildMergedVectorField_NullableSparseVector_Mixed(t *testing.T) {
	sparseSchema := makeNullableSchema(100, schemapb.DataType_SparseFloatVector, 0)
	// 3 rows: ValidData=[true,false,true], Contents=[vec0, vec2] (compact)
	r := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(1, 2, 3),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{
						Contents: [][]byte{makeTestSparseVec(1, 0.1), makeTestSparseVec(3, 0.3)},
					},
				},
			}},
			ValidData: []bool{true, false, true},
		}},
	}
	results := []*internalpb.RetrieveResults{r}
	// Select row 0 (valid) and row 1 (null)
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 0, rowIdx: 1}}

	merged, err := buildMergedRetrieveResults(results, selectedRows, sparseSchema)
	require.NoError(t, err)
	assert.Equal(t, []bool{true, false}, merged.FieldsData[0].ValidData)
	// Only 1 non-null row in output
	assert.Len(t, merged.FieldsData[0].GetVectors().GetSparseFloatVector().GetContents(), 1)
}

// TestBuildMergedFieldData_NullableScalar_EmptyValidData_FailFast validates that
// a nullable field with rows but absent ValidData triggers a fail-fast error,
// not a silent fallback to all-null. This catches segcore contract violations
// early instead of letting them propagate to downstream panics.
func TestBuildMergedVectorField_NullableVector_RejectsEmptyValidData(t *testing.T) {
	// Note: buildCompactIndices only validates vector fields. For scalar fields,
	// the ValidData check is still lenient (scalar fields are not compacted).
	// This test uses a vector schema to trigger the vector-path validation.
	sparseSchema := makeNullableSchema(100, schemapb.DataType_SparseFloatVector, 0)

	rA := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(1),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{
						Contents: [][]byte{makeTestSparseVec(1, 0.5)},
					},
				},
			}},
			ValidData: []bool{true},
		}},
	}
	// rB: ValidData absent → contract violation for nullable vector
	rB := &internalpb.RetrieveResults{
		Ids: makeTestIntIDs(2),
		FieldsData: []*schemapb.FieldData{{
			FieldId: 100,
			Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{
				Data: &schemapb.VectorField_SparseFloatVector{
					SparseFloatVector: &schemapb.SparseFloatArray{Contents: nil},
				},
			}},
			ValidData: nil,
		}},
	}

	results := []*internalpb.RetrieveResults{rA, rB}
	selectedRows := []rowRef{{resultIdx: 0, rowIdx: 0}, {resultIdx: 1, rowIdx: 0}}

	_, err := buildMergedRetrieveResults(results, selectedRows, sparseSchema)
	require.Error(t, err)
	assert.Contains(t, err.Error(), "empty ValidData")
}
