| 1340 | } |
| 1341 | |
| 1342 | BoolExprNode* InListBoolNode::decompose(CompilerScratch* csb) |
| 1343 | { |
| 1344 | // Search for list items depending on record streams. |
| 1345 | // If found, decompose expression: |
| 1346 | // <arg> IN (<item1>, <item2>, <item3>, <item4> ...) |
| 1347 | // into: |
| 1348 | // <arg> IN (<item1>, <item2>, ...) OR <arg> = <item3> OR <arg> = <item4> ... |
| 1349 | // where the ORed booleans are known to be stream-based (i.e. contain fields inside) |
| 1350 | // and thus could use an index, if possible. |
| 1351 | // |
| 1352 | // See #8109 in the tracker, example: |
| 1353 | // |
| 1354 | // SELECT e.* |
| 1355 | // FROM Employees e |
| 1356 | // WHERE :SomeID IN (e.LeaderID, e.DispEmpID) |
| 1357 | |
| 1358 | auto& pool = csb->csb_pool; |
| 1359 | BoolExprNode* boolNode = nullptr; |
| 1360 | |
| 1361 | for (auto iter = list->items.begin(); iter != list->items.end();) |
| 1362 | { |
| 1363 | ValueExprNode* const item = *iter; |
| 1364 | |
| 1365 | SortedStreamList streams; |
| 1366 | item->collectStreams(streams); |
| 1367 | |
| 1368 | if (streams.isEmpty()) |
| 1369 | { |
| 1370 | iter++; |
| 1371 | continue; |
| 1372 | } |
| 1373 | |
| 1374 | list->items.remove(iter); |
| 1375 | |
| 1376 | const auto cmpNode = FB_NEW_POOL(pool) ComparativeBoolNode(pool, blr_eql, arg, item); |
| 1377 | |
| 1378 | if (boolNode) |
| 1379 | boolNode = FB_NEW_POOL(pool) BinaryBoolNode(pool, blr_or, boolNode, cmpNode); |
| 1380 | else |
| 1381 | boolNode = cmpNode; |
| 1382 | } |
| 1383 | |
| 1384 | if (boolNode && list->items.hasData()) |
| 1385 | { |
| 1386 | BoolExprNode* priorNode = this; |
| 1387 | |
| 1388 | if (list->items.getCount() == 1) |
| 1389 | { |
| 1390 | // Convert A IN (B) into A = B |
| 1391 | priorNode = FB_NEW_POOL(pool) ComparativeBoolNode(pool, blr_eql, arg, list->items.front()); |
| 1392 | } |
| 1393 | |
| 1394 | boolNode = FB_NEW_POOL(pool) BinaryBoolNode(pool, blr_or, boolNode, priorNode); |
| 1395 | } |
| 1396 | |
| 1397 | return boolNode; |
| 1398 | } |
| 1399 |
nothing calls this directly
no test coverage detected