1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! Planner implementation-defined limits.
use std::num::NonZeroUsize;
/// Planner implementation-defined limits.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub struct ImplDefinedCaps {
/// Maximum accepted variable-length quantifier upper bound.
pub max_quantifier: u32,
/// Fixed-point optimizer iteration cap.
pub max_optimizer_iterations: u32,
/// Maximum character length for character-string concatenation results.
pub max_string_length: u32,
/// Maximum byte length for byte-string concatenation results.
pub max_byte_string_length: u32,
/// Default maximum path length for future path execution.
pub max_path_length: u32,
/// Maximum list cardinality for constructed list values.
pub max_list_length: u32,
/// Maximum number of expand nodes WCO cycle detection will inspect.
pub max_wco_traversal_nodes: u32,
/// Maximum unique row keys a set operation may hold while counting rows.
pub set_op_key_cap: NonZeroUsize,
/// Maximum distinct groups a `GROUP BY` may materialize.
pub group_by_key_cap: NonZeroUsize,
// The four key-label-set cardinality bounds (IL003) are `pub(crate)`, NOT
// `pub` like the other caps: the runtime can only represent a *singleton*
// key label set, so these are a fixed internal invariant (min = max = 1),
// not an embedder knob. Keeping them crate-private prevents an external
// caller from mutating `ImplDefinedCaps::DEFAULT.node_key_label_set_max` past
// 1 (which `#[non_exhaustive]` alone does NOT stop for public fields) and
// committing an unrepresentable multi-label set. They become `pub` +
// builder-configurable with multi-label runtime support (v1.3).
/// Minimum cardinality of an explicit node-type key label set (ISO/IEC
/// 39075:2024 IL003, §18.2 SR10). Fixed at 1.
pub(crate) node_key_label_set_min: u32,
/// Maximum cardinality of an explicit node-type key label set (ISO/IEC
/// 39075:2024 IL003, §18.2 SR11). Fixed at 1 (singleton).
pub(crate) node_key_label_set_max: u32,
/// Minimum cardinality of an explicit edge-type key label set (ISO/IEC
/// 39075:2024 IL003, §18.3 SR11). Fixed at 1.
pub(crate) edge_key_label_set_min: u32,
/// Maximum cardinality of an explicit edge-type key label set (ISO/IEC
/// 39075:2024 IL003, §18.3 SR12). Fixed at 1 (singleton).
pub(crate) edge_key_label_set_max: u32,
}
impl ImplDefinedCaps {
/// Default maximum unique row keys a set operation may hold.
pub const DEFAULT_SET_OP_KEY_CAP: usize = 1_000_000;
/// Default maximum distinct groups a `GROUP BY` may materialize.
pub const DEFAULT_GROUP_BY_KEY_CAP: usize = 1_000_000;
/// Default maximum character length for character-string concatenation results.
pub const DEFAULT_MAX_STRING_LENGTH: u32 = u32::MAX;
/// Default maximum byte length for byte-string concatenation results.
pub const DEFAULT_MAX_BYTE_STRING_LENGTH: u32 = u32::MAX;
/// Default maximum cardinality for constructed list values.
pub const DEFAULT_MAX_LIST_LENGTH: u32 = 1_000_000;
/// The default implementation-defined caps as a `const`.
///
/// Const-constructible so `const fn` callers (e.g. `Session::new`) can seed
/// the embedder-facing default without invoking the non-`const`
/// [`Default::default`]. [`Default`] delegates here, so the two never drift.
pub const DEFAULT: Self = Self {
max_quantifier: 100,
max_optimizer_iterations: 8,
max_string_length: Self::DEFAULT_MAX_STRING_LENGTH,
max_byte_string_length: Self::DEFAULT_MAX_BYTE_STRING_LENGTH,
max_path_length: 32,
max_list_length: Self::DEFAULT_MAX_LIST_LENGTH,
max_wco_traversal_nodes: 64,
set_op_key_cap: NonZeroUsize::new(Self::DEFAULT_SET_OP_KEY_CAP)
.expect("default set-op key cap is non-zero"),
group_by_key_cap: NonZeroUsize::new(Self::DEFAULT_GROUP_BY_KEY_CAP)
.expect("default group-by key cap is non-zero"),
// IL003: singleton key label sets only. Multi-label is a deferred
// feature (KeyLabelSetPolicy + containment identification), so the
// default min == max == 1 rejects every non-singleton explicit key
// label set with the spec-defined GQLSTATUS (§18.2 SR10/SR11, §18.3
// SR11/SR12).
node_key_label_set_min: 1,
node_key_label_set_max: 1,
edge_key_label_set_min: 1,
edge_key_label_set_max: 1,
};
/// Return a copy with a different variable-length quantifier upper-bound
/// cap (ISO IL018). Consulted by the plan-time quantifier gate.
#[must_use]
pub const fn with_max_quantifier(mut self, max_quantifier: u32) -> Self {
self.max_quantifier = max_quantifier;
self
}
/// Return a copy with a different maximum path length cap (ISO IL015).
#[must_use]
pub const fn with_max_path_length(mut self, max_path_length: u32) -> Self {
self.max_path_length = max_path_length;
self
}
/// Return a copy with a different character-string concat length cap (ISO IL013).
#[must_use]
pub const fn with_max_string_length(mut self, max_string_length: u32) -> Self {
self.max_string_length = max_string_length;
self
}
/// Return a copy with a different byte-string concat length cap (ISO IL013).
#[must_use]
pub const fn with_max_byte_string_length(mut self, max_byte_string_length: u32) -> Self {
self.max_byte_string_length = max_byte_string_length;
self
}
/// Return a copy with a different maximum list cardinality cap (ISO IL015).
#[must_use]
pub const fn with_max_list_length(mut self, max_list_length: u32) -> Self {
self.max_list_length = max_list_length;
self
}
/// Return the configured set-operation key cap.
#[must_use]
pub const fn set_op_key_cap(&self) -> usize {
self.set_op_key_cap.get()
}
/// Return a copy with a different set-operation key cap.
#[must_use]
pub const fn with_set_op_key_cap(mut self, set_op_key_cap: NonZeroUsize) -> Self {
self.set_op_key_cap = set_op_key_cap;
self
}
/// Return the configured `GROUP BY` distinct-group cap.
#[must_use]
pub const fn group_by_key_cap(&self) -> usize {
self.group_by_key_cap.get()
}
/// Return a copy with a different `GROUP BY` distinct-group cap.
#[must_use]
pub const fn with_group_by_key_cap(mut self, group_by_key_cap: NonZeroUsize) -> Self {
self.group_by_key_cap = group_by_key_cap;
self
}
// NOTE: the node/edge key-label-set cardinality bounds (IL003) are
// deliberately NOT embedder-tunable in this release — unlike `max_quantifier`
// / the key caps (which the runtime honors at any value), the runtime can
// only represent a *singleton* key label set: `EdgeTypeDef.label` is a single
// discriminator, and an empty explicit set has no element-type name. A
// configurable bound would let `> 1` silently drop labels or `0` synthesize a
// placeholder name. So the bounds are fixed at min = max = 1 via `DEFAULT` and
// their fields are `pub(crate)` (not `pub`) — `#[non_exhaustive]` blocks only
// struct-literal construction, not field mutation of a `DEFAULT`-derived
// instance, so crate-private visibility is what actually keeps an embedder
// from setting them. Configurable bounds land *with* multi-label runtime
// support (v1.3); adding `with_{node,edge}_key_label_set_bounds` + making the
// fields `pub` then is the atomic place to re-expose them.
}
impl Default for ImplDefinedCaps {
fn default() -> Self {
Self::DEFAULT
}
}