risingwave_frontend/binder/expr/
binary_op.rs1use risingwave_common::bail_not_implemented;
16use risingwave_common::types::{DataType, JsonbVal};
17use risingwave_sqlparser::ast::{BinaryOperator, Expr};
18
19use crate::binder::Binder;
20use crate::error::{ErrorCode, Result};
21use crate::expr::{Expr as _, ExprImpl, ExprType, FunctionCall};
22
23impl Binder {
24 pub(super) fn bind_binary_op(
25 &mut self,
26 left: &Expr,
27 op: &BinaryOperator,
28 mut right: &Expr,
29 ) -> Result<ExprImpl> {
30 let bound_left = self.bind_expr_inner(left)?;
31
32 let mut func_types = vec![];
33
34 right = match right {
35 Expr::SomeOp(expr) => {
36 func_types.push(ExprType::Some);
37 expr
38 }
39 Expr::AllOp(expr) => {
40 func_types.push(ExprType::All);
41 expr
42 }
43 right => right,
44 };
45
46 let bound_right = self.bind_expr_inner(right)?;
47
48 if let BinaryOperator::Custom(name) = &op
49 && matches!(name.as_str(), "@?" | "@@")
50 {
51 return Ok(FunctionCall::new_unchecked(
54 match name.as_str() {
55 "@?" => ExprType::JsonbPathExists,
56 "@@" => ExprType::JsonbPathMatch,
57 _ => unreachable!(),
58 },
59 vec![
60 bound_left,
61 bound_right,
62 ExprImpl::literal_jsonb(JsonbVal::empty_object()), ExprImpl::literal_bool(true), ],
65 DataType::Boolean,
66 )
67 .into());
68 }
69
70 func_types.extend(Self::resolve_binary_operator(
71 op,
72 &bound_left,
73 &bound_right,
74 )?);
75
76 FunctionCall::new_binary_op_func(func_types, vec![bound_left, bound_right])
77 }
78
79 fn resolve_binary_operator(
80 op: &BinaryOperator,
81 bound_left: &ExprImpl,
82 bound_right: &ExprImpl,
83 ) -> Result<Vec<ExprType>> {
84 let mut func_types = vec![];
85 let final_type = match op {
86 BinaryOperator::Plus => ExprType::Add,
87 BinaryOperator::Minus => ExprType::Subtract,
88 BinaryOperator::Multiply => ExprType::Multiply,
89 BinaryOperator::Divide => ExprType::Divide,
90 BinaryOperator::Modulo => ExprType::Modulus,
91 BinaryOperator::NotEq => ExprType::NotEqual,
92 BinaryOperator::Eq => ExprType::Equal,
93 BinaryOperator::Lt => ExprType::LessThan,
94 BinaryOperator::LtEq => ExprType::LessThanOrEqual,
95 BinaryOperator::Gt => ExprType::GreaterThan,
96 BinaryOperator::GtEq => ExprType::GreaterThanOrEqual,
97 BinaryOperator::And => ExprType::And,
98 BinaryOperator::Or => ExprType::Or,
99 BinaryOperator::Pow => ExprType::Pow,
100 BinaryOperator::Custom(name) if name == "@>" => {
101 let left_type = (!bound_left.is_untyped()).then(|| bound_left.return_type());
102 let right_type = (!bound_right.is_untyped()).then(|| bound_right.return_type());
103 match (left_type, right_type) {
104 (Some(DataType::List { .. }), Some(DataType::List { .. }))
105 | (Some(DataType::List { .. }), None)
106 | (None, Some(DataType::List { .. })) => ExprType::ArrayContains,
107 (Some(DataType::Jsonb), Some(DataType::Jsonb))
108 | (Some(DataType::Jsonb), None)
109 | (None, Some(DataType::Jsonb)) => ExprType::JsonbContains,
110 (left, right) => {
111 return Err(ErrorCode::BindError(format!(
112 "operator does not exist: {} @> {}",
113 left.map_or_else(|| String::from("unknown"), |x| x.to_string()),
114 right.map_or_else(|| String::from("unknown"), |x| x.to_string()),
115 ))
116 .into());
117 }
118 }
119 }
120 BinaryOperator::Custom(name) if name == "<@" => {
121 let left_type = (!bound_left.is_untyped()).then(|| bound_left.return_type());
122 let right_type = (!bound_right.is_untyped()).then(|| bound_right.return_type());
123 match (left_type, right_type) {
124 (Some(DataType::List { .. }), Some(DataType::List { .. }))
125 | (Some(DataType::List { .. }), None)
126 | (None, Some(DataType::List { .. })) => ExprType::ArrayContained,
127 (Some(DataType::Jsonb), Some(DataType::Jsonb))
128 | (Some(DataType::Jsonb), None)
129 | (None, Some(DataType::Jsonb)) => ExprType::JsonbContained,
130 (left, right) => {
131 return Err(ErrorCode::BindError(format!(
132 "operator does not exist: {} <@ {}",
133 left.map_or_else(|| String::from("unknown"), |x| x.to_string()),
134 right.map_or_else(|| String::from("unknown"), |x| x.to_string()),
135 ))
136 .into());
137 }
138 }
139 }
140 BinaryOperator::Custom(name) if name == "&&" => {
141 let left_type = (!bound_left.is_untyped()).then(|| bound_left.return_type());
142 let right_type = (!bound_right.is_untyped()).then(|| bound_right.return_type());
143 match (left_type, right_type) {
144 (Some(DataType::List { .. }), Some(DataType::List { .. }))
145 | (Some(DataType::List { .. }), None)
146 | (None, Some(DataType::List { .. })) => ExprType::ArrayOverlaps,
147 (left, right) => {
148 return Err(ErrorCode::BindError(format!(
149 "operator does not exist: {} && {}",
150 left.map_or_else(|| String::from("unknown"), |x| x.to_string()),
151 right.map_or_else(|| String::from("unknown"), |x| x.to_string()),
152 ))
153 .into());
154 }
155 }
156 }
157 BinaryOperator::Custom(name) if name == "||" => {
158 let left_type = (!bound_left.is_untyped()).then(|| bound_left.return_type());
159 let right_type = (!bound_right.is_untyped()).then(|| bound_right.return_type());
160 match (left_type, right_type) {
167 (Some(DataType::List { .. }), Some(DataType::List { .. }))
169 | (Some(DataType::List { .. }), None)
170 | (None, Some(DataType::List { .. })) => ExprType::ArrayCat,
171 (Some(DataType::List { .. }), Some(_)) => ExprType::ArrayAppend,
172 (Some(_), Some(DataType::List { .. })) => ExprType::ArrayPrepend,
173
174 (Some(DataType::Varchar), _) | (_, Some(DataType::Varchar)) => {
176 ExprType::ConcatOp
177 }
178
179 (Some(DataType::Jsonb), Some(DataType::Jsonb))
181 | (Some(DataType::Jsonb), None)
182 | (None, Some(DataType::Jsonb)) => ExprType::JsonbConcat,
183
184 (Some(DataType::Bytea), Some(DataType::Bytea))
186 | (Some(DataType::Bytea), None)
187 | (None, Some(DataType::Bytea)) => ExprType::ByteaConcatOp,
188
189 (Some(DataType::Vector(_)), Some(DataType::Vector(_)))
191 | (Some(DataType::Vector(_)), None)
192 | (None, Some(DataType::Vector(_))) => ExprType::VecConcat,
193
194 (None, _) | (_, None) => ExprType::ConcatOp,
199
200 (Some(left_type), Some(right_type)) => {
202 return Err(ErrorCode::BindError(format!(
203 "operator does not exist: {} || {}",
204 left_type, right_type
205 ))
206 .into());
207 }
208 }
209 }
210 BinaryOperator::Custom(name) => match name.as_str() {
211 "&" => ExprType::BitwiseAnd,
213 "|" => ExprType::BitwiseOr,
214 "#" => ExprType::BitwiseXor,
215 "<<" => ExprType::BitwiseShiftLeft,
216 ">>" => ExprType::BitwiseShiftRight,
217 "^@" => ExprType::StartsWith,
219 "~" => ExprType::RegexpEq,
220 "~~" => ExprType::Like,
221 "~~*" => ExprType::ILike,
222 "!~" => {
223 func_types.push(ExprType::Not);
224 ExprType::RegexpEq
225 }
226 "!~~" => {
227 func_types.push(ExprType::Not);
228 ExprType::Like
229 }
230 "!~~*" => {
231 func_types.push(ExprType::Not);
232 ExprType::ILike
233 }
234 "->" => ExprType::JsonbAccess,
236 "->>" => ExprType::JsonbAccessStr,
237 "#-" => ExprType::JsonbDeletePath,
238 "#>" => ExprType::JsonbExtractPathVariadic,
239 "#>>" => ExprType::JsonbExtractPathTextVariadic,
240 "?" => ExprType::JsonbExists,
241 "?|" => ExprType::JsonbExistsAny,
242 "?&" => ExprType::JsonbExistsAll,
243 "<->" => ExprType::L2Distance,
245 "<=>" => ExprType::CosineDistance,
246 "<+>" => ExprType::L1Distance,
247 "<#>" => {
248 func_types.push(ExprType::Neg);
249 ExprType::InnerProduct
250 }
251 _ => bail_not_implemented!(issue = 112, "binary op: {:?}", name),
252 },
253 BinaryOperator::Xor | BinaryOperator::PGQualified(_) => {
254 bail_not_implemented!(issue = 112, "binary op: {:?}", op)
255 }
256 };
257 func_types.push(final_type);
258 Ok(func_types)
259 }
260}