Skip to content

tdfs4ds.genai.exposed_views

tdfs4ds.genai.exposed_views

Views that expose a table (0.3.4.6).

Users are commonly given a view over a table they may not read, for a lock (LOCKING ROW FOR ACCESS) and often a row restriction (a WHERE on the user, a join to an entitlement table). The view's columns mean what the table's columns mean, so the table's documentation stands for the view.

A view exposes a table when every output column is a column of that one table, unchanged or renamed. Clauses that only remove rows (WHERE, QUALIFY, DISTINCT, TOP, SAMPLE, joins whose relations give no output column) make it filtered, never refused. Aggregation, GROUP BY and set operations are refused: the columns no longer mean the same thing.

The pair is stored as the reserved business-dictionary section EXPOSES of the view (JSON: table, column mapping, filters), and the table's documentation is copied onto the view as PROPAGATED rows: description, sections, columns through the mapping, and for a historian table its layout and tags. A part a person wrote on the view (IMPORTED / MANUAL) is kept. Every reader of the dictionary (agent, vector index, plots, coverage, export, documentation context) then sees the view documented, with no change on their side.

The mapping is read from the view's SHOW VIEW text, so no right on the table is needed. Its column list (to tell a historian tag from a column the view leaves out) comes from DBC or SHOW TABLE when allowed, else from the layout.

EXPOSES_SECTION module-attribute

EXPOSES_SECTION = 'EXPOSES'

_IDENT module-attribute

_IDENT = '(?:"(?:[^"]|"")+"|[A-Za-z_$#@][\\w$#@]*)'

_QNAME module-attribute

_QNAME = f'{_IDENT}(?:\s*\.\s*{_IDENT}){0,2}'

_ROW_CLAUSES module-attribute

_ROW_CLAUSES = ('WHERE', 'QUALIFY', 'SAMPLE')

_REFUSED module-attribute

_REFUSED = ('GROUP', 'HAVING', 'UNION', 'INTERSECT', 'EXCEPT', 'MINUS', 'EXPAND')

_JOIN_WORDS module-attribute

_JOIN_WORDS = ('INNER', 'LEFT', 'RIGHT', 'FULL', 'OUTER', 'CROSS', 'JOIN')

_LOCK_RE module-attribute

_LOCK_RE = compile(f'(?is)^LOCK(?:ING)?\s+(?:(?:ROW|TABLE|DATABASE|VIEW|OBJECT)\s+)?(?:(?!FOR\b|ACCESS\b){_QNAME}\s+)?(?:FOR\s+)?(?:ACCESS|READ|WRITE|EXCLUSIVE|LOAD)(?:\s+MODE)?(?:\s+NOWAIT)?\s+')

_HEADER_RE module-attribute

_HEADER_RE = compile(f'(?is)^(?:REPLACE|CREATE)\s+(?:RECURSIVE\s+)?VIEW\s+(?P<name>{_QNAME})\s*(?P<cols>\((?:[^()]|\([^()]*\))*\))?\s*AS\s+(?P<body>.*)$')

_STAR_RE module-attribute

_STAR_RE = compile(f'(?s)^(?:(?P<q>{_IDENT}(?:\s*\.\s*{_IDENT})?)\s*\.\s*)?\*$')

_COL_RE module-attribute

_COL_RE = compile(f'(?s)^(?:(?P<q>{_IDENT}(?:\s*\.\s*{_IDENT})?)\s*\.\s*)?(?P<c>{_IDENT})(?:\s+(?:AS\s+)?(?P<a>{_IDENT}))?$', IGNORECASE)

_AS_RE module-attribute

_AS_RE = compile(f'(?is)\bAS\s+(?P<a>{_IDENT})\s*$')

_REL_RE module-attribute

_REL_RE = compile(f'(?is)^(?P<name>{_QNAME}|\(.*\))\s*(?:AS\s+)?(?P<alias>{_IDENT})?\s*$')

_KEYWORD_ALIASES module-attribute

_KEYWORD_ALIASES = {'ON', 'WHERE', 'USING', 'SAMPLE', 'QUALIFY'}

logger_safe

logger_safe(level, message, *args, **kwargs)

Wrapper around the global logger that only emits logs when tdfs4ds.DISPLAY_LOGS is True. level is a string like "info", "error", etc.

sql_literal

sql_literal(value)

Escape value for use inside a single-quoted SQL string literal.

For the DBC probes and catalog predicates that compare a name as data (WHERE DatabaseName = '…'). The caller supplies the surrounding quotes.

_unq

_unq(s: str) -> str

_name_parts

_name_parts(text: str) -> List[str]

_strip_comments

_strip_comments(sql: str) -> str

_top_level

_top_level(text: str) -> Tuple[List[Tuple[str, int, int]], List[int]]

Words and commas at parenthesis depth 0, outside quotes.

_split_commas

_split_commas(text: str) -> List[str]

_refusal

_refusal(reason: str) -> dict

_relations

_relations(from_text: str) -> Optional[List[dict]]

The relations of a FROM clause: [{name: [db, obj] | None, alias}].

parse_exposed_view

parse_exposed_view(ddl: str, view_database: Optional[str] = None) -> dict

Whether the view of ddl exposes one table, and how.

Returns {"ok": False, "reason"}, or {"ok": True, "view": [db, name], "table": [db, name], "columns": {view column: table column}, "star", "computed": [view columns not taken from the table], "filtered", "filters": [what restricts the rows], "where"}. An unqualified table resolves to the view's database, as Teradata does.

map_layout

map_layout(layout: dict, info: dict) -> Optional[dict]

The historian layout of the table, in the view's column names (None when the view does not expose the tag, payload and timestamp columns).

plan_copy

plan_copy(view: Tuple[str, str], info: dict, docs: dict, table_columns: Optional[List[str]] = None) -> dict

The rows to write on the view (pure): objects, sections, columns, notes.

render_exposure

render_exposure(info: dict) -> str

summarize_access_stops

summarize_access_stops(stops) -> str

One readable text for lineage stops [(object, message)] (pure).

Objects refused with the same message (object name aside) are listed once, with the message once; the GRANT advice is grouped per database.

filter_tables_in_graph

filter_tables_in_graph(graph_nodes: dict) -> set

{'DB.OBJ'} (upper) of the tables that views of a lineage graph only use to restrict the rows of a table they expose (pure).

exposing_view_of

exposing_view_of(graph_nodes: dict, edges, table_node: str, fetch_ddl=None) -> Optional[Tuple[str, dict]]

A view of a lineage graph that exposes table_node, or None.

The graph keeps a view's text only when built with store_ddl=True; otherwise fetch_ddl(database, view) (e.g. SHOW VIEW) is called for the views directly above the table. Pure when fetch_ddl is None.

_bd

_bd(name: str) -> str

_rows

_rows(sql: str)

_where_obj

_where_obj(db_col, obj_col, db, obj) -> str

read_documentation

read_documentation(db: str, obj: str) -> dict

{"object": {"type", "description"} | None, "sections": {...}, "columns": {...}}.

_is_documented

_is_documented(docs: dict) -> bool

read_exposure

read_exposure(db: str, view: str) -> Optional[dict]

The stored EXPOSES section of a view, or None.

_parse_table_ddl_columns

_parse_table_ddl_columns(ddl: str) -> List[str]

table_columns

table_columns(db: str, table: str) -> Optional[List[str]]

The table's columns from DBC, else from SHOW TABLE; None when neither is allowed.

_view_ddl

_view_ddl(db: str, view: str) -> str

_split_name

_split_name(name: str) -> Tuple[str, str]

attach_exposed_view

attach_exposed_view(view: str, table: Optional[str] = None, *, overwrite_manual: bool = False, refresh_index: bool = True, regenerate_dependents: bool = False, author: Optional[str] = None, dry_run: bool = False) -> dict

Declare that view exposes a table and copy the table's documentation onto it.

The table is read from the view's SHOW VIEW text; pass table to check it. Filtered views (a row restriction, a join to an entitlement table) are accepted. A part a person wrote on the view is kept unless overwrite_manual. Returns the usual documentation report (written, propagated, skipped_manual, stale, index) plus exposure and notes.

detach_exposed_view

detach_exposed_view(view: str, *, dry_run: bool = False) -> dict

End the EXPOSES declaration of view. The copied documentation stays; it is no longer refreshed from the table.

exposed_views

exposed_views(table: Optional[str] = None) -> pd.DataFrame

The declared pairs: VIEW, TABLE, FILTERED, FILTERS (optionally of one table).

refresh_exposed_views

refresh_exposed_views(table: Optional[str] = None, *, refresh_index: bool = True, dry_run: bool = False) -> List[dict]

Copy the documentation again onto every declared view (of table when given).

suggest_exposed_views

suggest_exposed_views(databases=None, views=None) -> pd.DataFrame

Views that expose a table, read-only: VIEW, TABLE, FILTERED, FILTERS, COMPUTED, TABLE_DOCUMENTED, ATTACHED, REASON (REASON says why a view does not qualify).

document_exposed_view

document_exposed_view(db: str, view: str, ddl: Optional[str] = None, refresh: bool = True) -> Optional[bool]

The documentation pipeline's hook: True when the view was documented from the table it exposes, None to let the LLM document it (or leave it as it is).

A view already declared is copied again when refresh. Otherwise it is attached when it exposes a documented table with no computed column (filtered or not), unless tdfs4ds.EXPOSED_VIEW_AUTO_ATTACH is False. Never raises.