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

curth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-dotnet.git


The following commit(s) were added to refs/heads/main by this push:
     new d1c0a72  Implement largelistview support (#303)
d1c0a72 is described below

commit d1c0a72cda966037fb56daf7eac981b39e6e01fd
Author: Curt Hagenlocher <[email protected]>
AuthorDate: Tue Mar 31 06:16:44 2026 -0700

    Implement largelistview support (#303)
    
    ## What's Changed
    
    Support for largelistview has been implemented. This still doesn't
    support lists which are actually more than 2GB, but at least smaller
    lists of this type can be loaded.
---
 src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs   |  51 ++++++
 .../Arrays/ArrowArrayBuilderFactory.cs             |   2 +
 src/Apache.Arrow/Arrays/ArrowArrayFactory.cs       |   2 +
 .../{ListViewArray.cs => LargeListViewArray.cs}    |  44 +++---
 src/Apache.Arrow/Arrays/ListViewArray.cs           |   1 +
 src/Apache.Arrow/C/CArrowArrayImporter.cs          |  30 ++++
 src/Apache.Arrow/C/CArrowSchemaExporter.cs         |   1 +
 src/Apache.Arrow/C/CArrowSchemaImporter.cs         |  11 +-
 src/Apache.Arrow/Ipc/ArrowReaderImplementation.cs  |   1 +
 src/Apache.Arrow/Ipc/ArrowStreamWriter.cs          |  69 ++++++++
 src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs |   9 ++
 src/Apache.Arrow/Ipc/MessageSerializer.cs          |   6 +
 src/Apache.Arrow/Types/IArrowType.cs               |   1 +
 src/Apache.Arrow/Types/LargeListViewType.cs        |  36 +++++
 test/Apache.Arrow.IntegrationTest/JsonFile.cs      |  36 +++++
 test/Apache.Arrow.Tests/ArrayBuilderTests.cs       |  29 ++++
 .../ArrowArrayConcatenatorTests.cs                 |  13 ++
 test/Apache.Arrow.Tests/ArrowReaderVerifier.cs     |  41 +++++
 .../LargeListViewArrayBuilderTests.cs              | 156 +++++++++++++++++++
 test/Apache.Arrow.Tests/LargeListViewArrayTests.cs | 173 +++++++++++++++++++++
 test/Apache.Arrow.Tests/TableTests.cs              |   4 +-
 test/Apache.Arrow.Tests/TestData.cs                |  34 ++++
 22 files changed, 721 insertions(+), 29 deletions(-)

diff --git a/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs 
b/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs
index a835435..68f9fff 100644
--- a/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs
+++ b/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs
@@ -58,6 +58,7 @@ namespace Apache.Arrow
             IArrowTypeVisitor<LargeBinaryType>,
             IArrowTypeVisitor<LargeStringType>,
             IArrowTypeVisitor<LargeListType>,
+            IArrowTypeVisitor<LargeListViewType>,
             IArrowTypeVisitor<MapType>
         {
             public ArrayData Result { get; private set; }
@@ -110,6 +111,56 @@ namespace Apache.Arrow
 
             public void Visit(LargeListType type) => 
ConcatenateLargeLists(type);
 
+            public void Visit(LargeListViewType type)
+            {
+                CheckData(type, 3);
+                ArrowBuffer validityBuffer = ConcatenateValidityBuffer();
+                ArrowBuffer sizesBuffer = 
ConcatenateFixedWidthTypeValueBuffer(2, Int64Type.Default);
+
+                var children = new List<ArrayData>(_arrayDataList.Count);
+                var offsetsBuilder = new 
ArrowBuffer.Builder<long>(_totalLength);
+                long baseOffset = 0;
+
+                foreach (ArrayData arrayData in _arrayDataList)
+                {
+                    if (arrayData.Length == 0)
+                    {
+                        continue;
+                    }
+
+                    var child = arrayData.Children[0];
+                    ReadOnlySpan<long> offsets = 
arrayData.Buffers[1].Span.CastTo<long>().Slice(arrayData.Offset, 
arrayData.Length);
+                    ReadOnlySpan<long> sizes = 
arrayData.Buffers[2].Span.CastTo<long>().Slice(arrayData.Offset, 
arrayData.Length);
+                    var minOffset = offsets[0];
+                    long maxEnd = 0;
+
+                    for (int i = 0; i < arrayData.Length; ++i)
+                    {
+                        minOffset = Math.Min(minOffset, offsets[i]);
+                        maxEnd = Math.Max(maxEnd, offsets[i] + sizes[i]);
+                    }
+
+                    foreach (long offset in offsets)
+                    {
+                        offsetsBuilder.Append(baseOffset + offset - minOffset);
+                    }
+
+                    var childLength = maxEnd - minOffset;
+                    if (minOffset != 0 || childLength != child.Length)
+                    {
+                        child = child.Slice(checked((int)minOffset), 
checked((int)childLength));
+                    }
+
+                    baseOffset += childLength;
+                    children.Add(child);
+                }
+
+                ArrowBuffer offsetBuffer = offsetsBuilder.Build(_allocator);
+                ArrayData combinedChild = Concatenate(children, _allocator);
+
+                Result = new ArrayData(type, _totalLength, _totalNullCount, 0, 
new ArrowBuffer[] { validityBuffer, offsetBuffer, sizesBuffer }, new[] { 
combinedChild });
+            }
+
             public void Visit(ListType type) => ConcatenateLists(type);
 
             public void Visit(ListViewType type)
diff --git a/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs 
b/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs
index f4f551c..ec0206a 100644
--- a/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs
+++ b/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs
@@ -101,6 +101,8 @@ namespace Apache.Arrow
                     return new LargeStringArray.Builder();
                 case ArrowTypeId.LargeList:
                     return new LargeListArray.Builder(dataType as 
LargeListType);
+                case ArrowTypeId.LargeListView:
+                    return new LargeListViewArray.Builder(dataType as 
LargeListViewType);
                 case ArrowTypeId.Map:
                     return new MapArray.Builder(dataType as MapType);
                 case ArrowTypeId.Struct:
diff --git a/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs 
b/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs
index ae5d7be..0f81336 100644
--- a/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs
+++ b/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs
@@ -71,6 +71,8 @@ namespace Apache.Arrow
                     return new ListViewArray(data);
                 case ArrowTypeId.LargeList:
                     return new LargeListArray(data);
+                case ArrowTypeId.LargeListView:
+                    return new LargeListViewArray(data);
                 case ArrowTypeId.Map:
                     return new MapArray(data);
                 case ArrowTypeId.Struct:
diff --git a/src/Apache.Arrow/Arrays/ListViewArray.cs 
b/src/Apache.Arrow/Arrays/LargeListViewArray.cs
similarity index 80%
copy from src/Apache.Arrow/Arrays/ListViewArray.cs
copy to src/Apache.Arrow/Arrays/LargeListViewArray.cs
index 7bbb292..240b731 100644
--- a/src/Apache.Arrow/Arrays/ListViewArray.cs
+++ b/src/Apache.Arrow/Arrays/LargeListViewArray.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
+// Licensed to the Apache Software Foundation (ASF) 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
@@ -19,17 +19,17 @@ using Apache.Arrow.Types;
 
 namespace Apache.Arrow
 {
-    public class ListViewArray : Array
+    public class LargeListViewArray : Array
     {
-        public class Builder : IArrowArrayBuilder<ListViewArray, Builder>
+        public class Builder : IArrowArrayBuilder<LargeListViewArray, Builder>
         {
             public IArrowArrayBuilder<IArrowArray, 
IArrowArrayBuilder<IArrowArray>> ValueBuilder { get; }
 
             public int Length => ValueOffsetsBufferBuilder.Length;
 
-            private ArrowBuffer.Builder<int> ValueOffsetsBufferBuilder { get; }
+            private ArrowBuffer.Builder<long> ValueOffsetsBufferBuilder { get; 
}
 
-            private ArrowBuffer.Builder<int> SizesBufferBuilder { get; }
+            private ArrowBuffer.Builder<long> SizesBufferBuilder { get; }
 
             private ArrowBuffer.BitmapBuilder ValidityBufferBuilder { get; }
 
@@ -39,19 +39,19 @@ namespace Apache.Arrow
 
             private int Start { get; set; }
 
-            public Builder(IArrowType valueDataType) : this(new 
ListViewType(valueDataType))
+            public Builder(IArrowType valueDataType) : this(new 
LargeListViewType(valueDataType))
             {
             }
 
-            public Builder(Field valueField) : this(new 
ListViewType(valueField))
+            public Builder(Field valueField) : this(new 
LargeListViewType(valueField))
             {
             }
 
-            internal Builder(ListViewType dataType)
+            internal Builder(LargeListViewType dataType)
             {
                 ValueBuilder = 
ArrowArrayBuilderFactory.Build(dataType.ValueDataType);
-                ValueOffsetsBufferBuilder = new ArrowBuffer.Builder<int>();
-                SizesBufferBuilder = new ArrowBuffer.Builder<int>();
+                ValueOffsetsBufferBuilder = new ArrowBuffer.Builder<long>();
+                SizesBufferBuilder = new ArrowBuffer.Builder<long>();
                 ValidityBufferBuilder = new ArrowBuffer.BitmapBuilder();
                 DataType = dataType;
                 Start = -1;
@@ -61,8 +61,7 @@ namespace Apache.Arrow
             /// Start a new variable-length list slot
             ///
             /// This function should be called before beginning to append 
elements to the
-            /// value builder. TODO: Consider adding builder APIs to support 
construction
-            /// of overlapping lists.
+            /// value builder.
             /// </summary>
             public Builder Append()
             {
@@ -96,7 +95,7 @@ namespace Apache.Arrow
                 Start = ValueBuilder.Length;
             }
 
-            public ListViewArray Build(MemoryAllocator allocator = default)
+            public LargeListViewArray Build(MemoryAllocator allocator = 
default)
             {
                 AppendPrevious();
 
@@ -104,7 +103,7 @@ namespace Apache.Arrow
                                         ? 
ValidityBufferBuilder.Build(allocator)
                                         : ArrowBuffer.Empty;
 
-                return new ListViewArray(DataType, Length,
+                return new LargeListViewArray(DataType, Length,
                     ValueOffsetsBufferBuilder.Build(allocator), 
SizesBufferBuilder.Build(allocator),
                     ValueBuilder.Build(allocator),
                     validityBuffer, NullCount, 0);
@@ -133,6 +132,7 @@ namespace Apache.Arrow
                 ValueBuilder.Clear();
                 ValidityBufferBuilder.Clear();
                 NullCount = 0;
+                Start = -1;
                 return this;
             }
         }
@@ -141,13 +141,13 @@ namespace Apache.Arrow
 
         public ArrowBuffer ValueOffsetsBuffer => Data.Buffers[1];
 
-        public ReadOnlySpan<int> ValueOffsets => 
ValueOffsetsBuffer.Span.CastTo<int>().Slice(Offset, Length);
+        public ReadOnlySpan<long> ValueOffsets => 
ValueOffsetsBuffer.Span.CastTo<long>().Slice(Offset, Length);
 
         public ArrowBuffer SizesBuffer => Data.Buffers[2];
 
-        public ReadOnlySpan<int> Sizes => 
SizesBuffer.Span.CastTo<int>().Slice(Offset, Length);
+        public ReadOnlySpan<long> Sizes => 
SizesBuffer.Span.CastTo<long>().Slice(Offset, Length);
 
-        public ListViewArray(IArrowType dataType, int length,
+        public LargeListViewArray(IArrowType dataType, int length,
             ArrowBuffer valueOffsetsBuffer, ArrowBuffer sizesBuffer, 
IArrowArray values,
             ArrowBuffer nullBitmapBuffer, int nullCount = 0, int offset = 0)
             : this(new ArrayData(dataType, length, nullCount, offset,
@@ -156,15 +156,15 @@ namespace Apache.Arrow
         {
         }
 
-        public ListViewArray(ArrayData data)
+        public LargeListViewArray(ArrayData data)
             : this(data, ArrowArrayFactory.BuildArray(data.Children[0]))
         {
         }
 
-        private ListViewArray(ArrayData data, IArrowArray values) : base(data)
+        private LargeListViewArray(ArrayData data, IArrowArray values) : 
base(data)
         {
             data.EnsureBufferCount(3);
-            data.EnsureDataType(ArrowTypeId.ListView);
+            data.EnsureDataType(ArrowTypeId.LargeListView);
             Values = values;
         }
 
@@ -182,7 +182,7 @@ namespace Apache.Arrow
                 return 0;
             }
 
-            return Sizes[index];
+            return checked((int)Sizes[index]);
         }
 
         public IArrowArray GetSlicedValues(int index)
@@ -202,7 +202,7 @@ namespace Apache.Arrow
                 return default;
             }
 
-            return array.Slice(ValueOffsets[index], GetValueLength(index));
+            return array.Slice(checked((int)ValueOffsets[index]), 
GetValueLength(index));
         }
 
         protected override void Dispose(bool disposing)
diff --git a/src/Apache.Arrow/Arrays/ListViewArray.cs 
b/src/Apache.Arrow/Arrays/ListViewArray.cs
index 7bbb292..ab8eaa9 100644
--- a/src/Apache.Arrow/Arrays/ListViewArray.cs
+++ b/src/Apache.Arrow/Arrays/ListViewArray.cs
@@ -133,6 +133,7 @@ namespace Apache.Arrow
                 ValueBuilder.Clear();
                 ValidityBufferBuilder.Clear();
                 NullCount = 0;
+                Start = -1;
                 return this;
             }
         }
diff --git a/src/Apache.Arrow/C/CArrowArrayImporter.cs 
b/src/Apache.Arrow/C/CArrowArrayImporter.cs
index ed2462b..e87f3ca 100644
--- a/src/Apache.Arrow/C/CArrowArrayImporter.cs
+++ b/src/Apache.Arrow/C/CArrowArrayImporter.cs
@@ -179,6 +179,10 @@ namespace Apache.Arrow.C
                         children = ProcessListChildren(cArray, 
((LargeListType)storageType).ValueDataType);
                         buffers = ImportLargeListBuffers(cArray);
                         break;
+                    case ArrowTypeId.LargeListView:
+                        children = ProcessListChildren(cArray, 
((LargeListViewType)storageType).ValueDataType);
+                        buffers = ImportLargeListViewBuffers(cArray);
+                        break;
                     case ArrowTypeId.FixedSizeList:
                         children = ProcessListChildren(cArray, 
((FixedSizeListType)storageType).ValueDataType);
                         buffers = ImportFixedSizeListBuffers(cArray);
@@ -393,6 +397,32 @@ namespace Apache.Arrow.C
                 return buffers;
             }
 
+            private ArrowBuffer[] ImportLargeListViewBuffers(CArrowArray* 
cArray)
+            {
+                if (cArray->n_buffers != 3)
+                {
+                    throw new InvalidOperationException("Large list view 
arrays are expected to have exactly three buffers");
+                }
+
+                const int maxLength = int.MaxValue / 8;
+                if (cArray->length > maxLength)
+                {
+                    throw new OverflowException(
+                        $"Cannot import large list view array. Array length 
{cArray->length} " +
+                        $"is greater than the maximum supported large list 
view array length ({maxLength})");
+                }
+
+                int length = checked((int)cArray->offset + 
(int)cArray->length);
+                int bufferLength = checked(length * 8);
+
+                ArrowBuffer[] buffers = new ArrowBuffer[3];
+                buffers[0] = ImportValidityBuffer(cArray);
+                buffers[1] = ImportCArrayBuffer(cArray, 1, bufferLength);
+                buffers[2] = ImportCArrayBuffer(cArray, 2, bufferLength);
+
+                return buffers;
+            }
+
             private ArrowBuffer[] ImportLargeListBuffers(CArrowArray* cArray)
             {
                 if (cArray->n_buffers != 2)
diff --git a/src/Apache.Arrow/C/CArrowSchemaExporter.cs 
b/src/Apache.Arrow/C/CArrowSchemaExporter.cs
index 8865c18..3206642 100644
--- a/src/Apache.Arrow/C/CArrowSchemaExporter.cs
+++ b/src/Apache.Arrow/C/CArrowSchemaExporter.cs
@@ -231,6 +231,7 @@ namespace Apache.Arrow.C
                 case ListType _: return "+l";
                 case ListViewType _: return "+vl";
                 case LargeListType _: return "+L";
+                case LargeListViewType _: return "+vL";
                 case FixedSizeListType fixedListType:
                     return $"+w:{fixedListType.ListSize}";
                 case StructType _: return "+s";
diff --git a/src/Apache.Arrow/C/CArrowSchemaImporter.cs 
b/src/Apache.Arrow/C/CArrowSchemaImporter.cs
index fd06793..706890b 100644
--- a/src/Apache.Arrow/C/CArrowSchemaImporter.cs
+++ b/src/Apache.Arrow/C/CArrowSchemaImporter.cs
@@ -185,7 +185,7 @@ namespace Apache.Arrow.C
                 }
 
                 // Special handling for nested types
-                if (format == "+l" || format == "+vl" || format == "+L")
+                if (format == "+l" || format == "+vl" || format == "+L" || 
format == "+vL")
                 {
                     if (_cSchema->n_children != 1)
                     {
@@ -200,11 +200,12 @@ namespace Apache.Arrow.C
 
                     Field childField = childSchema.GetAsField();
 
-                    return format[1] switch
+                    return format switch
                     {
-                        'l' => new ListType(childField),
-                        'v' => new ListViewType(childField),
-                        'L' => new LargeListType(childField),
+                        "+l" => new ListType(childField),
+                        "+vl" => new ListViewType(childField),
+                        "+L" => new LargeListType(childField),
+                        "+vL" => new LargeListViewType(childField),
                         _ => throw new InvalidDataException($"Invalid format 
for list: '{format}'"),
                     };
                 }
diff --git a/src/Apache.Arrow/Ipc/ArrowReaderImplementation.cs 
b/src/Apache.Arrow/Ipc/ArrowReaderImplementation.cs
index 1ed8d8a..28757b9 100644
--- a/src/Apache.Arrow/Ipc/ArrowReaderImplementation.cs
+++ b/src/Apache.Arrow/Ipc/ArrowReaderImplementation.cs
@@ -301,6 +301,7 @@ namespace Apache.Arrow.Ipc
                 case ArrowTypeId.LargeString:
                 case ArrowTypeId.LargeBinary:
                 case ArrowTypeId.ListView:
+                case ArrowTypeId.LargeListView:
                     buffers = 3;
                     break;
                 case ArrowTypeId.StringView:
diff --git a/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs 
b/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs
index c5eed3b..18cc538 100644
--- a/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs
+++ b/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs
@@ -58,6 +58,7 @@ namespace Apache.Arrow.Ipc
             IArrowArrayVisitor<ListArray>,
             IArrowArrayVisitor<ListViewArray>,
             IArrowArrayVisitor<LargeListArray>,
+            IArrowArrayVisitor<LargeListViewArray>,
             IArrowArrayVisitor<FixedSizeListArray>,
             IArrowArrayVisitor<StringArray>,
             IArrowArrayVisitor<StringViewArray>,
@@ -228,6 +229,23 @@ namespace Apache.Arrow.Ipc
                 VisitArray(values);
             }
 
+            public void Visit(LargeListViewArray array)
+            {
+                var (valueOffsetsBuffer, minOffset, maxEnd) = 
GetZeroBasedLargeListViewOffsets(array);
+
+                _buffers.Add(CreateBitmapBuffer(array.NullBitmapBuffer, 
array.Offset, array.Length, false));
+                _buffers.Add(CreateBuffer(valueOffsetsBuffer, true));
+                _buffers.Add(CreateSlicedBuffer<long>(array.SizesBuffer, 
array.Offset, array.Length, false));
+
+                IArrowArray values = array.Values;
+                if (minOffset != 0 || values.Length != maxEnd)
+                {
+                    values = ArrowArrayFactory.Slice(values, 
checked((int)minOffset), checked((int)(maxEnd - minOffset)));
+                }
+
+                VisitArray(values);
+            }
+
             public void Visit(FixedSizeListArray array)
             {
                 _buffers.Add(CreateBitmapBuffer(array.NullBitmapBuffer, 
array.Offset, array.Length, false));
@@ -467,6 +485,57 @@ namespace Apache.Arrow.Ipc
                 return (new ArrowBuffer(newOffsetsBuffer), minOffset, maxEnd);
             }
 
+            private (ArrowBuffer Buffer, long minOffset, long maxEnd) 
GetZeroBasedLargeListViewOffsets(LargeListViewArray array)
+            {
+                if (array.Length == 0)
+                {
+                    return (ArrowBuffer.Empty, 0, 0);
+                }
+
+                var offsets = array.ValueOffsets;
+                var sizes = array.Sizes;
+
+                long minOffset = offsets[0];
+                long maxEnd = offsets[array.Length - 1] + sizes[array.Length - 
1];
+
+                if (minOffset != 0 || maxEnd != array.Values.Length)
+                {
+                    for (int i = 0; i < array.Length; ++i)
+                    {
+                        minOffset = Math.Min(minOffset, offsets[i]);
+                        maxEnd = Math.Max(maxEnd, offsets[i] + sizes[i]);
+                    }
+                }
+
+                var requiredBytes = CalculatePaddedBufferLength(sizeof(long) * 
array.Length);
+
+                if (minOffset == 0)
+                {
+                    ArrowBuffer buffer;
+                    if (array.Offset != 0 || array.ValueOffsetsBuffer.Length > 
requiredBytes)
+                    {
+                        var byteOffset = sizeof(long) * array.Offset;
+                        var sliceLength = Math.Min(requiredBytes, 
array.ValueOffsetsBuffer.Length - byteOffset);
+                        buffer = new 
ArrowBuffer(array.ValueOffsetsBuffer.Memory.Slice(byteOffset, sliceLength));
+                    }
+                    else
+                    {
+                        buffer = new 
ArrowBuffer(array.ValueOffsetsBuffer.Memory);
+                    }
+
+                    return (buffer, minOffset, maxEnd);
+                }
+
+                var newOffsetsBuffer = _allocator.Allocate(requiredBytes);
+                var newOffsets = newOffsetsBuffer.Memory.Span.CastTo<long>();
+                for (int i = 0; i < array.Length; ++i)
+                {
+                    newOffsets[i] = offsets[i] - minOffset;
+                }
+
+                return (new ArrowBuffer(newOffsetsBuffer), minOffset, maxEnd);
+            }
+
             private Buffer CreateBitmapBuffer(ArrowBuffer buffer, int offset, 
int length, bool locallyOwned)
             {
                 if (buffer.IsEmpty)
diff --git a/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs 
b/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs
index 503680a..893ae63 100644
--- a/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs
+++ b/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs
@@ -71,6 +71,7 @@ namespace Apache.Arrow.Ipc
             IArrowTypeVisitor<ListType>,
             IArrowTypeVisitor<ListViewType>,
             IArrowTypeVisitor<LargeListType>,
+            IArrowTypeVisitor<LargeListViewType>,
             IArrowTypeVisitor<FixedSizeListType>,
             IArrowTypeVisitor<UnionType>,
             IArrowTypeVisitor<StructType>,
@@ -157,6 +158,14 @@ namespace Apache.Arrow.Ipc
                     Flatbuf.LargeList.EndLargeList(Builder));
             }
 
+            public void Visit(LargeListViewType type)
+            {
+                Flatbuf.LargeListView.StartLargeListView(Builder);
+                Result = FieldType.Build(
+                    Flatbuf.Type.LargeListView,
+                    Flatbuf.LargeListView.EndLargeListView(Builder));
+            }
+
             public void Visit(FixedSizeListType type)
             {
                 Result = FieldType.Build(
diff --git a/src/Apache.Arrow/Ipc/MessageSerializer.cs 
b/src/Apache.Arrow/Ipc/MessageSerializer.cs
index 0984faf..645e6c8 100644
--- a/src/Apache.Arrow/Ipc/MessageSerializer.cs
+++ b/src/Apache.Arrow/Ipc/MessageSerializer.cs
@@ -237,6 +237,12 @@ namespace Apache.Arrow.Ipc
                         throw new InvalidDataException($"Large list type must 
have exactly one child.");
                     }
                     return new Types.LargeListType(childFields[0]);
+                case Flatbuf.Type.LargeListView:
+                    if (childFields == null || childFields.Length != 1)
+                    {
+                        throw new InvalidDataException($"Large list view type 
must have exactly one child.");
+                    }
+                    return new Types.LargeListViewType(childFields[0]);
                 case Flatbuf.Type.FixedSizeList:
                     if (childFields == null || childFields.Length != 1)
                     {
diff --git a/src/Apache.Arrow/Types/IArrowType.cs 
b/src/Apache.Arrow/Types/IArrowType.cs
index bf16368..ef1ec10 100644
--- a/src/Apache.Arrow/Types/IArrowType.cs
+++ b/src/Apache.Arrow/Types/IArrowType.cs
@@ -59,6 +59,7 @@ namespace Apache.Arrow.Types
         Decimal32,
         Decimal64,
         Extension,
+        LargeListView,
     }
 
     public interface IArrowType
diff --git a/src/Apache.Arrow/Types/LargeListViewType.cs 
b/src/Apache.Arrow/Types/LargeListViewType.cs
new file mode 100644
index 0000000..e28e067
--- /dev/null
+++ b/src/Apache.Arrow/Types/LargeListViewType.cs
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) 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.
+
+namespace Apache.Arrow.Types
+{
+    public sealed class LargeListViewType : NestedType
+    {
+        public override ArrowTypeId TypeId => ArrowTypeId.LargeListView;
+
+        public override string Name => "large_listview";
+
+        public Field ValueField => Fields[0];
+
+        public IArrowType ValueDataType => Fields[0].DataType;
+
+        public LargeListViewType(Field valueField)
+           : base(valueField) { }
+
+        public LargeListViewType(IArrowType valueDataType)
+            : this(new Field("item", valueDataType, true)) { }
+
+        public override void Accept(IArrowTypeVisitor visitor) => Accept(this, 
visitor);
+    }
+}
diff --git a/test/Apache.Arrow.IntegrationTest/JsonFile.cs 
b/test/Apache.Arrow.IntegrationTest/JsonFile.cs
index a75c419..71831a7 100644
--- a/test/Apache.Arrow.IntegrationTest/JsonFile.cs
+++ b/test/Apache.Arrow.IntegrationTest/JsonFile.cs
@@ -191,6 +191,7 @@ namespace Apache.Arrow.IntegrationTest
                 "list" => ToListArrowType(type, children),
                 "listview" => ToListViewArrowType(type, children),
                 "largelist" => ToLargeListArrowType(type, children),
+                "largelistview" => ToLargeListViewArrowType(type, children),
                 "fixedsizelist" => ToFixedSizeListArrowType(type, children),
                 "struct" => ToStructArrowType(type, children),
                 "union" => ToUnionArrowType(type, children),
@@ -315,6 +316,11 @@ namespace Apache.Arrow.IntegrationTest
             return new LargeListType(children[0]);
         }
 
+        private static IArrowType ToLargeListViewArrowType(JsonArrowType type, 
Field[] children)
+        {
+            return new LargeListViewType(children[0]);
+        }
+
         private static IArrowType ToFixedSizeListArrowType(JsonArrowType type, 
Field[] children)
         {
             return new FixedSizeListType(children[0], type.ListSize);
@@ -483,6 +489,7 @@ namespace Apache.Arrow.IntegrationTest
             IArrowTypeVisitor<ListType>,
             IArrowTypeVisitor<ListViewType>,
             IArrowTypeVisitor<LargeListType>,
+            IArrowTypeVisitor<LargeListViewType>,
             IArrowTypeVisitor<FixedSizeListType>,
             IArrowTypeVisitor<StructType>,
             IArrowTypeVisitor<UnionType>,
@@ -875,6 +882,22 @@ namespace Apache.Arrow.IntegrationTest
                 Array = new LargeListArray(arrayData);
             }
 
+            public void Visit(LargeListViewType type)
+            {
+                ArrowBuffer validityBuffer = GetValidityBuffer(out int 
nullCount);
+                ArrowBuffer offsetBuffer = GetLargeOffsetBuffer();
+                ArrowBuffer sizeBuffer = GetLargeSizeBuffer();
+
+                var data = JsonFieldData;
+                JsonFieldData = data.Children[0];
+                type.ValueDataType.Accept(this);
+                JsonFieldData = data;
+
+                ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, 
nullCount, 0,
+                    new[] { validityBuffer, offsetBuffer, sizeBuffer }, new[] 
{ Array.Data });
+                Array = new LargeListViewArray(arrayData);
+            }
+
             public void Visit(FixedSizeListType type)
             {
                 ArrowBuffer validityBuffer = GetValidityBuffer(out int 
nullCount);
@@ -1068,6 +1091,13 @@ namespace Apache.Arrow.IntegrationTest
                 return valueSizes.Build(default);
             }
 
+            private ArrowBuffer GetLargeSizeBuffer()
+            {
+                ArrowBuffer.Builder<long> valueSizes = new 
ArrowBuffer.Builder<long>(JsonFieldData.Size.Count);
+                valueSizes.AppendRange(JsonFieldData.LongSize);
+                return valueSizes.Build(default);
+            }
+
             private ArrowBuffer GetTypeIdBuffer()
             {
                 ArrowBuffer.Builder<byte> typeIds = new 
ArrowBuffer.Builder<byte>(JsonFieldData.TypeId.Length);
@@ -1137,6 +1167,12 @@ namespace Apache.Arrow.IntegrationTest
             get { return Size.Select(GetInt); }
         }
 
+        [JsonIgnore]
+        public IEnumerable<long> LongSize
+        {
+            get { return Size.Select(GetLong); }
+        }
+
         static int GetInt(JsonNode node)
         {
             try
diff --git a/test/Apache.Arrow.Tests/ArrayBuilderTests.cs 
b/test/Apache.Arrow.Tests/ArrayBuilderTests.cs
index 2db71b2..ddf4dc1 100644
--- a/test/Apache.Arrow.Tests/ArrayBuilderTests.cs
+++ b/test/Apache.Arrow.Tests/ArrayBuilderTests.cs
@@ -349,7 +349,36 @@ namespace Apache.Arrow.Tests
             valueBuilder.Append(10);
             var clearedList = builder.Build();
 
+            Assert.Equal(1, clearedList.Length);
             Assert.Equal(0, clearedList.NullCount);
+            var slice = (Int64Array)clearedList.GetSlicedValues(0);
+            Assert.Equal(1, slice.Length);
+            Assert.Equal(10, slice.GetValue(0));
+        }
+
+        [Fact]
+        public void ListViewArrayBuilderClearWithoutBuildResetsCorrectly()
+        {
+            var builder = new ListViewArray.Builder(Int64Type.Default);
+            var valueBuilder = (Int64Array.Builder)builder.ValueBuilder;
+
+            builder.Append();
+            valueBuilder.Append(1);
+            valueBuilder.Append(2);
+
+            // Clear without calling Build first
+            builder.Clear();
+
+            builder.Append();
+            valueBuilder.Append(10);
+
+            var array = builder.Build();
+
+            Assert.Equal(1, array.Length);
+            Assert.Equal(0, array.NullCount);
+            var slice = (Int64Array)array.GetSlicedValues(0);
+            Assert.Equal(1, slice.Length);
+            Assert.Equal(10, slice.GetValue(0));
         }
 
         [Fact]
diff --git a/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs 
b/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs
index f9589ef..e15e8e0 100644
--- a/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs
+++ b/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs
@@ -89,6 +89,7 @@ namespace Apache.Arrow.Tests
                     new LargeListType(Int64Type.Default),
                     new ListType(Int64Type.Default),
                     new ListViewType(Int64Type.Default),
+                    new LargeListViewType(Int64Type.Default),
                     new StructType(new List<Field>{
                         new 
Field.Builder().Name("Strings").DataType(StringType.Default).Nullable(true).Build(),
                         new 
Field.Builder().Name("Ints").DataType(Int32Type.Default).Nullable(true).Build()
@@ -160,6 +161,7 @@ namespace Apache.Arrow.Tests
             IArrowTypeVisitor<LargeBinaryType>,
             IArrowTypeVisitor<LargeStringType>,
             IArrowTypeVisitor<LargeListType>,
+            IArrowTypeVisitor<LargeListViewType>,
             IArrowTypeVisitor<MapType>
         {
             private readonly List<List<int?>> _baseData;
@@ -529,6 +531,17 @@ namespace Apache.Arrow.Tests
                     builder.ValueBuilder.Reserve(length);
                 });
 
+            public void Visit(LargeListViewType type) =>
+                GenerateTestData<LargeListViewArray, 
LargeListViewArray.Builder>(type, (builder, x) =>
+                {
+                    builder.Append();
+                    ((Int64Array.Builder)builder.ValueBuilder).Append(x);
+                }, initAction: (builder, length) =>
+                {
+                    builder.Reserve(length);
+                    builder.ValueBuilder.Reserve(length);
+                });
+
             public void Visit(MapType type) =>
                 GenerateTestData<MapArray, MapArray.Builder>(type, (builder, 
x) =>
                 {
diff --git a/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs 
b/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs
index bdbe4bb..2f647ae 100644
--- a/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs
+++ b/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs
@@ -96,6 +96,7 @@ namespace Apache.Arrow.Tests
             IArrowArrayVisitor<ListArray>,
             IArrowArrayVisitor<ListViewArray>,
             IArrowArrayVisitor<LargeListArray>,
+            IArrowArrayVisitor<LargeListViewArray>,
             IArrowArrayVisitor<FixedSizeListArray>,
             IArrowArrayVisitor<StringArray>,
             IArrowArrayVisitor<StringViewArray>,
@@ -150,6 +151,7 @@ namespace Apache.Arrow.Tests
             public void Visit(ListArray array) => CompareArrays(array);
             public void Visit(ListViewArray array) => CompareArrays(array);
             public void Visit(LargeListArray array) => CompareArrays(array);
+            public void Visit(LargeListViewArray array) => 
CompareArrays(array);
             public void Visit(FixedSizeListArray array) => 
CompareArrays(array);
             public void Visit(FixedSizeBinaryArray array) => 
CompareArrays(array);
             public void Visit(Decimal32Array array) => CompareArrays(array);
@@ -551,6 +553,45 @@ namespace Apache.Arrow.Tests
                 }
             }
 
+            private void CompareArrays(LargeListViewArray actualArray)
+            {
+                Assert.IsAssignableFrom<LargeListViewArray>(_expectedArray);
+                LargeListViewArray expectedArray = 
(LargeListViewArray)_expectedArray;
+
+                actualArray.Data.DataType.Accept(_arrayTypeComparer);
+
+                Assert.Equal(expectedArray.Length, actualArray.Length);
+                Assert.Equal(expectedArray.NullCount, actualArray.NullCount);
+
+                CompareValidityBuffer(
+                    expectedArray.NullCount, _expectedArray.Length, 
expectedArray.NullBitmapBuffer,
+                    expectedArray.Offset, actualArray.NullBitmapBuffer, 
actualArray.Offset);
+
+                if (_strictCompare)
+                {
+                    Assert.Equal(expectedArray.Offset, actualArray.Offset);
+                    
Assert.True(expectedArray.ValueOffsetsBuffer.Span.SequenceEqual(actualArray.ValueOffsetsBuffer.Span));
+                    
Assert.True(expectedArray.SizesBuffer.Span.SequenceEqual(actualArray.SizesBuffer.Span));
+                    actualArray.Values.Accept(new 
ArrayComparer(expectedArray.Values, _strictCompare));
+                }
+                else
+                {
+                    for (int i = 0; i < actualArray.Length; ++i)
+                    {
+                        if (expectedArray.IsNull(i))
+                        {
+                            Assert.True(actualArray.IsNull(i));
+                        }
+                        else
+                        {
+                            var expectedList = 
expectedArray.GetSlicedValues(i);
+                            var actualList = actualArray.GetSlicedValues(i);
+                            actualList.Accept(new ArrayComparer(expectedList, 
_strictCompare));
+                        }
+                    }
+                }
+            }
+
             private void CompareArrays(FixedSizeListArray actualArray)
             {
                 Assert.IsAssignableFrom<FixedSizeListArray>(_expectedArray);
diff --git a/test/Apache.Arrow.Tests/LargeListViewArrayBuilderTests.cs 
b/test/Apache.Arrow.Tests/LargeListViewArrayBuilderTests.cs
new file mode 100644
index 0000000..ad172fe
--- /dev/null
+++ b/test/Apache.Arrow.Tests/LargeListViewArrayBuilderTests.cs
@@ -0,0 +1,156 @@
+// Licensed to the Apache Software Foundation (ASF) 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.
+
+using Apache.Arrow.Types;
+using Xunit;
+
+namespace Apache.Arrow.Tests
+{
+    public class LargeListViewArrayBuilderTests
+    {
+        [Fact]
+        public void AppendBuildsCorrectArray()
+        {
+            var builder = new LargeListViewArray.Builder(Int32Type.Default);
+            var valueBuilder = (Int32Array.Builder)builder.ValueBuilder;
+
+            builder.Append();
+            valueBuilder.Append(1);
+            valueBuilder.Append(2);
+
+            builder.Append();
+            valueBuilder.Append(3);
+
+            builder.AppendNull();
+
+            builder.Append();
+
+            var array = builder.Build();
+
+            Assert.Equal(4, array.Length);
+
+            var slice0 = (Int32Array)array.GetSlicedValues(0);
+            Assert.Equal(2, slice0.Length);
+            Assert.Equal(1, slice0.GetValue(0));
+            Assert.Equal(2, slice0.GetValue(1));
+
+            var slice1 = (Int32Array)array.GetSlicedValues(1);
+            Assert.Equal(1, slice1.Length);
+            Assert.Equal(3, slice1.GetValue(0));
+
+            Assert.Null(array.GetSlicedValues(2));
+
+            var slice3 = (Int32Array)array.GetSlicedValues(3);
+            Assert.Equal(0, slice3.Length);
+        }
+
+        [Fact]
+        public void NullCountIsCorrect()
+        {
+            var builder = new LargeListViewArray.Builder(Int32Type.Default);
+            var valueBuilder = (Int32Array.Builder)builder.ValueBuilder;
+
+            builder.Append();
+            valueBuilder.Append(1);
+
+            builder.AppendNull();
+            builder.AppendNull();
+
+            builder.Append();
+            valueBuilder.Append(2);
+
+            var array = builder.Build();
+
+            Assert.Equal(4, array.Length);
+            Assert.Equal(2, array.NullCount);
+        }
+
+        [Fact]
+        public void ClearResetsBuilder()
+        {
+            var builder = new LargeListViewArray.Builder(Int32Type.Default);
+            var valueBuilder = (Int32Array.Builder)builder.ValueBuilder;
+
+            builder.Append();
+            valueBuilder.Append(1);
+            builder.AppendNull();
+
+            builder.Clear();
+
+            builder.Append();
+            valueBuilder.Append(99);
+
+            var array = builder.Build();
+
+            Assert.Equal(1, array.Length);
+            Assert.Equal(0, array.NullCount);
+            var slice = (Int32Array)array.GetSlicedValues(0);
+            Assert.Equal(1, slice.Length);
+            Assert.Equal(99, slice.GetValue(0));
+        }
+
+        [Fact]
+        public void ClearWithoutBuildResetsBuilder()
+        {
+            var builder = new LargeListViewArray.Builder(Int32Type.Default);
+            var valueBuilder = (Int32Array.Builder)builder.ValueBuilder;
+
+            builder.Append();
+            valueBuilder.Append(1);
+            valueBuilder.Append(2);
+
+            // Clear without calling Build first
+            builder.Clear();
+
+            builder.Append();
+            valueBuilder.Append(99);
+
+            var array = builder.Build();
+
+            Assert.Equal(1, array.Length);
+            Assert.Equal(0, array.NullCount);
+            var slice = (Int32Array)array.GetSlicedValues(0);
+            Assert.Equal(1, slice.Length);
+            Assert.Equal(99, slice.GetValue(0));
+        }
+
+        [Fact]
+        public void NestedStringListBuildsCorrectly()
+        {
+            var builder = new LargeListViewArray.Builder(StringType.Default);
+            var valueBuilder = (StringArray.Builder)builder.ValueBuilder;
+
+            builder.Append();
+            valueBuilder.Append("hello");
+            valueBuilder.Append("world");
+
+            builder.Append();
+            valueBuilder.Append("foo");
+
+            var array = builder.Build();
+
+            Assert.Equal(2, array.Length);
+
+            var slice0 = (StringArray)array.GetSlicedValues(0);
+            Assert.Equal(2, slice0.Length);
+            Assert.Equal("hello", slice0.GetString(0));
+            Assert.Equal("world", slice0.GetString(1));
+
+            var slice1 = (StringArray)array.GetSlicedValues(1);
+            Assert.Equal(1, slice1.Length);
+            Assert.Equal("foo", slice1.GetString(0));
+        }
+    }
+}
diff --git a/test/Apache.Arrow.Tests/LargeListViewArrayTests.cs 
b/test/Apache.Arrow.Tests/LargeListViewArrayTests.cs
new file mode 100644
index 0000000..6e0286a
--- /dev/null
+++ b/test/Apache.Arrow.Tests/LargeListViewArrayTests.cs
@@ -0,0 +1,173 @@
+// Licensed to the Apache Software Foundation (ASF) 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.
+
+using System;
+using System.Linq;
+using Apache.Arrow.Types;
+using Xunit;
+
+namespace Apache.Arrow.Tests;
+
+public class LargeListViewArrayTests
+{
+    [Fact]
+    public void GetSlicedValuesReturnsCorrectValues()
+    {
+        var values = new int?[][]
+        {
+            new int?[] { 0, 1, 2 },
+            System.Array.Empty<int?>(),
+            null,
+            new int?[] { 3, 4, null, 6 },
+        };
+
+        var array = BuildArray(values);
+
+        Assert.Equal(values.Length, array.Length);
+        for (int i = 0; i < values.Length; ++i)
+        {
+            Assert.Equal(values[i] == null, array.IsNull(i));
+            var arrayItem = (Int32Array)array.GetSlicedValues(i);
+            if (values[i] == null)
+            {
+                Assert.Null(arrayItem);
+            }
+            else
+            {
+                Assert.Equal(values[i], arrayItem.ToArray());
+            }
+        }
+    }
+
+    [Fact]
+    public void GetSlicedValuesChecksForOffsetOverflow()
+    {
+        var valuesArray = new Int32Array.Builder().Build();
+        var offsetBuffer = new ArrowBuffer.Builder<long>();
+        var sizesBuffer = new ArrowBuffer.Builder<long>();
+        var validityBuffer = new ArrowBuffer.BitmapBuilder();
+
+        offsetBuffer.Append((long)int.MaxValue + 1);
+        sizesBuffer.Append(1);
+        validityBuffer.Append(true);
+
+        var array = new LargeListViewArray(
+            new LargeListViewType(new Int32Type()), length: 1,
+            offsetBuffer.Build(), sizesBuffer.Build(), valuesArray, 
validityBuffer.Build(),
+            validityBuffer.UnsetBitCount);
+
+        Assert.Throws<OverflowException>(() => array.GetSlicedValues(0));
+    }
+
+    [Fact]
+    public void GetSlicedValuesChecksForSizeOverflow()
+    {
+        var valuesArray = new Int32Array.Builder().Build();
+        var offsetBuffer = new ArrowBuffer.Builder<long>();
+        var sizesBuffer = new ArrowBuffer.Builder<long>();
+        var validityBuffer = new ArrowBuffer.BitmapBuilder();
+
+        offsetBuffer.Append(0L);
+        sizesBuffer.Append((long)int.MaxValue + 1);
+        validityBuffer.Append(true);
+
+        var array = new LargeListViewArray(
+            new LargeListViewType(new Int32Type()), length: 1,
+            offsetBuffer.Build(), sizesBuffer.Build(), valuesArray, 
validityBuffer.Build(),
+            validityBuffer.UnsetBitCount);
+
+        Assert.Throws<OverflowException>(() => array.GetValueLength(0));
+    }
+
+    [Fact]
+    public void SliceReturnsCorrectValues()
+    {
+        var values = new int?[][]
+        {
+            new int?[] { 10, 20 },
+            new int?[] { 30 },
+            new int?[] { 40, 50, 60 },
+            new int?[] { 70 },
+        };
+
+        var array = BuildArray(values);
+        var sliced = (LargeListViewArray)array.Slice(1, 2);
+
+        Assert.Equal(2, sliced.Length);
+
+        var list0 = (Int32Array)sliced.GetSlicedValues(0);
+        Assert.Equal(1, list0.Length);
+        Assert.Equal(30, list0.GetValue(0));
+
+        var list1 = (Int32Array)sliced.GetSlicedValues(1);
+        Assert.Equal(3, list1.Length);
+        Assert.Equal(40, list1.GetValue(0));
+        Assert.Equal(60, list1.GetValue(2));
+    }
+
+    [Fact]
+    public void PropertiesReturnCorrectValues()
+    {
+        var values = new int?[][]
+        {
+            new int?[] { 1, 2, 3 },
+            null,
+            new int?[] { 4, 5 },
+        };
+
+        var array = BuildArray(values);
+
+        Assert.Equal(3, array.Length);
+        Assert.Equal(1, array.NullCount);
+        Assert.Equal(ArrowTypeId.LargeListView, array.Data.DataType.TypeId);
+
+        Assert.Equal(3, array.GetValueLength(0));
+        Assert.Equal(0, array.GetValueLength(1));
+        Assert.Equal(2, array.GetValueLength(2));
+    }
+
+    private static LargeListViewArray BuildArray(int?[][] values)
+    {
+        var valuesBuilder = new Int32Array.Builder();
+        var offsetBuffer = new ArrowBuffer.Builder<long>();
+        var sizesBuffer = new ArrowBuffer.Builder<long>();
+        var validityBuffer = new ArrowBuffer.BitmapBuilder();
+
+        foreach (var listValue in values)
+        {
+            if (listValue == null)
+            {
+                offsetBuffer.Append(valuesBuilder.Length);
+                sizesBuffer.Append(0);
+                validityBuffer.Append(false);
+            }
+            else
+            {
+                offsetBuffer.Append(valuesBuilder.Length);
+                sizesBuffer.Append(listValue.Length);
+                foreach (var value in listValue)
+                {
+                    valuesBuilder.Append(value);
+                }
+                validityBuffer.Append(true);
+            }
+        }
+
+        return new LargeListViewArray(
+            new LargeListViewType(new Int32Type()), values.Length,
+            offsetBuffer.Build(), sizesBuffer.Build(), valuesBuilder.Build(), 
validityBuffer.Build(),
+            validityBuffer.UnsetBitCount);
+    }
+}
diff --git a/test/Apache.Arrow.Tests/TableTests.cs 
b/test/Apache.Arrow.Tests/TableTests.cs
index a12e7b9..309ef7b 100644
--- a/test/Apache.Arrow.Tests/TableTests.cs
+++ b/test/Apache.Arrow.Tests/TableTests.cs
@@ -63,9 +63,9 @@ namespace Apache.Arrow.Tests
             Table table1 = Table.TableFromRecordBatches(recordBatch1.Schema, 
recordBatches);
             Assert.Equal(20, table1.RowCount);
 #if NET5_0_OR_GREATER
-            Assert.Equal(40, table1.ColumnCount);
+            Assert.Equal(41, table1.ColumnCount);
 #else
-            Assert.Equal(39, table1.ColumnCount);
+            Assert.Equal(40, table1.ColumnCount);
 #endif
             Assert.Equal("ChunkedArray: Length=20, DataType=list", 
table1.Column(0).Data.ToString());
 
diff --git a/test/Apache.Arrow.Tests/TestData.cs 
b/test/Apache.Arrow.Tests/TestData.cs
index 3991bcd..08205cb 100644
--- a/test/Apache.Arrow.Tests/TestData.cs
+++ b/test/Apache.Arrow.Tests/TestData.cs
@@ -51,6 +51,7 @@ namespace Apache.Arrow.Tests
                 AddField(CreateField(new ListType(Int64Type.Default), i));
                 AddField(CreateField(new ListViewType(Int64Type.Default), i));
                 AddField(CreateField(new LargeListType(Int64Type.Default), i));
+                AddField(CreateField(new LargeListViewType(Int64Type.Default), 
i));
                 AddField(CreateField(BooleanType.Default, i));
                 AddField(CreateField(UInt8Type.Default, i));
                 AddField(CreateField(Int8Type.Default, i));
@@ -154,6 +155,7 @@ namespace Apache.Arrow.Tests
             IArrowTypeVisitor<ListType>,
             IArrowTypeVisitor<ListViewType>,
             IArrowTypeVisitor<LargeListType>,
+            IArrowTypeVisitor<LargeListViewType>,
             IArrowTypeVisitor<FixedSizeListType>,
             IArrowTypeVisitor<StructType>,
             IArrowTypeVisitor<UnionType>,
@@ -489,6 +491,38 @@ namespace Apache.Arrow.Tests
                     validityBuffer.UnsetBitCount);
             }
 
+            public void Visit(LargeListViewType type)
+            {
+                var valueBuilder = new Int64Array.Builder().Reserve(Length * 3 
/ 2);
+                var offsetBuffer = new ArrowBuffer.Builder<long>();
+                var sizesBuffer = new ArrowBuffer.Builder<long>();
+                var validityBuffer = new ArrowBuffer.BitmapBuilder();
+
+                for (var i = 0; i < Length; i++)
+                {
+                    if (i % 10 == 2)
+                    {
+                        offsetBuffer.Append(valueBuilder.Length);
+                        sizesBuffer.Append(0);
+                        validityBuffer.Append(false);
+                    }
+                    else
+                    {
+                        var listLength = i % 4;
+                        offsetBuffer.Append(valueBuilder.Length);
+                        sizesBuffer.Append(listLength);
+                        valueBuilder.AppendRange(Enumerable.Range(i, 
listLength).Select(x => (long)x));
+                        validityBuffer.Append(true);
+                    }
+                }
+
+                var validity = validityBuffer.UnsetBitCount > 0 ? 
validityBuffer.Build() : ArrowBuffer.Empty;
+                Array = new LargeListViewArray(
+                    new LargeListViewType(new Int64Type()), Length,
+                    offsetBuffer.Build(), sizesBuffer.Build(), 
valueBuilder.Build(), validity,
+                    validityBuffer.UnsetBitCount);
+            }
+
             public void Visit(FixedSizeListType type)
             {
                 var builder = new FixedSizeListArray.Builder(type.ValueField, 
type.ListSize).Reserve(Length);

Reply via email to