| 1440 | // |
| 1441 | |
| 1442 | SortedStream* Optimizer::generateSort(const StreamList& streams, |
| 1443 | const StreamList* dbkeyStreams, |
| 1444 | RecordSource* rsb, |
| 1445 | SortNode* sort, |
| 1446 | bool refetchFlag, |
| 1447 | bool projectFlag) |
| 1448 | { |
| 1449 | /* We already know the number of keys, but we also need to compute the |
| 1450 | total number of fields, keys and non-keys, to be pumped thru sort. Starting |
| 1451 | with the number of keys, count the other field referenced. Since a field |
| 1452 | is often a key, check for overlap to keep the length of the sort record |
| 1453 | down. */ |
| 1454 | |
| 1455 | /* Along with the record number, the transaction id of the |
| 1456 | * record will also be stored in the sort file. This will |
| 1457 | * be used to detect update conflict in read committed |
| 1458 | * transactions. */ |
| 1459 | |
| 1460 | ULONG items = sort->expressions.getCount() + |
| 1461 | 3 * streams.getCount() + 2 * (dbkeyStreams ? dbkeyStreams->getCount() : 0); |
| 1462 | const NestConst<ValueExprNode>* const end_node = sort->expressions.end(); |
| 1463 | |
| 1464 | // Collect all fields involved into the sort |
| 1465 | |
| 1466 | HalfStaticArray<SortField, OPT_STATIC_ITEMS> fields; |
| 1467 | ULONG totalLength = 0; |
| 1468 | |
| 1469 | for (const auto stream : streams) |
| 1470 | { |
| 1471 | UInt32Bitmap::Accessor accessor(csb->csb_rpt[stream].csb_fields); |
| 1472 | |
| 1473 | if (accessor.getFirst()) |
| 1474 | { |
| 1475 | do |
| 1476 | { |
| 1477 | const auto id = accessor.current(); |
| 1478 | |
| 1479 | const auto format = CMP_format(tdbb, csb, stream); |
| 1480 | const auto desc = &format->fmt_desc[id]; |
| 1481 | |
| 1482 | if (id >= format->fmt_count || desc->isUnknown()) |
| 1483 | IBERROR(157); // msg 157 cannot sort on a field that does not exist |
| 1484 | |
| 1485 | fields.push(SortField(stream, id, desc)); |
| 1486 | totalLength += desc->dsc_length; |
| 1487 | |
| 1488 | // If the field has already been mentioned as a sort key, don't bother to repeat it. |
| 1489 | // Unless this key is computed/volatile and thus cannot be restored after sorting. |
| 1490 | |
| 1491 | for (const auto expr : sort->expressions) |
| 1492 | { |
| 1493 | const auto fieldNode = nodeAs<FieldNode>(expr); |
| 1494 | |
| 1495 | if (fieldNode && fieldNode->fieldStream == stream && fieldNode->fieldId == id) |
| 1496 | { |
| 1497 | if (!SortedStream::hasVolatileKey(desc)) |
| 1498 | { |
| 1499 | totalLength -= desc->dsc_length; |
no test coverage detected