| 572 | } |
| 573 | |
| 574 | String formatQuery(String query) |
| 575 | { |
| 576 | const unsigned max_parser_depth = DBMS_DEFAULT_MAX_PARSER_DEPTH; |
| 577 | const unsigned max_parser_backtracks = DBMS_DEFAULT_MAX_PARSER_BACKTRACKS; |
| 578 | |
| 579 | ParserQuery parser(query.data() + query.size(), /*allow_settings_after_format_in_insert_=*/ false, /*implicit_select_=*/ false); |
| 580 | |
| 581 | String res; |
| 582 | res.reserve(query.size()); |
| 583 | |
| 584 | auto comments_callback = [&](std::string_view comment) |
| 585 | { |
| 586 | res += comment; |
| 587 | res += '\n'; |
| 588 | }; |
| 589 | |
| 590 | const char * begin = query.data(); |
| 591 | const char * pos = begin; |
| 592 | const char * end = begin + query.size(); |
| 593 | |
| 594 | skipSpacesAndComments(pos, end, comments_callback); |
| 595 | |
| 596 | size_t queries = 0; |
| 597 | while (pos < end) |
| 598 | { |
| 599 | const char * query_start = pos; |
| 600 | const ASTPtr ast = parseQueryAndMovePosition(parser, pos, end, "query in editor", /*allow_multi_statements=*/ true, /*max_query_size=*/ 0, max_parser_depth, max_parser_backtracks); |
| 601 | |
| 602 | std::string_view insert_query_payload; |
| 603 | if (auto * insert_ast = ast->as<ASTInsertQuery>(); insert_ast && insert_ast->data) |
| 604 | { |
| 605 | if (Poco::toLower(insert_ast->format) == "values") |
| 606 | { |
| 607 | /// Reset format to default to have `INSERT INTO table VALUES` instead of `INSERT INTO table VALUES FORMAT Values` |
| 608 | insert_ast->format.clear(); |
| 609 | |
| 610 | /// We assume that data ends with a newline character (same as in other places) |
| 611 | const char * this_query_end = find_first_symbols<'\n'>(insert_ast->data, end); |
| 612 | insert_ast->end = this_query_end; |
| 613 | pos = this_query_end; |
| 614 | |
| 615 | /// Remove semicolon from the INSERT query payload, since it will be added explicitly below |
| 616 | if (*insert_ast->end == '\n') |
| 617 | { |
| 618 | while (insert_ast->end > insert_ast->data && std::isspace(*insert_ast->end)) |
| 619 | --insert_ast->end; |
| 620 | } |
| 621 | } |
| 622 | else |
| 623 | pos = insert_ast->end; |
| 624 | |
| 625 | /// No need to use getReadBufferFromASTInsertQuery() here, since it does extra things that we do not need here (i.e. handle INFILE) |
| 626 | insert_query_payload = std::string_view(insert_ast->data, insert_ast->end); |
| 627 | } |
| 628 | |
| 629 | bool multiline_query = std::string_view(query_start, pos).contains('\n'); |
| 630 | if (multiline_query) |
| 631 | res += ast->formatWithSecretsMultiLine(); |
no test coverage detected