| 153 | |
| 154 | template<typename TYPE> |
| 155 | void RadixSort::findStringTies(TieRange& keyBlockTie, uint8_t* keyBlockPtr, |
| 156 | std::queue<TieRange>& ties, StrKeyColInfo& keyColInfo) { |
| 157 | auto iTuplePtr = keyBlockPtr; |
| 158 | for (auto i = keyBlockTie.startingTupleIdx; i < keyBlockTie.endingTupleIdx; i++) { |
| 159 | bool isIValNull = OrderByKeyEncoder::isNullVal( |
| 160 | iTuplePtr + keyColInfo.colOffsetInEncodedKeyBlock, keyColInfo.isAscOrder); |
| 161 | // This variable will only be used when the current column is a string column. Otherwise, |
| 162 | // we just set this variable to false. |
| 163 | bool isIStringLong = OrderByKeyEncoder::isLongStr( |
| 164 | iTuplePtr + keyColInfo.colOffsetInEncodedKeyBlock, keyColInfo.isAscOrder); |
| 165 | TYPE iValue = |
| 166 | isIValNull ? |
| 167 | TYPE() : |
| 168 | factorizedTable.getData<TYPE>( |
| 169 | OrderByKeyEncoder::getEncodedFTBlockIdx(iTuplePtr + numBytesToRadixSort), |
| 170 | OrderByKeyEncoder::getEncodedFTBlockOffset(iTuplePtr + numBytesToRadixSort), |
| 171 | keyColInfo.colOffsetInFT); |
| 172 | auto j = i + 1; |
| 173 | auto jTuplePtr = iTuplePtr + numBytesPerTuple; |
| 174 | for (; j <= keyBlockTie.endingTupleIdx; j++) { |
| 175 | auto jTupleInfoPtr = jTuplePtr + numBytesToRadixSort; |
| 176 | bool isJValNull = OrderByKeyEncoder::isNullVal( |
| 177 | jTuplePtr + keyColInfo.colOffsetInEncodedKeyBlock, keyColInfo.isAscOrder); |
| 178 | if (isIValNull && isJValNull) { |
| 179 | // If the left value and the right value are nulls, we can just continue on |
| 180 | // the next tuple. |
| 181 | jTupleInfoPtr += numBytesPerTuple; |
| 182 | continue; |
| 183 | } else if (isIValNull || isJValNull) { |
| 184 | // If only one value is null, we can just conclude that those two values are |
| 185 | // not equal. |
| 186 | break; |
| 187 | } |
| 188 | if constexpr (std::is_same<TYPE, string_t>::value) { |
| 189 | // We do an optimization here to minimize the number of times that we fetch |
| 190 | // tuples from factorizedTable. If both left and right string are short, they |
| 191 | // must equal to each other (since they have the same prefix). If one string is |
| 192 | // short and the other string is long, then they must not equal to each other. |
| 193 | bool isJStringLong = OrderByKeyEncoder::isLongStr( |
| 194 | jTuplePtr + keyColInfo.colOffsetInEncodedKeyBlock, keyColInfo.isAscOrder); |
| 195 | if (!isIStringLong && !isJStringLong) { |
| 196 | jTupleInfoPtr += numBytesPerTuple; |
| 197 | continue; |
| 198 | } else if (isIStringLong != isJStringLong) { |
| 199 | break; |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | uint8_t result = UINT8_MAX; |
| 204 | function::NotEquals::operation<TYPE, TYPE>(iValue, |
| 205 | factorizedTable.getData<TYPE>( |
| 206 | OrderByKeyEncoder::getEncodedFTBlockIdx(jTupleInfoPtr), |
| 207 | OrderByKeyEncoder::getEncodedFTBlockOffset(jTupleInfoPtr), |
| 208 | keyColInfo.colOffsetInFT), |
| 209 | result, nullptr /* leftVector */, nullptr /* rightVector */); |
| 210 | if (result) { |
| 211 | break; |
| 212 | } |