---
name: compute_stage
kind: function
lang: cpp
domain: core
version: "1.1.0"
purity: pure
signature: "data_table::StageOutput data_table::compute_stage(const char* const* in_cells, int in_rows, int in_cols, const std::vector<std::string>& in_headers, const std::vector<ColumnType>& in_types, const Stage& stage)"
description: "Executes one TQL Stage over a cell matrix: apply_filters -> (group+agg | passthrough) -> sort. Returns a StageOutput owning its cell backing. No ImGui, no I/O."
tags: [tables, pipeline, tql, filter, aggregation, sort, pure, cpp-tables]
uses_functions: [tql_helpers_cpp_core]
uses_types: [data_table_types_cpp_core]
returns: []
returns_optional: false
error_type: ""
imports:
  - "core/tql_helpers.h"
tested: true
tests:
  - "compute_stage passthrough returns all rows"
  - "compute_stage filter eq keeps matching rows"
  - "compute_stage group sum aggregates correctly"
  - "compute_stage sort desc reorders rows"
  - "compute_stage filter then group then sort asc"
  - "apply_filters returns correct row indices"
  - "aggregation_alias produces expected names"
  - "compute_stage empty table empty stage"
test_file_path: "cpp/tests/test_compute_stage.cpp"
file_path: "cpp/functions/core/compute_stage.cpp"
params:
  - name: in_cells
    desc: "Row-major cell array (in_rows * in_cols pointers). May be null when in_rows == 0."
  - name: in_rows
    desc: "Number of input rows. 0 returns empty StageOutput."
  - name: in_cols
    desc: "Number of columns per row. Must match in_headers.size()."
  - name: in_headers
    desc: "Column names for in_cells. Used for breakout/sort/agg column lookup by name."
  - name: in_types
    desc: "Declared ColumnType per column. Used for aggregation output type and date truncation."
  - name: stage
    desc: "Stage descriptor: filters (row predicates), breakouts+aggregations (group-by), sorts (output order)."
output: "StageOutput with rows/cols/headers/types and cells pointer list into cell_backing. cell_backing owns all newly allocated strings (aggregation results, truncated dates). cells pointing to in_cells are not copied."
---

## Ejemplo

```cpp
#include "core/compute_stage.h"
using namespace data_table;

// 3 rows x 2 cols
const char* raw[] = {"eng","90000", "mktg","70000", "eng","95000"};
std::vector<std::string> hdrs = {"dept","salary"};
std::vector<ColumnType>  types = {ColumnType::String, ColumnType::Int};

// Stage: filter dept=eng, group by dept, sum salary, sort desc
Stage s;
Filter f; f.col=0; f.op=Op::Eq; f.value="eng"; s.filters.push_back(f);
s.breakouts = {"dept"};
Aggregation agg; agg.fn=AggFn::Sum; agg.col="salary"; s.aggregations.push_back(agg);
SortClause sc; sc.col="sum_salary"; sc.desc=true; s.sorts.push_back(sc);

StageOutput out = compute_stage(raw, 3, 2, hdrs, types, s);
// out.rows == 1, out.headers == {"dept","sum_salary"}
// out.cells[0] == "eng", out.cells[1] == "185000"
```

## Cuando usarla

- Cuando necesites aplicar filtros, agrupaciones y ordenacion sobre datos tabulares raw (cell array) en un solo paso.
- Como bloque de construccion de `compute_pipeline` para procesar stage por stage.
- En tests headless de logica TQL sin renderizar nada.

## Gotchas

- `cell_backing` crece con `emplace_back`; la reserva previa evita reallocs durante grupos. No guardes punteros a `cell_backing` antes de llamar a la funcion — usa `out.cells` del resultado.
- Las celdas de passthrough apuntan directamente a `in_cells` (sin copiar). El caller debe mantener `in_cells` vivo mientras use `StageOutput`.
- Breakouts con sufijo `:granularity` (`:year`, `:month`, `:week`, `:day`, `:hour`) truncan fechas ISO. Breakouts sin sufijo usan el valor raw.
- `apply_filters` y `aggregation_alias` son funciones publicas del mismo header — usables independientemente.
