diff --git a/dbms/src/Functions/FunctionsVisitParam.h b/dbms/src/Functions/FunctionsVisitParam.h index 761d6236a83..a212397f361 100644 --- a/dbms/src/Functions/FunctionsVisitParam.h +++ b/dbms/src/Functions/FunctionsVisitParam.h @@ -87,45 +87,47 @@ struct ExtractBool struct ExtractRaw { - inline static void skipAfterQuotationIfNeed(const UInt8 *& pos, const UInt8 * end, ColumnString::Chars_t & res_data) - { - if (pos + 1 < end && pos[1] == '"') - { - res_data.push_back(*pos); - ++pos; - } - } + static constexpr size_t bytes_on_stack = 64; + using ExpectChars = PODArray, bytes_on_stack>>; static void extract(const UInt8 * pos, const UInt8 * end, ColumnString::Chars_t & res_data) { - std::vector expect_end; + ExpectChars expects_end; + UInt8 current_expect_end = 0; - for (; pos != end; ++pos) + for (auto extract_begin = pos; pos != end; ++pos) { - if (!expect_end.empty() && *pos == expect_end.back()) - expect_end.pop_back(); + if (*pos == current_expect_end) + { + expects_end.pop_back(); + current_expect_end = (UInt8) (expects_end.empty() ? 0 : expects_end.back()); + } else { - switch (*pos) + switch(*pos) { - case '[': - expect_end.push_back(']'); + case '[': + expects_end.push_back((current_expect_end = ']')); break; - case '{': - expect_end.push_back('}'); + case '{': + expects_end.push_back((current_expect_end = '}')); break; - case '"': - expect_end.push_back('"'); + case '"' : + expects_end.push_back((current_expect_end = '"')); break; - case '\\': - skipAfterQuotationIfNeed(pos, end, res_data); + case '\\': + /// skip backslash + if (pos + 1 < end && pos[1] == '"') + pos++; break; default: - if (expect_end.empty() && (*pos == ',' || *pos == '}')) + if (!current_expect_end && (*pos == ',' || *pos == '}')) + { + res_data.insert(extract_begin, pos); return; + } } } - res_data.push_back(*pos); } } }; diff --git a/dbms/tests/performance/functions_json/visit_param_extract_raw.xml b/dbms/tests/performance/functions_json/visit_param_extract_raw.xml index c697373a72c..acd0bfe41a6 100644 --- a/dbms/tests/performance/functions_json/visit_param_extract_raw.xml +++ b/dbms/tests/performance/functions_json/visit_param_extract_raw.xml @@ -27,5 +27,5 @@ - SELECT count() FROM system.numbers WHERE NOT ignore(visitParamExtractRaw({param}, 'myparam')) + SELECT count() FROM system.numbers WHERE NOT ignore(visitParamExtractRaw(materialize({param}), 'myparam')) diff --git a/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.reference b/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.reference index 1b9bc7d15fe..ee7fb68b7c2 100644 --- a/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.reference +++ b/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.reference @@ -9,5 +9,5 @@ test"string "test_string" "test\\"string" "test\\"string" - [1,2,3] + ["]", "2", "3"] {"nested" : [1,2,3]} diff --git a/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.sql b/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.sql index 14d4fa3faf2..8a4d1794293 100644 --- a/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.sql +++ b/dbms/tests/queries/0_stateless/00539_functions_for_working_with_json.sql @@ -11,5 +11,5 @@ SELECT visitParamExtractRaw('{"myparam":"test_string"}', 'myparam'); SELECT visitParamExtractRaw('{"myparam": "test_string"}', 'myparam'); SELECT visitParamExtractRaw('{"myparam": "test\\"string"}', 'myparam'); SELECT visitParamExtractRaw('{"myparam": "test\\"string", "other":123}', 'myparam'); -SELECT visitParamExtractRaw('{"myparam": [1,2,3], "other":123}', 'myparam'); +SELECT visitParamExtractRaw('{"myparam": ["]", "2", "3"], "other":123}', 'myparam'); SELECT visitParamExtractRaw('{"myparam": {"nested" : [1,2,3]}, "other":123}', 'myparam');