| 3443 | // |
| 3444 | |
| 3445 | ValueExprNode* Optimizer::optimizeLikeSimilar(ComparativeBoolNode* cmpNode) |
| 3446 | { |
| 3447 | ValueExprNode* matchNode = cmpNode->arg1; |
| 3448 | ValueExprNode* patternNode = cmpNode->arg2; |
| 3449 | ValueExprNode* escapeNode = cmpNode->arg3; |
| 3450 | |
| 3451 | // if the pattern string or the escape string can't be |
| 3452 | // evaluated at compile time, forget it |
| 3453 | if (!nodeIs<LiteralNode>(patternNode) || (escapeNode && !nodeIs<LiteralNode>(escapeNode))) |
| 3454 | return nullptr; |
| 3455 | |
| 3456 | dsc matchDesc; |
| 3457 | matchNode->getDesc(tdbb, csb, &matchDesc); |
| 3458 | |
| 3459 | dsc* patternDesc = &nodeAs<LiteralNode>(patternNode)->litDesc; |
| 3460 | dsc* escapeDesc = nullptr; |
| 3461 | |
| 3462 | if (escapeNode) |
| 3463 | escapeDesc = &nodeAs<LiteralNode>(escapeNode)->litDesc; |
| 3464 | |
| 3465 | // if either is not a character expression, forget it |
| 3466 | if ((matchDesc.dsc_dtype > dtype_any_text) || |
| 3467 | (patternDesc->dsc_dtype > dtype_any_text) || |
| 3468 | (escapeNode && escapeDesc->dsc_dtype > dtype_any_text)) |
| 3469 | { |
| 3470 | return nullptr; |
| 3471 | } |
| 3472 | |
| 3473 | TextType* matchTextType = INTL_texttype_lookup(tdbb, INTL_TTYPE(&matchDesc)); |
| 3474 | CharSet* matchCharset = matchTextType->getCharSet(); |
| 3475 | TextType* patternTextType = INTL_texttype_lookup(tdbb, INTL_TTYPE(patternDesc)); |
| 3476 | CharSet* patternCharset = patternTextType->getCharSet(); |
| 3477 | |
| 3478 | if (cmpNode->blrOp == blr_like) |
| 3479 | { |
| 3480 | UCHAR escape_canonic[sizeof(ULONG)]; |
| 3481 | UCHAR first_ch[sizeof(ULONG)]; |
| 3482 | ULONG first_len; |
| 3483 | UCHAR* p; |
| 3484 | USHORT p_count; |
| 3485 | MoveBuffer escapeBuffer; |
| 3486 | |
| 3487 | // Get the escape character, if any |
| 3488 | if (escapeNode) |
| 3489 | { |
| 3490 | // Ensure escape string is same character set as match string |
| 3491 | p_count = MOV_make_string2(tdbb, escapeDesc, INTL_TTYPE(&matchDesc), &p, escapeBuffer); |
| 3492 | |
| 3493 | first_len = matchCharset->substring(p_count, p, sizeof(first_ch), first_ch, 0, 1); |
| 3494 | matchTextType->canonical(first_len, p, sizeof(escape_canonic), escape_canonic); |
| 3495 | } |
| 3496 | |
| 3497 | MoveBuffer patternBuffer; |
| 3498 | p_count = MOV_make_string2(tdbb, patternDesc, INTL_TTYPE(&matchDesc), &p, patternBuffer); |
| 3499 | |
| 3500 | first_len = matchCharset->substring(p_count, p, sizeof(first_ch), first_ch, 0, 1); |
| 3501 | |
| 3502 | UCHAR first_canonic[sizeof(ULONG)]; |
nothing calls this directly
no test coverage detected