| 1361 | // |
| 1362 | |
| 1363 | void Optimizer::generateAggregateDistincts(MapNode* map) |
| 1364 | { |
| 1365 | dsc descriptor; |
| 1366 | dsc* desc = &descriptor; |
| 1367 | |
| 1368 | for (auto from : map->sourceList) |
| 1369 | { |
| 1370 | auto aggNode = nodeAs<AggNode>(from); |
| 1371 | |
| 1372 | if (aggNode && aggNode->distinct) |
| 1373 | { |
| 1374 | // Build the sort key definition. Turn cstrings into varying text. |
| 1375 | aggNode->arg->getDesc(tdbb, csb, desc); |
| 1376 | |
| 1377 | if (desc->dsc_dtype == dtype_cstring) |
| 1378 | { |
| 1379 | desc->dsc_dtype = dtype_varying; |
| 1380 | desc->dsc_length++; |
| 1381 | } |
| 1382 | |
| 1383 | const auto asb = FB_NEW_POOL(getPool()) AggregateSort(getPool()); |
| 1384 | |
| 1385 | asb->intl = desc->isText() && desc->getTextType() != ttype_none && |
| 1386 | desc->getTextType() != ttype_binary && desc->getTextType() != ttype_ascii; |
| 1387 | |
| 1388 | sort_key_def* sort_key = asb->keyItems.getBuffer(asb->intl ? 2 : 1); |
| 1389 | sort_key->setSkdOffset(); |
| 1390 | |
| 1391 | if (asb->intl) |
| 1392 | { |
| 1393 | const USHORT key_length = ROUNDUP(INTL_key_length(tdbb, |
| 1394 | INTL_TEXT_TO_INDEX(desc->getTextType()), desc->getStringLength()), sizeof(SINT64)); |
| 1395 | |
| 1396 | sort_key->setSkdLength(SKD_bytes, key_length); |
| 1397 | sort_key->skd_flags = SKD_ascending; |
| 1398 | sort_key->skd_vary_offset = 0; |
| 1399 | |
| 1400 | ++sort_key; |
| 1401 | sort_key->setSkdOffset(&sort_key[-1]); |
| 1402 | asb->length = sort_key->getSkdOffset(); |
| 1403 | } |
| 1404 | |
| 1405 | fb_assert(desc->dsc_dtype < FB_NELEM(sort_dtypes)); |
| 1406 | sort_key->setSkdLength(sort_dtypes[desc->dsc_dtype], desc->dsc_length); |
| 1407 | |
| 1408 | if (!sort_key->skd_dtype) |
| 1409 | ERR_post(Arg::Gds(isc_invalid_sort_datatype) << Arg::Str(DSC_dtype_tostring(desc->dsc_dtype))); |
| 1410 | |
| 1411 | if (desc->dsc_dtype == dtype_varying) |
| 1412 | { |
| 1413 | // allocate space to store varying length |
| 1414 | sort_key->skd_vary_offset = sort_key->getSkdOffset() + ROUNDUP(desc->dsc_length, sizeof(SLONG)); |
| 1415 | asb->length = sort_key->skd_vary_offset + sizeof(USHORT); |
| 1416 | } |
| 1417 | else |
| 1418 | asb->length += sort_key->getSkdLength(); |
| 1419 | |
| 1420 | asb->length = ROUNDUP(asb->length, sizeof(SLONG)); |
no test coverage detected