| 1374 | } |
| 1375 | |
| 1376 | ColumnPtr executeImpl(const ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count) const override |
| 1377 | { |
| 1378 | ColumnsWithTypeAndName arguments = args; |
| 1379 | executeShortCircuitArguments(arguments); |
| 1380 | ColumnPtr res; |
| 1381 | if ( (res = executeForConstAndNullableCondition(arguments, result_type, input_rows_count)) |
| 1382 | || (res = executeForNullThenElse(arguments, result_type, input_rows_count)) |
| 1383 | || (res = executeForNullableThenElse(arguments, result_type, input_rows_count))) |
| 1384 | return res; |
| 1385 | |
| 1386 | const ColumnWithTypeAndName & arg_cond = arguments[0]; |
| 1387 | const ColumnWithTypeAndName & arg_then = arguments[1]; |
| 1388 | const ColumnWithTypeAndName & arg_else = arguments[2]; |
| 1389 | |
| 1390 | /// A case for identical then and else (pointers are the same). |
| 1391 | if (arg_then.column.get() == arg_else.column.get()) |
| 1392 | { |
| 1393 | /// Just point result to them. |
| 1394 | return arg_then.column; |
| 1395 | } |
| 1396 | |
| 1397 | const ColumnUInt8 * cond_col = typeid_cast<const ColumnUInt8 *>(arg_cond.column.get()); |
| 1398 | const ColumnConst * cond_const_col = checkAndGetColumnConst<ColumnVector<UInt8>>(arg_cond.column.get()); |
| 1399 | ColumnPtr materialized_cond_col; |
| 1400 | |
| 1401 | if (cond_const_col) |
| 1402 | { |
| 1403 | UInt8 value = cond_const_col->getValue<UInt8>(); |
| 1404 | const ColumnWithTypeAndName & arg = value ? arg_then : arg_else; |
| 1405 | if (arg.type->equals(*result_type)) |
| 1406 | return arg.column; |
| 1407 | return castForIf(arg, result_type); |
| 1408 | } |
| 1409 | |
| 1410 | if (!cond_col) |
| 1411 | throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of first argument of function {}. " |
| 1412 | "Must be ColumnUInt8 or ColumnConstUInt8.", arg_cond.column->getName(), getName()); |
| 1413 | |
| 1414 | /// If result is Variant, always use generic implementation. |
| 1415 | /// Using typed implementations may lead to incorrect result column type when |
| 1416 | /// resulting Variant is created by use_variant_when_no_common_type. |
| 1417 | if (isVariant(result_type)) |
| 1418 | return executeGeneric(cond_col, arguments, result_type, input_rows_count); |
| 1419 | |
| 1420 | auto call = [&](const auto & types) -> bool |
| 1421 | { |
| 1422 | using Types = std::decay_t<decltype(types)>; |
| 1423 | using T0 = typename Types::LeftType; |
| 1424 | using T1 = typename Types::RightType; |
| 1425 | |
| 1426 | res = executeTyped<T0, T1>(cond_col, arguments, result_type, input_rows_count); |
| 1427 | return res != nullptr; |
| 1428 | }; |
| 1429 | |
| 1430 | DataTypePtr left_type = arg_then.type; |
| 1431 | DataTypePtr right_type = arg_else.type; |
| 1432 | |
| 1433 | if (const auto * left_array = checkAndGetDataType<DataTypeArray>(arg_then.type.get())) |
nothing calls this directly
no test coverage detected