use super::base::parse_identifier;
use super::expressions::parse_expression;
use crate::ast::*;
use nom::{
IResult, Parser,
branch::alt,
bytes::complete::tag_no_case,
character::complete::{char, multispace0, multispace1},
combinator::{map, opt},
sequence::preceded,
};
pub fn parse_join_clause(input: &str) -> IResult<&str, Join> {
let (input, kind) = alt((
map(
(tag_no_case("left"), multispace1, tag_no_case("join")),
|_| JoinKind::Left,
),
map(
(tag_no_case("right"), multispace1, tag_no_case("join")),
|_| JoinKind::Right,
),
map(
(tag_no_case("inner"), multispace1, tag_no_case("join")),
|_| JoinKind::Inner,
),
map(tag_no_case("join"), |_| JoinKind::Left),
))
.parse(input)?;
let (input, _) = multispace1(input)?;
let (input, table) = parse_identifier(input)?;
let (input, _) = multispace0(input)?;
let (input, on_true_result) =
opt((tag_no_case("on"), multispace1, tag_no_case("true"))).parse(input)?;
let (input, on_clause, on_true) = if on_true_result.is_some() {
(input, None, true)
} else {
let (input, cond) = opt(preceded(
(tag_no_case("on"), multispace1),
parse_join_condition,
))
.parse(input)?;
(input, cond, false)
};
let (input, _) = multispace0(input)?;
Ok((
input,
Join {
table: table.to_string(),
kind,
on: on_clause,
on_true,
},
))
}
pub fn parse_join_condition(input: &str) -> IResult<&str, Vec<Condition>> {
let (input, left_expr) = parse_expression(input)?;
let (input, _) = multispace0(input)?;
let (input, _) = char('=').parse(input)?;
let (input, _) = multispace0(input)?;
let (input, right_col) = parse_identifier(input)?;
Ok((
input,
vec![Condition {
left: left_expr, op: Operator::Eq,
value: Value::Column(right_col.to_string()),
is_array_unnest: false,
}],
))
}