| 2683 | |
| 2684 | |
| 2685 | MultiQueryProcessingStage ClientBase::analyzeMultiQueryText( |
| 2686 | const char *& this_query_begin, const char *& this_query_end, const char * all_queries_end, |
| 2687 | ASTPtr & parsed_query, |
| 2688 | std::unique_ptr<Exception> & current_exception) |
| 2689 | { |
| 2690 | if (!is_interactive && cancelled) |
| 2691 | return MultiQueryProcessingStage::QUERIES_END; |
| 2692 | |
| 2693 | if (this_query_begin >= all_queries_end) |
| 2694 | return MultiQueryProcessingStage::QUERIES_END; |
| 2695 | |
| 2696 | // Remove leading empty newlines and other whitespace, because they |
| 2697 | // are annoying to filter in the query log. This is mostly relevant for |
| 2698 | // the tests. |
| 2699 | while (this_query_begin < all_queries_end && isWhitespaceASCII(*this_query_begin)) |
| 2700 | ++this_query_begin; |
| 2701 | |
| 2702 | if (this_query_begin >= all_queries_end) |
| 2703 | return MultiQueryProcessingStage::QUERIES_END; |
| 2704 | |
| 2705 | unsigned max_parser_depth = static_cast<unsigned>(client_context->getSettingsRef()[Setting::max_parser_depth]); |
| 2706 | unsigned max_parser_backtracks = static_cast<unsigned>(client_context->getSettingsRef()[Setting::max_parser_backtracks]); |
| 2707 | |
| 2708 | // If there are only comments left until the end of file, we just |
| 2709 | // stop. The parser can't handle this situation because it always |
| 2710 | // expects that there is some query that it can parse. |
| 2711 | // We can get into this situation because the parser also doesn't |
| 2712 | // skip the trailing comments after parsing a query. This is because |
| 2713 | // they may as well be the leading comments for the next query, |
| 2714 | // and it makes more sense to treat them as such. |
| 2715 | { |
| 2716 | Tokens tokens(this_query_begin, all_queries_end); |
| 2717 | IParser::Pos token_iterator(tokens, max_parser_depth, max_parser_backtracks); |
| 2718 | if (!token_iterator.isValid()) |
| 2719 | return MultiQueryProcessingStage::QUERIES_END; |
| 2720 | } |
| 2721 | |
| 2722 | this_query_end = this_query_begin; |
| 2723 | try |
| 2724 | { |
| 2725 | parsed_query = parseQuery(this_query_end, all_queries_end, |
| 2726 | client_context->getSettingsRef(), |
| 2727 | /*allow_multi_statements=*/ true); |
| 2728 | } |
| 2729 | catch (const Exception & e) |
| 2730 | { |
| 2731 | current_exception.reset(e.clone()); |
| 2732 | return MultiQueryProcessingStage::PARSING_EXCEPTION; |
| 2733 | } |
| 2734 | |
| 2735 | if (!parsed_query) |
| 2736 | { |
| 2737 | if (ignore_error) |
| 2738 | { |
| 2739 | Tokens tokens(this_query_begin, all_queries_end); |
| 2740 | IParser::Pos token_iterator(tokens, max_parser_depth, max_parser_backtracks); |
| 2741 | while (token_iterator->type != TokenType::Semicolon && token_iterator.isValid()) |
| 2742 | ++token_iterator; |
nothing calls this directly
no test coverage detected