Oninit® UDR — TimeSeries API: Read API
The oni_ts_read() call, its range semantics,
and the JSON document it returns — the part of the TimeSeries API
that's actually built and live-verified. Building and registering it is
on the Install guide; loading a YAML
mapping first is on the Configuration
guide.
The call
One invocation resolves one table row, scans its TimeSeries once over a
half-open [start, end) range, and returns one JSON document.
There is no cursor and no server-side state that outlives the call:
oni_ts_read(
p_key INTEGER,
p_start DATETIME YEAR TO FRACTION(5),
p_end DATETIME YEAR TO FRACTION(5),
p_metrics LVARCHAR
) RETURNING LVARCHAR; -- one JSON document
SELECT oni_ts_read(427, '2026-09-01 00:00:00.00000',
'2026-10-01 00:00:00.00000',
'cpu.usage,cpu.system,cpu.wait')
FROM sysmaster:sysdual;
p_metrics is a comma-separated list of logical metric
names, trimmed of surrounding whitespace, no empty or duplicate entries,
every one resolving to the same TimeSeries column. Caller order is
preserved in the response; physical extraction order may differ for
efficiency. start is inclusive, end is
exclusive — start == end is legal and returns an empty
rows array, not an error.
Which table?
Notice there's no table name anywhere in the call above — it's
resolved from p_metrics, not passed explicitly. Every logical
metric name is mapped, in the YAML
configuration, to a named source: a specific database, table,
TimeSeries column, and primary-key column, all in one place. The first
metric in p_metrics establishes which source the whole
request uses; every other metric listed must belong to that same source,
or the call fails with a hard error rather than silently reading across
two different tables. p_key is then looked up as that
source's primary-key column, in that source's table — so
cpu.usage,cpu.system,cpu.wait above only works as one request
because all three are configured under the same source; a metric from a
different table needs its own, separate call.
The response
An envelope describing the request, followed by one JSON object per TimeSeries element:
{
"oni_ts_version": 1,
"key": 427,
"start": "2026-09-01 00:00:00.00000",
"end": "2026-10-01 00:00:00.00000",
"tz": "UTC",
"metrics": ["cpu.usage", "cpu.system", "cpu.wait"],
"count": 8640,
"rows": [
{
"ts": "2026-09-01 00:00:00.00000",
"cpu.usage": 31.2,
"cpu.system": 7.8,
"cpu.wait": 0.4
},
{
"ts": "2026-09-01 00:05:00.00000",
"cpu.usage": 28.9,
"cpu.system": 7.1,
"cpu.wait": null
}
]
}
metrics in the envelope is the authoritative record of key
order — row objects generate keys in that same order, but callers
should not depend on JSON object key order surviving a round trip (RFC
8259 doesn't guarantee it). SQL NULL maps to JSON
null. Physical column names (col0, ...) are
never exposed; only the logical names from the
YAML mapping ever reach the response.
Verified against a real instance
The native TimeSeries scan and the JSON assembly above have been built
and exercised against a live, running IBM Informix Dynamic Server
instance, end to end. Observability is not an afterthought:
oni_ts_read()'s own request lifecycle is instrumented with
ONI_DEBUG() call sites under the shared
ONI UDR Debug subsystem — see the
debug usage guide for a real, live example
of that instrumentation.