| 37 | namespace { |
| 38 | |
| 39 | uint64_t* rowsWithError( |
| 40 | const SelectivityVector& rows, |
| 41 | const SelectivityVector& activeRows, |
| 42 | EvalCtx& context, |
| 43 | ErrorVectorPtr& previousErrors, |
| 44 | LocalSelectivityVector& errorRowsHolder) { |
| 45 | auto errors = context.errors(); |
| 46 | if (!errors) { |
| 47 | // No new errors. Put the old errors back. |
| 48 | context.swapErrors(previousErrors); |
| 49 | return nullptr; |
| 50 | } |
| 51 | uint64_t* errorMask = nullptr; |
| 52 | SelectivityVector* errorRows = errorRowsHolder.get(); |
| 53 | if (!errorRows) { |
| 54 | errorRows = errorRowsHolder.get(rows.end(), false); |
| 55 | } |
| 56 | errorMask = errorRows->asMutableRange().bits(); |
| 57 | std::fill(errorMask, errorMask + bits::nwords(rows.end()), 0); |
| 58 | // A 1 in activeRows with a not null in errors null flags makes a 1 |
| 59 | // in errorMask. |
| 60 | bits::andBits( |
| 61 | errorMask, |
| 62 | activeRows.asRange().bits(), |
| 63 | errors->rawNulls(), |
| 64 | rows.begin(), |
| 65 | std::min(errors->size(), rows.end())); |
| 66 | if (previousErrors) { |
| 67 | // Add the new errors to the previous ones and free the new errors. |
| 68 | bits::forEachSetBit( |
| 69 | errors->rawNulls(), rows.begin(), errors->size(), [&](int32_t row) { |
| 70 | context.addError( |
| 71 | row, |
| 72 | *std::static_pointer_cast<std::exception_ptr>( |
| 73 | errors->valueAt(row)), |
| 74 | previousErrors); |
| 75 | }); |
| 76 | context.swapErrors(previousErrors); |
| 77 | previousErrors = nullptr; |
| 78 | } |
| 79 | return errorMask; |
| 80 | } |
| 81 | |
| 82 | void finalizeErrors( |
| 83 | const SelectivityVector& rows, |
no test coverage detected