(args: &[ArrayRef])
| 92 | } |
| 93 | |
| 94 | fn elt(args: &[ArrayRef]) -> Result<ArrayRef, DataFusionError> { |
| 95 | let n_rows = args[0].len(); |
| 96 | |
| 97 | let idx: &PrimitiveArray<Int64Type> = |
| 98 | args[0].as_primitive_opt::<Int64Type>().ok_or_else(|| { |
| 99 | DataFusionError::Plan(format!( |
| 100 | "ELT function: first argument must be Int64 (got {:?})", |
| 101 | args[0].data_type() |
| 102 | )) |
| 103 | })?; |
| 104 | |
| 105 | let num_values = args.len() - 1; |
| 106 | let mut cols: Vec<Arc<StringArray>> = Vec::with_capacity(num_values); |
| 107 | for a in args.iter().skip(1) { |
| 108 | let casted = cast(a, &Utf8)?; |
| 109 | let sa = as_string_array(&casted)?; |
| 110 | cols.push(Arc::new(sa.clone())); |
| 111 | } |
| 112 | |
| 113 | let mut builder = StringBuilder::new(); |
| 114 | |
| 115 | for i in 0..n_rows { |
| 116 | if idx.is_null(i) { |
| 117 | builder.append_null(); |
| 118 | continue; |
| 119 | } |
| 120 | |
| 121 | let index = idx.value(i); |
| 122 | |
| 123 | // TODO: if spark.sql.ansi.enabled is true, |
| 124 | // throw ArrayIndexOutOfBoundsException for invalid indices; |
| 125 | // if false, return NULL instead (current behavior). |
| 126 | if index < 1 || (index as usize) > num_values { |
| 127 | builder.append_null(); |
| 128 | continue; |
| 129 | } |
| 130 | |
| 131 | let value_idx = (index as usize) - 1; |
| 132 | let col = &cols[value_idx]; |
| 133 | |
| 134 | if col.is_null(i) { |
| 135 | builder.append_null(); |
| 136 | } else { |
| 137 | builder.append_value(col.value(i)); |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | Ok(Arc::new(builder.finish()) as ArrayRef) |
| 142 | } |
| 143 | |
| 144 | #[cfg(test)] |
| 145 | mod tests { |
no test coverage detected