1use std::cmp::Ordering;
21use std::collections::HashSet;
22use std::fmt::{self, Display, Formatter, Write};
23use std::hash::{Hash, Hasher};
24use std::mem;
25use std::sync::Arc;
26
27use crate::expr_fn::binary_expr;
28use crate::function::WindowFunctionSimplification;
29use crate::logical_plan::Subquery;
30use crate::{AggregateUDF, Volatility};
31use crate::{ExprSchemable, Operator, Signature, WindowFrame, WindowUDF};
32
33use arrow::datatypes::{DataType, Field, FieldRef};
34use datafusion_common::cse::{HashNode, NormalizeEq, Normalizeable};
35use datafusion_common::tree_node::{
36 Transformed, TransformedResult, TreeNode, TreeNodeContainer, TreeNodeRecursion,
37};
38use datafusion_common::{
39 Column, DFSchema, HashMap, Result, ScalarValue, Spans, TableReference,
40};
41use datafusion_expr_common::placement::ExpressionPlacement;
42use datafusion_functions_window_common::field::WindowUDFFieldArgs;
43#[cfg(feature = "sql")]
44use sqlparser::ast::{
45 ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem, RenameSelectItem,
46 ReplaceSelectElement,
47};
48
49pub use datafusion_common::metadata::FieldMetadata;
51use datafusion_common::metadata::ScalarAndMetadata;
52
53#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
56pub enum NullTreatment {
57 IgnoreNulls,
58 RespectNulls,
59}
60
61impl Display for NullTreatment {
62 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63 f.write_str(match self {
64 NullTreatment::IgnoreNulls => "IGNORE NULLS",
65 NullTreatment::RespectNulls => "RESPECT NULLS",
66 })
67 }
68}
69
70#[cfg(feature = "sql")]
71impl From<sqlparser::ast::NullTreatment> for NullTreatment {
72 fn from(value: sqlparser::ast::NullTreatment) -> Self {
73 match value {
74 sqlparser::ast::NullTreatment::IgnoreNulls => Self::IgnoreNulls,
75 sqlparser::ast::NullTreatment::RespectNulls => Self::RespectNulls,
76 }
77 }
78}
79
80#[derive(Clone, PartialEq, PartialOrd, Eq, Debug, Hash)]
315pub enum Expr {
316 Alias(Alias),
318 Column(Column),
320 ScalarVariable(FieldRef, Vec<String>),
322 Literal(ScalarValue, Option<FieldMetadata>),
324 BinaryExpr(BinaryExpr),
326 Like(Like),
328 SimilarTo(Like),
330 Not(Box<Expr>),
332 IsNotNull(Box<Expr>),
334 IsNull(Box<Expr>),
336 IsTrue(Box<Expr>),
338 IsFalse(Box<Expr>),
340 IsUnknown(Box<Expr>),
342 IsNotTrue(Box<Expr>),
344 IsNotFalse(Box<Expr>),
346 IsNotUnknown(Box<Expr>),
348 Negative(Box<Expr>),
350 Between(Between),
352 Case(Case),
354 Cast(Cast),
357 TryCast(TryCast),
360 ScalarFunction(ScalarFunction),
362 AggregateFunction(AggregateFunction),
369 WindowFunction(Box<WindowFunction>),
371 InList(InList),
373 Exists(Exists),
375 InSubquery(InSubquery),
377 SetComparison(SetComparison),
379 ScalarSubquery(Subquery),
381 #[deprecated(
387 since = "46.0.0",
388 note = "A wildcard needs to be resolved to concrete expressions when constructing the logical plan. See https://github.com/apache/datafusion/issues/7765"
389 )]
390 Wildcard {
391 qualifier: Option<TableReference>,
392 options: Box<WildcardOptions>,
393 },
394 GroupingSet(GroupingSet),
397 Placeholder(Placeholder),
400 OuterReferenceColumn(FieldRef, Column),
403 Unnest(Unnest),
405}
406
407impl Default for Expr {
408 fn default() -> Self {
409 Expr::Literal(ScalarValue::Null, None)
410 }
411}
412
413impl AsRef<Expr> for Expr {
414 fn as_ref(&self) -> &Expr {
415 self
416 }
417}
418
419impl From<Column> for Expr {
421 fn from(value: Column) -> Self {
422 Expr::Column(value)
423 }
424}
425
426impl From<WindowFunction> for Expr {
428 fn from(value: WindowFunction) -> Self {
429 Expr::WindowFunction(Box::new(value))
430 }
431}
432
433impl From<ScalarAndMetadata> for Expr {
435 fn from(value: ScalarAndMetadata) -> Self {
436 let (value, metadata) = value.into_inner();
437 Expr::Literal(value, metadata)
438 }
439}
440
441impl<'a> From<(Option<&'a TableReference>, &'a FieldRef)> for Expr {
446 fn from(value: (Option<&'a TableReference>, &'a FieldRef)) -> Self {
447 Expr::from(Column::from(value))
448 }
449}
450
451impl<'a> TreeNodeContainer<'a, Self> for Expr {
452 fn apply_elements<F: FnMut(&'a Self) -> Result<TreeNodeRecursion>>(
453 &'a self,
454 mut f: F,
455 ) -> Result<TreeNodeRecursion> {
456 f(self)
457 }
458
459 fn map_elements<F: FnMut(Self) -> Result<Transformed<Self>>>(
460 self,
461 mut f: F,
462 ) -> Result<Transformed<Self>> {
463 f(self)
464 }
465}
466
467pub type SchemaFieldMetadata = std::collections::HashMap<String, String>;
488
489pub fn intersect_metadata_for_union<'a>(
511 metadatas: impl IntoIterator<Item = &'a SchemaFieldMetadata>,
512) -> SchemaFieldMetadata {
513 let mut metadatas = metadatas.into_iter();
514 let Some(mut intersected) = metadatas.next().cloned() else {
515 return Default::default();
516 };
517
518 for metadata in metadatas {
519 intersected.retain(|k, v| metadata.get(k) == Some(v));
521 }
522
523 intersected
524}
525
526#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
528pub struct Unnest {
529 pub expr: Box<Expr>,
530}
531
532impl Unnest {
533 pub fn new(expr: Expr) -> Self {
535 Self {
536 expr: Box::new(expr),
537 }
538 }
539
540 pub fn new_boxed(boxed: Box<Expr>) -> Self {
542 Self { expr: boxed }
543 }
544}
545
546#[derive(Clone, PartialEq, Eq, Debug)]
548pub struct Alias {
549 pub expr: Box<Expr>,
550 pub relation: Option<TableReference>,
551 pub name: String,
552 pub metadata: Option<FieldMetadata>,
553}
554
555impl Hash for Alias {
556 fn hash<H: Hasher>(&self, state: &mut H) {
557 self.expr.hash(state);
558 self.relation.hash(state);
559 self.name.hash(state);
560 }
561}
562
563impl PartialOrd for Alias {
564 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
565 let cmp = self.expr.partial_cmp(&other.expr);
566 let Some(Ordering::Equal) = cmp else {
567 return cmp;
568 };
569 let cmp = self.relation.partial_cmp(&other.relation);
570 let Some(Ordering::Equal) = cmp else {
571 return cmp;
572 };
573 self.name
574 .partial_cmp(&other.name)
575 .filter(|cmp| *cmp != Ordering::Equal || self == other)
577 }
578}
579
580impl Alias {
581 pub fn new(
583 expr: Expr,
584 relation: Option<impl Into<TableReference>>,
585 name: impl Into<String>,
586 ) -> Self {
587 Self {
588 expr: Box::new(expr),
589 relation: relation.map(|r| r.into()),
590 name: name.into(),
591 metadata: None,
592 }
593 }
594
595 pub fn with_metadata(mut self, metadata: Option<FieldMetadata>) -> Self {
596 self.metadata = metadata;
597 self
598 }
599}
600
601#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
603pub struct BinaryExpr {
604 pub left: Box<Expr>,
606 pub op: Operator,
608 pub right: Box<Expr>,
610}
611
612impl BinaryExpr {
613 pub fn new(left: Box<Expr>, op: Operator, right: Box<Expr>) -> Self {
615 Self { left, op, right }
616 }
617}
618
619impl Display for BinaryExpr {
620 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
621 fn write_child(
627 f: &mut Formatter<'_>,
628 expr: &Expr,
629 precedence: u8,
630 ) -> fmt::Result {
631 match expr {
632 Expr::BinaryExpr(child) => {
633 let p = child.op.precedence();
634 if p == 0 || p < precedence {
635 write!(f, "({child})")?;
636 } else {
637 write!(f, "{child}")?;
638 }
639 }
640 _ => write!(f, "{expr}")?,
641 }
642 Ok(())
643 }
644
645 let precedence = self.op.precedence();
646 write_child(f, self.left.as_ref(), precedence)?;
647 write!(f, " {} ", self.op)?;
648 write_child(f, self.right.as_ref(), precedence)
649 }
650}
651
652#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
676pub struct Case {
677 pub expr: Option<Box<Expr>>,
679 pub when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
681 pub else_expr: Option<Box<Expr>>,
683}
684
685impl Case {
686 pub fn new(
688 expr: Option<Box<Expr>>,
689 when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
690 else_expr: Option<Box<Expr>>,
691 ) -> Self {
692 Self {
693 expr,
694 when_then_expr,
695 else_expr,
696 }
697 }
698}
699
700#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
702pub struct Like {
703 pub negated: bool,
704 pub expr: Box<Expr>,
705 pub pattern: Box<Expr>,
706 pub escape_char: Option<char>,
707 pub case_insensitive: bool,
709}
710
711impl Like {
712 pub fn new(
714 negated: bool,
715 expr: Box<Expr>,
716 pattern: Box<Expr>,
717 escape_char: Option<char>,
718 case_insensitive: bool,
719 ) -> Self {
720 Self {
721 negated,
722 expr,
723 pattern,
724 escape_char,
725 case_insensitive,
726 }
727 }
728}
729
730#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
732pub struct Between {
733 pub expr: Box<Expr>,
735 pub negated: bool,
737 pub low: Box<Expr>,
739 pub high: Box<Expr>,
741}
742
743impl Between {
744 pub fn new(expr: Box<Expr>, negated: bool, low: Box<Expr>, high: Box<Expr>) -> Self {
746 Self {
747 expr,
748 negated,
749 low,
750 high,
751 }
752 }
753}
754
755#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
759pub struct ScalarFunction {
760 pub func: Arc<crate::ScalarUDF>,
762 pub args: Vec<Expr>,
764}
765
766impl ScalarFunction {
767 pub fn name(&self) -> &str {
769 self.func.name()
770 }
771}
772
773impl ScalarFunction {
774 pub fn new_udf(udf: Arc<crate::ScalarUDF>, args: Vec<Expr>) -> Self {
778 Self { func: udf, args }
779 }
780}
781
782#[derive(Clone, PartialEq, Eq, Hash, Debug)]
784pub enum GetFieldAccess {
785 NamedStructField { name: ScalarValue },
787 ListIndex { key: Box<Expr> },
789 ListRange {
791 start: Box<Expr>,
792 stop: Box<Expr>,
793 stride: Box<Expr>,
794 },
795}
796
797#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
799pub struct Cast {
800 pub expr: Box<Expr>,
802 pub data_type: DataType,
804}
805
806impl Cast {
807 pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
809 Self { expr, data_type }
810 }
811}
812
813#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
815pub struct TryCast {
816 pub expr: Box<Expr>,
818 pub data_type: DataType,
820}
821
822impl TryCast {
823 pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
825 Self { expr, data_type }
826 }
827}
828
829#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
831pub struct Sort {
832 pub expr: Expr,
834 pub asc: bool,
836 pub nulls_first: bool,
838}
839
840impl Sort {
841 pub fn new(expr: Expr, asc: bool, nulls_first: bool) -> Self {
843 Self {
844 expr,
845 asc,
846 nulls_first,
847 }
848 }
849
850 pub fn reverse(&self) -> Self {
852 Self {
853 expr: self.expr.clone(),
854 asc: !self.asc,
855 nulls_first: !self.nulls_first,
856 }
857 }
858
859 pub fn with_expr(&self, expr: Expr) -> Self {
861 Self {
862 expr,
863 asc: self.asc,
864 nulls_first: self.nulls_first,
865 }
866 }
867}
868
869impl Display for Sort {
870 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
871 write!(f, "{}", self.expr)?;
872 if self.asc {
873 write!(f, " ASC")?;
874 } else {
875 write!(f, " DESC")?;
876 }
877 if self.nulls_first {
878 write!(f, " NULLS FIRST")?;
879 } else {
880 write!(f, " NULLS LAST")?;
881 }
882 Ok(())
883 }
884}
885
886impl<'a> TreeNodeContainer<'a, Expr> for Sort {
887 fn apply_elements<F: FnMut(&'a Expr) -> Result<TreeNodeRecursion>>(
888 &'a self,
889 f: F,
890 ) -> Result<TreeNodeRecursion> {
891 self.expr.apply_elements(f)
892 }
893
894 fn map_elements<F: FnMut(Expr) -> Result<Transformed<Expr>>>(
895 self,
896 f: F,
897 ) -> Result<Transformed<Self>> {
898 self.expr
899 .map_elements(f)?
900 .map_data(|expr| Ok(Self { expr, ..self }))
901 }
902}
903
904#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
910pub struct AggregateFunction {
911 pub func: Arc<AggregateUDF>,
913 pub params: AggregateFunctionParams,
914}
915
916#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
917pub struct AggregateFunctionParams {
918 pub args: Vec<Expr>,
919 pub distinct: bool,
921 pub filter: Option<Box<Expr>>,
923 pub order_by: Vec<Sort>,
925 pub null_treatment: Option<NullTreatment>,
926}
927
928impl AggregateFunction {
929 pub fn new_udf(
931 func: Arc<AggregateUDF>,
932 args: Vec<Expr>,
933 distinct: bool,
934 filter: Option<Box<Expr>>,
935 order_by: Vec<Sort>,
936 null_treatment: Option<NullTreatment>,
937 ) -> Self {
938 Self {
939 func,
940 params: AggregateFunctionParams {
941 args,
942 distinct,
943 filter,
944 order_by,
945 null_treatment,
946 },
947 }
948 }
949}
950
951#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
957pub enum WindowFunctionDefinition {
958 AggregateUDF(Arc<AggregateUDF>),
960 WindowUDF(Arc<WindowUDF>),
962}
963
964impl WindowFunctionDefinition {
965 pub fn return_field(
967 &self,
968 input_expr_fields: &[FieldRef],
969 display_name: &str,
970 ) -> Result<FieldRef> {
971 match self {
972 WindowFunctionDefinition::AggregateUDF(fun) => {
973 fun.return_field(input_expr_fields)
974 }
975 WindowFunctionDefinition::WindowUDF(fun) => {
976 fun.field(WindowUDFFieldArgs::new(input_expr_fields, display_name))
977 }
978 }
979 }
980
981 pub fn signature(&self) -> Signature {
983 match self {
984 WindowFunctionDefinition::AggregateUDF(fun) => fun.signature().clone(),
985 WindowFunctionDefinition::WindowUDF(fun) => fun.signature().clone(),
986 }
987 }
988
989 pub fn name(&self) -> &str {
991 match self {
992 WindowFunctionDefinition::WindowUDF(fun) => fun.name(),
993 WindowFunctionDefinition::AggregateUDF(fun) => fun.name(),
994 }
995 }
996
997 pub fn simplify(&self) -> Option<WindowFunctionSimplification> {
1001 match self {
1002 WindowFunctionDefinition::AggregateUDF(_) => None,
1003 WindowFunctionDefinition::WindowUDF(udwf) => udwf.simplify(),
1004 }
1005 }
1006}
1007
1008impl Display for WindowFunctionDefinition {
1009 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1010 match self {
1011 WindowFunctionDefinition::AggregateUDF(fun) => Display::fmt(fun, f),
1012 WindowFunctionDefinition::WindowUDF(fun) => Display::fmt(fun, f),
1013 }
1014 }
1015}
1016
1017impl From<Arc<AggregateUDF>> for WindowFunctionDefinition {
1018 fn from(value: Arc<AggregateUDF>) -> Self {
1019 Self::AggregateUDF(value)
1020 }
1021}
1022
1023impl From<Arc<WindowUDF>> for WindowFunctionDefinition {
1024 fn from(value: Arc<WindowUDF>) -> Self {
1025 Self::WindowUDF(value)
1026 }
1027}
1028
1029#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1042pub struct WindowFunction {
1043 pub fun: WindowFunctionDefinition,
1045 pub params: WindowFunctionParams,
1046}
1047
1048#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1049pub struct WindowFunctionParams {
1050 pub args: Vec<Expr>,
1052 pub partition_by: Vec<Expr>,
1054 pub order_by: Vec<Sort>,
1056 pub window_frame: WindowFrame,
1058 pub filter: Option<Box<Expr>>,
1060 pub null_treatment: Option<NullTreatment>,
1062 pub distinct: bool,
1064}
1065
1066impl WindowFunction {
1067 pub fn new(fun: impl Into<WindowFunctionDefinition>, args: Vec<Expr>) -> Self {
1070 Self {
1071 fun: fun.into(),
1072 params: WindowFunctionParams {
1073 args,
1074 partition_by: Vec::default(),
1075 order_by: Vec::default(),
1076 window_frame: WindowFrame::new(None),
1077 filter: None,
1078 null_treatment: None,
1079 distinct: false,
1080 },
1081 }
1082 }
1083
1084 pub fn simplify(&self) -> Option<WindowFunctionSimplification> {
1088 self.fun.simplify()
1089 }
1090}
1091
1092#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1094pub struct Exists {
1095 pub subquery: Subquery,
1097 pub negated: bool,
1099}
1100
1101impl Exists {
1102 pub fn new(subquery: Subquery, negated: bool) -> Self {
1104 Self { subquery, negated }
1105 }
1106}
1107
1108#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Hash, Debug)]
1110pub enum SetQuantifier {
1111 Any,
1113 All,
1115}
1116
1117impl Display for SetQuantifier {
1118 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1119 match self {
1120 SetQuantifier::Any => write!(f, "ANY"),
1121 SetQuantifier::All => write!(f, "ALL"),
1122 }
1123 }
1124}
1125
1126#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1128pub struct SetComparison {
1129 pub expr: Box<Expr>,
1131 pub subquery: Subquery,
1133 pub op: Operator,
1135 pub quantifier: SetQuantifier,
1137}
1138
1139impl SetComparison {
1140 pub fn new(
1142 expr: Box<Expr>,
1143 subquery: Subquery,
1144 op: Operator,
1145 quantifier: SetQuantifier,
1146 ) -> Self {
1147 Self {
1148 expr,
1149 subquery,
1150 op,
1151 quantifier,
1152 }
1153 }
1154}
1155
1156#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1158pub struct InList {
1159 pub expr: Box<Expr>,
1161 pub list: Vec<Expr>,
1163 pub negated: bool,
1165}
1166
1167impl InList {
1168 pub fn new(expr: Box<Expr>, list: Vec<Expr>, negated: bool) -> Self {
1170 Self {
1171 expr,
1172 list,
1173 negated,
1174 }
1175 }
1176}
1177
1178#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1180pub struct InSubquery {
1181 pub expr: Box<Expr>,
1183 pub subquery: Subquery,
1185 pub negated: bool,
1187}
1188
1189impl InSubquery {
1190 pub fn new(expr: Box<Expr>, subquery: Subquery, negated: bool) -> Self {
1192 Self {
1193 expr,
1194 subquery,
1195 negated,
1196 }
1197 }
1198}
1199
1200#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1205pub struct Placeholder {
1206 pub id: String,
1208 pub field: Option<FieldRef>,
1210}
1211
1212impl Placeholder {
1213 #[deprecated(since = "51.0.0", note = "Use new_with_field instead")]
1215 pub fn new(id: String, data_type: Option<DataType>) -> Self {
1216 Self {
1217 id,
1218 field: data_type.map(|dt| Arc::new(Field::new("", dt, true))),
1219 }
1220 }
1221
1222 pub fn new_with_field(id: String, field: Option<FieldRef>) -> Self {
1224 Self { id, field }
1225 }
1226}
1227
1228#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1235pub enum GroupingSet {
1236 Rollup(Vec<Expr>),
1238 Cube(Vec<Expr>),
1240 GroupingSets(Vec<Vec<Expr>>),
1242}
1243
1244impl GroupingSet {
1245 pub fn distinct_expr(&self) -> Vec<&Expr> {
1249 match self {
1250 GroupingSet::Rollup(exprs) | GroupingSet::Cube(exprs) => {
1251 exprs.iter().collect()
1252 }
1253 GroupingSet::GroupingSets(groups) => {
1254 let mut exprs: Vec<&Expr> = vec![];
1255 for exp in groups.iter().flatten() {
1256 if !exprs.contains(&exp) {
1257 exprs.push(exp);
1258 }
1259 }
1260 exprs
1261 }
1262 }
1263 }
1264}
1265
1266#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1267#[cfg(not(feature = "sql"))]
1268pub struct IlikeSelectItem {
1269 pub pattern: String,
1270}
1271#[cfg(not(feature = "sql"))]
1272impl Display for IlikeSelectItem {
1273 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1274 write!(f, "ILIKE '{}'", &self.pattern)?;
1275 Ok(())
1276 }
1277}
1278#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1279#[cfg(not(feature = "sql"))]
1280pub enum ExcludeSelectItem {
1281 Single(Ident),
1282 Multiple(Vec<Ident>),
1283}
1284#[cfg(not(feature = "sql"))]
1285impl Display for ExcludeSelectItem {
1286 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1287 write!(f, "EXCLUDE")?;
1288 match self {
1289 Self::Single(column) => {
1290 write!(f, " {column}")?;
1291 }
1292 Self::Multiple(columns) => {
1293 write!(f, " ({})", display_comma_separated(columns))?;
1294 }
1295 }
1296 Ok(())
1297 }
1298}
1299#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1300#[cfg(not(feature = "sql"))]
1301pub struct ExceptSelectItem {
1302 pub first_element: Ident,
1303 pub additional_elements: Vec<Ident>,
1304}
1305#[cfg(not(feature = "sql"))]
1306impl Display for ExceptSelectItem {
1307 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1308 write!(f, "EXCEPT ")?;
1309 if self.additional_elements.is_empty() {
1310 write!(f, "({})", self.first_element)?;
1311 } else {
1312 write!(
1313 f,
1314 "({}, {})",
1315 self.first_element,
1316 display_comma_separated(&self.additional_elements)
1317 )?;
1318 }
1319 Ok(())
1320 }
1321}
1322
1323pub fn display_comma_separated<T>(slice: &[T]) -> String
1324where
1325 T: Display,
1326{
1327 use itertools::Itertools;
1328 slice.iter().map(|v| format!("{v}")).join(", ")
1329}
1330
1331#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1332#[cfg(not(feature = "sql"))]
1333pub enum RenameSelectItem {
1334 Single(String),
1335 Multiple(Vec<String>),
1336}
1337#[cfg(not(feature = "sql"))]
1338impl Display for RenameSelectItem {
1339 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1340 write!(f, "RENAME")?;
1341 match self {
1342 Self::Single(column) => {
1343 write!(f, " {column}")?;
1344 }
1345 Self::Multiple(columns) => {
1346 write!(f, " ({})", display_comma_separated(columns))?;
1347 }
1348 }
1349 Ok(())
1350 }
1351}
1352
1353#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1354#[cfg(not(feature = "sql"))]
1355pub struct Ident {
1356 pub value: String,
1358 pub quote_style: Option<char>,
1361 pub span: String,
1363}
1364#[cfg(not(feature = "sql"))]
1365impl Display for Ident {
1366 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1367 write!(f, "[{}]", self.value)
1368 }
1369}
1370
1371#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1372#[cfg(not(feature = "sql"))]
1373pub struct ReplaceSelectElement {
1374 pub expr: String,
1375 pub column_name: Ident,
1376 pub as_keyword: bool,
1377}
1378#[cfg(not(feature = "sql"))]
1379impl Display for ReplaceSelectElement {
1380 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1381 if self.as_keyword {
1382 write!(f, "{} AS {}", self.expr, self.column_name)
1383 } else {
1384 write!(f, "{} {}", self.expr, self.column_name)
1385 }
1386 }
1387}
1388
1389#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1391pub struct WildcardOptions {
1392 pub ilike: Option<IlikeSelectItem>,
1395 pub exclude: Option<ExcludeSelectItem>,
1398 pub except: Option<ExceptSelectItem>,
1402 pub replace: Option<PlannedReplaceSelectItem>,
1407 pub rename: Option<RenameSelectItem>,
1410}
1411
1412impl WildcardOptions {
1413 pub fn with_replace(self, replace: PlannedReplaceSelectItem) -> Self {
1414 WildcardOptions {
1415 ilike: self.ilike,
1416 exclude: self.exclude,
1417 except: self.except,
1418 replace: Some(replace),
1419 rename: self.rename,
1420 }
1421 }
1422}
1423
1424impl Display for WildcardOptions {
1425 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1426 if let Some(ilike) = &self.ilike {
1427 write!(f, " {ilike}")?;
1428 }
1429 if let Some(exclude) = &self.exclude {
1430 write!(f, " {exclude}")?;
1431 }
1432 if let Some(except) = &self.except {
1433 write!(f, " {except}")?;
1434 }
1435 if let Some(replace) = &self.replace {
1436 write!(f, " {replace}")?;
1437 }
1438 if let Some(rename) = &self.rename {
1439 write!(f, " {rename}")?;
1440 }
1441 Ok(())
1442 }
1443}
1444
1445#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1447pub struct PlannedReplaceSelectItem {
1448 pub items: Vec<ReplaceSelectElement>,
1450 pub planned_expressions: Vec<Expr>,
1452}
1453
1454impl Display for PlannedReplaceSelectItem {
1455 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1456 write!(f, "REPLACE")?;
1457 write!(f, " ({})", display_comma_separated(&self.items))?;
1458 Ok(())
1459 }
1460}
1461
1462impl PlannedReplaceSelectItem {
1463 pub fn items(&self) -> &[ReplaceSelectElement] {
1464 &self.items
1465 }
1466
1467 pub fn expressions(&self) -> &[Expr] {
1468 &self.planned_expressions
1469 }
1470}
1471
1472impl Expr {
1473 pub fn schema_name(&self) -> impl Display + '_ {
1496 SchemaDisplay(self)
1497 }
1498
1499 pub fn human_display(&self) -> impl Display + '_ {
1521 SqlDisplay(self)
1522 }
1523
1524 pub fn qualified_name(&self) -> (Option<TableReference>, String) {
1530 match self {
1531 Expr::Column(Column {
1532 relation,
1533 name,
1534 spans: _,
1535 }) => (relation.clone(), name.clone()),
1536 Expr::Alias(Alias { relation, name, .. }) => (relation.clone(), name.clone()),
1537 _ => (None, self.schema_name().to_string()),
1538 }
1539 }
1540
1541 pub fn placement(&self) -> ExpressionPlacement {
1546 match self {
1547 Expr::Column(_) => ExpressionPlacement::Column,
1548 Expr::Literal(_, _) => ExpressionPlacement::Literal,
1549 Expr::Alias(inner) => inner.expr.placement(),
1550 Expr::ScalarFunction(func) => {
1551 let arg_placements: Vec<_> =
1552 func.args.iter().map(|arg| arg.placement()).collect();
1553 func.func.placement(&arg_placements)
1554 }
1555 _ => ExpressionPlacement::KeepInPlace,
1556 }
1557 }
1558
1559 pub fn variant_name(&self) -> &str {
1562 match self {
1563 Expr::AggregateFunction { .. } => "AggregateFunction",
1564 Expr::Alias(..) => "Alias",
1565 Expr::Between { .. } => "Between",
1566 Expr::BinaryExpr { .. } => "BinaryExpr",
1567 Expr::Case { .. } => "Case",
1568 Expr::Cast { .. } => "Cast",
1569 Expr::Column(..) => "Column",
1570 Expr::OuterReferenceColumn(_, _) => "Outer",
1571 Expr::Exists { .. } => "Exists",
1572 Expr::GroupingSet(..) => "GroupingSet",
1573 Expr::InList { .. } => "InList",
1574 Expr::InSubquery(..) => "InSubquery",
1575 Expr::SetComparison(..) => "SetComparison",
1576 Expr::IsNotNull(..) => "IsNotNull",
1577 Expr::IsNull(..) => "IsNull",
1578 Expr::Like { .. } => "Like",
1579 Expr::SimilarTo { .. } => "RLike",
1580 Expr::IsTrue(..) => "IsTrue",
1581 Expr::IsFalse(..) => "IsFalse",
1582 Expr::IsUnknown(..) => "IsUnknown",
1583 Expr::IsNotTrue(..) => "IsNotTrue",
1584 Expr::IsNotFalse(..) => "IsNotFalse",
1585 Expr::IsNotUnknown(..) => "IsNotUnknown",
1586 Expr::Literal(..) => "Literal",
1587 Expr::Negative(..) => "Negative",
1588 Expr::Not(..) => "Not",
1589 Expr::Placeholder(_) => "Placeholder",
1590 Expr::ScalarFunction(..) => "ScalarFunction",
1591 Expr::ScalarSubquery { .. } => "ScalarSubquery",
1592 Expr::ScalarVariable(..) => "ScalarVariable",
1593 Expr::TryCast { .. } => "TryCast",
1594 Expr::WindowFunction { .. } => "WindowFunction",
1595 #[expect(deprecated)]
1596 Expr::Wildcard { .. } => "Wildcard",
1597 Expr::Unnest { .. } => "Unnest",
1598 }
1599 }
1600
1601 pub fn eq(self, other: Expr) -> Expr {
1603 binary_expr(self, Operator::Eq, other)
1604 }
1605
1606 pub fn not_eq(self, other: Expr) -> Expr {
1608 binary_expr(self, Operator::NotEq, other)
1609 }
1610
1611 pub fn gt(self, other: Expr) -> Expr {
1613 binary_expr(self, Operator::Gt, other)
1614 }
1615
1616 pub fn gt_eq(self, other: Expr) -> Expr {
1618 binary_expr(self, Operator::GtEq, other)
1619 }
1620
1621 pub fn lt(self, other: Expr) -> Expr {
1623 binary_expr(self, Operator::Lt, other)
1624 }
1625
1626 pub fn lt_eq(self, other: Expr) -> Expr {
1628 binary_expr(self, Operator::LtEq, other)
1629 }
1630
1631 pub fn and(self, other: Expr) -> Expr {
1633 binary_expr(self, Operator::And, other)
1634 }
1635
1636 pub fn or(self, other: Expr) -> Expr {
1638 binary_expr(self, Operator::Or, other)
1639 }
1640
1641 pub fn like(self, other: Expr) -> Expr {
1643 Expr::Like(Like::new(
1644 false,
1645 Box::new(self),
1646 Box::new(other),
1647 None,
1648 false,
1649 ))
1650 }
1651
1652 pub fn not_like(self, other: Expr) -> Expr {
1654 Expr::Like(Like::new(
1655 true,
1656 Box::new(self),
1657 Box::new(other),
1658 None,
1659 false,
1660 ))
1661 }
1662
1663 pub fn ilike(self, other: Expr) -> Expr {
1665 Expr::Like(Like::new(
1666 false,
1667 Box::new(self),
1668 Box::new(other),
1669 None,
1670 true,
1671 ))
1672 }
1673
1674 pub fn not_ilike(self, other: Expr) -> Expr {
1676 Expr::Like(Like::new(true, Box::new(self), Box::new(other), None, true))
1677 }
1678
1679 pub fn name_for_alias(&self) -> Result<String> {
1681 Ok(self.schema_name().to_string())
1682 }
1683
1684 pub fn alias_if_changed(self, original_name: String) -> Result<Expr> {
1687 let new_name = self.name_for_alias()?;
1688 if new_name == original_name {
1689 return Ok(self);
1690 }
1691
1692 Ok(self.alias(original_name))
1693 }
1694
1695 pub fn alias(self, name: impl Into<String>) -> Expr {
1697 Expr::Alias(Alias::new(self, None::<&str>, name.into()))
1698 }
1699
1700 pub fn alias_with_metadata(
1715 self,
1716 name: impl Into<String>,
1717 metadata: Option<FieldMetadata>,
1718 ) -> Expr {
1719 Expr::Alias(Alias::new(self, None::<&str>, name.into()).with_metadata(metadata))
1720 }
1721
1722 pub fn alias_qualified(
1724 self,
1725 relation: Option<impl Into<TableReference>>,
1726 name: impl Into<String>,
1727 ) -> Expr {
1728 Expr::Alias(Alias::new(self, relation, name.into()))
1729 }
1730
1731 pub fn alias_qualified_with_metadata(
1747 self,
1748 relation: Option<impl Into<TableReference>>,
1749 name: impl Into<String>,
1750 metadata: Option<FieldMetadata>,
1751 ) -> Expr {
1752 Expr::Alias(Alias::new(self, relation, name.into()).with_metadata(metadata))
1753 }
1754
1755 pub fn unalias(self) -> Expr {
1776 match self {
1777 Expr::Alias(alias) => *alias.expr,
1778 _ => self,
1779 }
1780 }
1781
1782 pub fn unalias_nested(self) -> Transformed<Expr> {
1803 self.transform_down_up(
1804 |expr| {
1805 let recursion = if matches!(
1807 expr,
1808 Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_)
1809 ) {
1810 TreeNodeRecursion::Jump
1812 } else {
1813 TreeNodeRecursion::Continue
1814 };
1815 Ok(Transformed::new(expr, false, recursion))
1816 },
1817 |expr| {
1818 if let Expr::Alias(alias) = expr {
1821 match alias
1822 .metadata
1823 .as_ref()
1824 .map(|h| h.is_empty())
1825 .unwrap_or(true)
1826 {
1827 true => Ok(Transformed::yes(*alias.expr)),
1828 false => Ok(Transformed::no(Expr::Alias(alias))),
1829 }
1830 } else {
1831 Ok(Transformed::no(expr))
1832 }
1833 },
1834 )
1835 .unwrap()
1837 }
1838
1839 pub fn in_list(self, list: Vec<Expr>, negated: bool) -> Expr {
1842 Expr::InList(InList::new(Box::new(self), list, negated))
1843 }
1844
1845 pub fn is_null(self) -> Expr {
1847 Expr::IsNull(Box::new(self))
1848 }
1849
1850 pub fn is_not_null(self) -> Expr {
1852 Expr::IsNotNull(Box::new(self))
1853 }
1854
1855 pub fn sort(self, asc: bool, nulls_first: bool) -> Sort {
1862 Sort::new(self, asc, nulls_first)
1863 }
1864
1865 pub fn is_true(self) -> Expr {
1867 Expr::IsTrue(Box::new(self))
1868 }
1869
1870 pub fn is_not_true(self) -> Expr {
1872 Expr::IsNotTrue(Box::new(self))
1873 }
1874
1875 pub fn is_false(self) -> Expr {
1877 Expr::IsFalse(Box::new(self))
1878 }
1879
1880 pub fn is_not_false(self) -> Expr {
1882 Expr::IsNotFalse(Box::new(self))
1883 }
1884
1885 pub fn is_unknown(self) -> Expr {
1887 Expr::IsUnknown(Box::new(self))
1888 }
1889
1890 pub fn is_not_unknown(self) -> Expr {
1892 Expr::IsNotUnknown(Box::new(self))
1893 }
1894
1895 pub fn between(self, low: Expr, high: Expr) -> Expr {
1897 Expr::Between(Between::new(
1898 Box::new(self),
1899 false,
1900 Box::new(low),
1901 Box::new(high),
1902 ))
1903 }
1904
1905 pub fn not_between(self, low: Expr, high: Expr) -> Expr {
1907 Expr::Between(Between::new(
1908 Box::new(self),
1909 true,
1910 Box::new(low),
1911 Box::new(high),
1912 ))
1913 }
1914 pub fn try_as_col(&self) -> Option<&Column> {
1932 if let Expr::Column(it) = self {
1933 Some(it)
1934 } else {
1935 None
1936 }
1937 }
1938
1939 pub fn get_as_join_column(&self) -> Option<&Column> {
1946 match self {
1947 Expr::Column(c) => Some(c),
1948 Expr::Cast(Cast { expr, .. }) => match &**expr {
1949 Expr::Column(c) => Some(c),
1950 _ => None,
1951 },
1952 _ => None,
1953 }
1954 }
1955
1956 pub fn column_refs(&self) -> HashSet<&Column> {
1972 let mut using_columns = HashSet::new();
1973 self.add_column_refs(&mut using_columns);
1974 using_columns
1975 }
1976
1977 pub fn add_column_refs<'a>(&'a self, set: &mut HashSet<&'a Column>) {
1981 self.apply(|expr| {
1982 if let Expr::Column(col) = expr {
1983 set.insert(col);
1984 }
1985 Ok(TreeNodeRecursion::Continue)
1986 })
1987 .expect("traversal is infallible");
1988 }
1989
1990 pub fn column_refs_counts(&self) -> HashMap<&Column, usize> {
2006 let mut map = HashMap::new();
2007 self.add_column_ref_counts(&mut map);
2008 map
2009 }
2010
2011 pub fn add_column_ref_counts<'a>(&'a self, map: &mut HashMap<&'a Column, usize>) {
2016 self.apply(|expr| {
2017 if let Expr::Column(col) = expr {
2018 *map.entry(col).or_default() += 1;
2019 }
2020 Ok(TreeNodeRecursion::Continue)
2021 })
2022 .expect("traversal is infallible");
2023 }
2024
2025 pub fn any_column_refs(&self) -> bool {
2027 self.exists(|expr| Ok(matches!(expr, Expr::Column(_))))
2028 .expect("exists closure is infallible")
2029 }
2030
2031 pub fn contains_outer(&self) -> bool {
2033 self.exists(|expr| Ok(matches!(expr, Expr::OuterReferenceColumn { .. })))
2034 .expect("exists closure is infallible")
2035 }
2036
2037 pub fn is_volatile_node(&self) -> bool {
2043 matches!(self, Expr::ScalarFunction(func) if func.func.signature().volatility == Volatility::Volatile)
2044 }
2045
2046 pub fn is_volatile(&self) -> bool {
2054 self.exists(|expr| Ok(expr.is_volatile_node()))
2055 .expect("exists closure is infallible")
2056 }
2057
2058 pub fn infer_placeholder_types(self, schema: &DFSchema) -> Result<(Expr, bool)> {
2067 let mut has_placeholder = false;
2068 self.transform(|mut expr| {
2069 match &mut expr {
2070 Expr::BinaryExpr(BinaryExpr { left, op: _, right }) => {
2072 rewrite_placeholder(left.as_mut(), right.as_ref(), schema)?;
2073 rewrite_placeholder(right.as_mut(), left.as_ref(), schema)?;
2074 }
2075 Expr::Between(Between {
2076 expr,
2077 negated: _,
2078 low,
2079 high,
2080 }) => {
2081 rewrite_placeholder(low.as_mut(), expr.as_ref(), schema)?;
2082 rewrite_placeholder(high.as_mut(), expr.as_ref(), schema)?;
2083 }
2084 Expr::InList(InList {
2085 expr,
2086 list,
2087 negated: _,
2088 }) => {
2089 for item in list.iter_mut() {
2090 rewrite_placeholder(item, expr.as_ref(), schema)?;
2091 }
2092 }
2093 Expr::Like(Like { expr, pattern, .. })
2094 | Expr::SimilarTo(Like { expr, pattern, .. }) => {
2095 rewrite_placeholder(pattern.as_mut(), expr.as_ref(), schema)?;
2096 }
2097 Expr::Placeholder(_) => {
2098 has_placeholder = true;
2099 }
2100 _ => {}
2101 }
2102 Ok(Transformed::yes(expr))
2103 })
2104 .data()
2105 .map(|data| (data, has_placeholder))
2106 }
2107
2108 pub fn short_circuits(&self) -> bool {
2111 match self {
2112 Expr::ScalarFunction(ScalarFunction { func, .. }) => func.short_circuits(),
2113 Expr::BinaryExpr(BinaryExpr { op, .. }) => {
2114 matches!(op, Operator::And | Operator::Or)
2115 }
2116 Expr::Case { .. } => true,
2117 #[expect(deprecated)]
2122 Expr::AggregateFunction(..)
2123 | Expr::Alias(..)
2124 | Expr::Between(..)
2125 | Expr::Cast(..)
2126 | Expr::Column(..)
2127 | Expr::Exists(..)
2128 | Expr::GroupingSet(..)
2129 | Expr::InList(..)
2130 | Expr::InSubquery(..)
2131 | Expr::SetComparison(..)
2132 | Expr::IsFalse(..)
2133 | Expr::IsNotFalse(..)
2134 | Expr::IsNotNull(..)
2135 | Expr::IsNotTrue(..)
2136 | Expr::IsNotUnknown(..)
2137 | Expr::IsNull(..)
2138 | Expr::IsTrue(..)
2139 | Expr::IsUnknown(..)
2140 | Expr::Like(..)
2141 | Expr::ScalarSubquery(..)
2142 | Expr::ScalarVariable(_, _)
2143 | Expr::SimilarTo(..)
2144 | Expr::Not(..)
2145 | Expr::Negative(..)
2146 | Expr::OuterReferenceColumn(_, _)
2147 | Expr::TryCast(..)
2148 | Expr::Unnest(..)
2149 | Expr::Wildcard { .. }
2150 | Expr::WindowFunction(..)
2151 | Expr::Literal(..)
2152 | Expr::Placeholder(..) => false,
2153 }
2154 }
2155
2156 pub fn spans(&self) -> Option<&Spans> {
2160 match self {
2161 Expr::Column(col) => Some(&col.spans),
2162 _ => None,
2163 }
2164 }
2165
2166 pub fn as_literal(&self) -> Option<&ScalarValue> {
2168 if let Expr::Literal(lit, _) = self {
2169 Some(lit)
2170 } else {
2171 None
2172 }
2173 }
2174}
2175
2176impl Normalizeable for Expr {
2177 fn can_normalize(&self) -> bool {
2178 #[expect(clippy::match_like_matches_macro)]
2179 match self {
2180 Expr::BinaryExpr(BinaryExpr {
2181 op:
2182 _op @ (Operator::Plus
2183 | Operator::Multiply
2184 | Operator::BitwiseAnd
2185 | Operator::BitwiseOr
2186 | Operator::BitwiseXor
2187 | Operator::Eq
2188 | Operator::NotEq),
2189 ..
2190 }) => true,
2191 _ => false,
2192 }
2193 }
2194}
2195
2196impl NormalizeEq for Expr {
2197 fn normalize_eq(&self, other: &Self) -> bool {
2198 match (self, other) {
2199 (
2200 Expr::BinaryExpr(BinaryExpr {
2201 left: self_left,
2202 op: self_op,
2203 right: self_right,
2204 }),
2205 Expr::BinaryExpr(BinaryExpr {
2206 left: other_left,
2207 op: other_op,
2208 right: other_right,
2209 }),
2210 ) => {
2211 if self_op != other_op {
2212 return false;
2213 }
2214
2215 if matches!(
2216 self_op,
2217 Operator::Plus
2218 | Operator::Multiply
2219 | Operator::BitwiseAnd
2220 | Operator::BitwiseOr
2221 | Operator::BitwiseXor
2222 | Operator::Eq
2223 | Operator::NotEq
2224 ) {
2225 (self_left.normalize_eq(other_left)
2226 && self_right.normalize_eq(other_right))
2227 || (self_left.normalize_eq(other_right)
2228 && self_right.normalize_eq(other_left))
2229 } else {
2230 self_left.normalize_eq(other_left)
2231 && self_right.normalize_eq(other_right)
2232 }
2233 }
2234 (
2235 Expr::Alias(Alias {
2236 expr: self_expr,
2237 relation: self_relation,
2238 name: self_name,
2239 ..
2240 }),
2241 Expr::Alias(Alias {
2242 expr: other_expr,
2243 relation: other_relation,
2244 name: other_name,
2245 ..
2246 }),
2247 ) => {
2248 self_name == other_name
2249 && self_relation == other_relation
2250 && self_expr.normalize_eq(other_expr)
2251 }
2252 (
2253 Expr::Like(Like {
2254 negated: self_negated,
2255 expr: self_expr,
2256 pattern: self_pattern,
2257 escape_char: self_escape_char,
2258 case_insensitive: self_case_insensitive,
2259 }),
2260 Expr::Like(Like {
2261 negated: other_negated,
2262 expr: other_expr,
2263 pattern: other_pattern,
2264 escape_char: other_escape_char,
2265 case_insensitive: other_case_insensitive,
2266 }),
2267 )
2268 | (
2269 Expr::SimilarTo(Like {
2270 negated: self_negated,
2271 expr: self_expr,
2272 pattern: self_pattern,
2273 escape_char: self_escape_char,
2274 case_insensitive: self_case_insensitive,
2275 }),
2276 Expr::SimilarTo(Like {
2277 negated: other_negated,
2278 expr: other_expr,
2279 pattern: other_pattern,
2280 escape_char: other_escape_char,
2281 case_insensitive: other_case_insensitive,
2282 }),
2283 ) => {
2284 self_negated == other_negated
2285 && self_escape_char == other_escape_char
2286 && self_case_insensitive == other_case_insensitive
2287 && self_expr.normalize_eq(other_expr)
2288 && self_pattern.normalize_eq(other_pattern)
2289 }
2290 (Expr::Not(self_expr), Expr::Not(other_expr))
2291 | (Expr::IsNull(self_expr), Expr::IsNull(other_expr))
2292 | (Expr::IsTrue(self_expr), Expr::IsTrue(other_expr))
2293 | (Expr::IsFalse(self_expr), Expr::IsFalse(other_expr))
2294 | (Expr::IsUnknown(self_expr), Expr::IsUnknown(other_expr))
2295 | (Expr::IsNotNull(self_expr), Expr::IsNotNull(other_expr))
2296 | (Expr::IsNotTrue(self_expr), Expr::IsNotTrue(other_expr))
2297 | (Expr::IsNotFalse(self_expr), Expr::IsNotFalse(other_expr))
2298 | (Expr::IsNotUnknown(self_expr), Expr::IsNotUnknown(other_expr))
2299 | (Expr::Negative(self_expr), Expr::Negative(other_expr))
2300 | (
2301 Expr::Unnest(Unnest { expr: self_expr }),
2302 Expr::Unnest(Unnest { expr: other_expr }),
2303 ) => self_expr.normalize_eq(other_expr),
2304 (
2305 Expr::Between(Between {
2306 expr: self_expr,
2307 negated: self_negated,
2308 low: self_low,
2309 high: self_high,
2310 }),
2311 Expr::Between(Between {
2312 expr: other_expr,
2313 negated: other_negated,
2314 low: other_low,
2315 high: other_high,
2316 }),
2317 ) => {
2318 self_negated == other_negated
2319 && self_expr.normalize_eq(other_expr)
2320 && self_low.normalize_eq(other_low)
2321 && self_high.normalize_eq(other_high)
2322 }
2323 (
2324 Expr::Cast(Cast {
2325 expr: self_expr,
2326 data_type: self_data_type,
2327 }),
2328 Expr::Cast(Cast {
2329 expr: other_expr,
2330 data_type: other_data_type,
2331 }),
2332 )
2333 | (
2334 Expr::TryCast(TryCast {
2335 expr: self_expr,
2336 data_type: self_data_type,
2337 }),
2338 Expr::TryCast(TryCast {
2339 expr: other_expr,
2340 data_type: other_data_type,
2341 }),
2342 ) => self_data_type == other_data_type && self_expr.normalize_eq(other_expr),
2343 (
2344 Expr::ScalarFunction(ScalarFunction {
2345 func: self_func,
2346 args: self_args,
2347 }),
2348 Expr::ScalarFunction(ScalarFunction {
2349 func: other_func,
2350 args: other_args,
2351 }),
2352 ) => {
2353 self_func.name() == other_func.name()
2354 && self_args.len() == other_args.len()
2355 && self_args
2356 .iter()
2357 .zip(other_args.iter())
2358 .all(|(a, b)| a.normalize_eq(b))
2359 }
2360 (
2361 Expr::AggregateFunction(AggregateFunction {
2362 func: self_func,
2363 params:
2364 AggregateFunctionParams {
2365 args: self_args,
2366 distinct: self_distinct,
2367 filter: self_filter,
2368 order_by: self_order_by,
2369 null_treatment: self_null_treatment,
2370 },
2371 }),
2372 Expr::AggregateFunction(AggregateFunction {
2373 func: other_func,
2374 params:
2375 AggregateFunctionParams {
2376 args: other_args,
2377 distinct: other_distinct,
2378 filter: other_filter,
2379 order_by: other_order_by,
2380 null_treatment: other_null_treatment,
2381 },
2382 }),
2383 ) => {
2384 self_func.name() == other_func.name()
2385 && self_distinct == other_distinct
2386 && self_null_treatment == other_null_treatment
2387 && self_args.len() == other_args.len()
2388 && self_args
2389 .iter()
2390 .zip(other_args.iter())
2391 .all(|(a, b)| a.normalize_eq(b))
2392 && match (self_filter, other_filter) {
2393 (Some(self_filter), Some(other_filter)) => {
2394 self_filter.normalize_eq(other_filter)
2395 }
2396 (None, None) => true,
2397 _ => false,
2398 }
2399 && self_order_by
2400 .iter()
2401 .zip(other_order_by.iter())
2402 .all(|(a, b)| {
2403 a.asc == b.asc
2404 && a.nulls_first == b.nulls_first
2405 && a.expr.normalize_eq(&b.expr)
2406 })
2407 && self_order_by.len() == other_order_by.len()
2408 }
2409 (Expr::WindowFunction(left), Expr::WindowFunction(other)) => {
2410 let WindowFunction {
2411 fun: self_fun,
2412 params:
2413 WindowFunctionParams {
2414 args: self_args,
2415 window_frame: self_window_frame,
2416 partition_by: self_partition_by,
2417 order_by: self_order_by,
2418 filter: self_filter,
2419 null_treatment: self_null_treatment,
2420 distinct: self_distinct,
2421 },
2422 } = left.as_ref();
2423 let WindowFunction {
2424 fun: other_fun,
2425 params:
2426 WindowFunctionParams {
2427 args: other_args,
2428 window_frame: other_window_frame,
2429 partition_by: other_partition_by,
2430 order_by: other_order_by,
2431 filter: other_filter,
2432 null_treatment: other_null_treatment,
2433 distinct: other_distinct,
2434 },
2435 } = other.as_ref();
2436
2437 self_fun.name() == other_fun.name()
2438 && self_window_frame == other_window_frame
2439 && match (self_filter, other_filter) {
2440 (Some(a), Some(b)) => a.normalize_eq(b),
2441 (None, None) => true,
2442 _ => false,
2443 }
2444 && self_null_treatment == other_null_treatment
2445 && self_args.len() == other_args.len()
2446 && self_args
2447 .iter()
2448 .zip(other_args.iter())
2449 .all(|(a, b)| a.normalize_eq(b))
2450 && self_partition_by
2451 .iter()
2452 .zip(other_partition_by.iter())
2453 .all(|(a, b)| a.normalize_eq(b))
2454 && self_order_by
2455 .iter()
2456 .zip(other_order_by.iter())
2457 .all(|(a, b)| {
2458 a.asc == b.asc
2459 && a.nulls_first == b.nulls_first
2460 && a.expr.normalize_eq(&b.expr)
2461 })
2462 && self_distinct == other_distinct
2463 }
2464 (
2465 Expr::Exists(Exists {
2466 subquery: self_subquery,
2467 negated: self_negated,
2468 }),
2469 Expr::Exists(Exists {
2470 subquery: other_subquery,
2471 negated: other_negated,
2472 }),
2473 ) => {
2474 self_negated == other_negated
2475 && self_subquery.normalize_eq(other_subquery)
2476 }
2477 (
2478 Expr::InSubquery(InSubquery {
2479 expr: self_expr,
2480 subquery: self_subquery,
2481 negated: self_negated,
2482 }),
2483 Expr::InSubquery(InSubquery {
2484 expr: other_expr,
2485 subquery: other_subquery,
2486 negated: other_negated,
2487 }),
2488 ) => {
2489 self_negated == other_negated
2490 && self_expr.normalize_eq(other_expr)
2491 && self_subquery.normalize_eq(other_subquery)
2492 }
2493 (
2494 Expr::ScalarSubquery(self_subquery),
2495 Expr::ScalarSubquery(other_subquery),
2496 ) => self_subquery.normalize_eq(other_subquery),
2497 (
2498 Expr::GroupingSet(GroupingSet::Rollup(self_exprs)),
2499 Expr::GroupingSet(GroupingSet::Rollup(other_exprs)),
2500 )
2501 | (
2502 Expr::GroupingSet(GroupingSet::Cube(self_exprs)),
2503 Expr::GroupingSet(GroupingSet::Cube(other_exprs)),
2504 ) => {
2505 self_exprs.len() == other_exprs.len()
2506 && self_exprs
2507 .iter()
2508 .zip(other_exprs.iter())
2509 .all(|(a, b)| a.normalize_eq(b))
2510 }
2511 (
2512 Expr::GroupingSet(GroupingSet::GroupingSets(self_exprs)),
2513 Expr::GroupingSet(GroupingSet::GroupingSets(other_exprs)),
2514 ) => {
2515 self_exprs.len() == other_exprs.len()
2516 && self_exprs.iter().zip(other_exprs.iter()).all(|(a, b)| {
2517 a.len() == b.len()
2518 && a.iter().zip(b.iter()).all(|(x, y)| x.normalize_eq(y))
2519 })
2520 }
2521 (
2522 Expr::InList(InList {
2523 expr: self_expr,
2524 list: self_list,
2525 negated: self_negated,
2526 }),
2527 Expr::InList(InList {
2528 expr: other_expr,
2529 list: other_list,
2530 negated: other_negated,
2531 }),
2532 ) => {
2533 self_negated == other_negated
2535 && self_expr.normalize_eq(other_expr)
2536 && self_list.len() == other_list.len()
2537 && self_list
2538 .iter()
2539 .zip(other_list.iter())
2540 .all(|(a, b)| a.normalize_eq(b))
2541 }
2542 (
2543 Expr::Case(Case {
2544 expr: self_expr,
2545 when_then_expr: self_when_then_expr,
2546 else_expr: self_else_expr,
2547 }),
2548 Expr::Case(Case {
2549 expr: other_expr,
2550 when_then_expr: other_when_then_expr,
2551 else_expr: other_else_expr,
2552 }),
2553 ) => {
2554 self_when_then_expr.len() == other_when_then_expr.len()
2557 && self_when_then_expr
2558 .iter()
2559 .zip(other_when_then_expr.iter())
2560 .all(|((self_when, self_then), (other_when, other_then))| {
2561 self_when.normalize_eq(other_when)
2562 && self_then.normalize_eq(other_then)
2563 })
2564 && match (self_expr, other_expr) {
2565 (Some(self_expr), Some(other_expr)) => {
2566 self_expr.normalize_eq(other_expr)
2567 }
2568 (None, None) => true,
2569 (_, _) => false,
2570 }
2571 && match (self_else_expr, other_else_expr) {
2572 (Some(self_else_expr), Some(other_else_expr)) => {
2573 self_else_expr.normalize_eq(other_else_expr)
2574 }
2575 (None, None) => true,
2576 (_, _) => false,
2577 }
2578 }
2579 (_, _) => self == other,
2580 }
2581 }
2582}
2583
2584impl HashNode for Expr {
2585 fn hash_node<H: Hasher>(&self, state: &mut H) {
2589 mem::discriminant(self).hash(state);
2590 match self {
2591 Expr::Alias(Alias {
2592 expr: _expr,
2593 relation,
2594 name,
2595 ..
2596 }) => {
2597 relation.hash(state);
2598 name.hash(state);
2599 }
2600 Expr::Column(column) => {
2601 column.hash(state);
2602 }
2603 Expr::ScalarVariable(field, name) => {
2604 field.hash(state);
2605 name.hash(state);
2606 }
2607 Expr::Literal(scalar_value, _) => {
2608 scalar_value.hash(state);
2609 }
2610 Expr::BinaryExpr(BinaryExpr {
2611 left: _left,
2612 op,
2613 right: _right,
2614 }) => {
2615 op.hash(state);
2616 }
2617 Expr::Like(Like {
2618 negated,
2619 expr: _expr,
2620 pattern: _pattern,
2621 escape_char,
2622 case_insensitive,
2623 })
2624 | Expr::SimilarTo(Like {
2625 negated,
2626 expr: _expr,
2627 pattern: _pattern,
2628 escape_char,
2629 case_insensitive,
2630 }) => {
2631 negated.hash(state);
2632 escape_char.hash(state);
2633 case_insensitive.hash(state);
2634 }
2635 Expr::Not(_expr)
2636 | Expr::IsNotNull(_expr)
2637 | Expr::IsNull(_expr)
2638 | Expr::IsTrue(_expr)
2639 | Expr::IsFalse(_expr)
2640 | Expr::IsUnknown(_expr)
2641 | Expr::IsNotTrue(_expr)
2642 | Expr::IsNotFalse(_expr)
2643 | Expr::IsNotUnknown(_expr)
2644 | Expr::Negative(_expr) => {}
2645 Expr::Between(Between {
2646 expr: _expr,
2647 negated,
2648 low: _low,
2649 high: _high,
2650 }) => {
2651 negated.hash(state);
2652 }
2653 Expr::Case(Case {
2654 expr: _expr,
2655 when_then_expr: _when_then_expr,
2656 else_expr: _else_expr,
2657 }) => {}
2658 Expr::Cast(Cast {
2659 expr: _expr,
2660 data_type,
2661 })
2662 | Expr::TryCast(TryCast {
2663 expr: _expr,
2664 data_type,
2665 }) => {
2666 data_type.hash(state);
2667 }
2668 Expr::ScalarFunction(ScalarFunction { func, args: _args }) => {
2669 func.hash(state);
2670 }
2671 Expr::AggregateFunction(AggregateFunction {
2672 func,
2673 params:
2674 AggregateFunctionParams {
2675 args: _args,
2676 distinct,
2677 filter: _,
2678 order_by: _,
2679 null_treatment,
2680 },
2681 }) => {
2682 func.hash(state);
2683 distinct.hash(state);
2684 null_treatment.hash(state);
2685 }
2686 Expr::WindowFunction(window_fun) => {
2687 let WindowFunction {
2688 fun,
2689 params:
2690 WindowFunctionParams {
2691 args: _args,
2692 partition_by: _,
2693 order_by: _,
2694 window_frame,
2695 filter,
2696 null_treatment,
2697 distinct,
2698 },
2699 } = window_fun.as_ref();
2700 fun.hash(state);
2701 window_frame.hash(state);
2702 filter.hash(state);
2703 null_treatment.hash(state);
2704 distinct.hash(state);
2705 }
2706 Expr::InList(InList {
2707 expr: _expr,
2708 list: _list,
2709 negated,
2710 }) => {
2711 negated.hash(state);
2712 }
2713 Expr::Exists(Exists { subquery, negated }) => {
2714 subquery.hash(state);
2715 negated.hash(state);
2716 }
2717 Expr::InSubquery(InSubquery {
2718 expr: _expr,
2719 subquery,
2720 negated,
2721 }) => {
2722 subquery.hash(state);
2723 negated.hash(state);
2724 }
2725 Expr::SetComparison(SetComparison {
2726 expr: _,
2727 subquery,
2728 op,
2729 quantifier,
2730 }) => {
2731 subquery.hash(state);
2732 op.hash(state);
2733 quantifier.hash(state);
2734 }
2735 Expr::ScalarSubquery(subquery) => {
2736 subquery.hash(state);
2737 }
2738 #[expect(deprecated)]
2739 Expr::Wildcard { qualifier, options } => {
2740 qualifier.hash(state);
2741 options.hash(state);
2742 }
2743 Expr::GroupingSet(grouping_set) => {
2744 mem::discriminant(grouping_set).hash(state);
2745 match grouping_set {
2746 GroupingSet::Rollup(_exprs) | GroupingSet::Cube(_exprs) => {}
2747 GroupingSet::GroupingSets(_exprs) => {}
2748 }
2749 }
2750 Expr::Placeholder(place_holder) => {
2751 place_holder.hash(state);
2752 }
2753 Expr::OuterReferenceColumn(field, column) => {
2754 field.hash(state);
2755 column.hash(state);
2756 }
2757 Expr::Unnest(Unnest { expr: _expr }) => {}
2758 };
2759 }
2760}
2761
2762fn rewrite_placeholder(expr: &mut Expr, other: &Expr, schema: &DFSchema) -> Result<()> {
2765 if let Expr::Placeholder(Placeholder { id: _, field }) = expr
2766 && field.is_none()
2767 {
2768 let other_field = other.to_field(schema);
2769 match other_field {
2770 Err(e) => {
2771 Err(e.context(format!(
2772 "Can not find type of {other} needed to infer type of {expr}"
2773 )))?;
2774 }
2775 Ok((_, other_field)) => {
2776 *field = Some(other_field.as_ref().clone().with_nullable(true).into());
2779 }
2780 }
2781 };
2782 Ok(())
2783}
2784
2785#[macro_export]
2786macro_rules! expr_vec_fmt {
2787 ( $ARRAY:expr ) => {{
2788 $ARRAY
2789 .iter()
2790 .map(|e| format!("{e}"))
2791 .collect::<Vec<String>>()
2792 .join(", ")
2793 }};
2794}
2795
2796struct SchemaDisplay<'a>(&'a Expr);
2797impl Display for SchemaDisplay<'_> {
2798 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2799 match self.0 {
2800 #[expect(deprecated)]
2803 Expr::Column(_)
2804 | Expr::Literal(_, _)
2805 | Expr::ScalarVariable(..)
2806 | Expr::OuterReferenceColumn(..)
2807 | Expr::Placeholder(_)
2808 | Expr::Wildcard { .. } => write!(f, "{}", self.0),
2809 Expr::AggregateFunction(AggregateFunction { func, params }) => {
2810 match func.schema_name(params) {
2811 Ok(name) => {
2812 write!(f, "{name}")
2813 }
2814 Err(e) => {
2815 write!(f, "got error from schema_name {e}")
2816 }
2817 }
2818 }
2819 Expr::Alias(Alias {
2821 name,
2822 relation: Some(relation),
2823 ..
2824 }) => write!(f, "{relation}.{name}"),
2825 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
2826 Expr::Between(Between {
2827 expr,
2828 negated,
2829 low,
2830 high,
2831 }) => {
2832 if *negated {
2833 write!(
2834 f,
2835 "{} NOT BETWEEN {} AND {}",
2836 SchemaDisplay(expr),
2837 SchemaDisplay(low),
2838 SchemaDisplay(high),
2839 )
2840 } else {
2841 write!(
2842 f,
2843 "{} BETWEEN {} AND {}",
2844 SchemaDisplay(expr),
2845 SchemaDisplay(low),
2846 SchemaDisplay(high),
2847 )
2848 }
2849 }
2850 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2851 write!(f, "{} {op} {}", SchemaDisplay(left), SchemaDisplay(right),)
2852 }
2853 Expr::Case(Case {
2854 expr,
2855 when_then_expr,
2856 else_expr,
2857 }) => {
2858 write!(f, "CASE ")?;
2859
2860 if let Some(e) = expr {
2861 write!(f, "{} ", SchemaDisplay(e))?;
2862 }
2863
2864 for (when, then) in when_then_expr {
2865 write!(
2866 f,
2867 "WHEN {} THEN {} ",
2868 SchemaDisplay(when),
2869 SchemaDisplay(then),
2870 )?;
2871 }
2872
2873 if let Some(e) = else_expr {
2874 write!(f, "ELSE {} ", SchemaDisplay(e))?;
2875 }
2876
2877 write!(f, "END")
2878 }
2879 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
2881 write!(f, "{}", SchemaDisplay(expr))
2882 }
2883 Expr::InList(InList {
2884 expr,
2885 list,
2886 negated,
2887 }) => {
2888 let inlist_name = schema_name_from_exprs(list)?;
2889
2890 if *negated {
2891 write!(f, "{} NOT IN {}", SchemaDisplay(expr), inlist_name)
2892 } else {
2893 write!(f, "{} IN {}", SchemaDisplay(expr), inlist_name)
2894 }
2895 }
2896 Expr::Exists(Exists { negated: true, .. }) => write!(f, "NOT EXISTS"),
2897 Expr::Exists(Exists { negated: false, .. }) => write!(f, "EXISTS"),
2898 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
2899 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2900 }
2901 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
2902 write!(f, "GROUPING SETS (")?;
2903 for exprs in lists_of_exprs.iter() {
2904 write!(f, "({})", schema_name_from_exprs(exprs)?)?;
2905 }
2906 write!(f, ")")
2907 }
2908 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
2909 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2910 }
2911 Expr::IsNull(expr) => write!(f, "{} IS NULL", SchemaDisplay(expr)),
2912 Expr::IsNotNull(expr) => {
2913 write!(f, "{} IS NOT NULL", SchemaDisplay(expr))
2914 }
2915 Expr::IsUnknown(expr) => {
2916 write!(f, "{} IS UNKNOWN", SchemaDisplay(expr))
2917 }
2918 Expr::IsNotUnknown(expr) => {
2919 write!(f, "{} IS NOT UNKNOWN", SchemaDisplay(expr))
2920 }
2921 Expr::InSubquery(InSubquery { negated: true, .. }) => {
2922 write!(f, "NOT IN")
2923 }
2924 Expr::InSubquery(InSubquery { negated: false, .. }) => write!(f, "IN"),
2925 Expr::SetComparison(SetComparison {
2926 expr,
2927 op,
2928 quantifier,
2929 ..
2930 }) => write!(f, "{} {op} {quantifier}", SchemaDisplay(expr.as_ref())),
2931 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SchemaDisplay(expr)),
2932 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SchemaDisplay(expr)),
2933 Expr::IsNotTrue(expr) => {
2934 write!(f, "{} IS NOT TRUE", SchemaDisplay(expr))
2935 }
2936 Expr::IsNotFalse(expr) => {
2937 write!(f, "{} IS NOT FALSE", SchemaDisplay(expr))
2938 }
2939 Expr::Like(Like {
2940 negated,
2941 expr,
2942 pattern,
2943 escape_char,
2944 case_insensitive,
2945 }) => {
2946 write!(
2947 f,
2948 "{} {}{} {}",
2949 SchemaDisplay(expr),
2950 if *negated { "NOT " } else { "" },
2951 if *case_insensitive { "ILIKE" } else { "LIKE" },
2952 SchemaDisplay(pattern),
2953 )?;
2954
2955 if let Some(char) = escape_char {
2956 write!(f, " CHAR '{char}'")?;
2957 }
2958
2959 Ok(())
2960 }
2961 Expr::Negative(expr) => write!(f, "(- {})", SchemaDisplay(expr)),
2962 Expr::Not(expr) => write!(f, "NOT {}", SchemaDisplay(expr)),
2963 Expr::Unnest(Unnest { expr }) => {
2964 write!(f, "UNNEST({})", SchemaDisplay(expr))
2965 }
2966 Expr::ScalarFunction(ScalarFunction { func, args }) => {
2967 match func.schema_name(args) {
2968 Ok(name) => {
2969 write!(f, "{name}")
2970 }
2971 Err(e) => {
2972 write!(f, "got error from schema_name {e}")
2973 }
2974 }
2975 }
2976 Expr::ScalarSubquery(Subquery { subquery, .. }) => {
2977 write!(f, "{}", subquery.schema().field(0).name())
2978 }
2979 Expr::SimilarTo(Like {
2980 negated,
2981 expr,
2982 pattern,
2983 escape_char,
2984 ..
2985 }) => {
2986 write!(
2987 f,
2988 "{} {} {}",
2989 SchemaDisplay(expr),
2990 if *negated {
2991 "NOT SIMILAR TO"
2992 } else {
2993 "SIMILAR TO"
2994 },
2995 SchemaDisplay(pattern),
2996 )?;
2997 if let Some(char) = escape_char {
2998 write!(f, " CHAR '{char}'")?;
2999 }
3000
3001 Ok(())
3002 }
3003 Expr::WindowFunction(window_fun) => {
3004 let WindowFunction { fun, params } = window_fun.as_ref();
3005 match fun {
3006 WindowFunctionDefinition::AggregateUDF(fun) => {
3007 match fun.window_function_schema_name(params) {
3008 Ok(name) => {
3009 write!(f, "{name}")
3010 }
3011 Err(e) => {
3012 write!(
3013 f,
3014 "got error from window_function_schema_name {e}"
3015 )
3016 }
3017 }
3018 }
3019 _ => {
3020 let WindowFunctionParams {
3021 args,
3022 partition_by,
3023 order_by,
3024 window_frame,
3025 filter,
3026 null_treatment,
3027 distinct,
3028 } = params;
3029
3030 write!(f, "{fun}(")?;
3032
3033 if *distinct {
3035 write!(f, "DISTINCT ")?;
3036 }
3037
3038 write!(
3040 f,
3041 "{}",
3042 schema_name_from_exprs_comma_separated_without_space(args)?
3043 )?;
3044
3045 write!(f, ")")?;
3047
3048 if let Some(null_treatment) = null_treatment {
3049 write!(f, " {null_treatment}")?;
3050 }
3051
3052 if let Some(filter) = filter {
3053 write!(f, " FILTER (WHERE {filter})")?;
3054 }
3055
3056 if !partition_by.is_empty() {
3057 write!(
3058 f,
3059 " PARTITION BY [{}]",
3060 schema_name_from_exprs(partition_by)?
3061 )?;
3062 }
3063
3064 if !order_by.is_empty() {
3065 write!(
3066 f,
3067 " ORDER BY [{}]",
3068 schema_name_from_sorts(order_by)?
3069 )?;
3070 };
3071
3072 write!(f, " {window_frame}")
3073 }
3074 }
3075 }
3076 }
3077 }
3078}
3079
3080struct SqlDisplay<'a>(&'a Expr);
3082
3083impl Display for SqlDisplay<'_> {
3084 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3085 match self.0 {
3086 Expr::Literal(scalar, _) => scalar.fmt(f),
3087 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
3088 Expr::Between(Between {
3089 expr,
3090 negated,
3091 low,
3092 high,
3093 }) => {
3094 if *negated {
3095 write!(
3096 f,
3097 "{} NOT BETWEEN {} AND {}",
3098 SqlDisplay(expr),
3099 SqlDisplay(low),
3100 SqlDisplay(high),
3101 )
3102 } else {
3103 write!(
3104 f,
3105 "{} BETWEEN {} AND {}",
3106 SqlDisplay(expr),
3107 SqlDisplay(low),
3108 SqlDisplay(high),
3109 )
3110 }
3111 }
3112 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
3113 write!(f, "{} {op} {}", SqlDisplay(left), SqlDisplay(right),)
3114 }
3115 Expr::Case(Case {
3116 expr,
3117 when_then_expr,
3118 else_expr,
3119 }) => {
3120 write!(f, "CASE ")?;
3121
3122 if let Some(e) = expr {
3123 write!(f, "{} ", SqlDisplay(e))?;
3124 }
3125
3126 for (when, then) in when_then_expr {
3127 write!(f, "WHEN {} THEN {} ", SqlDisplay(when), SqlDisplay(then),)?;
3128 }
3129
3130 if let Some(e) = else_expr {
3131 write!(f, "ELSE {} ", SqlDisplay(e))?;
3132 }
3133
3134 write!(f, "END")
3135 }
3136 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
3137 write!(f, "{}", SqlDisplay(expr))
3138 }
3139 Expr::InList(InList {
3140 expr,
3141 list,
3142 negated,
3143 }) => {
3144 write!(
3145 f,
3146 "{}{} IN {}",
3147 SqlDisplay(expr),
3148 if *negated { " NOT" } else { "" },
3149 ExprListDisplay::comma_separated(list.as_slice())
3150 )
3151 }
3152 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
3153 write!(
3154 f,
3155 "ROLLUP ({})",
3156 ExprListDisplay::comma_separated(exprs.as_slice())
3157 )
3158 }
3159 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
3160 write!(f, "GROUPING SETS (")?;
3161 for exprs in lists_of_exprs.iter() {
3162 write!(
3163 f,
3164 "({})",
3165 ExprListDisplay::comma_separated(exprs.as_slice())
3166 )?;
3167 }
3168 write!(f, ")")
3169 }
3170 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
3171 write!(
3172 f,
3173 "ROLLUP ({})",
3174 ExprListDisplay::comma_separated(exprs.as_slice())
3175 )
3176 }
3177 Expr::IsNull(expr) => write!(f, "{} IS NULL", SqlDisplay(expr)),
3178 Expr::IsNotNull(expr) => {
3179 write!(f, "{} IS NOT NULL", SqlDisplay(expr))
3180 }
3181 Expr::IsUnknown(expr) => {
3182 write!(f, "{} IS UNKNOWN", SqlDisplay(expr))
3183 }
3184 Expr::IsNotUnknown(expr) => {
3185 write!(f, "{} IS NOT UNKNOWN", SqlDisplay(expr))
3186 }
3187 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SqlDisplay(expr)),
3188 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SqlDisplay(expr)),
3189 Expr::IsNotTrue(expr) => {
3190 write!(f, "{} IS NOT TRUE", SqlDisplay(expr))
3191 }
3192 Expr::IsNotFalse(expr) => {
3193 write!(f, "{} IS NOT FALSE", SqlDisplay(expr))
3194 }
3195 Expr::Like(Like {
3196 negated,
3197 expr,
3198 pattern,
3199 escape_char,
3200 case_insensitive,
3201 }) => {
3202 write!(
3203 f,
3204 "{} {}{} {}",
3205 SqlDisplay(expr),
3206 if *negated { "NOT " } else { "" },
3207 if *case_insensitive { "ILIKE" } else { "LIKE" },
3208 SqlDisplay(pattern),
3209 )?;
3210
3211 if let Some(char) = escape_char {
3212 write!(f, " CHAR '{char}'")?;
3213 }
3214
3215 Ok(())
3216 }
3217 Expr::Negative(expr) => write!(f, "(- {})", SqlDisplay(expr)),
3218 Expr::Not(expr) => write!(f, "NOT {}", SqlDisplay(expr)),
3219 Expr::Unnest(Unnest { expr }) => {
3220 write!(f, "UNNEST({})", SqlDisplay(expr))
3221 }
3222 Expr::SimilarTo(Like {
3223 negated,
3224 expr,
3225 pattern,
3226 escape_char,
3227 ..
3228 }) => {
3229 write!(
3230 f,
3231 "{} {} {}",
3232 SqlDisplay(expr),
3233 if *negated {
3234 "NOT SIMILAR TO"
3235 } else {
3236 "SIMILAR TO"
3237 },
3238 SqlDisplay(pattern),
3239 )?;
3240 if let Some(char) = escape_char {
3241 write!(f, " CHAR '{char}'")?;
3242 }
3243
3244 Ok(())
3245 }
3246 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3247 match func.human_display(params) {
3248 Ok(name) => {
3249 write!(f, "{name}")
3250 }
3251 Err(e) => {
3252 write!(f, "got error from schema_name {e}")
3253 }
3254 }
3255 }
3256 _ => write!(f, "{}", self.0),
3257 }
3258 }
3259}
3260
3261pub(crate) fn schema_name_from_exprs_comma_separated_without_space(
3267 exprs: &[Expr],
3268) -> Result<String, fmt::Error> {
3269 schema_name_from_exprs_inner(exprs, ",")
3270}
3271
3272pub struct ExprListDisplay<'a> {
3274 exprs: &'a [Expr],
3275 sep: &'a str,
3276}
3277
3278impl<'a> ExprListDisplay<'a> {
3279 pub fn new(exprs: &'a [Expr], sep: &'a str) -> Self {
3281 Self { exprs, sep }
3282 }
3283
3284 pub fn comma_separated(exprs: &'a [Expr]) -> Self {
3286 Self::new(exprs, ", ")
3287 }
3288}
3289
3290impl Display for ExprListDisplay<'_> {
3291 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3292 let mut first = true;
3293 for expr in self.exprs {
3294 if !first {
3295 write!(f, "{}", self.sep)?;
3296 }
3297 write!(f, "{}", SqlDisplay(expr))?;
3298 first = false;
3299 }
3300 Ok(())
3301 }
3302}
3303
3304pub fn schema_name_from_exprs(exprs: &[Expr]) -> Result<String, fmt::Error> {
3306 schema_name_from_exprs_inner(exprs, ", ")
3307}
3308
3309fn schema_name_from_exprs_inner(exprs: &[Expr], sep: &str) -> Result<String, fmt::Error> {
3310 let mut s = String::new();
3311 for (i, e) in exprs.iter().enumerate() {
3312 if i > 0 {
3313 write!(&mut s, "{sep}")?;
3314 }
3315 write!(&mut s, "{}", SchemaDisplay(e))?;
3316 }
3317
3318 Ok(s)
3319}
3320
3321pub fn schema_name_from_sorts(sorts: &[Sort]) -> Result<String, fmt::Error> {
3322 let mut s = String::new();
3323 for (i, e) in sorts.iter().enumerate() {
3324 if i > 0 {
3325 write!(&mut s, ", ")?;
3326 }
3327 let ordering = if e.asc { "ASC" } else { "DESC" };
3328 let nulls_ordering = if e.nulls_first {
3329 "NULLS FIRST"
3330 } else {
3331 "NULLS LAST"
3332 };
3333 write!(&mut s, "{} {} {}", e.expr, ordering, nulls_ordering)?;
3334 }
3335
3336 Ok(s)
3337}
3338
3339pub const OUTER_REFERENCE_COLUMN_PREFIX: &str = "outer_ref";
3340pub const UNNEST_COLUMN_PREFIX: &str = "UNNEST";
3341
3342impl Display for Expr {
3345 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3346 match self {
3347 Expr::Alias(Alias { expr, name, .. }) => write!(f, "{expr} AS {name}"),
3348 Expr::Column(c) => write!(f, "{c}"),
3349 Expr::OuterReferenceColumn(_, c) => {
3350 write!(f, "{OUTER_REFERENCE_COLUMN_PREFIX}({c})")
3351 }
3352 Expr::ScalarVariable(_, var_names) => write!(f, "{}", var_names.join(".")),
3353 Expr::Literal(v, metadata) => {
3354 match metadata.as_ref().map(|m| m.is_empty()).unwrap_or(true) {
3355 false => write!(f, "{v:?} {:?}", metadata.as_ref().unwrap()),
3356 true => write!(f, "{v:?}"),
3357 }
3358 }
3359 Expr::Case(case) => {
3360 write!(f, "CASE ")?;
3361 if let Some(e) = &case.expr {
3362 write!(f, "{e} ")?;
3363 }
3364 for (w, t) in &case.when_then_expr {
3365 write!(f, "WHEN {w} THEN {t} ")?;
3366 }
3367 if let Some(e) = &case.else_expr {
3368 write!(f, "ELSE {e} ")?;
3369 }
3370 write!(f, "END")
3371 }
3372 Expr::Cast(Cast { expr, data_type }) => {
3373 write!(f, "CAST({expr} AS {data_type})")
3374 }
3375 Expr::TryCast(TryCast { expr, data_type }) => {
3376 write!(f, "TRY_CAST({expr} AS {data_type})")
3377 }
3378 Expr::Not(expr) => write!(f, "NOT {expr}"),
3379 Expr::Negative(expr) => write!(f, "(- {expr})"),
3380 Expr::IsNull(expr) => write!(f, "{expr} IS NULL"),
3381 Expr::IsNotNull(expr) => write!(f, "{expr} IS NOT NULL"),
3382 Expr::IsTrue(expr) => write!(f, "{expr} IS TRUE"),
3383 Expr::IsFalse(expr) => write!(f, "{expr} IS FALSE"),
3384 Expr::IsUnknown(expr) => write!(f, "{expr} IS UNKNOWN"),
3385 Expr::IsNotTrue(expr) => write!(f, "{expr} IS NOT TRUE"),
3386 Expr::IsNotFalse(expr) => write!(f, "{expr} IS NOT FALSE"),
3387 Expr::IsNotUnknown(expr) => write!(f, "{expr} IS NOT UNKNOWN"),
3388 Expr::Exists(Exists {
3389 subquery,
3390 negated: true,
3391 }) => write!(f, "NOT EXISTS ({subquery:?})"),
3392 Expr::Exists(Exists {
3393 subquery,
3394 negated: false,
3395 }) => write!(f, "EXISTS ({subquery:?})"),
3396 Expr::InSubquery(InSubquery {
3397 expr,
3398 subquery,
3399 negated: true,
3400 }) => write!(f, "{expr} NOT IN ({subquery:?})"),
3401 Expr::InSubquery(InSubquery {
3402 expr,
3403 subquery,
3404 negated: false,
3405 }) => write!(f, "{expr} IN ({subquery:?})"),
3406 Expr::SetComparison(SetComparison {
3407 expr,
3408 subquery,
3409 op,
3410 quantifier,
3411 }) => write!(f, "{expr} {op} {quantifier} ({subquery:?})"),
3412 Expr::ScalarSubquery(subquery) => write!(f, "({subquery:?})"),
3413 Expr::BinaryExpr(expr) => write!(f, "{expr}"),
3414 Expr::ScalarFunction(fun) => {
3415 fmt_function(f, fun.name(), false, &fun.args, true)
3416 }
3417 Expr::WindowFunction(window_fun) => {
3418 let WindowFunction { fun, params } = window_fun.as_ref();
3419 match fun {
3420 WindowFunctionDefinition::AggregateUDF(fun) => {
3421 match fun.window_function_display_name(params) {
3422 Ok(name) => {
3423 write!(f, "{name}")
3424 }
3425 Err(e) => {
3426 write!(
3427 f,
3428 "got error from window_function_display_name {e}"
3429 )
3430 }
3431 }
3432 }
3433 WindowFunctionDefinition::WindowUDF(fun) => {
3434 let WindowFunctionParams {
3435 args,
3436 partition_by,
3437 order_by,
3438 window_frame,
3439 filter,
3440 null_treatment,
3441 distinct,
3442 } = params;
3443
3444 fmt_function(f, &fun.to_string(), *distinct, args, true)?;
3445
3446 if let Some(nt) = null_treatment {
3447 write!(f, "{nt}")?;
3448 }
3449
3450 if let Some(fe) = filter {
3451 write!(f, " FILTER (WHERE {fe})")?;
3452 }
3453
3454 if !partition_by.is_empty() {
3455 write!(f, " PARTITION BY [{}]", expr_vec_fmt!(partition_by))?;
3456 }
3457 if !order_by.is_empty() {
3458 write!(f, " ORDER BY [{}]", expr_vec_fmt!(order_by))?;
3459 }
3460 write!(
3461 f,
3462 " {} BETWEEN {} AND {}",
3463 window_frame.units,
3464 window_frame.start_bound,
3465 window_frame.end_bound
3466 )
3467 }
3468 }
3469 }
3470 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3471 match func.display_name(params) {
3472 Ok(name) => {
3473 write!(f, "{name}")
3474 }
3475 Err(e) => {
3476 write!(f, "got error from display_name {e}")
3477 }
3478 }
3479 }
3480 Expr::Between(Between {
3481 expr,
3482 negated,
3483 low,
3484 high,
3485 }) => {
3486 if *negated {
3487 write!(f, "{expr} NOT BETWEEN {low} AND {high}")
3488 } else {
3489 write!(f, "{expr} BETWEEN {low} AND {high}")
3490 }
3491 }
3492 Expr::Like(Like {
3493 negated,
3494 expr,
3495 pattern,
3496 escape_char,
3497 case_insensitive,
3498 }) => {
3499 write!(f, "{expr}")?;
3500 let op_name = if *case_insensitive { "ILIKE" } else { "LIKE" };
3501 if *negated {
3502 write!(f, " NOT")?;
3503 }
3504 if let Some(char) = escape_char {
3505 write!(f, " {op_name} {pattern} ESCAPE '{char}'")
3506 } else {
3507 write!(f, " {op_name} {pattern}")
3508 }
3509 }
3510 Expr::SimilarTo(Like {
3511 negated,
3512 expr,
3513 pattern,
3514 escape_char,
3515 case_insensitive: _,
3516 }) => {
3517 write!(f, "{expr}")?;
3518 if *negated {
3519 write!(f, " NOT")?;
3520 }
3521 if let Some(char) = escape_char {
3522 write!(f, " SIMILAR TO {pattern} ESCAPE '{char}'")
3523 } else {
3524 write!(f, " SIMILAR TO {pattern}")
3525 }
3526 }
3527 Expr::InList(InList {
3528 expr,
3529 list,
3530 negated,
3531 }) => {
3532 if *negated {
3533 write!(f, "{expr} NOT IN ([{}])", expr_vec_fmt!(list))
3534 } else {
3535 write!(f, "{expr} IN ([{}])", expr_vec_fmt!(list))
3536 }
3537 }
3538 #[expect(deprecated)]
3539 Expr::Wildcard { qualifier, options } => match qualifier {
3540 Some(qualifier) => write!(f, "{qualifier}.*{options}"),
3541 None => write!(f, "*{options}"),
3542 },
3543 Expr::GroupingSet(grouping_sets) => match grouping_sets {
3544 GroupingSet::Rollup(exprs) => {
3545 write!(f, "ROLLUP ({})", expr_vec_fmt!(exprs))
3547 }
3548 GroupingSet::Cube(exprs) => {
3549 write!(f, "CUBE ({})", expr_vec_fmt!(exprs))
3551 }
3552 GroupingSet::GroupingSets(lists_of_exprs) => {
3553 write!(
3555 f,
3556 "GROUPING SETS ({})",
3557 lists_of_exprs
3558 .iter()
3559 .map(|exprs| format!("({})", expr_vec_fmt!(exprs)))
3560 .collect::<Vec<String>>()
3561 .join(", ")
3562 )
3563 }
3564 },
3565 Expr::Placeholder(Placeholder { id, .. }) => write!(f, "{id}"),
3566 Expr::Unnest(Unnest { expr }) => {
3567 write!(f, "{UNNEST_COLUMN_PREFIX}({expr})")
3568 }
3569 }
3570 }
3571}
3572
3573fn fmt_function(
3574 f: &mut Formatter,
3575 fun: &str,
3576 distinct: bool,
3577 args: &[Expr],
3578 display: bool,
3579) -> fmt::Result {
3580 let args: Vec<String> = match display {
3581 true => args.iter().map(|arg| format!("{arg}")).collect(),
3582 false => args.iter().map(|arg| format!("{arg:?}")).collect(),
3583 };
3584
3585 let distinct_str = match distinct {
3586 true => "DISTINCT ",
3587 false => "",
3588 };
3589 write!(f, "{}({}{})", fun, distinct_str, args.join(", "))
3590}
3591
3592pub fn physical_name(expr: &Expr) -> Result<String> {
3595 match expr {
3596 Expr::Column(col) => Ok(col.name.clone()),
3597 Expr::Alias(alias) => Ok(alias.name.clone()),
3598 _ => Ok(expr.schema_name().to_string()),
3599 }
3600}
3601
3602#[cfg(test)]
3603mod test {
3604 use crate::expr_fn::col;
3605 use crate::{
3606 ColumnarValue, ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl, Volatility, case,
3607 lit, placeholder, qualified_wildcard, wildcard, wildcard_with_options,
3608 };
3609 use arrow::datatypes::{Field, Schema};
3610 use sqlparser::ast;
3611 use sqlparser::ast::{Ident, IdentWithAlias};
3612 use std::any::Any;
3613
3614 #[test]
3615 fn infer_placeholder_in_clause() {
3616 let column = col("department_id");
3618 let param_placeholders = vec![
3619 Expr::Placeholder(Placeholder {
3620 id: "$1".to_string(),
3621 field: None,
3622 }),
3623 Expr::Placeholder(Placeholder {
3624 id: "$2".to_string(),
3625 field: None,
3626 }),
3627 Expr::Placeholder(Placeholder {
3628 id: "$3".to_string(),
3629 field: None,
3630 }),
3631 ];
3632 let in_list = Expr::InList(InList {
3633 expr: Box::new(column),
3634 list: param_placeholders,
3635 negated: false,
3636 });
3637
3638 let schema = Arc::new(Schema::new(vec![
3639 Field::new("name", DataType::Utf8, true),
3640 Field::new("department_id", DataType::Int32, true),
3641 ]));
3642 let df_schema = DFSchema::try_from(schema).unwrap();
3643
3644 let (inferred_expr, contains_placeholder) =
3645 in_list.infer_placeholder_types(&df_schema).unwrap();
3646
3647 assert!(contains_placeholder);
3648
3649 match inferred_expr {
3650 Expr::InList(in_list) => {
3651 for expr in in_list.list {
3652 match expr {
3653 Expr::Placeholder(placeholder) => {
3654 assert_eq!(
3655 placeholder.field.unwrap().data_type(),
3656 &DataType::Int32,
3657 "Placeholder {} should infer Int32",
3658 placeholder.id
3659 );
3660 }
3661 _ => panic!("Expected Placeholder expression"),
3662 }
3663 }
3664 }
3665 _ => panic!("Expected InList expression"),
3666 }
3667 }
3668
3669 #[test]
3670 fn infer_placeholder_like_and_similar_to() {
3671 let schema =
3673 Arc::new(Schema::new(vec![Field::new("name", DataType::Utf8, true)]));
3674 let df_schema = DFSchema::try_from(schema).unwrap();
3675
3676 let like = Like {
3677 expr: Box::new(col("name")),
3678 pattern: Box::new(Expr::Placeholder(Placeholder {
3679 id: "$1".to_string(),
3680 field: None,
3681 })),
3682 negated: false,
3683 case_insensitive: false,
3684 escape_char: None,
3685 };
3686
3687 let expr = Expr::Like(like.clone());
3688
3689 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3690 match inferred_expr {
3691 Expr::Like(like) => match *like.pattern {
3692 Expr::Placeholder(placeholder) => {
3693 assert_eq!(placeholder.field.unwrap().data_type(), &DataType::Utf8);
3694 }
3695 _ => panic!("Expected Placeholder"),
3696 },
3697 _ => panic!("Expected Like"),
3698 }
3699
3700 let expr = Expr::SimilarTo(like);
3702
3703 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3704 match inferred_expr {
3705 Expr::SimilarTo(like) => match *like.pattern {
3706 Expr::Placeholder(placeholder) => {
3707 assert_eq!(
3708 placeholder.field.unwrap().data_type(),
3709 &DataType::Utf8,
3710 "Placeholder {} should infer Utf8",
3711 placeholder.id
3712 );
3713 }
3714 _ => panic!("Expected Placeholder expression"),
3715 },
3716 _ => panic!("Expected SimilarTo expression"),
3717 }
3718 }
3719
3720 #[test]
3721 fn infer_placeholder_with_metadata() {
3722 let schema = Arc::new(Schema::new(vec![
3724 Field::new("name", DataType::Utf8, false).with_metadata(
3725 [("some_key".to_string(), "some_value".to_string())].into(),
3726 ),
3727 ]));
3728 let df_schema = DFSchema::try_from(schema).unwrap();
3729
3730 let expr = binary_expr(col("name"), Operator::Eq, placeholder("$1"));
3731
3732 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3733 match inferred_expr {
3734 Expr::BinaryExpr(BinaryExpr { right, .. }) => match *right {
3735 Expr::Placeholder(placeholder) => {
3736 assert_eq!(
3737 placeholder.field.as_ref().unwrap().data_type(),
3738 &DataType::Utf8
3739 );
3740 assert_eq!(
3741 placeholder.field.as_ref().unwrap().metadata(),
3742 df_schema.field(0).metadata()
3743 );
3744 assert!(placeholder.field.as_ref().unwrap().is_nullable());
3746 }
3747 _ => panic!("Expected Placeholder"),
3748 },
3749 _ => panic!("Expected BinaryExpr"),
3750 }
3751 }
3752
3753 #[test]
3754 fn format_case_when() -> Result<()> {
3755 let expr = case(col("a"))
3756 .when(lit(1), lit(true))
3757 .when(lit(0), lit(false))
3758 .otherwise(lit(ScalarValue::Null))?;
3759 let expected = "CASE a WHEN Int32(1) THEN Boolean(true) WHEN Int32(0) THEN Boolean(false) ELSE NULL END";
3760 assert_eq!(expected, format!("{expr}"));
3761 Ok(())
3762 }
3763
3764 #[test]
3765 fn format_cast() -> Result<()> {
3766 let expr = Expr::Cast(Cast {
3767 expr: Box::new(Expr::Literal(ScalarValue::Float32(Some(1.23)), None)),
3768 data_type: DataType::Utf8,
3769 });
3770 let expected_canonical = "CAST(Float32(1.23) AS Utf8)";
3771 assert_eq!(expected_canonical, format!("{expr}"));
3772 assert_eq!("Float32(1.23)", expr.schema_name().to_string());
3775 Ok(())
3776 }
3777
3778 #[test]
3779 fn test_partial_ord() {
3780 let exp1 = col("a") + lit(1);
3783 let exp2 = col("a") + lit(2);
3784 let exp3 = !(col("a") + lit(2));
3785
3786 assert!(exp1 < exp2);
3787 assert!(exp3 > exp2);
3788 assert!(exp1 < exp3)
3789 }
3790
3791 #[test]
3792 fn test_collect_expr() -> Result<()> {
3793 {
3795 let expr = &Expr::Cast(Cast::new(Box::new(col("a")), DataType::Float64));
3796 let columns = expr.column_refs();
3797 assert_eq!(1, columns.len());
3798 assert!(columns.contains(&Column::from_name("a")));
3799 }
3800
3801 {
3803 let expr = col("a") + col("b") + lit(1);
3804 let columns = expr.column_refs();
3805 assert_eq!(2, columns.len());
3806 assert!(columns.contains(&Column::from_name("a")));
3807 assert!(columns.contains(&Column::from_name("b")));
3808 }
3809
3810 Ok(())
3811 }
3812
3813 #[test]
3814 fn test_logical_ops() {
3815 assert_eq!(
3816 format!("{}", lit(1u32).eq(lit(2u32))),
3817 "UInt32(1) = UInt32(2)"
3818 );
3819 assert_eq!(
3820 format!("{}", lit(1u32).not_eq(lit(2u32))),
3821 "UInt32(1) != UInt32(2)"
3822 );
3823 assert_eq!(
3824 format!("{}", lit(1u32).gt(lit(2u32))),
3825 "UInt32(1) > UInt32(2)"
3826 );
3827 assert_eq!(
3828 format!("{}", lit(1u32).gt_eq(lit(2u32))),
3829 "UInt32(1) >= UInt32(2)"
3830 );
3831 assert_eq!(
3832 format!("{}", lit(1u32).lt(lit(2u32))),
3833 "UInt32(1) < UInt32(2)"
3834 );
3835 assert_eq!(
3836 format!("{}", lit(1u32).lt_eq(lit(2u32))),
3837 "UInt32(1) <= UInt32(2)"
3838 );
3839 assert_eq!(
3840 format!("{}", lit(1u32).and(lit(2u32))),
3841 "UInt32(1) AND UInt32(2)"
3842 );
3843 assert_eq!(
3844 format!("{}", lit(1u32).or(lit(2u32))),
3845 "UInt32(1) OR UInt32(2)"
3846 );
3847 }
3848
3849 #[test]
3850 fn test_is_volatile_scalar_func() {
3851 #[derive(Debug, PartialEq, Eq, Hash)]
3853 struct TestScalarUDF {
3854 signature: Signature,
3855 }
3856 impl ScalarUDFImpl for TestScalarUDF {
3857 fn as_any(&self) -> &dyn Any {
3858 self
3859 }
3860 fn name(&self) -> &str {
3861 "TestScalarUDF"
3862 }
3863
3864 fn signature(&self) -> &Signature {
3865 &self.signature
3866 }
3867
3868 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
3869 Ok(DataType::Utf8)
3870 }
3871
3872 fn invoke_with_args(
3873 &self,
3874 _args: ScalarFunctionArgs,
3875 ) -> Result<ColumnarValue> {
3876 Ok(ColumnarValue::Scalar(ScalarValue::from("a")))
3877 }
3878 }
3879 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3880 signature: Signature::uniform(1, vec![DataType::Float32], Volatility::Stable),
3881 }));
3882 assert_ne!(udf.signature().volatility, Volatility::Volatile);
3883
3884 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3885 signature: Signature::uniform(
3886 1,
3887 vec![DataType::Float32],
3888 Volatility::Volatile,
3889 ),
3890 }));
3891 assert_eq!(udf.signature().volatility, Volatility::Volatile);
3892 }
3893
3894 use super::*;
3895 use crate::logical_plan::{EmptyRelation, LogicalPlan};
3896
3897 #[test]
3898 fn test_display_wildcard() {
3899 assert_eq!(format!("{}", wildcard()), "*");
3900 assert_eq!(format!("{}", qualified_wildcard("t1")), "t1.*");
3901 assert_eq!(
3902 format!(
3903 "{}",
3904 wildcard_with_options(wildcard_options(
3905 Some(IlikeSelectItem {
3906 pattern: "c1".to_string()
3907 }),
3908 None,
3909 None,
3910 None,
3911 None
3912 ))
3913 ),
3914 "* ILIKE 'c1'"
3915 );
3916 assert_eq!(
3917 format!(
3918 "{}",
3919 wildcard_with_options(wildcard_options(
3920 None,
3921 Some(ExcludeSelectItem::Multiple(vec![
3922 Ident::from("c1"),
3923 Ident::from("c2")
3924 ])),
3925 None,
3926 None,
3927 None
3928 ))
3929 ),
3930 "* EXCLUDE (c1, c2)"
3931 );
3932 assert_eq!(
3933 format!(
3934 "{}",
3935 wildcard_with_options(wildcard_options(
3936 None,
3937 None,
3938 Some(ExceptSelectItem {
3939 first_element: Ident::from("c1"),
3940 additional_elements: vec![Ident::from("c2")]
3941 }),
3942 None,
3943 None
3944 ))
3945 ),
3946 "* EXCEPT (c1, c2)"
3947 );
3948 assert_eq!(
3949 format!(
3950 "{}",
3951 wildcard_with_options(wildcard_options(
3952 None,
3953 None,
3954 None,
3955 Some(PlannedReplaceSelectItem {
3956 items: vec![ReplaceSelectElement {
3957 expr: ast::Expr::Identifier(Ident::from("c1")),
3958 column_name: Ident::from("a1"),
3959 as_keyword: false
3960 }],
3961 planned_expressions: vec![]
3962 }),
3963 None
3964 ))
3965 ),
3966 "* REPLACE (c1 a1)"
3967 );
3968 assert_eq!(
3969 format!(
3970 "{}",
3971 wildcard_with_options(wildcard_options(
3972 None,
3973 None,
3974 None,
3975 None,
3976 Some(RenameSelectItem::Multiple(vec![IdentWithAlias {
3977 ident: Ident::from("c1"),
3978 alias: Ident::from("a1")
3979 }]))
3980 ))
3981 ),
3982 "* RENAME (c1 AS a1)"
3983 )
3984 }
3985
3986 #[test]
3987 fn test_display_set_comparison() {
3988 let subquery = Subquery {
3989 subquery: Arc::new(LogicalPlan::EmptyRelation(EmptyRelation {
3990 produce_one_row: false,
3991 schema: Arc::new(DFSchema::empty()),
3992 })),
3993 outer_ref_columns: vec![],
3994 spans: Spans::new(),
3995 };
3996
3997 let expr = Expr::SetComparison(SetComparison::new(
3998 Box::new(Expr::Column(Column::from_name("a"))),
3999 subquery,
4000 Operator::Gt,
4001 SetQuantifier::Any,
4002 ));
4003
4004 assert_eq!(format!("{expr}"), "a > ANY (<subquery>)");
4005 assert_eq!(format!("{}", expr.human_display()), "a > ANY (<subquery>)");
4006 }
4007
4008 #[test]
4009 fn test_schema_display_alias_with_relation() {
4010 assert_eq!(
4011 format!(
4012 "{}",
4013 SchemaDisplay(
4014 &lit(1).alias_qualified("table_name".into(), "column_name")
4015 )
4016 ),
4017 "table_name.column_name"
4018 );
4019 }
4020
4021 #[test]
4022 fn test_schema_display_alias_without_relation() {
4023 assert_eq!(
4024 format!(
4025 "{}",
4026 SchemaDisplay(&lit(1).alias_qualified(None::<&str>, "column_name"))
4027 ),
4028 "column_name"
4029 );
4030 }
4031
4032 fn wildcard_options(
4033 opt_ilike: Option<IlikeSelectItem>,
4034 opt_exclude: Option<ExcludeSelectItem>,
4035 opt_except: Option<ExceptSelectItem>,
4036 opt_replace: Option<PlannedReplaceSelectItem>,
4037 opt_rename: Option<RenameSelectItem>,
4038 ) -> WildcardOptions {
4039 WildcardOptions {
4040 ilike: opt_ilike,
4041 exclude: opt_exclude,
4042 except: opt_except,
4043 replace: opt_replace,
4044 rename: opt_rename,
4045 }
4046 }
4047
4048 #[test]
4049 fn test_size_of_expr() {
4050 assert_eq!(size_of::<Expr>(), 112);
4057 assert_eq!(size_of::<ScalarValue>(), 64);
4058 assert_eq!(size_of::<DataType>(), 24); assert_eq!(size_of::<Vec<Expr>>(), 24);
4060 assert_eq!(size_of::<Arc<Expr>>(), 8);
4061 }
4062
4063 #[test]
4064 fn test_accept_exprs() {
4065 fn accept_exprs<E: AsRef<Expr>>(_: &[E]) {}
4066
4067 let expr = || -> Expr { lit(1) };
4068
4069 let owned_exprs = vec![expr(), expr()];
4071 accept_exprs(&owned_exprs);
4072
4073 let udf = Expr::ScalarFunction(ScalarFunction {
4075 func: Arc::new(ScalarUDF::new_from_impl(TestUDF {})),
4076 args: vec![expr(), expr()],
4077 });
4078 let Expr::ScalarFunction(scalar) = &udf else {
4079 unreachable!()
4080 };
4081 accept_exprs(&scalar.args);
4082
4083 let mut collected_refs: Vec<&Expr> = scalar.args.iter().collect();
4085 collected_refs.extend(&owned_exprs);
4086 accept_exprs(&collected_refs);
4087
4088 #[derive(Debug, PartialEq, Eq, Hash)]
4090 struct TestUDF {}
4091 impl ScalarUDFImpl for TestUDF {
4092 fn as_any(&self) -> &dyn Any {
4093 unimplemented!()
4094 }
4095
4096 fn name(&self) -> &str {
4097 unimplemented!()
4098 }
4099
4100 fn signature(&self) -> &Signature {
4101 unimplemented!()
4102 }
4103
4104 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
4105 unimplemented!()
4106 }
4107
4108 fn invoke_with_args(
4109 &self,
4110 _args: ScalarFunctionArgs,
4111 ) -> Result<ColumnarValue> {
4112 unimplemented!()
4113 }
4114 }
4115 }
4116}