Imported Arrow strings lose nulls when exported in nonzero-offset record batches
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- Nửa ngày
- Mức phù hợp với người mới
- 66/100
Hướng nghiên cứu
The bug is in the null-count loop of ArrowStringDataFrameColumn.GetNullCount in src/Microsoft.Data.Analysis/DataFrameColumns/ArrowStringDataFrameColumn.cs, which uses i < numberOfRows where it should scan from startIndex to startIndex + numberOfRows. Check the same pattern in PrimitiveDataFrameColumn<T>.GetNullCount. Done when a small unit test with a nonzero-offset slice (not the multi-GB repro) shows the correct NullCount and IsNull for the final row.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
An Arrow record imported with DataFrame.FromArrowRecordBatch() can export a null string as a valid empty string when ToArrowRecordBatches() divides the DataFrame into multiple batches.
Reproduced on Microsoft.Data.Analysis 0.23.0, Apache.Arrow 14.0.2, Windows x64, .NET 10.
Reproduction
Create a console app, add Microsoft.Data.Analysis version 0.23.0, and run:
using System;
using System.Linq;
using Apache.Arrow;
using Microsoft.Data.Analysis;
const int rows = 268_304_384;
var builder = new StringArray.Builder().Reserve(rows);
builder.Append("a");
builder.AppendRange(Enumerable.Repeat("", rows - 2));
builder.AppendNull();
var input = new RecordBatch.Builder()
.Append("strings", true, builder.Build())
.Build();
var frame = DataFrame.FromArrowRecordBatch(input);
var numbers = new Int64DataFrameColumn("numbers");
numbers.AppendMany(42, rows);
frame.Columns.Add(numbers);
Console.WriteLine($"Imported rows={frame.Rows.Count}; NullCount={frame.Columns["strings"].NullCount}; final string is null={frame[rows - 1, 0] is null}");
int index = 0;
foreach (var batch in frame.ToArrowRecordBatches())
{
var strings = batch.Arrays.OfType<StringArray>().Last();
Console.WriteLine($"Batch {index++}: rows={batch.Length}; last string array length={strings.Length}; NullCount={strings.NullCount}");
if (strings.Length == 1)
Console.WriteLine($"Final exported string={(strings.GetString(0) is { } value ? $"\"{value}\"" : "null")}; IsNull={strings.IsNull(0)}");
}
This deliberately large input needs several GB of RAM. The numeric column naturally occupies two buffers and forces two record batches. The strings remain in one buffer; their final null is exported as a nonzero-offset, one-row slice. A small, single-batch input would not reach the faulty loop bounds.
Actual output
Imported rows=268304384; NullCount=1; final string is null=True
Batch 0: rows=268304383; last string array length=268304383; NullCount=0
Batch 1: rows=1; last string array length=1; NullCount=0
Final exported string=""; IsNull=False
Expected behavior
The final string array should have NullCount == 1, IsNull(0) == true, and GetString(0) == null.
The repro selects the last string array because there is a separate bug where ToArrowRecordBatches() includes previous batches' arrays in later batches (https://github.com/dotnet/machinelearning/issues/7799). This does not cause the newly exported string array's incorrect null metadata.
Cause
ArrowStringDataFrameColumn.GetNullCount loops with i < numberOfRows, treating a row count as an exclusive end index. It should scan [startIndex, startIndex + numberOfRows).
For the final batch, startIndex == 268304383 and numberOfRows == 1, so no validity bits are checked and the null count is incorrectly zero. PrimitiveDataFrameColumn<T>.GetNullCount contains the same loop-bound pattern and should also be considered when fixing this.
- Ngôn ngữ chính
- C#
- Star
- 9.4k
- Fork
- 2k
- Merge trung bình
- 2 ngày 18 giờ
- Pull request đã merge (30 ngày)
- 64
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của dotnet/machinelearning
-
area-Native untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
dotnet/machinelearning#7837 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area-TensorFlow untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
dotnet/machinelearning#7836 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
ToArrowRecordBatches accumulates arrays from previous batches, producing invalid record batchesĐang mởarea-DataFrame bug untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
dotnet/machinelearning#7799 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
LlamaTokenizer encodes some runs of repeated characters differently from SentencePieceCó thể đã có người làm @Laurianti đã nhận 42 ngày trước. Đang mởarea-Tokenizers untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
dotnet/machinelearning#7751 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
BertTokenizer merges words separated only by `\n`, `\t` or `\r`Có thể đã có người làm @Laurianti đã nhận 23 ngày trước. Đang mởarea-Tokenizers green
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
dotnet/machinelearning#7724 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của dotnet/machinelearning
Issue tương tự
-
bug emitter:client:csharp
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
microsoft/typespec#12572 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
needs-area-label
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 2 ngày
-
AWS Lambda: KeyNotFoundException drops HTTP-triggered transactions when allowAllHeaders is disabledĐang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
newrelic/newrelic-dotnet-agent#3949 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area-networking
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
dotnet/aspnetcore#70545 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 87/100
Maintainer thường phản hồi trong vòng 1 ngày