| 302 | } |
| 303 | |
| 304 | bool Cursor::fetchAbsolute(thread_db* tdbb, SINT64 offset) const |
| 305 | { |
| 306 | if (!m_rse->isScrollable()) |
| 307 | { |
| 308 | // error: invalid fetch direction |
| 309 | status_exception::raise(Arg::Gds(isc_invalid_fetch_option) << Arg::Str("ABSOLUTE")); |
| 310 | } |
| 311 | |
| 312 | if (!validate(tdbb)) |
| 313 | return false; |
| 314 | |
| 315 | const auto request = tdbb->getRequest(); |
| 316 | Impure* const impure = request->getImpure<Impure>(m_impure); |
| 317 | |
| 318 | if (!impure->irsb_active) |
| 319 | { |
| 320 | // error: invalid cursor state |
| 321 | status_exception::raise(Arg::Gds(isc_cursor_not_open)); |
| 322 | } |
| 323 | |
| 324 | if (!offset) |
| 325 | { |
| 326 | impure->irsb_state = BOS; |
| 327 | return false; |
| 328 | } |
| 329 | |
| 330 | const auto buffer = static_cast<const BufferedStream*>(m_root); |
| 331 | const auto count = buffer->getCount(tdbb); |
| 332 | const SINT64 position = (offset > 0) ? offset - 1 : count + offset; |
| 333 | |
| 334 | if (position < 0) |
| 335 | { |
| 336 | impure->irsb_state = BOS; |
| 337 | return false; |
| 338 | } |
| 339 | else if (position >= (SINT64) count) |
| 340 | { |
| 341 | impure->irsb_state = EOS; |
| 342 | return false; |
| 343 | } |
| 344 | |
| 345 | ProfilerSelectStopWatcher profilerSelectStopWatcher(tdbb, this, |
| 346 | ProfilerManager::RecordSourceStopWatcher::Event::GET_RECORD); |
| 347 | |
| 348 | impure->irsb_position = position; |
| 349 | buffer->locate(tdbb, impure->irsb_position); |
| 350 | |
| 351 | if (!buffer->getRecord(tdbb)) |
| 352 | { |
| 353 | fb_assert(false); // this should not happen |
| 354 | impure->irsb_state = (offset > 0) ? EOS : BOS; |
| 355 | return false; |
| 356 | } |
| 357 | |
| 358 | if (m_updateCounters) |
| 359 | { |
| 360 | request->req_records_selected++; |
| 361 | request->req_records_affected.bumpFetched(); |
nothing calls this directly
no test coverage detected