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 ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem, RenameSelectItem,
45 ReplaceSelectElement, display_comma_separated,
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(FieldRef, 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}
402
403impl Default for Expr {
404 fn default() -> Self {
405 Expr::Literal(ScalarValue::Null, None)
406 }
407}
408
409impl AsRef<Expr> for Expr {
410 fn as_ref(&self) -> &Expr {
411 self
412 }
413}
414
415impl From<Column> for Expr {
417 fn from(value: Column) -> Self {
418 Expr::Column(value)
419 }
420}
421
422impl From<WindowFunction> for Expr {
424 fn from(value: WindowFunction) -> Self {
425 Expr::WindowFunction(Box::new(value))
426 }
427}
428
429impl From<ScalarAndMetadata> for Expr {
431 fn from(value: ScalarAndMetadata) -> Self {
432 let (value, metadata) = value.into_inner();
433 Expr::Literal(value, metadata)
434 }
435}
436
437impl<'a> From<(Option<&'a TableReference>, &'a FieldRef)> for Expr {
442 fn from(value: (Option<&'a TableReference>, &'a FieldRef)) -> Self {
443 Expr::from(Column::from(value))
444 }
445}
446
447impl<'a> TreeNodeContainer<'a, Self> for Expr {
448 fn apply_elements<F: FnMut(&'a Self) -> Result<TreeNodeRecursion>>(
449 &'a self,
450 mut f: F,
451 ) -> Result<TreeNodeRecursion> {
452 f(self)
453 }
454
455 fn map_elements<F: FnMut(Self) -> Result<Transformed<Self>>>(
456 self,
457 mut f: F,
458 ) -> Result<Transformed<Self>> {
459 f(self)
460 }
461}
462
463pub type SchemaFieldMetadata = std::collections::HashMap<String, String>;
484
485pub fn intersect_metadata_for_union<'a>(
507 metadatas: impl IntoIterator<Item = &'a SchemaFieldMetadata>,
508) -> SchemaFieldMetadata {
509 let mut metadatas = metadatas.into_iter();
510 let Some(mut intersected) = metadatas.next().cloned() else {
511 return Default::default();
512 };
513
514 for metadata in metadatas {
515 intersected.retain(|k, v| metadata.get(k) == Some(v));
517 }
518
519 intersected
520}
521
522#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
524pub struct Unnest {
525 pub expr: Box<Expr>,
526}
527
528impl Unnest {
529 pub fn new(expr: Expr) -> Self {
531 Self {
532 expr: Box::new(expr),
533 }
534 }
535
536 pub fn new_boxed(boxed: Box<Expr>) -> Self {
538 Self { expr: boxed }
539 }
540}
541
542#[derive(Clone, PartialEq, Eq, Debug)]
544pub struct Alias {
545 pub expr: Box<Expr>,
546 pub relation: Option<TableReference>,
547 pub name: String,
548 pub metadata: Option<FieldMetadata>,
549}
550
551impl Hash for Alias {
552 fn hash<H: Hasher>(&self, state: &mut H) {
553 self.expr.hash(state);
554 self.relation.hash(state);
555 self.name.hash(state);
556 }
557}
558
559impl PartialOrd for Alias {
560 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
561 let cmp = self.expr.partial_cmp(&other.expr);
562 let Some(Ordering::Equal) = cmp else {
563 return cmp;
564 };
565 let cmp = self.relation.partial_cmp(&other.relation);
566 let Some(Ordering::Equal) = cmp else {
567 return cmp;
568 };
569 self.name
570 .partial_cmp(&other.name)
571 .filter(|cmp| *cmp != Ordering::Equal || self == other)
573 }
574}
575
576impl Alias {
577 pub fn new(
579 expr: Expr,
580 relation: Option<impl Into<TableReference>>,
581 name: impl Into<String>,
582 ) -> Self {
583 Self {
584 expr: Box::new(expr),
585 relation: relation.map(|r| r.into()),
586 name: name.into(),
587 metadata: None,
588 }
589 }
590
591 pub fn with_metadata(mut self, metadata: Option<FieldMetadata>) -> Self {
592 self.metadata = metadata;
593 self
594 }
595}
596
597#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
599pub struct BinaryExpr {
600 pub left: Box<Expr>,
602 pub op: Operator,
604 pub right: Box<Expr>,
606}
607
608impl BinaryExpr {
609 pub fn new(left: Box<Expr>, op: Operator, right: Box<Expr>) -> Self {
611 Self { left, op, right }
612 }
613}
614
615impl Display for BinaryExpr {
616 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
617 fn write_child(
623 f: &mut Formatter<'_>,
624 expr: &Expr,
625 precedence: u8,
626 ) -> fmt::Result {
627 match expr {
628 Expr::BinaryExpr(child) => {
629 let p = child.op.precedence();
630 if p == 0 || p < precedence {
631 write!(f, "({child})")?;
632 } else {
633 write!(f, "{child}")?;
634 }
635 }
636 _ => write!(f, "{expr}")?,
637 }
638 Ok(())
639 }
640
641 let precedence = self.op.precedence();
642 write_child(f, self.left.as_ref(), precedence)?;
643 write!(f, " {} ", self.op)?;
644 write_child(f, self.right.as_ref(), precedence)
645 }
646}
647
648#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
672pub struct Case {
673 pub expr: Option<Box<Expr>>,
675 pub when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
677 pub else_expr: Option<Box<Expr>>,
679}
680
681impl Case {
682 pub fn new(
684 expr: Option<Box<Expr>>,
685 when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
686 else_expr: Option<Box<Expr>>,
687 ) -> Self {
688 Self {
689 expr,
690 when_then_expr,
691 else_expr,
692 }
693 }
694}
695
696#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
698pub struct Like {
699 pub negated: bool,
700 pub expr: Box<Expr>,
701 pub pattern: Box<Expr>,
702 pub escape_char: Option<char>,
703 pub case_insensitive: bool,
705}
706
707impl Like {
708 pub fn new(
710 negated: bool,
711 expr: Box<Expr>,
712 pattern: Box<Expr>,
713 escape_char: Option<char>,
714 case_insensitive: bool,
715 ) -> Self {
716 Self {
717 negated,
718 expr,
719 pattern,
720 escape_char,
721 case_insensitive,
722 }
723 }
724}
725
726#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
728pub struct Between {
729 pub expr: Box<Expr>,
731 pub negated: bool,
733 pub low: Box<Expr>,
735 pub high: Box<Expr>,
737}
738
739impl Between {
740 pub fn new(expr: Box<Expr>, negated: bool, low: Box<Expr>, high: Box<Expr>) -> Self {
742 Self {
743 expr,
744 negated,
745 low,
746 high,
747 }
748 }
749}
750
751#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
755pub struct ScalarFunction {
756 pub func: Arc<crate::ScalarUDF>,
758 pub args: Vec<Expr>,
760}
761
762impl ScalarFunction {
763 pub fn name(&self) -> &str {
765 self.func.name()
766 }
767}
768
769impl ScalarFunction {
770 pub fn new_udf(udf: Arc<crate::ScalarUDF>, args: Vec<Expr>) -> Self {
774 Self { func: udf, args }
775 }
776}
777
778#[derive(Clone, PartialEq, Eq, Hash, Debug)]
780pub enum GetFieldAccess {
781 NamedStructField { name: ScalarValue },
783 ListIndex { key: Box<Expr> },
785 ListRange {
787 start: Box<Expr>,
788 stop: Box<Expr>,
789 stride: Box<Expr>,
790 },
791}
792
793#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
795pub struct Cast {
796 pub expr: Box<Expr>,
798 pub data_type: DataType,
800}
801
802impl Cast {
803 pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
805 Self { expr, data_type }
806 }
807}
808
809#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
811pub struct TryCast {
812 pub expr: Box<Expr>,
814 pub data_type: DataType,
816}
817
818impl TryCast {
819 pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
821 Self { expr, data_type }
822 }
823}
824
825#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
827pub struct Sort {
828 pub expr: Expr,
830 pub asc: bool,
832 pub nulls_first: bool,
834}
835
836impl Sort {
837 pub fn new(expr: Expr, asc: bool, nulls_first: bool) -> Self {
839 Self {
840 expr,
841 asc,
842 nulls_first,
843 }
844 }
845
846 pub fn reverse(&self) -> Self {
848 Self {
849 expr: self.expr.clone(),
850 asc: !self.asc,
851 nulls_first: !self.nulls_first,
852 }
853 }
854
855 pub fn with_expr(&self, expr: Expr) -> Self {
857 Self {
858 expr,
859 asc: self.asc,
860 nulls_first: self.nulls_first,
861 }
862 }
863}
864
865impl Display for Sort {
866 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
867 write!(f, "{}", self.expr)?;
868 if self.asc {
869 write!(f, " ASC")?;
870 } else {
871 write!(f, " DESC")?;
872 }
873 if self.nulls_first {
874 write!(f, " NULLS FIRST")?;
875 } else {
876 write!(f, " NULLS LAST")?;
877 }
878 Ok(())
879 }
880}
881
882impl<'a> TreeNodeContainer<'a, Expr> for Sort {
883 fn apply_elements<F: FnMut(&'a Expr) -> Result<TreeNodeRecursion>>(
884 &'a self,
885 f: F,
886 ) -> Result<TreeNodeRecursion> {
887 self.expr.apply_elements(f)
888 }
889
890 fn map_elements<F: FnMut(Expr) -> Result<Transformed<Expr>>>(
891 self,
892 f: F,
893 ) -> Result<Transformed<Self>> {
894 self.expr
895 .map_elements(f)?
896 .map_data(|expr| Ok(Self { expr, ..self }))
897 }
898}
899
900#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
906pub struct AggregateFunction {
907 pub func: Arc<AggregateUDF>,
909 pub params: AggregateFunctionParams,
910}
911
912#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
913pub struct AggregateFunctionParams {
914 pub args: Vec<Expr>,
915 pub distinct: bool,
917 pub filter: Option<Box<Expr>>,
919 pub order_by: Vec<Sort>,
921 pub null_treatment: Option<NullTreatment>,
922}
923
924impl AggregateFunction {
925 pub fn new_udf(
927 func: Arc<AggregateUDF>,
928 args: Vec<Expr>,
929 distinct: bool,
930 filter: Option<Box<Expr>>,
931 order_by: Vec<Sort>,
932 null_treatment: Option<NullTreatment>,
933 ) -> Self {
934 Self {
935 func,
936 params: AggregateFunctionParams {
937 args,
938 distinct,
939 filter,
940 order_by,
941 null_treatment,
942 },
943 }
944 }
945}
946
947#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
953pub enum WindowFunctionDefinition {
954 AggregateUDF(Arc<AggregateUDF>),
956 WindowUDF(Arc<WindowUDF>),
958}
959
960impl WindowFunctionDefinition {
961 pub fn return_field(
963 &self,
964 input_expr_fields: &[FieldRef],
965 display_name: &str,
966 ) -> Result<FieldRef> {
967 match self {
968 WindowFunctionDefinition::AggregateUDF(fun) => {
969 fun.return_field(input_expr_fields)
970 }
971 WindowFunctionDefinition::WindowUDF(fun) => {
972 fun.field(WindowUDFFieldArgs::new(input_expr_fields, display_name))
973 }
974 }
975 }
976
977 pub fn signature(&self) -> Signature {
979 match self {
980 WindowFunctionDefinition::AggregateUDF(fun) => fun.signature().clone(),
981 WindowFunctionDefinition::WindowUDF(fun) => fun.signature().clone(),
982 }
983 }
984
985 pub fn name(&self) -> &str {
987 match self {
988 WindowFunctionDefinition::WindowUDF(fun) => fun.name(),
989 WindowFunctionDefinition::AggregateUDF(fun) => fun.name(),
990 }
991 }
992
993 pub fn simplify(&self) -> Option<WindowFunctionSimplification> {
997 match self {
998 WindowFunctionDefinition::AggregateUDF(_) => None,
999 WindowFunctionDefinition::WindowUDF(udwf) => udwf.simplify(),
1000 }
1001 }
1002}
1003
1004impl Display for WindowFunctionDefinition {
1005 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1006 match self {
1007 WindowFunctionDefinition::AggregateUDF(fun) => Display::fmt(fun, f),
1008 WindowFunctionDefinition::WindowUDF(fun) => Display::fmt(fun, f),
1009 }
1010 }
1011}
1012
1013impl From<Arc<AggregateUDF>> for WindowFunctionDefinition {
1014 fn from(value: Arc<AggregateUDF>) -> Self {
1015 Self::AggregateUDF(value)
1016 }
1017}
1018
1019impl From<Arc<WindowUDF>> for WindowFunctionDefinition {
1020 fn from(value: Arc<WindowUDF>) -> Self {
1021 Self::WindowUDF(value)
1022 }
1023}
1024
1025#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1038pub struct WindowFunction {
1039 pub fun: WindowFunctionDefinition,
1041 pub params: WindowFunctionParams,
1042}
1043
1044#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1045pub struct WindowFunctionParams {
1046 pub args: Vec<Expr>,
1048 pub partition_by: Vec<Expr>,
1050 pub order_by: Vec<Sort>,
1052 pub window_frame: WindowFrame,
1054 pub filter: Option<Box<Expr>>,
1056 pub null_treatment: Option<NullTreatment>,
1058 pub distinct: bool,
1060}
1061
1062impl WindowFunction {
1063 pub fn new(fun: impl Into<WindowFunctionDefinition>, args: Vec<Expr>) -> Self {
1066 Self {
1067 fun: fun.into(),
1068 params: WindowFunctionParams {
1069 args,
1070 partition_by: Vec::default(),
1071 order_by: Vec::default(),
1072 window_frame: WindowFrame::new(None),
1073 filter: None,
1074 null_treatment: None,
1075 distinct: false,
1076 },
1077 }
1078 }
1079
1080 pub fn simplify(&self) -> Option<WindowFunctionSimplification> {
1084 self.fun.simplify()
1085 }
1086}
1087
1088#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1090pub struct Exists {
1091 pub subquery: Subquery,
1093 pub negated: bool,
1095}
1096
1097impl Exists {
1098 pub fn new(subquery: Subquery, negated: bool) -> Self {
1100 Self { subquery, negated }
1101 }
1102}
1103
1104#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1106pub struct InList {
1107 pub expr: Box<Expr>,
1109 pub list: Vec<Expr>,
1111 pub negated: bool,
1113}
1114
1115impl InList {
1116 pub fn new(expr: Box<Expr>, list: Vec<Expr>, negated: bool) -> Self {
1118 Self {
1119 expr,
1120 list,
1121 negated,
1122 }
1123 }
1124}
1125
1126#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1128pub struct InSubquery {
1129 pub expr: Box<Expr>,
1131 pub subquery: Subquery,
1133 pub negated: bool,
1135}
1136
1137impl InSubquery {
1138 pub fn new(expr: Box<Expr>, subquery: Subquery, negated: bool) -> Self {
1140 Self {
1141 expr,
1142 subquery,
1143 negated,
1144 }
1145 }
1146}
1147
1148#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1153pub struct Placeholder {
1154 pub id: String,
1156 pub field: Option<FieldRef>,
1158}
1159
1160impl Placeholder {
1161 #[deprecated(since = "51.0.0", note = "Use new_with_field instead")]
1163 pub fn new(id: String, data_type: Option<DataType>) -> Self {
1164 Self {
1165 id,
1166 field: data_type.map(|dt| Arc::new(Field::new("", dt, true))),
1167 }
1168 }
1169
1170 pub fn new_with_field(id: String, field: Option<FieldRef>) -> Self {
1172 Self { id, field }
1173 }
1174}
1175
1176#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1183pub enum GroupingSet {
1184 Rollup(Vec<Expr>),
1186 Cube(Vec<Expr>),
1188 GroupingSets(Vec<Vec<Expr>>),
1190}
1191
1192impl GroupingSet {
1193 pub fn distinct_expr(&self) -> Vec<&Expr> {
1197 match self {
1198 GroupingSet::Rollup(exprs) | GroupingSet::Cube(exprs) => {
1199 exprs.iter().collect()
1200 }
1201 GroupingSet::GroupingSets(groups) => {
1202 let mut exprs: Vec<&Expr> = vec![];
1203 for exp in groups.iter().flatten() {
1204 if !exprs.contains(&exp) {
1205 exprs.push(exp);
1206 }
1207 }
1208 exprs
1209 }
1210 }
1211 }
1212}
1213
1214#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1215#[cfg(not(feature = "sql"))]
1216pub struct IlikeSelectItem {
1217 pub pattern: String,
1218}
1219#[cfg(not(feature = "sql"))]
1220impl Display for IlikeSelectItem {
1221 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1222 write!(f, "ILIKE '{}'", &self.pattern)?;
1223 Ok(())
1224 }
1225}
1226#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1227#[cfg(not(feature = "sql"))]
1228pub enum ExcludeSelectItem {
1229 Single(Ident),
1230 Multiple(Vec<Ident>),
1231}
1232#[cfg(not(feature = "sql"))]
1233impl Display for ExcludeSelectItem {
1234 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1235 write!(f, "EXCLUDE")?;
1236 match self {
1237 Self::Single(column) => {
1238 write!(f, " {column}")?;
1239 }
1240 Self::Multiple(columns) => {
1241 write!(f, " ({})", display_comma_separated(columns))?;
1242 }
1243 }
1244 Ok(())
1245 }
1246}
1247#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1248#[cfg(not(feature = "sql"))]
1249pub struct ExceptSelectItem {
1250 pub first_element: Ident,
1251 pub additional_elements: Vec<Ident>,
1252}
1253#[cfg(not(feature = "sql"))]
1254impl Display for ExceptSelectItem {
1255 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1256 write!(f, "EXCEPT ")?;
1257 if self.additional_elements.is_empty() {
1258 write!(f, "({})", self.first_element)?;
1259 } else {
1260 write!(
1261 f,
1262 "({}, {})",
1263 self.first_element,
1264 display_comma_separated(&self.additional_elements)
1265 )?;
1266 }
1267 Ok(())
1268 }
1269}
1270
1271#[cfg(not(feature = "sql"))]
1272pub fn display_comma_separated<T>(slice: &[T]) -> String
1273where
1274 T: Display,
1275{
1276 use itertools::Itertools;
1277 slice.iter().map(|v| format!("{v}")).join(", ")
1278}
1279
1280#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1281#[cfg(not(feature = "sql"))]
1282pub enum RenameSelectItem {
1283 Single(String),
1284 Multiple(Vec<String>),
1285}
1286#[cfg(not(feature = "sql"))]
1287impl Display for RenameSelectItem {
1288 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1289 write!(f, "RENAME")?;
1290 match self {
1291 Self::Single(column) => {
1292 write!(f, " {column}")?;
1293 }
1294 Self::Multiple(columns) => {
1295 write!(f, " ({})", display_comma_separated(columns))?;
1296 }
1297 }
1298 Ok(())
1299 }
1300}
1301
1302#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1303#[cfg(not(feature = "sql"))]
1304pub struct Ident {
1305 pub value: String,
1307 pub quote_style: Option<char>,
1310 pub span: String,
1312}
1313#[cfg(not(feature = "sql"))]
1314impl Display for Ident {
1315 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1316 write!(f, "[{}]", self.value)
1317 }
1318}
1319
1320#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1321#[cfg(not(feature = "sql"))]
1322pub struct ReplaceSelectElement {
1323 pub expr: String,
1324 pub column_name: Ident,
1325 pub as_keyword: bool,
1326}
1327#[cfg(not(feature = "sql"))]
1328impl Display for ReplaceSelectElement {
1329 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1330 if self.as_keyword {
1331 write!(f, "{} AS {}", self.expr, self.column_name)
1332 } else {
1333 write!(f, "{} {}", self.expr, self.column_name)
1334 }
1335 }
1336}
1337
1338#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1340pub struct WildcardOptions {
1341 pub ilike: Option<IlikeSelectItem>,
1344 pub exclude: Option<ExcludeSelectItem>,
1347 pub except: Option<ExceptSelectItem>,
1351 pub replace: Option<PlannedReplaceSelectItem>,
1356 pub rename: Option<RenameSelectItem>,
1359}
1360
1361impl WildcardOptions {
1362 pub fn with_replace(self, replace: PlannedReplaceSelectItem) -> Self {
1363 WildcardOptions {
1364 ilike: self.ilike,
1365 exclude: self.exclude,
1366 except: self.except,
1367 replace: Some(replace),
1368 rename: self.rename,
1369 }
1370 }
1371}
1372
1373impl Display for WildcardOptions {
1374 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1375 if let Some(ilike) = &self.ilike {
1376 write!(f, " {ilike}")?;
1377 }
1378 if let Some(exclude) = &self.exclude {
1379 write!(f, " {exclude}")?;
1380 }
1381 if let Some(except) = &self.except {
1382 write!(f, " {except}")?;
1383 }
1384 if let Some(replace) = &self.replace {
1385 write!(f, " {replace}")?;
1386 }
1387 if let Some(rename) = &self.rename {
1388 write!(f, " {rename}")?;
1389 }
1390 Ok(())
1391 }
1392}
1393
1394#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1396pub struct PlannedReplaceSelectItem {
1397 pub items: Vec<ReplaceSelectElement>,
1399 pub planned_expressions: Vec<Expr>,
1401}
1402
1403impl Display for PlannedReplaceSelectItem {
1404 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1405 write!(f, "REPLACE")?;
1406 write!(f, " ({})", display_comma_separated(&self.items))?;
1407 Ok(())
1408 }
1409}
1410
1411impl PlannedReplaceSelectItem {
1412 pub fn items(&self) -> &[ReplaceSelectElement] {
1413 &self.items
1414 }
1415
1416 pub fn expressions(&self) -> &[Expr] {
1417 &self.planned_expressions
1418 }
1419}
1420
1421impl Expr {
1422 pub fn schema_name(&self) -> impl Display + '_ {
1445 SchemaDisplay(self)
1446 }
1447
1448 pub fn human_display(&self) -> impl Display + '_ {
1470 SqlDisplay(self)
1471 }
1472
1473 pub fn qualified_name(&self) -> (Option<TableReference>, String) {
1479 match self {
1480 Expr::Column(Column {
1481 relation,
1482 name,
1483 spans: _,
1484 }) => (relation.clone(), name.clone()),
1485 Expr::Alias(Alias { relation, name, .. }) => (relation.clone(), name.clone()),
1486 _ => (None, self.schema_name().to_string()),
1487 }
1488 }
1489
1490 pub fn variant_name(&self) -> &str {
1493 match self {
1494 Expr::AggregateFunction { .. } => "AggregateFunction",
1495 Expr::Alias(..) => "Alias",
1496 Expr::Between { .. } => "Between",
1497 Expr::BinaryExpr { .. } => "BinaryExpr",
1498 Expr::Case { .. } => "Case",
1499 Expr::Cast { .. } => "Cast",
1500 Expr::Column(..) => "Column",
1501 Expr::OuterReferenceColumn(_, _) => "Outer",
1502 Expr::Exists { .. } => "Exists",
1503 Expr::GroupingSet(..) => "GroupingSet",
1504 Expr::InList { .. } => "InList",
1505 Expr::InSubquery(..) => "InSubquery",
1506 Expr::IsNotNull(..) => "IsNotNull",
1507 Expr::IsNull(..) => "IsNull",
1508 Expr::Like { .. } => "Like",
1509 Expr::SimilarTo { .. } => "RLike",
1510 Expr::IsTrue(..) => "IsTrue",
1511 Expr::IsFalse(..) => "IsFalse",
1512 Expr::IsUnknown(..) => "IsUnknown",
1513 Expr::IsNotTrue(..) => "IsNotTrue",
1514 Expr::IsNotFalse(..) => "IsNotFalse",
1515 Expr::IsNotUnknown(..) => "IsNotUnknown",
1516 Expr::Literal(..) => "Literal",
1517 Expr::Negative(..) => "Negative",
1518 Expr::Not(..) => "Not",
1519 Expr::Placeholder(_) => "Placeholder",
1520 Expr::ScalarFunction(..) => "ScalarFunction",
1521 Expr::ScalarSubquery { .. } => "ScalarSubquery",
1522 Expr::ScalarVariable(..) => "ScalarVariable",
1523 Expr::TryCast { .. } => "TryCast",
1524 Expr::WindowFunction { .. } => "WindowFunction",
1525 #[expect(deprecated)]
1526 Expr::Wildcard { .. } => "Wildcard",
1527 Expr::Unnest { .. } => "Unnest",
1528 }
1529 }
1530
1531 pub fn eq(self, other: Expr) -> Expr {
1533 binary_expr(self, Operator::Eq, other)
1534 }
1535
1536 pub fn not_eq(self, other: Expr) -> Expr {
1538 binary_expr(self, Operator::NotEq, other)
1539 }
1540
1541 pub fn gt(self, other: Expr) -> Expr {
1543 binary_expr(self, Operator::Gt, other)
1544 }
1545
1546 pub fn gt_eq(self, other: Expr) -> Expr {
1548 binary_expr(self, Operator::GtEq, other)
1549 }
1550
1551 pub fn lt(self, other: Expr) -> Expr {
1553 binary_expr(self, Operator::Lt, other)
1554 }
1555
1556 pub fn lt_eq(self, other: Expr) -> Expr {
1558 binary_expr(self, Operator::LtEq, other)
1559 }
1560
1561 pub fn and(self, other: Expr) -> Expr {
1563 binary_expr(self, Operator::And, other)
1564 }
1565
1566 pub fn or(self, other: Expr) -> Expr {
1568 binary_expr(self, Operator::Or, other)
1569 }
1570
1571 pub fn like(self, other: Expr) -> Expr {
1573 Expr::Like(Like::new(
1574 false,
1575 Box::new(self),
1576 Box::new(other),
1577 None,
1578 false,
1579 ))
1580 }
1581
1582 pub fn not_like(self, other: Expr) -> Expr {
1584 Expr::Like(Like::new(
1585 true,
1586 Box::new(self),
1587 Box::new(other),
1588 None,
1589 false,
1590 ))
1591 }
1592
1593 pub fn ilike(self, other: Expr) -> Expr {
1595 Expr::Like(Like::new(
1596 false,
1597 Box::new(self),
1598 Box::new(other),
1599 None,
1600 true,
1601 ))
1602 }
1603
1604 pub fn not_ilike(self, other: Expr) -> Expr {
1606 Expr::Like(Like::new(true, Box::new(self), Box::new(other), None, true))
1607 }
1608
1609 pub fn name_for_alias(&self) -> Result<String> {
1611 Ok(self.schema_name().to_string())
1612 }
1613
1614 pub fn alias_if_changed(self, original_name: String) -> Result<Expr> {
1617 let new_name = self.name_for_alias()?;
1618 if new_name == original_name {
1619 return Ok(self);
1620 }
1621
1622 Ok(self.alias(original_name))
1623 }
1624
1625 pub fn alias(self, name: impl Into<String>) -> Expr {
1627 Expr::Alias(Alias::new(self, None::<&str>, name.into()))
1628 }
1629
1630 pub fn alias_with_metadata(
1645 self,
1646 name: impl Into<String>,
1647 metadata: Option<FieldMetadata>,
1648 ) -> Expr {
1649 Expr::Alias(Alias::new(self, None::<&str>, name.into()).with_metadata(metadata))
1650 }
1651
1652 pub fn alias_qualified(
1654 self,
1655 relation: Option<impl Into<TableReference>>,
1656 name: impl Into<String>,
1657 ) -> Expr {
1658 Expr::Alias(Alias::new(self, relation, name.into()))
1659 }
1660
1661 pub fn alias_qualified_with_metadata(
1677 self,
1678 relation: Option<impl Into<TableReference>>,
1679 name: impl Into<String>,
1680 metadata: Option<FieldMetadata>,
1681 ) -> Expr {
1682 Expr::Alias(Alias::new(self, relation, name.into()).with_metadata(metadata))
1683 }
1684
1685 pub fn unalias(self) -> Expr {
1706 match self {
1707 Expr::Alias(alias) => *alias.expr,
1708 _ => self,
1709 }
1710 }
1711
1712 pub fn unalias_nested(self) -> Transformed<Expr> {
1733 self.transform_down_up(
1734 |expr| {
1735 let recursion = if matches!(
1737 expr,
1738 Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_)
1739 ) {
1740 TreeNodeRecursion::Jump
1742 } else {
1743 TreeNodeRecursion::Continue
1744 };
1745 Ok(Transformed::new(expr, false, recursion))
1746 },
1747 |expr| {
1748 if let Expr::Alias(alias) = expr {
1751 match alias
1752 .metadata
1753 .as_ref()
1754 .map(|h| h.is_empty())
1755 .unwrap_or(true)
1756 {
1757 true => Ok(Transformed::yes(*alias.expr)),
1758 false => Ok(Transformed::no(Expr::Alias(alias))),
1759 }
1760 } else {
1761 Ok(Transformed::no(expr))
1762 }
1763 },
1764 )
1765 .unwrap()
1767 }
1768
1769 pub fn in_list(self, list: Vec<Expr>, negated: bool) -> Expr {
1772 Expr::InList(InList::new(Box::new(self), list, negated))
1773 }
1774
1775 pub fn is_null(self) -> Expr {
1777 Expr::IsNull(Box::new(self))
1778 }
1779
1780 pub fn is_not_null(self) -> Expr {
1782 Expr::IsNotNull(Box::new(self))
1783 }
1784
1785 pub fn sort(self, asc: bool, nulls_first: bool) -> Sort {
1792 Sort::new(self, asc, nulls_first)
1793 }
1794
1795 pub fn is_true(self) -> Expr {
1797 Expr::IsTrue(Box::new(self))
1798 }
1799
1800 pub fn is_not_true(self) -> Expr {
1802 Expr::IsNotTrue(Box::new(self))
1803 }
1804
1805 pub fn is_false(self) -> Expr {
1807 Expr::IsFalse(Box::new(self))
1808 }
1809
1810 pub fn is_not_false(self) -> Expr {
1812 Expr::IsNotFalse(Box::new(self))
1813 }
1814
1815 pub fn is_unknown(self) -> Expr {
1817 Expr::IsUnknown(Box::new(self))
1818 }
1819
1820 pub fn is_not_unknown(self) -> Expr {
1822 Expr::IsNotUnknown(Box::new(self))
1823 }
1824
1825 pub fn between(self, low: Expr, high: Expr) -> Expr {
1827 Expr::Between(Between::new(
1828 Box::new(self),
1829 false,
1830 Box::new(low),
1831 Box::new(high),
1832 ))
1833 }
1834
1835 pub fn not_between(self, low: Expr, high: Expr) -> Expr {
1837 Expr::Between(Between::new(
1838 Box::new(self),
1839 true,
1840 Box::new(low),
1841 Box::new(high),
1842 ))
1843 }
1844 pub fn try_as_col(&self) -> Option<&Column> {
1862 if let Expr::Column(it) = self {
1863 Some(it)
1864 } else {
1865 None
1866 }
1867 }
1868
1869 pub fn get_as_join_column(&self) -> Option<&Column> {
1876 match self {
1877 Expr::Column(c) => Some(c),
1878 Expr::Cast(Cast { expr, .. }) => match &**expr {
1879 Expr::Column(c) => Some(c),
1880 _ => None,
1881 },
1882 _ => None,
1883 }
1884 }
1885
1886 pub fn column_refs(&self) -> HashSet<&Column> {
1902 let mut using_columns = HashSet::new();
1903 self.add_column_refs(&mut using_columns);
1904 using_columns
1905 }
1906
1907 pub fn add_column_refs<'a>(&'a self, set: &mut HashSet<&'a Column>) {
1911 self.apply(|expr| {
1912 if let Expr::Column(col) = expr {
1913 set.insert(col);
1914 }
1915 Ok(TreeNodeRecursion::Continue)
1916 })
1917 .expect("traversal is infallible");
1918 }
1919
1920 pub fn column_refs_counts(&self) -> HashMap<&Column, usize> {
1936 let mut map = HashMap::new();
1937 self.add_column_ref_counts(&mut map);
1938 map
1939 }
1940
1941 pub fn add_column_ref_counts<'a>(&'a self, map: &mut HashMap<&'a Column, usize>) {
1946 self.apply(|expr| {
1947 if let Expr::Column(col) = expr {
1948 *map.entry(col).or_default() += 1;
1949 }
1950 Ok(TreeNodeRecursion::Continue)
1951 })
1952 .expect("traversal is infallible");
1953 }
1954
1955 pub fn any_column_refs(&self) -> bool {
1957 self.exists(|expr| Ok(matches!(expr, Expr::Column(_))))
1958 .expect("exists closure is infallible")
1959 }
1960
1961 pub fn contains_outer(&self) -> bool {
1963 self.exists(|expr| Ok(matches!(expr, Expr::OuterReferenceColumn { .. })))
1964 .expect("exists closure is infallible")
1965 }
1966
1967 pub fn is_volatile_node(&self) -> bool {
1973 matches!(self, Expr::ScalarFunction(func) if func.func.signature().volatility == Volatility::Volatile)
1974 }
1975
1976 pub fn is_volatile(&self) -> bool {
1984 self.exists(|expr| Ok(expr.is_volatile_node()))
1985 .expect("exists closure is infallible")
1986 }
1987
1988 pub fn infer_placeholder_types(self, schema: &DFSchema) -> Result<(Expr, bool)> {
1997 let mut has_placeholder = false;
1998 self.transform(|mut expr| {
1999 match &mut expr {
2000 Expr::BinaryExpr(BinaryExpr { left, op: _, right }) => {
2002 rewrite_placeholder(left.as_mut(), right.as_ref(), schema)?;
2003 rewrite_placeholder(right.as_mut(), left.as_ref(), schema)?;
2004 }
2005 Expr::Between(Between {
2006 expr,
2007 negated: _,
2008 low,
2009 high,
2010 }) => {
2011 rewrite_placeholder(low.as_mut(), expr.as_ref(), schema)?;
2012 rewrite_placeholder(high.as_mut(), expr.as_ref(), schema)?;
2013 }
2014 Expr::InList(InList {
2015 expr,
2016 list,
2017 negated: _,
2018 }) => {
2019 for item in list.iter_mut() {
2020 rewrite_placeholder(item, expr.as_ref(), schema)?;
2021 }
2022 }
2023 Expr::Like(Like { expr, pattern, .. })
2024 | Expr::SimilarTo(Like { expr, pattern, .. }) => {
2025 rewrite_placeholder(pattern.as_mut(), expr.as_ref(), schema)?;
2026 }
2027 Expr::Placeholder(_) => {
2028 has_placeholder = true;
2029 }
2030 _ => {}
2031 }
2032 Ok(Transformed::yes(expr))
2033 })
2034 .data()
2035 .map(|data| (data, has_placeholder))
2036 }
2037
2038 pub fn short_circuits(&self) -> bool {
2041 match self {
2042 Expr::ScalarFunction(ScalarFunction { func, .. }) => func.short_circuits(),
2043 Expr::BinaryExpr(BinaryExpr { op, .. }) => {
2044 matches!(op, Operator::And | Operator::Or)
2045 }
2046 Expr::Case { .. } => true,
2047 #[expect(deprecated)]
2052 Expr::AggregateFunction(..)
2053 | Expr::Alias(..)
2054 | Expr::Between(..)
2055 | Expr::Cast(..)
2056 | Expr::Column(..)
2057 | Expr::Exists(..)
2058 | Expr::GroupingSet(..)
2059 | Expr::InList(..)
2060 | Expr::InSubquery(..)
2061 | Expr::IsFalse(..)
2062 | Expr::IsNotFalse(..)
2063 | Expr::IsNotNull(..)
2064 | Expr::IsNotTrue(..)
2065 | Expr::IsNotUnknown(..)
2066 | Expr::IsNull(..)
2067 | Expr::IsTrue(..)
2068 | Expr::IsUnknown(..)
2069 | Expr::Like(..)
2070 | Expr::ScalarSubquery(..)
2071 | Expr::ScalarVariable(_, _)
2072 | Expr::SimilarTo(..)
2073 | Expr::Not(..)
2074 | Expr::Negative(..)
2075 | Expr::OuterReferenceColumn(_, _)
2076 | Expr::TryCast(..)
2077 | Expr::Unnest(..)
2078 | Expr::Wildcard { .. }
2079 | Expr::WindowFunction(..)
2080 | Expr::Literal(..)
2081 | Expr::Placeholder(..) => false,
2082 }
2083 }
2084
2085 pub fn spans(&self) -> Option<&Spans> {
2089 match self {
2090 Expr::Column(col) => Some(&col.spans),
2091 _ => None,
2092 }
2093 }
2094
2095 pub fn as_literal(&self) -> Option<&ScalarValue> {
2097 if let Expr::Literal(lit, _) = self {
2098 Some(lit)
2099 } else {
2100 None
2101 }
2102 }
2103}
2104
2105impl Normalizeable for Expr {
2106 fn can_normalize(&self) -> bool {
2107 #[expect(clippy::match_like_matches_macro)]
2108 match self {
2109 Expr::BinaryExpr(BinaryExpr {
2110 op:
2111 _op @ (Operator::Plus
2112 | Operator::Multiply
2113 | Operator::BitwiseAnd
2114 | Operator::BitwiseOr
2115 | Operator::BitwiseXor
2116 | Operator::Eq
2117 | Operator::NotEq),
2118 ..
2119 }) => true,
2120 _ => false,
2121 }
2122 }
2123}
2124
2125impl NormalizeEq for Expr {
2126 fn normalize_eq(&self, other: &Self) -> bool {
2127 match (self, other) {
2128 (
2129 Expr::BinaryExpr(BinaryExpr {
2130 left: self_left,
2131 op: self_op,
2132 right: self_right,
2133 }),
2134 Expr::BinaryExpr(BinaryExpr {
2135 left: other_left,
2136 op: other_op,
2137 right: other_right,
2138 }),
2139 ) => {
2140 if self_op != other_op {
2141 return false;
2142 }
2143
2144 if matches!(
2145 self_op,
2146 Operator::Plus
2147 | Operator::Multiply
2148 | Operator::BitwiseAnd
2149 | Operator::BitwiseOr
2150 | Operator::BitwiseXor
2151 | Operator::Eq
2152 | Operator::NotEq
2153 ) {
2154 (self_left.normalize_eq(other_left)
2155 && self_right.normalize_eq(other_right))
2156 || (self_left.normalize_eq(other_right)
2157 && self_right.normalize_eq(other_left))
2158 } else {
2159 self_left.normalize_eq(other_left)
2160 && self_right.normalize_eq(other_right)
2161 }
2162 }
2163 (
2164 Expr::Alias(Alias {
2165 expr: self_expr,
2166 relation: self_relation,
2167 name: self_name,
2168 ..
2169 }),
2170 Expr::Alias(Alias {
2171 expr: other_expr,
2172 relation: other_relation,
2173 name: other_name,
2174 ..
2175 }),
2176 ) => {
2177 self_name == other_name
2178 && self_relation == other_relation
2179 && self_expr.normalize_eq(other_expr)
2180 }
2181 (
2182 Expr::Like(Like {
2183 negated: self_negated,
2184 expr: self_expr,
2185 pattern: self_pattern,
2186 escape_char: self_escape_char,
2187 case_insensitive: self_case_insensitive,
2188 }),
2189 Expr::Like(Like {
2190 negated: other_negated,
2191 expr: other_expr,
2192 pattern: other_pattern,
2193 escape_char: other_escape_char,
2194 case_insensitive: other_case_insensitive,
2195 }),
2196 )
2197 | (
2198 Expr::SimilarTo(Like {
2199 negated: self_negated,
2200 expr: self_expr,
2201 pattern: self_pattern,
2202 escape_char: self_escape_char,
2203 case_insensitive: self_case_insensitive,
2204 }),
2205 Expr::SimilarTo(Like {
2206 negated: other_negated,
2207 expr: other_expr,
2208 pattern: other_pattern,
2209 escape_char: other_escape_char,
2210 case_insensitive: other_case_insensitive,
2211 }),
2212 ) => {
2213 self_negated == other_negated
2214 && self_escape_char == other_escape_char
2215 && self_case_insensitive == other_case_insensitive
2216 && self_expr.normalize_eq(other_expr)
2217 && self_pattern.normalize_eq(other_pattern)
2218 }
2219 (Expr::Not(self_expr), Expr::Not(other_expr))
2220 | (Expr::IsNull(self_expr), Expr::IsNull(other_expr))
2221 | (Expr::IsTrue(self_expr), Expr::IsTrue(other_expr))
2222 | (Expr::IsFalse(self_expr), Expr::IsFalse(other_expr))
2223 | (Expr::IsUnknown(self_expr), Expr::IsUnknown(other_expr))
2224 | (Expr::IsNotNull(self_expr), Expr::IsNotNull(other_expr))
2225 | (Expr::IsNotTrue(self_expr), Expr::IsNotTrue(other_expr))
2226 | (Expr::IsNotFalse(self_expr), Expr::IsNotFalse(other_expr))
2227 | (Expr::IsNotUnknown(self_expr), Expr::IsNotUnknown(other_expr))
2228 | (Expr::Negative(self_expr), Expr::Negative(other_expr))
2229 | (
2230 Expr::Unnest(Unnest { expr: self_expr }),
2231 Expr::Unnest(Unnest { expr: other_expr }),
2232 ) => self_expr.normalize_eq(other_expr),
2233 (
2234 Expr::Between(Between {
2235 expr: self_expr,
2236 negated: self_negated,
2237 low: self_low,
2238 high: self_high,
2239 }),
2240 Expr::Between(Between {
2241 expr: other_expr,
2242 negated: other_negated,
2243 low: other_low,
2244 high: other_high,
2245 }),
2246 ) => {
2247 self_negated == other_negated
2248 && self_expr.normalize_eq(other_expr)
2249 && self_low.normalize_eq(other_low)
2250 && self_high.normalize_eq(other_high)
2251 }
2252 (
2253 Expr::Cast(Cast {
2254 expr: self_expr,
2255 data_type: self_data_type,
2256 }),
2257 Expr::Cast(Cast {
2258 expr: other_expr,
2259 data_type: other_data_type,
2260 }),
2261 )
2262 | (
2263 Expr::TryCast(TryCast {
2264 expr: self_expr,
2265 data_type: self_data_type,
2266 }),
2267 Expr::TryCast(TryCast {
2268 expr: other_expr,
2269 data_type: other_data_type,
2270 }),
2271 ) => self_data_type == other_data_type && self_expr.normalize_eq(other_expr),
2272 (
2273 Expr::ScalarFunction(ScalarFunction {
2274 func: self_func,
2275 args: self_args,
2276 }),
2277 Expr::ScalarFunction(ScalarFunction {
2278 func: other_func,
2279 args: other_args,
2280 }),
2281 ) => {
2282 self_func.name() == other_func.name()
2283 && self_args.len() == other_args.len()
2284 && self_args
2285 .iter()
2286 .zip(other_args.iter())
2287 .all(|(a, b)| a.normalize_eq(b))
2288 }
2289 (
2290 Expr::AggregateFunction(AggregateFunction {
2291 func: self_func,
2292 params:
2293 AggregateFunctionParams {
2294 args: self_args,
2295 distinct: self_distinct,
2296 filter: self_filter,
2297 order_by: self_order_by,
2298 null_treatment: self_null_treatment,
2299 },
2300 }),
2301 Expr::AggregateFunction(AggregateFunction {
2302 func: other_func,
2303 params:
2304 AggregateFunctionParams {
2305 args: other_args,
2306 distinct: other_distinct,
2307 filter: other_filter,
2308 order_by: other_order_by,
2309 null_treatment: other_null_treatment,
2310 },
2311 }),
2312 ) => {
2313 self_func.name() == other_func.name()
2314 && self_distinct == other_distinct
2315 && self_null_treatment == other_null_treatment
2316 && self_args.len() == other_args.len()
2317 && self_args
2318 .iter()
2319 .zip(other_args.iter())
2320 .all(|(a, b)| a.normalize_eq(b))
2321 && match (self_filter, other_filter) {
2322 (Some(self_filter), Some(other_filter)) => {
2323 self_filter.normalize_eq(other_filter)
2324 }
2325 (None, None) => true,
2326 _ => false,
2327 }
2328 && self_order_by
2329 .iter()
2330 .zip(other_order_by.iter())
2331 .all(|(a, b)| {
2332 a.asc == b.asc
2333 && a.nulls_first == b.nulls_first
2334 && a.expr.normalize_eq(&b.expr)
2335 })
2336 && self_order_by.len() == other_order_by.len()
2337 }
2338 (Expr::WindowFunction(left), Expr::WindowFunction(other)) => {
2339 let WindowFunction {
2340 fun: self_fun,
2341 params:
2342 WindowFunctionParams {
2343 args: self_args,
2344 window_frame: self_window_frame,
2345 partition_by: self_partition_by,
2346 order_by: self_order_by,
2347 filter: self_filter,
2348 null_treatment: self_null_treatment,
2349 distinct: self_distinct,
2350 },
2351 } = left.as_ref();
2352 let WindowFunction {
2353 fun: other_fun,
2354 params:
2355 WindowFunctionParams {
2356 args: other_args,
2357 window_frame: other_window_frame,
2358 partition_by: other_partition_by,
2359 order_by: other_order_by,
2360 filter: other_filter,
2361 null_treatment: other_null_treatment,
2362 distinct: other_distinct,
2363 },
2364 } = other.as_ref();
2365
2366 self_fun.name() == other_fun.name()
2367 && self_window_frame == other_window_frame
2368 && match (self_filter, other_filter) {
2369 (Some(a), Some(b)) => a.normalize_eq(b),
2370 (None, None) => true,
2371 _ => false,
2372 }
2373 && self_null_treatment == other_null_treatment
2374 && self_args.len() == other_args.len()
2375 && self_args
2376 .iter()
2377 .zip(other_args.iter())
2378 .all(|(a, b)| a.normalize_eq(b))
2379 && self_partition_by
2380 .iter()
2381 .zip(other_partition_by.iter())
2382 .all(|(a, b)| a.normalize_eq(b))
2383 && self_order_by
2384 .iter()
2385 .zip(other_order_by.iter())
2386 .all(|(a, b)| {
2387 a.asc == b.asc
2388 && a.nulls_first == b.nulls_first
2389 && a.expr.normalize_eq(&b.expr)
2390 })
2391 && self_distinct == other_distinct
2392 }
2393 (
2394 Expr::Exists(Exists {
2395 subquery: self_subquery,
2396 negated: self_negated,
2397 }),
2398 Expr::Exists(Exists {
2399 subquery: other_subquery,
2400 negated: other_negated,
2401 }),
2402 ) => {
2403 self_negated == other_negated
2404 && self_subquery.normalize_eq(other_subquery)
2405 }
2406 (
2407 Expr::InSubquery(InSubquery {
2408 expr: self_expr,
2409 subquery: self_subquery,
2410 negated: self_negated,
2411 }),
2412 Expr::InSubquery(InSubquery {
2413 expr: other_expr,
2414 subquery: other_subquery,
2415 negated: other_negated,
2416 }),
2417 ) => {
2418 self_negated == other_negated
2419 && self_expr.normalize_eq(other_expr)
2420 && self_subquery.normalize_eq(other_subquery)
2421 }
2422 (
2423 Expr::ScalarSubquery(self_subquery),
2424 Expr::ScalarSubquery(other_subquery),
2425 ) => self_subquery.normalize_eq(other_subquery),
2426 (
2427 Expr::GroupingSet(GroupingSet::Rollup(self_exprs)),
2428 Expr::GroupingSet(GroupingSet::Rollup(other_exprs)),
2429 )
2430 | (
2431 Expr::GroupingSet(GroupingSet::Cube(self_exprs)),
2432 Expr::GroupingSet(GroupingSet::Cube(other_exprs)),
2433 ) => {
2434 self_exprs.len() == other_exprs.len()
2435 && self_exprs
2436 .iter()
2437 .zip(other_exprs.iter())
2438 .all(|(a, b)| a.normalize_eq(b))
2439 }
2440 (
2441 Expr::GroupingSet(GroupingSet::GroupingSets(self_exprs)),
2442 Expr::GroupingSet(GroupingSet::GroupingSets(other_exprs)),
2443 ) => {
2444 self_exprs.len() == other_exprs.len()
2445 && self_exprs.iter().zip(other_exprs.iter()).all(|(a, b)| {
2446 a.len() == b.len()
2447 && a.iter().zip(b.iter()).all(|(x, y)| x.normalize_eq(y))
2448 })
2449 }
2450 (
2451 Expr::InList(InList {
2452 expr: self_expr,
2453 list: self_list,
2454 negated: self_negated,
2455 }),
2456 Expr::InList(InList {
2457 expr: other_expr,
2458 list: other_list,
2459 negated: other_negated,
2460 }),
2461 ) => {
2462 self_negated == other_negated
2464 && self_expr.normalize_eq(other_expr)
2465 && self_list.len() == other_list.len()
2466 && self_list
2467 .iter()
2468 .zip(other_list.iter())
2469 .all(|(a, b)| a.normalize_eq(b))
2470 }
2471 (
2472 Expr::Case(Case {
2473 expr: self_expr,
2474 when_then_expr: self_when_then_expr,
2475 else_expr: self_else_expr,
2476 }),
2477 Expr::Case(Case {
2478 expr: other_expr,
2479 when_then_expr: other_when_then_expr,
2480 else_expr: other_else_expr,
2481 }),
2482 ) => {
2483 self_when_then_expr.len() == other_when_then_expr.len()
2486 && self_when_then_expr
2487 .iter()
2488 .zip(other_when_then_expr.iter())
2489 .all(|((self_when, self_then), (other_when, other_then))| {
2490 self_when.normalize_eq(other_when)
2491 && self_then.normalize_eq(other_then)
2492 })
2493 && match (self_expr, other_expr) {
2494 (Some(self_expr), Some(other_expr)) => {
2495 self_expr.normalize_eq(other_expr)
2496 }
2497 (None, None) => true,
2498 (_, _) => false,
2499 }
2500 && match (self_else_expr, other_else_expr) {
2501 (Some(self_else_expr), Some(other_else_expr)) => {
2502 self_else_expr.normalize_eq(other_else_expr)
2503 }
2504 (None, None) => true,
2505 (_, _) => false,
2506 }
2507 }
2508 (_, _) => self == other,
2509 }
2510 }
2511}
2512
2513impl HashNode for Expr {
2514 fn hash_node<H: Hasher>(&self, state: &mut H) {
2518 mem::discriminant(self).hash(state);
2519 match self {
2520 Expr::Alias(Alias {
2521 expr: _expr,
2522 relation,
2523 name,
2524 ..
2525 }) => {
2526 relation.hash(state);
2527 name.hash(state);
2528 }
2529 Expr::Column(column) => {
2530 column.hash(state);
2531 }
2532 Expr::ScalarVariable(field, name) => {
2533 field.hash(state);
2534 name.hash(state);
2535 }
2536 Expr::Literal(scalar_value, _) => {
2537 scalar_value.hash(state);
2538 }
2539 Expr::BinaryExpr(BinaryExpr {
2540 left: _left,
2541 op,
2542 right: _right,
2543 }) => {
2544 op.hash(state);
2545 }
2546 Expr::Like(Like {
2547 negated,
2548 expr: _expr,
2549 pattern: _pattern,
2550 escape_char,
2551 case_insensitive,
2552 })
2553 | Expr::SimilarTo(Like {
2554 negated,
2555 expr: _expr,
2556 pattern: _pattern,
2557 escape_char,
2558 case_insensitive,
2559 }) => {
2560 negated.hash(state);
2561 escape_char.hash(state);
2562 case_insensitive.hash(state);
2563 }
2564 Expr::Not(_expr)
2565 | Expr::IsNotNull(_expr)
2566 | Expr::IsNull(_expr)
2567 | Expr::IsTrue(_expr)
2568 | Expr::IsFalse(_expr)
2569 | Expr::IsUnknown(_expr)
2570 | Expr::IsNotTrue(_expr)
2571 | Expr::IsNotFalse(_expr)
2572 | Expr::IsNotUnknown(_expr)
2573 | Expr::Negative(_expr) => {}
2574 Expr::Between(Between {
2575 expr: _expr,
2576 negated,
2577 low: _low,
2578 high: _high,
2579 }) => {
2580 negated.hash(state);
2581 }
2582 Expr::Case(Case {
2583 expr: _expr,
2584 when_then_expr: _when_then_expr,
2585 else_expr: _else_expr,
2586 }) => {}
2587 Expr::Cast(Cast {
2588 expr: _expr,
2589 data_type,
2590 })
2591 | Expr::TryCast(TryCast {
2592 expr: _expr,
2593 data_type,
2594 }) => {
2595 data_type.hash(state);
2596 }
2597 Expr::ScalarFunction(ScalarFunction { func, args: _args }) => {
2598 func.hash(state);
2599 }
2600 Expr::AggregateFunction(AggregateFunction {
2601 func,
2602 params:
2603 AggregateFunctionParams {
2604 args: _args,
2605 distinct,
2606 filter: _,
2607 order_by: _,
2608 null_treatment,
2609 },
2610 }) => {
2611 func.hash(state);
2612 distinct.hash(state);
2613 null_treatment.hash(state);
2614 }
2615 Expr::WindowFunction(window_fun) => {
2616 let WindowFunction {
2617 fun,
2618 params:
2619 WindowFunctionParams {
2620 args: _args,
2621 partition_by: _,
2622 order_by: _,
2623 window_frame,
2624 filter,
2625 null_treatment,
2626 distinct,
2627 },
2628 } = window_fun.as_ref();
2629 fun.hash(state);
2630 window_frame.hash(state);
2631 filter.hash(state);
2632 null_treatment.hash(state);
2633 distinct.hash(state);
2634 }
2635 Expr::InList(InList {
2636 expr: _expr,
2637 list: _list,
2638 negated,
2639 }) => {
2640 negated.hash(state);
2641 }
2642 Expr::Exists(Exists { subquery, negated }) => {
2643 subquery.hash(state);
2644 negated.hash(state);
2645 }
2646 Expr::InSubquery(InSubquery {
2647 expr: _expr,
2648 subquery,
2649 negated,
2650 }) => {
2651 subquery.hash(state);
2652 negated.hash(state);
2653 }
2654 Expr::ScalarSubquery(subquery) => {
2655 subquery.hash(state);
2656 }
2657 #[expect(deprecated)]
2658 Expr::Wildcard { qualifier, options } => {
2659 qualifier.hash(state);
2660 options.hash(state);
2661 }
2662 Expr::GroupingSet(grouping_set) => {
2663 mem::discriminant(grouping_set).hash(state);
2664 match grouping_set {
2665 GroupingSet::Rollup(_exprs) | GroupingSet::Cube(_exprs) => {}
2666 GroupingSet::GroupingSets(_exprs) => {}
2667 }
2668 }
2669 Expr::Placeholder(place_holder) => {
2670 place_holder.hash(state);
2671 }
2672 Expr::OuterReferenceColumn(field, column) => {
2673 field.hash(state);
2674 column.hash(state);
2675 }
2676 Expr::Unnest(Unnest { expr: _expr }) => {}
2677 };
2678 }
2679}
2680
2681fn rewrite_placeholder(expr: &mut Expr, other: &Expr, schema: &DFSchema) -> Result<()> {
2684 if let Expr::Placeholder(Placeholder { id: _, field }) = expr
2685 && field.is_none()
2686 {
2687 let other_field = other.to_field(schema);
2688 match other_field {
2689 Err(e) => {
2690 Err(e.context(format!(
2691 "Can not find type of {other} needed to infer type of {expr}"
2692 )))?;
2693 }
2694 Ok((_, other_field)) => {
2695 *field = Some(other_field.as_ref().clone().with_nullable(true).into());
2698 }
2699 }
2700 };
2701 Ok(())
2702}
2703
2704#[macro_export]
2705macro_rules! expr_vec_fmt {
2706 ( $ARRAY:expr ) => {{
2707 $ARRAY
2708 .iter()
2709 .map(|e| format!("{e}"))
2710 .collect::<Vec<String>>()
2711 .join(", ")
2712 }};
2713}
2714
2715struct SchemaDisplay<'a>(&'a Expr);
2716impl Display for SchemaDisplay<'_> {
2717 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2718 match self.0 {
2719 #[expect(deprecated)]
2722 Expr::Column(_)
2723 | Expr::Literal(_, _)
2724 | Expr::ScalarVariable(..)
2725 | Expr::OuterReferenceColumn(..)
2726 | Expr::Placeholder(_)
2727 | Expr::Wildcard { .. } => write!(f, "{}", self.0),
2728 Expr::AggregateFunction(AggregateFunction { func, params }) => {
2729 match func.schema_name(params) {
2730 Ok(name) => {
2731 write!(f, "{name}")
2732 }
2733 Err(e) => {
2734 write!(f, "got error from schema_name {e}")
2735 }
2736 }
2737 }
2738 Expr::Alias(Alias {
2740 name,
2741 relation: Some(relation),
2742 ..
2743 }) => write!(f, "{relation}.{name}"),
2744 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
2745 Expr::Between(Between {
2746 expr,
2747 negated,
2748 low,
2749 high,
2750 }) => {
2751 if *negated {
2752 write!(
2753 f,
2754 "{} NOT BETWEEN {} AND {}",
2755 SchemaDisplay(expr),
2756 SchemaDisplay(low),
2757 SchemaDisplay(high),
2758 )
2759 } else {
2760 write!(
2761 f,
2762 "{} BETWEEN {} AND {}",
2763 SchemaDisplay(expr),
2764 SchemaDisplay(low),
2765 SchemaDisplay(high),
2766 )
2767 }
2768 }
2769 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2770 write!(f, "{} {op} {}", SchemaDisplay(left), SchemaDisplay(right),)
2771 }
2772 Expr::Case(Case {
2773 expr,
2774 when_then_expr,
2775 else_expr,
2776 }) => {
2777 write!(f, "CASE ")?;
2778
2779 if let Some(e) = expr {
2780 write!(f, "{} ", SchemaDisplay(e))?;
2781 }
2782
2783 for (when, then) in when_then_expr {
2784 write!(
2785 f,
2786 "WHEN {} THEN {} ",
2787 SchemaDisplay(when),
2788 SchemaDisplay(then),
2789 )?;
2790 }
2791
2792 if let Some(e) = else_expr {
2793 write!(f, "ELSE {} ", SchemaDisplay(e))?;
2794 }
2795
2796 write!(f, "END")
2797 }
2798 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
2800 write!(f, "{}", SchemaDisplay(expr))
2801 }
2802 Expr::InList(InList {
2803 expr,
2804 list,
2805 negated,
2806 }) => {
2807 let inlist_name = schema_name_from_exprs(list)?;
2808
2809 if *negated {
2810 write!(f, "{} NOT IN {}", SchemaDisplay(expr), inlist_name)
2811 } else {
2812 write!(f, "{} IN {}", SchemaDisplay(expr), inlist_name)
2813 }
2814 }
2815 Expr::Exists(Exists { negated: true, .. }) => write!(f, "NOT EXISTS"),
2816 Expr::Exists(Exists { negated: false, .. }) => write!(f, "EXISTS"),
2817 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
2818 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2819 }
2820 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
2821 write!(f, "GROUPING SETS (")?;
2822 for exprs in lists_of_exprs.iter() {
2823 write!(f, "({})", schema_name_from_exprs(exprs)?)?;
2824 }
2825 write!(f, ")")
2826 }
2827 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
2828 write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2829 }
2830 Expr::IsNull(expr) => write!(f, "{} IS NULL", SchemaDisplay(expr)),
2831 Expr::IsNotNull(expr) => {
2832 write!(f, "{} IS NOT NULL", SchemaDisplay(expr))
2833 }
2834 Expr::IsUnknown(expr) => {
2835 write!(f, "{} IS UNKNOWN", SchemaDisplay(expr))
2836 }
2837 Expr::IsNotUnknown(expr) => {
2838 write!(f, "{} IS NOT UNKNOWN", SchemaDisplay(expr))
2839 }
2840 Expr::InSubquery(InSubquery { negated: true, .. }) => {
2841 write!(f, "NOT IN")
2842 }
2843 Expr::InSubquery(InSubquery { negated: false, .. }) => write!(f, "IN"),
2844 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SchemaDisplay(expr)),
2845 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SchemaDisplay(expr)),
2846 Expr::IsNotTrue(expr) => {
2847 write!(f, "{} IS NOT TRUE", SchemaDisplay(expr))
2848 }
2849 Expr::IsNotFalse(expr) => {
2850 write!(f, "{} IS NOT FALSE", SchemaDisplay(expr))
2851 }
2852 Expr::Like(Like {
2853 negated,
2854 expr,
2855 pattern,
2856 escape_char,
2857 case_insensitive,
2858 }) => {
2859 write!(
2860 f,
2861 "{} {}{} {}",
2862 SchemaDisplay(expr),
2863 if *negated { "NOT " } else { "" },
2864 if *case_insensitive { "ILIKE" } else { "LIKE" },
2865 SchemaDisplay(pattern),
2866 )?;
2867
2868 if let Some(char) = escape_char {
2869 write!(f, " CHAR '{char}'")?;
2870 }
2871
2872 Ok(())
2873 }
2874 Expr::Negative(expr) => write!(f, "(- {})", SchemaDisplay(expr)),
2875 Expr::Not(expr) => write!(f, "NOT {}", SchemaDisplay(expr)),
2876 Expr::Unnest(Unnest { expr }) => {
2877 write!(f, "UNNEST({})", SchemaDisplay(expr))
2878 }
2879 Expr::ScalarFunction(ScalarFunction { func, args }) => {
2880 match func.schema_name(args) {
2881 Ok(name) => {
2882 write!(f, "{name}")
2883 }
2884 Err(e) => {
2885 write!(f, "got error from schema_name {e}")
2886 }
2887 }
2888 }
2889 Expr::ScalarSubquery(Subquery { subquery, .. }) => {
2890 write!(f, "{}", subquery.schema().field(0).name())
2891 }
2892 Expr::SimilarTo(Like {
2893 negated,
2894 expr,
2895 pattern,
2896 escape_char,
2897 ..
2898 }) => {
2899 write!(
2900 f,
2901 "{} {} {}",
2902 SchemaDisplay(expr),
2903 if *negated {
2904 "NOT SIMILAR TO"
2905 } else {
2906 "SIMILAR TO"
2907 },
2908 SchemaDisplay(pattern),
2909 )?;
2910 if let Some(char) = escape_char {
2911 write!(f, " CHAR '{char}'")?;
2912 }
2913
2914 Ok(())
2915 }
2916 Expr::WindowFunction(window_fun) => {
2917 let WindowFunction { fun, params } = window_fun.as_ref();
2918 match fun {
2919 WindowFunctionDefinition::AggregateUDF(fun) => {
2920 match fun.window_function_schema_name(params) {
2921 Ok(name) => {
2922 write!(f, "{name}")
2923 }
2924 Err(e) => {
2925 write!(
2926 f,
2927 "got error from window_function_schema_name {e}"
2928 )
2929 }
2930 }
2931 }
2932 _ => {
2933 let WindowFunctionParams {
2934 args,
2935 partition_by,
2936 order_by,
2937 window_frame,
2938 filter,
2939 null_treatment,
2940 distinct,
2941 } = params;
2942
2943 write!(f, "{fun}(")?;
2945
2946 if *distinct {
2948 write!(f, "DISTINCT ")?;
2949 }
2950
2951 write!(
2953 f,
2954 "{}",
2955 schema_name_from_exprs_comma_separated_without_space(args)?
2956 )?;
2957
2958 write!(f, ")")?;
2960
2961 if let Some(null_treatment) = null_treatment {
2962 write!(f, " {null_treatment}")?;
2963 }
2964
2965 if let Some(filter) = filter {
2966 write!(f, " FILTER (WHERE {filter})")?;
2967 }
2968
2969 if !partition_by.is_empty() {
2970 write!(
2971 f,
2972 " PARTITION BY [{}]",
2973 schema_name_from_exprs(partition_by)?
2974 )?;
2975 }
2976
2977 if !order_by.is_empty() {
2978 write!(
2979 f,
2980 " ORDER BY [{}]",
2981 schema_name_from_sorts(order_by)?
2982 )?;
2983 };
2984
2985 write!(f, " {window_frame}")
2986 }
2987 }
2988 }
2989 }
2990 }
2991}
2992
2993struct SqlDisplay<'a>(&'a Expr);
2995
2996impl Display for SqlDisplay<'_> {
2997 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2998 match self.0 {
2999 Expr::Literal(scalar, _) => scalar.fmt(f),
3000 Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
3001 Expr::Between(Between {
3002 expr,
3003 negated,
3004 low,
3005 high,
3006 }) => {
3007 if *negated {
3008 write!(
3009 f,
3010 "{} NOT BETWEEN {} AND {}",
3011 SqlDisplay(expr),
3012 SqlDisplay(low),
3013 SqlDisplay(high),
3014 )
3015 } else {
3016 write!(
3017 f,
3018 "{} BETWEEN {} AND {}",
3019 SqlDisplay(expr),
3020 SqlDisplay(low),
3021 SqlDisplay(high),
3022 )
3023 }
3024 }
3025 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
3026 write!(f, "{} {op} {}", SqlDisplay(left), SqlDisplay(right),)
3027 }
3028 Expr::Case(Case {
3029 expr,
3030 when_then_expr,
3031 else_expr,
3032 }) => {
3033 write!(f, "CASE ")?;
3034
3035 if let Some(e) = expr {
3036 write!(f, "{} ", SqlDisplay(e))?;
3037 }
3038
3039 for (when, then) in when_then_expr {
3040 write!(f, "WHEN {} THEN {} ", SqlDisplay(when), SqlDisplay(then),)?;
3041 }
3042
3043 if let Some(e) = else_expr {
3044 write!(f, "ELSE {} ", SqlDisplay(e))?;
3045 }
3046
3047 write!(f, "END")
3048 }
3049 Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
3050 write!(f, "{}", SqlDisplay(expr))
3051 }
3052 Expr::InList(InList {
3053 expr,
3054 list,
3055 negated,
3056 }) => {
3057 write!(
3058 f,
3059 "{}{} IN {}",
3060 SqlDisplay(expr),
3061 if *negated { " NOT" } else { "" },
3062 ExprListDisplay::comma_separated(list.as_slice())
3063 )
3064 }
3065 Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
3066 write!(
3067 f,
3068 "ROLLUP ({})",
3069 ExprListDisplay::comma_separated(exprs.as_slice())
3070 )
3071 }
3072 Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
3073 write!(f, "GROUPING SETS (")?;
3074 for exprs in lists_of_exprs.iter() {
3075 write!(
3076 f,
3077 "({})",
3078 ExprListDisplay::comma_separated(exprs.as_slice())
3079 )?;
3080 }
3081 write!(f, ")")
3082 }
3083 Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
3084 write!(
3085 f,
3086 "ROLLUP ({})",
3087 ExprListDisplay::comma_separated(exprs.as_slice())
3088 )
3089 }
3090 Expr::IsNull(expr) => write!(f, "{} IS NULL", SqlDisplay(expr)),
3091 Expr::IsNotNull(expr) => {
3092 write!(f, "{} IS NOT NULL", SqlDisplay(expr))
3093 }
3094 Expr::IsUnknown(expr) => {
3095 write!(f, "{} IS UNKNOWN", SqlDisplay(expr))
3096 }
3097 Expr::IsNotUnknown(expr) => {
3098 write!(f, "{} IS NOT UNKNOWN", SqlDisplay(expr))
3099 }
3100 Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SqlDisplay(expr)),
3101 Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SqlDisplay(expr)),
3102 Expr::IsNotTrue(expr) => {
3103 write!(f, "{} IS NOT TRUE", SqlDisplay(expr))
3104 }
3105 Expr::IsNotFalse(expr) => {
3106 write!(f, "{} IS NOT FALSE", SqlDisplay(expr))
3107 }
3108 Expr::Like(Like {
3109 negated,
3110 expr,
3111 pattern,
3112 escape_char,
3113 case_insensitive,
3114 }) => {
3115 write!(
3116 f,
3117 "{} {}{} {}",
3118 SqlDisplay(expr),
3119 if *negated { "NOT " } else { "" },
3120 if *case_insensitive { "ILIKE" } else { "LIKE" },
3121 SqlDisplay(pattern),
3122 )?;
3123
3124 if let Some(char) = escape_char {
3125 write!(f, " CHAR '{char}'")?;
3126 }
3127
3128 Ok(())
3129 }
3130 Expr::Negative(expr) => write!(f, "(- {})", SqlDisplay(expr)),
3131 Expr::Not(expr) => write!(f, "NOT {}", SqlDisplay(expr)),
3132 Expr::Unnest(Unnest { expr }) => {
3133 write!(f, "UNNEST({})", SqlDisplay(expr))
3134 }
3135 Expr::SimilarTo(Like {
3136 negated,
3137 expr,
3138 pattern,
3139 escape_char,
3140 ..
3141 }) => {
3142 write!(
3143 f,
3144 "{} {} {}",
3145 SqlDisplay(expr),
3146 if *negated {
3147 "NOT SIMILAR TO"
3148 } else {
3149 "SIMILAR TO"
3150 },
3151 SqlDisplay(pattern),
3152 )?;
3153 if let Some(char) = escape_char {
3154 write!(f, " CHAR '{char}'")?;
3155 }
3156
3157 Ok(())
3158 }
3159 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3160 match func.human_display(params) {
3161 Ok(name) => {
3162 write!(f, "{name}")
3163 }
3164 Err(e) => {
3165 write!(f, "got error from schema_name {e}")
3166 }
3167 }
3168 }
3169 _ => write!(f, "{}", self.0),
3170 }
3171 }
3172}
3173
3174pub(crate) fn schema_name_from_exprs_comma_separated_without_space(
3180 exprs: &[Expr],
3181) -> Result<String, fmt::Error> {
3182 schema_name_from_exprs_inner(exprs, ",")
3183}
3184
3185pub struct ExprListDisplay<'a> {
3187 exprs: &'a [Expr],
3188 sep: &'a str,
3189}
3190
3191impl<'a> ExprListDisplay<'a> {
3192 pub fn new(exprs: &'a [Expr], sep: &'a str) -> Self {
3194 Self { exprs, sep }
3195 }
3196
3197 pub fn comma_separated(exprs: &'a [Expr]) -> Self {
3199 Self::new(exprs, ", ")
3200 }
3201}
3202
3203impl Display for ExprListDisplay<'_> {
3204 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3205 let mut first = true;
3206 for expr in self.exprs {
3207 if !first {
3208 write!(f, "{}", self.sep)?;
3209 }
3210 write!(f, "{}", SqlDisplay(expr))?;
3211 first = false;
3212 }
3213 Ok(())
3214 }
3215}
3216
3217pub fn schema_name_from_exprs(exprs: &[Expr]) -> Result<String, fmt::Error> {
3219 schema_name_from_exprs_inner(exprs, ", ")
3220}
3221
3222fn schema_name_from_exprs_inner(exprs: &[Expr], sep: &str) -> Result<String, fmt::Error> {
3223 let mut s = String::new();
3224 for (i, e) in exprs.iter().enumerate() {
3225 if i > 0 {
3226 write!(&mut s, "{sep}")?;
3227 }
3228 write!(&mut s, "{}", SchemaDisplay(e))?;
3229 }
3230
3231 Ok(s)
3232}
3233
3234pub fn schema_name_from_sorts(sorts: &[Sort]) -> Result<String, fmt::Error> {
3235 let mut s = String::new();
3236 for (i, e) in sorts.iter().enumerate() {
3237 if i > 0 {
3238 write!(&mut s, ", ")?;
3239 }
3240 let ordering = if e.asc { "ASC" } else { "DESC" };
3241 let nulls_ordering = if e.nulls_first {
3242 "NULLS FIRST"
3243 } else {
3244 "NULLS LAST"
3245 };
3246 write!(&mut s, "{} {} {}", e.expr, ordering, nulls_ordering)?;
3247 }
3248
3249 Ok(s)
3250}
3251
3252pub const OUTER_REFERENCE_COLUMN_PREFIX: &str = "outer_ref";
3253pub const UNNEST_COLUMN_PREFIX: &str = "UNNEST";
3254
3255impl Display for Expr {
3258 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3259 match self {
3260 Expr::Alias(Alias { expr, name, .. }) => write!(f, "{expr} AS {name}"),
3261 Expr::Column(c) => write!(f, "{c}"),
3262 Expr::OuterReferenceColumn(_, c) => {
3263 write!(f, "{OUTER_REFERENCE_COLUMN_PREFIX}({c})")
3264 }
3265 Expr::ScalarVariable(_, var_names) => write!(f, "{}", var_names.join(".")),
3266 Expr::Literal(v, metadata) => {
3267 match metadata.as_ref().map(|m| m.is_empty()).unwrap_or(true) {
3268 false => write!(f, "{v:?} {:?}", metadata.as_ref().unwrap()),
3269 true => write!(f, "{v:?}"),
3270 }
3271 }
3272 Expr::Case(case) => {
3273 write!(f, "CASE ")?;
3274 if let Some(e) = &case.expr {
3275 write!(f, "{e} ")?;
3276 }
3277 for (w, t) in &case.when_then_expr {
3278 write!(f, "WHEN {w} THEN {t} ")?;
3279 }
3280 if let Some(e) = &case.else_expr {
3281 write!(f, "ELSE {e} ")?;
3282 }
3283 write!(f, "END")
3284 }
3285 Expr::Cast(Cast { expr, data_type }) => {
3286 write!(f, "CAST({expr} AS {data_type})")
3287 }
3288 Expr::TryCast(TryCast { expr, data_type }) => {
3289 write!(f, "TRY_CAST({expr} AS {data_type})")
3290 }
3291 Expr::Not(expr) => write!(f, "NOT {expr}"),
3292 Expr::Negative(expr) => write!(f, "(- {expr})"),
3293 Expr::IsNull(expr) => write!(f, "{expr} IS NULL"),
3294 Expr::IsNotNull(expr) => write!(f, "{expr} IS NOT NULL"),
3295 Expr::IsTrue(expr) => write!(f, "{expr} IS TRUE"),
3296 Expr::IsFalse(expr) => write!(f, "{expr} IS FALSE"),
3297 Expr::IsUnknown(expr) => write!(f, "{expr} IS UNKNOWN"),
3298 Expr::IsNotTrue(expr) => write!(f, "{expr} IS NOT TRUE"),
3299 Expr::IsNotFalse(expr) => write!(f, "{expr} IS NOT FALSE"),
3300 Expr::IsNotUnknown(expr) => write!(f, "{expr} IS NOT UNKNOWN"),
3301 Expr::Exists(Exists {
3302 subquery,
3303 negated: true,
3304 }) => write!(f, "NOT EXISTS ({subquery:?})"),
3305 Expr::Exists(Exists {
3306 subquery,
3307 negated: false,
3308 }) => write!(f, "EXISTS ({subquery:?})"),
3309 Expr::InSubquery(InSubquery {
3310 expr,
3311 subquery,
3312 negated: true,
3313 }) => write!(f, "{expr} NOT IN ({subquery:?})"),
3314 Expr::InSubquery(InSubquery {
3315 expr,
3316 subquery,
3317 negated: false,
3318 }) => write!(f, "{expr} IN ({subquery:?})"),
3319 Expr::ScalarSubquery(subquery) => write!(f, "({subquery:?})"),
3320 Expr::BinaryExpr(expr) => write!(f, "{expr}"),
3321 Expr::ScalarFunction(fun) => {
3322 fmt_function(f, fun.name(), false, &fun.args, true)
3323 }
3324 Expr::WindowFunction(window_fun) => {
3325 let WindowFunction { fun, params } = window_fun.as_ref();
3326 match fun {
3327 WindowFunctionDefinition::AggregateUDF(fun) => {
3328 match fun.window_function_display_name(params) {
3329 Ok(name) => {
3330 write!(f, "{name}")
3331 }
3332 Err(e) => {
3333 write!(
3334 f,
3335 "got error from window_function_display_name {e}"
3336 )
3337 }
3338 }
3339 }
3340 WindowFunctionDefinition::WindowUDF(fun) => {
3341 let WindowFunctionParams {
3342 args,
3343 partition_by,
3344 order_by,
3345 window_frame,
3346 filter,
3347 null_treatment,
3348 distinct,
3349 } = params;
3350
3351 fmt_function(f, &fun.to_string(), *distinct, args, true)?;
3352
3353 if let Some(nt) = null_treatment {
3354 write!(f, "{nt}")?;
3355 }
3356
3357 if let Some(fe) = filter {
3358 write!(f, " FILTER (WHERE {fe})")?;
3359 }
3360
3361 if !partition_by.is_empty() {
3362 write!(f, " PARTITION BY [{}]", expr_vec_fmt!(partition_by))?;
3363 }
3364 if !order_by.is_empty() {
3365 write!(f, " ORDER BY [{}]", expr_vec_fmt!(order_by))?;
3366 }
3367 write!(
3368 f,
3369 " {} BETWEEN {} AND {}",
3370 window_frame.units,
3371 window_frame.start_bound,
3372 window_frame.end_bound
3373 )
3374 }
3375 }
3376 }
3377 Expr::AggregateFunction(AggregateFunction { func, params }) => {
3378 match func.display_name(params) {
3379 Ok(name) => {
3380 write!(f, "{name}")
3381 }
3382 Err(e) => {
3383 write!(f, "got error from display_name {e}")
3384 }
3385 }
3386 }
3387 Expr::Between(Between {
3388 expr,
3389 negated,
3390 low,
3391 high,
3392 }) => {
3393 if *negated {
3394 write!(f, "{expr} NOT BETWEEN {low} AND {high}")
3395 } else {
3396 write!(f, "{expr} BETWEEN {low} AND {high}")
3397 }
3398 }
3399 Expr::Like(Like {
3400 negated,
3401 expr,
3402 pattern,
3403 escape_char,
3404 case_insensitive,
3405 }) => {
3406 write!(f, "{expr}")?;
3407 let op_name = if *case_insensitive { "ILIKE" } else { "LIKE" };
3408 if *negated {
3409 write!(f, " NOT")?;
3410 }
3411 if let Some(char) = escape_char {
3412 write!(f, " {op_name} {pattern} ESCAPE '{char}'")
3413 } else {
3414 write!(f, " {op_name} {pattern}")
3415 }
3416 }
3417 Expr::SimilarTo(Like {
3418 negated,
3419 expr,
3420 pattern,
3421 escape_char,
3422 case_insensitive: _,
3423 }) => {
3424 write!(f, "{expr}")?;
3425 if *negated {
3426 write!(f, " NOT")?;
3427 }
3428 if let Some(char) = escape_char {
3429 write!(f, " SIMILAR TO {pattern} ESCAPE '{char}'")
3430 } else {
3431 write!(f, " SIMILAR TO {pattern}")
3432 }
3433 }
3434 Expr::InList(InList {
3435 expr,
3436 list,
3437 negated,
3438 }) => {
3439 if *negated {
3440 write!(f, "{expr} NOT IN ([{}])", expr_vec_fmt!(list))
3441 } else {
3442 write!(f, "{expr} IN ([{}])", expr_vec_fmt!(list))
3443 }
3444 }
3445 #[expect(deprecated)]
3446 Expr::Wildcard { qualifier, options } => match qualifier {
3447 Some(qualifier) => write!(f, "{qualifier}.*{options}"),
3448 None => write!(f, "*{options}"),
3449 },
3450 Expr::GroupingSet(grouping_sets) => match grouping_sets {
3451 GroupingSet::Rollup(exprs) => {
3452 write!(f, "ROLLUP ({})", expr_vec_fmt!(exprs))
3454 }
3455 GroupingSet::Cube(exprs) => {
3456 write!(f, "CUBE ({})", expr_vec_fmt!(exprs))
3458 }
3459 GroupingSet::GroupingSets(lists_of_exprs) => {
3460 write!(
3462 f,
3463 "GROUPING SETS ({})",
3464 lists_of_exprs
3465 .iter()
3466 .map(|exprs| format!("({})", expr_vec_fmt!(exprs)))
3467 .collect::<Vec<String>>()
3468 .join(", ")
3469 )
3470 }
3471 },
3472 Expr::Placeholder(Placeholder { id, .. }) => write!(f, "{id}"),
3473 Expr::Unnest(Unnest { expr }) => {
3474 write!(f, "{UNNEST_COLUMN_PREFIX}({expr})")
3475 }
3476 }
3477 }
3478}
3479
3480fn fmt_function(
3481 f: &mut Formatter,
3482 fun: &str,
3483 distinct: bool,
3484 args: &[Expr],
3485 display: bool,
3486) -> fmt::Result {
3487 let args: Vec<String> = match display {
3488 true => args.iter().map(|arg| format!("{arg}")).collect(),
3489 false => args.iter().map(|arg| format!("{arg:?}")).collect(),
3490 };
3491
3492 let distinct_str = match distinct {
3493 true => "DISTINCT ",
3494 false => "",
3495 };
3496 write!(f, "{}({}{})", fun, distinct_str, args.join(", "))
3497}
3498
3499pub fn physical_name(expr: &Expr) -> Result<String> {
3502 match expr {
3503 Expr::Column(col) => Ok(col.name.clone()),
3504 Expr::Alias(alias) => Ok(alias.name.clone()),
3505 _ => Ok(expr.schema_name().to_string()),
3506 }
3507}
3508
3509#[cfg(test)]
3510mod test {
3511 use crate::expr_fn::col;
3512 use crate::{
3513 ColumnarValue, ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl, Volatility, case,
3514 lit, placeholder, qualified_wildcard, wildcard, wildcard_with_options,
3515 };
3516 use arrow::datatypes::{Field, Schema};
3517 use sqlparser::ast;
3518 use sqlparser::ast::{Ident, IdentWithAlias};
3519 use std::any::Any;
3520
3521 #[test]
3522 fn infer_placeholder_in_clause() {
3523 let column = col("department_id");
3525 let param_placeholders = vec![
3526 Expr::Placeholder(Placeholder {
3527 id: "$1".to_string(),
3528 field: None,
3529 }),
3530 Expr::Placeholder(Placeholder {
3531 id: "$2".to_string(),
3532 field: None,
3533 }),
3534 Expr::Placeholder(Placeholder {
3535 id: "$3".to_string(),
3536 field: None,
3537 }),
3538 ];
3539 let in_list = Expr::InList(InList {
3540 expr: Box::new(column),
3541 list: param_placeholders,
3542 negated: false,
3543 });
3544
3545 let schema = Arc::new(Schema::new(vec![
3546 Field::new("name", DataType::Utf8, true),
3547 Field::new("department_id", DataType::Int32, true),
3548 ]));
3549 let df_schema = DFSchema::try_from(schema).unwrap();
3550
3551 let (inferred_expr, contains_placeholder) =
3552 in_list.infer_placeholder_types(&df_schema).unwrap();
3553
3554 assert!(contains_placeholder);
3555
3556 match inferred_expr {
3557 Expr::InList(in_list) => {
3558 for expr in in_list.list {
3559 match expr {
3560 Expr::Placeholder(placeholder) => {
3561 assert_eq!(
3562 placeholder.field.unwrap().data_type(),
3563 &DataType::Int32,
3564 "Placeholder {} should infer Int32",
3565 placeholder.id
3566 );
3567 }
3568 _ => panic!("Expected Placeholder expression"),
3569 }
3570 }
3571 }
3572 _ => panic!("Expected InList expression"),
3573 }
3574 }
3575
3576 #[test]
3577 fn infer_placeholder_like_and_similar_to() {
3578 let schema =
3580 Arc::new(Schema::new(vec![Field::new("name", DataType::Utf8, true)]));
3581 let df_schema = DFSchema::try_from(schema).unwrap();
3582
3583 let like = Like {
3584 expr: Box::new(col("name")),
3585 pattern: Box::new(Expr::Placeholder(Placeholder {
3586 id: "$1".to_string(),
3587 field: None,
3588 })),
3589 negated: false,
3590 case_insensitive: false,
3591 escape_char: None,
3592 };
3593
3594 let expr = Expr::Like(like.clone());
3595
3596 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3597 match inferred_expr {
3598 Expr::Like(like) => match *like.pattern {
3599 Expr::Placeholder(placeholder) => {
3600 assert_eq!(placeholder.field.unwrap().data_type(), &DataType::Utf8);
3601 }
3602 _ => panic!("Expected Placeholder"),
3603 },
3604 _ => panic!("Expected Like"),
3605 }
3606
3607 let expr = Expr::SimilarTo(like);
3609
3610 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3611 match inferred_expr {
3612 Expr::SimilarTo(like) => match *like.pattern {
3613 Expr::Placeholder(placeholder) => {
3614 assert_eq!(
3615 placeholder.field.unwrap().data_type(),
3616 &DataType::Utf8,
3617 "Placeholder {} should infer Utf8",
3618 placeholder.id
3619 );
3620 }
3621 _ => panic!("Expected Placeholder expression"),
3622 },
3623 _ => panic!("Expected SimilarTo expression"),
3624 }
3625 }
3626
3627 #[test]
3628 fn infer_placeholder_with_metadata() {
3629 let schema = Arc::new(Schema::new(vec![
3631 Field::new("name", DataType::Utf8, false).with_metadata(
3632 [("some_key".to_string(), "some_value".to_string())].into(),
3633 ),
3634 ]));
3635 let df_schema = DFSchema::try_from(schema).unwrap();
3636
3637 let expr = binary_expr(col("name"), Operator::Eq, placeholder("$1"));
3638
3639 let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3640 match inferred_expr {
3641 Expr::BinaryExpr(BinaryExpr { right, .. }) => match *right {
3642 Expr::Placeholder(placeholder) => {
3643 assert_eq!(
3644 placeholder.field.as_ref().unwrap().data_type(),
3645 &DataType::Utf8
3646 );
3647 assert_eq!(
3648 placeholder.field.as_ref().unwrap().metadata(),
3649 df_schema.field(0).metadata()
3650 );
3651 assert!(placeholder.field.as_ref().unwrap().is_nullable());
3653 }
3654 _ => panic!("Expected Placeholder"),
3655 },
3656 _ => panic!("Expected BinaryExpr"),
3657 }
3658 }
3659
3660 #[test]
3661 fn format_case_when() -> Result<()> {
3662 let expr = case(col("a"))
3663 .when(lit(1), lit(true))
3664 .when(lit(0), lit(false))
3665 .otherwise(lit(ScalarValue::Null))?;
3666 let expected = "CASE a WHEN Int32(1) THEN Boolean(true) WHEN Int32(0) THEN Boolean(false) ELSE NULL END";
3667 assert_eq!(expected, format!("{expr}"));
3668 Ok(())
3669 }
3670
3671 #[test]
3672 fn format_cast() -> Result<()> {
3673 let expr = Expr::Cast(Cast {
3674 expr: Box::new(Expr::Literal(ScalarValue::Float32(Some(1.23)), None)),
3675 data_type: DataType::Utf8,
3676 });
3677 let expected_canonical = "CAST(Float32(1.23) AS Utf8)";
3678 assert_eq!(expected_canonical, format!("{expr}"));
3679 assert_eq!("Float32(1.23)", expr.schema_name().to_string());
3682 Ok(())
3683 }
3684
3685 #[test]
3686 fn test_partial_ord() {
3687 let exp1 = col("a") + lit(1);
3690 let exp2 = col("a") + lit(2);
3691 let exp3 = !(col("a") + lit(2));
3692
3693 assert!(exp1 < exp2);
3694 assert!(exp3 > exp2);
3695 assert!(exp1 < exp3)
3696 }
3697
3698 #[test]
3699 fn test_collect_expr() -> Result<()> {
3700 {
3702 let expr = &Expr::Cast(Cast::new(Box::new(col("a")), DataType::Float64));
3703 let columns = expr.column_refs();
3704 assert_eq!(1, columns.len());
3705 assert!(columns.contains(&Column::from_name("a")));
3706 }
3707
3708 {
3710 let expr = col("a") + col("b") + lit(1);
3711 let columns = expr.column_refs();
3712 assert_eq!(2, columns.len());
3713 assert!(columns.contains(&Column::from_name("a")));
3714 assert!(columns.contains(&Column::from_name("b")));
3715 }
3716
3717 Ok(())
3718 }
3719
3720 #[test]
3721 fn test_logical_ops() {
3722 assert_eq!(
3723 format!("{}", lit(1u32).eq(lit(2u32))),
3724 "UInt32(1) = UInt32(2)"
3725 );
3726 assert_eq!(
3727 format!("{}", lit(1u32).not_eq(lit(2u32))),
3728 "UInt32(1) != UInt32(2)"
3729 );
3730 assert_eq!(
3731 format!("{}", lit(1u32).gt(lit(2u32))),
3732 "UInt32(1) > UInt32(2)"
3733 );
3734 assert_eq!(
3735 format!("{}", lit(1u32).gt_eq(lit(2u32))),
3736 "UInt32(1) >= UInt32(2)"
3737 );
3738 assert_eq!(
3739 format!("{}", lit(1u32).lt(lit(2u32))),
3740 "UInt32(1) < UInt32(2)"
3741 );
3742 assert_eq!(
3743 format!("{}", lit(1u32).lt_eq(lit(2u32))),
3744 "UInt32(1) <= UInt32(2)"
3745 );
3746 assert_eq!(
3747 format!("{}", lit(1u32).and(lit(2u32))),
3748 "UInt32(1) AND UInt32(2)"
3749 );
3750 assert_eq!(
3751 format!("{}", lit(1u32).or(lit(2u32))),
3752 "UInt32(1) OR UInt32(2)"
3753 );
3754 }
3755
3756 #[test]
3757 fn test_is_volatile_scalar_func() {
3758 #[derive(Debug, PartialEq, Eq, Hash)]
3760 struct TestScalarUDF {
3761 signature: Signature,
3762 }
3763 impl ScalarUDFImpl for TestScalarUDF {
3764 fn as_any(&self) -> &dyn Any {
3765 self
3766 }
3767 fn name(&self) -> &str {
3768 "TestScalarUDF"
3769 }
3770
3771 fn signature(&self) -> &Signature {
3772 &self.signature
3773 }
3774
3775 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
3776 Ok(DataType::Utf8)
3777 }
3778
3779 fn invoke_with_args(
3780 &self,
3781 _args: ScalarFunctionArgs,
3782 ) -> Result<ColumnarValue> {
3783 Ok(ColumnarValue::Scalar(ScalarValue::from("a")))
3784 }
3785 }
3786 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3787 signature: Signature::uniform(1, vec![DataType::Float32], Volatility::Stable),
3788 }));
3789 assert_ne!(udf.signature().volatility, Volatility::Volatile);
3790
3791 let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3792 signature: Signature::uniform(
3793 1,
3794 vec![DataType::Float32],
3795 Volatility::Volatile,
3796 ),
3797 }));
3798 assert_eq!(udf.signature().volatility, Volatility::Volatile);
3799 }
3800
3801 use super::*;
3802
3803 #[test]
3804 fn test_display_wildcard() {
3805 assert_eq!(format!("{}", wildcard()), "*");
3806 assert_eq!(format!("{}", qualified_wildcard("t1")), "t1.*");
3807 assert_eq!(
3808 format!(
3809 "{}",
3810 wildcard_with_options(wildcard_options(
3811 Some(IlikeSelectItem {
3812 pattern: "c1".to_string()
3813 }),
3814 None,
3815 None,
3816 None,
3817 None
3818 ))
3819 ),
3820 "* ILIKE 'c1'"
3821 );
3822 assert_eq!(
3823 format!(
3824 "{}",
3825 wildcard_with_options(wildcard_options(
3826 None,
3827 Some(ExcludeSelectItem::Multiple(vec![
3828 Ident::from("c1"),
3829 Ident::from("c2")
3830 ])),
3831 None,
3832 None,
3833 None
3834 ))
3835 ),
3836 "* EXCLUDE (c1, c2)"
3837 );
3838 assert_eq!(
3839 format!(
3840 "{}",
3841 wildcard_with_options(wildcard_options(
3842 None,
3843 None,
3844 Some(ExceptSelectItem {
3845 first_element: Ident::from("c1"),
3846 additional_elements: vec![Ident::from("c2")]
3847 }),
3848 None,
3849 None
3850 ))
3851 ),
3852 "* EXCEPT (c1, c2)"
3853 );
3854 assert_eq!(
3855 format!(
3856 "{}",
3857 wildcard_with_options(wildcard_options(
3858 None,
3859 None,
3860 None,
3861 Some(PlannedReplaceSelectItem {
3862 items: vec![ReplaceSelectElement {
3863 expr: ast::Expr::Identifier(Ident::from("c1")),
3864 column_name: Ident::from("a1"),
3865 as_keyword: false
3866 }],
3867 planned_expressions: vec![]
3868 }),
3869 None
3870 ))
3871 ),
3872 "* REPLACE (c1 a1)"
3873 );
3874 assert_eq!(
3875 format!(
3876 "{}",
3877 wildcard_with_options(wildcard_options(
3878 None,
3879 None,
3880 None,
3881 None,
3882 Some(RenameSelectItem::Multiple(vec![IdentWithAlias {
3883 ident: Ident::from("c1"),
3884 alias: Ident::from("a1")
3885 }]))
3886 ))
3887 ),
3888 "* RENAME (c1 AS a1)"
3889 )
3890 }
3891
3892 #[test]
3893 fn test_schema_display_alias_with_relation() {
3894 assert_eq!(
3895 format!(
3896 "{}",
3897 SchemaDisplay(
3898 &lit(1).alias_qualified("table_name".into(), "column_name")
3899 )
3900 ),
3901 "table_name.column_name"
3902 );
3903 }
3904
3905 #[test]
3906 fn test_schema_display_alias_without_relation() {
3907 assert_eq!(
3908 format!(
3909 "{}",
3910 SchemaDisplay(&lit(1).alias_qualified(None::<&str>, "column_name"))
3911 ),
3912 "column_name"
3913 );
3914 }
3915
3916 fn wildcard_options(
3917 opt_ilike: Option<IlikeSelectItem>,
3918 opt_exclude: Option<ExcludeSelectItem>,
3919 opt_except: Option<ExceptSelectItem>,
3920 opt_replace: Option<PlannedReplaceSelectItem>,
3921 opt_rename: Option<RenameSelectItem>,
3922 ) -> WildcardOptions {
3923 WildcardOptions {
3924 ilike: opt_ilike,
3925 exclude: opt_exclude,
3926 except: opt_except,
3927 replace: opt_replace,
3928 rename: opt_rename,
3929 }
3930 }
3931
3932 #[test]
3933 fn test_size_of_expr() {
3934 assert_eq!(size_of::<Expr>(), 112);
3941 assert_eq!(size_of::<ScalarValue>(), 64);
3942 assert_eq!(size_of::<DataType>(), 24); assert_eq!(size_of::<Vec<Expr>>(), 24);
3944 assert_eq!(size_of::<Arc<Expr>>(), 8);
3945 }
3946
3947 #[test]
3948 fn test_accept_exprs() {
3949 fn accept_exprs<E: AsRef<Expr>>(_: &[E]) {}
3950
3951 let expr = || -> Expr { lit(1) };
3952
3953 let owned_exprs = vec![expr(), expr()];
3955 accept_exprs(&owned_exprs);
3956
3957 let udf = Expr::ScalarFunction(ScalarFunction {
3959 func: Arc::new(ScalarUDF::new_from_impl(TestUDF {})),
3960 args: vec![expr(), expr()],
3961 });
3962 let Expr::ScalarFunction(scalar) = &udf else {
3963 unreachable!()
3964 };
3965 accept_exprs(&scalar.args);
3966
3967 let mut collected_refs: Vec<&Expr> = scalar.args.iter().collect();
3969 collected_refs.extend(&owned_exprs);
3970 accept_exprs(&collected_refs);
3971
3972 #[derive(Debug, PartialEq, Eq, Hash)]
3974 struct TestUDF {}
3975 impl ScalarUDFImpl for TestUDF {
3976 fn as_any(&self) -> &dyn Any {
3977 unimplemented!()
3978 }
3979
3980 fn name(&self) -> &str {
3981 unimplemented!()
3982 }
3983
3984 fn signature(&self) -> &Signature {
3985 unimplemented!()
3986 }
3987
3988 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
3989 unimplemented!()
3990 }
3991
3992 fn invoke_with_args(
3993 &self,
3994 _args: ScalarFunctionArgs,
3995 ) -> Result<ColumnarValue> {
3996 unimplemented!()
3997 }
3998 }
3999 }
4000}