Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions core/wren/src/wren/memory/schema_indexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,16 @@ def _describe_model(model: dict, lines: list[str]) -> None:
if cols:
lines.append(" Columns:")
for col in cols:
if not isinstance(col, dict):
continue
_describe_column(col, lines)
lines.append("")


def _describe_column(col: dict, lines: list[str]) -> None:
name = col["name"]
name = col.get("name")
if not name:
return
dtype = col.get("type", "?")
parts = [f" - {name} ({dtype})"]

Expand Down Expand Up @@ -230,7 +234,9 @@ def extract_schema_items(manifest: dict) -> list[dict]:

for model in manifest.get("models", []):
items.append(_model_record(model, mdl_h, now))
for col in model.get("columns", []):
for col in model.get("columns", []) or []:
if not isinstance(col, dict) or not col.get("name"):
continue
items.append(_column_record(col, model["name"], mdl_h, now))

for rel in manifest.get("relationships", []):
Expand Down Expand Up @@ -264,7 +270,7 @@ def extract_schema_items(manifest: dict) -> list[dict]:

def _model_record(model: dict, mdl_h: str, now: datetime) -> dict:
name = model["name"]
cols = model.get("columns", [])
cols = [c for c in (model.get("columns") or []) if isinstance(c, dict) and c.get("name")]
col_summaries = ", ".join(f"{c['name']} ({c.get('type', '?')})" for c in cols[:20])
pk = model.get("primaryKey") or ""

Expand Down Expand Up @@ -297,7 +303,9 @@ def _model_record(model: dict, mdl_h: str, now: datetime) -> dict:


def _column_record(col: dict, model_name: str, mdl_h: str, now: datetime) -> dict:
name = col["name"]
name = col.get("name") or ""
if not name:
raise ValueError("column record requires name")
dtype = col.get("type", "")
expr = col.get("expression") or None
is_calc = col.get("isCalculated", False)
Expand Down
38 changes: 38 additions & 0 deletions core/wren/tests/unit/test_schema_indexer_malformed_columns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""schema_indexer must skip non-dict / nameless columns."""

from __future__ import annotations

from wren.memory.schema_indexer import describe_schema, extract_schema_items


def test_describe_schema_skips_non_dict_columns():
text = describe_schema(
{
"models": [
{
"name": "orders",
"columns": [None, {"name": "amount", "type": "int"}, {"type": "x"}],
}
]
}
)
assert "amount" in text
assert "None" not in text


def test_extract_schema_items_skips_non_dict_columns():
items = extract_schema_items(
{
"models": [
{
"name": "orders",
"columns": [None, {"name": "amount", "type": "int"}, {"type": "x"}],
}
]
}
)
col_items = [i for i in items if i["item_type"] == "column"]
assert len(col_items) == 1
assert col_items[0]["item_name"] == "amount"
model_items = [i for i in items if i["item_type"] == "model"]
assert "amount" in model_items[0]["text"]
Loading