duckdb 0.8.2-dev2850.0 → 0.8.2-dev3007.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/binding.gyp +1 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/src/common/adbc/adbc.cpp +400 -145
  4. package/src/duckdb/src/common/adbc/driver_manager.cpp +79 -31
  5. package/src/duckdb/src/common/adbc/nanoarrow/allocator.cpp +57 -0
  6. package/src/duckdb/src/common/adbc/nanoarrow/metadata.cpp +121 -0
  7. package/src/duckdb/src/common/adbc/nanoarrow/schema.cpp +474 -0
  8. package/src/duckdb/src/common/adbc/nanoarrow/single_batch_array_stream.cpp +84 -0
  9. package/src/duckdb/src/common/arrow/arrow_converter.cpp +4 -2
  10. package/src/duckdb/src/common/multi_file_reader.cpp +6 -0
  11. package/src/duckdb/src/execution/window_executor.cpp +5 -8
  12. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  13. package/src/duckdb/src/include/duckdb/common/adbc/adbc.h +1 -0
  14. package/src/duckdb/src/include/duckdb/common/adbc/adbc.hpp +3 -3
  15. package/src/duckdb/src/include/duckdb/common/adbc/single_batch_array_stream.hpp +16 -0
  16. package/src/duckdb/src/include/duckdb/common/arrow/arrow_appender.hpp +1 -2
  17. package/src/duckdb/src/include/duckdb/common/arrow/arrow_converter.hpp +0 -2
  18. package/src/duckdb/src/include/duckdb/common/arrow/nanoarrow/nanoarrow.h +462 -0
  19. package/src/duckdb/src/include/duckdb/common/arrow/nanoarrow/nanoarrow.hpp +14 -0
  20. package/src/duckdb/src/include/duckdb/common/types/data_chunk.hpp +0 -2
  21. package/src/duckdb/src/include/duckdb/main/chunk_scan_state.hpp +2 -4
  22. package/src/duckdb/src/include/duckdb.h +16 -0
  23. package/src/duckdb/src/main/capi/arrow-c.cpp +41 -0
  24. package/src/duckdb/src/main/capi/prepared-c.cpp +60 -30
  25. package/src/duckdb/src/main/chunk_scan_state.cpp +6 -0
  26. package/src/duckdb/src/main/client_context.cpp +1 -1
  27. package/src/duckdb/src/optimizer/topn_optimizer.cpp +7 -0
  28. package/src/duckdb/src/storage/compression/bitpacking.cpp +1 -1
  29. package/src/duckdb/ub_src_common_adbc_nanoarrow.cpp +8 -0
  30. package/src/duckdb_node.hpp +1 -0
  31. package/src/statement.cpp +1 -1
@@ -57,6 +57,15 @@ void GetWinError(std::string *buffer) {
57
57
 
58
58
  #endif // defined(_WIN32)
59
59
 
60
+ // Temporary state while the database is being configured.
61
+ struct TempDatabase {
62
+ std::unordered_map<std::string, std::string> options;
63
+ std::string driver;
64
+ // Default name (see adbc.h)
65
+ std::string entrypoint = "AdbcDriverInit";
66
+ AdbcDriverInitFunc init_func = nullptr;
67
+ };
68
+
60
69
  // Error handling
61
70
 
62
71
  void ReleaseError(struct AdbcError *error) {
@@ -92,6 +101,14 @@ void SetError(struct AdbcError *error, const std::string &message) {
92
101
  error->release = ReleaseError;
93
102
  }
94
103
 
104
+ void SetError(struct AdbcError *error, const char *message_p) {
105
+ if (!message_p) {
106
+ message_p = "";
107
+ }
108
+ std::string message(message_p);
109
+ SetError(error, message);
110
+ }
111
+
95
112
  // Driver state
96
113
 
97
114
  /// Hold the driver DLL and the driver release callback in the driver struct.
@@ -132,32 +149,6 @@ static AdbcStatusCode ReleaseDriver(struct AdbcDriver *driver, struct AdbcError
132
149
  return status;
133
150
  }
134
151
 
135
- // Default stubs
136
-
137
- AdbcStatusCode ConnectionGetInfo(struct AdbcConnection *connection, uint32_t *info_codes, size_t info_codes_length,
138
- struct ArrowArrayStream *out, struct AdbcError *error) {
139
- return ADBC_STATUS_NOT_IMPLEMENTED;
140
- }
141
-
142
- AdbcStatusCode StatementBind(struct AdbcStatement *, struct ArrowArray *, struct ArrowSchema *,
143
- struct AdbcError *error) {
144
- return ADBC_STATUS_NOT_IMPLEMENTED;
145
- }
146
-
147
- AdbcStatusCode StatementGetParameterSchema(struct AdbcStatement *statement, struct ArrowSchema *schema,
148
- struct AdbcError *error) {
149
- return ADBC_STATUS_NOT_IMPLEMENTED;
150
- }
151
-
152
- /// Temporary state while the database is being configured.
153
- struct TempDatabase {
154
- std::unordered_map<std::string, std::string> options;
155
- std::string driver;
156
- // Default name (see adbc.h)
157
- std::string entrypoint = "AdbcDriverInit";
158
- AdbcDriverInitFunc init_func = nullptr;
159
- };
160
-
161
152
  /// Temporary state while the database is being configured.
162
153
  struct TempConnection {
163
154
  std::unordered_map<std::string, std::string> options;
@@ -174,6 +165,9 @@ AdbcStatusCode AdbcDatabaseNew(struct AdbcDatabase *database, struct AdbcError *
174
165
 
175
166
  AdbcStatusCode AdbcDatabaseSetOption(struct AdbcDatabase *database, const char *key, const char *value,
176
167
  struct AdbcError *error) {
168
+ if (!database) {
169
+ return ADBC_STATUS_INVALID_ARGUMENT;
170
+ }
177
171
  if (database->private_driver) {
178
172
  return database->private_driver->DatabaseSetOption(database, key, value, error);
179
173
  }
@@ -191,6 +185,9 @@ AdbcStatusCode AdbcDatabaseSetOption(struct AdbcDatabase *database, const char *
191
185
 
192
186
  AdbcStatusCode AdbcDriverManagerDatabaseSetInitFunc(struct AdbcDatabase *database, AdbcDriverInitFunc init_func,
193
187
  struct AdbcError *error) {
188
+ if (!database) {
189
+ return ADBC_STATUS_INVALID_ARGUMENT;
190
+ }
194
191
  if (database->private_driver) {
195
192
  return ADBC_STATUS_INVALID_STATE;
196
193
  }
@@ -286,6 +283,9 @@ AdbcStatusCode AdbcDatabaseRelease(struct AdbcDatabase *database, struct AdbcErr
286
283
  }
287
284
 
288
285
  AdbcStatusCode AdbcConnectionCommit(struct AdbcConnection *connection, struct AdbcError *error) {
286
+ if (!connection) {
287
+ return ADBC_STATUS_INVALID_ARGUMENT;
288
+ }
289
289
  if (!connection->private_driver) {
290
290
  return ADBC_STATUS_INVALID_STATE;
291
291
  }
@@ -294,6 +294,9 @@ AdbcStatusCode AdbcConnectionCommit(struct AdbcConnection *connection, struct Ad
294
294
 
295
295
  AdbcStatusCode AdbcConnectionGetInfo(struct AdbcConnection *connection, uint32_t *info_codes, size_t info_codes_length,
296
296
  struct ArrowArrayStream *out, struct AdbcError *error) {
297
+ if (!connection) {
298
+ return ADBC_STATUS_INVALID_ARGUMENT;
299
+ }
297
300
  if (!connection->private_driver) {
298
301
  return ADBC_STATUS_INVALID_STATE;
299
302
  }
@@ -319,6 +322,9 @@ AdbcStatusCode AdbcConnectionGetObjects(struct AdbcConnection *connection, int d
319
322
  AdbcStatusCode AdbcConnectionGetTableSchema(struct AdbcConnection *connection, const char *catalog,
320
323
  const char *db_schema, const char *table_name, struct ArrowSchema *schema,
321
324
  struct AdbcError *error) {
325
+ if (!connection) {
326
+ return ADBC_STATUS_INVALID_ARGUMENT;
327
+ }
322
328
  if (!connection->private_driver) {
323
329
  return ADBC_STATUS_INVALID_STATE;
324
330
  }
@@ -328,6 +334,9 @@ AdbcStatusCode AdbcConnectionGetTableSchema(struct AdbcConnection *connection, c
328
334
 
329
335
  AdbcStatusCode AdbcConnectionGetTableTypes(struct AdbcConnection *connection, struct ArrowArrayStream *stream,
330
336
  struct AdbcError *error) {
337
+ if (!connection) {
338
+ return ADBC_STATUS_INVALID_ARGUMENT;
339
+ }
331
340
  if (!connection->private_driver) {
332
341
  return ADBC_STATUS_INVALID_STATE;
333
342
  }
@@ -336,6 +345,9 @@ AdbcStatusCode AdbcConnectionGetTableTypes(struct AdbcConnection *connection, st
336
345
 
337
346
  AdbcStatusCode AdbcConnectionInit(struct AdbcConnection *connection, struct AdbcDatabase *database,
338
347
  struct AdbcError *error) {
348
+ if (!connection) {
349
+ return ADBC_STATUS_INVALID_ARGUMENT;
350
+ }
339
351
  if (!connection->private_data) {
340
352
  SetError(error, "Must call AdbcConnectionNew first");
341
353
  return ADBC_STATUS_INVALID_STATE;
@@ -376,6 +388,9 @@ AdbcStatusCode AdbcConnectionNew(struct AdbcConnection *connection, struct AdbcE
376
388
  AdbcStatusCode AdbcConnectionReadPartition(struct AdbcConnection *connection, const uint8_t *serialized_partition,
377
389
  size_t serialized_length, struct ArrowArrayStream *out,
378
390
  struct AdbcError *error) {
391
+ if (!connection) {
392
+ return ADBC_STATUS_INVALID_ARGUMENT;
393
+ }
379
394
  if (!connection->private_driver) {
380
395
  return ADBC_STATUS_INVALID_STATE;
381
396
  }
@@ -384,6 +399,9 @@ AdbcStatusCode AdbcConnectionReadPartition(struct AdbcConnection *connection, co
384
399
  }
385
400
 
386
401
  AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection *connection, struct AdbcError *error) {
402
+ if (!connection) {
403
+ return ADBC_STATUS_INVALID_ARGUMENT;
404
+ }
387
405
  if (!connection->private_driver) {
388
406
  if (connection->private_data) {
389
407
  TempConnection *args = reinterpret_cast<TempConnection *>(connection->private_data);
@@ -399,6 +417,9 @@ AdbcStatusCode AdbcConnectionRelease(struct AdbcConnection *connection, struct A
399
417
  }
400
418
 
401
419
  AdbcStatusCode AdbcConnectionRollback(struct AdbcConnection *connection, struct AdbcError *error) {
420
+ if (!connection) {
421
+ return ADBC_STATUS_INVALID_ARGUMENT;
422
+ }
402
423
  if (!connection->private_driver) {
403
424
  return ADBC_STATUS_INVALID_STATE;
404
425
  }
@@ -407,6 +428,9 @@ AdbcStatusCode AdbcConnectionRollback(struct AdbcConnection *connection, struct
407
428
 
408
429
  AdbcStatusCode AdbcConnectionSetOption(struct AdbcConnection *connection, const char *key, const char *value,
409
430
  struct AdbcError *error) {
431
+ if (!connection) {
432
+ return ADBC_STATUS_INVALID_ARGUMENT;
433
+ }
410
434
  if (!connection->private_data) {
411
435
  SetError(error, "AdbcConnectionSetOption: must AdbcConnectionNew first");
412
436
  return ADBC_STATUS_INVALID_STATE;
@@ -422,6 +446,9 @@ AdbcStatusCode AdbcConnectionSetOption(struct AdbcConnection *connection, const
422
446
 
423
447
  AdbcStatusCode AdbcStatementBind(struct AdbcStatement *statement, struct ArrowArray *values, struct ArrowSchema *schema,
424
448
  struct AdbcError *error) {
449
+ if (!statement) {
450
+ return ADBC_STATUS_INVALID_ARGUMENT;
451
+ }
425
452
  if (!statement->private_driver) {
426
453
  return ADBC_STATUS_INVALID_STATE;
427
454
  }
@@ -430,6 +457,9 @@ AdbcStatusCode AdbcStatementBind(struct AdbcStatement *statement, struct ArrowAr
430
457
 
431
458
  AdbcStatusCode AdbcStatementBindStream(struct AdbcStatement *statement, struct ArrowArrayStream *stream,
432
459
  struct AdbcError *error) {
460
+ if (!statement) {
461
+ return ADBC_STATUS_INVALID_ARGUMENT;
462
+ }
433
463
  if (!statement->private_driver) {
434
464
  return ADBC_STATUS_INVALID_STATE;
435
465
  }
@@ -440,6 +470,9 @@ AdbcStatusCode AdbcStatementBindStream(struct AdbcStatement *statement, struct A
440
470
  AdbcStatusCode AdbcStatementExecutePartitions(struct AdbcStatement *statement, ArrowSchema *schema,
441
471
  struct AdbcPartitions *partitions, int64_t *rows_affected,
442
472
  struct AdbcError *error) {
473
+ if (!statement) {
474
+ return ADBC_STATUS_INVALID_ARGUMENT;
475
+ }
443
476
  if (!statement->private_driver) {
444
477
  return ADBC_STATUS_INVALID_STATE;
445
478
  }
@@ -459,6 +492,9 @@ AdbcStatusCode AdbcStatementExecuteQuery(struct AdbcStatement *statement, struct
459
492
 
460
493
  AdbcStatusCode AdbcStatementGetParameterSchema(struct AdbcStatement *statement, struct ArrowSchema *schema,
461
494
  struct AdbcError *error) {
495
+ if (!statement) {
496
+ return ADBC_STATUS_INVALID_ARGUMENT;
497
+ }
462
498
  if (!statement->private_driver) {
463
499
  return ADBC_STATUS_INVALID_STATE;
464
500
  }
@@ -479,18 +515,21 @@ AdbcStatusCode AdbcStatementNew(struct AdbcConnection *connection, struct AdbcSt
479
515
  }
480
516
 
481
517
  AdbcStatusCode AdbcStatementPrepare(struct AdbcStatement *statement, struct AdbcError *error) {
482
- auto status = SetErrorMaybe(statement, error, "Missing statement object");
483
- if (status != ADBC_STATUS_OK) {
484
- return status;
518
+ if (!statement) {
519
+ SetError(error, "Missing statement object");
520
+ return ADBC_STATUS_INVALID_ARGUMENT;
485
521
  }
486
- status = SetErrorMaybe(statement->private_data, error, "Invalid statement object");
487
- if (status != ADBC_STATUS_OK) {
522
+ if (!statement->private_data) {
523
+ SetError(error, "Invalid statement object");
488
524
  return ADBC_STATUS_INVALID_STATE;
489
525
  }
490
526
  return statement->private_driver->StatementPrepare(statement, error);
491
527
  }
492
528
 
493
529
  AdbcStatusCode AdbcStatementRelease(struct AdbcStatement *statement, struct AdbcError *error) {
530
+ if (!statement) {
531
+ return ADBC_STATUS_INVALID_ARGUMENT;
532
+ }
494
533
  if (!statement->private_driver) {
495
534
  return ADBC_STATUS_INVALID_STATE;
496
535
  }
@@ -501,6 +540,9 @@ AdbcStatusCode AdbcStatementRelease(struct AdbcStatement *statement, struct Adbc
501
540
 
502
541
  AdbcStatusCode AdbcStatementSetOption(struct AdbcStatement *statement, const char *key, const char *value,
503
542
  struct AdbcError *error) {
543
+ if (!statement) {
544
+ return ADBC_STATUS_INVALID_ARGUMENT;
545
+ }
504
546
  if (!statement->private_driver) {
505
547
  return ADBC_STATUS_INVALID_STATE;
506
548
  }
@@ -508,6 +550,9 @@ AdbcStatusCode AdbcStatementSetOption(struct AdbcStatement *statement, const cha
508
550
  }
509
551
 
510
552
  AdbcStatusCode AdbcStatementSetSqlQuery(struct AdbcStatement *statement, const char *query, struct AdbcError *error) {
553
+ if (!statement) {
554
+ return ADBC_STATUS_INVALID_ARGUMENT;
555
+ }
511
556
  if (!statement->private_driver) {
512
557
  return ADBC_STATUS_INVALID_STATE;
513
558
  }
@@ -516,6 +561,9 @@ AdbcStatusCode AdbcStatementSetSqlQuery(struct AdbcStatement *statement, const c
516
561
 
517
562
  AdbcStatusCode AdbcStatementSetSubstraitPlan(struct AdbcStatement *statement, const uint8_t *plan, size_t length,
518
563
  struct AdbcError *error) {
564
+ if (!statement) {
565
+ return ADBC_STATUS_INVALID_ARGUMENT;
566
+ }
519
567
  if (!statement->private_driver) {
520
568
  return ADBC_STATUS_INVALID_STATE;
521
569
  }
@@ -0,0 +1,57 @@
1
+ // Licensed to the Apache Software Foundation (ASF) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The ASF licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ #include <stddef.h>
19
+ #include <stdlib.h>
20
+
21
+ #include "duckdb/common/arrow/nanoarrow/nanoarrow.hpp"
22
+
23
+ namespace duckdb_nanoarrow {
24
+
25
+ void *ArrowMalloc(int64_t size) {
26
+ return malloc(size);
27
+ }
28
+
29
+ void *ArrowRealloc(void *ptr, int64_t size) {
30
+ return realloc(ptr, size);
31
+ }
32
+
33
+ void ArrowFree(void *ptr) {
34
+ free(ptr);
35
+ }
36
+
37
+ static uint8_t *ArrowBufferAllocatorMallocAllocate(struct ArrowBufferAllocator *allocator, int64_t size) {
38
+ return (uint8_t *)ArrowMalloc(size);
39
+ }
40
+
41
+ static uint8_t *ArrowBufferAllocatorMallocReallocate(struct ArrowBufferAllocator *allocator, uint8_t *ptr,
42
+ int64_t old_size, int64_t new_size) {
43
+ return (uint8_t *)ArrowRealloc(ptr, new_size);
44
+ }
45
+
46
+ static void ArrowBufferAllocatorMallocFree(struct ArrowBufferAllocator *allocator, uint8_t *ptr, int64_t size) {
47
+ ArrowFree(ptr);
48
+ }
49
+
50
+ static struct ArrowBufferAllocator ArrowBufferAllocatorMalloc = {
51
+ &ArrowBufferAllocatorMallocAllocate, &ArrowBufferAllocatorMallocReallocate, &ArrowBufferAllocatorMallocFree, NULL};
52
+
53
+ struct ArrowBufferAllocator *ArrowBufferAllocatorDefault() {
54
+ return &ArrowBufferAllocatorMalloc;
55
+ }
56
+
57
+ } // namespace duckdb_nanoarrow
@@ -0,0 +1,121 @@
1
+ // Licensed to the Apache Software Foundation (ASF) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The ASF licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ #include <errno.h>
19
+ #include <stdlib.h>
20
+ #include <string.h>
21
+
22
+ #include "duckdb/common/arrow/nanoarrow/nanoarrow.hpp"
23
+
24
+ namespace duckdb_nanoarrow {
25
+
26
+ ArrowErrorCode ArrowMetadataReaderInit(struct ArrowMetadataReader *reader, const char *metadata) {
27
+ reader->metadata = metadata;
28
+
29
+ if (reader->metadata == NULL) {
30
+ reader->offset = 0;
31
+ reader->remaining_keys = 0;
32
+ } else {
33
+ memcpy(&reader->remaining_keys, reader->metadata, sizeof(int32_t));
34
+ reader->offset = sizeof(int32_t);
35
+ }
36
+
37
+ return NANOARROW_OK;
38
+ }
39
+
40
+ ArrowErrorCode ArrowMetadataReaderRead(struct ArrowMetadataReader *reader, struct ArrowStringView *key_out,
41
+ struct ArrowStringView *value_out) {
42
+ if (reader->remaining_keys <= 0) {
43
+ return EINVAL;
44
+ }
45
+
46
+ int64_t pos = 0;
47
+
48
+ int32_t key_size;
49
+ memcpy(&key_size, reader->metadata + reader->offset + pos, sizeof(int32_t));
50
+ pos += sizeof(int32_t);
51
+
52
+ key_out->data = reader->metadata + reader->offset + pos;
53
+ key_out->n_bytes = key_size;
54
+ pos += key_size;
55
+
56
+ int32_t value_size;
57
+ memcpy(&value_size, reader->metadata + reader->offset + pos, sizeof(int32_t));
58
+ pos += sizeof(int32_t);
59
+
60
+ value_out->data = reader->metadata + reader->offset + pos;
61
+ value_out->n_bytes = value_size;
62
+ pos += value_size;
63
+
64
+ reader->offset += pos;
65
+ reader->remaining_keys--;
66
+ return NANOARROW_OK;
67
+ }
68
+
69
+ int64_t ArrowMetadataSizeOf(const char *metadata) {
70
+ if (metadata == NULL) {
71
+ return 0;
72
+ }
73
+
74
+ struct ArrowMetadataReader reader;
75
+ struct ArrowStringView key;
76
+ struct ArrowStringView value;
77
+ ArrowMetadataReaderInit(&reader, metadata);
78
+
79
+ int64_t size = sizeof(int32_t);
80
+ while (ArrowMetadataReaderRead(&reader, &key, &value) == NANOARROW_OK) {
81
+ size += sizeof(int32_t) + key.n_bytes + sizeof(int32_t) + value.n_bytes;
82
+ }
83
+
84
+ return size;
85
+ }
86
+
87
+ ArrowErrorCode ArrowMetadataGetValue(const char *metadata, const char *key, const char *default_value,
88
+ struct ArrowStringView *value_out) {
89
+ struct ArrowStringView target_key_view = {key, static_cast<int64_t>(strlen(key))};
90
+ value_out->data = default_value;
91
+ if (default_value != NULL) {
92
+ value_out->n_bytes = strlen(default_value);
93
+ } else {
94
+ value_out->n_bytes = 0;
95
+ }
96
+
97
+ struct ArrowMetadataReader reader;
98
+ struct ArrowStringView key_view;
99
+ struct ArrowStringView value;
100
+ ArrowMetadataReaderInit(&reader, metadata);
101
+
102
+ while (ArrowMetadataReaderRead(&reader, &key_view, &value) == NANOARROW_OK) {
103
+ int key_equal = target_key_view.n_bytes == key_view.n_bytes &&
104
+ strncmp(target_key_view.data, key_view.data, key_view.n_bytes) == 0;
105
+ if (key_equal) {
106
+ value_out->data = value.data;
107
+ value_out->n_bytes = value.n_bytes;
108
+ break;
109
+ }
110
+ }
111
+
112
+ return NANOARROW_OK;
113
+ }
114
+
115
+ char ArrowMetadataHasKey(const char *metadata, const char *key) {
116
+ struct ArrowStringView value;
117
+ ArrowMetadataGetValue(metadata, key, NULL, &value);
118
+ return value.data != NULL;
119
+ }
120
+
121
+ } // namespace duckdb_nanoarrow