@@ -11,22 +11,34 @@ namespace duckdb {
1111
1212#define MAX_RESOLUTION 30
1313
14+ // Helper function to validate resolution and throw with a clear error message
15+ inline void ValidateResolution (int32_t resolution, const char *function_name) {
16+ if (resolution < 0 || resolution > MAX_RESOLUTION) {
17+ throw InvalidInputException (string (function_name) + " : Resolution must be between 0 and 30" );
18+ }
19+ }
20+
21+ // Helper function to safely throw with error from Rust, freeing the error string
22+ inline void ThrowRustError (char *error_ptr, const char *function_name) {
23+ if (error_ptr != nullptr ) {
24+ string error_msg = string (function_name) + " : " + string (error_ptr);
25+ free (error_ptr);
26+ throw InvalidInputException (error_msg);
27+ }
28+ }
29+
1430inline void A5CellAreaFun (DataChunk &args, ExpressionState &state, Vector &result) {
1531 auto &resolution_vector = args.data [0 ];
1632 UnaryExecutor::Execute<int32_t , double >(resolution_vector, result, args.size (), [&](int32_t resolution) {
17- if (resolution > MAX_RESOLUTION) {
18- throw InvalidInputException (" Resolution must be between 0 and 30" );
19- }
33+ ValidateResolution (resolution, " a5_cell_area" );
2034 return a5_cell_area (resolution);
2135 });
2236}
2337
2438inline void A5GetNumCellsFun (DataChunk &args, ExpressionState &state, Vector &result) {
2539 auto &resolution_vector = args.data [0 ];
2640 UnaryExecutor::Execute<int32_t , uint64_t >(resolution_vector, result, args.size (), [&](int32_t resolution) {
27- if (resolution > MAX_RESOLUTION) {
28- throw InvalidInputException (" Resolution must be between 0 and 30" );
29- }
41+ ValidateResolution (resolution, " a5_get_num_cells" );
3042 return a5_get_num_cells (resolution);
3143 });
3244}
@@ -45,13 +57,9 @@ inline void A5LonLatToCellFun(DataChunk &args, ExpressionState &state, Vector &r
4557 TernaryExecutor::Execute<double , double , int32_t , uint64_t >(
4658 lon_vector, lat_vector, resolution_vector, result, args.size (),
4759 [&](double lon, double lat, int32_t resolution) {
48- if (resolution > MAX_RESOLUTION) {
49- throw InvalidInputException (" Resolution must be between 0 and 30" );
50- }
60+ ValidateResolution (resolution, " a5_lonlat_to_cell" );
5161 struct ResultU64 res = a5_lon_lat_to_cell (lon, lat, resolution);
52- if (res.error != nullptr ) {
53- throw InvalidInputException (res.error );
54- }
62+ ThrowRustError (res.error , " a5_lonlat_to_cell" );
5563 return res.value ;
5664 });
5765}
@@ -62,13 +70,9 @@ inline void A5CellToParentFun(DataChunk &args, ExpressionState &state, Vector &r
6270
6371 BinaryExecutor::Execute<uint64_t , int32_t , uint64_t >(
6472 cell_vector, parent_resolution_vector, result, args.size (), [&](uint64_t cell, int32_t parent_resolution) {
65- if (parent_resolution > MAX_RESOLUTION) {
66- throw InvalidInputException (" Resolution must be between 0 and 30" );
67- }
73+ ValidateResolution (parent_resolution, " a5_cell_to_parent" );
6874 struct ResultU64 res = a5_cell_to_parent (cell, parent_resolution);
69- if (res.error != nullptr ) {
70- throw InvalidInputException (res.error );
71- }
75+ ThrowRustError (res.error , " a5_cell_to_parent" );
7276 return res.value ;
7377 });
7478}
@@ -95,9 +99,7 @@ inline void A5CellToLonLatFun(DataChunk &args, ExpressionState &state, Vector &r
9599 }
96100
97101 struct ResultLonLat res = a5_cell_to_lon_lat (input_data_ptr[cell_idx]);
98- if (res.error != nullptr ) {
99- throw InvalidInputException (res.error );
100- }
102+ ThrowRustError (res.error , " a5_cell_to_lonlat" );
101103
102104 data_ptr[i * 2 ] = res.longitude ;
103105 data_ptr[i * 2 + 1 ] = res.latitude ;
@@ -121,10 +123,13 @@ inline void A5CellToChildrenFun(DataChunk &args, ExpressionState &state, Vector
121123 auto child_result = a5_cell_to_children (cell_id, child_resolution);
122124
123125 if (child_result.error ) {
124- throw InvalidInputException (child_result.error );
126+ string error_msg = string (" a5_cell_to_children: " ) + string (child_result.error );
127+ a5_free_cell_array (child_result);
128+ throw InvalidInputException (error_msg);
125129 }
126130
127131 if (child_result.len == 0 ) {
132+ a5_free_cell_array (child_result);
128133 return list_entry_t {0 , 0 };
129134 }
130135 for (auto i = 0 ; i < child_result.len ; i++) {
@@ -142,10 +147,13 @@ inline void A5CellToChildrenFun(DataChunk &args, ExpressionState &state, Vector
142147 auto child_result = a5_cell_to_children (cell_id, -1 );
143148
144149 if (child_result.error ) {
145- throw InvalidInputException (child_result.error );
150+ string error_msg = string (" a5_cell_to_children: " ) + string (child_result.error );
151+ a5_free_cell_array (child_result);
152+ throw InvalidInputException (error_msg);
146153 }
147154
148155 if (child_result.len == 0 ) {
156+ a5_free_cell_array (child_result);
149157 return list_entry_t {0 , 0 };
150158 }
151159 for (auto i = 0 ; i < child_result.len ; i++) {
@@ -178,7 +186,9 @@ inline void A5CellToBoundaryFun(DataChunk &args, ExpressionState &state, Vector
178186
179187 auto boundary_result = a5_cell_to_boundary (cell_id, options);
180188 if (boundary_result.error ) {
181- throw InvalidInputException (boundary_result.error );
189+ string error_msg = string (" a5_cell_to_boundary: " ) + string (boundary_result.error );
190+ a5_free_lonlatdegrees_array (boundary_result);
191+ throw InvalidInputException (error_msg);
182192 }
183193 if (boundary_result.len == 0 ) {
184194 a5_free_lonlatdegrees_array (boundary_result);
@@ -249,9 +259,12 @@ inline void A5CompactFun(DataChunk &args, ExpressionState &state, Vector &result
249259 // We need to prepare the list of values to pass in.
250260 auto compact_result = a5_compact (cell_list_data + cell_list_entry.offset , cell_list_entry.length );
251261 if (compact_result.error ) {
252- throw InvalidInputException (compact_result.error );
262+ string error_msg = string (" a5_compact: " ) + string (compact_result.error );
263+ a5_free_cell_array (compact_result);
264+ throw InvalidInputException (error_msg);
253265 }
254266 if (compact_result.len == 0 ) {
267+ a5_free_cell_array (compact_result);
255268 return list_entry_t {0 , 0 };
256269 }
257270 ListVector::Reserve (result, result_size + compact_result.len );
@@ -285,9 +298,12 @@ inline void A5UncompactFun(DataChunk &args, ExpressionState &state, Vector &resu
285298 auto compact_result =
286299 a5_uncompact (cell_list_data + cell_list_entry.offset , cell_list_entry.length , target_resolution);
287300 if (compact_result.error ) {
288- throw InvalidInputException (compact_result.error );
301+ string error_msg = string (" a5_uncompact: " ) + string (compact_result.error );
302+ a5_free_cell_array (compact_result);
303+ throw InvalidInputException (error_msg);
289304 }
290305 if (compact_result.len == 0 ) {
306+ a5_free_cell_array (compact_result);
291307 return list_entry_t {0 , 0 };
292308 }
293309 ListVector::Reserve (result, result_size + compact_result.len );
0 commit comments