| 229 | } |
| 230 | |
| 231 | bool DictionaryColumn::canOffsetCommitInPlace(const SegmentState& offsetState, |
| 232 | const SegmentState& dataState, uint64_t numNewStrings, uint64_t totalStringLengthToAdd) const { |
| 233 | auto totalStringOffsetsAfterUpdate = dataState.metadata.numValues + totalStringLengthToAdd; |
| 234 | auto offsetCapacity = |
| 235 | offsetState.metadata.compMeta.numValues(LBUG_PAGE_SIZE, offsetColumn->getDataType()) * |
| 236 | offsetState.metadata.getNumPages(); |
| 237 | auto numStringsAfterUpdate = offsetState.metadata.numValues + numNewStrings; |
| 238 | if (numStringsAfterUpdate > offsetCapacity) { |
| 239 | // Offsets cannot be updated in place |
| 240 | return false; |
| 241 | } |
| 242 | // Indices are limited to 32 bits but in theory could be larger than that since the offset |
| 243 | // column can grow beyond the node group size. |
| 244 | // |
| 245 | // E.g. one big string is written first, followed by NODE_GROUP_SIZE-1 small strings, |
| 246 | // which are all updated in-place many times (which may fit if the first string is large |
| 247 | // enough that 2^n minus the first string's size is large enough to fit the other strings, |
| 248 | // for some n. |
| 249 | // 32 bits should give plenty of space for updates. |
| 250 | if (numStringsAfterUpdate > std::numeric_limits<string_index_t>::max()) [[unlikely]] { |
| 251 | return false; |
| 252 | } |
| 253 | if (offsetState.metadata.compMeta.canAlwaysUpdateInPlace()) { |
| 254 | return true; |
| 255 | } |
| 256 | InPlaceUpdateLocalState localUpdateState{}; |
| 257 | if (!offsetState.metadata.compMeta.canUpdateInPlace( |
| 258 | (const uint8_t*)&totalStringOffsetsAfterUpdate, 0 /*offset*/, 1 /*numValues*/, |
| 259 | offsetColumn->getDataType().getPhysicalType(), localUpdateState)) { |
| 260 | return false; |
| 261 | } |
| 262 | return true; |
| 263 | } |
| 264 | |
| 265 | } // namespace storage |
| 266 | } // namespace lbug |
nothing calls this directly
no test coverage detected