diff --git a/dbms/include/DB/Functions/FunctionsMiscellaneous.h b/dbms/include/DB/Functions/FunctionsMiscellaneous.h index 35b10e52e8e..559dc0f8353 100644 --- a/dbms/include/DB/Functions/FunctionsMiscellaneous.h +++ b/dbms/include/DB/Functions/FunctionsMiscellaneous.h @@ -1003,6 +1003,13 @@ public: prepare(array_from->getData(), array_to->getData(), block, arguments); const auto in = block.getByPosition(arguments.front()).column.get(); + + if (in->isConst()) + { + executeConst(block, arguments, result); + return; + } + auto column_result = block.getByPosition(result).type->createColumn(); auto out = column_result.get(); @@ -1024,6 +1031,34 @@ public: block.getByPosition(result).column = column_result; } +private: + void executeConst(Block & block, const ColumnNumbers & arguments, const size_t result) + { + /// Составим блок из полноценных столбцов размера 1 и вычислим функцию как обычно. + + Block tmp_block; + ColumnNumbers tmp_arguments; + + tmp_block.insert(block.getByPosition(arguments[0])); + tmp_block.getByPosition(0).column = static_cast(tmp_block.getByPosition(0).column->cloneResized(1).get())->convertToFullColumn(); + tmp_arguments.push_back(0); + + for (size_t i = 1; i < arguments.size(); ++i) + { + tmp_block.insert(block.getByPosition(arguments[i])); + tmp_arguments.push_back(i); + } + + tmp_block.insert(block.getByPosition(result)); + size_t tmp_result = arguments.size(); + + execute(tmp_block, tmp_arguments, tmp_result); + + block.getByPosition(result).column = block.getByPosition(result).type->createConstColumn( + block.rowsInFirstColumn(), + (*tmp_block.getByPosition(tmp_result).column)[0]); + } + template bool executeNum(const IColumn * in_untyped, IColumn * out_untyped) { @@ -1060,12 +1095,6 @@ public: return true; } - else if (const auto in = typeid_cast *>(in_untyped)) - { - /* TODO */ - - return true; - } return false; } @@ -1091,12 +1120,6 @@ public: return true; } - else if (const auto in = typeid_cast(in_untyped)) - { - /* TODO */ - - return true; - } return false; } @@ -1252,7 +1275,7 @@ public: } } -private: + /// Разные варианты хэш-таблиц для реализации отображения. using NumToNum = HashMap>; @@ -1298,6 +1321,10 @@ private: if (arguments.size() == 4) { const IColumnConst * default_col = dynamic_cast(&*block.getByPosition(arguments[3]).column); + + if (!default_col) + throw Exception("Fourth argument of function " + getName() + " (default value) must be constant", ErrorCodes::ILLEGAL_COLUMN); + default_value = (*default_col)[0]; /// Нужно ли преобразовать элементы to и default_value к наименьшему общему типу, который является Float64? diff --git a/dbms/tests/queries/0_stateless/00153_transform.reference b/dbms/tests/queries/0_stateless/00153_transform.reference index 5265d492b9d..eea4fa0e1a8 100644 --- a/dbms/tests/queries/0_stateless/00153_transform.reference +++ b/dbms/tests/queries/0_stateless/00153_transform.reference @@ -98,3 +98,7 @@ abc 333 1 1 +Остальные +Яндекс +Google +Остальные diff --git a/dbms/tests/queries/0_stateless/00153_transform.sql b/dbms/tests/queries/0_stateless/00153_transform.sql index cfa64fa4a5f..a5b79eeecec 100644 --- a/dbms/tests/queries/0_stateless/00153_transform.sql +++ b/dbms/tests/queries/0_stateless/00153_transform.sql @@ -8,3 +8,7 @@ SELECT transform(toString(number), ['3', '5', '7'], [111, 222, 333], 0) FROM sys SELECT transform(toString(number), ['3', '5', '7'], [111, 222, 333], -1) FROM system.numbers LIMIT 10; SELECT transform(toString(number), ['3', '5', '7'], [111, 222, 333], -1.1) FROM system.numbers LIMIT 10; SELECT transform(toString(number), ['3', '5', '7'], [111, 222.2, 333], 1) FROM system.numbers LIMIT 10; +SELECT transform(1, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title; +SELECT transform(2, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title; +SELECT transform(3, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title; +SELECT transform(4, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title;