| 1364 | } |
| 1365 | |
| 1366 | IProcessor::Status WindowTransform::prepare() |
| 1367 | { |
| 1368 | if (output.isFinished() || isCancelled()) |
| 1369 | { |
| 1370 | // The consumer asked us not to continue (or we decided it ourselves), |
| 1371 | // so we abort. Not sure what the difference between the two conditions |
| 1372 | // is, but it seemed that output.isFinished() is not enough to cancel on |
| 1373 | // Ctrl+C. Test manually if you change it. |
| 1374 | input.close(); |
| 1375 | return Status::Finished; |
| 1376 | } |
| 1377 | |
| 1378 | if (output_data.exception) |
| 1379 | { |
| 1380 | // An exception occurred during processing. |
| 1381 | output.pushData(std::move(output_data)); |
| 1382 | output.finish(); |
| 1383 | input.close(); |
| 1384 | return Status::Finished; |
| 1385 | } |
| 1386 | |
| 1387 | chassert(first_not_ready_row.block >= first_block_number); |
| 1388 | // The first_not_ready_row might be past-the-end if we have already |
| 1389 | // calculated the window functions for all input rows. That's why the |
| 1390 | // equality is also valid here. |
| 1391 | chassert(first_not_ready_row.block <= first_block_number + blocks.size()); |
| 1392 | chassert(next_output_block_number >= first_block_number); |
| 1393 | |
| 1394 | // Output the ready data prepared by work(). |
| 1395 | // We inspect the calculation state and create the output chunk right here, |
| 1396 | // because this is pretty lightweight. |
| 1397 | if (next_output_block_number < first_not_ready_row.block) |
| 1398 | { |
| 1399 | if (output.canPush()) |
| 1400 | { |
| 1401 | // Output the ready block. |
| 1402 | const auto i = next_output_block_number - first_block_number; |
| 1403 | auto & block = blocks[i]; |
| 1404 | auto columns = block.original_input_columns; |
| 1405 | for (auto & res : block.output_columns) |
| 1406 | { |
| 1407 | columns.push_back(ColumnPtr(std::move(res))); |
| 1408 | } |
| 1409 | output_data.chunk.setColumns(columns, block.rows); |
| 1410 | |
| 1411 | ++next_output_block_number; |
| 1412 | |
| 1413 | output.pushData(std::move(output_data)); |
| 1414 | } |
| 1415 | |
| 1416 | // We don't need input.setNotNeeded() here, because we already pull with |
| 1417 | // the set_not_needed flag. |
| 1418 | return Status::PortFull; |
| 1419 | } |
| 1420 | |
| 1421 | if (input_is_finished) |
| 1422 | { |
| 1423 | // The input data ended at the previous prepare() + work() cycle, |
nothing calls this directly
no test coverage detected