| 198 | } |
| 199 | |
| 200 | Status ImpalaServer::FetchInternal(const TUniqueId& query_id, SessionState* session, |
| 201 | int32_t fetch_size, bool fetch_first, TFetchResultsResp* fetch_results, |
| 202 | int32_t* num_results) { |
| 203 | bool timed_out = false; |
| 204 | int64_t block_on_wait_time_us = 0; |
| 205 | QueryHandle query_handle; |
| 206 | RETURN_IF_ERROR( |
| 207 | WaitForResults(query_id, &query_handle, &block_on_wait_time_us, &timed_out)); |
| 208 | if (timed_out) { |
| 209 | fetch_results->status.__set_statusCode(thrift::TStatusCode::STILL_EXECUTING_STATUS); |
| 210 | fetch_results->__set_hasMoreRows(true); |
| 211 | fetch_results->__isset.results = false; |
| 212 | return Status::OK(); |
| 213 | } |
| 214 | |
| 215 | int64_t start_time_ns = MonotonicNanos(); |
| 216 | lock_guard<mutex> frl(*query_handle->fetch_rows_lock()); |
| 217 | lock_guard<mutex> l(*query_handle->lock()); |
| 218 | int64_t lock_wait_time_ns = MonotonicNanos() - start_time_ns; |
| 219 | query_handle->AddClientFetchLockWaitTime(lock_wait_time_ns); |
| 220 | |
| 221 | // Check for cancellation or an error. |
| 222 | RETURN_IF_ERROR(query_handle->query_status()); |
| 223 | |
| 224 | if (query_handle->num_rows_fetched() == 0) { |
| 225 | query_handle->set_fetched_rows(); |
| 226 | } |
| 227 | |
| 228 | if (fetch_first) RETURN_IF_ERROR(query_handle->RestartFetch()); |
| 229 | |
| 230 | fetch_results->results.__set_startRowOffset(query_handle->num_rows_fetched()); |
| 231 | |
| 232 | // Child queries should always return their results in row-major format, rather than |
| 233 | // inheriting the parent session's setting. |
| 234 | bool is_child_query = query_handle->parent_query_id() != TUniqueId(); |
| 235 | TProtocolVersion::type version = is_child_query ? |
| 236 | TProtocolVersion::HIVE_CLI_SERVICE_PROTOCOL_V1 : session->hs2_version; |
| 237 | |
| 238 | // In the first fetch, expect 0 results to avoid reserving unnecessarily large result |
| 239 | // vectors for small queries. If there are more fetches (so there are more rows than |
| 240 | // num_rows_fetched), then expect subsequent fetches to be fully filled. |
| 241 | int expected_result_count = query_handle->num_rows_fetched() == 0 ? 0 |
| 242 | : fetch_size; |
| 243 | |
| 244 | scoped_ptr<QueryResultSet> result_set(QueryResultSet::CreateHS2ResultSet( |
| 245 | version, *(query_handle->result_metadata()), &(fetch_results->results), |
| 246 | query_handle->query_options().stringify_map_keys, expected_result_count)); |
| 247 | RETURN_IF_ERROR( |
| 248 | query_handle->FetchRows(fetch_size, result_set.get(), block_on_wait_time_us)); |
| 249 | *num_results = result_set->size(); |
| 250 | fetch_results->__isset.results = true; |
| 251 | fetch_results->__set_hasMoreRows(!query_handle->eos()); |
| 252 | return Status::OK(); |
| 253 | } |
| 254 | |
| 255 | Status ImpalaServer::TExecuteStatementReqToTQueryContext( |
| 256 | const TExecuteStatementReq execute_request, TQueryCtx* query_ctx) { |
nothing calls this directly
no test coverage detected