GitHub user tanishqgandhi1908 added a comment to the discussion: Design: 
interactive grid for the operator result pane

Please find diagrams and architecture for the proposed idea - 

## **Default View of Proposed result pane**

<img width="1428" height="803" alt="Image" 
src="https://github.com/user-attachments/assets/c2f340fe-cf2e-4103-95b8-b70228867771";
 />

Default view. The new ag-grid-based result pane showing the full 150-row Iris 
dataset across 25 pages. Each column header preserves the existing Min / Max / 
Non-Null statistics inline via a custom header component (same data as today's 
stats row, restructured for the new grid). The ↕ icon on each header indicates 
the column is sortable; it brightens to a blue caret when active. Pagination at 
the bottom uses auto-fit page size — the page size follows the panel's height.

## **Full-data row search**

<img width="2000" height="723" alt="Image" 
src="https://github.com/user-attachments/assets/2f2b42c3-1255-41b4-800c-f9a75b51fab9";
 />
Row search across all columns. Typing into the "Search rows…" box runs a 
debounced substring match against every string-coercible column on the backend. 
Here 1.4 matches 20 rows out of 150 (3 pages of results) and the header stats 
stay anchored to the full dataset for context. The query is pushed down to 
Iceberg as a multi-column residual filter — full-dataset, not just rows 
currently in browser memory.



## **Per-column filter for a string column**

<img width="2000" height="619" alt="Image" 
src="https://github.com/user-attachments/assets/eae71121-76d8-48cd-9a65-6b99d3816b24";
 />
Per-column filter (string column). Each column header has its own filter 
funnel. Because the underlying schema marks Species as a string, ag-grid picks 
the text-filter UI: Contains / Starts with / Ends with / Equals, with AND/OR 
composition. Here Species contains "Iris-versi" narrows 150 rows down to 50. 
The filter predicate is sent to the backend as part of the extended 
ResultPaginationRequest, evaluated by Iceberg, and returned as a paginated 
subset.


## **Per-column filter for a numeric column**

<img width="500" height="616" alt="Image" 
src="https://github.com/user-attachments/assets/7e250051-50ee-44ab-a803-df24d991e74d";
 />

Per-column filter (numeric column). Same affordance, schema-aware behavior. 
Because PetalWidthCm is a numeric column, the filter UI offers numeric 
operators — Equals / Does not equal / Greater than / Less than / Between / 
Blank / Not blank — instead of string ones. This routes through 
IcebergPredicateBuilder with type-aware parsing so values are never silently 
mis-coerced (e.g. "30" is read as the integer 30, not the string).


## Architecture

```mermaid
flowchart TB
    subgraph Browser["Browser"]
        UI["ag-grid<br/>column filter · sort · row-search UI"]
        SVC["OperatorPaginationResultService<br/>per-page LRU cache"]
        UI -->|"getRows(startRow, endRow,<br/>filterModel, sortModel)"| SVC
    end

    subgraph Backend["Texera Backend (JVM)"]
        ERS["ExecutionResultService<br/>routes by query presence"]
        VD["VirtualDocument<br/>getRangeWithQuery · countWithQuery"]
        ID["IcebergDocument<br/>pushdown + residual + sort"]
        PB["IcebergPredicateBuilder<br/>ColumnFilter → Iceberg Expression"]
        ERS --> VD
        VD --> ID
        ID --> PB
    end

    DISK[("Iceberg / Parquet on disk")]

    SVC -. "WebSocket: ResultPaginationRequest<br/>filters? · sorts? · 
rowSearch?" .-> ERS
    ID -->|"newScan().filter(expr).select(cols)<br/>file pruning + reader-level 
predicate pushdown"| DISK
    DISK -. "matching rows only" .-> ID
```

**Read top-to-bottom.** ag-grid's `IDatasource` translates user interactions 
into a `ResultPaginationRequest` carrying the optional `filters` / `sorts` / 
`rowSearch` fields. `ExecutionResultService` routes between the no-query fast 
path (existing `getRange`) and the new `getRangeWithQuery`. `IcebergDocument` 
uses `IcebergPredicateBuilder` to turn wire-format filters into Iceberg 
`Expressions`, lets Iceberg prune entire files via min/max stats and push 
predicates into the Parquet reader, then evaluates residual ops (`contains` / 
`endsWith` / `rowSearch`) and sort in JVM memory before slicing the requested 
page.

GitHub link: 
https://github.com/apache/texera/discussions/5395#discussioncomment-17282105

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]

Reply via email to