1use std::slice;
16
17use itertools::Itertools;
18use risingwave_common::catalog::PG_CATALOG_SCHEMA_NAME;
19use risingwave_common::types::{DataType, MapType, StructType};
20use risingwave_common::util::iter_util::zip_eq_fast;
21use risingwave_common::{bail_no_function, bail_not_implemented, not_implemented};
22use risingwave_sqlparser::ast::{
23 Array, BinaryOperator, DataType as AstDataType, EscapeChar, Expr, Function, JsonPredicateType,
24 ObjectName, Query, TrimWhereField, UnaryOperator,
25};
26
27use crate::binder::Binder;
28use crate::binder::expr::function::is_sys_function_without_args;
29use crate::error::{ErrorCode, Result, RwError};
30use crate::expr::{
31 Expr as _, ExprImpl, ExprRewriter as _, ExprType, FunctionCall, InputRef,
32 InputRefDepthRewriter, Parameter, SubqueryKind,
33};
34
35mod binary_op;
36mod column;
37mod function;
38mod order_by;
39mod subquery;
40mod value;
41
42const CASE_WHEN_ARMS_OPTIMIZE_LIMIT: usize = 30;
48
49impl Binder {
50 pub fn bind_expr(&mut self, expr: &Expr) -> Result<ExprImpl> {
58 self.bind_expr_inner(expr).map_err(|e| {
59 RwError::from(ErrorCode::BindErrorRoot {
60 expr: expr.to_string(),
61 error: Box::new(e),
62 })
63 })
64 }
65
66 fn bind_expr_inner(&mut self, expr: &Expr) -> Result<ExprImpl> {
67 match expr {
68 Expr::Value(v) => Ok(ExprImpl::Literal(Box::new(self.bind_value(v)?))),
70 Expr::TypedString { data_type, value } => {
71 let s: ExprImpl = self.bind_string(value)?.into();
72 s.cast_explicit(&bind_data_type(data_type)?)
73 .map_err(Into::into)
74 }
75 Expr::Row(exprs) => self.bind_row(exprs),
76 Expr::Identifier(ident) => {
78 if is_sys_function_without_args(ident) {
79 self.bind_function(&Function::no_arg(ObjectName(vec![ident.clone()])))
84 } else if let Some(ref lambda_args) = self.context.lambda_args {
85 if let Some((arg_idx, arg_type)) = lambda_args.get(&ident.real_value()) {
88 Ok(InputRef::new(*arg_idx, arg_type.clone()).into())
89 } else {
90 Err(
91 ErrorCode::ItemNotFound(format!("Unknown arg: {}", ident.real_value()))
92 .into(),
93 )
94 }
95 } else if let Some(ctx) = self.secure_compare_context.as_ref() {
96 if ident.real_value() == *"headers" {
102 Ok(InputRef::new(0, DataType::Jsonb).into())
103 } else if ctx.secret_name.is_some()
104 && ident.real_value() == *ctx.secret_name.as_ref().unwrap()
105 {
106 Ok(InputRef::new(1, DataType::Varchar).into())
107 } else if ident.real_value() == ctx.payload_name {
108 Ok(InputRef::new(2, DataType::Bytea).into())
109 } else {
110 Err(
111 ErrorCode::ItemNotFound(format!("Unknown arg: {}", ident.real_value()))
112 .into(),
113 )
114 }
115 } else {
116 self.bind_column(slice::from_ref(ident))
117 }
118 }
119 Expr::CompoundIdentifier(idents) => self.bind_column(idents),
120 Expr::FieldIdentifier(field_expr, idents) => {
121 self.bind_single_field_column(field_expr, idents)
122 }
123 Expr::UnaryOp { op, expr } => self.bind_unary_expr(op, expr),
125 Expr::BinaryOp { left, op, right } => self.bind_binary_op(left, op, right),
126 Expr::Nested(expr) => self.bind_expr_inner(expr),
127 Expr::Array(Array { elem: exprs, .. }) => self.bind_array(exprs),
128 Expr::Index { obj, index } => self.bind_index(obj, index),
129 Expr::ArrayRangeIndex { obj, start, end } => {
130 self.bind_array_range_index(obj, start.as_deref(), end.as_deref())
131 }
132 Expr::Function(f) => self.bind_function(f),
133 Expr::Subquery(q) => self.bind_subquery_expr(q, SubqueryKind::Scalar),
134 Expr::Exists(q) => self.bind_subquery_expr(q, SubqueryKind::Existential),
135 Expr::InSubquery {
136 expr,
137 subquery,
138 negated,
139 } => self.bind_in_subquery(expr, subquery, *negated),
140 Expr::Cast { expr, data_type } => self.bind_cast(expr, data_type),
142 Expr::IsNull(expr) => self.bind_is_operator(ExprType::IsNull, expr),
143 Expr::IsNotNull(expr) => self.bind_is_operator(ExprType::IsNotNull, expr),
144 Expr::IsTrue(expr) => self.bind_is_operator(ExprType::IsTrue, expr),
145 Expr::IsNotTrue(expr) => self.bind_is_operator(ExprType::IsNotTrue, expr),
146 Expr::IsFalse(expr) => self.bind_is_operator(ExprType::IsFalse, expr),
147 Expr::IsNotFalse(expr) => self.bind_is_operator(ExprType::IsNotFalse, expr),
148 Expr::IsUnknown(expr) => self.bind_is_unknown(ExprType::IsNull, expr),
149 Expr::IsNotUnknown(expr) => self.bind_is_unknown(ExprType::IsNotNull, expr),
150 Expr::IsDistinctFrom(left, right) => self.bind_distinct_from(left, right),
151 Expr::IsNotDistinctFrom(left, right) => self.bind_not_distinct_from(left, right),
152 Expr::IsJson {
153 expr,
154 negated,
155 item_type,
156 unique_keys: false,
157 } => self.bind_is_json(expr, *negated, *item_type),
158 Expr::Case {
159 operand,
160 conditions,
161 results,
162 else_result,
163 } => self.bind_case(
164 operand.as_deref(),
165 conditions,
166 results,
167 else_result.as_deref(),
168 ),
169 Expr::Between {
170 expr,
171 negated,
172 low,
173 high,
174 } => self.bind_between(expr, *negated, low, high),
175 Expr::Like {
176 negated,
177 expr,
178 pattern,
179 escape_char,
180 } => self.bind_like(ExprType::Like, expr, *negated, pattern, *escape_char),
181 Expr::ILike {
182 negated,
183 expr,
184 pattern,
185 escape_char,
186 } => self.bind_like(ExprType::ILike, expr, *negated, pattern, *escape_char),
187 Expr::SimilarTo {
188 expr,
189 negated,
190 pattern,
191 escape_char,
192 } => self.bind_similar_to(expr, *negated, pattern, *escape_char),
193 Expr::InList {
194 expr,
195 list,
196 negated,
197 } => self.bind_in_list(expr, list, *negated),
198 Expr::Extract { field, expr } => self.bind_extract(field, expr),
200 Expr::AtTimeZone {
201 timestamp,
202 time_zone,
203 } => self.bind_at_time_zone(timestamp, time_zone),
204 Expr::Trim {
206 expr,
207 trim_where,
208 trim_what,
209 } => self.bind_trim(expr, trim_where.as_ref(), trim_what.as_deref()),
210 Expr::Substring {
211 expr,
212 substring_from,
213 substring_for,
214 } => self.bind_substring(expr, substring_from.as_deref(), substring_for.as_deref()),
215 Expr::Position { substring, string } => self.bind_position(substring, string),
216 Expr::Overlay {
217 expr,
218 new_substring,
219 start,
220 count,
221 } => self.bind_overlay(expr, new_substring, start, count.as_deref()),
222 Expr::Parameter { index } => self.bind_parameter(*index),
223 Expr::Collate { expr, collation } => self.bind_collate(expr, collation),
224 Expr::ArraySubquery(q) => self.bind_subquery_expr(q, SubqueryKind::Array),
225 Expr::Map { entries } => self.bind_map(entries),
226 Expr::IsJson {
227 unique_keys: true, ..
228 }
229 | Expr::SomeOp(_)
230 | Expr::AllOp(_)
231 | Expr::TryCast { .. }
232 | Expr::GroupingSets(_)
233 | Expr::Cube(_)
234 | Expr::Rollup(_)
235 | Expr::LambdaFunction { .. } => {
236 bail_not_implemented!(issue = 112, "unsupported expression {:?}", expr)
237 }
238 }
239 }
240
241 pub(super) fn bind_extract(&mut self, field: &String, expr: &Expr) -> Result<ExprImpl> {
242 let arg = self.bind_expr_inner(expr)?;
243 let arg_type = arg.return_type();
244 Ok(FunctionCall::new(
245 ExprType::Extract,
246 vec![self.bind_string(field)?.into(), arg],
247 )
248 .map_err(|_| {
249 not_implemented!(
250 issue = 112,
251 "function extract({} from {:?}) doesn't exist",
252 field,
253 arg_type
254 )
255 })?
256 .into())
257 }
258
259 pub(super) fn bind_at_time_zone(&mut self, input: &Expr, time_zone: &Expr) -> Result<ExprImpl> {
260 let input = self.bind_expr_inner(input)?;
261 let time_zone = self.bind_expr_inner(time_zone)?;
262 FunctionCall::new(ExprType::AtTimeZone, vec![input, time_zone]).map(Into::into)
263 }
264
265 pub(super) fn bind_in_list(
266 &mut self,
267 expr: &Expr,
268 list: &[Expr],
269 negated: bool,
270 ) -> Result<ExprImpl> {
271 let left = self.bind_expr_inner(expr)?;
272 let mut in_list_exprs = vec![left.clone()];
273 let mut non_const_exprs = vec![];
274 for elem in list {
275 let expr = self.bind_expr_inner(elem)?;
276 match expr.is_const() || matches!(&expr, ExprImpl::Parameter(_)) {
277 true => in_list_exprs.push(expr),
278 false => non_const_exprs.push(expr),
279 }
280 }
281
282 let mut ret = if in_list_exprs.len() == 1 {
283 None
284 } else {
285 Some(FunctionCall::new(ExprType::In, in_list_exprs)?.into())
286 };
287 for expr in non_const_exprs {
290 if let Some(inner_ret) = ret {
291 ret = Some(
292 FunctionCall::new(
293 ExprType::Or,
294 vec![
295 inner_ret,
296 FunctionCall::new(ExprType::Equal, vec![left.clone(), expr])?.into(),
297 ],
298 )?
299 .into(),
300 );
301 } else {
302 ret = Some(FunctionCall::new(ExprType::Equal, vec![left.clone(), expr])?.into());
303 }
304 }
305 if negated {
306 Ok(
307 FunctionCall::new_unchecked(ExprType::Not, vec![ret.unwrap()], DataType::Boolean)
308 .into(),
309 )
310 } else {
311 Ok(ret.unwrap())
312 }
313 }
314
315 pub(super) fn bind_in_subquery(
316 &mut self,
317 expr: &Expr,
318 subquery: &Query,
319 negated: bool,
320 ) -> Result<ExprImpl> {
321 let bound_expr = self.bind_expr_inner(expr)?;
322 let bound_subquery = self.bind_subquery_expr(subquery, SubqueryKind::In(bound_expr))?;
323 if negated {
324 Ok(
325 FunctionCall::new_unchecked(ExprType::Not, vec![bound_subquery], DataType::Boolean)
326 .into(),
327 )
328 } else {
329 Ok(bound_subquery)
330 }
331 }
332
333 pub(super) fn bind_is_json(
334 &mut self,
335 expr: &Expr,
336 negated: bool,
337 item_type: JsonPredicateType,
338 ) -> Result<ExprImpl> {
339 let mut args = vec![self.bind_expr_inner(expr)?];
340 let type_symbol = match item_type {
342 JsonPredicateType::Value => None,
343 JsonPredicateType::Array => Some("ARRAY"),
344 JsonPredicateType::Object => Some("OBJECT"),
345 JsonPredicateType::Scalar => Some("SCALAR"),
346 };
347 if let Some(s) = type_symbol {
348 args.push(ExprImpl::literal_varchar(s.into()));
349 }
350
351 let is_json = FunctionCall::new(ExprType::IsJson, args)?.into();
352 if negated {
353 Ok(FunctionCall::new(ExprType::Not, vec![is_json])?.into())
354 } else {
355 Ok(is_json)
356 }
357 }
358
359 pub(super) fn bind_unary_expr(&mut self, op: &UnaryOperator, expr: &Expr) -> Result<ExprImpl> {
360 let func_type = match &op {
361 UnaryOperator::Not => ExprType::Not,
362 UnaryOperator::Minus => ExprType::Neg,
363 UnaryOperator::Plus => {
364 return self.rewrite_positive(expr);
365 }
366 UnaryOperator::Custom(name) => match name.as_str() {
367 "~" => ExprType::BitwiseNot,
368 "@" => ExprType::Abs,
369 "|/" => ExprType::Sqrt,
370 "||/" => ExprType::Cbrt,
371 _ => bail_not_implemented!(issue = 112, "unsupported unary expression: {:?}", op),
372 },
373 UnaryOperator::PGQualified(_) => {
374 bail_not_implemented!(issue = 112, "unsupported unary expression: {:?}", op)
375 }
376 };
377 let expr = self.bind_expr_inner(expr)?;
378 FunctionCall::new(func_type, vec![expr]).map(|f| f.into())
379 }
380
381 fn rewrite_positive(&mut self, expr: &Expr) -> Result<ExprImpl> {
383 let expr = self.bind_expr_inner(expr)?;
384 let return_type = expr.return_type();
385 if return_type.is_numeric() {
386 return Ok(expr);
387 }
388 Err(ErrorCode::InvalidInputSyntax(format!("+ {:?}", return_type)).into())
389 }
390
391 pub(super) fn bind_trim(
392 &mut self,
393 expr: &Expr,
394 trim_where: Option<&TrimWhereField>,
396 trim_what: Option<&Expr>,
397 ) -> Result<ExprImpl> {
398 let mut inputs = vec![self.bind_expr_inner(expr)?];
399 let func_type = match trim_where {
400 Some(TrimWhereField::Both) => ExprType::Trim,
401 Some(TrimWhereField::Leading) => ExprType::Ltrim,
402 Some(TrimWhereField::Trailing) => ExprType::Rtrim,
403 None => ExprType::Trim,
404 };
405 if let Some(t) = trim_what {
406 inputs.push(self.bind_expr_inner(t)?);
407 }
408 Ok(FunctionCall::new(func_type, inputs)?.into())
409 }
410
411 fn bind_substring(
412 &mut self,
413 expr: &Expr,
414 substring_from: Option<&Expr>,
415 substring_for: Option<&Expr>,
416 ) -> Result<ExprImpl> {
417 let mut args = vec![
418 self.bind_expr_inner(expr)?,
419 match substring_from {
420 Some(expr) => self.bind_expr_inner(expr)?,
421 None => ExprImpl::literal_int(1),
422 },
423 ];
424 if let Some(expr) = substring_for {
425 args.push(self.bind_expr_inner(expr)?);
426 }
427 FunctionCall::new(ExprType::Substr, args).map(|f| f.into())
428 }
429
430 fn bind_position(&mut self, substring: &Expr, string: &Expr) -> Result<ExprImpl> {
431 let args = vec![
432 self.bind_expr_inner(string)?,
434 self.bind_expr_inner(substring)?,
435 ];
436 FunctionCall::new(ExprType::Position, args).map(Into::into)
437 }
438
439 fn bind_overlay(
440 &mut self,
441 expr: &Expr,
442 new_substring: &Expr,
443 start: &Expr,
444 count: Option<&Expr>,
445 ) -> Result<ExprImpl> {
446 let mut args = vec![
447 self.bind_expr_inner(expr)?,
448 self.bind_expr_inner(new_substring)?,
449 self.bind_expr_inner(start)?,
450 ];
451 if let Some(count) = count {
452 args.push(self.bind_expr_inner(count)?);
453 }
454 FunctionCall::new(ExprType::Overlay, args).map(|f| f.into())
455 }
456
457 fn is_binding_inline_sql_udf(&self) -> bool {
458 self.context.sql_udf_arguments.is_some()
459 }
460
461 fn is_binding_subquery_sql_udf(&self) -> bool {
464 self.upper_subquery_contexts
465 .iter()
466 .any(|(context, _)| context.sql_udf_arguments.is_some())
467 }
468
469 fn bind_sql_udf_parameter(&mut self, name: &str) -> Result<ExprImpl> {
471 for (depth, context) in std::iter::once(&self.context)
472 .chain((self.upper_subquery_contexts.iter().rev()).map(|(context, _)| context))
473 .enumerate()
474 {
475 if let Some(args) = &context.sql_udf_arguments {
478 if let Some(expr) = args.get(name) {
479 let mut rewriter = InputRefDepthRewriter::new(depth);
482 return Ok(rewriter.rewrite_expr(expr.clone()));
483 } else {
484 break;
487 }
488 }
489 }
490
491 Err(ErrorCode::BindError(format!(
492 "failed to find {} parameter {name}",
493 if name.starts_with('$') {
494 "unnamed"
495 } else {
496 "named"
497 }
498 ))
499 .into())
500 }
501
502 fn bind_parameter(&mut self, index: u64) -> Result<ExprImpl> {
503 if self.is_binding_inline_sql_udf() || self.is_binding_subquery_sql_udf() {
508 let column_name = format!("${index}");
509 return self.bind_sql_udf_parameter(&column_name);
510 }
511
512 Ok(Parameter::new(index, self.param_types.clone()).into())
513 }
514
515 pub(super) fn bind_between(
517 &mut self,
518 expr: &Expr,
519 negated: bool,
520 low: &Expr,
521 high: &Expr,
522 ) -> Result<ExprImpl> {
523 let expr = self.bind_expr_inner(expr)?;
524 let low = self.bind_expr_inner(low)?;
525 let high = self.bind_expr_inner(high)?;
526
527 let func_call = if negated {
528 FunctionCall::new_unchecked(
530 ExprType::Or,
531 vec![
532 FunctionCall::new(ExprType::LessThan, vec![expr.clone(), low])?.into(),
533 FunctionCall::new(ExprType::GreaterThan, vec![expr, high])?.into(),
534 ],
535 DataType::Boolean,
536 )
537 } else {
538 FunctionCall::new_unchecked(
540 ExprType::And,
541 vec![
542 FunctionCall::new(ExprType::GreaterThanOrEqual, vec![expr.clone(), low])?
543 .into(),
544 FunctionCall::new(ExprType::LessThanOrEqual, vec![expr, high])?.into(),
545 ],
546 DataType::Boolean,
547 )
548 };
549
550 Ok(func_call.into())
551 }
552
553 fn bind_like(
554 &mut self,
555 expr_type: ExprType,
556 expr: &Expr,
557 negated: bool,
558 pattern: &Expr,
559 escape_char: Option<EscapeChar>,
560 ) -> Result<ExprImpl> {
561 if matches!(pattern, Expr::AllOp(_) | Expr::SomeOp(_)) {
562 if escape_char.is_some() {
563 bail_not_implemented!(
569 "LIKE with both ALL|ANY pattern and escape character is not supported"
570 )
571 }
572 let op = match (expr_type, negated) {
574 (ExprType::Like, false) => BinaryOperator::Custom("~~".to_owned()),
575 (ExprType::Like, true) => BinaryOperator::Custom("!~~".to_owned()),
576 (ExprType::ILike, false) => BinaryOperator::Custom("~~*".to_owned()),
577 (ExprType::ILike, true) => BinaryOperator::Custom("!~~*".to_owned()),
578 _ => unreachable!(),
579 };
580 return self.bind_binary_op(expr, &op, pattern);
581 }
582 let expr = self.bind_expr_inner(expr)?;
583 let pattern = self.bind_expr_inner(pattern)?;
584 match (expr.return_type(), pattern.return_type()) {
585 (DataType::Varchar, DataType::Varchar) => {}
586 (string_ty, pattern_ty) => match expr_type {
587 ExprType::Like => bail_no_function!("like({}, {})", string_ty, pattern_ty),
588 ExprType::ILike => bail_no_function!("ilike({}, {})", string_ty, pattern_ty),
589 _ => unreachable!(),
590 },
591 }
592 let args = match escape_char {
593 Some(escape_char) => {
594 let escape_char = ExprImpl::literal_varchar(escape_char.to_string());
595 vec![expr, pattern, escape_char]
596 }
597 None => vec![expr, pattern],
598 };
599 let func_call = FunctionCall::new_unchecked(expr_type, args, DataType::Boolean);
600 let func_call = if negated {
601 FunctionCall::new_unchecked(ExprType::Not, vec![func_call.into()], DataType::Boolean)
602 } else {
603 func_call
604 };
605 Ok(func_call.into())
606 }
607
608 pub(super) fn bind_similar_to(
610 &mut self,
611 expr: &Expr,
612 negated: bool,
613 pattern: &Expr,
614 escape_char: Option<EscapeChar>,
615 ) -> Result<ExprImpl> {
616 let expr = self.bind_expr_inner(expr)?;
617 let pattern = self.bind_expr_inner(pattern)?;
618
619 let esc_inputs = if let Some(escape_char) = escape_char {
620 let escape_char = ExprImpl::literal_varchar(escape_char.to_string());
621 vec![pattern, escape_char]
622 } else {
623 vec![pattern]
624 };
625
626 let esc_call =
627 FunctionCall::new_unchecked(ExprType::SimilarToEscape, esc_inputs, DataType::Varchar);
628
629 let regex_call = FunctionCall::new_unchecked(
630 ExprType::RegexpEq,
631 vec![expr, esc_call.into()],
632 DataType::Boolean,
633 );
634 let func_call = if negated {
635 FunctionCall::new_unchecked(ExprType::Not, vec![regex_call.into()], DataType::Boolean)
636 } else {
637 regex_call
638 };
639
640 Ok(func_call.into())
641 }
642
643 fn check_constant_case_when_optimization(
646 &mut self,
647 conditions: &[Expr],
648 results_expr: &[ExprImpl],
649 operand: Option<&Expr>,
650 fallback: Option<&ExprImpl>,
651 constant_case_when_eval_inputs: &mut Vec<ExprImpl>,
652 ) -> bool {
653 let operand_value;
655
656 if let Some(operand) = operand {
657 let Ok(operand) = self.bind_expr_inner(operand) else {
658 return false;
659 };
660 if !operand.is_const() {
661 return false;
662 }
663 operand_value = operand;
664 } else {
665 return false;
666 }
667
668 for (condition, result) in zip_eq_fast(conditions, results_expr) {
669 if let Expr::Value(_) = condition.clone() {
670 let Ok(res) = self.bind_expr_inner(condition) else {
671 return false;
672 };
673 if res == operand_value {
675 constant_case_when_eval_inputs.push(result.clone());
676 return true;
677 }
678 } else {
679 return false;
680 }
681 }
682
683 debug_assert!(
685 constant_case_when_eval_inputs.is_empty(),
686 "expect `inputs` to be empty"
687 );
688
689 let Some(fallback) = fallback else {
690 return false;
691 };
692
693 constant_case_when_eval_inputs.push(fallback.clone());
694 true
695 }
696
697 fn compare_or_set(col_expr: &mut Option<Expr>, test_expr: &Expr) -> bool {
700 let Expr::Identifier(test_ident) = test_expr else {
701 return false;
702 };
703 if let Some(expr) = col_expr {
704 let Expr::Identifier(ident) = expr else {
705 return false;
706 };
707 if ident.real_value() != test_ident.real_value() {
708 return false;
709 }
710 } else {
711 *col_expr = Some(Expr::Identifier(test_ident.clone()));
712 }
713 true
714 }
715
716 fn check_invariant(left: &Expr, op: &BinaryOperator, right: &Expr) -> bool {
720 if op != &BinaryOperator::Eq {
721 return false;
722 }
723 if let Expr::Identifier(_) = left {
724 let Expr::Value(_) = right else {
726 return false;
727 };
728 } else {
729 let Expr::Value(_) = left else {
731 return false;
732 };
733 let Expr::Identifier(_) = right else {
734 return false;
735 };
736 }
737 true
738 }
739
740 fn try_extract_simple_form(
745 &mut self,
746 ident_expr: &Expr,
747 constant_expr: &Expr,
748 column_expr: &mut Option<Expr>,
749 inputs: &mut Vec<ExprImpl>,
750 ) -> bool {
751 if !Self::compare_or_set(column_expr, ident_expr) {
752 return false;
753 }
754 let Ok(bound_expr) = self.bind_expr_inner(constant_expr) else {
755 return false;
756 };
757 inputs.push(bound_expr);
758 true
759 }
760
761 fn check_convert_simple_form(
765 &mut self,
766 conditions: &[Expr],
767 results_expr: &[ExprImpl],
768 fallback: Option<ExprImpl>,
769 constant_lookup_inputs: &mut Vec<ExprImpl>,
770 ) -> bool {
771 let mut column_expr = None;
772
773 for (condition, result) in zip_eq_fast(conditions, results_expr) {
774 if let Expr::BinaryOp { left, op, right } = condition {
775 if !Self::check_invariant(left, op, right) {
776 return false;
777 }
778 if let Expr::Identifier(_) = &**left {
779 if !self.try_extract_simple_form(
780 left,
781 right,
782 &mut column_expr,
783 constant_lookup_inputs,
784 ) {
785 return false;
786 }
787 } else if !self.try_extract_simple_form(
788 right,
789 left,
790 &mut column_expr,
791 constant_lookup_inputs,
792 ) {
793 return false;
794 }
795 constant_lookup_inputs.push(result.clone());
796 } else {
797 return false;
798 }
799 }
800
801 let Some(operand) = column_expr else {
803 return false;
804 };
805 let Ok(bound_operand) = self.bind_expr_inner(&operand) else {
806 return false;
807 };
808 constant_lookup_inputs.insert(0, bound_operand);
809
810 if let Some(expr) = fallback {
812 constant_lookup_inputs.push(expr);
813 }
814
815 true
816 }
817
818 fn check_bind_case_optimization(
822 &mut self,
823 conditions: &[Expr],
824 results_expr: &[ExprImpl],
825 operand: Option<&Expr>,
826 fallback: Option<ExprImpl>,
827 constant_lookup_inputs: &mut Vec<ExprImpl>,
828 ) -> bool {
829 if conditions.len() < CASE_WHEN_ARMS_OPTIMIZE_LIMIT {
830 return false;
831 }
832
833 if let Some(operand) = operand {
834 let Ok(operand) = self.bind_expr_inner(operand) else {
835 return false;
836 };
837 if operand.is_const() {
841 return false;
842 }
843 constant_lookup_inputs.push(operand);
844 } else {
845 return self.check_convert_simple_form(
848 conditions,
849 results_expr,
850 fallback,
851 constant_lookup_inputs,
852 );
853 }
854
855 for (condition, result) in zip_eq_fast(conditions, results_expr) {
856 if let Expr::Value(_) = condition {
857 let Ok(input) = self.bind_expr_inner(condition) else {
858 return false;
859 };
860 constant_lookup_inputs.push(input);
861 } else {
862 return false;
865 }
866
867 constant_lookup_inputs.push(result.clone());
868 }
869
870 if let Some(expr) = fallback {
872 constant_lookup_inputs.push(expr);
873 }
874
875 true
876 }
877
878 pub(super) fn bind_case(
879 &mut self,
880 operand: Option<&Expr>,
881 conditions: &[Expr],
882 results: &[Expr],
883 else_result: Option<&Expr>,
884 ) -> Result<ExprImpl> {
885 let mut inputs = Vec::new();
886 let results_expr: Vec<ExprImpl> = results
887 .iter()
888 .map(|expr| self.bind_expr_inner(expr))
889 .collect::<Result<_>>()?;
890 let else_result_expr = else_result
891 .map(|expr| self.bind_expr_inner(expr))
892 .transpose()?;
893
894 let mut constant_lookup_inputs = Vec::new();
895 let mut constant_case_when_eval_inputs = Vec::new();
896
897 let constant_case_when_flag = self.check_constant_case_when_optimization(
898 conditions,
899 &results_expr,
900 operand,
901 else_result_expr.as_ref(),
902 &mut constant_case_when_eval_inputs,
903 );
904
905 if constant_case_when_flag {
906 if constant_case_when_eval_inputs.len() != 1 {
908 return Err(ErrorCode::BindError(
909 "expect `constant_case_when_eval_inputs` only contains a single bound expression".to_owned()
910 )
911 .into());
912 }
913 return Ok(constant_case_when_eval_inputs[0].take());
915 }
916
917 let optimize_flag = self.check_bind_case_optimization(
919 conditions,
920 &results_expr,
921 operand,
922 else_result_expr.clone(),
923 &mut constant_lookup_inputs,
924 );
925
926 if optimize_flag {
927 return Ok(FunctionCall::new(ExprType::ConstantLookup, constant_lookup_inputs)?.into());
928 }
929
930 for (condition, result) in zip_eq_fast(conditions, results_expr) {
931 let condition = condition.clone();
932 let condition = match operand {
933 Some(t) => Expr::BinaryOp {
934 left: t.clone().into(),
935 op: BinaryOperator::Eq,
936 right: Box::new(condition),
937 },
938 None => condition,
939 };
940 inputs.push(
941 self.bind_expr_inner(&condition)
942 .and_then(|expr| expr.enforce_bool_clause("CASE WHEN"))?,
943 );
944 inputs.push(result);
945 }
946
947 if let Some(expr) = else_result_expr {
949 inputs.push(expr);
950 }
951
952 if inputs.iter().any(ExprImpl::has_table_function) {
953 return Err(
954 ErrorCode::BindError("table functions are not allowed in CASE".into()).into(),
955 );
956 }
957
958 Ok(FunctionCall::new(ExprType::Case, inputs)?.into())
959 }
960
961 pub(super) fn bind_is_operator(
962 &mut self,
963 func_type: ExprType,
964 expr: &Expr,
965 ) -> Result<ExprImpl> {
966 let expr = self.bind_expr_inner(expr)?;
967 Ok(FunctionCall::new(func_type, vec![expr])?.into())
968 }
969
970 pub(super) fn bind_is_unknown(&mut self, func_type: ExprType, expr: &Expr) -> Result<ExprImpl> {
971 let expr = self
972 .bind_expr_inner(expr)?
973 .cast_implicit(&DataType::Boolean)?;
974 Ok(FunctionCall::new(func_type, vec![expr])?.into())
975 }
976
977 pub(super) fn bind_distinct_from(&mut self, left: &Expr, right: &Expr) -> Result<ExprImpl> {
978 let left = self.bind_expr_inner(left)?;
979 let right = self.bind_expr_inner(right)?;
980 let func_call = FunctionCall::new(ExprType::IsDistinctFrom, vec![left, right]);
981 Ok(func_call?.into())
982 }
983
984 pub(super) fn bind_not_distinct_from(&mut self, left: &Expr, right: &Expr) -> Result<ExprImpl> {
985 let left = self.bind_expr_inner(left)?;
986 let right = self.bind_expr_inner(right)?;
987 let func_call = FunctionCall::new(ExprType::IsNotDistinctFrom, vec![left, right]);
988 Ok(func_call?.into())
989 }
990
991 pub(super) fn bind_cast(&mut self, expr: &Expr, data_type: &AstDataType) -> Result<ExprImpl> {
992 match &data_type {
993 AstDataType::Regclass => {
996 let input = self.bind_expr_inner(expr)?;
997 Ok(input.cast_to_regclass()?)
998 }
999 AstDataType::Regproc => {
1000 let lhs = self.bind_expr_inner(expr)?;
1001 let lhs_ty = lhs.return_type();
1002 if lhs_ty == DataType::Varchar {
1003 Ok(lhs)
1007 } else {
1008 Err(ErrorCode::BindError(format!("Can't cast {} to regproc", lhs_ty)).into())
1009 }
1010 }
1011 AstDataType::Char(_) => self.bind_cast_inner(expr, &DataType::Varchar),
1025 _ => self.bind_cast_inner(expr, &bind_data_type(data_type)?),
1026 }
1027 }
1028
1029 pub fn bind_cast_inner(&mut self, expr: &Expr, data_type: &DataType) -> Result<ExprImpl> {
1030 match (expr, data_type) {
1031 (Expr::Array(Array { elem: expr, .. }), DataType::List(list_type)) => {
1032 self.bind_array_cast(expr, list_type.elem())
1033 }
1034 (Expr::Map { entries }, DataType::Map(m)) => self.bind_map_cast(entries, m),
1035 (expr, data_type) => {
1036 let lhs = self.bind_expr_inner(expr)?;
1037 lhs.cast_explicit(data_type).map_err(Into::into)
1038 }
1039 }
1040 }
1041
1042 pub fn bind_collate(&mut self, expr: &Expr, collation: &ObjectName) -> Result<ExprImpl> {
1043 if !["C", "POSIX"].contains(&collation.real_value().as_str()) {
1044 bail_not_implemented!("Collate collation other than `C` or `POSIX` is not implemented");
1045 }
1046
1047 let bound_inner = self.bind_expr_inner(expr)?;
1048 let ret_type = bound_inner.return_type();
1049
1050 match ret_type {
1051 DataType::Varchar => {}
1052 _ => {
1053 return Err(ErrorCode::NotSupported(
1054 format!("{} is not a collatable data type", ret_type),
1055 "The only built-in collatable data types are `varchar`, please check your type"
1056 .into(),
1057 )
1058 .into());
1059 }
1060 }
1061
1062 Ok(bound_inner)
1063 }
1064}
1065
1066pub fn bind_data_type(data_type: &AstDataType) -> Result<DataType> {
1067 let new_err = || not_implemented!("unsupported data type: {:}", data_type);
1068 let data_type = match data_type {
1069 AstDataType::Boolean => DataType::Boolean,
1070 AstDataType::SmallInt => DataType::Int16,
1071 AstDataType::Int => DataType::Int32,
1072 AstDataType::BigInt => DataType::Int64,
1073 AstDataType::Real | AstDataType::Float(Some(1..=24)) => DataType::Float32,
1074 AstDataType::Double | AstDataType::Float(Some(25..=53) | None) => DataType::Float64,
1075 AstDataType::Float(Some(0 | 54..)) => unreachable!(),
1076 AstDataType::Decimal(None, None) => DataType::Decimal,
1077 AstDataType::Varchar | AstDataType::Text => DataType::Varchar,
1078 AstDataType::Date => DataType::Date,
1079 AstDataType::Time(false) => DataType::Time,
1080 AstDataType::Timestamp(false) => DataType::Timestamp,
1081 AstDataType::Timestamp(true) => DataType::Timestamptz,
1082 AstDataType::Interval => DataType::Interval,
1083 AstDataType::Array(datatype) => DataType::list(bind_data_type(datatype)?),
1084 AstDataType::Char(..) => {
1085 bail_not_implemented!("CHAR is not supported, please use VARCHAR instead")
1086 }
1087 AstDataType::Struct(types) => StructType::new(
1088 types
1089 .iter()
1090 .map(|f| Ok((f.name.real_value(), bind_data_type(&f.data_type)?)))
1091 .collect::<Result<Vec<_>>>()?,
1092 )
1093 .into(),
1094 AstDataType::Map(kv) => {
1095 let key = bind_data_type(&kv.0)?;
1096 let value = bind_data_type(&kv.1)?;
1097 DataType::Map(MapType::try_from_kv(key, value).map_err(ErrorCode::BindError)?)
1098 }
1099 AstDataType::Custom(qualified_type_name) => {
1100 let idents = qualified_type_name
1101 .0
1102 .iter()
1103 .map(|n| n.real_value())
1104 .collect_vec();
1105 let name = if idents.len() == 1 {
1106 idents[0].as_str() } else if idents.len() == 2 && idents[0] == PG_CATALOG_SCHEMA_NAME {
1108 idents[1].as_str() } else {
1110 return Err(new_err().into());
1111 };
1112
1113 match name {
1116 "int2" => DataType::Int16,
1117 "int4" => DataType::Int32,
1118 "int8" => DataType::Int64,
1119 "rw_int256" => DataType::Int256,
1120 "float4" => DataType::Float32,
1121 "float8" => DataType::Float64,
1122 "timestamptz" => DataType::Timestamptz,
1123 "text" => DataType::Varchar,
1124 "serial" => {
1125 return Err(ErrorCode::NotSupported(
1126 "Column type SERIAL is not supported".into(),
1127 "Please remove the SERIAL column".into(),
1128 )
1129 .into());
1130 }
1131 _ => return Err(new_err().into()),
1132 }
1133 }
1134 AstDataType::Bytea => DataType::Bytea,
1135 AstDataType::Jsonb => DataType::Jsonb,
1136 AstDataType::Variant => DataType::Variant,
1137 AstDataType::Vector(size) => match (1..=DataType::VEC_MAX_SIZE).contains(&(*size as _)) {
1138 true => DataType::Vector(*size as _),
1139 false => {
1140 return Err(ErrorCode::BindError(format!(
1141 "vector size {} is out of range [1, {}]",
1142 size,
1143 DataType::VEC_MAX_SIZE
1144 ))
1145 .into());
1146 }
1147 },
1148 AstDataType::Regclass
1149 | AstDataType::Regproc
1150 | AstDataType::Uuid
1151 | AstDataType::Decimal(_, _)
1152 | AstDataType::Time(true) => return Err(new_err().into()),
1153 };
1154 Ok(data_type)
1155}