UAF ART-layer features ('uaf art view')¶
Register a UAF (Unbounded Array Framework) feature whose value lives in a
secondary ART (Analytical Result Table) layer as a governed, run()-recomputable
tdfs4ds feature — ARIMA fit-metrics (R_SQUARE/MAPE/AIC in ARTFITMETADATA),
residual-adequacy tests over ARTFITRESIDUALS (Ljung-Box / Durbin-Watson /
Breusch-Godfrey), TD_PACF, and similar.
Why a dedicated process type¶
A UAF operator whose entire result is in its inline output — TD_ACF,
TD_DICKEY_FULLER — can be served by wrapping the inline EXECUTE FUNCTION inside a
REPLACE VIEW and registering it as an ordinary 'denormalized view'. But a feature
whose value lives in a secondary layer needs two statements:
- materialise the operator's ART, then
TD_EXTRACT_RESULTSover a namedLAYERof that ART.
tdfs4ds ingestion is a single CREATE VOLATILE TABLE AS (SELECT * FROM <view>), with
nowhere to run the first statement — and every attempt to fold both into one object is
rejected by Vantage (nested EXECUTE FUNCTION → 3706, INTO ART in a view → 3707,
multi-statement view/macro → 3576).
The 'uaf art view' process type (v0.3.1.143) closes this gap. It stores the
ART-materialising statements as art_sql and runs them per FilterManager
partition, in the same session, immediately before the ingestion CTAS — so the
session-scoped volatile ART is visible to the CTAS reading the feature view.
The model — one feature view + art_sql + art_layers¶
A 'uaf art view' process stores three things:
| Piece | What |
|---|---|
art_sql |
A list of EXECUTE FUNCTION ... INTO VOLATILE ART(<name>) statements. Session-scoped: no PERM, auto-cleaned. Stored in the process METADATA JSON column — no DDL migration. |
art_layers |
The declared LAYER(...) name(s) the feature view reads (e.g. ['ARTFITMETADATA']). Used for documentation and lineage. |
| the feature view | The ordinary feature view, reading each layer via TD_EXTRACT_RESULTS(ART_SPEC(TABLE_NAME(<art>), LAYER(<layer>))). |
Order matters in art_sql
Statements execute in list order, and a later statement may read an ART an
earlier one created (chained operators — e.g. a residual test over the
ARTFITRESIDUALS layer of an ARIMA fit). A JSON array preserves that order; never
sort or reorder art_sql.
Full example — ARIMA fit-metrics (R_SQUARE + MAPE)¶
import teradataml as tdml
import tdfs4ds
from tdfs4ds import upload_features
from tdfs4ds.utils.filter_management import FilterManager
DB = 'MY_FS'; SRC = 'MY_SRC'
tdfs4ds.SCHEMA = DB
tdfs4ds.DATA_DOMAIN = 'FORECASTABILITY'
# 1. FilterManager over the series id (one model per series/partition)
fm = FilterManager(table_name='fm_series', schema_name=DB)
fm.load_filter(tdml.DataFrame.from_query(f"SELECT DISTINCT item_id FROM {SRC}.sales"))
# 2. series-input view — the store filter lives here as a scalar subquery
# (partition-aware, no templating)
tdml.execute_sql(f"""
REPLACE VIEW {DB}.vw_series_in AS
LOCKING ROW FOR ACCESS
SELECT item_id,
ROW_NUMBER() OVER (PARTITION BY item_id ORDER BY cal_date) AS seq_no,
sales_qty
FROM {SRC}.sales
WHERE item_id = (SELECT item_id FROM {fm.schema_name}.{fm.view_name})
""")
# 3. art_sql — materialise the ARIMA ART with FIT_METRICS(1) (generates ARTFITMETADATA)
art_sql = [f"""
EXECUTE FUNCTION INTO VOLATILE ART(arima_fit)
TD_ARIMAESTIMATE(
SERIES_SPEC(TABLE_NAME({DB}.vw_series_in), ROW_AXIS(SEQUENCE(seq_no)),
SERIES_ID(item_id), PAYLOAD(FIELDS(sales_qty), CONTENT(REAL))),
FUNC_PARAMS(NONSEASONAL(MODEL_ORDER(1,0,0)), CONSTANT(1), ALGORITHM(MLE),
FIT_PERCENTAGE(100), FIT_METRICS(1)))
"""]
# 4. materialise the ART ONCE, then create the feature view (see lifecycle note below)
fm.update(1)
tdml.execute_sql(art_sql[0])
tdml.execute_sql(f"""
REPLACE VIEW {DB}.vw_feat_arima_fit AS
LOCKING ROW FOR ACCESS
SELECT item_id,
CAST(R_SQUARE AS FLOAT) AS r_square,
CAST(MAPE AS FLOAT) AS mape
FROM ( EXECUTE FUNCTION TD_EXTRACT_RESULTS(
ART_SPEC(TABLE_NAME(arima_fit), LAYER(ARTFITMETADATA))) ) x
""")
# 5. register + ingest — art_sql runs per partition, before the CTAS
upload_features(
tdml.DataFrame(tdml.in_schema(DB, 'vw_feat_arima_fit')),
entity_id = ['item_id'],
feature_names = ['r_square', 'mape'],
art_sql = art_sql,
art_layers = ['ARTFITMETADATA'],
filtermanager = fm, # tdfs4ds drives its own per-partition loop
metadata = {'project': 'forecastability'},
# optimize_query is force-disabled for a uaf art view; document=True is fine.
)
Verified grammar (Vantage 20)¶
TD_EXTRACT_RESULTSis invoked viaEXECUTE FUNCTIONinside a derived table —FROM ( EXECUTE FUNCTION TD_EXTRACT_RESULTS(ART_SPEC(TABLE_NAME(<art>), LAYER(<layer>))) ) x. A plainFROM TD_EXTRACT_RESULTS(...)is a syntax error (3707).TD_ARIMAESTIMATEusesFUNC_PARAMS(NONSEASONAL(MODEL_ORDER(p,d,q)), CONSTANT(1), ALGORITHM(MLE), FIT_PERCENTAGE(100), FIT_METRICS(1)).FIT_METRICS(1)generates theARTFITMETADATAlayer;RESIDUALS(1)generatesARTFITRESIDUALS.- The
ARTFITMETADATAlayer projects named columns (item_id,ROW_I,NUM_SAMPLES,R_SQUARE,R_ADJ_SQUARE,MAE,MSE,MAPE, …), one row per series — not aMETRIC/VALUEkey-value shape. Confirm the exact columns against your Vantage build.
Creation-time lifecycle constraint
A view referencing a volatile ART cannot be REPLACE VIEW-created unless that ART
already exists in the session (Error 3807). So materialise the ART once
(EXECUTE FUNCTION ... INTO VOLATILE ART) before creating the feature view (step 4
above). The permanent view then survives across sessions, but reading it always
needs the ART present — which run() guarantees by re-materialising the ART per
partition before each ingestion.
What run() does for this type¶
Per FilterManager partition: filtermanager.update() → DROP TABLE <art> then execute
each art_sql statement (materialise the volatile ART) → ingest from the feature view
(which reads the ART layer) → close follow-up. run(process_id, force_compute=True)
re-materialises and re-ingests idempotently.
AI features, lineage, gates¶
optimize_queryis force-disabled —art_sqlis an opaque UAF invocation and the view EXPLAIN needs the ART materialised first.- Documentation skips the view-EXPLAIN and feeds the
art_sqloperator +art_layersinto the column-documentation context (grounding the layer columns in the real computation).get_process_infosurfacesART_SQL/ART_LAYERS. - Lineage traces through the ephemeral ART — the dangling
feature_view → <volatile ART>edge is rewritten tofeature_view → <operator/layer node> → series_input_source(parsed fromart_sql).
Related¶
upload_features— theart_sql/art_layerskwargs.- FilterManager — per-partition segmentation.
- Persisted lineage graph — where the traced edges land.