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_functions_window_common::field::WindowUDFFieldArgs;
42#[cfg(feature = "sql")]
43use sqlparser::ast::{
44 display_comma_separated, ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem,
45 RenameSelectItem, ReplaceSelectElement,
46};
47
48pub use datafusion_common::metadata::FieldMetadata;
50use datafusion_common::metadata::ScalarAndMetadata;
51
52#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
55pub enum NullTreatment {
56 IgnoreNulls,
57 RespectNulls,
58}
59
60impl Display for NullTreatment {
61 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
62 f.write_str(match self {
63 NullTreatment::IgnoreNulls => "IGNORE NULLS",
64 NullTreatment::RespectNulls => "RESPECT NULLS",
65 })
66 }
67}
68
69#[cfg(feature = "sql")]
70impl From<sqlparser::ast::NullTreatment> for NullTreatment {
71 fn from(value: sqlparser::ast::NullTreatment) -> Self {
72 match value {
73 sqlparser::ast::NullTreatment::IgnoreNulls => Self::IgnoreNulls,
74 sqlparser::ast::NullTreatment::RespectNulls => Self::RespectNulls,
75 }
76 }
77}
78
79#[derive(Clone, PartialEq, PartialOrd, Eq, Debug, Hash)]
313pub enum Expr {
314 Alias(Alias),
316 Column(Column),
318 ScalarVariable(DataType, Vec<String>),
320 Literal(ScalarValue, Option<FieldMetadata>),
322 BinaryExpr(BinaryExpr),
324 Like(Like),
326 SimilarTo(Like),
328 Not(Box<Expr>),
330 IsNotNull(Box<Expr>),
332 IsNull(Box<Expr>),
334 IsTrue(Box<Expr>),
336 IsFalse(Box<Expr>),
338 IsUnknown(Box<Expr>),
340 IsNotTrue(Box<Expr>),
342 IsNotFalse(Box<Expr>),
344 IsNotUnknown(Box<Expr>),
346 Negative(Box<Expr>),
348 Between(Between),
350 Case(Case),
352 Cast(Cast),
355 TryCast(TryCast),
358 ScalarFunction(ScalarFunction),
360 AggregateFunction(AggregateFunction),
367 WindowFunction(Box<WindowFunction>),
369 InList(InList),
371 Exists(Exists),
373 InSubquery(InSubquery),
375 ScalarSubquery(Subquery),
377 #[deprecated(
383 since = "46.0.0",
384 note = "A wildcard needs to be resolved to concrete expressions when constructing the logical plan. See https://github.com/apache/datafusion/issues/7765"
385 )]
386 Wildcard {
387 qualifier: Option<TableReference>,
388 options: Box<WildcardOptions>,
389 },
390 GroupingSet(GroupingSet),
393 Placeholder(Placeholder),
396 OuterReferenceColumn(FieldRef, Column),
399 Unnest(Unnest),
401 Lambda(Lambda),
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, PartialEq, Eq, PartialOrd, Hash, Debug)]
1110pub struct InList {
1111 pub expr: Box<Expr>,
1113 pub list: Vec<Expr>,
1115 pub negated: bool,
1117}
1118
1119impl InList {
1120 pub fn new(expr: Box<Expr>, list: Vec<Expr>, negated: bool) -> Self {
1122 Self {
1123 expr,
1124 list,
1125 negated,
1126 }
1127 }
1128}
1129
1130#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1132pub struct InSubquery {
1133 pub expr: Box<Expr>,
1135 pub subquery: Subquery,
1137 pub negated: bool,
1139}
1140
1141impl InSubquery {
1142 pub fn new(expr: Box<Expr>, subquery: Subquery, negated: bool) -> Self {
1144 Self {
1145 expr,
1146 subquery,
1147 negated,
1148 }
1149 }
1150}
1151
1152#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1157pub struct Placeholder {
1158 pub id: String,
1160 pub field: Option<FieldRef>,
1162}
1163
1164impl Placeholder {
1165 #[deprecated(since = "51.0.0", note = "Use new_with_field instead")]
1167 pub fn new(id: String, data_type: Option<DataType>) -> Self {
1168 Self {
1169 id,
1170 field: data_type.map(|dt| Arc::new(Field::new("", dt, true))),
1171 }
1172 }
1173
1174 pub fn new_with_field(id: String, field: Option<FieldRef>) -> Self {
1176 Self { id, field }
1177 }
1178}
1179
1180#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1187pub enum GroupingSet {
1188 Rollup(Vec<Expr>),
1190 Cube(Vec<Expr>),
1192 GroupingSets(Vec<Vec<Expr>>),
1194}
1195
1196impl GroupingSet {
1197 pub fn distinct_expr(&self) -> Vec<&Expr> {
1201 match self {
1202 GroupingSet::Rollup(exprs) | GroupingSet::Cube(exprs) => {
1203 exprs.iter().collect()
1204 }
1205 GroupingSet::GroupingSets(groups) => {
1206 let mut exprs: Vec<&Expr> = vec![];
1207 for exp in groups.iter().flatten() {
1208 if !exprs.contains(&exp) {
1209 exprs.push(exp);
1210 }
1211 }
1212 exprs
1213 }
1214 }
1215 }
1216}
1217
1218#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1220pub struct Lambda {
1221 pub params: Vec<String>,
1222 pub body: Box<Expr>,
1223}
1224
1225impl Lambda {
1226 pub fn new(params: Vec<String>, body: Expr) -> Self {
1228 Self {
1229 params,
1230 body: Box::new(body),
1231 }
1232 }
1233}
1234
1235#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1236#[cfg(not(feature = "sql"))]
1237pub struct IlikeSelectItem {
1238 pub pattern: String,
1239}
1240#[cfg(not(feature = "sql"))]
1241impl Display for IlikeSelectItem {
1242 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1243 write!(f, "ILIKE '{}'", &self.pattern)?;
1244 Ok(())
1245 }
1246}
1247#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1248#[cfg(not(feature = "sql"))]
1249pub enum ExcludeSelectItem {
1250 Single(Ident),
1251 Multiple(Vec<Ident>),
1252}
1253#[cfg(not(feature = "sql"))]
1254impl Display for ExcludeSelectItem {
1255 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1256 write!(f, "EXCLUDE")?;
1257 match self {
1258 Self::Single(column) => {
1259 write!(f, " {column}")?;
1260 }
1261 Self::Multiple(columns) => {
1262 write!(f, " ({})", display_comma_separated(columns))?;
1263 }
1264 }
1265 Ok(())
1266 }
1267}
1268#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1269#[cfg(not(feature = "sql"))]
1270pub struct ExceptSelectItem {
1271 pub first_element: Ident,
1272 pub additional_elements: Vec<Ident>,
1273}
1274#[cfg(not(feature = "sql"))]
1275impl Display for ExceptSelectItem {
1276 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1277 write!(f, "EXCEPT ")?;
1278 if self.additional_elements.is_empty() {
1279 write!(f, "({})", self.first_element)?;
1280 } else {
1281 write!(
1282 f,
1283 "({}, {})",
1284 self.first_element,
1285 display_comma_separated(&self.additional_elements)
1286 )?;
1287 }
1288 Ok(())
1289 }
1290}
1291
1292#[cfg(not(feature = "sql"))]
1293pub fn display_comma_separated<T>(slice: &[T]) -> String
1294where
1295 T: Display,
1296{
1297 use itertools::Itertools;
1298 slice.iter().map(|v| format!("{v}")).join(", ")
1299}
1300
1301#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1302#[cfg(not(feature = "sql"))]
1303pub enum RenameSelectItem {
1304 Single(String),
1305 Multiple(Vec<String>),
1306}
1307#[cfg(not(feature = "sql"))]
1308impl Display for RenameSelectItem {
1309 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1310 write!(f, "RENAME")?;
1311 match self {
1312 Self::Single(column) => {
1313 write!(f, " {column}")?;
1314 }
1315 Self::Multiple(columns) => {
1316 write!(f, " ({})", display_comma_separated(columns))?;
1317 }
1318 }
1319 Ok(())
1320 }
1321}
1322
1323#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1324#[cfg(not(feature = "sql"))]
1325pub struct Ident {
1326 pub value: String,
1328 pub quote_style: Option<char>,
1331 pub span: String,
1333}
1334#[cfg(not(feature = "sql"))]
1335impl Display for Ident {
1336 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1337 write!(f, "[{}]", self.value)
1338 }
1339}
1340
1341#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1342#[cfg(not(feature = "sql"))]
1343pub struct ReplaceSelectElement {
1344 pub expr: String,
1345 pub column_name: Ident,
1346 pub as_keyword: bool,
1347}
1348#[cfg(not(feature = "sql"))]
1349impl Display for ReplaceSelectElement {
1350 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1351 if self.as_keyword {
1352 write!(f, "{} AS {}", self.expr, self.column_name)
1353 } else {
1354 write!(f, "{} {}", self.expr, self.column_name)
1355 }
1356 }
1357}
1358
1359#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1361pub struct WildcardOptions {
1362 pub ilike: Option<IlikeSelectItem>,
1365 pub exclude: Option<ExcludeSelectItem>,
1368 pub except: Option<ExceptSelectItem>,
1372 pub replace: Option<PlannedReplaceSelectItem>,
1377 pub rename: Option<RenameSelectItem>,
1380}
1381
1382impl WildcardOptions {
1383 pub fn with_replace(self, replace: PlannedReplaceSelectItem) -> Self {
1384 WildcardOptions {
1385 ilike: self.ilike,
1386 exclude: self.exclude,
1387 except: self.except,
1388 replace: Some(replace),
1389 rename: self.rename,
1390 }
1391 }
1392}
1393
1394impl Display for WildcardOptions {
1395 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1396 if let Some(ilike) = &self.ilike {
1397 write!(f, " {ilike}")?;
1398 }
1399 if let Some(exclude) = &self.exclude {
1400 write!(f, " {exclude}")?;
1401 }
1402 if let Some(except) = &self.except {
1403 write!(f, " {except}")?;
1404 }
1405 if let Some(replace) = &self.replace {
1406 write!(f, " {replace}")?;
1407 }
1408 if let Some(rename) = &self.rename {
1409 write!(f, " {rename}")?;
1410 }
1411 Ok(())
1412 }
1413}
1414
1415#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1417pub struct PlannedReplaceSelectItem {
1418 pub items: Vec<ReplaceSelectElement>,
1420 pub planned_expressions: Vec<Expr>,
1422}
1423
1424impl Display for PlannedReplaceSelectItem {
1425 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1426 write!(f, "REPLACE")?;
1427 write!(f, " ({})", display_comma_separated(&self.items))?;
1428 Ok(())
1429 }
1430}
1431
1432impl PlannedReplaceSelectItem {
1433 pub fn items(&self) -> &[ReplaceSelectElement] {
1434 &self.items
1435 }
1436
1437 pub fn expressions(&self) -> &[Expr] {
1438 &self.planned_expressions
1439 }
1440}
1441
1442impl Expr {
1443 pub fn schema_name(&self) -> impl Display + '_ {
1466 SchemaDisplay(self)
1467 }
1468
1469 pub fn human_display(&self) -> impl Display + '_ {
1491 SqlDisplay(self)
1492 }
1493
1494 pub fn qualified_name(&self) -> (Option<TableReference>, String) {
1500 match self {
1501 Expr::Column(Column {
1502 relation,
1503 name,
1504 spans: _,
1505 }) => (relation.clone(), name.clone()),
1506 Expr::Alias(Alias { relation, name, .. }) => (relation.clone(), name.clone()),
1507 _ => (None, self.schema_name().to_string()),
1508 }
1509 }
1510
1511 pub fn variant_name(&self) -> &str {
1514 match self {
1515 Expr::AggregateFunction { .. } => "AggregateFunction",
1516 Expr::Alias(..) => "Alias",
1517 Expr::Between { .. } => "Between",
1518 Expr::BinaryExpr { .. } => "BinaryExpr",
1519 Expr::Case { .. } => "Case",
1520 Expr::Cast { .. } => "Cast",
1521 Expr::Column(..) => "Column",
1522 Expr::OuterReferenceColumn(_, _) => "Outer",
1523 Expr::Exists { .. } => "Exists",
1524 Expr::GroupingSet(..) => "GroupingSet",
1525 Expr::InList { .. } => "InList",
1526 Expr::InSubquery(..) => "InSubquery",
1527 Expr::IsNotNull(..) => "IsNotNull",
1528 Expr::IsNull(..) => "IsNull",
1529 Expr::Like { .. } => "Like",
1530 Expr::SimilarTo { .. } => "RLike",
1531 Expr::IsTrue(..) => "IsTrue",
1532 Expr::IsFalse(..) => "IsFalse",
1533 Expr::IsUnknown(..) => "IsUnknown",
1534 Expr::IsNotTrue(..) => "IsNotTrue",
1535 Expr::IsNotFalse(..) => "IsNotFalse",
1536 Expr::IsNotUnknown(..) => "IsNotUnknown",
1537 Expr::Literal(..) => "Literal",
1538 Expr::Negative(..) => "Negative",
1539 Expr::Not(..) => "Not",
1540 Expr::Placeholder(_) => "Placeholder",
1541 Expr::ScalarFunction(..) => "ScalarFunction",
1542 Expr::ScalarSubquery { .. } => "ScalarSubquery",
1543 Expr::ScalarVariable(..) => "ScalarVariable",
1544 Expr::TryCast { .. } => "TryCast",
1545 Expr::WindowFunction { .. } => "WindowFunction",
1546 #[expect(deprecated)]
1547 Expr::Wildcard { .. } => "Wildcard",
1548 Expr::Unnest { .. } => "Unnest",
1549 Expr::Lambda { .. } => "Lambda",
1550 }
1551 }
1552
1553 pub fn eq(self, other: Expr) -> Expr {
1555 binary_expr(self, Operator::Eq, other)
1556 }
1557
1558 pub fn not_eq(self, other: Expr) -> Expr {
1560 binary_expr(self, Operator::NotEq, other)
1561 }
1562
1563 pub fn gt(self, other: Expr) -> Expr {
1565 binary_expr(self, Operator::Gt, other)
1566 }
1567
1568 pub fn gt_eq(self, other: Expr) -> Expr {
1570 binary_expr(self, Operator::GtEq, other)
1571 }
1572
1573 pub fn lt(self, other: Expr) -> Expr {
1575 binary_expr(self, Operator::Lt, other)
1576 }
1577
1578 pub fn lt_eq(self, other: Expr) -> Expr {
1580 binary_expr(self, Operator::LtEq, other)
1581 }
1582
1583 pub fn and(self, other: Expr) -> Expr {
1585 binary_expr(self, Operator::And, other)
1586 }
1587
1588 pub fn or(self, other: Expr) -> Expr {
1590 binary_expr(self, Operator::Or, other)
1591 }
1592
1593 pub fn like(self, other: Expr) -> Expr {
1595 Expr::Like(Like::new(
1596 false,
1597 Box::new(self),
1598 Box::new(other),
1599 None,
1600 false,
1601 ))
1602 }
1603
1604 pub fn not_like(self, other: Expr) -> Expr {
1606 Expr::Like(Like::new(
1607 true,
1608 Box::new(self),
1609 Box::new(other),
1610 None,
1611 false,
1612 ))
1613 }
1614
1615 pub fn ilike(self, other: Expr) -> Expr {
1617 Expr::Like(Like::new(
1618 false,
1619 Box::new(self),
1620 Box::new(other),
1621 None,
1622 true,
1623 ))
1624 }
1625
1626 pub fn not_ilike(self, other: Expr) -> Expr {
1628 Expr::Like(Like::new(true, Box::new(self), Box::new(other), None, true))
1629 }
1630
1631 pub fn name_for_alias(&self) -> Result<String> {
1633 Ok(self.schema_name().to_string())
1634 }
1635
1636 pub fn alias_if_changed(self, original_name: String) -> Result<Expr> {
1639 let new_name = self.name_for_alias()?;
1640 if new_name == original_name {
1641 return Ok(self);
1642 }
1643
1644 Ok(self.alias(original_name))
1645 }
1646
1647 pub fn alias(self, name: impl Into<String>) -> Expr {
1649 Expr::Alias(Alias::new(self, None::<&str>, name.into()))
1650 }
1651
1652 pub fn alias_with_metadata(
1667 self,
1668 name: impl Into<String>,
1669 metadata: Option<FieldMetadata>,
1670 ) -> Expr {
1671 Expr::Alias(Alias::new(self, None::<&str>, name.into()).with_metadata(metadata))
1672 }
1673
1674 pub fn alias_qualified(
1676 self,
1677 relation: Option<impl Into<TableReference>>,
1678 name: impl Into<String>,
1679 ) -> Expr {
1680 Expr::Alias(Alias::new(self, relation, name.into()))
1681 }
1682
1683 pub fn alias_qualified_with_metadata(
1699 self,
1700 relation: Option<impl Into<TableReference>>,
1701 name: impl Into<String>,
1702 metadata: Option<FieldMetadata>,
1703 ) -> Expr {
1704 Expr::Alias(Alias::new(self, relation, name.into()).with_metadata(metadata))
1705 }
1706
1707 pub fn unalias(self) -> Expr {
1728 match self {
1729 Expr::Alias(alias) => *alias.expr,
1730 _ => self,
1731 }
1732 }
1733
1734 pub fn unalias_nested(self) -> Transformed<Expr> {
1755 self.transform_down_up(
1756 |expr| {
1757 let recursion = if matches!(
1759 expr,
1760 Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_)
1761 ) {
1762 TreeNodeRecursion::Jump
1764 } else {
1765 TreeNodeRecursion::Continue
1766 };
1767 Ok(Transformed::new(expr, false, recursion))
1768 },
1769 |expr| {
1770 if let Expr::Alias(alias) = expr {
1773 match alias
1774 .metadata
1775 .as_ref()
1776 .map(|h| h.is_empty())
1777 .unwrap_or(true)
1778 {
1779 true => Ok(Transformed::yes(*alias.expr)),
1780 false => Ok(Transformed::no(Expr::Alias(alias))),
1781 }
1782 } else {
1783 Ok(Transformed::no(expr))
1784 }
1785 },
1786 )
1787 .unwrap()
1789 }
1790
1791 pub fn in_list(self, list: Vec<Expr>, negated: bool) -> Expr {
1794 Expr::InList(InList::new(Box::new(self), list, negated))
1795 }
1796
1797 pub fn is_null(self) -> Expr {
1799 Expr::IsNull(Box::new(self))
1800 }
1801
1802 pub fn is_not_null(self) -> Expr {
1804 Expr::IsNotNull(Box::new(self))
1805 }
1806
1807 pub fn sort(self, asc: bool, nulls_first: bool) -> Sort {
1814 Sort::new(self, asc, nulls_first)
1815 }
1816
1817 pub fn is_true(self) -> Expr {
1819 Expr::IsTrue(Box::new(self))
1820 }
1821
1822 pub fn is_not_true(self) -> Expr {
1824 Expr::IsNotTrue(Box::new(self))
1825 }
1826
1827 pub fn is_false(self) -> Expr {
1829 Expr::IsFalse(Box::new(self))
1830 }
1831
1832 pub fn is_not_false(self) -> Expr {
1834 Expr::IsNotFalse(Box::new(self))
1835 }
1836
1837 pub fn is_unknown(self) -> Expr {
1839 Expr::IsUnknown(Box::new(self))
1840 }
1841
1842 pub fn is_not_unknown(self) -> Expr {
1844 Expr::IsNotUnknown(Box::new(self))
1845 }
1846
1847 pub fn between(self, low: Expr, high: Expr) -> Expr {
1849 Expr::Between(Between::new(
1850 Box::new(self),
1851 false,
1852 Box::new(low),
1853 Box::new(high),
1854 ))
1855 }
1856
1857 pub fn not_between(self, low: Expr, high: Expr) -> Expr {
1859 Expr::Between(Between::new(
1860 Box::new(self),
1861 true,
1862 Box::new(low),
1863 Box::new(high),
1864 ))
1865 }
1866 pub fn try_as_col(&self) -> Option<&Column> {
1884 if let Expr::Column(it) = self {
1885 Some(it)
1886 } else {
1887 None
1888 }
1889 }
1890
1891 pub fn get_as_join_column(&self) -> Option<&Column> {
1898 match self {
1899 Expr::Column(c) => Some(c),
1900 Expr::Cast(Cast { expr, .. }) => match &**expr {
1901 Expr::Column(c) => Some(c),
1902 _ => None,
1903 },
1904 _ => None,
1905 }
1906 }
1907
1908 pub fn column_refs(&self) -> HashSet<&Column> {
1924 let mut using_columns = HashSet::new();
1925 self.add_column_refs(&mut using_columns);
1926 using_columns
1927 }
1928
1929 pub fn add_column_refs<'a>(&'a self, set: &mut HashSet<&'a Column>) {
1933 self.apply_with_lambdas_params(|expr, lambdas_params| {
1934 if let Expr::Column(col) = expr {
1935 if col.relation.is_some() || !lambdas_params.contains(col.name()) {
1936 set.insert(col);
1937 }
1938 }
1939 Ok(TreeNodeRecursion::Continue)
1940 })
1941 .expect("traversal is infallible");
1942 }
1943
1944 pub fn column_refs_counts(&self) -> HashMap<&Column, usize> {
1960 let mut map = HashMap::new();
1961 self.add_column_ref_counts(&mut map);
1962 map
1963 }
1964
1965 pub fn add_column_ref_counts<'a>(&'a self, map: &mut HashMap<&'a Column, usize>) {
1970 self.apply_with_lambdas_params(|expr, lambdas_params| {
1971 if let Expr::Column(col) = expr {
1972 if !col.is_lambda_parameter(lambdas_params) {
1973 *map.entry(col).or_default() += 1;
1974 }
1975 }
1976 Ok(TreeNodeRecursion::Continue)
1977 })
1978 .expect("traversal is infallible");
1979 }
1980
1981 pub fn any_column_refs(&self) -> bool {
1983 self.exists_with_lambdas_params(|expr, lambdas_params| {
1984 Ok(matches!(expr, Expr::Column(c) if !c.is_lambda_parameter(lambdas_params)))
1985 })
1986 .expect("exists closure is infallible")
1987 }
1988
1989 pub fn contains_outer(&self) -> bool {
1991 self.exists(|expr| Ok(matches!(expr, Expr::OuterReferenceColumn { .. })))
1992 .expect("exists closure is infallible")
1993 }
1994
1995 pub fn is_volatile_node(&self) -> bool {
2001 matches!(self, Expr::ScalarFunction(func) if func.func.signature().volatility == Volatility::Volatile)
2002 }
2003
2004 pub fn is_volatile(&self) -> bool {
2012 self.exists(|expr| Ok(expr.is_volatile_node()))
2013 .expect("exists closure is infallible")
2014 }
2015
2016 pub fn infer_placeholder_types(self, schema: &DFSchema) -> Result<(Expr, bool)> {
2025 let mut has_placeholder = false;
2026 self.transform_with_schema(schema, |mut expr, schema| {
2027 match &mut expr {
2028 Expr::BinaryExpr(BinaryExpr { left, op: _, right }) => {
2030 rewrite_placeholder(left.as_mut(), right.as_ref(), schema)?;
2031 rewrite_placeholder(right.as_mut(), left.as_ref(), schema)?;
2032 }
2033 Expr::Between(Between {
2034 expr,
2035 negated: _,
2036 low,
2037 high,
2038 }) => {
2039 rewrite_placeholder(low.as_mut(), expr.as_ref(), schema)?;
2040 rewrite_placeholder(high.as_mut(), expr.as_ref(), schema)?;
2041 }
2042 Expr::InList(InList {
2043 expr,
2044 list,
2045 negated: _,
2046 }) => {
2047 for item in list.iter_mut() {
2048 rewrite_placeholder(item, expr.as_ref(), schema)?;
2049 }
2050 }
2051 Expr::Like(Like { expr, pattern, .. })
2052 | Expr::SimilarTo(Like { expr, pattern, .. }) => {
2053 rewrite_placeholder(pattern.as_mut(), expr.as_ref(), schema)?;
2054 }
2055 Expr::Placeholder(_) => {
2056 has_placeholder = true;
2057 }
2058 _ => {}
2059 }
2060 Ok(Transformed::yes(expr))
2061 })
2062 .data()
2063 .map(|data| (data, has_placeholder))
2064 }
2065
2066 pub fn short_circuits(&self) -> bool {
2069 match self {
2070 Expr::ScalarFunction(ScalarFunction { func, .. }) => func.short_circuits(),
2071 Expr::BinaryExpr(BinaryExpr { op, .. }) => {
2072 matches!(op, Operator::And | Operator::Or)
2073 }
2074 Expr::Case { .. } => true,
2075 #[expect(deprecated)]
2080 Expr::AggregateFunction(..)
2081 | Expr::Alias(..)
2082 | Expr::Between(..)
2083 | Expr::Cast(..)
2084 | Expr::Column(..)
2085 | Expr::Exists(..)
2086 | Expr::GroupingSet(..)
2087 | Expr::InList(..)
2088 | Expr::InSubquery(..)
2089 | Expr::IsFalse(..)
2090 | Expr::IsNotFalse(..)
2091 | Expr::IsNotNull(..)
2092 | Expr::IsNotTrue(..)
2093 | Expr::IsNotUnknown(..)
2094 | Expr::IsNull(..)
2095 | Expr::IsTrue(..)
2096 | Expr::IsUnknown(..)
2097 | Expr::Like(..)
2098 | Expr::ScalarSubquery(..)
2099 | Expr::ScalarVariable(_, _)
2100 | Expr::SimilarTo(..)
2101 | Expr::Not(..)
2102 | Expr::Negative(..)
2103 | Expr::OuterReferenceColumn(_, _)
2104 | Expr::TryCast(..)
2105 | Expr::Unnest(..)
2106 | Expr::Wildcard { .. }
2107 | Expr::WindowFunction(..)
2108 | Expr::Literal(..)
2109 | Expr::Placeholder(..)
2110 | Expr::Lambda { .. } => false,
2111 }
2112 }
2113
2114 pub fn spans(&self) -> Option<&Spans> {
2118 match self {
2119 Expr::Column(col) => Some(&col.spans),
2120 _ => None,
2121 }
2122 }
2123
2124 pub fn as_literal(&self) -> Option<&ScalarValue> {
2126 if let Expr::Literal(lit, _) = self {
2127 Some(lit)
2128 } else {
2129 None
2130 }
2131 }
2132}
2133
2134impl Normalizeable for Expr {
2135 fn can_normalize(&self) -> bool {
2136 #[allow(clippy::match_like_matches_macro)]
2137 match self {
2138 Expr::BinaryExpr(BinaryExpr {
2139 op:
2140 _op @ (Operator::Plus
2141 | Operator::Multiply
2142 | Operator::BitwiseAnd
2143 | Operator::BitwiseOr
2144 | Operator::BitwiseXor
2145 | Operator::Eq
2146 | Operator::NotEq),
2147 ..
2148 }) => true,
2149 _ => false,
2150 }
2151 }
2152}
2153
2154impl NormalizeEq for Expr {
2155 fn normalize_eq(&self, other: &Self) -> bool {
2156 match (self, other) {
2157 (
2158 Expr::BinaryExpr(BinaryExpr {
2159 left: self_left,
2160 op: self_op,
2161 right: self_right,
2162 }),
2163 Expr::BinaryExpr(BinaryExpr {
2164 left: other_left,
2165 op: other_op,
2166 right: other_right,
2167 }),
2168 ) => {
2169 if self_op != other_op {
2170 return false;
2171 }
2172
2173 if matches!(
2174 self_op,
2175 Operator::Plus
2176 | Operator::Multiply
2177 | Operator::BitwiseAnd
2178 | Operator::BitwiseOr
2179 | Operator::BitwiseXor
2180 | Operator::Eq
2181 | Operator::NotEq
2182 ) {
2183 (self_left.normalize_eq(other_left)
2184 && self_right.normalize_eq(other_right))
2185 || (self_left.normalize_eq(other_right)
2186 && self_right.normalize_eq(other_left))
2187 } else {
2188 self_left.normalize_eq(other_left)
2189 && self_right.normalize_eq(other_right)
2190 }
2191 }
2192 (
2193 Expr::Alias(Alias {
2194 expr: self_expr,
2195 relation: self_relation,
2196 name: self_name,
2197 ..
2198 }),
2199 Expr::Alias(Alias {
2200 expr: other_expr,
2201 relation: other_relation,
2202 name: other_name,
2203 ..
2204 }),
2205 ) => {
2206 self_name == other_name
2207 && self_relation == other_relation
2208 && self_expr.normalize_eq(other_expr)
2209 }
2210 (
2211 Expr::Like(Like {
2212 negated: self_negated,
2213 expr: self_expr,
2214 pattern: self_pattern,
2215 escape_char: self_escape_char,
2216 case_insensitive: self_case_insensitive,
2217 }),
2218 Expr::Like(Like {
2219 negated: other_negated,
2220 expr: other_expr,
2221 pattern: other_pattern,
2222 escape_char: other_escape_char,
2223 case_insensitive: other_case_insensitive,
2224 }),
2225 )
2226 | (
2227 Expr::SimilarTo(Like {
2228 negated: self_negated,
2229 expr: self_expr,
2230 pattern: self_pattern,
2231 escape_char: self_escape_char,
2232 case_insensitive: self_case_insensitive,
2233 }),
2234 Expr::SimilarTo(Like {
2235 negated: other_negated,
2236 expr: other_expr,
2237 pattern: other_pattern,
2238 escape_char: other_escape_char,
2239 case_insensitive: other_case_insensitive,
2240 }),
2241 ) => {
2242 self_negated == other_negated
2243 && self_escape_char == other_escape_char
2244 && self_case_insensitive == other_case_insensitive
2245 && self_expr.normalize_eq(other_expr)
2246 && self_pattern.normalize_eq(other_pattern)
2247 }
2248 (Expr::Not(self_expr), Expr::Not(other_expr))
2249 | (Expr::IsNull(self_expr), Expr::IsNull(other_expr))
2250 | (Expr::IsTrue(self_expr), Expr::IsTrue(other_expr))
2251 | (Expr::IsFalse(self_expr), Expr::IsFalse(other_expr))
2252 | (Expr::IsUnknown(self_expr), Expr::IsUnknown(other_expr))
2253 | (Expr::IsNotNull(self_expr), Expr::IsNotNull(other_expr))
2254 | (Expr::IsNotTrue(self_expr), Expr::IsNotTrue(other_expr))
2255 | (Expr::IsNotFalse(self_expr), Expr::IsNotFalse(other_expr))
2256 | (Expr::IsNotUnknown(self_expr), Expr::IsNotUnknown(other_expr))
2257 | (Expr::Negative(self_expr), Expr::Negative(other_expr))
2258 | (
2259 Expr::Unnest(Unnest { expr: self_expr }),
2260 Expr::Unnest(Unnest { expr: other_expr }),
2261 ) => self_expr.normalize_eq(other_expr),
2262 (
2263 Expr::Between(Between {
2264 expr: self_expr,
2265 negated: self_negated,
2266 low: self_low,
2267 high: self_high,
2268 }),
2269 Expr::Between(Between {
2270 expr: other_expr,
2271 negated: other_negated,
2272 low: other_low,
2273 high: other_high,
2274 }),
2275 ) => {
2276 self_negated == other_negated
2277 && self_expr.normalize_eq(other_expr)
2278 && self_low.normalize_eq(other_low)
2279 && self_high.normalize_eq(other_high)
2280 }
2281 (
2282 Expr::Cast(Cast {
2283 expr: self_expr,
2284 data_type: self_data_type,
2285 }),
2286 Expr::Cast(Cast {
2287 expr: other_expr,
2288 data_type: other_data_type,
2289 }),
2290 )
2291 | (
2292 Expr::TryCast(TryCast {
2293 expr: self_expr,
2294 data_type: self_data_type,
2295 }),
2296 Expr::TryCast(TryCast {
2297 expr: other_expr,
2298 data_type: other_data_type,
2299 }),
2300 ) => self_data_type == other_data_type && self_expr.normalize_eq(other_expr),
2301 (
2302 Expr::ScalarFunction(ScalarFunction {
2303 func: self_func,
2304 args: self_args,
2305 }),
2306 Expr::ScalarFunction(ScalarFunction {
2307 func: other_func,
2308 args: other_args,
2309 }),
2310 ) => {
2311 self_func.name() == other_func.name()
2312 && self_args.len() == other_args.len()
2313 && self_args
2314 .iter()
2315 .zip(other_args.iter())
2316 .all(|(a, b)| a.normalize_eq(b))
2317 }
2318 (
2319 Expr::AggregateFunction(AggregateFunction {
2320 func: self_func,
2321 params:
2322 AggregateFunctionParams {
2323 args: self_args,
2324 distinct: self_distinct,
2325 filter: self_filter,
2326 order_by: self_order_by,
2327 null_treatment: self_null_treatment,
2328 },
2329 }),
2330 Expr::AggregateFunction(AggregateFunction {
2331 func: other_func,
2332 params:
2333 AggregateFunctionParams {
2334 args: other_args,
2335 distinct: other_distinct,
2336 filter: other_filter,
2337 order_by: other_order_by,
2338 null_treatment: other_null_treatment,
2339 },
2340 }),
2341 ) => {
2342 self_func.name() == other_func.name()
2343 && self_distinct == other_distinct
2344 && self_null_treatment == other_null_treatment
2345 && self_args.len() == other_args.len()
2346 && self_args
2347 .iter()
2348 .zip(other_args.iter())
2349 .all(|(a, b)| a.normalize_eq(b))
2350 && match (self_filter, other_filter) {
2351 (Some(self_filter), Some(other_filter)) => {
2352 self_filter.normalize_eq(other_filter)
2353 }
2354 (None, None) => true,
2355 _ => false,
2356 }
2357 && self_order_by
2358 .iter()
2359 .zip(other_order_by.iter())
2360 .all(|(a, b)| {
2361 a.asc == b.asc
2362 && a.nulls_first == b.nulls_first
2363 && a.expr.normalize_eq(&b.expr)
2364 })
2365 && self_order_by.len() == other_order_by.len()
2366 }
2367 (Expr::WindowFunction(left), Expr::WindowFunction(other)) => {
2368 let WindowFunction {
2369 fun: self_fun,
2370 params:
2371 WindowFunctionParams {
2372 args: self_args,
2373 window_frame: self_window_frame,
2374 partition_by: self_partition_by,
2375 order_by: self_order_by,
2376 filter: self_filter,
2377 null_treatment: self_null_treatment,
2378 distinct: self_distinct,
2379 },
2380 } = left.as_ref();
2381 let WindowFunction {
2382 fun: other_fun,
2383 params:
2384 WindowFunctionParams {
2385 args: other_args,
2386 window_frame: other_window_frame,
2387 partition_by: other_partition_by,
2388 order_by: other_order_by,
2389 filter: other_filter,
2390 null_treatment: other_null_treatment,
2391 distinct: other_distinct,
2392 },
2393 } = other.as_ref();
2394
2395 self_fun.name() == other_fun.name()
2396 && self_window_frame == other_window_frame
2397 && match (self_filter, other_filter) {
2398 (Some(a), Some(b)) => a.normalize_eq(b),
2399 (None, None) => true,
2400 _ => false,
2401 }
2402 && self_null_treatment == other_null_treatment
2403 && self_args.len() == other_args.len()
2404 && self_args
2405 .iter()
2406 .zip(other_args.iter())
2407 .all(|(a, b)| a.normalize_eq(b))
2408 && self_partition_by
2409 .iter()
2410 .zip(other_partition_by.iter())
2411 .all(|(a, b)| a.normalize_eq(b))
2412 && self_order_by
2413 .iter()
2414 .zip(other_order_by.iter())
2415 .all(|(a, b)| {
2416 a.asc == b.asc
2417 && a.nulls_first == b.nulls_first
2418 && a.expr.normalize_eq(&b.expr)
2419 })
2420 && self_distinct == other_distinct
2421 }
2422 (
2423 Expr::Exists(Exists {
2424 subquery: self_subquery,
2425 negated: self_negated,
2426 }),
2427 Expr::Exists(Exists {
2428 subquery: other_subquery,
2429 negated: other_negated,
2430 }),
2431 ) => {
2432 self_negated == other_negated
2433 && self_subquery.normalize_eq(other_subquery)
2434 }
2435 (
2436 Expr::InSubquery(InSubquery {
2437 expr: self_expr,
2438 subquery: self_subquery,
2439 negated: self_negated,
2440 }),
2441 Expr::InSubquery(InSubquery {
2442 expr: other_expr,
2443 subquery: other_subquery,
2444 negated: other_negated,
2445 }),
2446 ) => {
2447 self_negated == other_negated
2448 && self_expr.normalize_eq(other_expr)
2449 && self_subquery.normalize_eq(other_subquery)
2450 }
2451 (
2452 Expr::ScalarSubquery(self_subquery),
2453 Expr::ScalarSubquery(other_subquery),
2454 ) => self_subquery.normalize_eq(other_subquery),
2455 (
2456 Expr::GroupingSet(GroupingSet::Rollup(self_exprs)),
2457 Expr::GroupingSet(GroupingSet::Rollup(other_exprs)),
2458 )
2459 | (
2460 Expr::GroupingSet(GroupingSet::Cube(self_exprs)),
2461 Expr::GroupingSet(GroupingSet::Cube(other_exprs)),
2462 ) => {
2463 self_exprs.len() == other_exprs.len()
2464 && self_exprs
2465 .iter()
2466 .zip(other_exprs.iter())
2467 .all(|(a, b)| a.normalize_eq(b))
2468 }
2469 (
2470 Expr::GroupingSet(GroupingSet::GroupingSets(self_exprs)),
2471 Expr::GroupingSet(GroupingSet::GroupingSets(other_exprs)),
2472 ) => {
2473 self_exprs.len() == other_exprs.len()
2474 && self_exprs.iter().zip(other_exprs.iter()).all(|(a, b)| {
2475 a.len() == b.len()
2476 && a.iter().zip(b.iter()).all(|(x, y)| x.normalize_eq(y))
2477 })
2478 }
2479 (
2480 Expr::InList(InList {
2481 expr: self_expr,
2482 list: self_list,
2483 negated: self_negated,
2484 }),
2485 Expr::InList(InList {
2486 expr: other_expr,
2487 list: other_list,
2488 negated: other_negated,
2489 }),
2490 ) => {
2491 self_negated == other_negated
2493 && self_expr.normalize_eq(other_expr)
2494 && self_list.len() == other_list.len()
2495 && self_list
2496 .iter()
2497 .zip(other_list.iter())
2498 .all(|(a, b)| a.normalize_eq(b))
2499 }
2500 (
2501 Expr::Case(Case {
2502 expr: self_expr,
2503 when_then_expr: self_when_then_expr,
2504 else_expr: self_else_expr,
2505 }),
2506 Expr::Case(Case {
2507 expr: other_expr,
2508 when_then_expr: other_when_then_expr,
2509 else_expr: other_else_expr,
2510 }),
2511 ) => {
2512 self_when_then_expr.len() == other_when_then_expr.len()
2515 && self_when_then_expr
2516 .iter()
2517 .zip(other_when_then_expr.iter())
2518 .all(|((self_when, self_then), (other_when, other_then))| {
2519 self_when.normalize_eq(other_when)
2520 && self_then.normalize_eq(other_then)
2521 })
2522 && match (self_expr, other_expr) {
2523 (Some(self_expr), Some(other_expr)) => {
2524 self_expr.normalize_eq(other_expr)
2525 }
2526 (None, None) => true,
2527 (_, _) => false,
2528 }
2529 && match (self_else_expr, other_else_expr) {
2530 (Some(self_else_expr), Some(other_else_expr)) => {
2531 self_else_expr.normalize_eq(other_else_expr)
2532 }
2533 (None, None) => true,
2534 (_, _) => false,
2535 }
2536 }
2537 (_, _) => self == other,
2538 }
2539 }
2540}
2541
2542impl HashNode for Expr {
2543 fn hash_node<H: Hasher>(&self, state: &mut H) {
2547 mem::discriminant(self).hash(state);
2548 match self {
2549 Expr::Alias(Alias {
2550 expr: _expr,
2551 relation,
2552 name,
2553 ..
2554 }) => {
2555 relation.hash(state);
2556 name.hash(state);
2557 }
2558 Expr::Column(column) => {
2559 column.hash(state);
2560 }
2561 Expr::ScalarVariable(data_type, name) => {
2562 data_type.hash(state);
2563 name.hash(state);
2564 }
2565 Expr::Literal(scalar_value, _) => {
2566 scalar_value.hash(state);
2567 }
2568 Expr::BinaryExpr(BinaryExpr {
2569 left: _left,
2570 op,
2571 right: _right,
2572 }) => {
2573 op.hash(state);
2574 }
2575 Expr::Like(Like {
2576 negated,
2577 expr: _expr,
2578 pattern: _pattern,
2579 escape_char,
2580 case_insensitive,
2581 })
2582 | Expr::SimilarTo(Like {
2583 negated,
2584 expr: _expr,
2585 pattern: _pattern,
2586 escape_char,
2587 case_insensitive,
2588 }) => {
2589 negated.hash(state);
2590 escape_char.hash(state);
2591 case_insensitive.hash(state);
2592 }
2593 Expr::Not(_expr)
2594 | Expr::IsNotNull(_expr)
2595 | Expr::IsNull(_expr)
2596 | Expr::IsTrue(_expr)
2597 | Expr::IsFalse(_expr)
2598 | Expr::IsUnknown(_expr)
2599 | Expr::IsNotTrue(_expr)
2600 | Expr::IsNotFalse(_expr)
2601 | Expr::IsNotUnknown(_expr)
2602 | Expr::Negative(_expr) => {}
2603 Expr::Between(Between {
2604 expr: _expr,
2605 negated,
2606 low: _low,
2607 high: _high,
2608 }) => {
2609 negated.hash(state);
2610 }
2611 Expr::Case(Case {
2612 expr: _expr,
2613 when_then_expr: _when_then_expr,
2614 else_expr: _else_expr,
2615 }) => {}
2616 Expr::Cast(Cast {
2617 expr: _expr,
2618 data_type,
2619 })
2620 | Expr::TryCast(TryCast {
2621 expr: _expr,
2622 data_type,
2623 }) => {
2624 data_type.hash(state);
2625 }
2626 Expr::ScalarFunction(ScalarFunction { func, args: _args }) => {
2627 func.hash(state);
2628 }
2629 Expr::AggregateFunction(AggregateFunction {
2630 func,
2631 params:
2632 AggregateFunctionParams {
2633 args: _args,
2634 distinct,
2635 filter: _,
2636 order_by: _,
2637 null_treatment,
2638 },
2639 }) => {
2640 func.hash(state);
2641 distinct.hash(state);
2642 null_treatment.hash(state);
2643 }
2644 Expr::WindowFunction(window_fun) => {
2645 let WindowFunction {
2646 fun,
2647 params:
2648 WindowFunctionParams {
2649 args: _args,
2650 partition_by: _,
2651 order_by: _,
2652 window_frame,
2653 filter,
2654 null_treatment,
2655 distinct,
2656 },
2657 } = window_fun.as_ref();
2658 fun.hash(state);
2659 window_frame.hash(state);
2660 filter.hash(state);
2661 null_treatment.hash(state);
2662 distinct.hash(state);
2663 }
2664 Expr::InList(InList {
2665 expr: _expr,
2666 list: _list,
2667 negated,
2668 }) => {
2669 negated.hash(state);
2670 }
2671 Expr::Exists(Exists { subquery, negated }) => {
2672 subquery.hash(state);
2673 negated.hash(state);
2674 }
2675 Expr::InSubquery(InSubquery {
2676 expr: _expr,
2677 subquery,
2678 negated,
2679 }) => {
2680 subquery.hash(state);
2681 negated.hash(state);
2682 }
2683 Expr::ScalarSubquery(subquery) => {
2684 subquery.hash(state);
2685 }
2686 #[expect(deprecated)]
2687 Expr::Wildcard { qualifier, options } => {
2688 qualifier.hash(state);
2689 options.hash(state);
2690 }
2691 Expr::GroupingSet(grouping_set) => {
2692 mem::discriminant(grouping_set).hash(state);
2693 match grouping_set {
2694 GroupingSet::Rollup(_exprs) | GroupingSet::Cube(_exprs) => {}
2695 GroupingSet::GroupingSets(_exprs) => {}
2696 }
2697 }
2698 Expr::Placeholder(place_holder) => {
2699 place_holder.hash(state);
2700 }
2701 Expr::OuterReferenceColumn(field, column) => {
2702 field.hash(state);
2703 column.hash(state);
2704 }
2705 Expr::Unnest(Unnest { expr: _expr }) => {}
2706 Expr::Lambda(Lambda {
2707 params,
2708 body: _,
2709 }) => {
2710 params.hash(state);
2711 }
2712 };
2713 }
2714}
2715
2716fn rewrite_placeholder(expr: &mut Expr, other: &Expr, schema: &DFSchema) -> Result<()> {
2719 if let Expr::Placeholder(Placeholder { id: _, field }) = expr {
2720 if field.is_none() {
2721 let other_field = other.to_field(schema);
2722 match other_field {
2723 Err(e) => {
2724 Err(e.context(format!(
2725 "Can not find type of {other} needed to infer type of {expr}"
2726 )))?;
2727 }
2728 Ok((_, other_field)) => {
2729 *field =
2732 Some(other_field.as_ref().clone().with_nullable(true).into());
2733 }
2734 }
2735 };
2736 }
2737 Ok(())
2738}
2739
2740#[macro_export]
2741macro_rules! expr_vec_fmt {
2742 ( $ARRAY:expr ) => {{
2743 $ARRAY
2744 .iter()
2745 .map(|e| format!("{e}"))
2746 .collect::<Vec<String>>()
2747 .join(", ")
2748 }};
2749}
2750
2751struct SchemaDisplay<'a>(&'a Expr);
2752impl Display for SchemaDisplay<'_> {
2753 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2754 match self.0 {
2755 #[expect(deprecated)]
2758 Expr::Column(_)
2759 | Expr::Literal(_, _)
2760 | Expr::ScalarVariable(..)
2761 | Expr::OuterReferenceColumn(..)
2762 | Expr::Placeholder(_)
2763 | Expr::Wildcard { .. } => write!(f, "{}", self.0),
2764 Expr::AggregateFunction(AggregateFunction { func, params }) => {
2765 match func.schema_name(params) {
2766 Ok(name) => {
2767 write!(f, "{name}")
2768 }
2769 Err(e) => {
2770 write!(f, "got error from schema_name {e}")
2771 }
2772 }
2773 }
2774 Expr::Alias(Alias {
2776 name,
2777 relation: Some(relation),
2778 ..
2779 }) => write!(f, "{relation}.{name}"),
2780 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
2781 Expr::Between(Between {
2782 expr,
2783 negated,
2784 low,
2785 high,
2786 }) => {
2787 if *negated {
2788 write!(
2789 f,
2790 "{} NOT BETWEEN {} AND {}",
2791 SchemaDisplay(expr),
2792 SchemaDisplay(low),
2793 SchemaDisplay(high),
2794 )
2795 } else {
2796 write!(
2797 f,
2798 "{} BETWEEN {} AND {}",
2799 SchemaDisplay(expr),
2800 SchemaDisplay(low),
2801 SchemaDisplay(high),
2802 )
2803 }
2804 }
2805 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2806 write!(f, "{} {op} {}", SchemaDisplay(left), SchemaDisplay(right),)
2807 }
2808 Expr::Case(Case {
2809 expr,
2810 when_then_expr,
2811 else_expr,
2812 }) => {
2813 write!(f, "CASE ")?;
2814
2815 if let Some(e) = expr {
2816 write!(f, "{} ", SchemaDisplay(e))?;
2817 }
2818
2819 for (when, then) in when_then_expr {
2820 write!(
2821 f,
2822 "WHEN {} THEN {} ",
2823 SchemaDisplay(when),
2824 SchemaDisplay(then),
2825 )?;
2826 }
2827
2828 if let Some(e) = else_expr {
2829 write!(f, "ELSE {} ", SchemaDisplay(e))?;
2830 }
2831
2832 write!(f, "END")
2833 }
2834 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
2836 write!(f, "{}", SchemaDisplay(expr))
2837 }
2838 Expr::InList(InList {
2839 expr,
2840 list,
2841 negated,
2842 }) => {
2843 let inlist_name = schema_name_from_exprs(list)?;
2844
2845 if *negated {
2846 write!(f, "{} NOT IN {}", SchemaDisplay(expr), inlist_name)
2847 } else {
2848 write!(f, "{} IN {}", SchemaDisplay(expr), inlist_name)
2849 }
2850 }
2851 Expr::Exists(Exists { negated: true, .. }) => write!(f, "NOT EXISTS"),
2852 Expr::Exists(Exists { negated: false, .. }) => write!(f, "EXISTS"),
2853 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
2854 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2855 }
2856 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
2857 write!(f, "GROUPING SETS (")?;
2858 for exprs in lists_of_exprs.iter() {
2859 write!(f, "({})", schema_name_from_exprs(exprs)?)?;
2860 }
2861 write!(f, ")")
2862 }
2863 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
2864 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2865 }
2866 Expr::IsNull(expr) => write!(f, "{} IS NULL", SchemaDisplay(expr)),
2867 Expr::IsNotNull(expr) => {
2868 write!(f, "{} IS NOT NULL", SchemaDisplay(expr))
2869 }
2870 Expr::IsUnknown(expr) => {
2871 write!(f, "{} IS UNKNOWN", SchemaDisplay(expr))
2872 }
2873 Expr::IsNotUnknown(expr) => {
2874 write!(f, "{} IS NOT UNKNOWN", SchemaDisplay(expr))
2875 }
2876 Expr::InSubquery(InSubquery { negated: true, .. }) => {
2877 write!(f, "NOT IN")
2878 }
2879 Expr::InSubquery(InSubquery { negated: false, .. }) => write!(f, "IN"),
2880 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SchemaDisplay(expr)),
2881 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SchemaDisplay(expr)),
2882 Expr::IsNotTrue(expr) => {
2883 write!(f, "{} IS NOT TRUE", SchemaDisplay(expr))
2884 }
2885 Expr::IsNotFalse(expr) => {
2886 write!(f, "{} IS NOT FALSE", SchemaDisplay(expr))
2887 }
2888 Expr::Like(Like {
2889 negated,
2890 expr,
2891 pattern,
2892 escape_char,
2893 case_insensitive,
2894 }) => {
2895 write!(
2896 f,
2897 "{} {}{} {}",
2898 SchemaDisplay(expr),
2899 if *negated { "NOT " } else { "" },
2900 if *case_insensitive { "ILIKE" } else { "LIKE" },
2901 SchemaDisplay(pattern),
2902 )?;
2903
2904 if let Some(char) = escape_char {
2905 write!(f, " CHAR '{char}'")?;
2906 }
2907
2908 Ok(())
2909 }
2910 Expr::Negative(expr) => write!(f, "(- {})", SchemaDisplay(expr)),
2911 Expr::Not(expr) => write!(f, "NOT {}", SchemaDisplay(expr)),
2912 Expr::Unnest(Unnest { expr }) => {
2913 write!(f, "UNNEST({})", SchemaDisplay(expr))
2914 }
2915 Expr::ScalarFunction(ScalarFunction { func, args }) => {
2916 match func.schema_name(args) {
2917 Ok(name) => {
2918 write!(f, "{name}")
2919 }
2920 Err(e) => {
2921 write!(f, "got error from schema_name {e}")
2922 }
2923 }
2924 }
2925 Expr::ScalarSubquery(Subquery { subquery, .. }) => {
2926 write!(f, "{}", subquery.schema().field(0).name())
2927 }
2928 Expr::SimilarTo(Like {
2929 negated,
2930 expr,
2931 pattern,
2932 escape_char,
2933 ..
2934 }) => {
2935 write!(
2936 f,
2937 "{} {} {}",
2938 SchemaDisplay(expr),
2939 if *negated {
2940 "NOT SIMILAR TO"
2941 } else {
2942 "SIMILAR TO"
2943 },
2944 SchemaDisplay(pattern),
2945 )?;
2946 if let Some(char) = escape_char {
2947 write!(f, " CHAR '{char}'")?;
2948 }
2949
2950 Ok(())
2951 }
2952 Expr::WindowFunction(window_fun) => {
2953 let WindowFunction { fun, params } = window_fun.as_ref();
2954 match fun {
2955 WindowFunctionDefinition::AggregateUDF(fun) => {
2956 match fun.window_function_schema_name(params) {
2957 Ok(name) => {
2958 write!(f, "{name}")
2959 }
2960 Err(e) => {
2961 write!(
2962 f,
2963 "got error from window_function_schema_name {e}"
2964 )
2965 }
2966 }
2967 }
2968 _ => {
2969 let WindowFunctionParams {
2970 args,
2971 partition_by,
2972 order_by,
2973 window_frame,
2974 filter,
2975 null_treatment,
2976 distinct,
2977 } = params;
2978
2979 write!(f, "{fun}(")?;
2981
2982 if *distinct {
2984 write!(f, "DISTINCT ")?;
2985 }
2986
2987 write!(
2989 f,
2990 "{}",
2991 schema_name_from_exprs_comma_separated_without_space(args)?
2992 )?;
2993
2994 write!(f, ")")?;
2996
2997 if let Some(null_treatment) = null_treatment {
2998 write!(f, " {null_treatment}")?;
2999 }
3000
3001 if let Some(filter) = filter {
3002 write!(f, " FILTER (WHERE {filter})")?;
3003 }
3004
3005 if !partition_by.is_empty() {
3006 write!(
3007 f,
3008 " PARTITION BY [{}]",
3009 schema_name_from_exprs(partition_by)?
3010 )?;
3011 }
3012
3013 if !order_by.is_empty() {
3014 write!(
3015 f,
3016 " ORDER BY [{}]",
3017 schema_name_from_sorts(order_by)?
3018 )?;
3019 };
3020
3021 write!(f, " {window_frame}")
3022 }
3023 }
3024 }
3025 Expr::Lambda(Lambda {
3026 params,
3027 body,
3028 }) => {
3029 write!(f, "({}) -> {body}", display_comma_separated(params))
3030 }
3031 }
3032 }
3033}
3034
3035struct SqlDisplay<'a>(&'a Expr);
3037
3038impl Display for SqlDisplay<'_> {
3039 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3040 match self.0 {
3041 Expr::Literal(scalar, _) => scalar.fmt(f),
3042 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
3043 Expr::Between(Between {
3044 expr,
3045 negated,
3046 low,
3047 high,
3048 }) => {
3049 if *negated {
3050 write!(
3051 f,
3052 "{} NOT BETWEEN {} AND {}",
3053 SqlDisplay(expr),
3054 SqlDisplay(low),
3055 SqlDisplay(high),
3056 )
3057 } else {
3058 write!(
3059 f,
3060 "{} BETWEEN {} AND {}",
3061 SqlDisplay(expr),
3062 SqlDisplay(low),
3063 SqlDisplay(high),
3064 )
3065 }
3066 }
3067 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
3068 write!(f, "{} {op} {}", SqlDisplay(left), SqlDisplay(right),)
3069 }
3070 Expr::Case(Case {
3071 expr,
3072 when_then_expr,
3073 else_expr,
3074 }) => {
3075 write!(f, "CASE ")?;
3076
3077 if let Some(e) = expr {
3078 write!(f, "{} ", SqlDisplay(e))?;
3079 }
3080
3081 for (when, then) in when_then_expr {
3082 write!(f, "WHEN {} THEN {} ", SqlDisplay(when), SqlDisplay(then),)?;
3083 }
3084
3085 if let Some(e) = else_expr {
3086 write!(f, "ELSE {} ", SqlDisplay(e))?;
3087 }
3088
3089 write!(f, "END")
3090 }
3091 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
3092 write!(f, "{}", SqlDisplay(expr))
3093 }
3094 Expr::InList(InList {
3095 expr,
3096 list,
3097 negated,
3098 }) => {
3099 write!(
3100 f,
3101 "{}{} IN {}",
3102 SqlDisplay(expr),
3103 if *negated { " NOT" } else { "" },
3104 ExprListDisplay::comma_separated(list.as_slice())
3105 )
3106 }
3107 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
3108 write!(
3109 f,
3110 "ROLLUP ({})",
3111 ExprListDisplay::comma_separated(exprs.as_slice())
3112 )
3113 }
3114 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
3115 write!(f, "GROUPING SETS (")?;
3116 for exprs in lists_of_exprs.iter() {
3117 write!(
3118 f,
3119 "({})",
3120 ExprListDisplay::comma_separated(exprs.as_slice())
3121 )?;
3122 }
3123 write!(f, ")")
3124 }
3125 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
3126 write!(
3127 f,
3128 "ROLLUP ({})",
3129 ExprListDisplay::comma_separated(exprs.as_slice())
3130 )
3131 }
3132 Expr::IsNull(expr) => write!(f, "{} IS NULL", SqlDisplay(expr)),
3133 Expr::IsNotNull(expr) => {
3134 write!(f, "{} IS NOT NULL", SqlDisplay(expr))
3135 }
3136 Expr::IsUnknown(expr) => {
3137 write!(f, "{} IS UNKNOWN", SqlDisplay(expr))
3138 }
3139 Expr::IsNotUnknown(expr) => {
3140 write!(f, "{} IS NOT UNKNOWN", SqlDisplay(expr))
3141 }
3142 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SqlDisplay(expr)),
3143 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SqlDisplay(expr)),
3144 Expr::IsNotTrue(expr) => {
3145 write!(f, "{} IS NOT TRUE", SqlDisplay(expr))
3146 }
3147 Expr::IsNotFalse(expr) => {
3148 write!(f, "{} IS NOT FALSE", SqlDisplay(expr))
3149 }
3150 Expr::Like(Like {
3151 negated,
3152 expr,
3153 pattern,
3154 escape_char,
3155 case_insensitive,
3156 }) => {
3157 write!(
3158 f,
3159 "{} {}{} {}",
3160 SqlDisplay(expr),
3161 if *negated { "NOT " } else { "" },
3162 if *case_insensitive { "ILIKE" } else { "LIKE" },
3163 SqlDisplay(pattern),
3164 )?;
3165
3166 if let Some(char) = escape_char {
3167 write!(f, " CHAR '{char}'")?;
3168 }
3169
3170 Ok(())
3171 }
3172 Expr::Negative(expr) => write!(f, "(- {})", SqlDisplay(expr)),
3173 Expr::Not(expr) => write!(f, "NOT {}", SqlDisplay(expr)),
3174 Expr::Unnest(Unnest { expr }) => {
3175 write!(f, "UNNEST({})", SqlDisplay(expr))
3176 }
3177 Expr::SimilarTo(Like {
3178 negated,
3179 expr,
3180 pattern,
3181 escape_char,
3182 ..
3183 }) => {
3184 write!(
3185 f,
3186 "{} {} {}",
3187 SqlDisplay(expr),
3188 if *negated {
3189 "NOT SIMILAR TO"
3190 } else {
3191 "SIMILAR TO"
3192 },
3193 SqlDisplay(pattern),
3194 )?;
3195 if let Some(char) = escape_char {
3196 write!(f, " CHAR '{char}'")?;
3197 }
3198
3199 Ok(())
3200 }
3201 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3202 match func.human_display(params) {
3203 Ok(name) => {
3204 write!(f, "{name}")
3205 }
3206 Err(e) => {
3207 write!(f, "got error from schema_name {e}")
3208 }
3209 }
3210 }
3211 Expr::Lambda(Lambda {
3212 params,
3213 body,
3214 }) => {
3215 write!(f, "({}) -> {}", params.join(", "), SchemaDisplay(body))
3216 }
3217 _ => write!(f, "{}", self.0),
3218 }
3219 }
3220}
3221
3222pub(crate) fn schema_name_from_exprs_comma_separated_without_space(
3228 exprs: &[Expr],
3229) -> Result<String, fmt::Error> {
3230 schema_name_from_exprs_inner(exprs, ",")
3231}
3232
3233pub struct ExprListDisplay<'a> {
3235 exprs: &'a [Expr],
3236 sep: &'a str,
3237}
3238
3239impl<'a> ExprListDisplay<'a> {
3240 pub fn new(exprs: &'a [Expr], sep: &'a str) -> Self {
3242 Self { exprs, sep }
3243 }
3244
3245 pub fn comma_separated(exprs: &'a [Expr]) -> Self {
3247 Self::new(exprs, ", ")
3248 }
3249}
3250
3251impl Display for ExprListDisplay<'_> {
3252 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3253 let mut first = true;
3254 for expr in self.exprs {
3255 if !first {
3256 write!(f, "{}", self.sep)?;
3257 }
3258 write!(f, "{}", SqlDisplay(expr))?;
3259 first = false;
3260 }
3261 Ok(())
3262 }
3263}
3264
3265pub fn schema_name_from_exprs(exprs: &[Expr]) -> Result<String, fmt::Error> {
3267 schema_name_from_exprs_inner(exprs, ", ")
3268}
3269
3270fn schema_name_from_exprs_inner(exprs: &[Expr], sep: &str) -> Result<String, fmt::Error> {
3271 let mut s = String::new();
3272 for (i, e) in exprs.iter().enumerate() {
3273 if i > 0 {
3274 write!(&mut s, "{sep}")?;
3275 }
3276 write!(&mut s, "{}", SchemaDisplay(e))?;
3277 }
3278
3279 Ok(s)
3280}
3281
3282pub fn schema_name_from_sorts(sorts: &[Sort]) -> Result<String, fmt::Error> {
3283 let mut s = String::new();
3284 for (i, e) in sorts.iter().enumerate() {
3285 if i > 0 {
3286 write!(&mut s, ", ")?;
3287 }
3288 let ordering = if e.asc { "ASC" } else { "DESC" };
3289 let nulls_ordering = if e.nulls_first {
3290 "NULLS FIRST"
3291 } else {
3292 "NULLS LAST"
3293 };
3294 write!(&mut s, "{} {} {}", e.expr, ordering, nulls_ordering)?;
3295 }
3296
3297 Ok(s)
3298}
3299
3300pub const OUTER_REFERENCE_COLUMN_PREFIX: &str = "outer_ref";
3301pub const UNNEST_COLUMN_PREFIX: &str = "UNNEST";
3302
3303impl Display for Expr {
3306 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3307 match self {
3308 Expr::Alias(Alias { expr, name, .. }) => write!(f, "{expr} AS {name}"),
3309 Expr::Column(c) => write!(f, "{c}"),
3310 Expr::OuterReferenceColumn(_, c) => {
3311 write!(f, "{OUTER_REFERENCE_COLUMN_PREFIX}({c})")
3312 }
3313 Expr::ScalarVariable(_, var_names) => write!(f, "{}", var_names.join(".")),
3314 Expr::Literal(v, metadata) => {
3315 match metadata.as_ref().map(|m| m.is_empty()).unwrap_or(true) {
3316 false => write!(f, "{v:?} {:?}", metadata.as_ref().unwrap()),
3317 true => write!(f, "{v:?}"),
3318 }
3319 }
3320 Expr::Case(case) => {
3321 write!(f, "CASE ")?;
3322 if let Some(e) = &case.expr {
3323 write!(f, "{e} ")?;
3324 }
3325 for (w, t) in &case.when_then_expr {
3326 write!(f, "WHEN {w} THEN {t} ")?;
3327 }
3328 if let Some(e) = &case.else_expr {
3329 write!(f, "ELSE {e} ")?;
3330 }
3331 write!(f, "END")
3332 }
3333 Expr::Cast(Cast { expr, data_type }) => {
3334 write!(f, "CAST({expr} AS {data_type})")
3335 }
3336 Expr::TryCast(TryCast { expr, data_type }) => {
3337 write!(f, "TRY_CAST({expr} AS {data_type})")
3338 }
3339 Expr::Not(expr) => write!(f, "NOT {expr}"),
3340 Expr::Negative(expr) => write!(f, "(- {expr})"),
3341 Expr::IsNull(expr) => write!(f, "{expr} IS NULL"),
3342 Expr::IsNotNull(expr) => write!(f, "{expr} IS NOT NULL"),
3343 Expr::IsTrue(expr) => write!(f, "{expr} IS TRUE"),
3344 Expr::IsFalse(expr) => write!(f, "{expr} IS FALSE"),
3345 Expr::IsUnknown(expr) => write!(f, "{expr} IS UNKNOWN"),
3346 Expr::IsNotTrue(expr) => write!(f, "{expr} IS NOT TRUE"),
3347 Expr::IsNotFalse(expr) => write!(f, "{expr} IS NOT FALSE"),
3348 Expr::IsNotUnknown(expr) => write!(f, "{expr} IS NOT UNKNOWN"),
3349 Expr::Exists(Exists {
3350 subquery,
3351 negated: true,
3352 }) => write!(f, "NOT EXISTS ({subquery:?})"),
3353 Expr::Exists(Exists {
3354 subquery,
3355 negated: false,
3356 }) => write!(f, "EXISTS ({subquery:?})"),
3357 Expr::InSubquery(InSubquery {
3358 expr,
3359 subquery,
3360 negated: true,
3361 }) => write!(f, "{expr} NOT IN ({subquery:?})"),
3362 Expr::InSubquery(InSubquery {
3363 expr,
3364 subquery,
3365 negated: false,
3366 }) => write!(f, "{expr} IN ({subquery:?})"),
3367 Expr::ScalarSubquery(subquery) => write!(f, "({subquery:?})"),
3368 Expr::BinaryExpr(expr) => write!(f, "{expr}"),
3369 Expr::ScalarFunction(fun) => {
3370 fmt_function(f, fun.name(), false, &fun.args, true)
3371 }
3372 Expr::WindowFunction(window_fun) => {
3373 let WindowFunction { fun, params } = window_fun.as_ref();
3374 match fun {
3375 WindowFunctionDefinition::AggregateUDF(fun) => {
3376 match fun.window_function_display_name(params) {
3377 Ok(name) => {
3378 write!(f, "{name}")
3379 }
3380 Err(e) => {
3381 write!(
3382 f,
3383 "got error from window_function_display_name {e}"
3384 )
3385 }
3386 }
3387 }
3388 WindowFunctionDefinition::WindowUDF(fun) => {
3389 let WindowFunctionParams {
3390 args,
3391 partition_by,
3392 order_by,
3393 window_frame,
3394 filter,
3395 null_treatment,
3396 distinct,
3397 } = params;
3398
3399 fmt_function(f, &fun.to_string(), *distinct, args, true)?;
3400
3401 if let Some(nt) = null_treatment {
3402 write!(f, "{nt}")?;
3403 }
3404
3405 if let Some(fe) = filter {
3406 write!(f, " FILTER (WHERE {fe})")?;
3407 }
3408
3409 if !partition_by.is_empty() {
3410 write!(f, " PARTITION BY [{}]", expr_vec_fmt!(partition_by))?;
3411 }
3412 if !order_by.is_empty() {
3413 write!(f, " ORDER BY [{}]", expr_vec_fmt!(order_by))?;
3414 }
3415 write!(
3416 f,
3417 " {} BETWEEN {} AND {}",
3418 window_frame.units,
3419 window_frame.start_bound,
3420 window_frame.end_bound
3421 )
3422 }
3423 }
3424 }
3425 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3426 match func.display_name(params) {
3427 Ok(name) => {
3428 write!(f, "{name}")
3429 }
3430 Err(e) => {
3431 write!(f, "got error from display_name {e}")
3432 }
3433 }
3434 }
3435 Expr::Between(Between {
3436 expr,
3437 negated,
3438 low,
3439 high,
3440 }) => {
3441 if *negated {
3442 write!(f, "{expr} NOT BETWEEN {low} AND {high}")
3443 } else {
3444 write!(f, "{expr} BETWEEN {low} AND {high}")
3445 }
3446 }
3447 Expr::Like(Like {
3448 negated,
3449 expr,
3450 pattern,
3451 escape_char,
3452 case_insensitive,
3453 }) => {
3454 write!(f, "{expr}")?;
3455 let op_name = if *case_insensitive { "ILIKE" } else { "LIKE" };
3456 if *negated {
3457 write!(f, " NOT")?;
3458 }
3459 if let Some(char) = escape_char {
3460 write!(f, " {op_name} {pattern} ESCAPE '{char}'")
3461 } else {
3462 write!(f, " {op_name} {pattern}")
3463 }
3464 }
3465 Expr::SimilarTo(Like {
3466 negated,
3467 expr,
3468 pattern,
3469 escape_char,
3470 case_insensitive: _,
3471 }) => {
3472 write!(f, "{expr}")?;
3473 if *negated {
3474 write!(f, " NOT")?;
3475 }
3476 if let Some(char) = escape_char {
3477 write!(f, " SIMILAR TO {pattern} ESCAPE '{char}'")
3478 } else {
3479 write!(f, " SIMILAR TO {pattern}")
3480 }
3481 }
3482 Expr::InList(InList {
3483 expr,
3484 list,
3485 negated,
3486 }) => {
3487 if *negated {
3488 write!(f, "{expr} NOT IN ([{}])", expr_vec_fmt!(list))
3489 } else {
3490 write!(f, "{expr} IN ([{}])", expr_vec_fmt!(list))
3491 }
3492 }
3493 #[expect(deprecated)]
3494 Expr::Wildcard { qualifier, options } => match qualifier {
3495 Some(qualifier) => write!(f, "{qualifier}.*{options}"),
3496 None => write!(f, "*{options}"),
3497 },
3498 Expr::GroupingSet(grouping_sets) => match grouping_sets {
3499 GroupingSet::Rollup(exprs) => {
3500 write!(f, "ROLLUP ({})", expr_vec_fmt!(exprs))
3502 }
3503 GroupingSet::Cube(exprs) => {
3504 write!(f, "CUBE ({})", expr_vec_fmt!(exprs))
3506 }
3507 GroupingSet::GroupingSets(lists_of_exprs) => {
3508 write!(
3510 f,
3511 "GROUPING SETS ({})",
3512 lists_of_exprs
3513 .iter()
3514 .map(|exprs| format!("({})", expr_vec_fmt!(exprs)))
3515 .collect::<Vec<String>>()
3516 .join(", ")
3517 )
3518 }
3519 },
3520 Expr::Placeholder(Placeholder { id, .. }) => write!(f, "{id}"),
3521 Expr::Unnest(Unnest { expr }) => {
3522 write!(f, "{UNNEST_COLUMN_PREFIX}({expr})")
3523 }
3524 Expr::Lambda(Lambda {
3525 params,
3526 body,
3527 }) => {
3528 write!(f, "({}) -> {body}", params.join(", "))
3529 }
3530 }
3531 }
3532}
3533
3534fn fmt_function(
3535 f: &mut Formatter,
3536 fun: &str,
3537 distinct: bool,
3538 args: &[Expr],
3539 display: bool,
3540) -> fmt::Result {
3541 let args: Vec<String> = match display {
3542 true => args.iter().map(|arg| format!("{arg}")).collect(),
3543 false => args.iter().map(|arg| format!("{arg:?}")).collect(),
3544 };
3545
3546 let distinct_str = match distinct {
3547 true => "DISTINCT ",
3548 false => "",
3549 };
3550 write!(f, "{}({}{})", fun, distinct_str, args.join(", "))
3551}
3552
3553pub fn physical_name(expr: &Expr) -> Result<String> {
3556 match expr {
3557 Expr::Column(col) => Ok(col.name.clone()),
3558 Expr::Alias(alias) => Ok(alias.name.clone()),
3559 _ => Ok(expr.schema_name().to_string()),
3560 }
3561}
3562
3563#[cfg(test)]
3564mod test {
3565 use crate::expr_fn::col;
3566 use crate::{
3567 case, lit, placeholder, qualified_wildcard, wildcard, wildcard_with_options,
3568 ColumnarValue, ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl, Volatility,
3569 };
3570 use arrow::datatypes::{Field, Schema};
3571 use sqlparser::ast;
3572 use sqlparser::ast::{Ident, IdentWithAlias};
3573 use std::any::Any;
3574
3575 #[test]
3576 fn infer_placeholder_in_clause() {
3577 let column = col("department_id");
3579 let param_placeholders = vec![
3580 Expr::Placeholder(Placeholder {
3581 id: "$1".to_string(),
3582 field: None,
3583 }),
3584 Expr::Placeholder(Placeholder {
3585 id: "$2".to_string(),
3586 field: None,
3587 }),
3588 Expr::Placeholder(Placeholder {
3589 id: "$3".to_string(),
3590 field: None,
3591 }),
3592 ];
3593 let in_list = Expr::InList(InList {
3594 expr: Box::new(column),
3595 list: param_placeholders,
3596 negated: false,
3597 });
3598
3599 let schema = Arc::new(Schema::new(vec![
3600 Field::new("name", DataType::Utf8, true),
3601 Field::new("department_id", DataType::Int32, true),
3602 ]));
3603 let df_schema = DFSchema::try_from(schema).unwrap();
3604
3605 let (inferred_expr, contains_placeholder) =
3606 in_list.infer_placeholder_types(&df_schema).unwrap();
3607
3608 assert!(contains_placeholder);
3609
3610 match inferred_expr {
3611 Expr::InList(in_list) => {
3612 for expr in in_list.list {
3613 match expr {
3614 Expr::Placeholder(placeholder) => {
3615 assert_eq!(
3616 placeholder.field.unwrap().data_type(),
3617 &DataType::Int32,
3618 "Placeholder {} should infer Int32",
3619 placeholder.id
3620 );
3621 }
3622 _ => panic!("Expected Placeholder expression"),
3623 }
3624 }
3625 }
3626 _ => panic!("Expected InList expression"),
3627 }
3628 }
3629
3630 #[test]
3631 fn infer_placeholder_like_and_similar_to() {
3632 let schema =
3634 Arc::new(Schema::new(vec![Field::new("name", DataType::Utf8, true)]));
3635 let df_schema = DFSchema::try_from(schema).unwrap();
3636
3637 let like = Like {
3638 expr: Box::new(col("name")),
3639 pattern: Box::new(Expr::Placeholder(Placeholder {
3640 id: "$1".to_string(),
3641 field: None,
3642 })),
3643 negated: false,
3644 case_insensitive: false,
3645 escape_char: None,
3646 };
3647
3648 let expr = Expr::Like(like.clone());
3649
3650 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3651 match inferred_expr {
3652 Expr::Like(like) => match *like.pattern {
3653 Expr::Placeholder(placeholder) => {
3654 assert_eq!(placeholder.field.unwrap().data_type(), &DataType::Utf8);
3655 }
3656 _ => panic!("Expected Placeholder"),
3657 },
3658 _ => panic!("Expected Like"),
3659 }
3660
3661 let expr = Expr::SimilarTo(like);
3663
3664 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3665 match inferred_expr {
3666 Expr::SimilarTo(like) => match *like.pattern {
3667 Expr::Placeholder(placeholder) => {
3668 assert_eq!(
3669 placeholder.field.unwrap().data_type(),
3670 &DataType::Utf8,
3671 "Placeholder {} should infer Utf8",
3672 placeholder.id
3673 );
3674 }
3675 _ => panic!("Expected Placeholder expression"),
3676 },
3677 _ => panic!("Expected SimilarTo expression"),
3678 }
3679 }
3680
3681 #[test]
3682 fn infer_placeholder_with_metadata() {
3683 let schema =
3685 Arc::new(Schema::new(vec![Field::new("name", DataType::Utf8, false)
3686 .with_metadata(
3687 [("some_key".to_string(), "some_value".to_string())].into(),
3688 )]));
3689 let df_schema = DFSchema::try_from(schema).unwrap();
3690
3691 let expr = binary_expr(col("name"), Operator::Eq, placeholder("$1"));
3692
3693 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3694 match inferred_expr {
3695 Expr::BinaryExpr(BinaryExpr { right, .. }) => match *right {
3696 Expr::Placeholder(placeholder) => {
3697 assert_eq!(
3698 placeholder.field.as_ref().unwrap().data_type(),
3699 &DataType::Utf8
3700 );
3701 assert_eq!(
3702 placeholder.field.as_ref().unwrap().metadata(),
3703 df_schema.field(0).metadata()
3704 );
3705 assert!(placeholder.field.as_ref().unwrap().is_nullable());
3707 }
3708 _ => panic!("Expected Placeholder"),
3709 },
3710 _ => panic!("Expected BinaryExpr"),
3711 }
3712 }
3713
3714 #[test]
3715 fn format_case_when() -> Result<()> {
3716 let expr = case(col("a"))
3717 .when(lit(1), lit(true))
3718 .when(lit(0), lit(false))
3719 .otherwise(lit(ScalarValue::Null))?;
3720 let expected = "CASE a WHEN Int32(1) THEN Boolean(true) WHEN Int32(0) THEN Boolean(false) ELSE NULL END";
3721 assert_eq!(expected, format!("{expr}"));
3722 Ok(())
3723 }
3724
3725 #[test]
3726 fn format_cast() -> Result<()> {
3727 let expr = Expr::Cast(Cast {
3728 expr: Box::new(Expr::Literal(ScalarValue::Float32(Some(1.23)), None)),
3729 data_type: DataType::Utf8,
3730 });
3731 let expected_canonical = "CAST(Float32(1.23) AS Utf8)";
3732 assert_eq!(expected_canonical, format!("{expr}"));
3733 assert_eq!("Float32(1.23)", expr.schema_name().to_string());
3736 Ok(())
3737 }
3738
3739 #[test]
3740 fn test_partial_ord() {
3741 let exp1 = col("a") + lit(1);
3744 let exp2 = col("a") + lit(2);
3745 let exp3 = !(col("a") + lit(2));
3746
3747 assert!(exp1 < exp2);
3748 assert!(exp3 > exp2);
3749 assert!(exp1 < exp3)
3750 }
3751
3752 #[test]
3753 fn test_collect_expr() -> Result<()> {
3754 {
3756 let expr = &Expr::Cast(Cast::new(Box::new(col("a")), DataType::Float64));
3757 let columns = expr.column_refs();
3758 assert_eq!(1, columns.len());
3759 assert!(columns.contains(&Column::from_name("a")));
3760 }
3761
3762 {
3764 let expr = col("a") + col("b") + lit(1);
3765 let columns = expr.column_refs();
3766 assert_eq!(2, columns.len());
3767 assert!(columns.contains(&Column::from_name("a")));
3768 assert!(columns.contains(&Column::from_name("b")));
3769 }
3770
3771 Ok(())
3772 }
3773
3774 #[test]
3775 fn test_logical_ops() {
3776 assert_eq!(
3777 format!("{}", lit(1u32).eq(lit(2u32))),
3778 "UInt32(1) = UInt32(2)"
3779 );
3780 assert_eq!(
3781 format!("{}", lit(1u32).not_eq(lit(2u32))),
3782 "UInt32(1) != UInt32(2)"
3783 );
3784 assert_eq!(
3785 format!("{}", lit(1u32).gt(lit(2u32))),
3786 "UInt32(1) > UInt32(2)"
3787 );
3788 assert_eq!(
3789 format!("{}", lit(1u32).gt_eq(lit(2u32))),
3790 "UInt32(1) >= UInt32(2)"
3791 );
3792 assert_eq!(
3793 format!("{}", lit(1u32).lt(lit(2u32))),
3794 "UInt32(1) < UInt32(2)"
3795 );
3796 assert_eq!(
3797 format!("{}", lit(1u32).lt_eq(lit(2u32))),
3798 "UInt32(1) <= UInt32(2)"
3799 );
3800 assert_eq!(
3801 format!("{}", lit(1u32).and(lit(2u32))),
3802 "UInt32(1) AND UInt32(2)"
3803 );
3804 assert_eq!(
3805 format!("{}", lit(1u32).or(lit(2u32))),
3806 "UInt32(1) OR UInt32(2)"
3807 );
3808 }
3809
3810 #[test]
3811 fn test_is_volatile_scalar_func() {
3812 #[derive(Debug, PartialEq, Eq, Hash)]
3814 struct TestScalarUDF {
3815 signature: Signature,
3816 }
3817 impl ScalarUDFImpl for TestScalarUDF {
3818 fn as_any(&self) -> &dyn Any {
3819 self
3820 }
3821 fn name(&self) -> &str {
3822 "TestScalarUDF"
3823 }
3824
3825 fn signature(&self) -> &Signature {
3826 &self.signature
3827 }
3828
3829 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
3830 Ok(DataType::Utf8)
3831 }
3832
3833 fn invoke_with_args(
3834 &self,
3835 _args: ScalarFunctionArgs,
3836 ) -> Result<ColumnarValue> {
3837 Ok(ColumnarValue::Scalar(ScalarValue::from("a")))
3838 }
3839 }
3840 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3841 signature: Signature::uniform(1, vec![DataType::Float32], Volatility::Stable),
3842 }));
3843 assert_ne!(udf.signature().volatility, Volatility::Volatile);
3844
3845 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3846 signature: Signature::uniform(
3847 1,
3848 vec![DataType::Float32],
3849 Volatility::Volatile,
3850 ),
3851 }));
3852 assert_eq!(udf.signature().volatility, Volatility::Volatile);
3853 }
3854
3855 use super::*;
3856
3857 #[test]
3858 fn test_display_wildcard() {
3859 assert_eq!(format!("{}", wildcard()), "*");
3860 assert_eq!(format!("{}", qualified_wildcard("t1")), "t1.*");
3861 assert_eq!(
3862 format!(
3863 "{}",
3864 wildcard_with_options(wildcard_options(
3865 Some(IlikeSelectItem {
3866 pattern: "c1".to_string()
3867 }),
3868 None,
3869 None,
3870 None,
3871 None
3872 ))
3873 ),
3874 "* ILIKE 'c1'"
3875 );
3876 assert_eq!(
3877 format!(
3878 "{}",
3879 wildcard_with_options(wildcard_options(
3880 None,
3881 Some(ExcludeSelectItem::Multiple(vec![
3882 Ident::from("c1"),
3883 Ident::from("c2")
3884 ])),
3885 None,
3886 None,
3887 None
3888 ))
3889 ),
3890 "* EXCLUDE (c1, c2)"
3891 );
3892 assert_eq!(
3893 format!(
3894 "{}",
3895 wildcard_with_options(wildcard_options(
3896 None,
3897 None,
3898 Some(ExceptSelectItem {
3899 first_element: Ident::from("c1"),
3900 additional_elements: vec![Ident::from("c2")]
3901 }),
3902 None,
3903 None
3904 ))
3905 ),
3906 "* EXCEPT (c1, c2)"
3907 );
3908 assert_eq!(
3909 format!(
3910 "{}",
3911 wildcard_with_options(wildcard_options(
3912 None,
3913 None,
3914 None,
3915 Some(PlannedReplaceSelectItem {
3916 items: vec![ReplaceSelectElement {
3917 expr: ast::Expr::Identifier(Ident::from("c1")),
3918 column_name: Ident::from("a1"),
3919 as_keyword: false
3920 }],
3921 planned_expressions: vec![]
3922 }),
3923 None
3924 ))
3925 ),
3926 "* REPLACE (c1 a1)"
3927 );
3928 assert_eq!(
3929 format!(
3930 "{}",
3931 wildcard_with_options(wildcard_options(
3932 None,
3933 None,
3934 None,
3935 None,
3936 Some(RenameSelectItem::Multiple(vec![IdentWithAlias {
3937 ident: Ident::from("c1"),
3938 alias: Ident::from("a1")
3939 }]))
3940 ))
3941 ),
3942 "* RENAME (c1 AS a1)"
3943 )
3944 }
3945
3946 #[test]
3947 fn test_schema_display_alias_with_relation() {
3948 assert_eq!(
3949 format!(
3950 "{}",
3951 SchemaDisplay(
3952 &lit(1).alias_qualified("table_name".into(), "column_name")
3953 )
3954 ),
3955 "table_name.column_name"
3956 );
3957 }
3958
3959 #[test]
3960 fn test_schema_display_alias_without_relation() {
3961 assert_eq!(
3962 format!(
3963 "{}",
3964 SchemaDisplay(&lit(1).alias_qualified(None::<&str>, "column_name"))
3965 ),
3966 "column_name"
3967 );
3968 }
3969
3970 fn wildcard_options(
3971 opt_ilike: Option<IlikeSelectItem>,
3972 opt_exclude: Option<ExcludeSelectItem>,
3973 opt_except: Option<ExceptSelectItem>,
3974 opt_replace: Option<PlannedReplaceSelectItem>,
3975 opt_rename: Option<RenameSelectItem>,
3976 ) -> WildcardOptions {
3977 WildcardOptions {
3978 ilike: opt_ilike,
3979 exclude: opt_exclude,
3980 except: opt_except,
3981 replace: opt_replace,
3982 rename: opt_rename,
3983 }
3984 }
3985
3986 #[test]
3987 fn test_size_of_expr() {
3988 assert_eq!(size_of::<Expr>(), 112);
3995 assert_eq!(size_of::<ScalarValue>(), 64);
3996 assert_eq!(size_of::<DataType>(), 24); assert_eq!(size_of::<Vec<Expr>>(), 24);
3998 assert_eq!(size_of::<Arc<Expr>>(), 8);
3999 }
4000
4001 #[test]
4002 fn test_accept_exprs() {
4003 fn accept_exprs<E: AsRef<Expr>>(_: &[E]) {}
4004
4005 let expr = || -> Expr { lit(1) };
4006
4007 let owned_exprs = vec![expr(), expr()];
4009 accept_exprs(&owned_exprs);
4010
4011 let udf = Expr::ScalarFunction(ScalarFunction {
4013 func: Arc::new(ScalarUDF::new_from_impl(TestUDF {})),
4014 args: vec![expr(), expr()],
4015 });
4016 let Expr::ScalarFunction(scalar) = &udf else {
4017 unreachable!()
4018 };
4019 accept_exprs(&scalar.args);
4020
4021 let mut collected_refs: Vec<&Expr> = scalar.args.iter().collect();
4023 collected_refs.extend(&owned_exprs);
4024 accept_exprs(&collected_refs);
4025
4026 #[derive(Debug, PartialEq, Eq, Hash)]
4028 struct TestUDF {}
4029 impl ScalarUDFImpl for TestUDF {
4030 fn as_any(&self) -> &dyn Any {
4031 unimplemented!()
4032 }
4033
4034 fn name(&self) -> &str {
4035 unimplemented!()
4036 }
4037
4038 fn signature(&self) -> &Signature {
4039 unimplemented!()
4040 }
4041
4042 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
4043 unimplemented!()
4044 }
4045
4046 fn invoke_with_args(
4047 &self,
4048 _args: ScalarFunctionArgs,
4049 ) -> Result<ColumnarValue> {
4050 unimplemented!()
4051 }
4052 }
4053 }
4054}