#include #include #include namespace DB { #pragma region URL_Parser struct URL { std::string scheme; std::string user; std::string password; std::string host; uint16_t port = 0; std::string path; std::map query; std::string fragment; }; URL ParseURL(const std::string& url) { URL result; std::string cur = url; size_t pos = cur.find("://"); if (pos != std::string::npos) { result.scheme = cur.substr(0, pos); cur = cur.substr(pos + 3); } pos = cur.find('@'); auto pos0 = pos; if (pos != std::string::npos) { std::string userInfo = cur.substr(0, pos); pos = userInfo.find(':'); if (pos != std::string::npos) { result.user = userInfo.substr(0, pos); result.password = userInfo.substr(pos + 1); } else result.user = userInfo; cur = cur.substr(pos0 + 1); } pos = cur.find_first_of("/?#"); auto pos1 = pos; std::string address = cur.substr(0, pos); pos = address.find(':'); if (pos != std::string::npos) { result.host = address.substr(0, pos); result.port = static_cast(std::stoi(address.substr(pos + 1))); } else result.host = address; if (pos1 == std::string::npos) return result; else cur = cur.substr(pos1); pos = cur.find_first_of("?#"); result.path = cur.substr(0, pos); if (pos == std::string::npos) return result; else cur = cur.substr(pos); if (cur[0] == '?') { cur = cur.substr(1); pos = cur.find('#'); std::string query = cur.substr(0, pos); if (pos != std::string::npos) { result.fragment = cur.substr(pos + 1); } std::vector pairs = SplitStrWithPattern(query, "&"); for (auto& pair : pairs) { std::string k, v; pos = pair.find('='); if (pos == std::string::npos) k = pair; else { k = pair.substr(0, pos); v = pair.substr(pos + 1); } result.query.emplace(k, v); } } else if (cur[0] == '#') { result.fragment = cur.substr(1); } return result; } extern Logger dbLogger; void PrintURL(const URL& url) { dbLogger.debug("Parsed URL"); dbLogger.debug("scheme: {}", url.scheme); dbLogger.debug("user: {}", url.user); dbLogger.debug("password: {}", url.password); dbLogger.debug("host: {}", url.host); dbLogger.debug("port: {}", url.port); dbLogger.debug("path: {}", url.path); dbLogger.debug("query:"); for (auto& pair : url.query) dbLogger.debug("- {}: {}", pair.first, pair.second); dbLogger.debug("fragment: {}", url.fragment); } #pragma endregion ConnParams::ConnParams(const std::initializer_list& list) : std::unordered_map() { bool key = true; std::string keyName; for (auto& item : list) { if (key) { if (item.is_string()) { throw std::invalid_argument("ConnParams::ConnParams: Key must be string"); } keyName = item.get(); key = false; } else { insert({keyName, item}); key = true; } } auto host = getHost(); if (host.find(':') != std::string::npos) { host = host.substr(0, host.find_last_of(':')); auto port = host.substr(host.find_last_of(':') + 1); (*this)["host"] = host; (*this)["port"] = std::stoi(port); } } ConnParams::ConnParams(const std::initializer_list>& list) : std::unordered_map() { for (auto& item : list) { insert(item); } auto host = getHost(); if (host.find(':') != std::string::npos) { host = host.substr(0, host.find_last_of(':')); auto port = host.substr(host.find_last_of(':') + 1); (*this)["host"] = host; (*this)["port"] = std::stoi(port); } } ConnParams::ConnParams(const std::string& str) : std::unordered_map() { raw = str; auto url = ParseURL(str); #if defined(LLDB_DEBUG_MODE) PrintURL(url); #endif if (!url.scheme.empty()) insert({"scheme", url.scheme}); if (!url.host.empty()) insert({"host", url.host}); if (url.port) insert({"port", url.port}); if (!url.user.empty()) insert({"user", url.user}); if (!url.password.empty()) insert({"password", url.password}); if (!url.path.empty()) { std::string path = url.path; if (path[0] == '/') path = path.substr(1); insert({"path", path}); } if (!url.fragment.empty()) insert({"fragment", url.fragment}); for (auto& pair : url.query) { insert({pair.first, Any::str2any(pair.second)}); } } ConnParams::ConnParams(const char* str) : std::unordered_map() { *this = ConnParams(std::string(str)); } std::string ConnParams::getScheme() { return get({"scheme", "protocol", "type"}, true); } std::string ConnParams::getHost() { return get({"host", "hostname", "server", "server_name", "ip", "address"}, true); } uint16_t ConnParams::getPort() { return get({"port", "port_number", "port_num", "port_id", "portid"}, true, 0); } std::string ConnParams::getUsername() { return get({"user", "username", "user_name", "usr", "usrname"}, true); } std::string ConnParams::getPassword() { return get({"password", "pass", "passwd", "pass_word"}, true); } std::string ConnParams::getDatabase() { return get({"database", "db", "db_name", "dbname", "path"}, true); } std::string ConnParams::getPath() { return get({"path", "file", "file_name", "filename"}, true); } std::string ConnParams::getRaw() { return raw; } } // namespace DB