mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
Merge pull request #280 from aSealBack/BlockStructureDiff
Added new diff for block structures.
This commit is contained in:
commit
d277d55763
@ -137,6 +137,9 @@ using BlocksList = std::list<Block>;
|
||||
/// Сравнить типы столбцов у блоков. Порядок столбцов имеет значение. Имена не имеют значения.
|
||||
bool blocksHaveEqualStructure(const Block & lhs, const Block & rhs);
|
||||
|
||||
/// Записать различные столбцы у блоков.
|
||||
void getColumnDiff(const Block & lhs, const Block & rhs, std::string & lhs_diff, std::string & rhs_diff);
|
||||
|
||||
/** Дополнительные данные к блокам. Они пока нужны только для запроса
|
||||
* DESCRIBE TABLE с Distributed-таблицами.
|
||||
*/
|
||||
|
@ -31,6 +31,24 @@ struct ColumnWithTypeAndName
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator==(const ColumnWithTypeAndName & other) const
|
||||
{
|
||||
return name == other.name
|
||||
&& ((!type && !other.type) || (type && other.type && type->getName() == other.type->getName()))
|
||||
&& ((!column && !other.column) || (column && other.column && column->getName() == other.column->getName()));
|
||||
}
|
||||
|
||||
std::string prettyPrint() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << name << ' ';
|
||||
if (type)
|
||||
str << type->getName() << ' ';
|
||||
if (column)
|
||||
str << column->getName();
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -455,6 +455,61 @@ bool blocksHaveEqualStructure(const Block & lhs, const Block & rhs)
|
||||
return true;
|
||||
}
|
||||
|
||||
void getColumnDiff(const Block & lhs, const Block & rhs, std::string & lhs_diff, std::string & rhs_diff)
|
||||
{
|
||||
/// Традиционная задача: наибольшая общая подпоследовательность (LCS).
|
||||
/// Полагаем, что порядок важен. Если это когда-то станет не так, упростим: например, намутим 2 set'а.
|
||||
std::vector<std::vector<int>> LCS;
|
||||
LCS.resize(lhs.columns() + 1);
|
||||
for (auto & v : LCS)
|
||||
v.resize(rhs.columns() + 1, 0);
|
||||
for (size_t i = 1; i <= lhs.columns(); ++i)
|
||||
for (size_t j = 1; j <= rhs.columns(); ++j)
|
||||
{
|
||||
if (lhs.getByPosition(i-1) == rhs.getByPosition(j-1))
|
||||
LCS[i][j] = LCS[i-1][j-1] + 1;
|
||||
else
|
||||
LCS[i][j] = std::max(LCS[i-1][j], LCS[i][j-1]);
|
||||
}
|
||||
|
||||
/// Теперь идем обратно и собираем ответ.
|
||||
std::vector<std::string> left_columns, right_columns;
|
||||
size_t l = lhs.columns(), r = rhs.columns();
|
||||
while (l > 0 && r > 0)
|
||||
{
|
||||
if (lhs.getByPosition(l-1) == rhs.getByPosition(r-1))
|
||||
{
|
||||
/// Данный элемент в обеих последовательностях, значит, в diff не попадает.
|
||||
--l;
|
||||
--r;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Маленькая эвристика: чаще всего используется при получении разницы для (expected_block, actual_block).
|
||||
/// Поэтому предпочтение будем отдавать полю, которое есть в левом блоке (expected_block), поэтому
|
||||
/// в diff попадет столбец из actual_block.
|
||||
if (LCS[l][r-1] >= LCS[l-1][r])
|
||||
right_columns.push_back(rhs.getByPosition(--r).prettyPrint());
|
||||
else
|
||||
left_columns.push_back(lhs.getByPosition(--l).prettyPrint());
|
||||
}
|
||||
}
|
||||
|
||||
while (l > 0)
|
||||
left_columns.push_back(lhs.getByPosition(--l).prettyPrint());
|
||||
while (r > 0)
|
||||
right_columns.push_back(rhs.getByPosition(--r).prettyPrint());
|
||||
|
||||
std::stringstream lhs_columns_diff, rhs_columns_diff;
|
||||
for (auto it = left_columns.rbegin(); it != left_columns.rend(); ++it)
|
||||
lhs_columns_diff << *it << '\n';
|
||||
for (auto it = right_columns.rbegin(); it != right_columns.rend(); ++it)
|
||||
rhs_columns_diff << *it << '\n';
|
||||
|
||||
lhs_diff = lhs_columns_diff.str();
|
||||
rhs_diff = rhs_columns_diff.str();
|
||||
}
|
||||
|
||||
|
||||
void Block::clear()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user