| 289 | |
| 290 | |
| 291 | void EVL_dbkey_bounds(thread_db* tdbb, const Array<DbKeyRangeNode*>& ranges, |
| 292 | jrd_rel* relation, RecordNumber& lowerBound, RecordNumber& upperBound) |
| 293 | { |
| 294 | /************************************** |
| 295 | * |
| 296 | * E V L _ d b k e y _ b o u n d s |
| 297 | * |
| 298 | ************************************** |
| 299 | * |
| 300 | * Functional description |
| 301 | * Evaluate DBKEY ranges and find lower/upper bounds. |
| 302 | * |
| 303 | **************************************/ |
| 304 | SET_TDBB(tdbb); |
| 305 | |
| 306 | Request* const request = tdbb->getRequest(); |
| 307 | |
| 308 | for (const auto node : ranges) |
| 309 | { |
| 310 | if (node->lower) |
| 311 | { |
| 312 | const auto desc = EVL_expr(tdbb, request, node->lower); |
| 313 | |
| 314 | if (!(request->req_flags & req_null) && |
| 315 | desc && (desc->isText() || desc->isDbKey())) |
| 316 | { |
| 317 | UCHAR* ptr = NULL; |
| 318 | const auto length = MOV_get_string(tdbb, desc, &ptr, NULL, 0); |
| 319 | |
| 320 | if (length == sizeof(RecordNumber::Packed)) |
| 321 | { |
| 322 | Aligner<RecordNumber::Packed> alignedNumber(ptr, length); |
| 323 | const auto dbkey = (const RecordNumber::Packed*) alignedNumber; |
| 324 | |
| 325 | if (dbkey->bid_relation_id == relation->rel_id) |
| 326 | { |
| 327 | RecordNumber recno; |
| 328 | recno.bid_decode(dbkey); |
| 329 | // Decrement the value in order to switch back to the zero based numbering |
| 330 | recno.decrement(); |
| 331 | recno.setValid(true); |
| 332 | |
| 333 | if ((!lowerBound.isValid() || recno > lowerBound) && |
| 334 | recno.getValue() > BOF_NUMBER) |
| 335 | { |
| 336 | lowerBound = recno; |
| 337 | } |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | if (node->upper) |
| 344 | { |
| 345 | const auto desc = EVL_expr(tdbb, request, node->upper); |
| 346 | |
| 347 | if (!(request->req_flags & req_null) && |
| 348 | desc && (desc->isText() || desc->isDbKey())) |
no test coverage detected