Repository navigation
feat!: add typed SQL macros and require @py./@sql. macro calls - #1224
Merged
Merged
Conversation
kvlonge
enabled auto-merge (squash)
October 22, 2026 21:19
Add SQL macros: logic-free SQL fragments in macros/sql/ with a MACRO header and typed arguments, in three forms decided by the body (an expression, a WITH list of CTEs, or a SELECT list of columns). Calls are written @sql.name(...), expand in place in the declaration pass, and are checked on their own and again in every caller. Parameters are written @name in bodies; types follow schema declaration types, with CONST for compile-time scalars, LIST/SET, ENUM, RELATION and COLUMN OF arguments. Runtime parameters in literal-only positions are rejected. Formatting, rules and column lineage see through calls, and macro-mode unit tests and __macro__ mocks work for SQL macros. BREAKING CHANGE: Python macros now live in macros/python/ (and the python/ folder of scoped macro roots) and are called as @py.name(...). A macro file directly under a macros/ folder fails with D013, and a bare @name(...) call fails with P014; move files into macros/python/ and replace @name( with @py.name( in project SQL.
…lacement Report RELATION columns, COLUMN OF names and typed arguments that do not fit at the call, with the parameter's declaration. Accept every comma spelling around CTE-list and column-list calls, reject aliases on column-list calls, resolve macro bodies in the macro file's own scope, keep valid SQL macros when another fails inventory, use real call spans, read backslash-escaped strings, parenthesise before AT, OVER and FILTER, keep separators in mocks, record hook-only SQL macro dependencies, and format expression bodies and MACRO headers.
Check cache-hit models' SQL macro arguments too, resolve macro body declarations through the native per-file declaration context, build related locations as native records, and keep the SQL macro helpers flat.
Treat typed arguments in subqueries or set-operation scopes as unknown, resolve a FROM alias before a same-named CTE, keep DISTINCT ON calls rejected as before, and keep string literal lines when unwrapping formatted expression bodies.
Merge a scope's typed arguments into one probe, infer probe output types directly instead of running full analysis per probe, check a wave's models together, and locate calls without re-scanning the whole file.
Apply group-folder layout rules within a macro's python/ or sql/ folder, migrate the layout and move tests to kind folders and @py. calls, and teach the agent skill SQL macros and kind-prefixed calls.
Treat a probe as unknown when any FROM or JOIN source in it cannot be typed, so stars over unnest() or table functions no longer report missing columns. Teach kind-prefixed macro calls in the remaining docs.
The render-stage view filtered unknown-column findings inside macro calls by redeclaring B002, which the render code inventory reads as a code it emits. Name the analysis-owned constant instead.
The byte-by-byte scan cost about 4 instructions per byte of every authored SQL text, 0.15% of a 10,000-model compile without SQL macros.
Fingerprint a SQL macro declaration by its form, typed arguments, result type and normalised body, ignoring layout, comments and its description, and keep the edges to the SQL macros it calls.
kvlonge
force-pushed
the
feat/sql-macros
branch
from
October 23, 2026 04:32
8db0f9e to
ca52b0a
Compare
kvlonge
disabled auto-merge
October 23, 2026 05:13
kvlonge
enabled auto-merge (squash)
October 23, 2026 05:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Python macros were the only way to reuse SQL, so logic-free fragments were opaque to the compiler, formatter, rules and lineage. SQL macros are typed, checked fragments; every call names its kind.
Changes
macros/sql/(and scoped_macros/sql/), one per file, called@sql.name(...): expression, CTE-list and column-list forms; commas around list calls are optional.CONST,LIST/SET,ENUM,RELATION (...),COLUMN OF,DEFAULT, named arguments.sqb format, rules, lineage, macro tests,__macro__mocks andsqb mvsupport SQL macros._helper modules they import move tomacros/python/(imports gain.python) and are called@py.name(...); files directly undermacros/fail with D013, bare@name(...)with P014.--sincecompares SQL macros by their parsed definition (formatting, comments and description ignored) and follows nested SQL macro calls.unnest(), skip the argument check; rule findings inside an expansion point into the expanded query; a backslash-escaped string that also reads as balanced without escapes can be misread.Verification
--sincecase.@py.prefix andpython/paths.make check-cipasses.