| 489 | } |
| 490 | |
| 491 | bsoncxx::document::value StorageMongoDB::buildMongoDBQuery(const ContextPtr & context, mongocxx::options::find & options, const SelectQueryInfo & query, const Block & sample_block) |
| 492 | { |
| 493 | document projection{}; |
| 494 | for (const auto & column : sample_block) |
| 495 | projection.append(kvp(column.name, 1)); |
| 496 | |
| 497 | LOG_DEBUG(log, "MongoDB projection has built: '{}'", bsoncxx::to_json(projection)); |
| 498 | options.projection(projection.extract()); |
| 499 | |
| 500 | bool throw_on_error = context->getSettingsRef()[Setting::mongodb_throw_on_unsupported_query]; |
| 501 | |
| 502 | if (!context->getSettingsRef()[Setting::allow_experimental_analyzer]) |
| 503 | { |
| 504 | if (throw_on_error) |
| 505 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "MongoDB storage does not support 'enable_analyzer = 0' setting"); |
| 506 | return make_document(); |
| 507 | } |
| 508 | |
| 509 | const auto & query_tree = query.query_tree->as<QueryNode &>(); |
| 510 | |
| 511 | if (throw_on_error) |
| 512 | { |
| 513 | if (query_tree.hasHaving()) |
| 514 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "HAVING section is not supported. You can disable this error with 'SET mongodb_throw_on_unsupported_query=0', but this may cause poor performance, and is highly not recommended"); |
| 515 | if (query_tree.hasGroupBy()) |
| 516 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "GROUP BY section is not supported. You can disable this error with 'SET mongodb_throw_on_unsupported_query=0', but this may cause poor performance, and is highly not recommended"); |
| 517 | if (query_tree.hasWindow()) |
| 518 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "WINDOW section is not supported. You can disable this error with 'SET mongodb_throw_on_unsupported_query=0', but this may cause poor performance, and is highly not recommended"); |
| 519 | if (query_tree.hasPrewhere()) |
| 520 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "PREWHERE section is not supported. You can disable this error with 'SET mongodb_throw_on_unsupported_query=0', but this may cause poor performance, and is highly not recommended"); |
| 521 | if (query_tree.hasLimitBy()) |
| 522 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "LIMIT BY section is not supported. You can disable this error with 'SET mongodb_throw_on_unsupported_query=0', but this may cause poor performance, and is highly not recommended"); |
| 523 | } |
| 524 | |
| 525 | auto on_error = [&] (const auto * node) |
| 526 | { |
| 527 | /// Reset limit, because if we omit ORDER BY, it should not be applied |
| 528 | options.limit(0); |
| 529 | |
| 530 | if (throw_on_error) |
| 531 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, |
| 532 | "Only simple queries are supported, failed to convert expression '{}' to MongoDB query. " |
| 533 | "You can disable this restriction with 'SET mongodb_throw_on_unsupported_query=0', to read the full table and process on ClickHouse side (this may cause poor performance)", node->formatASTForErrorMessage()); |
| 534 | LOG_WARNING(log, "Failed to build MongoDB query for '{}'", node ? node->formatASTForErrorMessage() : "<unknown>"); |
| 535 | }; |
| 536 | |
| 537 | const ConstantNode * limit = nullptr; |
| 538 | const ConstantNode * offset = nullptr; |
| 539 | |
| 540 | if (query_tree.hasLimit()) |
| 541 | { |
| 542 | limit = query_tree.getLimit()->as<ConstantNode>(); |
| 543 | if (!limit) |
| 544 | { |
| 545 | on_error(query_tree.getLimit().get()); |
| 546 | } |
| 547 | } |
| 548 |
nothing calls this directly
no test coverage detected