1- using System ;
1+ using DuckDB . NET . Native ;
2+ using System ;
23using System . Collections ;
34using System . Collections . Generic ;
45using System . Numerics ;
5- using DuckDB . NET . Native ;
66
77namespace DuckDB . NET . Data . Internal . Writer ;
88
99internal sealed unsafe class ListVectorDataWriter : VectorDataWriterBase
1010{
1111 private ulong offset = 0 ;
12+ private readonly ulong arraySize ;
1213 private readonly VectorDataWriterBase listItemWriter ;
1314
15+ public bool IsList => ColumnType == DuckDBType . List ;
16+ private ulong vectorReservedSize = DuckDBGlobalData . VectorSize ;
17+
1418 public ListVectorDataWriter ( IntPtr vector , void * vectorData , DuckDBType columnType , DuckDBLogicalType logicalType ) : base ( vector , vectorData , columnType )
1519 {
16- using var childType = NativeMethods . LogicalType . DuckDBListTypeChildType ( logicalType ) ;
17- var childVector = NativeMethods . Vectors . DuckDBListVectorGetChild ( vector ) ;
20+ using var childType = IsList ? NativeMethods . LogicalType . DuckDBListTypeChildType ( logicalType ) : NativeMethods . LogicalType . DuckDBArrayTypeChildType ( logicalType ) ;
21+ var childVector = IsList ? NativeMethods . Vectors . DuckDBListVectorGetChild ( vector ) : NativeMethods . Vectors . DuckDBArrayVectorGetChild ( vector ) ; ;
22+
23+ arraySize = IsList ? 0 : ( ulong ) NativeMethods . LogicalType . DuckDBArrayVectorGetSize ( logicalType ) ;
1824 listItemWriter = VectorDataWriterFactory . CreateWriter ( childVector , childType ) ;
1925 }
2026
21- internal override bool AppendCollection ( IList value , int rowIndex )
27+ internal override bool AppendCollection ( ICollection value , int rowIndex )
2228 {
29+ var count = ( ulong ) value . Count ;
30+
31+ ResizeVector ( rowIndex , count ) ;
32+
2333 _ = value switch
2434 {
2535 IEnumerable < bool > items => WriteItems ( items ) ,
@@ -32,10 +42,10 @@ internal override bool AppendCollection(IList value, int rowIndex)
3242 IEnumerable < ushort > items => WriteItems ( items ) ,
3343 IEnumerable < uint > items => WriteItems ( items ) ,
3444 IEnumerable < ulong > items => WriteItems ( items ) ,
35-
45+
3646 IEnumerable < decimal > items => WriteItems ( items ) ,
3747 IEnumerable < BigInteger > items => WriteItems ( items ) ,
38-
48+
3949 IEnumerable < string > items => WriteItems ( items ) ,
4050 IEnumerable < Guid > items => WriteItems ( items ) ,
4151 IEnumerable < DateTime > items => WriteItems ( items ) ,
@@ -47,18 +57,24 @@ internal override bool AppendCollection(IList value, int rowIndex)
4757 IEnumerable< TimeOnly > items => WriteItems ( items ) ,
4858#endif
4959 IEnumerable< DateTimeOffset > items => WriteItems ( items ) ,
50-
60+
5161 _ => WriteItems < object > ( ( IEnumerable < object > ) value )
5262 } ;
5363
54- var result = AppendValueInternal ( new DuckDBListEntry ( offset , ( ulong ) value . Count ) , rowIndex ) ;
64+ var duckDBListEntry = new DuckDBListEntry ( offset , count ) ;
65+ var result = ! IsList || AppendValueInternal ( duckDBListEntry , rowIndex ) ;
5566
56- offset += ( ulong ) value . Count ;
67+ offset += count ;
5768
5869 return result ;
5970
6071 int WriteItems < T > ( IEnumerable < T > items )
6172 {
73+ if ( IsList == false && count != arraySize )
74+ {
75+ throw new InvalidOperationException ( $ "Column has Array size of { arraySize } but the specified value has size of { count } ") ;
76+ } ;
77+
6278 var index = 0 ;
6379
6480 foreach ( var item in items )
@@ -69,4 +85,32 @@ int WriteItems<T>(IEnumerable<T> items)
6985 return 0 ;
7086 }
7187 }
88+
89+ private void ResizeVector ( int rowIndex , ulong count )
90+ {
91+ //If writing to a list column we need to make sure that enough space is allocated. Not needed for Arrays as DuckDB does it for us.
92+ if ( ! IsList || offset + count <= vectorReservedSize ) return ;
93+
94+ var factor = 2d ;
95+
96+ if ( rowIndex > DuckDBGlobalData . VectorSize * 0.25 && rowIndex < DuckDBGlobalData . VectorSize * 0.5 )
97+ {
98+ factor = 1.75 ;
99+ }
100+
101+ if ( rowIndex > DuckDBGlobalData . VectorSize * 0.5 && rowIndex < DuckDBGlobalData . VectorSize * 0.75 )
102+ {
103+ factor = 1.5 ;
104+ }
105+
106+ if ( rowIndex > DuckDBGlobalData . VectorSize * 0.75 )
107+ {
108+ factor = 1.25 ;
109+ }
110+
111+ vectorReservedSize = ( ulong ) Math . Max ( vectorReservedSize * factor , offset + count ) ;
112+ var state = NativeMethods . Vectors . DuckDBListVectorReserve ( Vector , vectorReservedSize ) ;
113+
114+ listItemWriter . FetchDataPointer ( ) ;
115+ }
72116}
0 commit comments