ISSUES-2973 support nested json struct for visitParamExtractRaw

This commit is contained in:
zhang2014 2018-08-28 12:23:29 +08:00
parent 9cdd576332
commit 16404c8e7b
6 changed files with 82 additions and 55 deletions

View File

@ -87,60 +87,36 @@ 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 void extract(const UInt8 * pos, const UInt8 * end, ColumnString::Chars_t & res_data)
{
if (pos == end)
std::vector<char> expect_end;
for (; pos != end; ++pos)
{
if (!expect_end.empty() && *pos == expect_end.back())
expect_end.pop_back();
else
{
switch(*pos)
{
case '[' : expect_end.push_back(']'); break;
case '{' : expect_end.push_back('}'); break;
case '"' : expect_end.push_back('"'); break;
case '\\' : skipAfterQuotationIfNeed(&pos, end, res_data); break;
default :
if (expect_end.empty() && (*pos == ',' || *pos == '}'))
return;
UInt8 open_char = *pos;
UInt8 close_char = 0;
switch (open_char)
{
case '[':
close_char = ']';
break;
case '{':
close_char = '}';
break;
case '"':
close_char = '"';
break;
}
if (close_char != 0)
{
size_t balance = 1;
char last_char = 0;
res_data.push_back(*pos);
++pos;
for (; pos != end && balance > 0; ++pos)
{
res_data.push_back(*pos);
if (open_char == '"' && *pos == '"')
{
if (last_char != '\\')
break;
}
else
{
if (*pos == open_char)
++balance;
if (*pos == close_char)
--balance;
}
if (last_char == '\\')
last_char = 0;
else
last_char = *pos;
}
}
else
{
for (; pos != end && *pos != ',' && *pos != '}'; ++pos)
res_data.push_back(*pos);
}
}

View File

@ -0,0 +1,31 @@
<test>
<name>visit_param_extract_raw</name>
<type>once</type>
<stop_conditions>
<any_of>
<average_speed_not_changing_for_ms>10000</average_speed_not_changing_for_ms>
<total_time_ms>1000</total_time_ms>
</any_of>
</stop_conditions>
<main_metric>
<max_rows_per_second />
<max_bytes_per_second />
<avg_rows_per_second />
<avg_bytes_per_second />
</main_metric>
<substitutions>
<substitution>
<name>param</name>
<values>
<value>'{"myparam":"test_string"}'</value>
<value>'{"myparam":{"nested_1":"test_string","nested_2":"test_2"}}'</value>
<value>'{"myparam":{"nested_1":"test_string","nested_2":"test_2","nested_1":"test_string","nested_2":"test_2","nested_1":"test_string","nested_2":"test_2"}}'</value>
</values>
</substitution>
</substitutions>
<query>SELECT count() FROM system.numbers WHERE NOT ignore(visitParamExtractRaw({param}, 'myparam'))</query>
</test>

View File

@ -0,0 +1,13 @@
-1
0
0
-1
1
test_string
test"string
"test_string"
"test_string"
"test\\"string"
"test\\"string"
[1,2,3]
{"nested" : [1,2,3]}

View File

@ -0,0 +1,15 @@
-- VisitParam with basic type
SELECT visitParamExtractInt('{"myparam":-1}', 'myparam');
SELECT visitParamExtractUInt('{"myparam":-1}', 'myparam');
SELECT visitParamExtractFloat('{"myparam":null}', 'myparam');
SELECT visitParamExtractFloat('{"myparam":-1}', 'myparam');
SELECT visitParamExtractBool('{"myparam":true}', 'myparam');
SELECT visitParamExtractString('{"myparam":"test_string"}', 'myparam');
SELECT visitParamExtractString('{"myparam":"test\\"string"}', 'myparam');
-- VisitParam with complex type
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": {"nested" : [1,2,3]}, "other":123}', 'myparam');

View File

@ -1,4 +0,0 @@
select visitParamExtractInt('{"myparam":-1}', 'myparam') AS res;
select visitParamExtractUInt('{"myparam":-1}', 'myparam') AS res;
select visitParamExtractFloat('{"myparam":null}', 'myparam') AS res;
select visitParamExtractFloat('{"myparam":-1}', 'myparam') AS res;