Repository navigation
Conversation
One incompatible change to the GQ grammar, edition 3, after which every later capability is a registry row, a plan node behind existing syntax or the filling of a reserved slot. The RFC carries the freeze list (mutation keyword, arrow traversals, a retrieve clause binding score columns, generic calls over a function registry, the closed reserved set, limit as a parameter, generic annotations, and the reserved declaration kinds, blocks, clauses, meta-fields, catalogue names and namespaced type references), the rewriter that migrates edition-2 sources with an IR-equality proof, and the one-release window in which edition 2 is rewritten at boot instead of quarantined.
…-evaluation-5a029b # Conflicts: # docs/rfcs/README.md
…-evaluation-5a029b # Conflicts: # docs/rfcs/README.md
|
Recommendation: revise. This review covers head WhyEach GQ feature has reserved a word, added a call, or advanced an explain version. Three open drafts still schedule a later major. #805 schedules What this RFC decidesEdition 3 is the one incompatible break. After it, the grammar accepts more text and keeps every produced shape. The grammar parses each reserved position. The type checker refuses a position whose owner has not landed, with a stable code that names that RFC. The latest commit keeps one directed spelling, Claims that match the codeChecked at the RFC pin
Blocking1. The retrieve column records the wrong type, and a score
|
…hema queryable at any size
…e-spelling rule removes
|
Recommendation: revise. This review covers head WhyEach GQ feature has reserved a word, added a call, or advanced an explain version. Open drafts still schedule their own majors. One edition that reserves the missing positions costs less, when those positions match the engine that already exists. What this delta changesThe triple stays. Keeping the triple is the right cut. The arrowhead adds no fact. Position and the schema already carry direction. The rewrite of every traversal was the largest mechanical edit in the break, and this delta removes it. Earlier findings
Optional items from that comment:
Blocking1. An incoming triple is legal edition-2 text, and the swap fails the equality proof
This RFC makes that triple The swap also fails the IR proof when the rewriter does apply it. The original lowers to The compatibility sentence says every edition-2 text other than
Keep both written orders for an asymmetric edge. They are one meaning, and the type checker already records which orientation each member takes. The one-spelling rule still removes the arrow, the infix operators, positional 2. The evaluation still specifies the arrow rewrite this delta withdrewThe RFC cites the evaluation as its evidence. These passages still tell an implementer to rewrite triples into arrows, or they keep decisions the RFC has dropped:
§9.3, §13.3, and §14.2 record the withdrawal. The operative rewrite, the sample, and the stage table do not. One source has to win. Make the evaluation match the RFC's freeze list, rewriter table, and compatibility list. A historical sentence can say the first draft chose the arrow. It cannot remain the instruction for 3. A catalogue
|
Why
GQ has grown one capability at a time: a logic word reserved when a filter needed it, ranking placed in
orderbecause that is where a score was first wanted, search functions added as keywords, the operator vocabulary amended in place, an explain version per feature, a deprecation shim per rename. Each change was right on its own terms and none was asked to fit the next five, so the language now carries decisions justified only by arrival order, and four open RFCs each schedule a break of their own. A whole-language review against SQL, GQL, Cypher, GraphQL, Datalog and the Elasticsearch, LanceDB and Vespa query languages found the semantics sound and the accretion the problem: every expressiveness gap is a position the grammar never reserved.This RFC opens a revision of the language as a whole. The goal is a foundation that is evolvable (every later capability has a reserved position), maintainable (one grammar, one function registry, one annotation form, one diagnostic contract), expressive (slots for derived relations, optional patterns, block aggregates as values, retrieval as typed columns, post-group filters, pattern-scoped writes) and extensible (registry rows and declarations an agent can author without a compiler release). It does the breaking work first, once, so everything after it is additive.
Summary
Adds
docs/rfcs/2026-10-28-gq-3-grammar.md(maintainer track) and its registry row, and commits the evaluation it is drawn from asdocs/rfcs/assets/2026-10-28-gq-3-grammar-evaluation.md(17 axes against SQL, GQL, Cypher, GraphQL, Datalog, Elasticsearch, LanceDB and Vespa; literature; the GQ 3 redesign; the RFC review; staging; TypeDB; direction; the one-way rule). The RFC links it from the Motivation and the decision log.The RFC decides that GQ makes one incompatible change, edition 3, and then stops making incompatible changes. The release that ships it lands every syntactic decision that would otherwise force a later break; forms whose semantics arrive in later RFCs land as slots the parser accepts and the type checker refuses with a stable code naming the owning RFC.
The freeze list:
mutationfor writes; the triple traversal kept unchanged ($p worksAt $c, source on the left;<e>for either orientation), with every arrow form a parse error whose fix prints the triple; aretrieve { }clause binding typed score columns, withordersorting values andhavingfiltering them; every function a generic call over a registry, with nothing left in the grammar; the reserved set closed at the six logic words;limit $k; generic@name(args)annotations; reserved declaration kinds (view,batch), blocks (optional { }, block aggregates as values), a view binding with arguments,returning, the meta-fields@type_id/@distance/@score, the schema-catalogue type names, namespaced type referencesa::b::C, and the schema rolesVector(n, distance=…),@analyzed,@valid; an optionalgq 3;edition line.A rewriter,
omnigraph queries migrate, turns edition-2 sources into edition 3 by byte-range edits with an IR-equality proof; the release that ships edition 3 rewrites an edition-2 stored source at boot with a warning instead of quarantining its graph, and the release after removes the edition-2 grammar.Owners of the slots
Derived relations and optional patterns (new), the RFC 0048 rewrite, the analyzed lexical search RFC (#792), a writes RFC (new), polymorphic types (#884), schema namespaces (#1015). No permissions construct is reserved: the permissions model is not accepted, and a file-level declaration keyword can be added later without a break.
Gates (
blocked_on)Checks
python3 scripts/check-docs.py(425 files OK) andtypospass.Update 2026-10-29: TypeDB, direction, one spelling per meaning
One way. The maintainer's requirement that there be one way of expressing something is now a stated design rule (Go's "a language needs only one conditional control flow construct"): a respelling with no meaning of its own is absent from the grammar and named by the diagnostics; a form that falls out of a general construct is canonicalised by
omnigraph queries fmt(count { } > 0→exists { },count { } = 0→not { }, later$x.@type = "T"→$x is T). The freeze list is checked against the rule in the Design section.Direction. The left arrow
$b <-knows- $ais removed as a second spelling of$a -knows-> $b(GQ has no path chains, so it never continues a line); it is a parse error whose fix prints the swap. An arrow written against the schema isT5with a machine-applicable swapped clause, the deterministic correction the Cypher ecosystem bolts on after generation (LangChain'sCypherQueryCorrector; CypherBench counts a reversed relation in about one gpt-4o failure in six) made loud and moved into the compiler.-e-resolves orientation per member from the endpoint types (the issue 659 alternation case), andT22narrows to the genuinely ambiguous case.TypeDB 3 / TypeQL. Reviewed against the design (pipelines, functions,
try, type variables, roles, the 2-to-3 migration, its agent benchmarks). It confirms the slot strategy (TypeQL's grammar carries lists, structs and three annotations its docs call "not yet available") and the rewriter (TypeDB's break had no query-migration tool), and changes no slot: its pipeline closure is the alternative the RFC rejects (text order is plan order, rows cross-product, reads and writes mix) and is now an Alternatives row; its type-variable binding and row-valuedgivenparameters are additive in GQ and noted for the polymorphism and a later RFC; roles are an Alternatives row.Schema queryable at any size. A sixth property in the Motivation: the schema is data in the same language. Catalogue types (
@Type,@Property,@Edge,@Interface,@Index,@Function,@View) are node types for every purpose of the grammar, so a thousand-type schema is bound, traversed, searched (retrieve { $t.lex: bm25($t.instruction, $q) }) and counted instead of dumped into a context window. The@-prefixed catalogue edge selector ($t: @Type -@property-> $p: @Property) is reserved so catalogue edges never collide with a user edge namedpropertyorfrom; the engine catalogue RFC's schema extension owns the catalogue's edges and searchable fields.Update 2026-10-30: no arrow
The arrow spelling is withdrawn. The arrowhead carries no information: when the endpoint types differ the schema fixes the orientation, and when they are the same the position does, in a triple exactly as in an arrow form. Its two justifications did not hold up (a triple reads in source-to-target order; the only in-context measurement GQ has is on the triple, with no direction errors, while CypherBench shows arrows do not prevent reversals), and it was the break's largest rewrite. The triple traversal therefore stays unchanged from edition 2,
<e>keeps the per-member orientation rule and the narrowedT22, a triple written against the schema isT5with the swapped clause as its fix, and-e->,<-e-and-e-are recognised parse errors whose fix prints the triple. Catalogue edges are$t: @Type @property $p: @Property. The rewriter table and the compatibility section lose their traversal rows; the break no longer touches every stored query.