diff --git a/dbms/include/DB/Interpreters/Context.h b/dbms/include/DB/Interpreters/Context.h index ff53d362ec3ca613e04d16647eb427b29ed3f1c3..9b955adbbe6a4aba52263a742c3eb9c65ed4d956 100644 --- a/dbms/include/DB/Interpreters/Context.h +++ b/dbms/include/DB/Interpreters/Context.h @@ -320,21 +320,22 @@ private: }; -/** Кладёт элемент в map, в деструкторе - удаляет. - * Если элемент уже есть - кидает исключение. - */ +/// Puts an element into the map, erases it in the destructor. +/// If the element already exists in the map, throws an exception containing provided message. class DDLGuard { - /// Имя объекта -> сообщение. - using Map = std::unordered_map; +public: + /// Element name -> message. + /// NOTE: using std::map here (and not std::unordered_map) to avoid iterator invalidation on insertion. + using Map = std::map; + + DDLGuard(Map & map_, std::mutex & mutex_, std::unique_lock && lock, const String & elem, const String & message); + ~DDLGuard(); +private: Map & map; Map::iterator it; std::mutex & mutex; - -public: - DDLGuard(Map & map_, std::mutex & mutex_, std::unique_lock && lock, const String & elem, const String & message); - ~DDLGuard(); }; } diff --git a/dbms/src/Interpreters/Context.cpp b/dbms/src/Interpreters/Context.cpp index 47c04e1e0677dc99b450d43a9959fdbae46ccb9c..5d51dad1a565a492aa9e81d970c212eec8d93c28 100644 --- a/dbms/src/Interpreters/Context.cpp +++ b/dbms/src/Interpreters/Context.cpp @@ -140,7 +140,7 @@ struct ContextShared /// database -> table -> exception_message /// На время выполнения операции, сюда помещается элемент, и возвращается объект, который в деструкторе удаляет элемент. /// В случае, если элемент уже есть - кидается исключение. См. class DDLGuard ниже. - using DDLGuards = std::unordered_map>; + using DDLGuards = std::unordered_map; DDLGuards ddl_guards; /// Если вы захватываете mutex и ddl_guards_mutex, то захватывать их нужно строго в этом порядке. mutable std::mutex ddl_guards_mutex;