|
35 | 35 |
|
36 | 36 | namespace iceberg { |
37 | 37 |
|
| 38 | +namespace { |
| 39 | + |
| 40 | +// A RAII guard for ArrowSchema. |
| 41 | +struct ArrowSchemaGuard { |
| 42 | + ArrowSchema* schema; |
| 43 | + |
| 44 | + ~ArrowSchemaGuard() { |
| 45 | + if (schema != nullptr) { |
| 46 | + ReleaseRecursively(schema); |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + private: |
| 51 | + void ReleaseRecursively(ArrowSchema* schema_ptr) { |
| 52 | + if (schema_ptr == nullptr) { |
| 53 | + return; |
| 54 | + } |
| 55 | + |
| 56 | + // First, recursively release all children |
| 57 | + if (schema_ptr->children != nullptr && schema_ptr->n_children > 0) { |
| 58 | + for (int64_t i = 0; i < schema_ptr->n_children; ++i) { |
| 59 | + if (schema_ptr->children[i] != nullptr) { |
| 60 | + ReleaseRecursively(schema_ptr->children[i]); |
| 61 | + } |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + // Then release this schema if it has a release callback |
| 66 | + if (schema_ptr->release != nullptr) { |
| 67 | + schema_ptr->release(schema_ptr); |
| 68 | + } |
| 69 | + } |
| 70 | +}; |
| 71 | + |
| 72 | +} // namespace |
| 73 | + |
38 | 74 | TEST(ArrowCDataTest, CheckArrowSchemaAndArrayByNanoarrow) { |
39 | 75 | auto [schema, array] = internal::CreateExampleArrowSchemaAndArrayByNanoarrow(); |
40 | 76 |
|
@@ -86,7 +122,8 @@ TEST_P(ToArrowSchemaTest, PrimitiveType) { |
86 | 122 | : SchemaField::MakeRequired(kFieldId, std::string(kFieldName), |
87 | 123 | param.iceberg_type)}, |
88 | 124 | /*schema_id=*/0); |
89 | | - ArrowSchema arrow_schema; |
| 125 | + ArrowSchema arrow_schema{}; |
| 126 | + ArrowSchemaGuard guard{&arrow_schema}; |
90 | 127 | ASSERT_THAT(ToArrowSchema(schema, &arrow_schema), IsOk()); |
91 | 128 |
|
92 | 129 | auto imported_schema = ::arrow::ImportSchema(&arrow_schema).ValueOrDie(); |
@@ -170,7 +207,8 @@ TEST(ToArrowSchemaTest, StructType) { |
170 | 207 | struct_type)}, |
171 | 208 | /*schema_id=*/0); |
172 | 209 |
|
173 | | - ArrowSchema arrow_schema; |
| 210 | + ArrowSchema arrow_schema{}; |
| 211 | + ArrowSchemaGuard guard{&arrow_schema}; |
174 | 212 | ASSERT_THAT(ToArrowSchema(schema, &arrow_schema), IsOk()); |
175 | 213 |
|
176 | 214 | auto imported_schema = ::arrow::ImportSchema(&arrow_schema).ValueOrDie(); |
@@ -202,7 +240,8 @@ TEST(ToArrowSchemaTest, ListType) { |
202 | 240 | {SchemaField::MakeRequired(kListFieldId, std::string(kListFieldName), list_type)}, |
203 | 241 | /*schema_id=*/0); |
204 | 242 |
|
205 | | - ArrowSchema arrow_schema; |
| 243 | + ArrowSchema arrow_schema{}; |
| 244 | + ArrowSchemaGuard guard{&arrow_schema}; |
206 | 245 | ASSERT_THAT(ToArrowSchema(schema, &arrow_schema), IsOk()); |
207 | 246 |
|
208 | 247 | auto imported_schema = ::arrow::ImportSchema(&arrow_schema).ValueOrDie(); |
@@ -237,7 +276,8 @@ TEST(ToArrowSchemaTest, MapType) { |
237 | 276 | {SchemaField::MakeRequired(kFieldId, std::string(kMapFieldName), map_type)}, |
238 | 277 | /*schema_id=*/0); |
239 | 278 |
|
240 | | - ArrowSchema arrow_schema; |
| 279 | + ArrowSchema arrow_schema{}; |
| 280 | + ArrowSchemaGuard guard{&arrow_schema}; |
241 | 281 | ASSERT_THAT(ToArrowSchema(schema, &arrow_schema), IsOk()); |
242 | 282 |
|
243 | 283 | auto imported_schema = ::arrow::ImportSchema(&arrow_schema).ValueOrDie(); |
@@ -278,7 +318,8 @@ TEST_P(FromArrowSchemaTest, PrimitiveType) { |
278 | 318 | {std::string(kFieldIdKey), std::to_string(kFieldId)}}); |
279 | 319 | auto arrow_schema = ::arrow::schema({::arrow::field( |
280 | 320 | std::string(kFieldName), param.arrow_type, param.optional, std::move(metadata))}); |
281 | | - ArrowSchema exported_schema; |
| 321 | + ArrowSchema exported_schema{}; |
| 322 | + ArrowSchemaGuard guard{&exported_schema}; |
282 | 323 | ASSERT_TRUE(::arrow::ExportSchema(*arrow_schema, &exported_schema).ok()); |
283 | 324 |
|
284 | 325 | auto type_result = FromArrowSchema(exported_schema, /*schema_id=*/1); |
@@ -353,7 +394,8 @@ TEST(FromArrowSchemaTest, StructType) { |
353 | 394 | ::arrow::key_value_metadata(std::unordered_map<std::string, std::string>{ |
354 | 395 | {std::string(kFieldIdKey), std::to_string(kStructFieldId)}})); |
355 | 396 | auto arrow_schema = ::arrow::schema({struct_field}); |
356 | | - ArrowSchema exported_schema; |
| 397 | + ArrowSchema exported_schema{}; |
| 398 | + ArrowSchemaGuard guard{&exported_schema}; |
357 | 399 | ASSERT_TRUE(::arrow::ExportSchema(*arrow_schema, &exported_schema).ok()); |
358 | 400 |
|
359 | 401 | auto schema_result = FromArrowSchema(exported_schema, /*schema_id=*/0); |
@@ -403,7 +445,8 @@ TEST(FromArrowSchemaTest, ListType) { |
403 | 445 | {std::string(kFieldIdKey), std::to_string(kListFieldId)}})); |
404 | 446 | auto arrow_schema = ::arrow::schema({list_field}); |
405 | 447 |
|
406 | | - ArrowSchema exported_schema; |
| 448 | + ArrowSchema exported_schema{}; |
| 449 | + ArrowSchemaGuard guard{&exported_schema}; |
407 | 450 | ASSERT_TRUE(::arrow::ExportSchema(*arrow_schema, &exported_schema).ok()); |
408 | 451 |
|
409 | 452 | auto schema_result = FromArrowSchema(exported_schema, /*schema_id=*/0); |
@@ -453,7 +496,8 @@ TEST(FromArrowSchemaTest, MapType) { |
453 | 496 | {std::string(kFieldIdKey), std::to_string(kFieldId)}})); |
454 | 497 | auto arrow_schema = ::arrow::schema({map_field}); |
455 | 498 |
|
456 | | - ArrowSchema exported_schema; |
| 499 | + ArrowSchema exported_schema{}; |
| 500 | + ArrowSchemaGuard guard{&exported_schema}; |
457 | 501 | ASSERT_TRUE(::arrow::ExportSchema(*arrow_schema, &exported_schema).ok()); |
458 | 502 |
|
459 | 503 | auto schema_result = FromArrowSchema(exported_schema, /*schema_id=*/0); |
|
0 commit comments