sim_relation_plan/model.rs
1use sim_relation_core::{
2 BindingName, Cell, ColumnName, ConstraintName, FieldName, ParameterName, RelationId, Row,
3 RowType, SourceName, TableName,
4};
5use std::fmt;
6
7/// An explicitly qualified field reference.
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct FieldRef {
10 /// Relation binding.
11 pub binding: BindingName,
12 /// Field within the binding.
13 pub field: FieldName,
14}
15/// A named scalar projection.
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct NamedScalar {
18 /// Output field name.
19 pub name: FieldName,
20 /// Expression.
21 pub scalar: Scalar,
22}
23/// A named aggregate projection.
24#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct NamedAggregate {
26 /// Output field name.
27 pub name: FieldName,
28 /// Aggregate expression.
29 pub aggregate: Aggregate,
30}
31/// Join semantics.
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub enum JoinKind {
34 /// Matching rows only.
35 Inner,
36 /// All left rows, nullable right side.
37 Left,
38 /// Cartesian product.
39 Cross,
40}
41/// Set operation semantics.
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum SetOp {
44 /// Deduplicating union.
45 Union,
46 /// Multiset union.
47 UnionAll,
48 /// Intersection.
49 Intersect,
50 /// Difference.
51 Except,
52}
53/// Sort direction.
54#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub enum OrderDirection {
56 /// Ascending.
57 Asc,
58 /// Descending.
59 Desc,
60}
61/// A typed ordering expression.
62#[derive(Clone, Debug, PartialEq, Eq)]
63pub struct OrderKey {
64 /// Expression.
65 pub scalar: Scalar,
66 /// Direction.
67 pub direction: OrderDirection,
68}
69/// Portable scalar operators.
70#[derive(Clone, Copy, Debug, PartialEq, Eq)]
71pub enum ScalarOp {
72 /// Boolean conjunction.
73 And,
74 /// Boolean disjunction.
75 Or,
76 /// Boolean negation.
77 Not,
78 /// Equality.
79 Eq,
80 /// Inequality.
81 Ne,
82 /// Less than.
83 Lt,
84 /// Less than or equal.
85 Le,
86 /// Greater than.
87 Gt,
88 /// Greater than or equal.
89 Ge,
90 /// Addition.
91 Add,
92 /// Subtraction.
93 Sub,
94 /// Multiplication.
95 Mul,
96 /// Division.
97 Div,
98 /// Null test.
99 IsNull,
100 /// Null coalescing.
101 Coalesce,
102}
103/// A scalar expression. Subqueries retain lexical access to their outer scope.
104#[derive(Clone, Debug, PartialEq, Eq)]
105pub enum Scalar {
106 /// Bound field.
107 Field(FieldRef),
108 /// Typed literal.
109 Literal(Cell),
110 /// Declared parameter.
111 Param(ParameterName),
112 /// Portable operator call.
113 Call(ScalarOp, Vec<Scalar>),
114 /// Conditional expression.
115 Case {
116 /// Ordered predicate/value branches.
117 branches: Vec<(Scalar, Scalar)>,
118 /// Optional else expression.
119 otherwise: Option<Box<Scalar>>,
120 },
121 /// Existence subquery.
122 Exists(Box<Rel>),
123 /// Membership subquery.
124 InQuery {
125 /// Compared expression.
126 value: Box<Scalar>,
127 /// Single-column query.
128 query: Box<Rel>,
129 },
130 /// Single-value subquery.
131 ScalarQuery(Box<Rel>),
132}
133/// Aggregate operations with domain-derived result types.
134#[derive(Clone, Debug, PartialEq, Eq)]
135pub enum Aggregate {
136 /// Count all input rows.
137 CountAll,
138 /// Count non-null values.
139 Count(Scalar),
140 /// Sum ordered numeric values.
141 Sum(Scalar),
142 /// Minimum ordered value.
143 Min(Scalar),
144 /// Maximum ordered value.
145 Max(Scalar),
146}
147/// Complete logical relation algebra.
148#[derive(Clone, Debug, PartialEq, Eq)]
149pub enum Rel {
150 /// Catalog table scan.
151 Scan {
152 /// Provider source.
153 source: SourceName,
154 /// Schema table.
155 table: TableName,
156 /// Introduced binding.
157 bind: BindingName,
158 },
159 /// Bounded literal rows.
160 Values {
161 /// Introduced binding.
162 bind: BindingName,
163 /// Declared row type.
164 row_type: RowType,
165 /// Rows.
166 rows: Vec<Row>,
167 },
168 /// Projection.
169 Project {
170 /// Input.
171 input: Box<Rel>,
172 /// Introduced output binding.
173 bind: BindingName,
174 /// Fields.
175 fields: Vec<NamedScalar>,
176 },
177 /// Predicate filter.
178 Filter {
179 /// Input.
180 input: Box<Rel>,
181 /// Boolean predicate.
182 predicate: Scalar,
183 },
184 /// Binary join.
185 Join {
186 /// Left relation.
187 left: Box<Rel>,
188 /// Right relation.
189 right: Box<Rel>,
190 /// Kind.
191 kind: JoinKind,
192 /// Boolean condition; ignored only for cross joins.
193 on: Scalar,
194 },
195 /// Grouped projection.
196 Group {
197 /// Input.
198 input: Box<Rel>,
199 /// Introduced output binding.
200 bind: BindingName,
201 /// Group keys.
202 keys: Vec<NamedScalar>,
203 /// Aggregates.
204 aggregates: Vec<NamedAggregate>,
205 /// Post-aggregate predicate.
206 having: Option<Scalar>,
207 },
208 /// Compatible set operation.
209 Set {
210 /// Operation.
211 op: SetOp,
212 /// Two or more inputs.
213 inputs: Vec<Rel>,
214 },
215 /// Duplicate elimination.
216 Distinct(Box<Rel>),
217 /// Stable ordering.
218 Order {
219 /// Input.
220 input: Box<Rel>,
221 /// Ordering keys.
222 keys: Vec<OrderKey>,
223 },
224 /// Bounded result window.
225 Limit {
226 /// Input.
227 input: Box<Rel>,
228 /// Optional maximum rows.
229 count: Option<u64>,
230 /// Rows skipped.
231 offset: u64,
232 },
233}
234
235/// A uniqueness target for insert conflicts.
236#[derive(Clone, Debug, PartialEq, Eq)]
237pub enum ConflictTarget {
238 /// Primary key.
239 PrimaryKey,
240 /// Named unique constraint.
241 UniqueConstraint(ConstraintName),
242 /// Exact unique column sequence.
243 Columns(Vec<ColumnName>),
244}
245/// Complete conflict behavior.
246#[derive(Clone, Debug, PartialEq, Eq)]
247pub enum ConflictAction {
248 /// Raise conflict.
249 Fail,
250 /// Ignore a matching row.
251 DoNothing {
252 /// Unique target.
253 target: ConflictTarget,
254 },
255 /// Update a matching row.
256 DoUpdate {
257 /// Unique target.
258 target: ConflictTarget,
259 /// Assignments.
260 assignments: Vec<(ColumnName, Scalar)>,
261 /// Optional update predicate.
262 predicate: Option<Scalar>,
263 },
264}
265/// Provider-neutral data mutation.
266#[derive(Clone, Debug, PartialEq, Eq)]
267pub enum Mutation {
268 /// Insert rows produced by a relation.
269 Insert {
270 /// Target table.
271 table: TableName,
272 /// Populated columns in input order.
273 columns: Vec<ColumnName>,
274 /// Row-producing input.
275 input: Box<Rel>,
276 /// Conflict behavior.
277 conflict: ConflictAction,
278 /// Returned expressions.
279 returning: Vec<NamedScalar>,
280 },
281 /// Update matching rows.
282 Update {
283 /// Target table.
284 table: TableName,
285 /// Target binding.
286 bind: BindingName,
287 /// Assignments.
288 assignments: Vec<(ColumnName, Scalar)>,
289 /// Optional filter.
290 predicate: Option<Scalar>,
291 /// Returned expressions.
292 returning: Vec<NamedScalar>,
293 },
294 /// Delete matching rows.
295 Delete {
296 /// Target table.
297 table: TableName,
298 /// Target binding.
299 bind: BindingName,
300 /// Optional filter.
301 predicate: Option<Scalar>,
302 /// Returned expressions.
303 returning: Vec<NamedScalar>,
304 },
305}
306
307/// Admission resource limits.
308#[derive(Clone, Copy, Debug, PartialEq, Eq)]
309pub struct AdmissionLimits {
310 /// Maximum literal rows in one Values node.
311 pub max_literal_rows: usize,
312}
313impl Default for AdmissionLimits {
314 fn default() -> Self {
315 Self {
316 max_literal_rows: 1024,
317 }
318 }
319}
320/// Plan admission failure.
321#[derive(Clone, Debug, PartialEq, Eq)]
322pub enum AdmissionError {
323 /// Unknown table.
324 UnknownTable(TableName),
325 /// Unknown binding.
326 UnresolvedBinding(BindingName),
327 /// Binding shadows a live binding.
328 AmbiguousBinding(BindingName),
329 /// Unknown field.
330 UnresolvedField(FieldRef),
331 /// Parameter was not declared.
332 UnresolvedParameter(ParameterName),
333 /// Domain mismatch or unsupported operator.
334 TypeError(&'static str),
335 /// Aggregate appears outside aggregate position or grouping is invalid.
336 IllegalAggregateScope,
337 /// Set inputs disagree.
338 IncompatibleSet,
339 /// Scalar subquery does not return one field.
340 ScalarQueryArity,
341 /// Conflict target is not unique.
342 UnsafeConflictTarget,
343 /// Insert omits a required field.
344 MissingRequiredInsertField(ColumnName),
345 /// Literal rows exceed policy.
346 LiteralRowLimit {
347 /// Configured bound.
348 limit: usize,
349 /// Supplied rows.
350 actual: usize,
351 },
352 /// Duplicate output or assignment name.
353 DuplicateName,
354}
355impl fmt::Display for AdmissionError {
356 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
357 write!(f, "{self:?}")
358 }
359}
360impl std::error::Error for AdmissionError {}
361
362/// Opaque admitted query. Its fields cannot be forged or changed by providers.
363#[derive(Clone, Debug)]
364pub struct CheckedQuery {
365 pub(crate) schema_id: RelationId,
366 pub(crate) catalog_id: RelationId,
367 pub(crate) parameters: RowType,
368 pub(crate) output: RowType,
369 pub(crate) plan_id: RelationId,
370 pub(crate) raw: Rel,
371}
372impl CheckedQuery {
373 /// Schema identity used for admission.
374 pub fn schema_id(&self) -> &RelationId {
375 &self.schema_id
376 }
377 /// Domain catalog identity.
378 pub fn catalog_id(&self) -> &RelationId {
379 &self.catalog_id
380 }
381 /// Ordered parameter contract.
382 pub fn parameters(&self) -> &RowType {
383 &self.parameters
384 }
385 /// Output row contract.
386 pub fn output(&self) -> &RowType {
387 &self.output
388 }
389 /// Canonical plan identity.
390 pub fn plan_id(&self) -> &RelationId {
391 &self.plan_id
392 }
393 /// Read-only logical plan for codecs/providers.
394 pub fn plan(&self) -> &Rel {
395 &self.raw
396 }
397}
398/// Opaque admitted mutation.
399#[derive(Clone, Debug)]
400pub struct CheckedMutation {
401 pub(crate) schema_id: RelationId,
402 pub(crate) catalog_id: RelationId,
403 pub(crate) parameters: RowType,
404 pub(crate) output: RowType,
405 pub(crate) plan_id: RelationId,
406 pub(crate) raw: Mutation,
407}
408impl CheckedMutation {
409 /// Schema identity used for admission.
410 pub fn schema_id(&self) -> &RelationId {
411 &self.schema_id
412 }
413 /// Domain catalog identity.
414 pub fn catalog_id(&self) -> &RelationId {
415 &self.catalog_id
416 }
417 /// Parameter contract.
418 pub fn parameters(&self) -> &RowType {
419 &self.parameters
420 }
421 /// Returned row contract.
422 pub fn output(&self) -> &RowType {
423 &self.output
424 }
425 /// Canonical plan identity.
426 pub fn plan_id(&self) -> &RelationId {
427 &self.plan_id
428 }
429 /// Read-only mutation.
430 pub fn plan(&self) -> &Mutation {
431 &self.raw
432 }
433}