| 381 | } |
| 382 | |
| 383 | static double getSelectivity(const BoolExprNode* node) |
| 384 | { |
| 385 | auto factor = REDUCE_SELECTIVITY_FACTOR_OTHER; |
| 386 | |
| 387 | if (const auto binaryNode = nodeAs<BinaryBoolNode>(node)) |
| 388 | { |
| 389 | if (binaryNode->blrOp == blr_and) |
| 390 | factor = getSelectivity(binaryNode->arg1) * getSelectivity(binaryNode->arg2); |
| 391 | else if (binaryNode->blrOp == blr_or) |
| 392 | factor = getSelectivity(binaryNode->arg1) + getSelectivity(binaryNode->arg2); |
| 393 | else |
| 394 | fb_assert(false); |
| 395 | } |
| 396 | else if (const auto listNode = nodeAs<InListBoolNode>(node)) |
| 397 | { |
| 398 | factor = REDUCE_SELECTIVITY_FACTOR_EQUALITY * listNode->list->items.getCount(); |
| 399 | } |
| 400 | else if (nodeIs<MissingBoolNode>(node)) |
| 401 | { |
| 402 | factor = REDUCE_SELECTIVITY_FACTOR_EQUALITY; |
| 403 | } |
| 404 | else if (const auto cmpNode = nodeAs<ComparativeBoolNode>(node)) |
| 405 | { |
| 406 | switch (cmpNode->blrOp) |
| 407 | { |
| 408 | case blr_eql: |
| 409 | case blr_equiv: |
| 410 | factor = REDUCE_SELECTIVITY_FACTOR_EQUALITY; |
| 411 | break; |
| 412 | |
| 413 | case blr_gtr: |
| 414 | case blr_geq: |
| 415 | factor = REDUCE_SELECTIVITY_FACTOR_GREATER; |
| 416 | break; |
| 417 | |
| 418 | case blr_lss: |
| 419 | case blr_leq: |
| 420 | factor = REDUCE_SELECTIVITY_FACTOR_LESS; |
| 421 | break; |
| 422 | |
| 423 | case blr_between: |
| 424 | factor = REDUCE_SELECTIVITY_FACTOR_BETWEEN; |
| 425 | break; |
| 426 | |
| 427 | case blr_starting: |
| 428 | factor = REDUCE_SELECTIVITY_FACTOR_STARTING; |
| 429 | break; |
| 430 | |
| 431 | default: |
| 432 | break; |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | // dimitr: |
| 437 | // |
| 438 | // Adjust to values similar to those used when the index selectivity is missing. |
| 439 | // The final value will be in the range [0.1 .. 0.5] that also matches the v3/v4 logic. |
| 440 | // This estimation is quite pessimistic but it seems to work better in practice, |
no test coverage detected