@@ -171,8 +171,49 @@ WITH [RECURSIVE]
171171main query
172172```
173173
174- It records only proven declaration names, body boundaries, declaration order,
175- and visibility. It is not a miniature general SQL AST.
174+ The accepted grammar is dialect-owned and closed:
175+
176+ | Dialect | Declarations per frame | ` RECURSIVE ` | Declared columns | Materialization modifier |
177+ | --- | ---: | --- | --- | --- |
178+ | PostgreSQL | up to the global bound | accepted | accepted | ` MATERIALIZED ` and ` NOT MATERIALIZED ` |
179+ | DuckDB | up to the global bound | accepted | accepted | ` MATERIALIZED ` and ` NOT MATERIALIZED ` |
180+ | BigQuery | up to the global bound | accepted | rejected | rejected |
181+ | Dremio | one | rejected | accepted | rejected |
182+
183+ This matrix describes only syntax the bounded recognizer can prove. Rejection
184+ does not claim that a database engine rejects every extension or future
185+ version; it makes the current completion result explicitly incomplete or
186+ unavailable instead of borrowing another dialect's grammar.
187+
188+ The recognizer records only:
189+
190+ - flat query-block frames and their parent frame;
191+ - proven declaration names, exact source spelling and name ranges;
192+ - body ranges and declaration order;
193+ - authenticated main-query ` SELECT ` entrypoints; and
194+ - bounded candidate-name and uncertainty evidence for incomplete headers.
195+
196+ It stores no AST, SQL substring, token tape, inferred output columns, or
197+ recursive dependency graph. A declaration is committed only after its ` AS `
198+ body has a proven matching close parenthesis. Seeing ` WITH name ` , ` name AS ` , or
199+ an opening body alone never invents a visible relation. Once a body opening is
200+ proven, a separate bounded draft record retains its name, ordinal, body range,
201+ and comparison evidence. Drafts can establish the current body phase and
202+ fail-closed shadow uncertainty, but never become completion candidates.
203+
204+ Candidate-name evidence, visible-candidate evidence, and shadow evidence are
205+ distinct. Before a body opens, an active incomplete header has no supported
206+ relation site; direct private projection still reports recovered unknown
207+ coverage rather than exact absence. Once a body opens, its draft name is not
208+ returned as a completion candidate, but it prevents the service from claiming
209+ exact scope or exact non-shadowing where recursive or uncertain equality could
210+ make it visible. Such a result is marked incomplete with
211+ ` cte-scope-uncertainty ` . A proven declaration shadows an equivalent outer CTE
212+ or unqualified catalog insertion only over its proven visibility range. A
213+ duplicate equivalence class produces no arbitrary first- or last-wins
214+ candidate and blocks an equivalent outer or catalog name wherever that class
215+ would be visible. Uncertainty in one nested frame does not erase independently
216+ proven candidates outside that frame.
176217
177218For non-recursive CTEs:
178219
@@ -184,13 +225,69 @@ For non-recursive CTEs:
184225- a nested declaration shadows an outer name only inside its query block; and
185226- nested declarations never leak outward.
186227
187- Identifier equality follows the dialect. Duplicate names and structurally
188- ambiguous headers make the affected frame partial. ` WITH RECURSIVE ` may expose
189- proven names in the main query, but self and mutual-recursive body visibility
190- remain explicitly incomplete until implemented.
228+ Identifier comparison follows the dialect and is tri-state: ` equal ` ,
229+ ` distinct ` , or ` unknown ` . PostgreSQL non-ASCII folding can depend on server
230+ encoding and locale, while BigQuery and Dremio document case-insensitivity
231+ without giving this package an authoritative general Unicode folding
232+ algorithm. ` unknown ` therefore degrades namespace coverage and never means
233+ ` distinct ` . The private layout builder consumes the same pairwise
234+ ` compareCteIdentifiers ` operation exposed by the relation-completion dialect
235+ runtime; it does not define a second nullable comparison key. Within the
236+ 256-name bound it snapshots symmetric pairwise results into frozen
237+ equivalence classes and scoped uncertainty evidence. Throws, invalid values,
238+ asymmetry, non-reflexivity, or inconsistent equivalence results fail closed.
239+ Duplicate detection uses those classes rather than generic case folding.
240+
241+ A declaration retains both its decoded value and exact source token. The
242+ decoded value is the completion label; the exact token is the insertion text,
243+ so required quoting, case, and escapes are never reconstructed by the catalog
244+ renderer. CTEs are considered only for unqualified relation sites. Prefix
245+ eligibility is also a dialect-owned tri-state operation distinct from equality;
246+ generic locale-sensitive or Unicode case folding is never used.
247+
248+ ` WITH RECURSIVE ` may expose proven names in the main query. The initial
249+ recognizer also retains independently proven earlier-sibling and outer
250+ visibility inside a recursive body, but self and forward or mutual-recursive
251+ body candidates remain incomplete and add ` recursive-cte-uncertainty ` . Every
252+ known frame-local recursive name still contributes shadow evidence inside a
253+ recursive body, so withholding a self candidate cannot incorrectly reveal an
254+ equivalent outer or catalog relation. The recognizer does not infer a recursive
255+ dependency graph or output columns. DuckDB ` USING KEY ` , PostgreSQL
256+ ` SEARCH ` /` CYCLE ` , and any Dremio recursive extension remain unsupported.
257+
258+ The index is cursor-independent and cached with the immutable source,
259+ statement, embedded-region, and dialect-runtime identities. Visibility is a
260+ pure projection over its flat frozen ranges. Building the index and recognizing
261+ the relation query site may initially make two independent linear streaming
262+ passes over the shared lexer; traversal fusion is allowed only after benchmark
263+ evidence. Neither cursor movement nor catalog invalidation rebuilds the index.
264+
265+ Stored source ranges remain half-open. Visibility projection accepts cursor
266+ positions, so a cursor exactly before a proven closing delimiter remains in
267+ the body or nested frame, and a top-level cursor at statement EOF remains in
268+ the main query. A cursor after the delimiter is outside. At the first
269+ untrusted boundary the enclosing draft phase may still contribute proven
270+ positive evidence, but quality and shadow coverage are recovered rather than
271+ exact.
272+
273+ An opaque region in a CTE header or body, an unterminated quoted token, an
274+ unsupported dialect modifier, a duplicate declaration, or a structurally
275+ plausible but unfinished declaration makes the affected frame partial. The
276+ first opaque region terminates exact structural coverage: visible punctuation
277+ after an untyped barrier never closes a body or frame that started before it.
278+ A resource limit records the same first-untrusted boundary. Partial artifacts
279+ may still contribute declarations, entrypoints, and visibility ranges proven
280+ entirely before that boundary, but they never produce exact absence or shadow
281+ claims across it.
191282
192283An empty positive-only local-relation list never proves that no CTE is visible.
193284
285+ The first bounded grammar intentionally authenticates only ` SELECT ` query
286+ leaders. PostgreSQL ` VALUES ` and data-modifying CTE bodies, DuckDB ` FROM ` -first
287+ queries, and additionally parenthesized BigQuery recursive terms currently
288+ fail closed. Their query-leader sets will become dialect-owned in a follow-up
289+ before relation completion is declared feature-complete.
290+
194291### Embedded regions
195292
196293The first public template input is a complete set of length-preserving embedded
@@ -525,6 +622,7 @@ The initial checked limits are:
525622| Active statement scanned | 65,536 UTF-16 units |
526623| Lexical tokens | 16,384 |
527624| Parenthesis/query depth | 128 |
625+ | CTE frames | 256 |
528626| CTE declarations | 256 |
529627| Identifier path segments | 32 global ceiling; dialect runtime sets the checked limit |
530628| Identifier segment | 256 UTF-16 units |
0 commit comments