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 "["
|
echo -n "["
|
||||||
for i in $(seq 1 $TRIES); do
|
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"
|
[[ "$?" == "0" ]] && echo -n "$RES" || echo -n "null"
|
||||||
[[ "$i" != $TRIES ]] && echo -n ", "
|
[[ "$i" != $TRIES ]] && echo -n ", "
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
Note: column store in MemSQL was introduced in Feb 2014.
|
||||||
|
|
||||||
http://www.memsql.com/download/
|
http://www.memsql.com/download/
|
||||||
http://docs.memsql.com/docs/latest/setup/setup_onprem.html
|
http://docs.memsql.com/docs/latest/setup/setup_onprem.html
|
||||||
wget http://download.memsql.com/8d9f4c4d99a547baa40ba097b171bd15/memsql-3.2.x86_64.deb
|
wget http://download.memsql.com/8d9f4c4d99a547baa40ba097b171bd15/memsql-3.2.x86_64.deb
|
||||||
|
@ -110,7 +110,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
TableFullWriteLockPtr lockForAlter()
|
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()
|
void InterpreterRenameQuery::execute()
|
||||||
{
|
{
|
||||||
String path = context.getPath();
|
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 database_name;
|
||||||
String from_database_name_escaped = escapeForFileName(from_database_name);
|
String table_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 to_database_name = it->to.database.empty() ? current_database : it->to.database;
|
UniqueTableName(const String & database_name_, const String & table_name_)
|
||||||
String to_database_name_escaped = escapeForFileName(to_database_name);
|
: database_name(database_name_), table_name(table_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" : "");
|
|
||||||
|
|
||||||
/// Заблокировать таблицу нужно при незаблокированном контексте.
|
bool operator< (const UniqueTableName & rhs) const
|
||||||
StoragePtr table = context.getTable(from_database_name, from_table_name);
|
{
|
||||||
auto table_lock = table->lockForAlter();
|
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());
|
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);
|
||||||
|
|
||||||
/// Уведомляем таблицу о том, что она переименовывается. Если таблица не поддерживает переименование - кинется исключение.
|
/// Уведомляем таблицу о том, что она переименовывается. Если таблица не поддерживает переименование - кинется исключение.
|
||||||
|
StoragePtr table = context.getTable(elem.from_database_name, elem.from_table_name);
|
||||||
table->rename(path + "data/" + to_database_name_escaped + "/", to_database_name, to_table_name);
|
table->rename(path + "data/" + elem.to_database_name_escaped + "/", elem.to_database_name, elem.to_table_name);
|
||||||
|
|
||||||
/// Пишем новый файл с метаданными.
|
/// Пишем новый файл с метаданными.
|
||||||
{
|
{
|
||||||
String create_query;
|
String create_query;
|
||||||
{
|
{
|
||||||
ReadBufferFromFile in(from_metadata_path, 1024);
|
ReadBufferFromFile in(elem.from_metadata_path, 1024);
|
||||||
WriteBufferFromString out(create_query);
|
WriteBufferFromString out(create_query);
|
||||||
copyData(in, out);
|
copyData(in, out);
|
||||||
}
|
}
|
||||||
@ -82,22 +134,22 @@ void InterpreterRenameQuery::execute()
|
|||||||
|
|
||||||
/// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой.
|
/// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой.
|
||||||
if (!parse_res || (pos != end && *pos != ';'))
|
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);
|
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);
|
formatAST(*ast, ostr, 0, false);
|
||||||
ostr << '\n';
|
ostr << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Переименовываем таблицу в контексте.
|
/// Переименовываем таблицу в контексте.
|
||||||
context.addTable(to_database_name, to_table_name,
|
context.addTable(elem.to_database_name, elem.to_table_name,
|
||||||
context.detachTable(from_database_name, from_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