Skip to main content

gluesql_core/plan/statement/query/
offset.rs

1use {
2    super::{DistinctPlan, ProjectPlan, SelectOrderByPlan, ValuesOrderByPlan, ValuesPlan},
3    crate::plan::ExprPlan,
4    serde::{Deserialize, Serialize},
5};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct OffsetPlan {
9    pub input: OffsetInputPlan,
10    pub count: ExprPlan,
11}
12
13impl OffsetPlan {
14    pub(super) fn project(&self) -> Option<&ProjectPlan> {
15        match &self.input {
16            OffsetInputPlan::Project(project) => Some(project),
17            OffsetInputPlan::Values(_) | OffsetInputPlan::ValuesOrderBy(_) => None,
18            OffsetInputPlan::SelectOrderBy(order_by) => Some(&order_by.input),
19            OffsetInputPlan::Distinct(distinct) => Some(distinct.project()),
20        }
21    }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub enum OffsetInputPlan {
26    Project(ProjectPlan),
27    Values(ValuesPlan),
28    SelectOrderBy(SelectOrderByPlan),
29    ValuesOrderBy(ValuesOrderByPlan),
30    Distinct(DistinctPlan),
31}
32
33#[cfg(test)]
34mod tests {
35    use {
36        super::{OffsetInputPlan, OffsetPlan},
37        crate::{
38            ast::Literal,
39            plan::{ExprPlan, ValuesPlan},
40        },
41    };
42
43    fn count(value: i64) -> ExprPlan {
44        ExprPlan::Literal(Literal::Number(value.into()))
45    }
46
47    #[test]
48    fn offset_accepts_values_input() {
49        let plan = OffsetPlan {
50            input: OffsetInputPlan::Values(ValuesPlan(Vec::new())),
51            count: count(2),
52        };
53
54        assert!(matches!(
55            plan,
56            OffsetPlan {
57                input: OffsetInputPlan::Values(_),
58                count: actual,
59            } if actual == count(2)
60        ));
61    }
62}