int main(int argc, char ** argv) try { Poco::AutoPtr<Poco::ConsoleChannel> channel = new Poco::ConsoleChannel(std::cerr); Logger::root().setChannel(channel); Logger::root().setLevel("trace"); /// Pre-initialize the `DateLUT` so that the first initialization does not affect the measured execution speed. DateLUT::instance(); Context context; context.setPath("./"); loadMetadata(context); DatabasePtr system = std::make_shared<DatabaseOrdinary>("system", "./metadata/system/"); context.addDatabase("system", system); system->loadTables(context, nullptr, false); system->attachTable("one", StorageSystemOne::create("one")); system->attachTable("numbers", StorageSystemNumbers::create("numbers")); context.setCurrentDatabase("default"); ReadBufferFromIStream in(std::cin); WriteBufferFromOStream out(std::cout); executeQuery(in, out, /* allow_into_outfile = */ false, context, {}); return 0; } catch (const Exception & e) { std::cerr << e.what() << ", " << e.displayText() << std::endl << std::endl << "Stack trace:" << std::endl << e.getStackTrace().toString(); return 1; }
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 {}; }
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; } }