Skip to main content

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}