#pragma once #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int UNSUPPORTED_METHOD; } /** Генерирует запрос для загрузки данных из внешней БД. */ struct ExternalQueryBuilder { const DictionaryStructure & dict_struct; const std::string & db; const std::string & table; const std::string & where; ExternalQueryBuilder( const DictionaryStructure & dict_struct, const std::string & db, const std::string & table, const std::string & where) : dict_struct(dict_struct), db(db), table(table), where(where) { } /** Получить запрос на загрузку всех данных. */ std::string composeLoadAllQuery() const { std::string query; { WriteBufferFromString out{query}; writeString("SELECT ", out); if (dict_struct.id) { if (!dict_struct.id.value().expression.empty()) { writeParenthesisedString(dict_struct.id.value().expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(dict_struct.id.value().name, out); if (dict_struct.range_min && dict_struct.range_max) { writeString(", ", out); if (!dict_struct.range_min.value().expression.empty()) { writeParenthesisedString(dict_struct.range_min.value().expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(dict_struct.range_min.value().name, out); writeString(", ", out); if (!dict_struct.range_max.value().expression.empty()) { writeParenthesisedString(dict_struct.range_max.value().expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(dict_struct.range_max.value().name, out); } } else if (dict_struct.key) { auto first = true; for (const auto & key : *dict_struct.key) { if (!first) writeString(", ", out); first = false; if (!key.expression.empty()) { writeParenthesisedString(key.expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(key.name, out); } } for (const auto & attr : dict_struct.attributes) { writeString(", ", out); if (!attr.expression.empty()) { writeParenthesisedString(attr.expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(attr.name, out); } writeString(" FROM ", out); if (!db.empty()) { writeProbablyBackQuotedString(db, out); writeChar('.', out); } writeProbablyBackQuotedString(table, out); if (!where.empty()) { writeString(" WHERE ", out); writeString(where, out); } writeChar(';', out); } return query; } /** Получить запрос на загрузку данных по множеству простых ключей. */ std::string composeLoadIdsQuery(const std::vector & ids) { if (!dict_struct.id) throw Exception{"Simple key required for method", ErrorCodes::UNSUPPORTED_METHOD}; std::string query; { WriteBufferFromString out{query}; writeString("SELECT ", out); if (!dict_struct.id.value().expression.empty()) { writeParenthesisedString(dict_struct.id.value().expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(dict_struct.id.value().name, out); for (const auto & attr : dict_struct.attributes) { writeString(", ", out); if (!attr.expression.empty()) { writeParenthesisedString(attr.expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(attr.name, out); } writeString(" FROM ", out); if (!db.empty()) { writeProbablyBackQuotedString(db, out); writeChar('.', out); } writeProbablyBackQuotedString(table, out); writeString(" WHERE ", out); if (!where.empty()) { writeString(where, out); writeString(" AND ", out); } writeProbablyBackQuotedString(dict_struct.id.value().name, out); writeString(" IN (", out); auto first = true; for (const auto id : ids) { if (!first) writeString(", ", out); first = false; writeString(DB::toString(id), out); } writeString(");", out); } return query; } /** Получить запрос на загрузку данных по множеству сложных ключей. */ std::string composeLoadKeysQuery( const ConstColumnPlainPtrs & key_columns, const std::vector & requested_rows) { if (!dict_struct.key) throw Exception{"Composite key required for method", ErrorCodes::UNSUPPORTED_METHOD}; std::string query; { WriteBufferFromString out{query}; writeString("SELECT ", out); auto first = true; for (const auto & key_or_attribute : boost::join(*dict_struct.key, dict_struct.attributes)) { if (!first) writeString(", ", out); first = false; if (!key_or_attribute.expression.empty()) { writeParenthesisedString(key_or_attribute.expression, out); writeString(" AS ", out); } writeProbablyBackQuotedString(key_or_attribute.name, out); } writeString(" FROM ", out); if (!db.empty()) { writeProbablyBackQuotedString(db, out); writeChar('.', out); } writeProbablyBackQuotedString(table, out); writeString(" WHERE ", out); if (!where.empty()) { writeString(where, out); writeString(" AND ", out); } first = true; for (const auto row : requested_rows) { if (!first) writeString(" OR ", out); first = false; composeKeyCondition(key_columns, row, out); } writeString(";", out); } return query; } private: void composeKeyCondition(const ConstColumnPlainPtrs & key_columns, const std::size_t row, WriteBuffer & out) const { writeString("(", out); const auto keys_size = key_columns.size(); auto first = true; for (const auto i : ext::range(0, keys_size)) { if (!first) writeString(" AND ", out); first = false; const auto & key_description = (*dict_struct.key)[i]; /// key_i=value_i writeString(key_description.name, out); writeString("=", out); key_description.type->serializeTextQuoted(*key_columns[i], row, out); } writeString(")", out); } }; }