Fix "There is no supertype" error on ALTER UPDATE #7306

This commit is contained in:
Alexey Milovidov 2020-07-21 16:31:59 +03:00
parent 796acbc185
commit fe5fb271dc
3 changed files with 51 additions and 4 deletions

View File

@ -367,15 +367,28 @@ ASTPtr MutationsInterpreter::prepare(bool dry_run)
affected_materialized.emplace(mat_column); affected_materialized.emplace(mat_column);
} }
/// Just to be sure, that we don't change type /// When doing UPDATE column = expression WHERE condition
/// after update expression execution. /// we will replace column to the result of the following expression:
///
/// CAST(if(condition, CAST(expression, type), column), type)
///
/// Inner CAST is needed to make 'if' work when branches have no common type,
/// example: type is UInt64, UPDATE x = -1 or UPDATE x = x - 1.
///
/// Outer CAST is added just in case if we don't trust the returning type of 'if'.
auto type_literal = std::make_shared<ASTLiteral>(columns_desc.getPhysical(column).type->getName());
const auto & update_expr = kv.second; const auto & update_expr = kv.second;
auto updated_column = makeASTFunction("CAST", auto updated_column = makeASTFunction("CAST",
makeASTFunction("if", makeASTFunction("if",
command.predicate->clone(), command.predicate->clone(),
update_expr->clone(), makeASTFunction("CAST",
update_expr->clone(),
type_literal),
std::make_shared<ASTIdentifier>(column)), std::make_shared<ASTIdentifier>(column)),
std::make_shared<ASTLiteral>(columns_desc.getPhysical(column).type->getName())); type_literal);
stages.back().column_to_updated.emplace(column, updated_column); stages.back().column_to_updated.emplace(column, updated_column);
} }

View File

@ -0,0 +1,21 @@
0
1
2
3
4
5
6
7
8
9
---
0
0
2
2
4
4
6
6
8
8

View File

@ -0,0 +1,13 @@
DROP TABLE IF EXISTS t;
CREATE TABLE t (x UInt64) ENGINE = MergeTree ORDER BY tuple();
INSERT INTO t SELECT number FROM numbers(10);
SELECT * FROM t;
SET mutations_sync = 1;
ALTER TABLE t UPDATE x = x - 1 WHERE x % 2 = 1;
SELECT '---';
SELECT * FROM t;
DROP TABLE t;