Skip to content

Commit f68d03d

Browse files
committed
test(native): prove every attachment kind renders macros through the native bridge
1 parent 9dbc3a8 commit f68d03d

2 files changed

Lines changed: 63 additions & 11 deletions

File tree

‎tests/integration/src/sqlbuild/compiler/attachments/helpers.py‎

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import random
66
from collections.abc import Callable
77
from dataclasses import dataclass
8+
from functools import partial
89
from pathlib import Path
910
from typing import cast
1011

@@ -23,6 +24,7 @@
2324
resolve_audit_run_scope,
2425
resolve_audit_severity,
2526
)
27+
from sqlbuild.compiler.compile._helpers.render import macros
2628
from sqlbuild.compiler.compile._helpers.render.cursor_intrinsics import reject_cursor_intrinsics
2729
from sqlbuild.compiler.compile._helpers.render.sql_vars import expand_authored_sql_result
2830
from sqlbuild.compiler.compile.exceptions import CompileInputError
@@ -36,7 +38,8 @@
3638
from sqlbuild.compiler.discovery.main.discover import discover_project_inputs
3739
from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs
3840
from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR
39-
from sqlbuild.compiler.frontier.types import CompilerEngine
41+
from sqlbuild.compiler.frontier.main._compile_frontier import compile_frontier
42+
from sqlbuild.compiler.frontier.types import CompilerEngine, CompilerStage
4043
from sqlbuild.compiler.planner.constants import (
4144
MICROBATCH_END_SENTINEL,
4245
MICROBATCH_START_SENTINEL,
@@ -289,6 +292,11 @@ def _python_rendering(audit: GeneratedAudit) -> tuple[object, ...] | str:
289292
'[connections.local]\ndatabase = "orders.duckdb"\n\n'
290293
'[targets.dev]\nconnection = "local"\nschema = "dev"\n'
291294
),
295+
"macros/labels.py": (
296+
"def tidy_label(expression: str) -> str:\n"
297+
' """Trim and lower-case a label."""\n'
298+
' return f"LOWER(TRIM({expression}))"\n'
299+
),
292300
"seeds/channel_codes.csv": "id,label\n1,web\n2,store\n",
293301
"seeds/channel_codes.yml": (
294302
"seeds:\n - name: channel_codes\n description: Channel codes.\n columns:\n"
@@ -302,26 +310,41 @@ def _python_rendering(audit: GeneratedAudit) -> tuple[object, ...] | str:
302310
"sources/events.yml": (
303311
"sources:\n - name: order_events\n"
304312
f" description: \"Order feed ${{coalesce(ENV:{_MISSING_ENV}, 'events')}}\"\n"
305-
" expression: \"(SELECT 1 AS id, '@@region' AS region)\"\n"
313+
" expression: \"(SELECT 1 AS id, @tidy_label('@@region') AS region)\"\n"
306314
" columns:\n - name: id\n type: INTEGER\n audits:\n"
307315
" - accepted_values:\n values: [1, 2]\n"
308316
" - name: region\n type: VARCHAR\n"
309317
),
310318
"functions/sql/order_label.sql": (
311319
'FUNCTION (\n description "Label an order status.",\n'
312320
f" schema \"${{coalesce(ENV:{_MISSING_ENV}, 'udfs')}}\",\n"
313-
" arguments (raw_status STRING),\n returns STRING,\n);\n\nUPPER(raw_status)\n"
321+
" arguments (raw_status STRING),\n returns STRING,\n);\n\n"
322+
'UPPER(@tidy_label("raw_status"))\n'
314323
),
315324
"audits/generic/amount_floor.sql": (
316325
'AUDIT ();\n\nSELECT *\nFROM __ref("@model")\nWHERE @column < @minimum '
317-
"AND label <> @'label'\n"
326+
"AND @tidy_label(\"label\") <> @'label'\n"
318327
),
319328
"models/orders.sql": (
320329
'MODEL (\n materialized table,\n description "Orders.",\n'
321330
' audits [amount_floor (column amount, minimum -5, label "it\'s", severity warn)],\n'
322331
");\n\nSELECT c.id, 1.5 AS amount, c.label\n"
323332
'FROM __seed("channel_codes") c\nJOIN __source("order_events") e ON e.id = c.id\n'
324333
),
334+
"tests/unit/test_orders.sql": (
335+
"TEST();\n\nWITH\n__seed__channel_codes AS (\n"
336+
" SELECT 1 AS id, @tidy_label(\"' Web '\") AS label\n),\n"
337+
"__source__order_events AS (\n SELECT 1 AS id, 'north' AS region\n),\n"
338+
"__expected__orders AS (\n SELECT 1 AS id, 1.5 AS amount, 'web' AS label\n)\n"
339+
"SELECT 1\n"
340+
),
341+
"tests/scenarios/orders_scenario.sql": (
342+
'SCENARIO (\n description "Orders join their channel"\n);\n\n'
343+
"WITH\n__seed__channel_codes AS (\n SELECT 1 AS id, @tidy_label(\"'Web'\") AS label\n),\n"
344+
"__source__order_events AS (\n SELECT 1 AS id, 'north' AS region\n),\n"
345+
"__expected__orders AS (\n SELECT 1 AS id, 1.5 AS amount, 'web' AS label\n)\n"
346+
"SELECT 1\n"
347+
),
325348
}
326349

327350

@@ -340,8 +363,14 @@ def attachment_engine_outcome(
340363
called: set[str] = set()
341364
for name in NATIVE_ATTACHMENT_ENTRIES:
342365
monkeypatch.setattr(_native, name, _recorded(called=called, name=name))
366+
bridged: list[Path] = []
367+
monkeypatch.setattr(macros, "_bridged_sql_macros", _recorded_bridge(bridged=bridged))
343368
monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value)
344-
inputs: CompileProjectInputs = _compile_inputs(project_dir=project_dir)
369+
inputs: CompileProjectInputs = compile_frontier(
370+
until=CompilerStage.COMPILE_PROJECT_INPUTS,
371+
python_stage=partial(_compile_inputs, project_dir=project_dir),
372+
)
373+
called.update(f"bridged:{str(path).replace(str(project_dir), '<project>')}" for path in bridged)
345374
return frozenset(called), repr(
346375
(
347376
inputs.seed_inputs,
@@ -377,6 +406,16 @@ def _compile_inputs(*, project_dir: Path) -> CompileProjectInputs:
377406
)
378407

379408

409+
def _recorded_bridge(*, bridged: list[Path]) -> Callable[..., object]:
410+
entry: Callable[..., object] = cast(Callable[..., object], macros._bridged_sql_macros)
411+
412+
def recorded(*, consumer_path: Path, **arguments: object) -> object:
413+
bridged.append(consumer_path)
414+
return entry(consumer_path=consumer_path, **arguments)
415+
416+
return recorded
417+
418+
380419
def _recorded(*, called: set[str], name: str) -> Callable[..., object]:
381420
entry: Callable[..., object] = getattr(_native, name)
382421

‎tests/integration/src/sqlbuild/compiler/attachments/test_native_attachment_project.py‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Compile inputs of a project with every attachment kind match Python under the preview engine."""
1+
"""Every attachment kind compiles like Python under preview, with macros through the bridge."""
22

33
from __future__ import annotations
44

@@ -14,8 +14,21 @@
1414
attachment_engine_outcome,
1515
)
1616

17-
_PREVIEW_ONLY_ENTRIES: frozenset[str] = frozenset(
18-
{"pair_seed_files", "render_attached_generic_audit", "expand_config_templates"}
17+
_BRIDGED_CONSUMERS: frozenset[str] = frozenset(
18+
{
19+
"bridged:<built-in>/audits/generic/accepted_values.sql",
20+
"bridged:<built-in>/audits/generic/not_null.sql",
21+
"bridged:<project>/audits/generic/amount_floor.sql",
22+
"bridged:<project>/functions/sql/order_label.sql",
23+
"bridged:<project>/models/orders.sql",
24+
"bridged:<project>/sources/events.yml",
25+
"bridged:<project>/tests/scenarios/orders_scenario.sql",
26+
"bridged:<project>/tests/unit/test_orders.sql",
27+
}
28+
)
29+
_PREVIEW_ONLY_ENTRIES: frozenset[str] = (
30+
frozenset({"pair_seed_files", "render_attached_generic_audit", "expand_config_templates"})
31+
| _BRIDGED_CONSUMERS
1932
)
2033
_ATTACHMENT_ENTRIES: frozenset[str] = frozenset(
2134
{
@@ -32,8 +45,8 @@
3245
"test_case",
3346
[
3447
AttachmentProjectTestCase(
35-
description="seeds, templated source and function, and an attached generic audit",
36-
expected_preview_entries=_ATTACHMENT_ENTRIES,
48+
description="macros in every attachment kind, seeds, templates and generic audits",
49+
expected_preview_entries=_ATTACHMENT_ENTRIES | _BRIDGED_CONSUMERS,
3750
),
3851
],
3952
ids=lambda case: case.description,
@@ -56,7 +69,7 @@ def test_given_attachment_project_when_building_inputs_then_preview_matches_pyth
5669
assert (
5770
preview_outcome.replace(CompilerEngine.NATIVE_PREVIEW.value, "python"),
5871
native_outcome.replace(CompilerEngine.NATIVE.value, "python"),
59-
preview_called & _ATTACHMENT_ENTRIES >= test_case.expected_preview_entries,
72+
preview_called >= test_case.expected_preview_entries,
6073
(python_called | native_called) & _PREVIEW_ONLY_ENTRIES,
6174
) == (python_outcome, python_outcome, True, frozenset()), test_case.description
6275

0 commit comments

Comments
 (0)