Files
wehub-resource-sync 498b235461
Build and test / Build and test AMD64 Ubuntu 22.04 (push) Failing after 0s
Publish Builder / amazonlinux2023 (push) Failing after 1s
Build and test / UT for Go (push) Has been skipped
Publish KRTE Images / KRTE (push) Failing after 1s
Build and test / Integration Test (push) Has been skipped
Build and test / Upload Code Coverage (push) Has been skipped
Publish Builder / rockylinux9 (push) Failing after 1s
Publish Builder / ubuntu22.04 (push) Failing after 0s
Publish Builder / ubuntu24.04 (push) Failing after 0s
Publish Gpu Builder / publish-gpu-builder (push) Failing after 1s
Publish Test Images / PyTest (push) Failing after 0s
Build and test / UT for Cpp (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:31:17 +08:00

116 lines
3.6 KiB
Go

/*
* 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 tasks
import (
"strconv"
"github.com/apache/arrow/go/v17/arrow"
"github.com/apache/arrow/go/v17/arrow/array"
"github.com/milvus-io/milvus-proto/go-api/v3/schemapb"
"github.com/milvus-io/milvus/internal/util/function/chain"
"github.com/milvus-io/milvus/pkg/v3/util/merr"
)
const (
arrowMetadataFieldIDKey = "milvus.field_id"
arrowMetadataDataTypeKey = "milvus.data_type"
)
func dataFrameFromArrowRecordBatch(rec arrow.Record, chunkSizes []int64) (*chain.DataFrame, error) {
if rec == nil {
return nil, merr.WrapErrServiceInternal("nil Arrow record batch")
}
if len(chunkSizes) == 0 {
return nil, merr.WrapErrServiceInternal("empty Arrow RecordBatch chunk sizes")
}
var totalRows int64
for _, size := range chunkSizes {
if size < 0 {
return nil, merr.WrapErrServiceInternalMsg("invalid negative Arrow chunk size: %d", size)
}
totalRows += size
}
if totalRows != rec.NumRows() {
return nil, merr.WrapErrServiceInternalMsg("Arrow record batch row count %d does not match chunk sizes total %d", rec.NumRows(), totalRows)
}
numCols := int(rec.NumCols())
builder := chain.NewDataFrameBuilder()
defer builder.Release()
builder.SetChunkSizes(chunkSizes)
for colIdx := 0; colIdx < numCols; colIdx++ {
field := rec.Schema().Field(colIdx)
colName := field.Name
fullChunk := rec.Column(colIdx)
chunks := make([]arrow.Array, len(chunkSizes))
nullable := field.Nullable
releaseChunks := func() {
for _, chunk := range chunks {
if chunk != nil {
chunk.Release()
}
}
}
var offset int64
for i, size := range chunkSizes {
chunks[i] = array.NewSlice(fullChunk, offset, offset+size)
if chunks[i].NullN() > 0 {
nullable = true
}
offset += size
}
builder.SetFieldNullable(colName, nullable)
if fieldID, ok, err := fieldMetadataInt64(field.Metadata, arrowMetadataFieldIDKey); err != nil {
releaseChunks()
return nil, merr.WrapErrServiceInternalMsg("invalid Arrow field metadata %s for column %s: %v", arrowMetadataFieldIDKey, colName, err)
} else if ok {
builder.SetFieldID(colName, fieldID)
}
if dataType, ok, err := fieldMetadataInt64(field.Metadata, arrowMetadataDataTypeKey); err != nil {
releaseChunks()
return nil, merr.WrapErrServiceInternalMsg("invalid Arrow field metadata %s for column %s: %v", arrowMetadataDataTypeKey, colName, err)
} else if ok {
builder.SetFieldType(colName, schemapb.DataType(dataType))
}
if err := builder.AddColumnFromChunks(colName, chunks); err != nil {
return nil, err
}
}
df := builder.Build()
return df, nil
}
func fieldMetadataInt64(metadata arrow.Metadata, key string) (int64, bool, error) {
value, ok := metadata.GetValue(key)
if !ok {
return 0, false, nil
}
parsed, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0, false, err
}
return parsed, true, nil
}