コード例 #1
0
String getTableDefinitionFromCreateQuery(const ASTPtr & query)
{
    ASTPtr query_clone = query->clone();
    ASTCreateQuery & create = typeid_cast<ASTCreateQuery &>(*query_clone.get());

    /// We remove everything that is not needed for ATTACH from the query.
    create.attach = true;
    create.database.clear();
    create.as_database.clear();
    create.as_table.clear();
    create.if_not_exists = false;
    create.is_populate = false;

    /// For views it is necessary to save the SELECT query itself, for the rest - on the contrary
    if (!create.is_view && !create.is_materialized_view)
        create.select = nullptr;

    create.format = nullptr;
    create.out_file = nullptr;

    std::ostringstream statement_stream;
    formatAST(create, statement_stream, false);
    statement_stream << '\n';
    return statement_stream.str();
}
コード例 #2
0
void CollectAliases::dump(WriteBuffer & out) const
{
	/// For need of tests, we need to dump result in some fixed order.
	std::vector<Aliases::const_iterator> vec;
	vec.reserve(aliases.size());
	for (auto it = aliases.begin(); it != aliases.end(); ++it)
		vec.emplace_back(it);

	std::sort(vec.begin(), vec.end(), [](const auto & a, const auto & b) { return a->first < b->first; });

	for (const auto & it : vec)
	{
		writeProbablyBackQuotedString(it->first, out);
		writeCString(" -> ", out);

		switch (it->second.kind)
		{
			case Kind::Expression:
				writeCString("(expression) ", out);
				break;
			case Kind::Table:
				writeCString("(table) ", out);
				break;
			case Kind::ArrayJoin:
				writeCString("(array join) ", out);
				break;
		}

		std::stringstream formatted_ast;
		formatAST(*it->second.node, formatted_ast, 0, false, true);
		writeString(formatted_ast.str(), out);

		writeChar('\n', out);
	}
}
コード例 #3
0
ファイル: AnalyzeColumns.cpp プロジェクト: bamx23/ClickHouse
void AnalyzeColumns::dump(WriteBuffer & out) const
{
    /// For need of tests, we need to dump result in some fixed order.
    std::vector<Columns::const_iterator> vec;
    vec.reserve(columns.size());
    for (auto it = columns.begin(); it != columns.end(); ++it)
        vec.emplace_back(it);

    std::sort(vec.begin(), vec.end(), [](const auto & a, const auto & b) { return a->first < b->first; });

    for (const auto & it : vec)
    {
        writeString(it->first, out);
        writeCString(" -> ", out);

        writeProbablyBackQuotedString(it->second.name_in_table, out);
        writeCString(" ", out);
        writeProbablyBackQuotedString(it->second.data_type->getName(), out);

        const auto & table = it->second.table;

        writeCString(". Database name: ", out);
        if (table.database_name.empty())
            writeCString("(none)", out);
        else
            writeProbablyBackQuotedString(table.database_name, out);

        writeCString(". Table name: ", out);
        if (table.table_name.empty())
            writeCString("(none)", out);
        else
            writeProbablyBackQuotedString(table.table_name, out);

        writeCString(". Alias: ", out);
        if (table.alias.empty())
            writeCString("(none)", out);
        else
            writeProbablyBackQuotedString(table.alias, out);

        writeCString(". Storage: ", out);
        if (!table.storage)
            writeCString("(none)", out);
        else
            writeProbablyBackQuotedString(table.storage->getName(), out);

        writeCString(". AST: ", out);
        if (it->second.node)
        {
            std::stringstream formatted_ast;
            formatAST(*it->second.node, formatted_ast, false, true);
            writeString(formatted_ast.str(), out);
        }
        else
            writeCString("(none)", out);

        writeChar('\n', out);
    }
}
コード例 #4
0
static void processImpl(const ASTPtr & ast, CollectAliases::Aliases & aliases, CollectAliases::Kind kind, size_t keep_kind_for_depth)
{
	String alias = ast->tryGetAlias();
	if (!alias.empty())
	{
		auto it_inserted = aliases.emplace(alias, CollectAliases::AliasInfo(ast, kind));

		if (!it_inserted.second && ast->getTreeHash() != it_inserted.first->second.node->getTreeHash())
		{
			std::stringstream message;
			message << "Different expressions with the same alias " << backQuoteIfNeed(alias) << ":\n";
			formatAST(*it_inserted.first->second.node, message, 0, false, true);
			message << "\nand\n";
			formatAST(*ast, message, 0, false, true);
			message << "\n";

			throw Exception(message.str(), ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS);
		}
	}

	for (auto & child : ast->children)
	{
		if (typeid_cast<const ASTSelectQuery *>(child.get()))
		{
			/// Don't go into subqueries.
		}
		else if (typeid_cast<const ASTTableExpression *>(child.get()))
		{
			processImpl(child, aliases, CollectAliases::Kind::Table, 1);
		}
		else if (typeid_cast<const ASTArrayJoin *>(child.get()))
		{
			/// ASTArrayJoin -> ASTExpressionList -> element of expression AS alias
			processImpl(child, aliases, CollectAliases::Kind::ArrayJoin, 3);
		}
		else if (keep_kind_for_depth > 0)
		{
			processImpl(child, aliases, kind, keep_kind_for_depth - 1);
		}
		else
		{
			processImpl(child, aliases, CollectAliases::Kind::Expression, 0);
		}
	}
}
コード例 #5
0
String getTableDefinitionFromCreateQuery(const ASTPtr & query)
{
	ASTPtr query_clone = query->clone();
	ASTCreateQuery & create = typeid_cast<ASTCreateQuery &>(*query_clone.get());

	/// Удаляем из запроса всё, что не нужно для ATTACH.
	create.attach = true;
	create.database.clear();
	create.as_database.clear();
	create.as_table.clear();
	create.if_not_exists = false;
	create.is_populate = false;

	String engine = typeid_cast<ASTFunction &>(*create.storage).name;

	/// Для engine VIEW необходимо сохранить сам селект запрос, для остальных - наоборот
	if (engine != "View" && engine != "MaterializedView")
		create.select = nullptr;

	std::ostringstream statement_stream;
	formatAST(create, statement_stream, 0, false);
	statement_stream << '\n';
	return statement_stream.str();
}
コード例 #6
0
void TypeAndConstantInference::dump(WriteBuffer & out) const
{
    /// For need of tests, we need to dump result in some fixed order.
    std::vector<Info::const_iterator> vec;
    vec.reserve(info.size());
    for (auto it = info.begin(); it != info.end(); ++it)
        vec.emplace_back(it);

    std::sort(vec.begin(), vec.end(), [](const auto & a, const auto & b) { return a->first < b->first; });

    for (const auto & it : vec)
    {
        writeString(it->first, out);
        writeCString(" -> ", out);
        writeString(it->second.data_type->getName(), out);

        if (it->second.is_constant_expression)
        {
            writeCString(" = ", out);
            String value = applyVisitor(FieldVisitorToString(), it->second.value);
            writeString(value, out);
        }

        writeCString(". AST: ", out);
        if (!it->second.node)
            writeCString("(none)", out);
        else
        {
            std::stringstream formatted_ast;
            formatAST(*it->second.node, formatted_ast, false, true);
            writeString(formatted_ast.str(), out);
        }

        writeChar('\n', out);
    }
}
コード例 #7
0
BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
{
    if (!create.cluster.empty())
        return executeDDLQueryOnCluster(query_ptr, context, {create.database});

    String database_name = create.database;

    if (create.if_not_exists && context.isDatabaseExist(database_name))
        return {};

    String database_engine_name;
    if (!create.storage)
    {
        database_engine_name = "Ordinary"; /// Default database engine.
        auto engine = std::make_shared<ASTFunction>();
        engine->name = database_engine_name;
        auto storage = std::make_shared<ASTStorage>();
        storage->set(storage->engine, engine);
        create.set(create.storage, storage);
    }
    else
    {
        const ASTStorage & storage = *create.storage;
        const ASTFunction & engine = *storage.engine;
        /// Currently, there are no database engines, that support any arguments.
        if (engine.arguments || engine.parameters || storage.partition_by || storage.order_by || storage.sample_by || storage.settings)
        {
            std::stringstream ostr;
            formatAST(storage, ostr, false, false);
            throw Exception("Unknown database engine: " + ostr.str(), ErrorCodes::UNKNOWN_DATABASE_ENGINE);
        }

        database_engine_name = engine.name;
    }

    String database_name_escaped = escapeForFileName(database_name);

    /// Create directories for tables metadata.
    String path = context.getPath();
    String metadata_path = path + "metadata/" + database_name_escaped + "/";
    Poco::File(metadata_path).createDirectory();

    DatabasePtr database = DatabaseFactory::get(database_engine_name, database_name, metadata_path, context);

    /// Will write file with database metadata, if needed.
    String metadata_file_tmp_path = path + "metadata/" + database_name_escaped + ".sql.tmp";
    String metadata_file_path = path + "metadata/" + database_name_escaped + ".sql";

    bool need_write_metadata = !create.attach;

    if (need_write_metadata)
    {
        create.attach = true;
        create.if_not_exists = false;

        std::ostringstream statement_stream;
        formatAST(create, statement_stream, false);
        statement_stream << '\n';
        String statement = statement_stream.str();

        /// Exclusive flag guarantees, that database is not created right now in another thread.
        WriteBufferFromFile out(metadata_file_tmp_path, statement.size(), O_WRONLY | O_CREAT | O_EXCL);
        writeString(statement, out);

        out.next();
        if (context.getSettingsRef().fsync_metadata)
            out.sync();
        out.close();
    }

    try
    {
        context.addDatabase(database_name, database);

        if (need_write_metadata)
            Poco::File(metadata_file_tmp_path).renameTo(metadata_file_path);

        database->loadTables(context, thread_pool, has_force_restore_data_flag);
    }
    catch (...)
    {
        if (need_write_metadata)
            Poco::File(metadata_file_tmp_path).remove();

        throw;
    }

    return {};
}
コード例 #8
0
 String queryToString(const IAST & query)
 {
     std::ostringstream out;
     formatAST(query, out, false, true);
     return out.str();
 }
コード例 #9
0
void InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
{
    String database_name = create.database;

    if (create.if_not_exists && context.isDatabaseExist(database_name))
        return;

    String database_engine_name;
    if (!create.storage)
    {
        database_engine_name = "Ordinary";	/// Движок баз данных по-умолчанию.
        auto func = std::make_shared<ASTFunction>();
        func->name = database_engine_name;
        create.storage = func;
    }
    else
    {
        const ASTFunction & engine_id = typeid_cast<const ASTFunction &>(*create.storage);

        /// На данный момент, движков таблиц с аргументами не бывает.
        if (engine_id.arguments || engine_id.parameters)
        {
            std::stringstream ostr;
            formatAST(*create.storage, ostr, 0, false, false);
            throw Exception("Unknown database engine: " + ostr.str(), ErrorCodes::UNKNOWN_DATABASE_ENGINE);
        }

        database_engine_name = engine_id.name;
    }

    String database_name_escaped = escapeForFileName(database_name);

    /// Создаём директории с данными и метаданными таблиц.
    String path = context.getPath();
    String data_path = path + "data/" + database_name_escaped + "/";
    String metadata_path = path + "metadata/" + database_name_escaped + "/";

    Poco::File(metadata_path).createDirectory();
    Poco::File(data_path).createDirectory();

    DatabasePtr database = DatabaseFactory::get(database_engine_name, database_name, metadata_path, context);

    /// Записываем файл с метаданными, если нужно.
    String metadata_file_tmp_path = path + "metadata/" + database_name_escaped + ".sql.tmp";
    String metadata_file_path = path + "metadata/" + database_name_escaped + ".sql";

    bool need_write_metadata = !create.attach;

    if (need_write_metadata)
    {
        create.attach = true;
        create.if_not_exists = false;

        std::ostringstream statement_stream;
        formatAST(create, statement_stream, 0, false);
        statement_stream << '\n';
        String statement = statement_stream.str();

        /// Гарантирует, что база данных не создаётся прямо сейчас.
        WriteBufferFromFile out(metadata_file_tmp_path, statement.size(), O_WRONLY | O_CREAT | O_EXCL);
        writeString(statement, out);
        out.next();
        out.sync();
        out.close();
    }

    try
    {
        context.addDatabase(database_name, database);

        if (need_write_metadata)
            Poco::File(metadata_file_tmp_path).renameTo(metadata_file_path);

        database->loadTables(context, thread_pool);
    }
    catch (...)
    {
        if (need_write_metadata)
            Poco::File(metadata_file_tmp_path).remove();

        throw;
    }
}