| 367 | } |
| 368 | |
| 369 | std::unique_ptr<QueryResult> ClientContext::executeWithParams(PreparedStatement* preparedStatement, |
| 370 | std::unordered_map<std::string, std::unique_ptr<Value>> inputParams, |
| 371 | std::optional<uint64_t> queryID) { // NOLINT(performance-unnecessary-value-param): It doesn't |
| 372 | // make sense to pass the map as a const reference. |
| 373 | lock_t lck{mtx}; |
| 374 | if (!preparedStatement->isSuccess()) { |
| 375 | return QueryResult::getQueryResultWithError(preparedStatement->errMsg); |
| 376 | } |
| 377 | const auto useCachedPlan = preparedStatement->canReuseCachedPlanWith(inputParams); |
| 378 | try { |
| 379 | bindParametersNoLock(*preparedStatement, inputParams); |
| 380 | } catch (std::exception& e) { |
| 381 | return QueryResult::getQueryResultWithError(e.what()); |
| 382 | } |
| 383 | auto name = preparedStatement->getName(); |
| 384 | // LCOV_EXCL_START |
| 385 | // The following should never happen. But we still throw just in case. |
| 386 | if (!cachedPreparedStatementManager.containsStatement(name)) { |
| 387 | return QueryResult::getQueryResultWithError( |
| 388 | std::format("Cannot find prepared statement with name {}.", name)); |
| 389 | } |
| 390 | // LCOV_EXCL_STOP |
| 391 | auto cachedStatement = cachedPreparedStatementManager.getCachedStatement(name); |
| 392 | if (useCachedPlan) { |
| 393 | return executeNoLock(preparedStatement, cachedStatement, queryID); |
| 394 | } |
| 395 | // rebind |
| 396 | auto [newPreparedStatement, newCachedStatement] = |
| 397 | prepareNoLock(cachedStatement->parsedStatement, false /*shouldCommitNewTransaction*/, |
| 398 | preparedStatement->parameterMap); |
| 399 | useInternalCatalogEntry_ = false; |
| 400 | return executeNoLock(newPreparedStatement.get(), newCachedStatement.get(), queryID); |
| 401 | } |
| 402 | |
| 403 | std::unique_ptr<QueryResult> ClientContext::query(std::string_view query, |
| 404 | std::optional<uint64_t> queryID, QueryConfig config) { |
nothing calls this directly
no test coverage detected