mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
Merge
This commit is contained in:
commit
e477d0f7d9
@ -11,7 +11,7 @@ cat "$QUERIES_FILE" | sed "s/{table}/${TABLE}/g" | while read query; do
|
||||
echo -n "["
|
||||
for i in $(seq 1 $TRIES); do
|
||||
|
||||
RES=$(mysql -u root -h 127.0.0.1 -P 3306 --database=test -t -vvv -e "$query" 2>&1 | grep 'in set' | grep -oP '\d+\.\d+')
|
||||
RES=$(mysql -u root -h 127.0.0.1 -P 3306 --database=test -t -vvv -e "$query" 2>&1 | grep ' set ' | grep -oP '\d+\.\d+')
|
||||
|
||||
[[ "$?" == "0" ]] && echo -n "$RES" || echo -n "null"
|
||||
[[ "$i" != $TRIES ]] && echo -n ", "
|
||||
|
@ -1,3 +1,5 @@
|
||||
Note: column store in MemSQL was introduced in Feb 2014.
|
||||
|
||||
http://www.memsql.com/download/
|
||||
http://docs.memsql.com/docs/latest/setup/setup_onprem.html
|
||||
wget http://download.memsql.com/8d9f4c4d99a547baa40ba097b171bd15/memsql-3.2.x86_64.deb
|
||||
|
@ -110,7 +110,11 @@ public:
|
||||
*/
|
||||
TableFullWriteLockPtr lockForAlter()
|
||||
{
|
||||
return std::make_pair(lockDataForAlter(), lockStructureForAlter());
|
||||
/// Порядок вычисления важен.
|
||||
auto data_lock = lockDataForAlter();
|
||||
auto structure_lock = lockStructureForAlter();
|
||||
|
||||
return {std::move(data_lock), std::move(structure_lock)};
|
||||
}
|
||||
|
||||
/** Не дает изменять данные в таблице. (Более того, не дает посмотреть на структуру таблицы с намерением изменить данные).
|
||||
|
@ -26,6 +26,37 @@ InterpreterRenameQuery::InterpreterRenameQuery(ASTPtr query_ptr_, Context & cont
|
||||
}
|
||||
|
||||
|
||||
struct RenameDescription
|
||||
{
|
||||
RenameDescription(const ASTRenameQuery::Element & elem, const String & path, const String & current_database) :
|
||||
from_database_name(elem.from.database.empty() ? current_database : elem.from.database),
|
||||
from_database_name_escaped(escapeForFileName(from_database_name)),
|
||||
from_table_name(elem.from.table),
|
||||
from_table_name_escaped(escapeForFileName(from_table_name)),
|
||||
from_metadata_path(path + "metadata/" + from_database_name_escaped + "/"
|
||||
+ (!from_table_name.empty() ? from_table_name_escaped + ".sql" : "")),
|
||||
to_database_name(elem.to.database.empty() ? current_database : elem.to.database),
|
||||
to_database_name_escaped(escapeForFileName(to_database_name)),
|
||||
to_table_name(elem.to.table),
|
||||
to_table_name_escaped(escapeForFileName(to_table_name)),
|
||||
to_metadata_path(path + "metadata/" + to_database_name_escaped + "/"
|
||||
+ (!to_table_name.empty() ? to_table_name_escaped + ".sql" : ""))
|
||||
{}
|
||||
|
||||
String from_database_name;
|
||||
String from_database_name_escaped;
|
||||
String from_table_name;
|
||||
String from_table_name_escaped;
|
||||
String from_metadata_path;
|
||||
|
||||
String to_database_name;
|
||||
String to_database_name_escaped;
|
||||
String to_table_name;
|
||||
String to_table_name_escaped;
|
||||
String to_metadata_path;
|
||||
};
|
||||
|
||||
|
||||
void InterpreterRenameQuery::execute()
|
||||
{
|
||||
String path = context.getPath();
|
||||
@ -37,38 +68,59 @@ void InterpreterRenameQuery::execute()
|
||||
* или состояние может стать неконсистентным. (Это имеет смысл исправить.)
|
||||
*/
|
||||
|
||||
for (ASTRenameQuery::Elements::const_iterator it = rename.elements.begin(); it != rename.elements.end(); ++it)
|
||||
std::vector<RenameDescription> descriptions;
|
||||
descriptions.reserve(rename.elements.size());
|
||||
|
||||
/// Для того, чтобы захватывать блокировки таблиц в одном и том же порядке в разных RENAME-ах.
|
||||
struct UniqueTableName
|
||||
{
|
||||
String from_database_name = it->from.database.empty() ? current_database : it->from.database;
|
||||
String from_database_name_escaped = escapeForFileName(from_database_name);
|
||||
String from_table_name = it->from.table;
|
||||
String from_table_name_escaped = escapeForFileName(from_table_name);
|
||||
String from_metadata_path = path + "metadata/" + from_database_name_escaped + "/" + (!from_table_name.empty() ? from_table_name_escaped + ".sql" : "");
|
||||
String database_name;
|
||||
String table_name;
|
||||
|
||||
String to_database_name = it->to.database.empty() ? current_database : it->to.database;
|
||||
String to_database_name_escaped = escapeForFileName(to_database_name);
|
||||
String to_table_name = it->to.table;
|
||||
String to_table_name_escaped = escapeForFileName(to_table_name);
|
||||
String to_metadata_path = path + "metadata/" + to_database_name_escaped + "/" + (!to_table_name.empty() ? to_table_name_escaped + ".sql" : "");
|
||||
UniqueTableName(const String & database_name_, const String & table_name_)
|
||||
: database_name(database_name_), table_name(table_name_) {}
|
||||
|
||||
/// Заблокировать таблицу нужно при незаблокированном контексте.
|
||||
StoragePtr table = context.getTable(from_database_name, from_table_name);
|
||||
auto table_lock = table->lockForAlter();
|
||||
bool operator< (const UniqueTableName & rhs) const
|
||||
{
|
||||
return std::tie(database_name, table_name) < std::tie(rhs.database_name, rhs.table_name);
|
||||
}
|
||||
};
|
||||
|
||||
std::set<UniqueTableName> unique_tables;
|
||||
|
||||
for (const auto & elem : rename.elements)
|
||||
{
|
||||
descriptions.emplace_back(elem, path, current_database);
|
||||
unique_tables.emplace(descriptions.back().from_database_name, descriptions.back().from_table_name);
|
||||
}
|
||||
|
||||
std::vector<IStorage::TableFullWriteLockPtr> locks;
|
||||
locks.reserve(unique_tables.size());
|
||||
|
||||
for (const auto & names : unique_tables)
|
||||
if (auto table = context.tryGetTable(names.database_name, names.table_name))
|
||||
locks.emplace_back(table->lockForAlter());
|
||||
|
||||
/** Все таблицы заблокированы. Теперь можно блокировать Context. Порядок важен, чтобы избежать deadlock-ов.
|
||||
* Это обеспечивает атомарность всех указанных RENAME с точки зрения пользователя СУБД,
|
||||
* но лишь в случаях, когда в процессе переименования не было исключений и сервер не падал.
|
||||
*/
|
||||
|
||||
/** Все таблицы переименовываются под глобальной блокировкой. */
|
||||
Poco::ScopedLock<Poco::Mutex> lock(context.getMutex());
|
||||
|
||||
context.assertTableDoesntExist(to_database_name, to_table_name);
|
||||
for (const auto & elem : descriptions)
|
||||
{
|
||||
context.assertTableDoesntExist(elem.to_database_name, elem.to_table_name);
|
||||
|
||||
/// Уведомляем таблицу о том, что она переименовывается. Если таблица не поддерживает переименование - кинется исключение.
|
||||
|
||||
table->rename(path + "data/" + to_database_name_escaped + "/", to_database_name, to_table_name);
|
||||
StoragePtr table = context.getTable(elem.from_database_name, elem.from_table_name);
|
||||
table->rename(path + "data/" + elem.to_database_name_escaped + "/", elem.to_database_name, elem.to_table_name);
|
||||
|
||||
/// Пишем новый файл с метаданными.
|
||||
{
|
||||
String create_query;
|
||||
{
|
||||
ReadBufferFromFile in(from_metadata_path, 1024);
|
||||
ReadBufferFromFile in(elem.from_metadata_path, 1024);
|
||||
WriteBufferFromString out(create_query);
|
||||
copyData(in, out);
|
||||
}
|
||||
@ -82,22 +134,22 @@ void InterpreterRenameQuery::execute()
|
||||
|
||||
/// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой.
|
||||
if (!parse_res || (pos != end && *pos != ';'))
|
||||
throw Exception(getSyntaxErrorMessage(parse_res, create_query.data(), end, pos, expected, "in file " + from_metadata_path),
|
||||
throw Exception(getSyntaxErrorMessage(parse_res, create_query.data(), end, pos, expected, "in file " + elem.from_metadata_path),
|
||||
ErrorCodes::SYNTAX_ERROR);
|
||||
|
||||
typeid_cast<ASTCreateQuery &>(*ast).table = to_table_name;
|
||||
typeid_cast<ASTCreateQuery &>(*ast).table = elem.to_table_name;
|
||||
|
||||
Poco::FileOutputStream ostr(to_metadata_path);
|
||||
Poco::FileOutputStream ostr(elem.to_metadata_path);
|
||||
formatAST(*ast, ostr, 0, false);
|
||||
ostr << '\n';
|
||||
}
|
||||
|
||||
/// Переименовываем таблицу в контексте.
|
||||
context.addTable(to_database_name, to_table_name,
|
||||
context.detachTable(from_database_name, from_table_name));
|
||||
context.addTable(elem.to_database_name, elem.to_table_name,
|
||||
context.detachTable(elem.from_database_name, elem.from_table_name));
|
||||
|
||||
/// Удаляем старый файл с метаданными.
|
||||
Poco::File(from_metadata_path).remove();
|
||||
Poco::File(elem.from_metadata_path).remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user