The generated pipeline
Every indicator app carries a pipeline that Ovidens generates from the app's own configuration. You do not build it and you cannot edit it - it is rebuilt whenever you change the app's structure - but you can read all of it, and that is the point. Open the editor and choose the Pipeline tab (or press P).
What you are looking at
The pipeline has three kinds of node.
- Relations are tables rather than statements. Each one carries a part of the app's own configuration as rows: its indicators and their cadence, the dimensions they are collected by, every member of every dimension, its rules, and the values collected against it.
- Your datapoints are one node each - a step named after the datapoint, carrying just the cells collected for it.
- Engine steps are single SQL statements over the tables before them. A few are the platform's own groundwork - the period calendar, the dimension member tree, the collection members, the stranded-data findings. The rest are one step per thing you configured: one for each formula datapoint's calculation, one for each datapoint's applicability and value rules, one for each consistency check. Each is a single statement you can read in full.
Click a node to read it.
Your datapoints, one step each
Every datapoint you collect - a number, a text, a yes/no or a single choice - has a step of its own. Open it and you see that datapoint's cells and nothing else: the period they were collected for, one column for each dimension you collect that datapoint by, and the value.
Each dimension column is named after your dimension. Underneath, every cell of the app
is stored with an address that says which dimension each of its members belongs to - so
region means region in the stored cell, in this step, and in anything you write against
it. These steps unpack that address into one column per dimension, in the order you
assigned them. It is also what makes the SQL worth reading: a statement written against
region still means region tomorrow.
A datapoint can be collected by as many dimensions as your workspace allows. There is no separate storage limit underneath - the only ceiling is the one your workspace's settings state.
Three columns come from Ovidens rather than from you, and they start with an underscore so
they can never collide with a dimension of your own: _period_type (the cadence),
_period_start (which period) and _value (the collected value itself). A dimension you
call value is perfectly legal and gets a column called value, right beside _value.
Two kinds of datapoint have no step here, each for its own reason. A formula datapoint has no collected cells at all - its figures come out of its own engine step, which carries the calculation you configured. A file datapoint's stored value is a pointer to the uploaded file rather than a value, so it is not something a table of results can carry; the files themselves stay on the datapoint, where you uploaded them.
Reading one of these steps is cheap: it reads your collected cells directly rather than running the whole engine, so opening a datapoint's data is quick even on a large app.
Every node opens the same way a node opens in an analytics app - the same panel, drawn the same way, down to the last control: a Configuration tab, and a Data tab showing that node's rows in the ordinary table. Nothing there is editable - the pipeline is Ovidens's, not yours - but everything the engine reads, and everything each step of it produced, is in front of you. Rows are read a page at a time as you scroll, and you can sort, filter and search them exactly as you would any other table; nothing is left out and nothing is summarised.
What differs is the Configuration tab. A relation names which part of the app's configuration it carries. An engine step shows its statement in full - not a summary and not an excerpt - alongside the list of tables it reads, so you can read what produced the rows on the tab beside it.
The pipeline is Ovidens's, whole. No step can be edited, handed over or taken on, in this editor or anywhere else. If the building blocks cannot express something you need, read the data into an analytic app with an Indicator data node: that app has a real SQL editor with previews and typed output columns, and its statements are yours to write and keep.
This pipeline is not a picture of how your app is computed - it is what computes it. Every number your app shows comes out of these steps: the value in a formula datapoint's cell, the pass or fail of a value rule and a consistency check, whether a conditional datapoint applies for a period. Open a formula datapoint's own step and you are reading the figures the collection grid shows you, at the coordinates it shows them at; open a step above it and you are reading what they were computed from. There is no second, private calculation anywhere behind them.
One object, one statement. A calculation is not interpreted at run time - it is turned into SQL once, when you save it, and that statement is what runs. So the step you can read IS your calculation, and there is no engine between the two that could read it differently.
That is also why a refusal reaches you at Save rather than as a finding you have to go looking for. A reference to a datapoint the app does not hold, a cadence that does not reconcile, a breakdown that cannot be lined up, a calculation that reads itself: each is refused while the statement is being generated, naming what did not fit. Nothing unsound is ever written, so there is no "findings" step to consult - the refusal happened before there was a step at all.
Why Run is greyed out on an engine step
A step's SQL sits in the same editor an analytics app's SQL node uses, with the same Run control underneath it - and on an engine step that control is deliberately switched off, with the reason beside it.
An engine step is not a query against tables that sit somewhere waiting to be read. It runs as one part of the app's own evaluation, over relations that are assembled for the length of that evaluation and then gone, so there is nothing for a stand-alone run to read. What that statement produced is on the Data tab beside it, which is a page of the real result rather than a rehearsal of it.
The statements themselves are ordinary SQL for DuckDB and nothing about them is special to Ovidens: select the text in the editor to take a copy into an editor of your own and read it at your own pace.
If the tab is empty
An app's pipeline is generated from its structure, and an app that existed before the pipeline did does not carry one yet. Saving any change to its structure generates it: add or edit a datapoint, a dimension, a group or a consistency check, and the tab fills. Every app created since carries its pipeline from the moment it exists.
Stranded data
A value is stored together with the structure it was collected against: which indicator, which dimension members, and which collection interval. Change that structure afterwards and the values already collected do not move with it - they are left behind, outside the grid the indicator now asks for, where nothing reads them.
The Pipeline tab reports them, with the indicator and how many rows are affected.
| What it says | What happened | What to do |
|---|---|---|
| Collected at a collection interval the datapoint no longer uses | The indicator's collection interval was changed after these values were entered | Set the interval back to reach them, or clear them |
| Collected against a dimension the datapoint no longer has | A dimension was taken off the indicator, and these rows still name one of its members | Assign the dimension again, or clear them |
| Collected before a dimension was added | A dimension was added after these values were entered, so they name no member for it | Enter the values again against the new dimension, or clear them |
| Collected against a member that is no longer active | A dimension member was deleted or deactivated while values still named it | Make the member active again, or clear them |
| Collected against a member at another level of the hierarchy | The indicator collects the dimension at one level, and these rows name an active member above or below it - usually because the collection level was changed after the values were entered | Collect the indicator at that level again, or clear them |
When there is nothing to report, the tab says so. If the check could not run - the platform was busy, or your workspace has used up its compute allowance for the month - it says that instead, rather than reporting a clean result over data it did not read.
The check is taken each time you open the Pipeline tab, so there is no refresh button to press. Nothing that could change the answer is reachable while the tab is open: values are entered on the data-entry grid and the structure is edited on the other tabs, so coming back here is what takes a fresh reading.
Clearing one of these values. Where the value still has a cell on the data-entry grid - most often after a collection level or a member changed - empty the cell and save, exactly as you would correct any other value. That works even though entering a NEW value at the same place is refused: clearing is always allowed, because it is how you act on what this list tells you. The cell then reads as empty rather than disappearing from the grid.
What needs compute, and what happens without it
Because the pipeline is what computes the app, reading it and changing it both use your workspace's compute allowance, and a workspace that has used the allowance up (or a platform-wide pause) will say so rather than answering with something it did not compute.
- Reading a step's Data tab runs the engine for that step. Reading a relation's rows does not - a relation is your own configuration, so its columns and rows are free.
- Changing the structure does not. The pipeline is rebuilt from your configuration alone, and a calculation is checked by generating the statement for it - both of which happen in Ovidens itself. So a datapoint, a dimension, a group or a check can be saved while compute is unavailable, including one carrying a calculation. What you cannot do meanwhile is read the results.
- Entering a value checks the app's rules against what you typed, so that needs compute as well. This is deliberate: accepting a value the platform could not check is worse than telling you to come back.
The refusal always names itself and what to do about it; nothing is saved or shown on a half-answer.
Why a cadence change can be refused
Because a value carries the interval it was collected at, changing an indicator's collection interval would strand every value already collected. When you edit the indicator, Ovidens refuses that change while such values exist and tells you how many rows are involved.
The way forward is to clear those values first and then change the interval. There is deliberately no "change it anyway" option: it would be a button whose only effect is to lose data quietly.
Restoring an earlier version is not held to that check. A restore puts the whole app back the way it was, collection intervals included, so it can strand values that an edit would have been refused for. It is deliberately not blocked - a rollback you are not allowed to perform is its own kind of trap - so what it strands is reported rather than prevented: check the Stranded data list above after restoring a version.
Collection rounds
Collect an indicator app's figures from named people - name the units you report from, say who is responsible for each one, define what a round asks for, and approve or send back each answer.
Build with Vera
Create, change and understand indicators, dimensions and calculations in a continuing conversation with Vera.