Skip to main content

selene_core/
feature_register.rs

1//! ISO/IEC 39075:2024 feature and implementation-defined registers.
2//!
3//! This file is the canonical source for selene-db's optional-feature language
4//! claim. The markdown tables for Spec 01, Spec 07, and Spec 09 are rendered or
5//! checked from these constants by `build/regen_feature_docs.sh`.
6
7use std::fmt;
8
9/// Stable ISO GQL feature identifier.
10///
11/// The private field makes the set closed to this module while preserving the
12/// spec's string IDs as the stable ABI-facing representation.
13#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
14#[repr(transparent)]
15pub struct FeatureId(&'static str);
16
17impl FeatureId {
18    /// Return the ISO feature ID string, such as `GP04`.
19    pub const fn as_str(self) -> &'static str {
20        self.0
21    }
22}
23
24impl fmt::Display for FeatureId {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        f.write_str(self.as_str())
27    }
28}
29
30macro_rules! feature_ids {
31    ($($name:ident = $id:literal => $display:literal;)*) => {
32        impl FeatureId {
33            $(
34                #[doc = concat!("`", $display, "`")]
35                pub const $name: FeatureId = FeatureId($id);
36            )*
37        }
38
39        /// Every feature ID currently referenced by selene-db specs.
40        pub const REFERENCED_FEATURES: &[(FeatureId, &str)] = &[
41            $((FeatureId::$name, $display),)*
42        ];
43    };
44}
45
46feature_ids! {
47    G002 = "G002" => "Different-edges match mode";
48    G003 = "G003" => "Explicit REPEATABLE ELEMENTS keyword";
49    G010 = "G010" => "Explicit WALK keyword";
50    G011 = "G011" => "Advanced path modes: TRAIL";
51    G012 = "G012" => "Advanced path modes: SIMPLE";
52    G013 = "G013" => "Advanced path modes: ACYCLIC";
53    G014 = "G014" => "Explicit PATH/PATHS keywords";
54    G015 = "G015" => "All path search: explicit ALL keyword";
55    G016 = "G016" => "Any path search";
56    G017 = "G017" => "All shortest path search";
57    G018 = "G018" => "Any shortest path search";
58    G019 = "G019" => "Counted shortest path search";
59    G020 = "G020" => "Counted shortest group search";
60    G036 = "G036" => "Quantified edges";
61    G037 = "G037" => "Questioned paths";
62    G060 = "G060" => "Bounded graph pattern quantifiers";
63    G061 = "G061" => "Unbounded graph pattern quantifiers";
64    G100 = "G100" => "ELEMENT_ID function";
65    G110 = "G110" => "IS DIRECTED predicate";
66    G111 = "G111" => "IS LABELED predicate";
67    G112 = "G112" => "IS SOURCE and IS DESTINATION predicate";
68    G113 = "G113" => "ALL_DIFFERENT predicate";
69    G114 = "G114" => "SAME predicate";
70    G115 = "G115" => "PROPERTY_EXISTS predicate";
71    GA01 = "GA01" => "IEEE 754 floating point operations";
72    GA07 = "GA07" => "Ordering by discarded binding variables";
73    GC02 = "GC02" => "Graph schema management: IF [ NOT ] EXISTS";
74    GC03 = "GC03" => "Graph type: IF [ NOT ] EXISTS";
75    GC04 = "GC04" => "Graph management";
76    GC05 = "GC05" => "Graph management: IF [ NOT ] EXISTS";
77    GD01 = "GD01" => "Updatable graphs";
78    GE04 = "GE04" => "Graph parameters";
79    GE05 = "GE05" => "Binding table parameters";
80    GE06 = "GE06" => "Path value construction";
81    GE07 = "GE07" => "Boolean XOR";
82    // ISO/IEC 39075:2024 Annex D Table D.1 row 77 / subclause 17.7: GE08 is
83    // "Reference parameters", NOT a CAST feature. selene-db does not implement
84    // reference parameters, so GE08 is referenced-but-not-supported (see
85    // NOT_SUPPORTED_RATIONALE). CAST is `<cast specification>` (§20.8 /
86    // Table D.1 row 53 = GA05, "Cast specification"). Per ISO Annex A item 52
87    // (Feature GA05), without GA05 "conforming GQL language shall not contain a
88    // <cast specification>" — CAST is gated behind GA05, NOT baseline. selene-db
89    // implements the cast construct, so it claims GA05 in SUPPORTED_FEATURES and
90    // stamps it on every `ValueExpr::Cast`. GA06 is the sibling construct-level
91    // feature for `IS [NOT] TYPED <value type>` (§19.6); selene-db implements that
92    // value type predicate and stamps it on every typed `IsCheckKind`.
93    GE08 = "GE08" => "Reference parameters";
94    GA05 = "GA05" => "Cast specification";
95    GA06 = "GA06" => "Value type predicate";
96    GF01 = "GF01" => "Enhanced numeric functions";
97    GF02 = "GF02" => "Trigonometric functions";
98    GF03 = "GF03" => "Logarithmic functions";
99    GF04 = "GF04" => "Enhanced path functions";
100    GF05 = "GF05" => "Multi-character TRIM function";
101    GF06 = "GF06" => "Explicit TRIM function";
102    GF07 = "GF07" => "Byte string TRIM function";
103    GF10 = "GF10" => "Advanced aggregate functions: general set functions";
104    GF11 = "GF11" => "Advanced aggregate functions: binary set functions";
105    GF12 = "GF12" => "CARDINALITY function";
106    GF13 = "GF13" => "SIZE function";
107    GF20 = "GF20" => "Aggregate functions in sort keys";
108    GL01 = "GL01" => "Hexadecimal literals";
109    GL02 = "GL02" => "Octal literals";
110    GL03 = "GL03" => "Binary literals";
111    GL04 = "GL04" => "Exact number in common notation without suffix";
112    GL05 = "GL05" => "Exact number in common notation or as decimal integer with suffix";
113    GL06 = "GL06" => "Exact number in scientific notation with suffix";
114    GL07 = "GL07" => "Approximate number in common notation or as decimal integer with suffix";
115    GL08 = "GL08" => "Approximate number in scientific notation with suffix";
116    GL09 = "GL09" => "Optional float number suffix";
117    GL10 = "GL10" => "Optional double number suffix";
118    GL11 = "GL11" => "Opt-out character escaping";
119    IM_UUID = "IM_UUID" => "selene-db UUID extension";
120    IM_JSON = "IM_JSON" => "selene-db JSON extension";
121    IM_VECTOR = "IM_VECTOR" => "selene-db VECTOR extension";
122    IM_EXTENDS = "IM_EXTENDS" => "selene-db EXTENDS type composition extension";
123    IM_INDEX_DDL = "IM_INDEX_DDL" => "selene-db named index DDL extension";
124    IM_TYPED_PARAMS = "IM_TYPED_PARAMS" => "selene-db inline typed parameter declaration extension";
125    IM_TRUNCATE = "IM_TRUNCATE" => "selene-db bulk truncate extension";
126    IM_DROP_CASCADE = "IM_DROP_CASCADE" => "selene-db cascading DROP TYPE extension";
127    IM_DROP_GRAPH = "IM_DROP_GRAPH" => "selene-db DROP GRAPH factory-reset extension";
128    GH02 = "GH02" => "Undirected edge patterns";
129    GG01 = "GG01" => "Graph with an open graph type";
130    GG02 = "GG02" => "Graph with a closed graph type";
131    GG20 = "GG20" => "Explicit element type names";
132    GG21 = "GG21" => "Explicit element type key label sets";
133    GP01 = "GP01" => "Inline procedure";
134    GP02 = "GP02" => "Inline procedure with implicit nested variable scope";
135    GP03 = "GP03" => "Inline procedure with explicit nested variable scope";
136    GP04 = "GP04" => "Named procedure calls";
137    GP05 = "GP05" => "Procedure-local value variable definitions";
138    GP06 = "GP06" => "Procedure-local value variable definitions: value variables based on simple expressions";
139    GP07 = "GP07" => "Procedure-local value variable definitions: value variable based on subqueries";
140    GP08 = "GP08" => "Procedure-local binding table variable definitions";
141    GP09 = "GP09" => "Procedure-local binding table variable definitions: binding table variables based on simple expressions or references";
142    GP10 = "GP10" => "Procedure-local binding table variable definitions: binding table variables based on subqueries";
143    GP11 = "GP11" => "Procedure-local graph variable definitions";
144    GP12 = "GP12" => "Procedure-local graph variable definitions: graph variables based on simple expressions or references";
145    GP13 = "GP13" => "Procedure-local graph variable definitions: graph variables based on subqueries";
146    GP14 = "GP14" => "Binding tables as procedure arguments";
147    GP15 = "GP15" => "Graphs as procedure arguments";
148    GP18 = "GP18" => "Catalog and data statement mixing";
149    GQ02 = "GQ02" => "Composite query: OTHERWISE";
150    GQ03 = "GQ03" => "Composite query: UNION";
151    GQ04 = "GQ04" => "Composite query: EXCEPT DISTINCT";
152    GQ05 = "GQ05" => "Composite query: EXCEPT ALL";
153    GQ06 = "GQ06" => "Composite query: INTERSECT DISTINCT";
154    GQ07 = "GQ07" => "Composite query: INTERSECT ALL";
155    GQ08 = "GQ08" => "FILTER statement";
156    GQ09 = "GQ09" => "LET statement";
157    GQ10 = "GQ10" => "FOR statement: list value support";
158    GQ11 = "GQ11" => "FOR statement: WITH ORDINALITY";
159    GQ12 = "GQ12" => "ORDER BY and page statement: OFFSET clause";
160    GQ13 = "GQ13" => "ORDER BY and page statement: LIMIT clause";
161    GQ14 = "GQ14" => "Complex expressions in sort keys";
162    GQ15 = "GQ15" => "GROUP BY clause";
163    GQ16 = "GQ16" => "Pre-projection aliases in sort keys";
164    GQ18 = "GQ18" => "Scalar subqueries";
165    GQ20 = "GQ20" => "Advanced linear composition with NEXT";
166    GQ24 = "GQ24" => "FOR statement: WITH OFFSET";
167    GS01 = "GS01" => "SESSION SET command: session-local graph parameters";
168    GS02 = "GS02" => "SESSION SET command: session-local binding table parameters";
169    GS03 = "GS03" => "SESSION SET command: session-local value parameters";
170    GS04 = "GS04" => "SESSION RESET command: reset all characteristics";
171    GS05 = "GS05" => "SESSION RESET command: reset session schema";
172    GS06 = "GS06" => "SESSION RESET command: reset session graph";
173    GS07 = "GS07" => "SESSION RESET command: reset time zone displacement";
174    GS08 = "GS08" => "SESSION RESET command: reset all session parameters";
175    GS10 = "GS10" => "SESSION SET command: session-local binding table parameters based on subqueries";
176    GS11 = "GS11" => "SESSION SET command: session-local value parameters based on subqueries";
177    GS12 = "GS12" => "SESSION SET command: session-local graph parameters based on simple expressions or references";
178    GS13 = "GS13" => "SESSION SET command: session-local binding table parameters based on simple expressions or references";
179    GS14 = "GS14" => "SESSION SET command: session-local value parameters based on simple expressions";
180    GS15 = "GS15" => "SESSION SET command: set time zone displacement";
181    GS16 = "GS16" => "SESSION RESET command: reset individual session parameters";
182    GT01 = "GT01" => "Explicit transaction commands";
183    GT03 = "GT03" => "Use of multiple graphs in a transaction";
184    GV01 = "GV01" => "8 bit unsigned integer numbers";
185    GV02 = "GV02" => "8 bit signed integer numbers";
186    GV03 = "GV03" => "16 bit unsigned integer numbers";
187    GV04 = "GV04" => "16 bit signed integer numbers";
188    GV05 = "GV05" => "Small unsigned integer numbers";
189    GV06 = "GV06" => "32 bit unsigned integer numbers";
190    GV07 = "GV07" => "32 bit signed integer numbers";
191    GV08 = "GV08" => "Regular unsigned integer numbers";
192    GV09 = "GV09" => "Specified integer number precision";
193    GV10 = "GV10" => "Big unsigned integer numbers";
194    GV11 = "GV11" => "64 bit unsigned integer numbers";
195    GV12 = "GV12" => "64 bit signed integer numbers";
196    GV13 = "GV13" => "128 bit unsigned integer numbers";
197    GV14 = "GV14" => "128 bit signed integer numbers";
198    GV15 = "GV15" => "256 bit unsigned integer numbers";
199    GV16 = "GV16" => "256 bit signed integer numbers";
200    GV17 = "GV17" => "Decimal numbers";
201    GV18 = "GV18" => "Small signed integer numbers";
202    GV19 = "GV19" => "Big signed integer numbers";
203    GV20 = "GV20" => "16 bit floating point numbers";
204    GV21 = "GV21" => "32 bit floating point numbers";
205    GV22 = "GV22" => "Specified floating point number precision";
206    GV23 = "GV23" => "Floating point type name synonyms";
207    GV24 = "GV24" => "64 bit floating point numbers";
208    GV25 = "GV25" => "128 bit floating point numbers";
209    GV26 = "GV26" => "256 bit floating point numbers";
210    GV30 = "GV30" => "Specified character string minimum length";
211    GV31 = "GV31" => "Specified character string maximum length";
212    GV32 = "GV32" => "Specified character string fixed length";
213    GV35 = "GV35" => "Byte string types";
214    GV36 = "GV36" => "Specified byte string minimum length";
215    GV37 = "GV37" => "Specified byte string maximum length";
216    GV38 = "GV38" => "Specified byte string fixed length";
217    GV39 = "GV39" => "Temporal types: date, local datetime and local time support";
218    GV40 = "GV40" => "Temporal types: zoned datetime and zoned time support";
219    GV41 = "GV41" => "Temporal types: duration support";
220    GV45 = "GV45" => "Record types";
221    GV46 = "GV46" => "Closed record types";
222    GV47 = "GV47" => "Open record types";
223    GV48 = "GV48" => "Nested record types";
224    GV50 = "GV50" => "List value types";
225    GV55 = "GV55" => "Path value types";
226    GV60 = "GV60" => "Graph reference value types";
227    GV61 = "GV61" => "Binding table reference value types";
228    GV66 = "GV66" => "Open dynamic union types";
229    GV67 = "GV67" => "Closed dynamic union types";
230    GV68 = "GV68" => "Dynamic property value types";
231    GV90 = "GV90" => "Explicit value type nullability";
232}
233
234/// Supported optional feature set.
235///
236/// ISO sources: Annex A numbered pp. 522-554; Annex D Table D.1 numbered
237/// pp. 577-586. Implication closure is handled by the flagger/planner.
238pub const SUPPORTED_FEATURES: &[FeatureId] = &[
239    FeatureId::G002,
240    FeatureId::G003,
241    FeatureId::G010,
242    FeatureId::G011,
243    FeatureId::G012,
244    FeatureId::G013,
245    // G014 "Explicit PATH/PATHS keywords" (ISO §16.6 <path or paths>, Annex A
246    // §16.6 CR5). The match-prefix grammar parses the optional PATH/PATHS sugar
247    // and the flagger stamps G014 iff it is present. Pure surface sugar per
248    // §1.2.4 — inert at runtime. G014 has NO ISO §24.7 implied-feature
249    // relationship (it appears in neither column of Table 10).
250    FeatureId::G014,
251    FeatureId::G015,
252    FeatureId::G016,
253    FeatureId::G017,
254    FeatureId::G018,
255    FeatureId::G019,
256    FeatureId::G020,
257    FeatureId::G036,
258    FeatureId::G037,
259    FeatureId::G060,
260    FeatureId::G061,
261    FeatureId::G100,
262    FeatureId::G110,
263    FeatureId::G111,
264    FeatureId::G112,
265    FeatureId::G113,
266    FeatureId::G114,
267    FeatureId::G115,
268    FeatureId::GA01,
269    FeatureId::GA05,
270    FeatureId::GA06,
271    FeatureId::GA07,
272    FeatureId::GC03,
273    FeatureId::GD01,
274    FeatureId::GE04,
275    FeatureId::GE05,
276    FeatureId::GE06,
277    FeatureId::GE07,
278    FeatureId::GF01,
279    FeatureId::GF02,
280    FeatureId::GF03,
281    FeatureId::GF04,
282    FeatureId::GF05,
283    FeatureId::GF06,
284    FeatureId::GF07,
285    FeatureId::GF10,
286    FeatureId::GF11,
287    FeatureId::GF12,
288    FeatureId::GF13,
289    FeatureId::GF20,
290    FeatureId::GL01,
291    FeatureId::GL02,
292    FeatureId::GL03,
293    FeatureId::GL04,
294    FeatureId::GL05,
295    FeatureId::GL06,
296    FeatureId::GL07,
297    FeatureId::GL08,
298    FeatureId::GL09,
299    FeatureId::GL10,
300    FeatureId::GL11,
301    FeatureId::IM_UUID,
302    FeatureId::IM_JSON,
303    FeatureId::IM_VECTOR,
304    FeatureId::IM_EXTENDS,
305    FeatureId::IM_INDEX_DDL,
306    FeatureId::IM_TYPED_PARAMS,
307    FeatureId::IM_TRUNCATE,
308    FeatureId::IM_DROP_CASCADE,
309    FeatureId::IM_DROP_GRAPH,
310    FeatureId::GH02,
311    FeatureId::GG01,
312    FeatureId::GG02,
313    FeatureId::GG20,
314    // GG21 "Explicit element type key label sets" — the type-DDL grammar now
315    // parses the explicit `<...type key label set>` (`[ <label set phrase> ]
316    // <implies>`, the `=>` marker, ISO §18.2/18.3) and the flagger stamps it.
317    // Per the §24.7 implied-feature-relationships table GG21 implies GG02
318    // ("Graph with a closed graph type"), which is already claimed above, so
319    // the claim is implication-consistent. selene-db sets the IL003 key-label-
320    // set cardinality cap to 1 (singleton), rejecting cardinality 0 (42012/
321    // 42014) and > 1 (42013/42015) per §18.2 SR10/SR11 + §18.3 SR11/SR12 — a
322    // conforming impl-defined cap, not a missing feature.
323    FeatureId::GG21,
324    FeatureId::GP01,
325    FeatureId::GP02,
326    FeatureId::GP03,
327    FeatureId::GP04,
328    FeatureId::GQ02,
329    FeatureId::GQ03,
330    FeatureId::GQ04,
331    FeatureId::GQ05,
332    FeatureId::GQ06,
333    FeatureId::GQ07,
334    FeatureId::GQ08,
335    FeatureId::GQ09,
336    FeatureId::GQ10,
337    FeatureId::GQ11,
338    FeatureId::GQ12,
339    FeatureId::GQ13,
340    FeatureId::GQ14,
341    FeatureId::GQ15,
342    FeatureId::GQ16,
343    FeatureId::GQ18,
344    FeatureId::GQ20,
345    FeatureId::GQ24,
346    FeatureId::GS03,
347    FeatureId::GS04,
348    FeatureId::GS07,
349    FeatureId::GS08,
350    FeatureId::GS15,
351    FeatureId::GS16,
352    FeatureId::GT01,
353    FeatureId::GV01,
354    FeatureId::GV02,
355    FeatureId::GV03,
356    FeatureId::GV04,
357    FeatureId::GV05,
358    FeatureId::GV06,
359    FeatureId::GV07,
360    FeatureId::GV08,
361    FeatureId::GV09,
362    FeatureId::GV10,
363    FeatureId::GV11,
364    FeatureId::GV12,
365    FeatureId::GV13,
366    FeatureId::GV14,
367    FeatureId::GV17,
368    FeatureId::GV18,
369    FeatureId::GV19,
370    FeatureId::GV21,
371    FeatureId::GV22,
372    FeatureId::GV23,
373    FeatureId::GV24,
374    FeatureId::GV30,
375    FeatureId::GV31,
376    FeatureId::GV32,
377    FeatureId::GV35,
378    FeatureId::GV36,
379    FeatureId::GV37,
380    FeatureId::GV38,
381    FeatureId::GV39,
382    FeatureId::GV40,
383    FeatureId::GV41,
384    FeatureId::GV45,
385    FeatureId::GV46,
386    FeatureId::GV47,
387    FeatureId::GV48,
388    FeatureId::GV50,
389    FeatureId::GV55,
390    FeatureId::GV66,
391    FeatureId::GV67,
392    FeatureId::GV68,
393    FeatureId::GV90,
394];
395
396/// Rationale for referenced optional features not currently claimed.
397///
398/// This list is reserved for features that are *parser-reachable but rejected*:
399/// each entry is backed by a negative conformance-corpus case proving the
400/// `UnsupportedFeature` rejection (see `corpus_covers_feature_register`).
401/// Features that have no syntactic surface at all — and so can be neither
402/// claimed nor rejected — are NOT listed here; they remain in
403/// `REFERENCED_FEATURES` only and surface as the `"referenced"` status in
404/// `selene.feature_status()`. GE08 ("Reference parameters", §17.7 —
405/// unimplemented) is deliberately in that referenced-only bucket
406/// (CONFORMANCE-00). GA05 ("Cast specification", §20.8) and GA06 ("Value type
407/// predicate", §19.6) are CLAIMED in `SUPPORTED_FEATURES`: CAST is gated behind
408/// GA05, and `IS [NOT] TYPED` is gated behind GA06. GG21 ("Explicit element type
409/// key label sets", §18.2/18.3) is now CLAIMED as well: the type-DDL grammar
410/// parses the explicit `<...type key label set>` (`=>` marker) and bounds its
411/// cardinality to the IL003 singleton cap.
412pub const NOT_SUPPORTED_RATIONALE: &[(FeatureId, &str)] = &[
413    (
414        FeatureId::GP05,
415        "procedure-local definitions require the procedure body parser; not yet supported",
416    ),
417    (
418        FeatureId::GP06,
419        "procedure-local definitions require the procedure body parser; not yet supported",
420    ),
421    (
422        FeatureId::GP07,
423        "procedure-local definitions require the procedure body parser; not yet supported",
424    ),
425    (
426        FeatureId::GP08,
427        "procedure-local definitions require the procedure body parser; not yet supported",
428    ),
429    (
430        FeatureId::GP09,
431        "procedure-local definitions require the procedure body parser; not yet supported",
432    ),
433    (
434        FeatureId::GP10,
435        "procedure-local definitions require the procedure body parser; not yet supported",
436    ),
437    (
438        FeatureId::GP11,
439        "procedure-local definitions require the procedure body parser; not yet supported",
440    ),
441    (
442        FeatureId::GP12,
443        "procedure-local definitions require the procedure body parser; not yet supported",
444    ),
445    (
446        FeatureId::GP13,
447        "procedure-local definitions require the procedure body parser; not yet supported",
448    ),
449    (
450        FeatureId::GP14,
451        "procedure-local definitions require the procedure body parser; not yet supported",
452    ),
453    (
454        FeatureId::GP15,
455        "procedure-local definitions require the procedure body parser; not yet supported",
456    ),
457    (
458        FeatureId::GP18,
459        "mixed catalog/data transaction behavior remains forbidden",
460    ),
461    (
462        FeatureId::GC02,
463        "CREATE/DROP SCHEMA is outside the current catalog claim (graph-schema vs graph-type vs graph)",
464    ),
465    (
466        FeatureId::GC04,
467        "CREATE GRAPH stays outside the current catalog claim (D1 single-graph embeddable cannot create a second graph); DROP GRAPH is the IM_DROP_GRAPH factory-reset extension, not GC04",
468    ),
469    (
470        FeatureId::GC05,
471        "CREATE GRAPH IF NOT EXISTS modifier remains outside the current catalog claim",
472    ),
473    (
474        FeatureId::GS01,
475        "SESSION SET <name> GRAPH binds a session-local graph parameter; D1 single-graph embeddable has one graph and no graph-parameter catalog/value slot to bind",
476    ),
477    (
478        FeatureId::GS02,
479        "SESSION SET <name> BINDING TABLE binds a typed binding-table reference value (GV61); the reference-type surface is deferred, so D1 has no spelling to bind",
480    ),
481    (
482        FeatureId::GS05,
483        "SESSION RESET SCHEMA resets the session schema; D1 single-graph embeddable has no schema layer (section 4.2.5.1) to reset",
484    ),
485    (
486        FeatureId::GS06,
487        "SESSION RESET GRAPH resets the session graph; D1 single-graph embeddable has exactly one graph and no working-graph switch to reset",
488    ),
489    (
490        FeatureId::GS10,
491        "session-local binding table parameters from subqueries depend on GS02 (binding-table parameters) and a procedure body; both deferred under D1",
492    ),
493    (
494        FeatureId::GS11,
495        "session-local value parameters from subqueries depend on procedure-body support; SESSION SET VALUE restricts the RHS to a value expression with no row context",
496    ),
497    (
498        FeatureId::GS12,
499        "session-local graph parameters from simple graph expressions/references depend on GS01 (graph parameters); D1-blocked",
500    ),
501    (
502        FeatureId::GS13,
503        "session-local binding table parameters from simple expressions/references depend on GS02 (binding-table parameters); deferred",
504    ),
505    (
506        FeatureId::GS14,
507        "selene-db evaluates SESSION SET VALUE against an empty binding so the RHS is restricted to a <value specification> (literal/parameter); the full <value expression> form (GS14) is not claimed",
508    ),
509    (
510        FeatureId::GT03,
511        "multi-graph transactions are out of scope under the D1 single-graph embeddable model",
512    ),
513    (
514        FeatureId::GV15,
515        "256-bit unsigned integers are not represented in Value v1",
516    ),
517    (
518        FeatureId::GV16,
519        "256-bit signed integers are not represented in Value v1",
520    ),
521    (FeatureId::GV20, "FLOAT16 remains deferred"),
522    (FeatureId::GV25, "FLOAT128 is deferred"),
523    (FeatureId::GV26, "FLOAT256 is deferred"),
524    (
525        FeatureId::GV60,
526        "GRAPH reference type spellings parse to the Flagger, but graph reference value semantics and closed graph constraints remain deferred",
527    ),
528    (
529        FeatureId::GV61,
530        "binding table reference types require TABLE field-type descriptors and binding-table value semantics before claiming",
531    ),
532];
533
534mod annex_b;
535
536pub use annex_b::{ANNEX_B_REGISTER, AnnexBId, ImplDefinedChoice};
537
538/// True when `id` is in the supported feature set.
539pub fn is_supported(id: FeatureId) -> bool {
540    SUPPORTED_FEATURES.contains(&id)
541}
542
543/// Return the ISO display name for a referenced feature ID.
544pub fn name_of(id: FeatureId) -> Option<&'static str> {
545    REFERENCED_FEATURES
546        .iter()
547        .find_map(|(feature, name)| (*feature == id).then_some(*name))
548}
549
550/// Return a referenced feature ID from its stable string representation.
551pub fn feature_id_from_str(id: &str) -> Option<FeatureId> {
552    REFERENCED_FEATURES
553        .iter()
554        .find_map(|(feature, _)| (feature.as_str() == id).then_some(*feature))
555}
556
557/// Return the non-support rationale for a referenced feature ID.
558pub fn non_supported_rationale(id: FeatureId) -> Option<&'static str> {
559    NOT_SUPPORTED_RATIONALE
560        .iter()
561        .find_map(|(feature, rationale)| (*feature == id).then_some(*rationale))
562}
563
564#[cfg(test)]
565mod tests;