Skip to content

Commit a8362f8

Browse files
committed
refactor(raster): return StringViewArray from CRS conversion helpers
srid_to_crs_columnar and normalize_crs_columnar now return StringViewArray directly instead of ColumnarValue, removing redundant Scalar/Array re-wrapping and the cast_to(Utf8View) in replace_raster_crs. Broadcasting for scalar CRS applied to array raster is handled explicitly.
1 parent 64d0837 commit a8362f8

1 file changed

Lines changed: 26 additions & 34 deletions

File tree

rust/sedona-raster-functions/src/rs_setsrid.rs

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl SedonaScalarKernel for RsSetCrs {
190190
/// null will have the entire raster nulled out (not just the CRS column).
191191
fn replace_raster_crs(
192192
raster_arg: &ColumnarValue,
193-
crs_value: &ColumnarValue,
193+
crs_array: &StringViewArray,
194194
input_nulls: Option<&NullBuffer>,
195195
) -> Result<ColumnarValue> {
196196
match raster_arg {
@@ -205,10 +205,8 @@ fn replace_raster_crs(
205205
})?;
206206

207207
let num_rows = raster_struct.len();
208-
let new_crs_array = crs_value
209-
.cast_to(&DataType::Utf8View, None)?
210-
.to_array(num_rows)?;
211-
let new_struct = swap_crs_column(raster_struct, new_crs_array)?;
208+
let new_crs: ArrayRef = broadcast_string_view(crs_array, num_rows);
209+
let new_struct = swap_crs_column(raster_struct, new_crs)?;
212210

213211
// Merge input nulls: rows where the SRID/CRS input was null become null rasters
214212
let merged_nulls = NullBuffer::union(new_struct.nulls(), input_nulls);
@@ -221,11 +219,8 @@ fn replace_raster_crs(
221219
Ok(ColumnarValue::Array(Arc::new(new_struct)))
222220
}
223221
ColumnarValue::Scalar(ScalarValue::Struct(arc_struct)) => {
224-
let num_rows = arc_struct.len();
225-
let new_crs_array = crs_value
226-
.cast_to(&DataType::Utf8View, None)?
227-
.to_array(num_rows)?;
228-
let new_struct = swap_crs_column(arc_struct.as_ref(), new_crs_array)?;
222+
let new_crs: ArrayRef = Arc::new(crs_array.clone());
223+
let new_struct = swap_crs_column(arc_struct.as_ref(), new_crs)?;
229224

230225
// Merge input nulls: null SRID/CRS input produces a null raster
231226
let merged_nulls = NullBuffer::union(new_struct.nulls(), input_nulls);
@@ -244,6 +239,23 @@ fn replace_raster_crs(
244239
}
245240
}
246241

242+
/// Broadcast a `StringViewArray` to a target length.
243+
///
244+
/// If the array already has the target length, it is returned as-is (clone of Arc).
245+
/// Otherwise the array must have length 1, and its single value is repeated.
246+
fn broadcast_string_view(array: &StringViewArray, len: usize) -> ArrayRef {
247+
if array.len() == len {
248+
return Arc::new(array.clone());
249+
}
250+
debug_assert_eq!(array.len(), 1);
251+
if array.is_null(0) {
252+
Arc::new(StringViewArray::new_null(len))
253+
} else {
254+
let value = array.value(0);
255+
Arc::new(std::iter::repeat_n(Some(value), len).collect::<StringViewArray>())
256+
}
257+
}
258+
247259
/// Swap only the CRS column of a raster StructArray, keeping all other columns intact.
248260
fn swap_crs_column(raster_struct: &StructArray, new_crs_array: ArrayRef) -> Result<StructArray> {
249261
let mut columns: Vec<ArrayRef> = raster_struct.columns().to_vec();
@@ -291,7 +303,7 @@ fn extract_input_nulls(input: &ColumnarValue) -> Option<NullBuffer> {
291303
fn srid_to_crs_columnar(
292304
srid_arg: &ColumnarValue,
293305
maybe_engine: Option<&Arc<dyn CrsEngine + Send + Sync>>,
294-
) -> Result<ColumnarValue> {
306+
) -> Result<StringViewArray> {
295307
let mut srid_to_crs = CachedSRIDToCrs::new();
296308

297309
// Cast to Int64 for uniform handling
@@ -314,17 +326,7 @@ fn srid_to_crs_columnar(
314326
})
315327
.collect::<Result<_>>()?;
316328

317-
// Return as Scalar if the original was scalar, Array otherwise
318-
if matches!(srid_arg, ColumnarValue::Scalar(_)) {
319-
let scalar = if crs_array.is_null(0) {
320-
ScalarValue::Utf8View(None)
321-
} else {
322-
ScalarValue::Utf8View(Some(crs_array.value(0).to_string()))
323-
};
324-
Ok(ColumnarValue::Scalar(scalar))
325-
} else {
326-
Ok(ColumnarValue::Array(Arc::new(crs_array)))
327-
}
329+
Ok(crs_array)
328330
}
329331

330332
// ---------------------------------------------------------------------------
@@ -339,7 +341,7 @@ fn srid_to_crs_columnar(
339341
fn normalize_crs_columnar(
340342
crs_arg: &ColumnarValue,
341343
_maybe_engine: Option<&Arc<dyn CrsEngine + Send + Sync>>,
342-
) -> Result<ColumnarValue> {
344+
) -> Result<StringViewArray> {
343345
let mut crs_norm = CachedCrsNormalization::new();
344346

345347
let string_value = crs_arg.cast_to(&DataType::Utf8View, None)?;
@@ -358,17 +360,7 @@ fn normalize_crs_columnar(
358360
})
359361
.collect::<Result<_>>()?;
360362

361-
// Return as Scalar if the original was scalar, Array otherwise
362-
if matches!(crs_arg, ColumnarValue::Scalar(_)) {
363-
let scalar = if crs_array.is_null(0) {
364-
ScalarValue::Utf8View(None)
365-
} else {
366-
ScalarValue::Utf8View(Some(crs_array.value(0).to_string()))
367-
};
368-
Ok(ColumnarValue::Scalar(scalar))
369-
} else {
370-
Ok(ColumnarValue::Array(Arc::new(crs_array)))
371-
}
363+
Ok(crs_array)
372364
}
373365

374366
/// Validate a CRS string

0 commit comments

Comments
 (0)