| 41 | namespace { |
| 42 | |
| 43 | BufferPtr sortElements( |
| 44 | const SelectivityVector& rows, |
| 45 | const ArrayVector& inputArray, |
| 46 | const BaseVector& inputElements, |
| 47 | bool ascending, |
| 48 | bool nullsFirst, |
| 49 | exec::EvalCtx& context, |
| 50 | bool throwOnNestedNull) { |
| 51 | const SelectivityVector inputElementRows = |
| 52 | toElementRows(inputElements.size(), rows, &inputArray); |
| 53 | exec::LocalDecodedVector decodedElements( |
| 54 | context, inputElements, inputElementRows); |
| 55 | const auto* baseElementsVector = decodedElements->base(); |
| 56 | |
| 57 | // Allocate new vectors for indices. |
| 58 | BufferPtr indices = allocateIndices(inputElements.size(), context.pool()); |
| 59 | vector_size_t* rawIndices = indices->asMutable<vector_size_t>(); |
| 60 | |
| 61 | CompareFlags flags{.nullsFirst = nullsFirst, .ascending = ascending}; |
| 62 | if (throwOnNestedNull) { |
| 63 | flags.nullHandlingMode = |
| 64 | CompareFlags::NullHandlingMode::kNullAsIndeterminate; |
| 65 | } |
| 66 | |
| 67 | auto decodedIndices = decodedElements->indices(); |
| 68 | context.applyToSelectedNoThrow(rows, [&](vector_size_t row) { |
| 69 | const auto size = inputArray.sizeAt(row); |
| 70 | const auto offset = inputArray.offsetAt(row); |
| 71 | |
| 72 | for (auto i = offset; i < offset + size; ++i) { |
| 73 | rawIndices[i] = i; |
| 74 | } |
| 75 | |
| 76 | std::sort( |
| 77 | rawIndices + offset, |
| 78 | rawIndices + offset + size, |
| 79 | [&](vector_size_t& a, vector_size_t& b) { |
| 80 | if (a == b) { |
| 81 | return false; |
| 82 | } |
| 83 | bool nullAtA = decodedElements->isNullAt(a); |
| 84 | bool nullAtB = decodedElements->isNullAt(b); |
| 85 | |
| 86 | if (nullAtA && nullAtB) { |
| 87 | return false; |
| 88 | } |
| 89 | if (nullAtA) { |
| 90 | return nullsFirst; |
| 91 | } |
| 92 | if (nullAtB) { |
| 93 | return !nullsFirst; |
| 94 | } |
| 95 | |
| 96 | std::optional<int32_t> result = baseElementsVector->compare( |
| 97 | baseElementsVector, decodedIndices[a], decodedIndices[b], flags); |
| 98 | |
| 99 | if (!result.has_value()) { |
| 100 | BOLT_USER_FAIL("Ordering nulls is not supported"); |
no test coverage detected