Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new diff for block structures. #280

Merged
merged 1 commit into from
Dec 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions dbms/include/DB/Core/Block.h
Original file line number Diff line number Diff line change
Expand Up @@ -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-таблицами.
*/
Expand Down
18 changes: 18 additions & 0 deletions dbms/include/DB/Core/ColumnWithTypeAndName.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
};

}
55 changes: 55 additions & 0 deletions dbms/src/Core/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down