Concatenates all but the first argument, with separators. The first argument is used as the separator string, and should not be NULL. Other NULL arguments are ignored. concat_ws(',', 'abcde', 2, NULL, 22) = 'abcde,2,22'
(&self, args: ScalarFunctionArgs)
| 114 | /// NULL arguments are ignored. |
| 115 | /// concat_ws(',', 'abcde', 2, NULL, 22) = 'abcde,2,22' |
| 116 | fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> { |
| 117 | let ScalarFunctionArgs { args, .. } = args; |
| 118 | |
| 119 | if args.len() < 2 { |
| 120 | return exec_err!( |
| 121 | "concat_ws was called with {} arguments. It requires at least 2.", |
| 122 | args.len() |
| 123 | ); |
| 124 | } |
| 125 | |
| 126 | let return_datatype = if args.iter().any(|c| c.data_type() == DataType::Utf8View) |
| 127 | { |
| 128 | DataType::Utf8View |
| 129 | } else if args.iter().any(|c| c.data_type() == DataType::LargeUtf8) { |
| 130 | DataType::LargeUtf8 |
| 131 | } else { |
| 132 | DataType::Utf8 |
| 133 | }; |
| 134 | |
| 135 | let array_len = args.iter().find_map(|x| match x { |
| 136 | ColumnarValue::Array(array) => Some(array.len()), |
| 137 | _ => None, |
| 138 | }); |
| 139 | |
| 140 | // Scalar |
| 141 | if array_len.is_none() { |
| 142 | let ColumnarValue::Scalar(scalar) = &args[0] else { |
| 143 | unreachable!() |
| 144 | }; |
| 145 | let sep = match scalar.try_as_str() { |
| 146 | Some(Some(s)) => s, |
| 147 | Some(None) => { |
| 148 | // null literal string |
| 149 | return match return_datatype { |
| 150 | DataType::Utf8View => { |
| 151 | Ok(ColumnarValue::Scalar(ScalarValue::Utf8View(None))) |
| 152 | } |
| 153 | DataType::LargeUtf8 => { |
| 154 | Ok(ColumnarValue::Scalar(ScalarValue::LargeUtf8(None))) |
| 155 | } |
| 156 | _ => Ok(ColumnarValue::Scalar(ScalarValue::Utf8(None))), |
| 157 | }; |
| 158 | } |
| 159 | None => return internal_err!("Expected string literal, got {scalar:?}"), |
| 160 | }; |
| 161 | |
| 162 | let mut values = Vec::with_capacity(args.len() - 1); |
| 163 | for arg in &args[1..] { |
| 164 | let ColumnarValue::Scalar(scalar) = arg else { |
| 165 | unreachable!() |
| 166 | }; |
| 167 | |
| 168 | match scalar.try_as_str() { |
| 169 | Some(Some(v)) => values.push(v), |
| 170 | Some(None) => {} // null literal string |
| 171 | None => { |
| 172 | return internal_err!("Expected string literal, got {scalar:?}"); |
| 173 | } |