| 285 | } |
| 286 | |
| 287 | Result<QueryInfo::Ptr> SQLEngineImpl::build_query_info( |
| 288 | CollectionSchema::Ptr collection, const SearchQuery &request, |
| 289 | std::shared_ptr<GroupBy> group_by) { |
| 290 | ScopedProfilerStage stage_guard(profiler_, "build_sql_info"); |
| 291 | Node::Ptr filter_node; |
| 292 | if (!request.filter_.empty()) { |
| 293 | ZVecParser::Ptr parser = ZVecParser::create(); |
| 294 | filter_node = parser->parse_filter(request.filter_); |
| 295 | if (filter_node == nullptr) { |
| 296 | LOG_ERROR("parse filter failed. reason:[%s] filter:[%s]", |
| 297 | parser->err_msg().c_str(), request.filter_.c_str()); |
| 298 | return tl::make_unexpected(Status::InvalidArgument( |
| 299 | "Invalid filter [", request.filter_, "]: ", parser->err_msg())); |
| 300 | } |
| 301 | } |
| 302 | if (group_by) { |
| 303 | auto &group = *group_by; |
| 304 | if (group.group_by_field.empty() || group.group_count == 0 || |
| 305 | group.group_topk == 0) { |
| 306 | return tl::make_unexpected(Status::InvalidArgument( |
| 307 | "Invalid group_by request: group_by_field='", group.group_by_field, |
| 308 | "', group_count=", group.group_count, |
| 309 | ", group_topk=", group.group_topk)); |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | FtsCondInfo::Ptr fts_cond_info; |
| 314 | if (const auto *fts_clause = request.target_.get_fts_clause()) { |
| 315 | auto fts_result = |
| 316 | parse_fts_query(collection, request.target_.field_name_, *fts_clause, |
| 317 | request.target_.query_params_); |
| 318 | if (!fts_result) { |
| 319 | return tl::make_unexpected(fts_result.error()); |
| 320 | } |
| 321 | fts_cond_info = std::move(fts_result.value()); |
| 322 | } |
| 323 | |
| 324 | auto sql_info = sqlengine::SQLInfoHelper::BuildSQLInfoFromSearchQuery( |
| 325 | request, std::move(filter_node), std::move(group_by)); |
| 326 | if (!sql_info) { |
| 327 | return tl::make_unexpected(sql_info.error()); |
| 328 | } |
| 329 | |
| 330 | // Attach FTS info to SelectInfo so query_analyzer can propagate it to |
| 331 | // QueryInfo. |
| 332 | if (fts_cond_info) { |
| 333 | auto select_info = |
| 334 | std::dynamic_pointer_cast<SelectInfo>(sql_info.value()->base_info()); |
| 335 | if (!select_info) { |
| 336 | return tl::make_unexpected(Status::InternalError( |
| 337 | "BuildSQLInfoFromSearchQuery did not produce SelectInfo")); |
| 338 | } |
| 339 | select_info->set_fts_cond_info(std::move(fts_cond_info)); |
| 340 | } |
| 341 | |
| 342 | LOG_DEBUG("Sql info is %s", sql_info.value()->to_string().c_str()); |
| 343 | stage_guard.close(); |
| 344 | return parse_sql_info(*collection, std::move(sql_info.value())); |