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

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


The following commit(s) were added to refs/heads/main by this push:
     new a6f7cb7  chore(c/vendor): Update vendored nanoarrow (#596)
a6f7cb7 is described below

commit a6f7cb7f15c06a85a520fab8205dae19c5a35058
Author: Dewey Dunnington <[email protected]>
AuthorDate: Wed Apr 19 22:03:23 2023 -0400

    chore(c/vendor): Update vendored nanoarrow (#596)
    
    Updates to the latest nanoarrow. In particular, this is needed to fix
    the Windows postgres driver packaging for R since the existing
    nanoarrow.hpp was creating some compiler errors.
---
 c/driver/postgresql/statement.cc    |   2 +-
 c/driver/sqlite/sqlite.c            |   8 +-
 c/driver/sqlite/statement_reader.c  |   2 +-
 c/validation/adbc_validation_util.h |   2 +-
 c/vendor/nanoarrow/nanoarrow.c      | 393 +++++++++++++++++++++++++++---------
 c/vendor/nanoarrow/nanoarrow.h      | 231 +++++++++++++++++++--
 c/vendor/nanoarrow/nanoarrow.hpp    |   4 +-
 c/vendor/vendor_nanoarrow.sh        |  16 +-
 8 files changed, 537 insertions(+), 121 deletions(-)

diff --git a/c/driver/postgresql/statement.cc b/c/driver/postgresql/statement.cc
index 8bd1782..900b23e 100644
--- a/c/driver/postgresql/statement.cc
+++ b/c/driver/postgresql/statement.cc
@@ -464,7 +464,7 @@ int TupleReader::GetNext(struct ArrowArray* out) {
     out->children[col]->length = num_rows;
   }
   out->length = num_rows;
-  na_res = ArrowArrayFinishBuilding(out, 0);
+  na_res = ArrowArrayFinishBuildingDefault(out, 0);
   if (na_res != 0) {
     result_code = na_res;
     if (!last_error_.empty()) last_error_ += '\n';
diff --git a/c/driver/sqlite/sqlite.c b/c/driver/sqlite/sqlite.c
index 1c93fdf..dab5e72 100644
--- a/c/driver/sqlite/sqlite.c
+++ b/c/driver/sqlite/sqlite.c
@@ -343,7 +343,8 @@ AdbcStatusCode SqliteConnectionGetInfoImpl(const uint32_t* 
info_codes,
     CHECK_NA(INTERNAL, ArrowArrayFinishElement(array), error);
   }
 
-  CHECK_NA_DETAIL(INTERNAL, ArrowArrayFinishBuilding(array, &na_error), 
&na_error, error);
+  CHECK_NA_DETAIL(INTERNAL, ArrowArrayFinishBuildingDefault(array, &na_error), 
&na_error,
+                  error);
 
   return ADBC_STATUS_OK;
 }  // NOLINT(whitespace/indent)
@@ -971,7 +972,8 @@ AdbcStatusCode SqliteConnectionGetObjectsImpl(
     // TODO: implement "temp", other attached databases as catalogs
   }
 
-  CHECK_NA_DETAIL(INTERNAL, ArrowArrayFinishBuilding(array, &na_error), 
&na_error, error);
+  CHECK_NA_DETAIL(INTERNAL, ArrowArrayFinishBuildingDefault(array, &na_error), 
&na_error,
+                  error);
   return ADBC_STATUS_OK;
 }
 
@@ -1072,7 +1074,7 @@ AdbcStatusCode SqliteConnectionGetTableTypesImpl(struct 
ArrowSchema* schema,
            error);
   CHECK_NA(INTERNAL, ArrowArrayFinishElement(array), error);
 
-  CHECK_NA(INTERNAL, ArrowArrayFinishBuilding(array, NULL), error);
+  CHECK_NA(INTERNAL, ArrowArrayFinishBuildingDefault(array, NULL), error);
   return ADBC_STATUS_OK;
 }
 
diff --git a/c/driver/sqlite/statement_reader.c 
b/c/driver/sqlite/statement_reader.c
index 8b57906..abde44a 100644
--- a/c/driver/sqlite/statement_reader.c
+++ b/c/driver/sqlite/statement_reader.c
@@ -424,7 +424,7 @@ int StatementReaderGetNext(struct ArrowArrayStream* self, 
struct ArrowArray* out
   if (status == 0) {
     out->length = batch_size;
     for (int i = 0; i < reader->schema.n_children; i++) {
-      status = ArrowArrayFinishBuilding(out->children[i], &reader->error);
+      status = ArrowArrayFinishBuildingDefault(out->children[i], 
&reader->error);
       if (status != 0) break;
     }
 
diff --git a/c/validation/adbc_validation_util.h 
b/c/validation/adbc_validation_util.h
index 66d1a05..9086068 100644
--- a/c/validation/adbc_validation_util.h
+++ b/c/validation/adbc_validation_util.h
@@ -298,7 +298,7 @@ int MakeBatch(struct ArrowArray* batch, struct ArrowError* 
error,
     }
     batch->length = batch->children[i]->length;
   }
-  return ArrowArrayFinishBuilding(batch, error);
+  return ArrowArrayFinishBuildingDefault(batch, error);
 }
 
 template <typename... T>
diff --git a/c/vendor/nanoarrow/nanoarrow.c b/c/vendor/nanoarrow/nanoarrow.c
index 23042dc..0b8fc35 100644
--- a/c/vendor/nanoarrow/nanoarrow.c
+++ b/c/vendor/nanoarrow/nanoarrow.c
@@ -24,9 +24,9 @@
 
 #include "nanoarrow.h"
 
-const char* ArrowNanoarrowVersion() { return NANOARROW_VERSION; }
+const char* ArrowNanoarrowVersion(void) { return NANOARROW_VERSION; }
 
-int ArrowNanoarrowVersionInt() { return NANOARROW_VERSION_INT; }
+int ArrowNanoarrowVersionInt(void) { return NANOARROW_VERSION_INT; }
 
 int ArrowErrorSet(struct ArrowError* error, const char* fmt, ...) {
   if (error == NULL) {
@@ -169,7 +169,7 @@ void ArrowFree(void* ptr) { free(ptr); }
 static uint8_t* ArrowBufferAllocatorMallocReallocate(
     struct ArrowBufferAllocator* allocator, uint8_t* ptr, int64_t old_size,
     int64_t new_size) {
-  return ArrowRealloc(ptr, new_size);
+  return (uint8_t*)ArrowRealloc(ptr, new_size);
 }
 
 static void ArrowBufferAllocatorMallocFree(struct ArrowBufferAllocator* 
allocator,
@@ -1040,12 +1040,12 @@ static ArrowErrorCode ArrowSchemaViewParse(struct 
ArrowSchemaView* schema_view,
         case 's':
           switch (format[2]) {
             case 's':
-              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
+              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
               schema_view->type = NANOARROW_TYPE_TIMESTAMP;
               schema_view->time_unit = NANOARROW_TIME_UNIT_SECOND;
               break;
             case 'm':
-              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
+              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
               schema_view->type = NANOARROW_TYPE_TIMESTAMP;
               schema_view->time_unit = NANOARROW_TIME_UNIT_MILLI;
               break;
@@ -1080,13 +1080,13 @@ static ArrowErrorCode ArrowSchemaViewParse(struct 
ArrowSchemaView* schema_view,
         case 'D':
           switch (format[2]) {
             case 's':
-              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
+              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
               schema_view->type = NANOARROW_TYPE_DURATION;
               schema_view->time_unit = NANOARROW_TIME_UNIT_SECOND;
               *format_end_out = format + 3;
               return NANOARROW_OK;
             case 'm':
-              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT32);
+              ArrowSchemaViewSetPrimitive(schema_view, NANOARROW_TYPE_INT64);
               schema_view->type = NANOARROW_TYPE_DURATION;
               schema_view->time_unit = NANOARROW_TIME_UNIT_MILLI;
               *format_end_out = format + 3;
@@ -1413,6 +1413,24 @@ static int64_t ArrowSchemaTypeToStringInternal(struct 
ArrowSchemaView* schema_vi
   }
 }
 
+// Helper for bookeeping to emulate sprintf()-like behaviour spread
+// among multiple sprintf calls.
+static inline void ArrowToStringLogChars(char** out, int64_t n_chars_last,
+                                         int64_t* n_remaining, int64_t* 
n_chars) {
+  *n_chars += n_chars_last;
+  *n_remaining -= n_chars_last;
+
+  // n_remaining is never less than 0
+  if (*n_remaining < 0) {
+    *n_remaining = 0;
+  }
+
+  // Can't do math on a NULL pointer
+  if (*out != NULL) {
+    *out += n_chars_last;
+  }
+}
+
 int64_t ArrowSchemaToString(struct ArrowSchema* schema, char* out, int64_t n,
                             char recursive) {
   if (schema == NULL) {
@@ -1439,90 +1457,59 @@ int64_t ArrowSchemaToString(struct ArrowSchema* schema, 
char* out, int64_t n,
 
   // Uncommon but not technically impossible that both are true
   if (is_extension && is_dictionary) {
-    n_chars_last = snprintf(out + n_chars, n, "%.*s{dictionary(%s)<",
-                            (int)schema_view.extension_name.size_bytes,
-                            schema_view.extension_name.data,
-                            ArrowTypeString(schema_view.storage_type));
+    n_chars_last = snprintf(
+        out, n, "%.*s{dictionary(%s)<", 
(int)schema_view.extension_name.size_bytes,
+        schema_view.extension_name.data, 
ArrowTypeString(schema_view.storage_type));
   } else if (is_extension) {
-    n_chars_last =
-        snprintf(out + n_chars, n, "%.*s{", 
(int)schema_view.extension_name.size_bytes,
-                 schema_view.extension_name.data);
+    n_chars_last = snprintf(out, n, "%.*s{", 
(int)schema_view.extension_name.size_bytes,
+                            schema_view.extension_name.data);
   } else if (is_dictionary) {
-    n_chars_last = snprintf(out + n_chars, n, "dictionary(%s)<",
-                            ArrowTypeString(schema_view.storage_type));
+    n_chars_last =
+        snprintf(out, n, "dictionary(%s)<", 
ArrowTypeString(schema_view.storage_type));
   }
 
-  n_chars += n_chars_last;
-  n -= n_chars_last;
-  if (n < 0) {
-    n = 0;
-  }
+  ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
 
   if (!is_dictionary) {
-    n_chars_last = ArrowSchemaTypeToStringInternal(&schema_view, out + 
n_chars, n);
+    n_chars_last = ArrowSchemaTypeToStringInternal(&schema_view, out, n);
   } else {
-    n_chars_last = ArrowSchemaToString(schema->dictionary, out + n_chars, n, 
recursive);
+    n_chars_last = ArrowSchemaToString(schema->dictionary, out, n, recursive);
   }
 
-  n_chars += n_chars_last;
-  n -= n_chars_last;
-  if (n < 0) {
-    n = 0;
-  }
+  ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
 
   if (recursive && schema->format[0] == '+') {
-    n_chars_last = snprintf(out + n_chars, n, "<");
-    n_chars += n_chars_last;
-    n -= n_chars_last;
-    if (n < 0) {
-      n = 0;
-    }
+    n_chars_last = snprintf(out, n, "<");
+    ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
 
     for (int64_t i = 0; i < schema->n_children; i++) {
       if (i > 0) {
-        n_chars_last = snprintf(out + n_chars, n, ", ");
-        n_chars += n_chars_last;
-        n -= n_chars_last;
-        if (n < 0) {
-          n = 0;
-        }
+        n_chars_last = snprintf(out, n, ", ");
+        ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
       }
 
       // ArrowSchemaToStringInternal() will validate the child and print the 
error,
       // but we need the name first
       if (schema->children[i] != NULL && schema->children[i]->release != NULL 
&&
           schema->children[i]->name != NULL) {
-        n_chars_last = snprintf(out + n_chars, n, "%s: ", 
schema->children[i]->name);
-        n_chars += n_chars_last;
-        n -= n_chars_last;
-        if (n < 0) {
-          n = 0;
-        }
+        n_chars_last = snprintf(out, n, "%s: ", schema->children[i]->name);
+        ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
       }
 
-      n_chars_last =
-          ArrowSchemaToString(schema->children[i], out + n_chars, n, 
recursive);
-      n_chars += n_chars_last;
-      n -= n_chars_last;
-      if (n < 0) {
-        n = 0;
-      }
+      n_chars_last = ArrowSchemaToString(schema->children[i], out, n, 
recursive);
+      ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
     }
 
-    n_chars_last = snprintf(out + n_chars, n, ">");
-    n_chars += n_chars_last;
-    n -= n_chars_last;
-    if (n < 0) {
-      n = 0;
-    }
+    n_chars_last = snprintf(out, n, ">");
+    ArrowToStringLogChars(&out, n_chars_last, &n, &n_chars);
   }
 
   if (is_extension && is_dictionary) {
-    n_chars += snprintf(out + n_chars, n, ">}");
+    n_chars += snprintf(out, n, ">}");
   } else if (is_extension) {
-    n_chars += snprintf(out + n_chars, n, "}");
+    n_chars += snprintf(out, n, "}");
   } else if (is_dictionary) {
-    n_chars += snprintf(out + n_chars, n, ">");
+    n_chars += snprintf(out, n, ">");
   }
 
   return n_chars;
@@ -2160,8 +2147,8 @@ static ArrowErrorCode ArrowArrayCheckInternalBufferSizes(
     if (actual_size < expected_size) {
       ArrowErrorSet(
           error,
-          "Expected buffer %d to size >= %ld bytes but found buffer with %ld 
bytes", i,
-          (long)expected_size, (long)actual_size);
+          "Expected buffer %d to size >= %ld bytes but found buffer with %ld 
bytes",
+          (int)i, (long)expected_size, (long)actual_size);
       return EINVAL;
     }
   }
@@ -2175,14 +2162,23 @@ static ArrowErrorCode 
ArrowArrayCheckInternalBufferSizes(
 }
 
 ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray* array,
+                                        enum ArrowValidationLevel 
validation_level,
                                         struct ArrowError* error) {
-  // Even if the data buffer is size zero, the value needs to be non-null
-  NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array));
+  // Even if the data buffer is size zero, the pointer value needed to be 
non-null
+  // in some implementations (at least one version of Arrow C++ at the time 
this
+  // was added). Only do this fix if we can assume CPU data access.
+  if (validation_level >= NANOARROW_VALIDATION_LEVEL_DEFAULT) {
+    NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array));
+  }
 
   // Make sure the value we get with array->buffers[i] is set to the actual
   // pointer (which may have changed from the original due to reallocation)
   ArrowArrayFlushInternalPointers(array);
 
+  if (validation_level == NANOARROW_VALIDATION_LEVEL_NONE) {
+    return NANOARROW_OK;
+  }
+
   // Check buffer sizes to make sure we are not sending an ArrowArray
   // into the wild that is going to segfault
   struct ArrowArrayView array_view;
@@ -2198,6 +2194,11 @@ ArrowErrorCode ArrowArrayFinishBuilding(struct 
ArrowArray* array,
     return result;
   }
 
+  if (validation_level == NANOARROW_VALIDATION_LEVEL_MINIMAL) {
+    ArrowArrayViewReset(&array_view);
+    return NANOARROW_OK;
+  }
+
   result = ArrowArrayViewSetArray(&array_view, array, error);
   if (result != NANOARROW_OK) {
     ArrowArrayViewReset(&array_view);
@@ -2205,10 +2206,26 @@ ArrowErrorCode ArrowArrayFinishBuilding(struct 
ArrowArray* array,
   }
 
   result = ArrowArrayCheckInternalBufferSizes(array, &array_view, 0, error);
+  if (result != NANOARROW_OK) {
+    ArrowArrayViewReset(&array_view);
+    return result;
+  }
+
+  if (validation_level == NANOARROW_VALIDATION_LEVEL_DEFAULT) {
+    ArrowArrayViewReset(&array_view);
+    return NANOARROW_OK;
+  }
+
+  result = ArrowArrayViewValidateFull(&array_view, error);
   ArrowArrayViewReset(&array_view);
   return result;
 }
 
+ArrowErrorCode ArrowArrayFinishBuildingDefault(struct ArrowArray* array,
+                                               struct ArrowError* error) {
+  return ArrowArrayFinishBuilding(array, NANOARROW_VALIDATION_LEVEL_DEFAULT, 
error);
+}
+
 void ArrowArrayViewInitFromType(struct ArrowArrayView* array_view,
                                 enum ArrowType storage_type) {
   memset(array_view, 0, sizeof(struct ArrowArrayView));
@@ -2362,6 +2379,21 @@ ArrowErrorCode ArrowArrayViewSetArray(struct 
ArrowArrayView* array_view,
                                       struct ArrowArray* array,
                                       struct ArrowError* error) {
   array_view->array = array;
+
+  // Check length and offset
+  if (array->offset < 0) {
+    ArrowErrorSet(error, "Expected array offset >= 0 but found array offset of 
%ld",
+                  (long)array->offset);
+    return EINVAL;
+  }
+
+  if (array->length < 0) {
+    ArrowErrorSet(error, "Expected array length >= 0 but found array length of 
%ld",
+                  (long)array->length);
+    return EINVAL;
+  }
+
+  // First pass setting lengths that do not depend on the data buffer
   ArrowArrayViewSetLength(array_view, array->offset + array->length);
 
   int64_t buffers_required = 0;
@@ -2388,15 +2420,25 @@ ArrowErrorCode ArrowArrayViewSetArray(struct 
ArrowArrayView* array_view,
   }
 
   if (array_view->n_children != array->n_children) {
+    ArrowErrorSet(error, "Expected %ld children but found %ld children",
+                  (long)array_view->n_children, (long)array->n_children);
     return EINVAL;
   }
 
   // Check child sizes and calculate sizes that depend on data in the array 
buffers
+  int64_t first_offset;
   int64_t last_offset;
   switch (array_view->storage_type) {
     case NANOARROW_TYPE_STRING:
     case NANOARROW_TYPE_BINARY:
       if (array_view->buffer_views[1].size_bytes != 0) {
+        first_offset = array_view->buffer_views[1].data.as_int32[0];
+        if (first_offset < 0) {
+          ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
+                        (long)first_offset);
+          return EINVAL;
+        }
+
         last_offset =
             array_view->buffer_views[1].data.as_int32[array->offset + 
array->length];
         array_view->buffer_views[2].size_bytes = last_offset;
@@ -2405,6 +2447,13 @@ ArrowErrorCode ArrowArrayViewSetArray(struct 
ArrowArrayView* array_view,
     case NANOARROW_TYPE_LARGE_STRING:
     case NANOARROW_TYPE_LARGE_BINARY:
       if (array_view->buffer_views[1].size_bytes != 0) {
+        first_offset = array_view->buffer_views[1].data.as_int64[0];
+        if (first_offset < 0) {
+          ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
+                        (long)first_offset);
+          return EINVAL;
+        }
+
         last_offset =
             array_view->buffer_views[1].data.as_int64[array->offset + 
array->length];
         array_view->buffer_views[2].size_bytes = last_offset;
@@ -2434,6 +2483,13 @@ ArrowErrorCode ArrowArrayViewSetArray(struct 
ArrowArrayView* array_view,
       }
 
       if (array_view->buffer_views[1].size_bytes != 0) {
+        first_offset = array_view->buffer_views[1].data.as_int32[0];
+        if (first_offset < 0) {
+          ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
+                        (long)first_offset);
+          return EINVAL;
+        }
+
         last_offset =
             array_view->buffer_views[1].data.as_int32[array->offset + 
array->length];
         if (array->children[0]->length < last_offset) {
@@ -2456,6 +2512,13 @@ ArrowErrorCode ArrowArrayViewSetArray(struct 
ArrowArrayView* array_view,
       }
 
       if (array_view->buffer_views[1].size_bytes != 0) {
+        first_offset = array_view->buffer_views[1].data.as_int64[0];
+        if (first_offset < 0) {
+          ArrowErrorSet(error, "Expected first offset >= 0 but found %ld",
+                        (long)first_offset);
+          return EINVAL;
+        }
+
         last_offset =
             array_view->buffer_views[1].data.as_int64[array->offset + 
array->length];
         if (array->children[0]->length < last_offset) {
@@ -2498,6 +2561,140 @@ ArrowErrorCode ArrowArrayViewSetArray(struct 
ArrowArrayView* array_view,
 
   return NANOARROW_OK;
 }
+
+static int ArrowAssertIncreasingInt32(struct ArrowBufferView view,
+                                      struct ArrowError* error) {
+  if (view.size_bytes <= (int64_t)sizeof(int32_t)) {
+    return NANOARROW_OK;
+  }
+
+  for (int64_t i = 1; i < view.size_bytes / (int64_t)sizeof(int32_t); i++) {
+    int32_t diff = view.data.as_int32[i] - view.data.as_int32[i - 1];
+    if (diff < 0) {
+      ArrowErrorSet(error, "[%ld] Expected element size >= 0 but found element 
size %ld",
+                    (long)i, (long)diff);
+      return EINVAL;
+    }
+  }
+
+  return NANOARROW_OK;
+}
+
+static int ArrowAssertIncreasingInt64(struct ArrowBufferView view,
+                                      struct ArrowError* error) {
+  if (view.size_bytes <= (int64_t)sizeof(int64_t)) {
+    return NANOARROW_OK;
+  }
+
+  for (int64_t i = 1; i < view.size_bytes / (int64_t)sizeof(int64_t); i++) {
+    int64_t diff = view.data.as_int64[i] - view.data.as_int64[i - 1];
+    if (diff < 0) {
+      ArrowErrorSet(error, "[%ld] Expected element size >= 0 but found element 
size %ld",
+                    (long)i, (long)diff);
+      return EINVAL;
+    }
+  }
+
+  return NANOARROW_OK;
+}
+
+static int ArrowAssertRangeInt8(struct ArrowBufferView view, int8_t min_value,
+                                int8_t max_value, struct ArrowError* error) {
+  for (int64_t i = 0; i < view.size_bytes; i++) {
+    if (view.data.as_int8[i] < min_value || view.data.as_int8[i] > max_value) {
+      ArrowErrorSet(error,
+                    "[%ld] Expected buffer value between %d and %d but found 
value %d",
+                    (long)i, (int)min_value, (int)max_value, 
(int)view.data.as_int8[i]);
+      return EINVAL;
+    }
+  }
+
+  return NANOARROW_OK;
+}
+
+static int ArrowAssertInt8In(struct ArrowBufferView view, const int8_t* values,
+                             int64_t n_values, struct ArrowError* error) {
+  for (int64_t i = 0; i < view.size_bytes; i++) {
+    int item_found = 0;
+    for (int64_t j = 0; j < n_values; j++) {
+      if (view.data.as_int8[i] == values[j]) {
+        item_found = 1;
+        break;
+      }
+    }
+
+    if (!item_found) {
+      ArrowErrorSet(error, "[%ld] Unexpected buffer value %d", (long)i,
+                    (int)view.data.as_int8[i]);
+      return EINVAL;
+    }
+  }
+
+  return NANOARROW_OK;
+}
+
+ArrowErrorCode ArrowArrayViewValidateFull(struct ArrowArrayView* array_view,
+                                          struct ArrowError* error) {
+  for (int i = 0; i < 3; i++) {
+    switch (array_view->layout.buffer_type[i]) {
+      case NANOARROW_BUFFER_TYPE_DATA_OFFSET:
+        if (array_view->layout.element_size_bits[i] == 32) {
+          NANOARROW_RETURN_NOT_OK(
+              ArrowAssertIncreasingInt32(array_view->buffer_views[i], error));
+        } else {
+          NANOARROW_RETURN_NOT_OK(
+              ArrowAssertIncreasingInt64(array_view->buffer_views[i], error));
+        }
+        break;
+      default:
+        break;
+    }
+  }
+
+  if (array_view->storage_type == NANOARROW_TYPE_DENSE_UNION ||
+      array_view->storage_type == NANOARROW_TYPE_SPARSE_UNION) {
+    // Check that we have valid type ids.
+    if (array_view->union_type_id_map == NULL) {
+      // If the union_type_id map is NULL
+      // (e.g., when using ArrowArrayInitFromType() + 
ArrowArrayAllocateChildren()
+      // + ArrowArrayFinishBuilding()), we don't have enough information to 
validate
+      // this buffer (GH-178).
+    } else if (_ArrowParsedUnionTypeIdsWillEqualChildIndices(
+                   array_view->union_type_id_map, array_view->n_children,
+                   array_view->n_children)) {
+      
NANOARROW_RETURN_NOT_OK(ArrowAssertRangeInt8(array_view->buffer_views[0], 0,
+                                                   array_view->n_children - 1, 
error));
+    } else {
+      NANOARROW_RETURN_NOT_OK(ArrowAssertInt8In(array_view->buffer_views[0],
+                                                array_view->union_type_id_map 
+ 128,
+                                                array_view->n_children, 
error));
+    }
+  }
+
+  if (array_view->storage_type == NANOARROW_TYPE_DENSE_UNION &&
+      array_view->union_type_id_map != NULL) {
+    // Check that offsets refer to child elements that actually exist
+    for (int64_t i = 0; i < array_view->array->length; i++) {
+      int8_t child_id = ArrowArrayViewUnionChildIndex(array_view, i);
+      int64_t offset = ArrowArrayViewUnionChildOffset(array_view, i);
+      int64_t child_length = array_view->array->children[child_id]->length;
+      if (offset < 0 || offset > child_length) {
+        ArrowErrorSet(
+            error,
+            "[%ld] Expected union offset for child id %d to be between 0 and 
%ld but "
+            "found offset value %ld",
+            (long)i, (int)child_id, (long)child_length, offset);
+        return EINVAL;
+      }
+    }
+  }
+
+  for (int64_t i = 0; i < array_view->n_children; i++) {
+    
NANOARROW_RETURN_NOT_OK(ArrowArrayViewValidateFull(array_view->children[i], 
error));
+  }
+
+  return NANOARROW_OK;
+}
 // 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
@@ -2532,9 +2729,9 @@ static int ArrowBasicArrayStreamGetSchema(struct 
ArrowArrayStream* array_stream,
     return EINVAL;
   }
 
-  struct BasicArrayStreamPrivate* private =
+  struct BasicArrayStreamPrivate* private_data =
       (struct BasicArrayStreamPrivate*)array_stream->private_data;
-  return ArrowSchemaDeepCopy(&private->schema, schema);
+  return ArrowSchemaDeepCopy(&private_data->schema, schema);
 }
 
 static int ArrowBasicArrayStreamGetNext(struct ArrowArrayStream* array_stream,
@@ -2543,15 +2740,15 @@ static int ArrowBasicArrayStreamGetNext(struct 
ArrowArrayStream* array_stream,
     return EINVAL;
   }
 
-  struct BasicArrayStreamPrivate* private =
+  struct BasicArrayStreamPrivate* private_data =
       (struct BasicArrayStreamPrivate*)array_stream->private_data;
 
-  if (private->arrays_i == private->n_arrays) {
+  if (private_data->arrays_i == private_data->n_arrays) {
     array->release = NULL;
     return NANOARROW_OK;
   }
 
-  ArrowArrayMove(&private->arrays[private->arrays_i++], array);
+  ArrowArrayMove(&private_data->arrays[private_data->arrays_i++], array);
   return NANOARROW_OK;
 }
 
@@ -2565,81 +2762,81 @@ static void ArrowBasicArrayStreamRelease(struct 
ArrowArrayStream* array_stream)
     return;
   }
 
-  struct BasicArrayStreamPrivate* private =
+  struct BasicArrayStreamPrivate* private_data =
       (struct BasicArrayStreamPrivate*)array_stream->private_data;
 
-  if (private->schema.release != NULL) {
-    private->schema.release(&private->schema);
+  if (private_data->schema.release != NULL) {
+    private_data->schema.release(&private_data->schema);
   }
 
-  for (int64_t i = 0; i < private->n_arrays; i++) {
-    if (private->arrays[i].release != NULL) {
-      private->arrays[i].release(&private->arrays[i]);
+  for (int64_t i = 0; i < private_data->n_arrays; i++) {
+    if (private_data->arrays[i].release != NULL) {
+      private_data->arrays[i].release(&private_data->arrays[i]);
     }
   }
 
-  if (private->arrays != NULL) {
-    ArrowFree(private->arrays);
+  if (private_data->arrays != NULL) {
+    ArrowFree(private_data->arrays);
   }
 
-  ArrowFree(private);
+  ArrowFree(private_data);
   array_stream->release = NULL;
 }
 
 ArrowErrorCode ArrowBasicArrayStreamInit(struct ArrowArrayStream* array_stream,
                                          struct ArrowSchema* schema, int64_t 
n_arrays) {
-  struct BasicArrayStreamPrivate* private = (struct 
BasicArrayStreamPrivate*)ArrowMalloc(
+  struct BasicArrayStreamPrivate* private_data = (struct 
BasicArrayStreamPrivate*)ArrowMalloc(
       sizeof(struct BasicArrayStreamPrivate));
-  if (private == NULL) {
+  if (private_data == NULL) {
     return ENOMEM;
   }
 
-  ArrowSchemaMove(schema, &private->schema);
+  ArrowSchemaMove(schema, &private_data->schema);
 
-  private->n_arrays = n_arrays;
-  private->arrays = NULL;
-  private->arrays_i = 0;
+  private_data->n_arrays = n_arrays;
+  private_data->arrays = NULL;
+  private_data->arrays_i = 0;
 
   if (n_arrays > 0) {
-    private->arrays =
+    private_data->arrays =
         (struct ArrowArray*)ArrowMalloc(n_arrays * sizeof(struct ArrowArray));
-    if (private->arrays == NULL) {
+    if (private_data->arrays == NULL) {
       ArrowBasicArrayStreamRelease(array_stream);
       return ENOMEM;
     }
   }
 
-  for (int64_t i = 0; i < private->n_arrays; i++) {
-    private->arrays[i].release = NULL;
+  for (int64_t i = 0; i < private_data->n_arrays; i++) {
+    private_data->arrays[i].release = NULL;
   }
 
   array_stream->get_schema = &ArrowBasicArrayStreamGetSchema;
   array_stream->get_next = &ArrowBasicArrayStreamGetNext;
   array_stream->get_last_error = ArrowBasicArrayStreamGetLastError;
   array_stream->release = ArrowBasicArrayStreamRelease;
-  array_stream->private_data = private;
+  array_stream->private_data = private_data;
   return NANOARROW_OK;
 }
 
 void ArrowBasicArrayStreamSetArray(struct ArrowArrayStream* array_stream, 
int64_t i,
                                    struct ArrowArray* array) {
-  struct BasicArrayStreamPrivate* private =
+  struct BasicArrayStreamPrivate* private_data =
       (struct BasicArrayStreamPrivate*)array_stream->private_data;
-  ArrowArrayMove(array, &private->arrays[i]);
+  ArrowArrayMove(array, &private_data->arrays[i]);
 }
 
 ArrowErrorCode ArrowBasicArrayStreamValidate(struct ArrowArrayStream* 
array_stream,
                                              struct ArrowError* error) {
-  struct BasicArrayStreamPrivate* private =
+  struct BasicArrayStreamPrivate* private_data =
       (struct BasicArrayStreamPrivate*)array_stream->private_data;
 
   struct ArrowArrayView array_view;
   NANOARROW_RETURN_NOT_OK(
-      ArrowArrayViewInitFromSchema(&array_view, &private->schema, error));
+      ArrowArrayViewInitFromSchema(&array_view, &private_data->schema, error));
 
-  for (int64_t i = 0; i < private->n_arrays; i++) {
-    if (private->arrays[i].release != NULL) {
-      int result = ArrowArrayViewSetArray(&array_view, &private->arrays[i], 
error);
+  for (int64_t i = 0; i < private_data->n_arrays; i++) {
+    if (private_data->arrays[i].release != NULL) {
+      int result = ArrowArrayViewSetArray(&array_view, 
&private_data->arrays[i], error);
       if (result != NANOARROW_OK) {
         ArrowArrayViewReset(&array_view);
         return result;
diff --git a/c/vendor/nanoarrow/nanoarrow.h b/c/vendor/nanoarrow/nanoarrow.h
index 8fd74a0..f337795 100644
--- a/c/vendor/nanoarrow/nanoarrow.h
+++ b/c/vendor/nanoarrow/nanoarrow.h
@@ -19,15 +19,15 @@
 #define NANOARROW_BUILD_ID_H_INCLUDED
 
 #define NANOARROW_VERSION_MAJOR 0
-#define NANOARROW_VERSION_MINOR 1
+#define NANOARROW_VERSION_MINOR 2
 #define NANOARROW_VERSION_PATCH 0
-#define NANOARROW_VERSION "0.1.0-SNAPSHOT"
+#define NANOARROW_VERSION "0.2.0-SNAPSHOT"
 
 #define NANOARROW_VERSION_INT                                        \
   (NANOARROW_VERSION_MAJOR * 10000 + NANOARROW_VERSION_MINOR * 100 + \
    NANOARROW_VERSION_PATCH)
 
-// #define NANOARROW_NAMESPACE YourNamespaceHere
+#define NANOARROW_NAMESPACE AdbcNs
 
 #endif
 // Licensed to the Apache Software Foundation (ASF) under one
@@ -204,6 +204,13 @@ typedef int ArrowErrorCode;
 #define NANOARROW_RETURN_NOT_OK(EXPR) \
   _NANOARROW_RETURN_NOT_OK_IMPL(_NANOARROW_MAKE_NAME(errno_status_, 
__COUNTER__), EXPR)
 
+static char _ArrowIsLittleEndian(void) {
+  uint32_t check = 1;
+  char first_byte;
+  memcpy(&first_byte, &check, sizeof(char));
+  return first_byte;
+}
+
 /// \brief Arrow type enumerator
 /// \ingroup nanoarrow-utils
 ///
@@ -351,6 +358,25 @@ enum ArrowTimeUnit {
   NANOARROW_TIME_UNIT_NANO = 3
 };
 
+/// \brief Validation level enumerator
+/// \ingroup nanoarrow-array
+enum ArrowValidationLevel {
+  /// \brief Do not validate buffer sizes or content.
+  NANOARROW_VALIDATION_LEVEL_NONE = 0,
+
+  /// \brief Validate buffer sizes that depend on array length but do not 
validate buffer
+  /// sizes that depend on buffer data access.
+  NANOARROW_VALIDATION_LEVEL_MINIMAL = 1,
+
+  /// \brief Validate all buffer sizes, including those that require buffer 
data access,
+  /// but do not perform any checks that are O(1) along the length of the 
buffers.
+  NANOARROW_VALIDATION_LEVEL_DEFAULT = 2,
+
+  /// \brief Validate all buffer sizes and all buffer content. This is useful 
in the
+  /// context of untrusted input or input that may have been corrupted in 
transit.
+  NANOARROW_VALIDATION_LEVEL_FULL = 3
+};
+
 /// \brief Get a string value of an enum ArrowTimeUnit value
 /// \ingroup nanoarrow-utils
 ///
@@ -535,7 +561,8 @@ struct ArrowArrayView {
   ///
   /// If storage_type is a union type, a 256-byte ArrowMalloc()ed buffer
   /// such that child_index == union_type_id_map[type_id] and
-  /// type_id == union_type_id_map[128 + child_index]
+  /// type_id == union_type_id_map[128 + child_index]. This value may be
+  /// NULL in the case where child_id == type_id.
   int8_t* union_type_id_map;
 };
 
@@ -566,6 +593,90 @@ struct ArrowArrayPrivateData {
   int8_t union_type_id_is_child_index;
 };
 
+/// \brief A representation of a fixed-precision decimal number
+/// \ingroup nanoarrow-utils
+///
+/// This structure should be initialized with ArrowDecimalInit() once and
+/// values set using ArrowDecimalSetInt(), ArrowDecimalSetBytes128(),
+/// or ArrowDecimalSetBytes256().
+struct ArrowDecimal {
+  /// \brief An array of 64-bit integers of n_words length defined in 
native-endian order
+  uint64_t words[4];
+
+  /// \brief The number of significant digits this decimal number can represent
+  int32_t precision;
+
+  /// \brief The number of digits after the decimal point. This can be 
negative.
+  int32_t scale;
+
+  /// \brief The number of words in the words array
+  int n_words;
+
+  /// \brief Cached value used by the implementation
+  int high_word_index;
+
+  /// \brief Cached value used by the implementation
+  int low_word_index;
+};
+
+/// \brief Initialize a decimal with a given set of type parameters
+/// \ingroup nanoarrow-utils
+static inline void ArrowDecimalInit(struct ArrowDecimal* decimal, int32_t 
bitwidth,
+                                    int32_t precision, int32_t scale) {
+  memset(decimal->words, 0, sizeof(decimal->words));
+  decimal->precision = precision;
+  decimal->scale = scale;
+  decimal->n_words = bitwidth / 8 / sizeof(uint64_t);
+
+  if (_ArrowIsLittleEndian()) {
+    decimal->low_word_index = 0;
+    decimal->high_word_index = decimal->n_words - 1;
+  } else {
+    decimal->low_word_index = decimal->n_words - 1;
+    decimal->high_word_index = 0;
+  }
+}
+
+/// \brief Get a signed integer value of a sufficiently small ArrowDecimal
+///
+/// This does not check if the decimal's precision sufficiently small to fit
+/// within the signed 64-bit integer range (A precision less than or equal
+/// to 18 is sufficiently small).
+static inline int64_t ArrowDecimalGetIntUnsafe(struct ArrowDecimal* decimal) {
+  return (int64_t)decimal->words[decimal->low_word_index];
+}
+
+/// \brief Copy the bytes of this decimal into a sufficiently large buffer
+/// \ingroup nanoarrow-utils
+static inline void ArrowDecimalGetBytes(struct ArrowDecimal* decimal, uint8_t* 
out) {
+  memcpy(out, decimal->words, decimal->n_words * sizeof(uint64_t));
+}
+
+/// \brief Returns 1 if the value represented by decimal is >= 0 or -1 
otherwise
+/// \ingroup nanoarrow-utils
+static inline int64_t ArrowDecimalSign(struct ArrowDecimal* decimal) {
+  return 1 | ((int64_t)(decimal->words[decimal->high_word_index]) >> 63);
+}
+
+/// \brief Sets the integer value of this decimal
+/// \ingroup nanoarrow-utils
+static inline void ArrowDecimalSetInt(struct ArrowDecimal* decimal, int64_t 
value) {
+  if (value < 0) {
+    memset(decimal->words, 0xff, decimal->n_words * sizeof(uint64_t));
+  } else {
+    memset(decimal->words, 0, decimal->n_words * sizeof(uint64_t));
+  }
+
+  decimal->words[decimal->low_word_index] = value;
+}
+
+/// \brief Copy bytes from a buffer into this decimal
+/// \ingroup nanoarrow-utils
+static inline void ArrowDecimalSetBytes(struct ArrowDecimal* decimal,
+                                        const uint8_t* value) {
+  memcpy(decimal->words, value, decimal->n_words * sizeof(uint64_t));
+}
+
 #ifdef __cplusplus
 }
 #endif
@@ -675,6 +786,8 @@ struct ArrowArrayPrivateData {
 #define ArrowArrayReserve NANOARROW_SYMBOL(NANOARROW_NAMESPACE, 
ArrowArrayReserve)
 #define ArrowArrayFinishBuilding \
   NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayFinishBuilding)
+#define ArrowArrayFinishBuildingDefault \
+  NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayFinishBuildingDefault)
 #define ArrowArrayViewInitFromType \
   NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayViewInitFromType)
 #define ArrowArrayViewInitFromSchema \
@@ -685,6 +798,8 @@ struct ArrowArrayPrivateData {
   NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayViewSetLength)
 #define ArrowArrayViewSetArray \
   NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayViewSetArray)
+#define ArrowArrayViewValidateFull \
+  NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayViewValidateFull)
 #define ArrowArrayViewReset NANOARROW_SYMBOL(NANOARROW_NAMESPACE, 
ArrowArrayViewReset)
 #define ArrowBasicArrayStreamInit \
   NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowBasicArrayStreamInit)
@@ -774,10 +889,10 @@ const char* ArrowErrorMessage(struct ArrowError* error);
 /// @{
 
 /// \brief Return a version string in the form "major.minor.patch"
-const char* ArrowNanoarrowVersion();
+const char* ArrowNanoarrowVersion(void);
 
 /// \brief Return an integer that can be used to compare versions sequentially
-int ArrowNanoarrowVersionInt();
+int ArrowNanoarrowVersionInt(void);
 
 /// \brief Initialize a description of buffer arrangements from a storage type
 void ArrowLayoutInit(struct ArrowLayout* layout, enum ArrowType storage_type);
@@ -1275,7 +1390,10 @@ static inline void ArrowBitmapReset(struct ArrowBitmap* 
bitmap);
 
 /// \defgroup nanoarrow-array Creating arrays
 ///
-/// These functions allocate, copy, and destroy ArrowArray structures
+/// These functions allocate, copy, and destroy ArrowArray structures.
+/// Once an ArrowArray has been initialized via ArrowArrayInitFromType()
+/// or ArrowArrayInitFromSchema(), the caller is responsible for releasing
+/// it using the embedded release callback.
 ///
 /// @{
 
@@ -1390,12 +1508,20 @@ static inline ArrowErrorCode 
ArrowArrayAppendBytes(struct ArrowArray* array,
                                                    struct ArrowBufferView 
value);
 
 /// \brief Append a string value to an array
+///
 /// Returns NANOARROW_OK if value can be exactly represented by
 /// the underlying storage type or EINVAL otherwise (e.g.,
 /// the underlying array is not a string or large string array).
 static inline ArrowErrorCode ArrowArrayAppendString(struct ArrowArray* array,
                                                     struct ArrowStringView 
value);
 
+/// \brief Append a decimal value to an array
+///
+/// Returns NANOARROW_OK if array is a decimal array with the appropriate
+/// bitwidth or EINVAL otherwise.
+static inline ArrowErrorCode ArrowArrayAppendDecimal(struct ArrowArray* array,
+                                                     struct ArrowDecimal* 
value);
+
 /// \brief Finish a nested array element
 ///
 /// Appends a non-null element to the array based on the first child's current
@@ -1423,10 +1549,21 @@ static inline ArrowErrorCode 
ArrowArrayShrinkToFit(struct ArrowArray* array);
 /// \brief Finish building an ArrowArray
 ///
 /// Flushes any pointers from internal buffers that may have been reallocated
-/// into the array->buffers array and checks the actual size of the buffers
+/// into array->buffers and checks the actual size of the buffers
 /// against the expected size based on the final length.
 /// array must have been allocated using ArrowArrayInitFromType()
+ArrowErrorCode ArrowArrayFinishBuildingDefault(struct ArrowArray* array,
+                                               struct ArrowError* error);
+
+/// \brief Finish building an ArrowArray with explicit validation
+///
+/// Finish building with an explicit validation level. This could perform less 
validation
+/// (i.e. NANOARROW_VALIDATION_LEVEL_NONE or 
NANOARROW_VALIDATION_LEVEL_MINIMAL) if CPU
+/// buffer data access is not possible or more validation (i.e.,
+/// NANOARROW_VALIDATION_LEVEL_FULL) if buffer content was obtained from an 
untrusted or
+/// corruptable source.
 ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray* array,
+                                        enum ArrowValidationLevel 
validation_level,
                                         struct ArrowError* error);
 
 /// @}
@@ -1466,6 +1603,10 @@ void ArrowArrayViewSetLength(struct ArrowArrayView* 
array_view, int64_t length);
 ArrowErrorCode ArrowArrayViewSetArray(struct ArrowArrayView* array_view,
                                       struct ArrowArray* array, struct 
ArrowError* error);
 
+/// \brief Performs extra checks on the array that was set via 
ArrowArrayViewSetArray()
+ArrowErrorCode ArrowArrayViewValidateFull(struct ArrowArrayView* array_view,
+                                          struct ArrowError* error);
+
 /// \brief Reset the contents of an ArrowArrayView and frees resources
 void ArrowArrayViewReset(struct ArrowArrayView* array_view);
 
@@ -1517,6 +1658,14 @@ static inline struct ArrowStringView 
ArrowArrayViewGetStringUnsafe(
 static inline struct ArrowBufferView ArrowArrayViewGetBytesUnsafe(
     struct ArrowArrayView* array_view, int64_t i);
 
+/// \brief Get an element in an ArrowArrayView as an ArrowDecimal
+///
+/// This function does not check for null values. The out parameter must
+/// be initialized with ArrowDecimalInit() with the proper parameters for this
+/// type before calling this for the first time.
+static inline void ArrowArrayViewGetDecimalUnsafe(struct ArrowArrayView* 
array_view,
+                                                  int64_t i, struct 
ArrowDecimal* out);
+
 /// @}
 
 /// \defgroup nanoarrow-basic-array-stream Basic ArrowArrayStream 
implementation
@@ -2155,10 +2304,9 @@ static inline int8_t _ArrowParseUnionTypeIds(const char* 
type_ids, int8_t* out)
   return -1;
 }
 
-static inline int8_t _ArrowUnionTypeIdsWillEqualChildIndices(const char* 
type_id_str,
-                                                             int64_t 
n_children) {
-  int8_t type_ids[128];
-  int8_t n_type_ids = _ArrowParseUnionTypeIds(type_id_str, type_ids);
+static inline int8_t _ArrowParsedUnionTypeIdsWillEqualChildIndices(const 
int8_t* type_ids,
+                                                                   int64_t 
n_type_ids,
+                                                                   int64_t 
n_children) {
   if (n_type_ids != n_children) {
     return 0;
   }
@@ -2172,6 +2320,13 @@ static inline int8_t 
_ArrowUnionTypeIdsWillEqualChildIndices(const char* type_id
   return 1;
 }
 
+static inline int8_t _ArrowUnionTypeIdsWillEqualChildIndices(const char* 
type_id_str,
+                                                             int64_t 
n_children) {
+  int8_t type_ids[128];
+  int8_t n_type_ids = _ArrowParseUnionTypeIds(type_id_str, type_ids);
+  return _ArrowParsedUnionTypeIdsWillEqualChildIndices(type_ids, n_type_ids, 
n_children);
+}
+
 static inline ArrowErrorCode ArrowArrayStartAppending(struct ArrowArray* 
array) {
   struct ArrowArrayPrivateData* private_data =
       (struct ArrowArrayPrivateData*)array->private_data;
@@ -2574,6 +2729,41 @@ static inline ArrowErrorCode 
ArrowArrayAppendString(struct ArrowArray* array,
   }
 }
 
+static inline ArrowErrorCode ArrowArrayAppendDecimal(struct ArrowArray* array,
+                                                     struct ArrowDecimal* 
value) {
+  struct ArrowArrayPrivateData* private_data =
+      (struct ArrowArrayPrivateData*)array->private_data;
+  struct ArrowBuffer* data_buffer = ArrowArrayBuffer(array, 1);
+
+  switch (private_data->storage_type) {
+    case NANOARROW_TYPE_DECIMAL128:
+      if (value->n_words != 2) {
+        return EINVAL;
+      } else {
+        NANOARROW_RETURN_NOT_OK(
+            ArrowBufferAppend(data_buffer, value->words, 2 * 
sizeof(uint64_t)));
+        break;
+      }
+    case NANOARROW_TYPE_DECIMAL256:
+      if (value->n_words != 4) {
+        return EINVAL;
+      } else {
+        NANOARROW_RETURN_NOT_OK(
+            ArrowBufferAppend(data_buffer, value->words, 4 * 
sizeof(uint64_t)));
+        break;
+      }
+    default:
+      return EINVAL;
+  }
+
+  if (private_data->bitmap.buffer.data != NULL) {
+    NANOARROW_RETURN_NOT_OK(ArrowBitmapAppend(ArrowArrayValidityBitmap(array), 
1, 1));
+  }
+
+  array->length++;
+  return NANOARROW_OK;
+}
+
 static inline ArrowErrorCode ArrowArrayFinishElement(struct ArrowArray* array) 
{
   struct ArrowArrayPrivateData* private_data =
       (struct ArrowArrayPrivateData*)array->private_data;
@@ -2883,6 +3073,23 @@ static inline struct ArrowBufferView 
ArrowArrayViewGetBytesUnsafe(
   return view;
 }
 
+static inline void ArrowArrayViewGetDecimalUnsafe(struct ArrowArrayView* 
array_view,
+                                                  int64_t i, struct 
ArrowDecimal* out) {
+  i += array_view->array->offset;
+  const uint8_t* data_view = array_view->buffer_views[1].data.as_uint8;
+  switch (array_view->storage_type) {
+    case NANOARROW_TYPE_DECIMAL128:
+      ArrowDecimalSetBytes(out, data_view + (i * 16));
+      break;
+    case NANOARROW_TYPE_DECIMAL256:
+      ArrowDecimalSetBytes(out, data_view + (i * 32));
+      break;
+    default:
+      memset(out->words, 0, sizeof(out->words));
+      break;
+  }
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/c/vendor/nanoarrow/nanoarrow.hpp b/c/vendor/nanoarrow/nanoarrow.hpp
index 1fe25db..b01d2a6 100644
--- a/c/vendor/nanoarrow/nanoarrow.hpp
+++ b/c/vendor/nanoarrow/nanoarrow.hpp
@@ -278,10 +278,10 @@ class VectorArrayStream : public EmptyArrayStream {
 
  protected:
   VectorArrayStream(struct ArrowSchema* schema, std::vector<UniqueArray> 
arrays)
-      : EmptyArrayStream(schema), offset_(0), arrays_(std::move(arrays)) {}
+      : EmptyArrayStream(schema), arrays_(std::move(arrays)), offset_(0) {}
 
   int get_next(struct ArrowArray* array) {
-    if (offset_ < arrays_.size()) {
+    if (offset_ < static_cast<int64_t>(arrays_.size())) {
       arrays_[offset_++].move(array);
     } else {
       array->release = nullptr;
diff --git a/c/vendor/vendor_nanoarrow.sh b/c/vendor/vendor_nanoarrow.sh
index b5d65c7..b7da540 100755
--- a/c/vendor/vendor_nanoarrow.sh
+++ b/c/vendor/vendor_nanoarrow.sh
@@ -32,9 +32,19 @@ main() {
     mkdir -p nanoarrow
     tar --strip-components 1 -C "$SCRATCH" -xf "$tarball"
 
-    cp "$SCRATCH/dist/nanoarrow.c" nanoarrow/
-    cp "$SCRATCH/dist/nanoarrow.h" nanoarrow/
-    cp "$SCRATCH/src/nanoarrow/nanoarrow.hpp" nanoarrow/
+    # Build the bundle using cmake. We could also use the dist/ files
+    # but this allows us to add the symbol namespace and ensures that the
+    # resulting bundle is perfectly synchronized with the commit we've pulled.
+    pushd "$SCRATCH"
+    mkdir build && cd build
+    cmake .. -DNANOARROW_BUNDLE=ON -DNANOARROW_NAMESPACE=AdbcNs
+    cmake --build .
+    cmake --install . --prefix=../dist-adbc
+    popd
+
+    cp "$SCRATCH/dist-adbc/nanoarrow.c" nanoarrow/
+    cp "$SCRATCH/dist-adbc/nanoarrow.h" nanoarrow/
+    cp "$SCRATCH/dist-adbc/nanoarrow.hpp" nanoarrow/
 }
 
 main "$@"


Reply via email to