diff --git a/src/internals/sql-ref.rst b/src/internals/sql-ref.rst index a1780892..791aebba 100644 --- a/src/internals/sql-ref.rst +++ b/src/internals/sql-ref.rst @@ -2475,14 +2475,14 @@ parse_url(*url*) .. code-block:: custsqlite ;SELECT parse_url('https://example.com/search?q=hello%20world') - {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/search","query":{"q":"hello world"},"fragment":null} + {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/search","query":"q=hello%20world","parameters":{"q":"hello world"},"fragment":null} To parse the URL 'https://alice@[fe80::14ff:4ee5:1215:2fb2]': .. code-block:: custsqlite ;SELECT parse_url('https://alice@[fe80::14ff:4ee5:1215:2fb2]') - {"scheme":"https","user":"alice","password":null,"host":"[fe80::14ff:4ee5:1215:2fb2]","port":null,"path":"/","query":null,"fragment":null} + {"scheme":"https","user":"alice","password":null,"host":"[fe80::14ff:4ee5:1215:2fb2]","port":null,"path":"/","query":null,"parameters":null,"fragment":null} **See Also** :ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`unparse_url`, :ref:`unparse_url`, :ref:`upper`, :ref:`xpath` diff --git a/src/string-extension-functions.cc b/src/string-extension-functions.cc index 0ef4fd96..e20840e1 100644 --- a/src/string-extension-functions.cc +++ b/src/string-extension-functions.cc @@ -699,9 +699,12 @@ sql_parse_url(string_fragment url_frag) } else { root.gen(); } - root.gen("query"); rc = curl_url_get(cu, CURLUPART_QUERY, url_part.out(), 0); if (rc == CURLUE_OK) { + root.gen("query"); + root.gen(string_fragment::from_c_str(url_part.in())); + + root.gen("parameters"); robin_hood::unordered_set seen_keys; yajlpp_map query_map(gen); @@ -754,6 +757,9 @@ sql_parse_url(string_fragment url_frag) remaining = split_res->second; } } else { + root.gen("query"); + root.gen(); + root.gen("parameters"); root.gen(); } root.gen("fragment"); @@ -776,13 +782,14 @@ struct url_parts { nonstd::optional up_host; nonstd::optional up_port; nonstd::optional up_path; - std::map> up_query; + nonstd::optional up_query; + std::map> up_parameters; nonstd::optional up_fragment; }; -static const json_path_container url_query_handlers = { +static const json_path_container url_params_handlers = { yajlpp::pattern_property_handler("(?.+)") - .for_field(&url_parts::up_query), + .for_field(&url_parts::up_parameters), }; static const typed_json_path_container url_parts_handlers = { @@ -792,7 +799,8 @@ static const typed_json_path_container url_parts_handlers = { yajlpp::property_handler("host").for_field(&url_parts::up_host), yajlpp::property_handler("port").for_field(&url_parts::up_port), yajlpp::property_handler("path").for_field(&url_parts::up_path), - yajlpp::property_handler("query").with_children(url_query_handlers), + yajlpp::property_handler("query").for_field(&url_parts::up_query), + yajlpp::property_handler("parameters").with_children(url_params_handlers), yajlpp::property_handler("fragment").for_field(&url_parts::up_fragment), }; @@ -832,8 +840,10 @@ sql_unparse_url(string_fragment in) if (up.up_path) { curl_url_set(cu, CURLUPART_PATH, up.up_path->c_str(), CURLU_URLENCODE); } - if (!up.up_query.empty()) { - for (const auto& pair : up.up_query) { + if (up.up_query) { + curl_url_set(cu, CURLUPART_QUERY, up.up_query->c_str(), 0); + } else if (!up.up_parameters.empty()) { + for (const auto& pair : up.up_parameters) { auto_mem key(curl_free); auto_mem value(curl_free); std::string qparam; @@ -1159,6 +1169,10 @@ string_extension_functions(struct FuncDef** basic_funcs, }) .with_result({ "query", + "The query string in the URL", + }) + .with_result({ + "parameters", "An object containing the query parameters", }) .with_result({