Implementation:TobikoData Sqlmesh Context Render Evaluate Fetchdf
| Knowledge Sources | |
|---|---|
| Domains | Data_Engineering, Model_Development, Data_Quality |
| Last Updated | 2026-02-07 00:00 GMT |
Overview
Concrete query rendering, execution, and data retrieval methods for model exploration provided by SQLMesh.
Description
SQLMesh provides three complementary methods for data exploration during development: Context.render expands a model's query with all macros and references resolved, returning the final SQL expression without executing it; Context.evaluate executes a model's query against the database for a specific time interval and returns the results as a DataFrame; Context.fetchdf executes arbitrary SQL queries and returns results as a DataFrame.
These methods form a complete toolkit for iterative model development. render helps debug macro expansion and understand generated SQL. evaluate validates model logic with real data and specific time boundaries, respecting incremental model semantics. fetchdf enables ad-hoc exploration of source tables and testing of query fragments. Together, they provide visibility into the transformation pipeline at multiple abstraction levels.
Usage
Use render when debugging macro issues, verifying dependency resolution, or understanding what SQL will execute. Use evaluate when testing model logic with production data, validating incremental processing, or generating sample outputs. Use fetchdf for ad-hoc queries, exploring source data, or debugging specific data issues outside the model framework.
Code Reference
Source Location
- Repository: sqlmesh
- File:
sqlmesh/core/context.pyrender: Lines 1096-1119evaluate: Lines 1165-1184fetchdf: Lines 236-248
Signature
# Method 1: render
def render(
self,
model_or_snapshot: ModelOrSnapshot,
*,
start: t.Optional[TimeLike] = None,
end: t.Optional[TimeLike] = None,
execution_time: t.Optional[TimeLike] = None,
expand: t.Union[bool, t.Iterable[str]] = False,
**kwargs: t.Any,
) -> exp.Expression
# Method 2: evaluate
def evaluate(
self,
model_or_snapshot: ModelOrSnapshot,
start: TimeLike,
end: TimeLike,
execution_time: TimeLike,
limit: t.Optional[int] = None,
**kwargs: t.Any,
) -> DF
# Method 3: fetchdf
def fetchdf(
self,
query: t.Union[exp.Expression, str],
quote_identifiers: bool = False
) -> pd.DataFrame
Import
from sqlmesh import Context
context = Context()
I/O Contract
Inputs
render method:
| Name | Type | Required | Description |
|---|---|---|---|
| model_or_snapshot | ModelOrSnapshot | Yes | Model object, model name, or snapshot to render |
| start | TimeLike | No | Start of time interval for incremental models |
| end | TimeLike | No | End of time interval for incremental models |
| execution_time | TimeLike | No | Execution timestamp reference (default: now) |
| expand | bool or Iterable[str] | No | Whether to inline upstream model queries (True=all, list=specific models) |
evaluate method:
| Name | Type | Required | Description |
|---|---|---|---|
| model_or_snapshot | ModelOrSnapshot | Yes | Model object, model name, or snapshot to evaluate |
| start | TimeLike | Yes | Start of time interval to evaluate |
| end | TimeLike | Yes | End of time interval to evaluate |
| execution_time | TimeLike | Yes | Execution timestamp reference |
| limit | int | No | Row limit for sampling results |
fetchdf method:
| Name | Type | Required | Description |
|---|---|---|---|
| query | Expression or str | Yes | SQL query to execute |
| quote_identifiers | bool | No | Whether to quote all identifiers (default: False) |
Outputs
| Method | Return Type | Description |
|---|---|---|
| render | exp.Expression | SQLGlot Expression object representing the rendered SQL |
| evaluate | DF | DataFrame with query results (Pandas or PySpark depending on engine) |
| fetchdf | pd.DataFrame | Pandas DataFrame with query results |
Usage Examples
Rendering Model SQL
from sqlmesh import Context
context = Context()
# Render model SQL with macro expansion
rendered = context.render(
"my_schema.my_model",
start="2024-01-01",
end="2024-01-31",
execution_time="2024-02-01"
)
# View the generated SQL
print(rendered.sql(pretty=True))
Expanding Upstream References
# Render with all upstream models inlined
expanded_query = context.render(
"my_schema.final_model",
start="2024-01-01",
end="2024-01-01",
expand=True # Inline all upstream model queries
)
# Or expand only specific models
partial_expand = context.render(
"my_schema.final_model",
start="2024-01-01",
end="2024-01-01",
expand=["my_schema.intermediate_model"] # Only inline this model
)
print(partial_expand.sql(pretty=True))
Evaluating Model with Sample Data
# Execute model and get results
results = context.evaluate(
"my_schema.revenue_summary",
start="2024-01-01",
end="2024-01-07",
execution_time="2024-01-08",
limit=100 # Sample first 100 rows
)
# Inspect results
print(f"Rows returned: {len(results)}")
print(results.head())
# Validate business logic
assert results['revenue'].sum() > 0
assert results['revenue'].isnull().sum() == 0
Ad-hoc Query Execution
# Execute arbitrary SQL for exploration
df = context.fetchdf("""
SELECT
date,
COUNT(*) as transaction_count,
SUM(amount) as total_amount
FROM raw.transactions
WHERE date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY date
ORDER BY date
""")
print(df)
Combined Workflow for Development
# Step 1: Render to verify SQL looks correct
rendered = context.render(
"my_schema.new_model",
start="2024-01-01",
end="2024-01-01"
)
print("Generated SQL:")
print(rendered.sql(pretty=True))
# Step 2: Evaluate to test with real data
results = context.evaluate(
"my_schema.new_model",
start="2024-01-01",
end="2024-01-01",
execution_time="2024-01-02",
limit=10
)
print("\nSample results:")
print(results)
# Step 3: Query upstream source for comparison
source_data = context.fetchdf("""
SELECT * FROM raw.source_table
WHERE date = '2024-01-01'
LIMIT 10
""")
print("\nUpstream source data:")
print(source_data)
# Step 4: Validate transformation logic
assert len(results) <= len(source_data), "Model should not create rows"
Debugging Macro Expansion
# Compare rendered SQL with and without macro context
rendered_dev = context.render(
"my_schema.model_with_macros",
start="2024-01-01",
end="2024-01-01"
)
# Check that macros expanded correctly
sql_text = rendered_dev.sql(pretty=True)
assert "@" not in sql_text, "Macro variables should be expanded"
print("Macros expanded successfully:")
print(sql_text)