Skip to main content

sql_fun_sqlast/sem/data_source/
join_kind.rs

1use crate::{
2    sem::{AnalysisError, Nullable},
3    syn::{JoinType, JoinTypeOpt, Opt},
4};
5
6/// table join kind
7#[derive(Debug, Clone, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
8pub enum JoinKind {
9    /// inner join
10    Inner,
11    /// left outer join
12    Left,
13    /// right outer join
14    Right,
15    /// cross join
16    Full,
17    /// semi join  (may be not use in SQL syntax)
18    Semi,
19    /// anti join  (may be not use in SQL syntax)
20    Anti,
21    /// right anti join  (may be not use in SQL syntax)
22    RightAnti,
23    /// unique inner join  (may be not use in SQL syntax)
24    UniqueInner,
25    /// unique outer join  (may be not use in SQL syntax)
26    UniqueOuter,
27}
28
29impl TryFrom<JoinTypeOpt> for JoinKind {
30    type Error = AnalysisError;
31
32    fn try_from(value: JoinTypeOpt) -> Result<Self, Self::Error> {
33        let Some(join_ty) = value.as_inner() else {
34            AnalysisError::raise_unexpected_none("join_type")?
35        };
36        match join_ty {
37            JoinType::JoinInner => Ok(Self::Inner),
38            JoinType::JoinLeft => Ok(Self::Left),
39            JoinType::JoinFull => Ok(Self::Full),
40            JoinType::JoinRight => Ok(Self::Right),
41            JoinType::JoinSemi => Ok(Self::Semi),
42            JoinType::JoinAnti => Ok(Self::Anti),
43            JoinType::JoinRightAnti => Ok(Self::RightAnti),
44            JoinType::JoinUniqueOuter => Ok(Self::UniqueOuter),
45            JoinType::JoinUniqueInner => Ok(Self::UniqueInner),
46            JoinType::Undefined | JoinType::OptionNone => {
47                AnalysisError::raise_unexpected_none("join_type")?
48            }
49        }
50    }
51}
52
53impl JoinKind {
54    /// get left nullability
55    #[must_use]
56    pub fn left_nullable(&self, in_nullable: Nullable) -> Nullable {
57        match self {
58            JoinKind::Inner => in_nullable,
59            JoinKind::Left => in_nullable,
60            JoinKind::Right => true,
61            JoinKind::Full => true,
62            JoinKind::Semi => in_nullable,
63            JoinKind::Anti => in_nullable,
64            JoinKind::RightAnti => false,
65            JoinKind::UniqueInner => in_nullable,
66            JoinKind::UniqueOuter => true,
67        }
68    }
69
70    /// get right nullability
71    #[must_use]
72    pub fn right_nullable(&self, in_nullable: Nullable) -> Nullable {
73        match self {
74            JoinKind::Inner => in_nullable,
75            JoinKind::Left => true,
76            JoinKind::Right => in_nullable,
77            JoinKind::Full => true,
78            JoinKind::Semi => in_nullable,
79            JoinKind::Anti => in_nullable,
80            JoinKind::RightAnti => false,
81            JoinKind::UniqueInner => in_nullable,
82            JoinKind::UniqueOuter => true,
83        }
84    }
85}