1use std::collections::HashSet;
21use std::fmt::{self, Display, Formatter, Write};
22use std::hash::{Hash, Hasher};
23use std::mem;
24use std::sync::Arc;
25
26use crate::expr_fn::binary_expr;
27use crate::logical_plan::Subquery;
28use crate::Volatility;
29use crate::{udaf, ExprSchemable, Operator, Signature, WindowFrame, WindowUDF};
30
31use arrow::datatypes::{DataType, FieldRef};
32use datafusion_common::cse::{HashNode, NormalizeEq, Normalizeable};
33use datafusion_common::tree_node::{
34 Transformed, TransformedResult, TreeNode, TreeNodeContainer, TreeNodeRecursion,
35};
36use datafusion_common::{
37 Column, DFSchema, HashMap, Result, ScalarValue, Spans, TableReference,
38};
39use datafusion_functions_window_common::field::WindowUDFFieldArgs;
40use sqlparser::ast::{
41 display_comma_separated, ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem,
42 NullTreatment, RenameSelectItem, ReplaceSelectElement,
43};
44
45#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
278pub enum Expr {
279 Alias(Alias),
281 Column(Column),
283 ScalarVariable(DataType, Vec<String>),
285 Literal(ScalarValue),
287 BinaryExpr(BinaryExpr),
289 Like(Like),
291 SimilarTo(Like),
293 Not(Box<Expr>),
295 IsNotNull(Box<Expr>),
297 IsNull(Box<Expr>),
299 IsTrue(Box<Expr>),
301 IsFalse(Box<Expr>),
303 IsUnknown(Box<Expr>),
305 IsNotTrue(Box<Expr>),
307 IsNotFalse(Box<Expr>),
309 IsNotUnknown(Box<Expr>),
311 Negative(Box<Expr>),
313 Between(Between),
315 Case(Case),
337 Cast(Cast),
340 TryCast(TryCast),
343 ScalarFunction(ScalarFunction),
345 AggregateFunction(AggregateFunction),
352 WindowFunction(WindowFunction),
354 InList(InList),
356 Exists(Exists),
358 InSubquery(InSubquery),
360 ScalarSubquery(Subquery),
362 #[deprecated(
368 since = "46.0.0",
369 note = "A wildcard needs to be resolved to concrete expressions when constructing the logical plan. See https://github.com/apache/datafusion/issues/7765"
370 )]
371 Wildcard {
372 qualifier: Option<TableReference>,
373 options: Box<WildcardOptions>,
374 },
375 GroupingSet(GroupingSet),
378 Placeholder(Placeholder),
381 OuterReferenceColumn(DataType, Column),
384 Unnest(Unnest),
386}
387
388impl Default for Expr {
389 fn default() -> Self {
390 Expr::Literal(ScalarValue::Null)
391 }
392}
393
394impl From<Column> for Expr {
396 fn from(value: Column) -> Self {
397 Expr::Column(value)
398 }
399}
400
401impl<'a> From<(Option<&'a TableReference>, &'a FieldRef)> for Expr {
406 fn from(value: (Option<&'a TableReference>, &'a FieldRef)) -> Self {
407 Expr::from(Column::from(value))
408 }
409}
410
411impl<'a> TreeNodeContainer<'a, Self> for Expr {
412 fn apply_elements<F: FnMut(&'a Self) -> Result<TreeNodeRecursion>>(
413 &'a self,
414 mut f: F,
415 ) -> Result<TreeNodeRecursion> {
416 f(self)
417 }
418
419 fn map_elements<F: FnMut(Self) -> Result<Transformed<Self>>>(
420 self,
421 mut f: F,
422 ) -> Result<Transformed<Self>> {
423 f(self)
424 }
425}
426
427#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
429pub struct Unnest {
430 pub expr: Box<Expr>,
431}
432
433impl Unnest {
434 pub fn new(expr: Expr) -> Self {
436 Self {
437 expr: Box::new(expr),
438 }
439 }
440
441 pub fn new_boxed(boxed: Box<Expr>) -> Self {
443 Self { expr: boxed }
444 }
445}
446
447#[derive(Clone, PartialEq, Eq, Debug)]
449pub struct Alias {
450 pub expr: Box<Expr>,
451 pub relation: Option<TableReference>,
452 pub name: String,
453 pub metadata: Option<std::collections::HashMap<String, String>>,
454}
455
456impl Hash for Alias {
457 fn hash<H: Hasher>(&self, state: &mut H) {
458 self.expr.hash(state);
459 self.relation.hash(state);
460 self.name.hash(state);
461 }
462}
463
464impl PartialOrd for Alias {
465 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
466 let cmp = self.expr.partial_cmp(&other.expr);
467 let Some(std::cmp::Ordering::Equal) = cmp else {
468 return cmp;
469 };
470 let cmp = self.relation.partial_cmp(&other.relation);
471 let Some(std::cmp::Ordering::Equal) = cmp else {
472 return cmp;
473 };
474 self.name.partial_cmp(&other.name)
475 }
476}
477
478impl Alias {
479 pub fn new(
481 expr: Expr,
482 relation: Option<impl Into<TableReference>>,
483 name: impl Into<String>,
484 ) -> Self {
485 Self {
486 expr: Box::new(expr),
487 relation: relation.map(|r| r.into()),
488 name: name.into(),
489 metadata: None,
490 }
491 }
492
493 pub fn with_metadata(
494 mut self,
495 metadata: Option<std::collections::HashMap<String, String>>,
496 ) -> Self {
497 self.metadata = metadata;
498 self
499 }
500}
501
502#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
504pub struct BinaryExpr {
505 pub left: Box<Expr>,
507 pub op: Operator,
509 pub right: Box<Expr>,
511}
512
513impl BinaryExpr {
514 pub fn new(left: Box<Expr>, op: Operator, right: Box<Expr>) -> Self {
516 Self { left, op, right }
517 }
518}
519
520impl Display for BinaryExpr {
521 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
522 fn write_child(
528 f: &mut Formatter<'_>,
529 expr: &Expr,
530 precedence: u8,
531 ) -> fmt::Result {
532 match expr {
533 Expr::BinaryExpr(child) => {
534 let p = child.op.precedence();
535 if p == 0 || p < precedence {
536 write!(f, "({child})")?;
537 } else {
538 write!(f, "{child}")?;
539 }
540 }
541 _ => write!(f, "{expr}")?,
542 }
543 Ok(())
544 }
545
546 let precedence = self.op.precedence();
547 write_child(f, self.left.as_ref(), precedence)?;
548 write!(f, " {} ", self.op)?;
549 write_child(f, self.right.as_ref(), precedence)
550 }
551}
552
553#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
555pub struct Case {
556 pub expr: Option<Box<Expr>>,
558 pub when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
560 pub else_expr: Option<Box<Expr>>,
562}
563
564impl Case {
565 pub fn new(
567 expr: Option<Box<Expr>>,
568 when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
569 else_expr: Option<Box<Expr>>,
570 ) -> Self {
571 Self {
572 expr,
573 when_then_expr,
574 else_expr,
575 }
576 }
577}
578
579#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
581pub struct Like {
582 pub negated: bool,
583 pub expr: Box<Expr>,
584 pub pattern: Box<Expr>,
585 pub escape_char: Option<char>,
586 pub case_insensitive: bool,
588}
589
590impl Like {
591 pub fn new(
593 negated: bool,
594 expr: Box<Expr>,
595 pattern: Box<Expr>,
596 escape_char: Option<char>,
597 case_insensitive: bool,
598 ) -> Self {
599 Self {
600 negated,
601 expr,
602 pattern,
603 escape_char,
604 case_insensitive,
605 }
606 }
607}
608
609#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
611pub struct Between {
612 pub expr: Box<Expr>,
614 pub negated: bool,
616 pub low: Box<Expr>,
618 pub high: Box<Expr>,
620}
621
622impl Between {
623 pub fn new(expr: Box<Expr>, negated: bool, low: Box<Expr>, high: Box<Expr>) -> Self {
625 Self {
626 expr,
627 negated,
628 low,
629 high,
630 }
631 }
632}
633
634#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
636pub struct ScalarFunction {
637 pub func: Arc<crate::ScalarUDF>,
639 pub args: Vec<Expr>,
641}
642
643impl ScalarFunction {
644 pub fn name(&self) -> &str {
646 self.func.name()
647 }
648}
649
650impl ScalarFunction {
651 pub fn new_udf(udf: Arc<crate::ScalarUDF>, args: Vec<Expr>) -> Self {
653 Self { func: udf, args }
654 }
655}
656
657#[derive(Clone, PartialEq, Eq, Hash, Debug)]
659pub enum GetFieldAccess {
660 NamedStructField { name: ScalarValue },
662 ListIndex { key: Box<Expr> },
664 ListRange {
666 start: Box<Expr>,
667 stop: Box<Expr>,
668 stride: Box<Expr>,
669 },
670}
671
672#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
674pub struct Cast {
675 pub expr: Box<Expr>,
677 pub data_type: DataType,
679}
680
681impl Cast {
682 pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
684 Self { expr, data_type }
685 }
686}
687
688#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
690pub struct TryCast {
691 pub expr: Box<Expr>,
693 pub data_type: DataType,
695}
696
697impl TryCast {
698 pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
700 Self { expr, data_type }
701 }
702}
703
704#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
706pub struct Sort {
707 pub expr: Expr,
709 pub asc: bool,
711 pub nulls_first: bool,
713}
714
715impl Sort {
716 pub fn new(expr: Expr, asc: bool, nulls_first: bool) -> Self {
718 Self {
719 expr,
720 asc,
721 nulls_first,
722 }
723 }
724
725 pub fn reverse(&self) -> Self {
727 Self {
728 expr: self.expr.clone(),
729 asc: !self.asc,
730 nulls_first: !self.nulls_first,
731 }
732 }
733
734 pub fn with_expr(&self, expr: Expr) -> Self {
736 Self {
737 expr,
738 asc: self.asc,
739 nulls_first: self.nulls_first,
740 }
741 }
742}
743
744impl Display for Sort {
745 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
746 write!(f, "{}", self.expr)?;
747 if self.asc {
748 write!(f, " ASC")?;
749 } else {
750 write!(f, " DESC")?;
751 }
752 if self.nulls_first {
753 write!(f, " NULLS FIRST")?;
754 } else {
755 write!(f, " NULLS LAST")?;
756 }
757 Ok(())
758 }
759}
760
761impl<'a> TreeNodeContainer<'a, Expr> for Sort {
762 fn apply_elements<F: FnMut(&'a Expr) -> Result<TreeNodeRecursion>>(
763 &'a self,
764 f: F,
765 ) -> Result<TreeNodeRecursion> {
766 self.expr.apply_elements(f)
767 }
768
769 fn map_elements<F: FnMut(Expr) -> Result<Transformed<Expr>>>(
770 self,
771 f: F,
772 ) -> Result<Transformed<Self>> {
773 self.expr
774 .map_elements(f)?
775 .map_data(|expr| Ok(Self { expr, ..self }))
776 }
777}
778
779#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
785pub struct AggregateFunction {
786 pub func: Arc<crate::AggregateUDF>,
788 pub params: AggregateFunctionParams,
789}
790
791#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
792pub struct AggregateFunctionParams {
793 pub args: Vec<Expr>,
794 pub distinct: bool,
796 pub filter: Option<Box<Expr>>,
798 pub order_by: Option<Vec<Sort>>,
800 pub null_treatment: Option<NullTreatment>,
801}
802
803impl AggregateFunction {
804 pub fn new_udf(
806 func: Arc<crate::AggregateUDF>,
807 args: Vec<Expr>,
808 distinct: bool,
809 filter: Option<Box<Expr>>,
810 order_by: Option<Vec<Sort>>,
811 null_treatment: Option<NullTreatment>,
812 ) -> Self {
813 Self {
814 func,
815 params: AggregateFunctionParams {
816 args,
817 distinct,
818 filter,
819 order_by,
820 null_treatment,
821 },
822 }
823 }
824}
825
826#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
832pub enum WindowFunctionDefinition {
833 AggregateUDF(Arc<crate::AggregateUDF>),
835 WindowUDF(Arc<WindowUDF>),
837}
838
839impl WindowFunctionDefinition {
840 pub fn return_type(
842 &self,
843 input_expr_types: &[DataType],
844 _input_expr_nullable: &[bool],
845 display_name: &str,
846 ) -> Result<DataType> {
847 match self {
848 WindowFunctionDefinition::AggregateUDF(fun) => {
849 fun.return_type(input_expr_types)
850 }
851 WindowFunctionDefinition::WindowUDF(fun) => fun
852 .field(WindowUDFFieldArgs::new(input_expr_types, display_name))
853 .map(|field| field.data_type().clone()),
854 }
855 }
856
857 pub fn signature(&self) -> Signature {
859 match self {
860 WindowFunctionDefinition::AggregateUDF(fun) => fun.signature().clone(),
861 WindowFunctionDefinition::WindowUDF(fun) => fun.signature().clone(),
862 }
863 }
864
865 pub fn name(&self) -> &str {
867 match self {
868 WindowFunctionDefinition::WindowUDF(fun) => fun.name(),
869 WindowFunctionDefinition::AggregateUDF(fun) => fun.name(),
870 }
871 }
872}
873
874impl Display for WindowFunctionDefinition {
875 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
876 match self {
877 WindowFunctionDefinition::AggregateUDF(fun) => Display::fmt(fun, f),
878 WindowFunctionDefinition::WindowUDF(fun) => Display::fmt(fun, f),
879 }
880 }
881}
882
883impl From<Arc<crate::AggregateUDF>> for WindowFunctionDefinition {
884 fn from(value: Arc<crate::AggregateUDF>) -> Self {
885 Self::AggregateUDF(value)
886 }
887}
888
889impl From<Arc<WindowUDF>> for WindowFunctionDefinition {
890 fn from(value: Arc<WindowUDF>) -> Self {
891 Self::WindowUDF(value)
892 }
893}
894
895#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
908pub struct WindowFunction {
909 pub fun: WindowFunctionDefinition,
911 pub params: WindowFunctionParams,
912}
913
914#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
915pub struct WindowFunctionParams {
916 pub args: Vec<Expr>,
918 pub partition_by: Vec<Expr>,
920 pub order_by: Vec<Sort>,
922 pub window_frame: WindowFrame,
924 pub null_treatment: Option<NullTreatment>,
926}
927
928impl WindowFunction {
929 pub fn new(fun: impl Into<WindowFunctionDefinition>, args: Vec<Expr>) -> Self {
932 Self {
933 fun: fun.into(),
934 params: WindowFunctionParams {
935 args,
936 partition_by: Vec::default(),
937 order_by: Vec::default(),
938 window_frame: WindowFrame::new(None),
939 null_treatment: None,
940 },
941 }
942 }
943}
944
945#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
947pub struct Exists {
948 pub subquery: Subquery,
950 pub negated: bool,
952}
953
954impl Exists {
955 pub fn new(subquery: Subquery, negated: bool) -> Self {
957 Self { subquery, negated }
958 }
959}
960
961#[derive(Clone, PartialEq, Eq, Hash, Debug)]
965pub struct AggregateUDF {
966 pub fun: Arc<udaf::AggregateUDF>,
968 pub args: Vec<Expr>,
970 pub filter: Option<Box<Expr>>,
972 pub order_by: Option<Vec<Expr>>,
974}
975
976impl AggregateUDF {
977 pub fn new(
979 fun: Arc<udaf::AggregateUDF>,
980 args: Vec<Expr>,
981 filter: Option<Box<Expr>>,
982 order_by: Option<Vec<Expr>>,
983 ) -> Self {
984 Self {
985 fun,
986 args,
987 filter,
988 order_by,
989 }
990 }
991}
992
993#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
995pub struct InList {
996 pub expr: Box<Expr>,
998 pub list: Vec<Expr>,
1000 pub negated: bool,
1002}
1003
1004impl InList {
1005 pub fn new(expr: Box<Expr>, list: Vec<Expr>, negated: bool) -> Self {
1007 Self {
1008 expr,
1009 list,
1010 negated,
1011 }
1012 }
1013}
1014
1015#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1017pub struct InSubquery {
1018 pub expr: Box<Expr>,
1020 pub subquery: Subquery,
1022 pub negated: bool,
1024}
1025
1026impl InSubquery {
1027 pub fn new(expr: Box<Expr>, subquery: Subquery, negated: bool) -> Self {
1029 Self {
1030 expr,
1031 subquery,
1032 negated,
1033 }
1034 }
1035}
1036
1037#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1042pub struct Placeholder {
1043 pub id: String,
1045 pub data_type: Option<DataType>,
1047}
1048
1049impl Placeholder {
1050 pub fn new(id: String, data_type: Option<DataType>) -> Self {
1052 Self { id, data_type }
1053 }
1054}
1055
1056#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1063pub enum GroupingSet {
1064 Rollup(Vec<Expr>),
1066 Cube(Vec<Expr>),
1068 GroupingSets(Vec<Vec<Expr>>),
1070}
1071
1072impl GroupingSet {
1073 pub fn distinct_expr(&self) -> Vec<&Expr> {
1077 match self {
1078 GroupingSet::Rollup(exprs) | GroupingSet::Cube(exprs) => {
1079 exprs.iter().collect()
1080 }
1081 GroupingSet::GroupingSets(groups) => {
1082 let mut exprs: Vec<&Expr> = vec![];
1083 for exp in groups.iter().flatten() {
1084 if !exprs.contains(&exp) {
1085 exprs.push(exp);
1086 }
1087 }
1088 exprs
1089 }
1090 }
1091 }
1092}
1093
1094#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1096pub struct WildcardOptions {
1097 pub ilike: Option<IlikeSelectItem>,
1100 pub exclude: Option<ExcludeSelectItem>,
1103 pub except: Option<ExceptSelectItem>,
1107 pub replace: Option<PlannedReplaceSelectItem>,
1112 pub rename: Option<RenameSelectItem>,
1115}
1116
1117impl WildcardOptions {
1118 pub fn with_replace(self, replace: PlannedReplaceSelectItem) -> Self {
1119 WildcardOptions {
1120 ilike: self.ilike,
1121 exclude: self.exclude,
1122 except: self.except,
1123 replace: Some(replace),
1124 rename: self.rename,
1125 }
1126 }
1127}
1128
1129impl Display for WildcardOptions {
1130 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1131 if let Some(ilike) = &self.ilike {
1132 write!(f, " {ilike}")?;
1133 }
1134 if let Some(exclude) = &self.exclude {
1135 write!(f, " {exclude}")?;
1136 }
1137 if let Some(except) = &self.except {
1138 write!(f, " {except}")?;
1139 }
1140 if let Some(replace) = &self.replace {
1141 write!(f, " {replace}")?;
1142 }
1143 if let Some(rename) = &self.rename {
1144 write!(f, " {rename}")?;
1145 }
1146 Ok(())
1147 }
1148}
1149
1150#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1152pub struct PlannedReplaceSelectItem {
1153 pub items: Vec<ReplaceSelectElement>,
1155 pub planned_expressions: Vec<Expr>,
1157}
1158
1159impl Display for PlannedReplaceSelectItem {
1160 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1161 write!(f, "REPLACE")?;
1162 write!(f, " ({})", display_comma_separated(&self.items))?;
1163 Ok(())
1164 }
1165}
1166
1167impl PlannedReplaceSelectItem {
1168 pub fn items(&self) -> &[ReplaceSelectElement] {
1169 &self.items
1170 }
1171
1172 pub fn expressions(&self) -> &[Expr] {
1173 &self.planned_expressions
1174 }
1175}
1176
1177impl Expr {
1178 pub fn schema_name(&self) -> impl Display + '_ {
1201 SchemaDisplay(self)
1202 }
1203
1204 pub fn human_display(&self) -> impl Display + '_ {
1226 SqlDisplay(self)
1227 }
1228
1229 pub fn qualified_name(&self) -> (Option<TableReference>, String) {
1235 match self {
1236 Expr::Column(Column {
1237 relation,
1238 name,
1239 spans: _,
1240 }) => (relation.clone(), name.clone()),
1241 Expr::Alias(Alias { relation, name, .. }) => (relation.clone(), name.clone()),
1242 _ => (None, self.schema_name().to_string()),
1243 }
1244 }
1245
1246 #[deprecated(since = "42.0.0", note = "use format! instead")]
1248 pub fn canonical_name(&self) -> String {
1249 format!("{self}")
1250 }
1251
1252 pub fn variant_name(&self) -> &str {
1255 match self {
1256 Expr::AggregateFunction { .. } => "AggregateFunction",
1257 Expr::Alias(..) => "Alias",
1258 Expr::Between { .. } => "Between",
1259 Expr::BinaryExpr { .. } => "BinaryExpr",
1260 Expr::Case { .. } => "Case",
1261 Expr::Cast { .. } => "Cast",
1262 Expr::Column(..) => "Column",
1263 Expr::OuterReferenceColumn(_, _) => "Outer",
1264 Expr::Exists { .. } => "Exists",
1265 Expr::GroupingSet(..) => "GroupingSet",
1266 Expr::InList { .. } => "InList",
1267 Expr::InSubquery(..) => "InSubquery",
1268 Expr::IsNotNull(..) => "IsNotNull",
1269 Expr::IsNull(..) => "IsNull",
1270 Expr::Like { .. } => "Like",
1271 Expr::SimilarTo { .. } => "RLike",
1272 Expr::IsTrue(..) => "IsTrue",
1273 Expr::IsFalse(..) => "IsFalse",
1274 Expr::IsUnknown(..) => "IsUnknown",
1275 Expr::IsNotTrue(..) => "IsNotTrue",
1276 Expr::IsNotFalse(..) => "IsNotFalse",
1277 Expr::IsNotUnknown(..) => "IsNotUnknown",
1278 Expr::Literal(..) => "Literal",
1279 Expr::Negative(..) => "Negative",
1280 Expr::Not(..) => "Not",
1281 Expr::Placeholder(_) => "Placeholder",
1282 Expr::ScalarFunction(..) => "ScalarFunction",
1283 Expr::ScalarSubquery { .. } => "ScalarSubquery",
1284 Expr::ScalarVariable(..) => "ScalarVariable",
1285 Expr::TryCast { .. } => "TryCast",
1286 Expr::WindowFunction { .. } => "WindowFunction",
1287 #[expect(deprecated)]
1288 Expr::Wildcard { .. } => "Wildcard",
1289 Expr::Unnest { .. } => "Unnest",
1290 }
1291 }
1292
1293 pub fn eq(self, other: Expr) -> Expr {
1295 binary_expr(self, Operator::Eq, other)
1296 }
1297
1298 pub fn not_eq(self, other: Expr) -> Expr {
1300 binary_expr(self, Operator::NotEq, other)
1301 }
1302
1303 pub fn gt(self, other: Expr) -> Expr {
1305 binary_expr(self, Operator::Gt, other)
1306 }
1307
1308 pub fn gt_eq(self, other: Expr) -> Expr {
1310 binary_expr(self, Operator::GtEq, other)
1311 }
1312
1313 pub fn lt(self, other: Expr) -> Expr {
1315 binary_expr(self, Operator::Lt, other)
1316 }
1317
1318 pub fn lt_eq(self, other: Expr) -> Expr {
1320 binary_expr(self, Operator::LtEq, other)
1321 }
1322
1323 pub fn and(self, other: Expr) -> Expr {
1325 binary_expr(self, Operator::And, other)
1326 }
1327
1328 pub fn or(self, other: Expr) -> Expr {
1330 binary_expr(self, Operator::Or, other)
1331 }
1332
1333 pub fn like(self, other: Expr) -> Expr {
1335 Expr::Like(Like::new(
1336 false,
1337 Box::new(self),
1338 Box::new(other),
1339 None,
1340 false,
1341 ))
1342 }
1343
1344 pub fn not_like(self, other: Expr) -> Expr {
1346 Expr::Like(Like::new(
1347 true,
1348 Box::new(self),
1349 Box::new(other),
1350 None,
1351 false,
1352 ))
1353 }
1354
1355 pub fn ilike(self, other: Expr) -> Expr {
1357 Expr::Like(Like::new(
1358 false,
1359 Box::new(self),
1360 Box::new(other),
1361 None,
1362 true,
1363 ))
1364 }
1365
1366 pub fn not_ilike(self, other: Expr) -> Expr {
1368 Expr::Like(Like::new(true, Box::new(self), Box::new(other), None, true))
1369 }
1370
1371 pub fn name_for_alias(&self) -> Result<String> {
1373 Ok(self.schema_name().to_string())
1374 }
1375
1376 pub fn alias_if_changed(self, original_name: String) -> Result<Expr> {
1379 let new_name = self.name_for_alias()?;
1380 if new_name == original_name {
1381 return Ok(self);
1382 }
1383
1384 Ok(self.alias(original_name))
1385 }
1386
1387 pub fn alias(self, name: impl Into<String>) -> Expr {
1389 Expr::Alias(Alias::new(self, None::<&str>, name.into()))
1390 }
1391
1392 pub fn alias_with_metadata(
1406 self,
1407 name: impl Into<String>,
1408 metadata: Option<std::collections::HashMap<String, String>>,
1409 ) -> Expr {
1410 Expr::Alias(Alias::new(self, None::<&str>, name.into()).with_metadata(metadata))
1411 }
1412
1413 pub fn alias_qualified(
1415 self,
1416 relation: Option<impl Into<TableReference>>,
1417 name: impl Into<String>,
1418 ) -> Expr {
1419 Expr::Alias(Alias::new(self, relation, name.into()))
1420 }
1421
1422 pub fn alias_qualified_with_metadata(
1436 self,
1437 relation: Option<impl Into<TableReference>>,
1438 name: impl Into<String>,
1439 metadata: Option<std::collections::HashMap<String, String>>,
1440 ) -> Expr {
1441 Expr::Alias(Alias::new(self, relation, name.into()).with_metadata(metadata))
1442 }
1443
1444 pub fn unalias(self) -> Expr {
1465 match self {
1466 Expr::Alias(alias) => *alias.expr,
1467 _ => self,
1468 }
1469 }
1470
1471 pub fn unalias_nested(self) -> Transformed<Expr> {
1492 self.transform_down_up(
1493 |expr| {
1494 let recursion = if matches!(
1496 expr,
1497 Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_)
1498 ) {
1499 TreeNodeRecursion::Jump
1501 } else {
1502 TreeNodeRecursion::Continue
1503 };
1504 Ok(Transformed::new(expr, false, recursion))
1505 },
1506 |expr| {
1507 if let Expr::Alias(Alias { expr, .. }) = expr {
1510 Ok(Transformed::yes(*expr))
1511 } else {
1512 Ok(Transformed::no(expr))
1513 }
1514 },
1515 )
1516 .unwrap()
1518 }
1519
1520 pub fn in_list(self, list: Vec<Expr>, negated: bool) -> Expr {
1523 Expr::InList(InList::new(Box::new(self), list, negated))
1524 }
1525
1526 pub fn is_null(self) -> Expr {
1528 Expr::IsNull(Box::new(self))
1529 }
1530
1531 pub fn is_not_null(self) -> Expr {
1533 Expr::IsNotNull(Box::new(self))
1534 }
1535
1536 pub fn sort(self, asc: bool, nulls_first: bool) -> Sort {
1543 Sort::new(self, asc, nulls_first)
1544 }
1545
1546 pub fn is_true(self) -> Expr {
1548 Expr::IsTrue(Box::new(self))
1549 }
1550
1551 pub fn is_not_true(self) -> Expr {
1553 Expr::IsNotTrue(Box::new(self))
1554 }
1555
1556 pub fn is_false(self) -> Expr {
1558 Expr::IsFalse(Box::new(self))
1559 }
1560
1561 pub fn is_not_false(self) -> Expr {
1563 Expr::IsNotFalse(Box::new(self))
1564 }
1565
1566 pub fn is_unknown(self) -> Expr {
1568 Expr::IsUnknown(Box::new(self))
1569 }
1570
1571 pub fn is_not_unknown(self) -> Expr {
1573 Expr::IsNotUnknown(Box::new(self))
1574 }
1575
1576 pub fn between(self, low: Expr, high: Expr) -> Expr {
1578 Expr::Between(Between::new(
1579 Box::new(self),
1580 false,
1581 Box::new(low),
1582 Box::new(high),
1583 ))
1584 }
1585
1586 pub fn not_between(self, low: Expr, high: Expr) -> Expr {
1588 Expr::Between(Between::new(
1589 Box::new(self),
1590 true,
1591 Box::new(low),
1592 Box::new(high),
1593 ))
1594 }
1595 pub fn try_as_col(&self) -> Option<&Column> {
1613 if let Expr::Column(it) = self {
1614 Some(it)
1615 } else {
1616 None
1617 }
1618 }
1619
1620 pub fn get_as_join_column(&self) -> Option<&Column> {
1627 match self {
1628 Expr::Column(c) => Some(c),
1629 Expr::Cast(Cast { expr, .. }) => match &**expr {
1630 Expr::Column(c) => Some(c),
1631 _ => None,
1632 },
1633 _ => None,
1634 }
1635 }
1636
1637 pub fn column_refs(&self) -> HashSet<&Column> {
1653 let mut using_columns = HashSet::new();
1654 self.add_column_refs(&mut using_columns);
1655 using_columns
1656 }
1657
1658 pub fn add_column_refs<'a>(&'a self, set: &mut HashSet<&'a Column>) {
1662 self.apply(|expr| {
1663 if let Expr::Column(col) = expr {
1664 set.insert(col);
1665 }
1666 Ok(TreeNodeRecursion::Continue)
1667 })
1668 .expect("traversal is infallible");
1669 }
1670
1671 pub fn column_refs_counts(&self) -> HashMap<&Column, usize> {
1687 let mut map = HashMap::new();
1688 self.add_column_ref_counts(&mut map);
1689 map
1690 }
1691
1692 pub fn add_column_ref_counts<'a>(&'a self, map: &mut HashMap<&'a Column, usize>) {
1697 self.apply(|expr| {
1698 if let Expr::Column(col) = expr {
1699 *map.entry(col).or_default() += 1;
1700 }
1701 Ok(TreeNodeRecursion::Continue)
1702 })
1703 .expect("traversal is infallible");
1704 }
1705
1706 pub fn any_column_refs(&self) -> bool {
1708 self.exists(|expr| Ok(matches!(expr, Expr::Column(_))))
1709 .expect("exists closure is infallible")
1710 }
1711
1712 pub fn contains_outer(&self) -> bool {
1714 self.exists(|expr| Ok(matches!(expr, Expr::OuterReferenceColumn { .. })))
1715 .expect("exists closure is infallible")
1716 }
1717
1718 pub fn is_volatile_node(&self) -> bool {
1724 matches!(self, Expr::ScalarFunction(func) if func.func.signature().volatility == Volatility::Volatile)
1725 }
1726
1727 pub fn is_volatile(&self) -> bool {
1735 self.exists(|expr| Ok(expr.is_volatile_node()))
1736 .expect("exists closure is infallible")
1737 }
1738
1739 pub fn infer_placeholder_types(self, schema: &DFSchema) -> Result<(Expr, bool)> {
1748 let mut has_placeholder = false;
1749 self.transform(|mut expr| {
1750 if let Expr::BinaryExpr(BinaryExpr { left, op: _, right }) = &mut expr {
1752 rewrite_placeholder(left.as_mut(), right.as_ref(), schema)?;
1753 rewrite_placeholder(right.as_mut(), left.as_ref(), schema)?;
1754 };
1755 if let Expr::Between(Between {
1756 expr,
1757 negated: _,
1758 low,
1759 high,
1760 }) = &mut expr
1761 {
1762 rewrite_placeholder(low.as_mut(), expr.as_ref(), schema)?;
1763 rewrite_placeholder(high.as_mut(), expr.as_ref(), schema)?;
1764 }
1765 if let Expr::Placeholder(_) = &expr {
1766 has_placeholder = true;
1767 }
1768 Ok(Transformed::yes(expr))
1769 })
1770 .data()
1771 .map(|data| (data, has_placeholder))
1772 }
1773
1774 pub fn short_circuits(&self) -> bool {
1777 match self {
1778 Expr::ScalarFunction(ScalarFunction { func, .. }) => func.short_circuits(),
1779 Expr::BinaryExpr(BinaryExpr { op, .. }) => {
1780 matches!(op, Operator::And | Operator::Or)
1781 }
1782 Expr::Case { .. } => true,
1783 #[expect(deprecated)]
1788 Expr::AggregateFunction(..)
1789 | Expr::Alias(..)
1790 | Expr::Between(..)
1791 | Expr::Cast(..)
1792 | Expr::Column(..)
1793 | Expr::Exists(..)
1794 | Expr::GroupingSet(..)
1795 | Expr::InList(..)
1796 | Expr::InSubquery(..)
1797 | Expr::IsFalse(..)
1798 | Expr::IsNotFalse(..)
1799 | Expr::IsNotNull(..)
1800 | Expr::IsNotTrue(..)
1801 | Expr::IsNotUnknown(..)
1802 | Expr::IsNull(..)
1803 | Expr::IsTrue(..)
1804 | Expr::IsUnknown(..)
1805 | Expr::Like(..)
1806 | Expr::ScalarSubquery(..)
1807 | Expr::ScalarVariable(_, _)
1808 | Expr::SimilarTo(..)
1809 | Expr::Not(..)
1810 | Expr::Negative(..)
1811 | Expr::OuterReferenceColumn(_, _)
1812 | Expr::TryCast(..)
1813 | Expr::Unnest(..)
1814 | Expr::Wildcard { .. }
1815 | Expr::WindowFunction(..)
1816 | Expr::Literal(..)
1817 | Expr::Placeholder(..) => false,
1818 }
1819 }
1820
1821 pub fn spans(&self) -> Option<&Spans> {
1825 match self {
1826 Expr::Column(col) => Some(&col.spans),
1827 _ => None,
1828 }
1829 }
1830}
1831
1832impl Normalizeable for Expr {
1833 fn can_normalize(&self) -> bool {
1834 #[allow(clippy::match_like_matches_macro)]
1835 match self {
1836 Expr::BinaryExpr(BinaryExpr {
1837 op:
1838 _op @ (Operator::Plus
1839 | Operator::Multiply
1840 | Operator::BitwiseAnd
1841 | Operator::BitwiseOr
1842 | Operator::BitwiseXor
1843 | Operator::Eq
1844 | Operator::NotEq),
1845 ..
1846 }) => true,
1847 _ => false,
1848 }
1849 }
1850}
1851
1852impl NormalizeEq for Expr {
1853 fn normalize_eq(&self, other: &Self) -> bool {
1854 match (self, other) {
1855 (
1856 Expr::BinaryExpr(BinaryExpr {
1857 left: self_left,
1858 op: self_op,
1859 right: self_right,
1860 }),
1861 Expr::BinaryExpr(BinaryExpr {
1862 left: other_left,
1863 op: other_op,
1864 right: other_right,
1865 }),
1866 ) => {
1867 if self_op != other_op {
1868 return false;
1869 }
1870
1871 if matches!(
1872 self_op,
1873 Operator::Plus
1874 | Operator::Multiply
1875 | Operator::BitwiseAnd
1876 | Operator::BitwiseOr
1877 | Operator::BitwiseXor
1878 | Operator::Eq
1879 | Operator::NotEq
1880 ) {
1881 (self_left.normalize_eq(other_left)
1882 && self_right.normalize_eq(other_right))
1883 || (self_left.normalize_eq(other_right)
1884 && self_right.normalize_eq(other_left))
1885 } else {
1886 self_left.normalize_eq(other_left)
1887 && self_right.normalize_eq(other_right)
1888 }
1889 }
1890 (
1891 Expr::Alias(Alias {
1892 expr: self_expr,
1893 relation: self_relation,
1894 name: self_name,
1895 ..
1896 }),
1897 Expr::Alias(Alias {
1898 expr: other_expr,
1899 relation: other_relation,
1900 name: other_name,
1901 ..
1902 }),
1903 ) => {
1904 self_name == other_name
1905 && self_relation == other_relation
1906 && self_expr.normalize_eq(other_expr)
1907 }
1908 (
1909 Expr::Like(Like {
1910 negated: self_negated,
1911 expr: self_expr,
1912 pattern: self_pattern,
1913 escape_char: self_escape_char,
1914 case_insensitive: self_case_insensitive,
1915 }),
1916 Expr::Like(Like {
1917 negated: other_negated,
1918 expr: other_expr,
1919 pattern: other_pattern,
1920 escape_char: other_escape_char,
1921 case_insensitive: other_case_insensitive,
1922 }),
1923 )
1924 | (
1925 Expr::SimilarTo(Like {
1926 negated: self_negated,
1927 expr: self_expr,
1928 pattern: self_pattern,
1929 escape_char: self_escape_char,
1930 case_insensitive: self_case_insensitive,
1931 }),
1932 Expr::SimilarTo(Like {
1933 negated: other_negated,
1934 expr: other_expr,
1935 pattern: other_pattern,
1936 escape_char: other_escape_char,
1937 case_insensitive: other_case_insensitive,
1938 }),
1939 ) => {
1940 self_negated == other_negated
1941 && self_escape_char == other_escape_char
1942 && self_case_insensitive == other_case_insensitive
1943 && self_expr.normalize_eq(other_expr)
1944 && self_pattern.normalize_eq(other_pattern)
1945 }
1946 (Expr::Not(self_expr), Expr::Not(other_expr))
1947 | (Expr::IsNull(self_expr), Expr::IsNull(other_expr))
1948 | (Expr::IsTrue(self_expr), Expr::IsTrue(other_expr))
1949 | (Expr::IsFalse(self_expr), Expr::IsFalse(other_expr))
1950 | (Expr::IsUnknown(self_expr), Expr::IsUnknown(other_expr))
1951 | (Expr::IsNotNull(self_expr), Expr::IsNotNull(other_expr))
1952 | (Expr::IsNotTrue(self_expr), Expr::IsNotTrue(other_expr))
1953 | (Expr::IsNotFalse(self_expr), Expr::IsNotFalse(other_expr))
1954 | (Expr::IsNotUnknown(self_expr), Expr::IsNotUnknown(other_expr))
1955 | (Expr::Negative(self_expr), Expr::Negative(other_expr))
1956 | (
1957 Expr::Unnest(Unnest { expr: self_expr }),
1958 Expr::Unnest(Unnest { expr: other_expr }),
1959 ) => self_expr.normalize_eq(other_expr),
1960 (
1961 Expr::Between(Between {
1962 expr: self_expr,
1963 negated: self_negated,
1964 low: self_low,
1965 high: self_high,
1966 }),
1967 Expr::Between(Between {
1968 expr: other_expr,
1969 negated: other_negated,
1970 low: other_low,
1971 high: other_high,
1972 }),
1973 ) => {
1974 self_negated == other_negated
1975 && self_expr.normalize_eq(other_expr)
1976 && self_low.normalize_eq(other_low)
1977 && self_high.normalize_eq(other_high)
1978 }
1979 (
1980 Expr::Cast(Cast {
1981 expr: self_expr,
1982 data_type: self_data_type,
1983 }),
1984 Expr::Cast(Cast {
1985 expr: other_expr,
1986 data_type: other_data_type,
1987 }),
1988 )
1989 | (
1990 Expr::TryCast(TryCast {
1991 expr: self_expr,
1992 data_type: self_data_type,
1993 }),
1994 Expr::TryCast(TryCast {
1995 expr: other_expr,
1996 data_type: other_data_type,
1997 }),
1998 ) => self_data_type == other_data_type && self_expr.normalize_eq(other_expr),
1999 (
2000 Expr::ScalarFunction(ScalarFunction {
2001 func: self_func,
2002 args: self_args,
2003 }),
2004 Expr::ScalarFunction(ScalarFunction {
2005 func: other_func,
2006 args: other_args,
2007 }),
2008 ) => {
2009 self_func.name() == other_func.name()
2010 && self_args.len() == other_args.len()
2011 && self_args
2012 .iter()
2013 .zip(other_args.iter())
2014 .all(|(a, b)| a.normalize_eq(b))
2015 }
2016 (
2017 Expr::AggregateFunction(AggregateFunction {
2018 func: self_func,
2019 params:
2020 AggregateFunctionParams {
2021 args: self_args,
2022 distinct: self_distinct,
2023 filter: self_filter,
2024 order_by: self_order_by,
2025 null_treatment: self_null_treatment,
2026 },
2027 }),
2028 Expr::AggregateFunction(AggregateFunction {
2029 func: other_func,
2030 params:
2031 AggregateFunctionParams {
2032 args: other_args,
2033 distinct: other_distinct,
2034 filter: other_filter,
2035 order_by: other_order_by,
2036 null_treatment: other_null_treatment,
2037 },
2038 }),
2039 ) => {
2040 self_func.name() == other_func.name()
2041 && self_distinct == other_distinct
2042 && self_null_treatment == other_null_treatment
2043 && self_args.len() == other_args.len()
2044 && self_args
2045 .iter()
2046 .zip(other_args.iter())
2047 .all(|(a, b)| a.normalize_eq(b))
2048 && match (self_filter, other_filter) {
2049 (Some(self_filter), Some(other_filter)) => {
2050 self_filter.normalize_eq(other_filter)
2051 }
2052 (None, None) => true,
2053 _ => false,
2054 }
2055 && match (self_order_by, other_order_by) {
2056 (Some(self_order_by), Some(other_order_by)) => self_order_by
2057 .iter()
2058 .zip(other_order_by.iter())
2059 .all(|(a, b)| {
2060 a.asc == b.asc
2061 && a.nulls_first == b.nulls_first
2062 && a.expr.normalize_eq(&b.expr)
2063 }),
2064 (None, None) => true,
2065 _ => false,
2066 }
2067 }
2068 (
2069 Expr::WindowFunction(WindowFunction {
2070 fun: self_fun,
2071 params: self_params,
2072 }),
2073 Expr::WindowFunction(WindowFunction {
2074 fun: other_fun,
2075 params: other_params,
2076 }),
2077 ) => {
2078 let (
2079 WindowFunctionParams {
2080 args: self_args,
2081 window_frame: self_window_frame,
2082 partition_by: self_partition_by,
2083 order_by: self_order_by,
2084 null_treatment: self_null_treatment,
2085 },
2086 WindowFunctionParams {
2087 args: other_args,
2088 window_frame: other_window_frame,
2089 partition_by: other_partition_by,
2090 order_by: other_order_by,
2091 null_treatment: other_null_treatment,
2092 },
2093 ) = (self_params, other_params);
2094
2095 self_fun.name() == other_fun.name()
2096 && self_window_frame == other_window_frame
2097 && self_null_treatment == other_null_treatment
2098 && self_args.len() == other_args.len()
2099 && self_args
2100 .iter()
2101 .zip(other_args.iter())
2102 .all(|(a, b)| a.normalize_eq(b))
2103 && self_partition_by
2104 .iter()
2105 .zip(other_partition_by.iter())
2106 .all(|(a, b)| a.normalize_eq(b))
2107 && self_order_by
2108 .iter()
2109 .zip(other_order_by.iter())
2110 .all(|(a, b)| {
2111 a.asc == b.asc
2112 && a.nulls_first == b.nulls_first
2113 && a.expr.normalize_eq(&b.expr)
2114 })
2115 }
2116 (
2117 Expr::Exists(Exists {
2118 subquery: self_subquery,
2119 negated: self_negated,
2120 }),
2121 Expr::Exists(Exists {
2122 subquery: other_subquery,
2123 negated: other_negated,
2124 }),
2125 ) => {
2126 self_negated == other_negated
2127 && self_subquery.normalize_eq(other_subquery)
2128 }
2129 (
2130 Expr::InSubquery(InSubquery {
2131 expr: self_expr,
2132 subquery: self_subquery,
2133 negated: self_negated,
2134 }),
2135 Expr::InSubquery(InSubquery {
2136 expr: other_expr,
2137 subquery: other_subquery,
2138 negated: other_negated,
2139 }),
2140 ) => {
2141 self_negated == other_negated
2142 && self_expr.normalize_eq(other_expr)
2143 && self_subquery.normalize_eq(other_subquery)
2144 }
2145 (
2146 Expr::ScalarSubquery(self_subquery),
2147 Expr::ScalarSubquery(other_subquery),
2148 ) => self_subquery.normalize_eq(other_subquery),
2149 (
2150 Expr::GroupingSet(GroupingSet::Rollup(self_exprs)),
2151 Expr::GroupingSet(GroupingSet::Rollup(other_exprs)),
2152 )
2153 | (
2154 Expr::GroupingSet(GroupingSet::Cube(self_exprs)),
2155 Expr::GroupingSet(GroupingSet::Cube(other_exprs)),
2156 ) => {
2157 self_exprs.len() == other_exprs.len()
2158 && self_exprs
2159 .iter()
2160 .zip(other_exprs.iter())
2161 .all(|(a, b)| a.normalize_eq(b))
2162 }
2163 (
2164 Expr::GroupingSet(GroupingSet::GroupingSets(self_exprs)),
2165 Expr::GroupingSet(GroupingSet::GroupingSets(other_exprs)),
2166 ) => {
2167 self_exprs.len() == other_exprs.len()
2168 && self_exprs.iter().zip(other_exprs.iter()).all(|(a, b)| {
2169 a.len() == b.len()
2170 && a.iter().zip(b.iter()).all(|(x, y)| x.normalize_eq(y))
2171 })
2172 }
2173 (
2174 Expr::InList(InList {
2175 expr: self_expr,
2176 list: self_list,
2177 negated: self_negated,
2178 }),
2179 Expr::InList(InList {
2180 expr: other_expr,
2181 list: other_list,
2182 negated: other_negated,
2183 }),
2184 ) => {
2185 self_negated == other_negated
2187 && self_expr.normalize_eq(other_expr)
2188 && self_list.len() == other_list.len()
2189 && self_list
2190 .iter()
2191 .zip(other_list.iter())
2192 .all(|(a, b)| a.normalize_eq(b))
2193 }
2194 (
2195 Expr::Case(Case {
2196 expr: self_expr,
2197 when_then_expr: self_when_then_expr,
2198 else_expr: self_else_expr,
2199 }),
2200 Expr::Case(Case {
2201 expr: other_expr,
2202 when_then_expr: other_when_then_expr,
2203 else_expr: other_else_expr,
2204 }),
2205 ) => {
2206 self_when_then_expr.len() == other_when_then_expr.len()
2209 && self_when_then_expr
2210 .iter()
2211 .zip(other_when_then_expr.iter())
2212 .all(|((self_when, self_then), (other_when, other_then))| {
2213 self_when.normalize_eq(other_when)
2214 && self_then.normalize_eq(other_then)
2215 })
2216 && match (self_expr, other_expr) {
2217 (Some(self_expr), Some(other_expr)) => {
2218 self_expr.normalize_eq(other_expr)
2219 }
2220 (None, None) => true,
2221 (_, _) => false,
2222 }
2223 && match (self_else_expr, other_else_expr) {
2224 (Some(self_else_expr), Some(other_else_expr)) => {
2225 self_else_expr.normalize_eq(other_else_expr)
2226 }
2227 (None, None) => true,
2228 (_, _) => false,
2229 }
2230 }
2231 (_, _) => self == other,
2232 }
2233 }
2234}
2235
2236impl HashNode for Expr {
2237 fn hash_node<H: Hasher>(&self, state: &mut H) {
2241 mem::discriminant(self).hash(state);
2242 match self {
2243 Expr::Alias(Alias {
2244 expr: _expr,
2245 relation,
2246 name,
2247 ..
2248 }) => {
2249 relation.hash(state);
2250 name.hash(state);
2251 }
2252 Expr::Column(column) => {
2253 column.hash(state);
2254 }
2255 Expr::ScalarVariable(data_type, name) => {
2256 data_type.hash(state);
2257 name.hash(state);
2258 }
2259 Expr::Literal(scalar_value) => {
2260 scalar_value.hash(state);
2261 }
2262 Expr::BinaryExpr(BinaryExpr {
2263 left: _left,
2264 op,
2265 right: _right,
2266 }) => {
2267 op.hash(state);
2268 }
2269 Expr::Like(Like {
2270 negated,
2271 expr: _expr,
2272 pattern: _pattern,
2273 escape_char,
2274 case_insensitive,
2275 })
2276 | Expr::SimilarTo(Like {
2277 negated,
2278 expr: _expr,
2279 pattern: _pattern,
2280 escape_char,
2281 case_insensitive,
2282 }) => {
2283 negated.hash(state);
2284 escape_char.hash(state);
2285 case_insensitive.hash(state);
2286 }
2287 Expr::Not(_expr)
2288 | Expr::IsNotNull(_expr)
2289 | Expr::IsNull(_expr)
2290 | Expr::IsTrue(_expr)
2291 | Expr::IsFalse(_expr)
2292 | Expr::IsUnknown(_expr)
2293 | Expr::IsNotTrue(_expr)
2294 | Expr::IsNotFalse(_expr)
2295 | Expr::IsNotUnknown(_expr)
2296 | Expr::Negative(_expr) => {}
2297 Expr::Between(Between {
2298 expr: _expr,
2299 negated,
2300 low: _low,
2301 high: _high,
2302 }) => {
2303 negated.hash(state);
2304 }
2305 Expr::Case(Case {
2306 expr: _expr,
2307 when_then_expr: _when_then_expr,
2308 else_expr: _else_expr,
2309 }) => {}
2310 Expr::Cast(Cast {
2311 expr: _expr,
2312 data_type,
2313 })
2314 | Expr::TryCast(TryCast {
2315 expr: _expr,
2316 data_type,
2317 }) => {
2318 data_type.hash(state);
2319 }
2320 Expr::ScalarFunction(ScalarFunction { func, args: _args }) => {
2321 func.hash(state);
2322 }
2323 Expr::AggregateFunction(AggregateFunction {
2324 func,
2325 params:
2326 AggregateFunctionParams {
2327 args: _args,
2328 distinct,
2329 filter: _,
2330 order_by: _,
2331 null_treatment,
2332 },
2333 }) => {
2334 func.hash(state);
2335 distinct.hash(state);
2336 null_treatment.hash(state);
2337 }
2338 Expr::WindowFunction(WindowFunction { fun, params }) => {
2339 let WindowFunctionParams {
2340 args: _args,
2341 partition_by: _,
2342 order_by: _,
2343 window_frame,
2344 null_treatment,
2345 } = params;
2346 fun.hash(state);
2347 window_frame.hash(state);
2348 null_treatment.hash(state);
2349 }
2350 Expr::InList(InList {
2351 expr: _expr,
2352 list: _list,
2353 negated,
2354 }) => {
2355 negated.hash(state);
2356 }
2357 Expr::Exists(Exists { subquery, negated }) => {
2358 subquery.hash(state);
2359 negated.hash(state);
2360 }
2361 Expr::InSubquery(InSubquery {
2362 expr: _expr,
2363 subquery,
2364 negated,
2365 }) => {
2366 subquery.hash(state);
2367 negated.hash(state);
2368 }
2369 Expr::ScalarSubquery(subquery) => {
2370 subquery.hash(state);
2371 }
2372 #[expect(deprecated)]
2373 Expr::Wildcard { qualifier, options } => {
2374 qualifier.hash(state);
2375 options.hash(state);
2376 }
2377 Expr::GroupingSet(grouping_set) => {
2378 mem::discriminant(grouping_set).hash(state);
2379 match grouping_set {
2380 GroupingSet::Rollup(_exprs) | GroupingSet::Cube(_exprs) => {}
2381 GroupingSet::GroupingSets(_exprs) => {}
2382 }
2383 }
2384 Expr::Placeholder(place_holder) => {
2385 place_holder.hash(state);
2386 }
2387 Expr::OuterReferenceColumn(data_type, column) => {
2388 data_type.hash(state);
2389 column.hash(state);
2390 }
2391 Expr::Unnest(Unnest { expr: _expr }) => {}
2392 };
2393 }
2394}
2395
2396fn rewrite_placeholder(expr: &mut Expr, other: &Expr, schema: &DFSchema) -> Result<()> {
2398 if let Expr::Placeholder(Placeholder { id: _, data_type }) = expr {
2399 if data_type.is_none() {
2400 let other_dt = other.get_type(schema);
2401 match other_dt {
2402 Err(e) => {
2403 Err(e.context(format!(
2404 "Can not find type of {other} needed to infer type of {expr}"
2405 )))?;
2406 }
2407 Ok(dt) => {
2408 *data_type = Some(dt);
2409 }
2410 }
2411 };
2412 }
2413 Ok(())
2414}
2415
2416#[macro_export]
2417macro_rules! expr_vec_fmt {
2418 ( $ARRAY:expr ) => {{
2419 $ARRAY
2420 .iter()
2421 .map(|e| format!("{e}"))
2422 .collect::<Vec<String>>()
2423 .join(", ")
2424 }};
2425}
2426
2427struct SchemaDisplay<'a>(&'a Expr);
2428impl Display for SchemaDisplay<'_> {
2429 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2430 match self.0 {
2431 #[expect(deprecated)]
2434 Expr::Column(_)
2435 | Expr::Literal(_)
2436 | Expr::ScalarVariable(..)
2437 | Expr::OuterReferenceColumn(..)
2438 | Expr::Placeholder(_)
2439 | Expr::Wildcard { .. } => write!(f, "{}", self.0),
2440 Expr::AggregateFunction(AggregateFunction { func, params }) => {
2441 match func.schema_name(params) {
2442 Ok(name) => {
2443 write!(f, "{name}")
2444 }
2445 Err(e) => {
2446 write!(f, "got error from schema_name {}", e)
2447 }
2448 }
2449 }
2450 Expr::Alias(Alias {
2452 name,
2453 relation: Some(relation),
2454 ..
2455 }) => write!(f, "{relation}.{name}"),
2456 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
2457 Expr::Between(Between {
2458 expr,
2459 negated,
2460 low,
2461 high,
2462 }) => {
2463 if *negated {
2464 write!(
2465 f,
2466 "{} NOT BETWEEN {} AND {}",
2467 SchemaDisplay(expr),
2468 SchemaDisplay(low),
2469 SchemaDisplay(high),
2470 )
2471 } else {
2472 write!(
2473 f,
2474 "{} BETWEEN {} AND {}",
2475 SchemaDisplay(expr),
2476 SchemaDisplay(low),
2477 SchemaDisplay(high),
2478 )
2479 }
2480 }
2481 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2482 write!(f, "{} {op} {}", SchemaDisplay(left), SchemaDisplay(right),)
2483 }
2484 Expr::Case(Case {
2485 expr,
2486 when_then_expr,
2487 else_expr,
2488 }) => {
2489 write!(f, "CASE ")?;
2490
2491 if let Some(e) = expr {
2492 write!(f, "{} ", SchemaDisplay(e))?;
2493 }
2494
2495 for (when, then) in when_then_expr {
2496 write!(
2497 f,
2498 "WHEN {} THEN {} ",
2499 SchemaDisplay(when),
2500 SchemaDisplay(then),
2501 )?;
2502 }
2503
2504 if let Some(e) = else_expr {
2505 write!(f, "ELSE {} ", SchemaDisplay(e))?;
2506 }
2507
2508 write!(f, "END")
2509 }
2510 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
2512 write!(f, "{}", SchemaDisplay(expr))
2513 }
2514 Expr::InList(InList {
2515 expr,
2516 list,
2517 negated,
2518 }) => {
2519 let inlist_name = schema_name_from_exprs(list)?;
2520
2521 if *negated {
2522 write!(f, "{} NOT IN {}", SchemaDisplay(expr), inlist_name)
2523 } else {
2524 write!(f, "{} IN {}", SchemaDisplay(expr), inlist_name)
2525 }
2526 }
2527 Expr::Exists(Exists { negated: true, .. }) => write!(f, "NOT EXISTS"),
2528 Expr::Exists(Exists { negated: false, .. }) => write!(f, "EXISTS"),
2529 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
2530 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2531 }
2532 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
2533 write!(f, "GROUPING SETS (")?;
2534 for exprs in lists_of_exprs.iter() {
2535 write!(f, "({})", schema_name_from_exprs(exprs)?)?;
2536 }
2537 write!(f, ")")
2538 }
2539 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
2540 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2541 }
2542 Expr::IsNull(expr) => write!(f, "{} IS NULL", SchemaDisplay(expr)),
2543 Expr::IsNotNull(expr) => {
2544 write!(f, "{} IS NOT NULL", SchemaDisplay(expr))
2545 }
2546 Expr::IsUnknown(expr) => {
2547 write!(f, "{} IS UNKNOWN", SchemaDisplay(expr))
2548 }
2549 Expr::IsNotUnknown(expr) => {
2550 write!(f, "{} IS NOT UNKNOWN", SchemaDisplay(expr))
2551 }
2552 Expr::InSubquery(InSubquery { negated: true, .. }) => {
2553 write!(f, "NOT IN")
2554 }
2555 Expr::InSubquery(InSubquery { negated: false, .. }) => write!(f, "IN"),
2556 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SchemaDisplay(expr)),
2557 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SchemaDisplay(expr)),
2558 Expr::IsNotTrue(expr) => {
2559 write!(f, "{} IS NOT TRUE", SchemaDisplay(expr))
2560 }
2561 Expr::IsNotFalse(expr) => {
2562 write!(f, "{} IS NOT FALSE", SchemaDisplay(expr))
2563 }
2564 Expr::Like(Like {
2565 negated,
2566 expr,
2567 pattern,
2568 escape_char,
2569 case_insensitive,
2570 }) => {
2571 write!(
2572 f,
2573 "{} {}{} {}",
2574 SchemaDisplay(expr),
2575 if *negated { "NOT " } else { "" },
2576 if *case_insensitive { "ILIKE" } else { "LIKE" },
2577 SchemaDisplay(pattern),
2578 )?;
2579
2580 if let Some(char) = escape_char {
2581 write!(f, " CHAR '{char}'")?;
2582 }
2583
2584 Ok(())
2585 }
2586 Expr::Negative(expr) => write!(f, "(- {})", SchemaDisplay(expr)),
2587 Expr::Not(expr) => write!(f, "NOT {}", SchemaDisplay(expr)),
2588 Expr::Unnest(Unnest { expr }) => {
2589 write!(f, "UNNEST({})", SchemaDisplay(expr))
2590 }
2591 Expr::ScalarFunction(ScalarFunction { func, args }) => {
2592 match func.schema_name(args) {
2593 Ok(name) => {
2594 write!(f, "{name}")
2595 }
2596 Err(e) => {
2597 write!(f, "got error from schema_name {}", e)
2598 }
2599 }
2600 }
2601 Expr::ScalarSubquery(Subquery { subquery, .. }) => {
2602 write!(f, "{}", subquery.schema().field(0).name())
2603 }
2604 Expr::SimilarTo(Like {
2605 negated,
2606 expr,
2607 pattern,
2608 escape_char,
2609 ..
2610 }) => {
2611 write!(
2612 f,
2613 "{} {} {}",
2614 SchemaDisplay(expr),
2615 if *negated {
2616 "NOT SIMILAR TO"
2617 } else {
2618 "SIMILAR TO"
2619 },
2620 SchemaDisplay(pattern),
2621 )?;
2622 if let Some(char) = escape_char {
2623 write!(f, " CHAR '{char}'")?;
2624 }
2625
2626 Ok(())
2627 }
2628 Expr::WindowFunction(WindowFunction { fun, params }) => match fun {
2629 WindowFunctionDefinition::AggregateUDF(fun) => {
2630 match fun.window_function_schema_name(params) {
2631 Ok(name) => {
2632 write!(f, "{name}")
2633 }
2634 Err(e) => {
2635 write!(f, "got error from window_function_schema_name {}", e)
2636 }
2637 }
2638 }
2639 _ => {
2640 let WindowFunctionParams {
2641 args,
2642 partition_by,
2643 order_by,
2644 window_frame,
2645 null_treatment,
2646 } = params;
2647
2648 write!(
2649 f,
2650 "{}({})",
2651 fun,
2652 schema_name_from_exprs_comma_separated_without_space(args)?
2653 )?;
2654
2655 if let Some(null_treatment) = null_treatment {
2656 write!(f, " {}", null_treatment)?;
2657 }
2658
2659 if !partition_by.is_empty() {
2660 write!(
2661 f,
2662 " PARTITION BY [{}]",
2663 schema_name_from_exprs(partition_by)?
2664 )?;
2665 }
2666
2667 if !order_by.is_empty() {
2668 write!(f, " ORDER BY [{}]", schema_name_from_sorts(order_by)?)?;
2669 };
2670
2671 write!(f, " {window_frame}")
2672 }
2673 },
2674 }
2675 }
2676}
2677
2678struct SqlDisplay<'a>(&'a Expr);
2680
2681impl Display for SqlDisplay<'_> {
2682 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2683 match self.0 {
2684 Expr::Literal(scalar) => scalar.fmt(f),
2685 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
2686 Expr::Between(Between {
2687 expr,
2688 negated,
2689 low,
2690 high,
2691 }) => {
2692 if *negated {
2693 write!(
2694 f,
2695 "{} NOT BETWEEN {} AND {}",
2696 SqlDisplay(expr),
2697 SqlDisplay(low),
2698 SqlDisplay(high),
2699 )
2700 } else {
2701 write!(
2702 f,
2703 "{} BETWEEN {} AND {}",
2704 SqlDisplay(expr),
2705 SqlDisplay(low),
2706 SqlDisplay(high),
2707 )
2708 }
2709 }
2710 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2711 write!(f, "{} {op} {}", SqlDisplay(left), SqlDisplay(right),)
2712 }
2713 Expr::Case(Case {
2714 expr,
2715 when_then_expr,
2716 else_expr,
2717 }) => {
2718 write!(f, "CASE ")?;
2719
2720 if let Some(e) = expr {
2721 write!(f, "{} ", SqlDisplay(e))?;
2722 }
2723
2724 for (when, then) in when_then_expr {
2725 write!(f, "WHEN {} THEN {} ", SqlDisplay(when), SqlDisplay(then),)?;
2726 }
2727
2728 if let Some(e) = else_expr {
2729 write!(f, "ELSE {} ", SqlDisplay(e))?;
2730 }
2731
2732 write!(f, "END")
2733 }
2734 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
2735 write!(f, "{}", SqlDisplay(expr))
2736 }
2737 Expr::InList(InList {
2738 expr,
2739 list,
2740 negated,
2741 }) => {
2742 write!(
2743 f,
2744 "{}{} IN {}",
2745 SqlDisplay(expr),
2746 if *negated { " NOT" } else { "" },
2747 ExprListDisplay::comma_separated(list.as_slice())
2748 )
2749 }
2750 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
2751 write!(
2752 f,
2753 "ROLLUP ({})",
2754 ExprListDisplay::comma_separated(exprs.as_slice())
2755 )
2756 }
2757 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
2758 write!(f, "GROUPING SETS (")?;
2759 for exprs in lists_of_exprs.iter() {
2760 write!(
2761 f,
2762 "({})",
2763 ExprListDisplay::comma_separated(exprs.as_slice())
2764 )?;
2765 }
2766 write!(f, ")")
2767 }
2768 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
2769 write!(
2770 f,
2771 "ROLLUP ({})",
2772 ExprListDisplay::comma_separated(exprs.as_slice())
2773 )
2774 }
2775 Expr::IsNull(expr) => write!(f, "{} IS NULL", SqlDisplay(expr)),
2776 Expr::IsNotNull(expr) => {
2777 write!(f, "{} IS NOT NULL", SqlDisplay(expr))
2778 }
2779 Expr::IsUnknown(expr) => {
2780 write!(f, "{} IS UNKNOWN", SqlDisplay(expr))
2781 }
2782 Expr::IsNotUnknown(expr) => {
2783 write!(f, "{} IS NOT UNKNOWN", SqlDisplay(expr))
2784 }
2785 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SqlDisplay(expr)),
2786 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SqlDisplay(expr)),
2787 Expr::IsNotTrue(expr) => {
2788 write!(f, "{} IS NOT TRUE", SqlDisplay(expr))
2789 }
2790 Expr::IsNotFalse(expr) => {
2791 write!(f, "{} IS NOT FALSE", SqlDisplay(expr))
2792 }
2793 Expr::Like(Like {
2794 negated,
2795 expr,
2796 pattern,
2797 escape_char,
2798 case_insensitive,
2799 }) => {
2800 write!(
2801 f,
2802 "{} {}{} {}",
2803 SqlDisplay(expr),
2804 if *negated { "NOT " } else { "" },
2805 if *case_insensitive { "ILIKE" } else { "LIKE" },
2806 SqlDisplay(pattern),
2807 )?;
2808
2809 if let Some(char) = escape_char {
2810 write!(f, " CHAR '{char}'")?;
2811 }
2812
2813 Ok(())
2814 }
2815 Expr::Negative(expr) => write!(f, "(- {})", SqlDisplay(expr)),
2816 Expr::Not(expr) => write!(f, "NOT {}", SqlDisplay(expr)),
2817 Expr::Unnest(Unnest { expr }) => {
2818 write!(f, "UNNEST({})", SqlDisplay(expr))
2819 }
2820 Expr::SimilarTo(Like {
2821 negated,
2822 expr,
2823 pattern,
2824 escape_char,
2825 ..
2826 }) => {
2827 write!(
2828 f,
2829 "{} {} {}",
2830 SqlDisplay(expr),
2831 if *negated {
2832 "NOT SIMILAR TO"
2833 } else {
2834 "SIMILAR TO"
2835 },
2836 SqlDisplay(pattern),
2837 )?;
2838 if let Some(char) = escape_char {
2839 write!(f, " CHAR '{char}'")?;
2840 }
2841
2842 Ok(())
2843 }
2844 Expr::AggregateFunction(AggregateFunction { func, params }) => {
2845 match func.human_display(params) {
2846 Ok(name) => {
2847 write!(f, "{name}")
2848 }
2849 Err(e) => {
2850 write!(f, "got error from schema_name {}", e)
2851 }
2852 }
2853 }
2854 _ => write!(f, "{}", self.0),
2855 }
2856 }
2857}
2858
2859pub(crate) fn schema_name_from_exprs_comma_separated_without_space(
2865 exprs: &[Expr],
2866) -> Result<String, fmt::Error> {
2867 schema_name_from_exprs_inner(exprs, ",")
2868}
2869
2870pub struct ExprListDisplay<'a> {
2872 exprs: &'a [Expr],
2873 sep: &'a str,
2874}
2875
2876impl<'a> ExprListDisplay<'a> {
2877 pub fn new(exprs: &'a [Expr], sep: &'a str) -> Self {
2879 Self { exprs, sep }
2880 }
2881
2882 pub fn comma_separated(exprs: &'a [Expr]) -> Self {
2884 Self::new(exprs, ", ")
2885 }
2886}
2887
2888impl Display for ExprListDisplay<'_> {
2889 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
2890 let mut first = true;
2891 for expr in self.exprs {
2892 if !first {
2893 write!(f, "{}", self.sep)?;
2894 }
2895 write!(f, "{}", SqlDisplay(expr))?;
2896 first = false;
2897 }
2898 Ok(())
2899 }
2900}
2901
2902pub fn schema_name_from_exprs(exprs: &[Expr]) -> Result<String, fmt::Error> {
2904 schema_name_from_exprs_inner(exprs, ", ")
2905}
2906
2907fn schema_name_from_exprs_inner(exprs: &[Expr], sep: &str) -> Result<String, fmt::Error> {
2908 let mut s = String::new();
2909 for (i, e) in exprs.iter().enumerate() {
2910 if i > 0 {
2911 write!(&mut s, "{sep}")?;
2912 }
2913 write!(&mut s, "{}", SchemaDisplay(e))?;
2914 }
2915
2916 Ok(s)
2917}
2918
2919pub fn schema_name_from_sorts(sorts: &[Sort]) -> Result<String, fmt::Error> {
2920 let mut s = String::new();
2921 for (i, e) in sorts.iter().enumerate() {
2922 if i > 0 {
2923 write!(&mut s, ", ")?;
2924 }
2925 let ordering = if e.asc { "ASC" } else { "DESC" };
2926 let nulls_ordering = if e.nulls_first {
2927 "NULLS FIRST"
2928 } else {
2929 "NULLS LAST"
2930 };
2931 write!(&mut s, "{} {} {}", e.expr, ordering, nulls_ordering)?;
2932 }
2933
2934 Ok(s)
2935}
2936
2937pub const OUTER_REFERENCE_COLUMN_PREFIX: &str = "outer_ref";
2938pub const UNNEST_COLUMN_PREFIX: &str = "UNNEST";
2939
2940impl Display for Expr {
2943 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
2944 match self {
2945 Expr::Alias(Alias { expr, name, .. }) => write!(f, "{expr} AS {name}"),
2946 Expr::Column(c) => write!(f, "{c}"),
2947 Expr::OuterReferenceColumn(_, c) => {
2948 write!(f, "{OUTER_REFERENCE_COLUMN_PREFIX}({c})")
2949 }
2950 Expr::ScalarVariable(_, var_names) => write!(f, "{}", var_names.join(".")),
2951 Expr::Literal(v) => write!(f, "{v:?}"),
2952 Expr::Case(case) => {
2953 write!(f, "CASE ")?;
2954 if let Some(e) = &case.expr {
2955 write!(f, "{e} ")?;
2956 }
2957 for (w, t) in &case.when_then_expr {
2958 write!(f, "WHEN {w} THEN {t} ")?;
2959 }
2960 if let Some(e) = &case.else_expr {
2961 write!(f, "ELSE {e} ")?;
2962 }
2963 write!(f, "END")
2964 }
2965 Expr::Cast(Cast { expr, data_type }) => {
2966 write!(f, "CAST({expr} AS {data_type:?})")
2967 }
2968 Expr::TryCast(TryCast { expr, data_type }) => {
2969 write!(f, "TRY_CAST({expr} AS {data_type:?})")
2970 }
2971 Expr::Not(expr) => write!(f, "NOT {expr}"),
2972 Expr::Negative(expr) => write!(f, "(- {expr})"),
2973 Expr::IsNull(expr) => write!(f, "{expr} IS NULL"),
2974 Expr::IsNotNull(expr) => write!(f, "{expr} IS NOT NULL"),
2975 Expr::IsTrue(expr) => write!(f, "{expr} IS TRUE"),
2976 Expr::IsFalse(expr) => write!(f, "{expr} IS FALSE"),
2977 Expr::IsUnknown(expr) => write!(f, "{expr} IS UNKNOWN"),
2978 Expr::IsNotTrue(expr) => write!(f, "{expr} IS NOT TRUE"),
2979 Expr::IsNotFalse(expr) => write!(f, "{expr} IS NOT FALSE"),
2980 Expr::IsNotUnknown(expr) => write!(f, "{expr} IS NOT UNKNOWN"),
2981 Expr::Exists(Exists {
2982 subquery,
2983 negated: true,
2984 }) => write!(f, "NOT EXISTS ({subquery:?})"),
2985 Expr::Exists(Exists {
2986 subquery,
2987 negated: false,
2988 }) => write!(f, "EXISTS ({subquery:?})"),
2989 Expr::InSubquery(InSubquery {
2990 expr,
2991 subquery,
2992 negated: true,
2993 }) => write!(f, "{expr} NOT IN ({subquery:?})"),
2994 Expr::InSubquery(InSubquery {
2995 expr,
2996 subquery,
2997 negated: false,
2998 }) => write!(f, "{expr} IN ({subquery:?})"),
2999 Expr::ScalarSubquery(subquery) => write!(f, "({subquery:?})"),
3000 Expr::BinaryExpr(expr) => write!(f, "{expr}"),
3001 Expr::ScalarFunction(fun) => {
3002 fmt_function(f, fun.name(), false, &fun.args, true)
3003 }
3004 Expr::WindowFunction(WindowFunction { fun, params }) => match fun {
3009 WindowFunctionDefinition::AggregateUDF(fun) => {
3010 match fun.window_function_display_name(params) {
3011 Ok(name) => {
3012 write!(f, "{}", name)
3013 }
3014 Err(e) => {
3015 write!(f, "got error from window_function_display_name {}", e)
3016 }
3017 }
3018 }
3019 WindowFunctionDefinition::WindowUDF(fun) => {
3020 let WindowFunctionParams {
3021 args,
3022 partition_by,
3023 order_by,
3024 window_frame,
3025 null_treatment,
3026 } = params;
3027
3028 fmt_function(f, &fun.to_string(), false, args, true)?;
3029
3030 if let Some(nt) = null_treatment {
3031 write!(f, "{}", nt)?;
3032 }
3033
3034 if !partition_by.is_empty() {
3035 write!(f, " PARTITION BY [{}]", expr_vec_fmt!(partition_by))?;
3036 }
3037 if !order_by.is_empty() {
3038 write!(f, " ORDER BY [{}]", expr_vec_fmt!(order_by))?;
3039 }
3040 write!(
3041 f,
3042 " {} BETWEEN {} AND {}",
3043 window_frame.units,
3044 window_frame.start_bound,
3045 window_frame.end_bound
3046 )
3047 }
3048 },
3049 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3050 match func.display_name(params) {
3051 Ok(name) => {
3052 write!(f, "{}", name)
3053 }
3054 Err(e) => {
3055 write!(f, "got error from display_name {}", e)
3056 }
3057 }
3058 }
3059 Expr::Between(Between {
3060 expr,
3061 negated,
3062 low,
3063 high,
3064 }) => {
3065 if *negated {
3066 write!(f, "{expr} NOT BETWEEN {low} AND {high}")
3067 } else {
3068 write!(f, "{expr} BETWEEN {low} AND {high}")
3069 }
3070 }
3071 Expr::Like(Like {
3072 negated,
3073 expr,
3074 pattern,
3075 escape_char,
3076 case_insensitive,
3077 }) => {
3078 write!(f, "{expr}")?;
3079 let op_name = if *case_insensitive { "ILIKE" } else { "LIKE" };
3080 if *negated {
3081 write!(f, " NOT")?;
3082 }
3083 if let Some(char) = escape_char {
3084 write!(f, " {op_name} {pattern} ESCAPE '{char}'")
3085 } else {
3086 write!(f, " {op_name} {pattern}")
3087 }
3088 }
3089 Expr::SimilarTo(Like {
3090 negated,
3091 expr,
3092 pattern,
3093 escape_char,
3094 case_insensitive: _,
3095 }) => {
3096 write!(f, "{expr}")?;
3097 if *negated {
3098 write!(f, " NOT")?;
3099 }
3100 if let Some(char) = escape_char {
3101 write!(f, " SIMILAR TO {pattern} ESCAPE '{char}'")
3102 } else {
3103 write!(f, " SIMILAR TO {pattern}")
3104 }
3105 }
3106 Expr::InList(InList {
3107 expr,
3108 list,
3109 negated,
3110 }) => {
3111 if *negated {
3112 write!(f, "{expr} NOT IN ([{}])", expr_vec_fmt!(list))
3113 } else {
3114 write!(f, "{expr} IN ([{}])", expr_vec_fmt!(list))
3115 }
3116 }
3117 #[expect(deprecated)]
3118 Expr::Wildcard { qualifier, options } => match qualifier {
3119 Some(qualifier) => write!(f, "{qualifier}.*{options}"),
3120 None => write!(f, "*{options}"),
3121 },
3122 Expr::GroupingSet(grouping_sets) => match grouping_sets {
3123 GroupingSet::Rollup(exprs) => {
3124 write!(f, "ROLLUP ({})", expr_vec_fmt!(exprs))
3126 }
3127 GroupingSet::Cube(exprs) => {
3128 write!(f, "CUBE ({})", expr_vec_fmt!(exprs))
3130 }
3131 GroupingSet::GroupingSets(lists_of_exprs) => {
3132 write!(
3134 f,
3135 "GROUPING SETS ({})",
3136 lists_of_exprs
3137 .iter()
3138 .map(|exprs| format!("({})", expr_vec_fmt!(exprs)))
3139 .collect::<Vec<String>>()
3140 .join(", ")
3141 )
3142 }
3143 },
3144 Expr::Placeholder(Placeholder { id, .. }) => write!(f, "{id}"),
3145 Expr::Unnest(Unnest { expr }) => {
3146 write!(f, "{UNNEST_COLUMN_PREFIX}({expr})")
3147 }
3148 }
3149 }
3150}
3151
3152fn fmt_function(
3153 f: &mut Formatter,
3154 fun: &str,
3155 distinct: bool,
3156 args: &[Expr],
3157 display: bool,
3158) -> fmt::Result {
3159 let args: Vec<String> = match display {
3160 true => args.iter().map(|arg| format!("{arg}")).collect(),
3161 false => args.iter().map(|arg| format!("{arg:?}")).collect(),
3162 };
3163
3164 let distinct_str = match distinct {
3165 true => "DISTINCT ",
3166 false => "",
3167 };
3168 write!(f, "{}({}{})", fun, distinct_str, args.join(", "))
3169}
3170
3171pub fn physical_name(expr: &Expr) -> Result<String> {
3174 match expr {
3175 Expr::Column(col) => Ok(col.name.clone()),
3176 Expr::Alias(alias) => Ok(alias.name.clone()),
3177 _ => Ok(expr.schema_name().to_string()),
3178 }
3179}
3180
3181#[cfg(test)]
3182mod test {
3183 use crate::expr_fn::col;
3184 use crate::{
3185 case, lit, qualified_wildcard, wildcard, wildcard_with_options, ColumnarValue,
3186 ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl, Volatility,
3187 };
3188 use sqlparser::ast;
3189 use sqlparser::ast::{Ident, IdentWithAlias};
3190 use std::any::Any;
3191
3192 #[test]
3193 #[allow(deprecated)]
3194 fn format_case_when() -> Result<()> {
3195 let expr = case(col("a"))
3196 .when(lit(1), lit(true))
3197 .when(lit(0), lit(false))
3198 .otherwise(lit(ScalarValue::Null))?;
3199 let expected = "CASE a WHEN Int32(1) THEN Boolean(true) WHEN Int32(0) THEN Boolean(false) ELSE NULL END";
3200 assert_eq!(expected, expr.canonical_name());
3201 assert_eq!(expected, format!("{expr}"));
3202 Ok(())
3203 }
3204
3205 #[test]
3206 #[allow(deprecated)]
3207 fn format_cast() -> Result<()> {
3208 let expr = Expr::Cast(Cast {
3209 expr: Box::new(Expr::Literal(ScalarValue::Float32(Some(1.23)))),
3210 data_type: DataType::Utf8,
3211 });
3212 let expected_canonical = "CAST(Float32(1.23) AS Utf8)";
3213 assert_eq!(expected_canonical, expr.canonical_name());
3214 assert_eq!(expected_canonical, format!("{expr}"));
3215 assert_eq!("Float32(1.23)", expr.schema_name().to_string());
3218 Ok(())
3219 }
3220
3221 #[test]
3222 fn test_partial_ord() {
3223 let exp1 = col("a") + lit(1);
3226 let exp2 = col("a") + lit(2);
3227 let exp3 = !(col("a") + lit(2));
3228
3229 assert!(exp1 < exp2);
3230 assert!(exp3 > exp2);
3231 assert!(exp1 < exp3)
3232 }
3233
3234 #[test]
3235 fn test_collect_expr() -> Result<()> {
3236 {
3238 let expr = &Expr::Cast(Cast::new(Box::new(col("a")), DataType::Float64));
3239 let columns = expr.column_refs();
3240 assert_eq!(1, columns.len());
3241 assert!(columns.contains(&Column::from_name("a")));
3242 }
3243
3244 {
3246 let expr = col("a") + col("b") + lit(1);
3247 let columns = expr.column_refs();
3248 assert_eq!(2, columns.len());
3249 assert!(columns.contains(&Column::from_name("a")));
3250 assert!(columns.contains(&Column::from_name("b")));
3251 }
3252
3253 Ok(())
3254 }
3255
3256 #[test]
3257 fn test_logical_ops() {
3258 assert_eq!(
3259 format!("{}", lit(1u32).eq(lit(2u32))),
3260 "UInt32(1) = UInt32(2)"
3261 );
3262 assert_eq!(
3263 format!("{}", lit(1u32).not_eq(lit(2u32))),
3264 "UInt32(1) != UInt32(2)"
3265 );
3266 assert_eq!(
3267 format!("{}", lit(1u32).gt(lit(2u32))),
3268 "UInt32(1) > UInt32(2)"
3269 );
3270 assert_eq!(
3271 format!("{}", lit(1u32).gt_eq(lit(2u32))),
3272 "UInt32(1) >= UInt32(2)"
3273 );
3274 assert_eq!(
3275 format!("{}", lit(1u32).lt(lit(2u32))),
3276 "UInt32(1) < UInt32(2)"
3277 );
3278 assert_eq!(
3279 format!("{}", lit(1u32).lt_eq(lit(2u32))),
3280 "UInt32(1) <= UInt32(2)"
3281 );
3282 assert_eq!(
3283 format!("{}", lit(1u32).and(lit(2u32))),
3284 "UInt32(1) AND UInt32(2)"
3285 );
3286 assert_eq!(
3287 format!("{}", lit(1u32).or(lit(2u32))),
3288 "UInt32(1) OR UInt32(2)"
3289 );
3290 }
3291
3292 #[test]
3293 fn test_is_volatile_scalar_func() {
3294 #[derive(Debug)]
3296 struct TestScalarUDF {
3297 signature: Signature,
3298 }
3299 impl ScalarUDFImpl for TestScalarUDF {
3300 fn as_any(&self) -> &dyn Any {
3301 self
3302 }
3303 fn name(&self) -> &str {
3304 "TestScalarUDF"
3305 }
3306
3307 fn signature(&self) -> &Signature {
3308 &self.signature
3309 }
3310
3311 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
3312 Ok(DataType::Utf8)
3313 }
3314
3315 fn invoke_with_args(
3316 &self,
3317 _args: ScalarFunctionArgs,
3318 ) -> Result<ColumnarValue> {
3319 Ok(ColumnarValue::Scalar(ScalarValue::from("a")))
3320 }
3321 }
3322 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3323 signature: Signature::uniform(1, vec![DataType::Float32], Volatility::Stable),
3324 }));
3325 assert_ne!(udf.signature().volatility, Volatility::Volatile);
3326
3327 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3328 signature: Signature::uniform(
3329 1,
3330 vec![DataType::Float32],
3331 Volatility::Volatile,
3332 ),
3333 }));
3334 assert_eq!(udf.signature().volatility, Volatility::Volatile);
3335 }
3336
3337 use super::*;
3338
3339 #[test]
3340 fn test_display_wildcard() {
3341 assert_eq!(format!("{}", wildcard()), "*");
3342 assert_eq!(format!("{}", qualified_wildcard("t1")), "t1.*");
3343 assert_eq!(
3344 format!(
3345 "{}",
3346 wildcard_with_options(wildcard_options(
3347 Some(IlikeSelectItem {
3348 pattern: "c1".to_string()
3349 }),
3350 None,
3351 None,
3352 None,
3353 None
3354 ))
3355 ),
3356 "* ILIKE 'c1'"
3357 );
3358 assert_eq!(
3359 format!(
3360 "{}",
3361 wildcard_with_options(wildcard_options(
3362 None,
3363 Some(ExcludeSelectItem::Multiple(vec![
3364 Ident::from("c1"),
3365 Ident::from("c2")
3366 ])),
3367 None,
3368 None,
3369 None
3370 ))
3371 ),
3372 "* EXCLUDE (c1, c2)"
3373 );
3374 assert_eq!(
3375 format!(
3376 "{}",
3377 wildcard_with_options(wildcard_options(
3378 None,
3379 None,
3380 Some(ExceptSelectItem {
3381 first_element: Ident::from("c1"),
3382 additional_elements: vec![Ident::from("c2")]
3383 }),
3384 None,
3385 None
3386 ))
3387 ),
3388 "* EXCEPT (c1, c2)"
3389 );
3390 assert_eq!(
3391 format!(
3392 "{}",
3393 wildcard_with_options(wildcard_options(
3394 None,
3395 None,
3396 None,
3397 Some(PlannedReplaceSelectItem {
3398 items: vec![ReplaceSelectElement {
3399 expr: ast::Expr::Identifier(Ident::from("c1")),
3400 column_name: Ident::from("a1"),
3401 as_keyword: false
3402 }],
3403 planned_expressions: vec![]
3404 }),
3405 None
3406 ))
3407 ),
3408 "* REPLACE (c1 a1)"
3409 );
3410 assert_eq!(
3411 format!(
3412 "{}",
3413 wildcard_with_options(wildcard_options(
3414 None,
3415 None,
3416 None,
3417 None,
3418 Some(RenameSelectItem::Multiple(vec![IdentWithAlias {
3419 ident: Ident::from("c1"),
3420 alias: Ident::from("a1")
3421 }]))
3422 ))
3423 ),
3424 "* RENAME (c1 AS a1)"
3425 )
3426 }
3427
3428 #[test]
3429 fn test_schema_display_alias_with_relation() {
3430 assert_eq!(
3431 format!(
3432 "{}",
3433 SchemaDisplay(
3434 &lit(1).alias_qualified("table_name".into(), "column_name")
3435 )
3436 ),
3437 "table_name.column_name"
3438 );
3439 }
3440
3441 #[test]
3442 fn test_schema_display_alias_without_relation() {
3443 assert_eq!(
3444 format!(
3445 "{}",
3446 SchemaDisplay(&lit(1).alias_qualified(None::<&str>, "column_name"))
3447 ),
3448 "column_name"
3449 );
3450 }
3451
3452 fn wildcard_options(
3453 opt_ilike: Option<IlikeSelectItem>,
3454 opt_exclude: Option<ExcludeSelectItem>,
3455 opt_except: Option<ExceptSelectItem>,
3456 opt_replace: Option<PlannedReplaceSelectItem>,
3457 opt_rename: Option<RenameSelectItem>,
3458 ) -> WildcardOptions {
3459 WildcardOptions {
3460 ilike: opt_ilike,
3461 exclude: opt_exclude,
3462 except: opt_except,
3463 replace: opt_replace,
3464 rename: opt_rename,
3465 }
3466 }
3467}