mangle_ir/physical.rs
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Physical Plan IR for Mangle.
16//!
17//! This represents the imperative execution logic (loops, joins, inserts)
18//! derived from the declarative logical IR.
19
20use crate::{NameId, StringId};
21
22#[derive(Debug, Clone, PartialEq)]
23pub enum Op {
24 /// A no-op.
25 Nop,
26
27 /// Sequence of operations executed in order.
28 Seq(Vec<Op>),
29
30 /// Iterate over a data source.
31 /// For each tuple yielded by `source`, `body` is executed.
32 /// Variables defined in `source` are bound and available in `body`.
33 Iterate { source: DataSource, body: Box<Op> },
34
35 /// Filter / Check condition.
36 /// If `cond` evaluates to true, `body` is executed.
37 Filter { cond: Condition, body: Box<Op> },
38
39 /// Insert a tuple into a relation.
40 /// All variables in `args` must be bound.
41 Insert {
42 relation: NameId,
43 args: Vec<Operand>,
44 },
45
46 /// Calculate a value and bind it to a variable.
47 /// `let var = expr`
48 Let {
49 var: NameId,
50 expr: Expr,
51 body: Box<Op>,
52 },
53
54 /// GroupBy operation.
55 /// Scans `source` (binding columns to `vars`), groups by `keys`, computes `aggregates`
56 /// for each group, and then executes `body` for each group.
57 GroupBy {
58 source: NameId, // Relation to scan
59 vars: Vec<NameId>, // Variables to bind to source columns
60 keys: Vec<NameId>, // Variables to group by (must be in `vars` or previously bound?)
61 // Typically `keys` are subset of `vars`.
62 aggregates: Vec<Aggregate>,
63 body: Box<Op>,
64 },
65}
66
67#[derive(Debug, Clone, PartialEq)]
68pub struct Aggregate {
69 pub var: NameId,
70 pub func: NameId,
71 pub args: Vec<Operand>,
72}
73
74#[derive(Debug, Clone, PartialEq)]
75pub enum DataSource {
76 /// Scan a relation (iterate over all tuples).
77 /// Binds the variables in `vars` to the columns of the relation.
78 Scan { relation: NameId, vars: Vec<NameId> },
79
80 /// Scan only the "delta" set of a relation (new facts from last iteration).
81 ScanDelta { relation: NameId, vars: Vec<NameId> },
82
83 /// Lookup in an index.
84 /// `col_idx`: The column index to lookup on.
85 /// `key`: The value to look up.
86 /// `vars`: Variables to bind to the *other* columns (or all columns?).
87 /// For simplicity: `vars` maps to the relation columns. The column at `col_idx`
88 /// is already bound (to `key`), but we might re-bind it or check it.
89 IndexLookup {
90 relation: NameId,
91 col_idx: usize,
92 key: Operand,
93 vars: Vec<NameId>,
94 },
95}
96
97#[derive(Debug, Clone, Copy, PartialEq)]
98pub enum CmpOp {
99 Eq,
100 Neq,
101 Lt,
102 Le,
103 Gt,
104 Ge,
105}
106
107#[derive(Debug, Clone, PartialEq)]
108pub enum Condition {
109 /// Comparison of two operands.
110 Cmp {
111 op: CmpOp,
112 left: Operand,
113 right: Operand,
114 },
115 /// Negation check: !exists(...)
116 Negation {
117 relation: NameId,
118 args: Vec<Operand>,
119 },
120 /// Call to a boolean function / predicate (e.g. starts_with).
121 Call {
122 function: NameId,
123 args: Vec<Operand>,
124 },
125}
126
127#[derive(Debug, Clone, PartialEq)]
128pub enum Expr {
129 // Basic value
130 Value(Operand),
131 // Function call (arithmetic or built-in)
132 Call {
133 function: NameId,
134 args: Vec<Operand>,
135 },
136}
137
138#[derive(Debug, Clone, PartialEq)]
139pub enum Operand {
140 Var(NameId),
141 Const(Constant),
142}
143
144#[derive(Clone, Debug, PartialEq)]
145pub enum Constant {
146 Number(i64),
147 Float(f64),
148 String(StringId),
149 Name(NameId),
150 Time(i64),
151 Duration(i64),
152}