NULL handling of function Concat and ConcatWs are different. Function concat was reimplemented to keep the original NULL handling.
| 1240 | // Function concat was reimplemented to keep the original |
| 1241 | // NULL handling. |
| 1242 | StringVal StringFunctions::Concat( |
| 1243 | FunctionContext* context, int num_children, const StringVal* strs) { |
| 1244 | DCHECK_GE(num_children, 1); |
| 1245 | DCHECK(strs != nullptr); |
| 1246 | // Pass through if there's only one argument. |
| 1247 | if (num_children == 1) return strs[0]; |
| 1248 | |
| 1249 | // Loop once to compute the final size and reserve space. |
| 1250 | int64_t total_size = 0; |
| 1251 | for (int32_t i = 0; i < num_children; ++i) { |
| 1252 | if (strs[i].is_null) return StringVal::null(); |
| 1253 | total_size += strs[i].len; |
| 1254 | } |
| 1255 | |
| 1256 | if (total_size > StringVal::MAX_LENGTH) { |
| 1257 | context->SetError(Substitute(ERROR_CHARACTER_LIMIT_EXCEEDED, |
| 1258 | "Concatenated string length", |
| 1259 | PrettyPrinter::Print(StringVal::MAX_LENGTH, TUnit::BYTES)).c_str()); |
| 1260 | return StringVal::null(); |
| 1261 | } |
| 1262 | |
| 1263 | // If total_size is zero, directly returns empty string |
| 1264 | if (total_size <= 0) return StringVal(); |
| 1265 | |
| 1266 | StringVal result(context, total_size); |
| 1267 | if (UNLIKELY(result.is_null)) return StringVal::null(); |
| 1268 | |
| 1269 | // Loop again to append the data. |
| 1270 | uint8_t* ptr = result.ptr; |
| 1271 | for (int32_t i = 0; i < num_children; ++i) { |
| 1272 | Ubsan::MemCpy(ptr, strs[i].ptr, strs[i].len); |
| 1273 | ptr += strs[i].len; |
| 1274 | } |
| 1275 | return result; |
| 1276 | } |
| 1277 | |
| 1278 | StringVal StringFunctions::ConcatWs(FunctionContext* context, const StringVal& sep, |
| 1279 | int num_children, const StringVal* strs) { |
nothing calls this directly
no test coverage detected