@@ -2023,19 +2023,35 @@ fn parse_is_distinct_from_precedence() {
20232023 );
20242024
20252025 // `AND` binds tighter than `OR` within the surrounding expression.
2026- assert_matches!(
2027- verified_expr("a IS DISTINCT FROM 1 AND b OR c"),
2026+ assert_eq!(
20282027 BinaryOp {
2028+ left: Box::new(BinaryOp {
2029+ left: Box::new(IsDistinctFrom(
2030+ Box::new(Identifier(Ident::new("a"))),
2031+ Box::new(Expr::value(number("1"))),
2032+ )),
2033+ op: BinaryOperator::And,
2034+ right: Box::new(Identifier(Ident::new("b"))),
2035+ }),
20292036 op: BinaryOperator::Or,
2030- ..
2031- }
2037+ right: Box::new(Identifier(Ident::new("c"))),
2038+ },
2039+ verified_expr("a IS DISTINCT FROM 1 AND b OR c")
20322040 );
2033- assert_matches!(
2034- verified_expr("a IS DISTINCT FROM 1 OR b AND c"),
2041+ assert_eq!(
20352042 BinaryOp {
2043+ left: Box::new(IsDistinctFrom(
2044+ Box::new(Identifier(Ident::new("a"))),
2045+ Box::new(Expr::value(number("1"))),
2046+ )),
20362047 op: BinaryOperator::Or,
2037- ..
2038- }
2048+ right: Box::new(BinaryOp {
2049+ left: Box::new(Identifier(Ident::new("b"))),
2050+ op: BinaryOperator::And,
2051+ right: Box::new(Identifier(Ident::new("c"))),
2052+ }),
2053+ },
2054+ verified_expr("a IS DISTINCT FROM 1 OR b AND c")
20392055 );
20402056
20412057 // Explicit parentheses still push the boolean expression into the right operand.
@@ -2074,6 +2090,89 @@ fn parse_is_distinct_from_precedence() {
20742090 ),
20752091 verified_expr("a IS DISTINCT FROM b + 1")
20762092 );
2093+
2094+ assert_eq!(
2095+ IsDistinctFrom(
2096+ Box::new(Identifier(Ident::new("a"))),
2097+ Box::new(BinaryOp {
2098+ left: Box::new(Identifier(Ident::new("b"))),
2099+ op: BinaryOperator::Eq,
2100+ right: Box::new(Identifier(Ident::new("c"))),
2101+ }),
2102+ ),
2103+ verified_expr("a IS DISTINCT FROM b = c")
2104+ );
2105+
2106+ // `NOT` binds more loosely than `IS`, so it applies to the whole comparison.
2107+ assert_eq!(
2108+ UnaryOp {
2109+ op: UnaryOperator::Not,
2110+ expr: Box::new(IsDistinctFrom(
2111+ Box::new(Identifier(Ident::new("a"))),
2112+ Box::new(Identifier(Ident::new("b"))),
2113+ )),
2114+ },
2115+ verified_expr("NOT a IS DISTINCT FROM b")
2116+ );
2117+
2118+ assert_eq!(
2119+ BinaryOp {
2120+ left: Box::new(IsNotDistinctFrom(
2121+ Box::new(Identifier(Ident::new("a"))),
2122+ Box::new(Identifier(Ident::new("b"))),
2123+ )),
2124+ op: BinaryOperator::And,
2125+ right: Box::new(IsNotDistinctFrom(
2126+ Box::new(Identifier(Ident::new("c"))),
2127+ Box::new(Identifier(Ident::new("d"))),
2128+ )),
2129+ },
2130+ verified_expr("a IS NOT DISTINCT FROM b AND c IS NOT DISTINCT FROM d")
2131+ );
2132+ }
2133+
2134+ #[test]
2135+ fn parse_pg_other_operator_precedence() {
2136+ let arrow_k = |left: Expr| Expr::BinaryOp {
2137+ left: Box::new(left),
2138+ op: BinaryOperator::Arrow,
2139+ right: Box::new(Expr::Value(
2140+ Value::SingleQuotedString("k".into()).with_empty_span(),
2141+ )),
2142+ };
2143+ let t_a = || Expr::CompoundIdentifier(vec![Ident::new("t"), Ident::new("a")]);
2144+
2145+ // `->` binds tighter than comparison operators, so the arrow expression is
2146+ // the left operand rather than the comparison being the arrow's key.
2147+ let expected_eq = |left: Expr| Expr::BinaryOp {
2148+ left: Box::new(arrow_k(left)),
2149+ op: BinaryOperator::Eq,
2150+ right: Box::new(Identifier(Ident::new("b"))),
2151+ };
2152+
2153+ // Dialects with lambda functions read a bare `a ->` as the start of a lambda.
2154+ assert_eq!(
2155+ expected_eq(Identifier(Ident::new("a"))),
2156+ all_dialects_where(|d| !d.supports_lambda_functions()).verified_expr("a -> 'k' = b")
2157+ );
2158+ assert_eq!(
2159+ expected_eq(t_a()),
2160+ all_dialects().verified_expr("t.a -> 'k' = b")
2161+ );
2162+
2163+ // `LIKE` sits below `=` in the precedence table, so cover that boundary too.
2164+ assert_eq!(
2165+ Expr::Like {
2166+ negated: false,
2167+ any: false,
2168+ expr: Box::new(arrow_k(t_a())),
2169+ pattern: Box::new(Expr::Value(
2170+ Value::SingleQuotedString("x".into()).with_empty_span(),
2171+ )),
2172+ escape_char: None,
2173+ },
2174+ all_dialects().verified_expr("t.a -> 'k' LIKE 'x'")
2175+ );
20772176}
20782177
20792178#[test]
0 commit comments