@@ -141,32 +141,32 @@ static std::pair<ArrowSchema*, ArrowArray*> arrow_string_array(
141141 schema->release = &release_schema;
142142 schema->private_data = nullptr ;
143143
144- int n_buffers = offsets.capacity () ? 3 : 2 ;
145-
146144 auto array = (struct ArrowArray *)malloc (sizeof (struct ArrowArray ));
147145 array->length = length;
148146 array->null_count = 0 ;
149147 array->offset = 0 ;
150- array->n_buffers = n_buffers ;
148+ array->n_buffers = 3 ;
151149 array->n_children = 0 ;
152150 array->buffers = nullptr ;
153151 array->children = nullptr ;
154152 array->dictionary = nullptr ;
155153 array->release = &release_array;
156154 array->private_data = (void *)new ArrowBuffer (buffer);
157155
158- array->buffers = (const void **)malloc (n_buffers * sizeof (void *));
159- array->buffers [0 ] = nullptr ; // validity
160- array->buffers [n_buffers - 1 ] = data.data (); // data
161- if (n_buffers == 3 ) {
162- array->buffers [1 ] = offsets.data (); // offsets
163- }
164-
156+ array->buffers = (const void **)malloc (3 * sizeof (void *));
165157 if (bitmap.capacity ()) {
166158 schema->flags |= ARROW_FLAG_NULLABLE ;
167159 array->null_count = -1 ;
168160 array->buffers [0 ] = bitmap.data ();
161+ } else {
162+ array->buffers [0 ] = nullptr ; // validity
163+ }
164+ // Edge case: empty results should still have a single 0 offset
165+ if (!length && !offsets.size ()) {
166+ offsets.push_back (0 );
169167 }
168+ array->buffers [1 ] = offsets.data (); // offsets
169+ array->buffers [2 ] = data.data (); // data
170170
171171 return std::make_pair (schema, array);
172172}
@@ -205,7 +205,11 @@ static std::pair<ArrowSchema*, ArrowArray*> arrow_list_array(
205205 array->private_data = nullptr ; // Buffers will be deleted by the child array
206206
207207 array->buffers = (const void **)malloc (array->n_buffers * sizeof (void *));
208- array->buffers [0 ] = nullptr ; // validity
208+ array->buffers [0 ] = nullptr ; // validity
209+ // Edge case: empty results should still have a single 0 offset
210+ if (!length && !value_offsets.size ()) {
211+ value_offsets.push_back (0 );
212+ }
209213 array->buffers [1 ] = value_offsets.data (); // data
210214
211215 if (bitmap.capacity ()) {
@@ -234,12 +238,12 @@ void build_arrow_array(
234238 auto [values_schema, values_array] =
235239 arrow_data_array (buffer, num_data_elements, buffer->data ());
236240
241+ // Edge case: only subtract if there's offsets to avoid underflow
242+ if (num_offsets) {
243+ num_offsets -= 1 ;
244+ }
237245 std::tie (array_schema, array_array) = arrow_list_array (
238- buffer,
239- num_offsets - 1 ,
240- buffer->offsets (),
241- values_schema,
242- values_array);
246+ buffer, num_offsets, buffer->offsets (), values_schema, values_array);
243247 } else {
244248 std::tie (array_schema, array_array) =
245249 arrow_data_array (buffer, num_data_elements, buffer->data ());
@@ -278,9 +282,13 @@ void build_arrow_array_from_buffer(
278282 uint64_t num_data_elements) {
279283 if (buffer->datatype () == TILEDB_VCF_CHAR ) {
280284 if (buffer->list_offsets ().capacity () > 0 ) {
285+ // Edge case: only subtract if there's offsets to avoid underflow
286+ if (num_offsets) {
287+ num_offsets -= 1 ;
288+ }
281289 // Array of strings
282290 auto [values_schema, values_array] = arrow_string_array (
283- buffer, num_offsets - 1 , buffer->offsets (), buffer->data ());
291+ buffer, num_offsets, buffer->offsets (), buffer->data ());
284292
285293 // Array of lists of strings
286294 auto [arrow_schema, arrow_array] = arrow_list_array (
0 commit comments