This commit is contained in:
l1tsolaiki 2021-06-25 19:24:22 +03:00
parent f8b1a6d185
commit 6981eb64ac
3 changed files with 17 additions and 26 deletions

View File

@ -41,7 +41,7 @@ public:
class Executor class Executor
{ {
public: public:
static ColumnPtr run(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) static ColumnPtr run(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count, uint32_t parse_depth)
{ {
MutableColumnPtr to{result_type->createColumn()}; MutableColumnPtr to{result_type->createColumn()};
to->reserve(input_rows_count); to->reserve(input_rows_count);
@ -76,23 +76,10 @@ public:
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
} }
/// If argument is successfully cast to (ColumnConst *) then it is quoted string
/// Example:
/// SomeFunction('some string argument')
///
/// Otherwise it is a column
/// Example:
/// SomeFunction(database.table.column)
const ColumnPtr & arg_jsonpath = first_column.column; const ColumnPtr & arg_jsonpath = first_column.column;
const auto * arg_jsonpath_const = typeid_cast<const ColumnConst *>(arg_jsonpath.get()); const auto * arg_jsonpath_const = typeid_cast<const ColumnConst *>(arg_jsonpath.get());
const auto * arg_jsonpath_string = typeid_cast<const ColumnString *>(arg_jsonpath_const->getDataColumnPtr().get()); const auto * arg_jsonpath_string = typeid_cast<const ColumnString *>(arg_jsonpath_const->getDataColumnPtr().get());
if (!arg_jsonpath_string)
{
throw Exception{"Illegal column " + arg_jsonpath->getName(), ErrorCodes::ILLEGAL_COLUMN};
}
const ColumnPtr & arg_json = second_column.column; const ColumnPtr & arg_json = second_column.column;
const auto * col_json_const = typeid_cast<const ColumnConst *>(arg_json.get()); const auto * col_json_const = typeid_cast<const ColumnConst *>(arg_json.get());
const auto * col_json_string const auto * col_json_string
@ -102,14 +89,14 @@ public:
const ColumnString::Chars & chars_path = arg_jsonpath_string->getChars(); const ColumnString::Chars & chars_path = arg_jsonpath_string->getChars();
const ColumnString::Offsets & offsets_path = arg_jsonpath_string->getOffsets(); const ColumnString::Offsets & offsets_path = arg_jsonpath_string->getOffsets();
/// Get data and offsets for 1 argument (JSON) /// Prepare to parse 1 argument (JSONPath)
const char * query_begin = reinterpret_cast<const char *>(&chars_path[0]); const char * query_begin = reinterpret_cast<const char *>(&chars_path[0]);
const char * query_end = query_begin + offsets_path[0] - 1; const char * query_end = query_begin + offsets_path[0] - 1;
/// Tokenize query /// Tokenize query
Tokens tokens(query_begin, query_end); Tokens tokens(query_begin, query_end);
/// Max depth 0 indicates that depth is not limited /// Max depth 0 indicates that depth is not limited
IParser::Pos token_iterator(tokens, 0); IParser::Pos token_iterator(tokens, parse_depth);
/// Parse query and create AST tree /// Parse query and create AST tree
Expected expected; Expected expected;
@ -121,7 +108,7 @@ public:
throw Exception{"Unable to parse JSONPath", ErrorCodes::BAD_ARGUMENTS}; throw Exception{"Unable to parse JSONPath", ErrorCodes::BAD_ARGUMENTS};
} }
/// Get data and offsets for 1 argument (JSON) /// Get data and offsets for 2 argument (JSON)
const ColumnString::Chars & chars_json = col_json_string->getChars(); const ColumnString::Chars & chars_json = col_json_string->getChars();
const ColumnString::Offsets & offsets_json = col_json_string->getOffsets(); const ColumnString::Offsets & offsets_json = col_json_string->getOffsets();
@ -179,12 +166,13 @@ public:
/// 1. Lexer(path) -> Tokens /// 1. Lexer(path) -> Tokens
/// 2. Create ASTPtr /// 2. Create ASTPtr
/// 3. Parser(Tokens, ASTPtr) -> complete AST /// 3. Parser(Tokens, ASTPtr) -> complete AST
/// 4. Execute functions, call interpreter for each json (in function) /// 4. Execute functions: call getNextItem on generator and handle each item
uint32_t parse_depth = getContext()->getSettingsRef().max_parser_depth;
#if USE_SIMDJSON #if USE_SIMDJSON
if (getContext()->getSettingsRef().allow_simdjson) if (getContext()->getSettingsRef().allow_simdjson)
return FunctionSQLJSONHelpers::Executor<Name, Impl, SimdJSONParser>::run(arguments, result_type, input_rows_count); return FunctionSQLJSONHelpers::Executor<Name, Impl, SimdJSONParser>::run(arguments, result_type, input_rows_count, parse_depth);
#endif #endif
return FunctionSQLJSONHelpers::Executor<Name, Impl, DummyJSONParser>::run(arguments, result_type, input_rows_count); return FunctionSQLJSONHelpers::Executor<Name, Impl, DummyJSONParser>::run(arguments, result_type, input_rows_count, parse_depth);
} }
}; };
@ -325,6 +313,8 @@ public:
else if (status == VisitorStatus::Error) else if (status == VisitorStatus::Error)
{ {
/// ON ERROR /// ON ERROR
/// Here it is possible to handle errors with ON ERROR (as described in ISO/IEC TR 19075-6),
/// however this functionality is not implemented yet
} }
current_element = root; current_element = root;
} }

View File

@ -14,8 +14,8 @@ public:
public: public:
/// Ranges to lookup in json array ($[0, 1, 2, 4 to 9]) /// Ranges to lookup in json array ($[0, 1, 2, 4 to 9])
/// Range is represented as <start, end> /// Range is represented as <start, end (non-inclusive)>
/// Single index is represented as <start, start> /// Single index is represented as <start, start + 1>
std::vector<std::pair<UInt32, UInt32>> ranges; std::vector<std::pair<UInt32, UInt32>> ranges;
bool is_star = false; bool is_star = false;
}; };

View File

@ -73,7 +73,8 @@ public:
{ {
while (true) while (true)
{ {
auto root = element; /// element passed to us actually is root, so here we assign current to root
auto current = element;
if (current_visitor < 0) if (current_visitor < 0)
{ {
return VisitorStatus::Exhausted; return VisitorStatus::Exhausted;
@ -81,13 +82,13 @@ public:
for (int i = 0; i < current_visitor; ++i) for (int i = 0; i < current_visitor; ++i)
{ {
visitors[i]->apply(root); visitors[i]->apply(current);
} }
VisitorStatus status = VisitorStatus::Error; VisitorStatus status = VisitorStatus::Error;
for (size_t i = current_visitor; i < visitors.size(); ++i) for (size_t i = current_visitor; i < visitors.size(); ++i)
{ {
status = visitors[i]->visit(root); status = visitors[i]->visit(current);
current_visitor = i; current_visitor = i;
if (status == VisitorStatus::Error || status == VisitorStatus::Ignore) if (status == VisitorStatus::Error || status == VisitorStatus::Ignore)
{ {
@ -98,7 +99,7 @@ public:
if (status != VisitorStatus::Ignore) if (status != VisitorStatus::Ignore)
{ {
element = root; element = current;
return status; return status;
} }
} }