1use std::sync::Arc;
7
8use vortex_error::VortexExpect;
9use vortex_error::vortex_panic;
10use vortex_utils::iter::ReduceBalancedIterExt;
11
12use crate::aggregate_fn::NumericalAggregateOpts;
13use crate::dtype::DType;
14use crate::dtype::FieldName;
15use crate::dtype::FieldNames;
16use crate::dtype::Nullability;
17use crate::expr::BoundExpression;
18use crate::expr::Expression;
19use crate::scalar::Scalar;
20use crate::scalar::ScalarValue;
21use crate::scalar_fn::EmptyOptions;
22use crate::scalar_fn::ScalarFnVTableExt;
23use crate::scalar_fn::fns::between::Between;
24use crate::scalar_fn::fns::between::BetweenOptions;
25use crate::scalar_fn::fns::binary::Binary;
26use crate::scalar_fn::fns::byte_length::ByteLength;
27use crate::scalar_fn::fns::case_when::CaseWhen;
28use crate::scalar_fn::fns::case_when::CaseWhenOptions;
29use crate::scalar_fn::fns::cast::Cast;
30use crate::scalar_fn::fns::dynamic::DynamicComparison;
31use crate::scalar_fn::fns::dynamic::DynamicComparisonExpr;
32use crate::scalar_fn::fns::dynamic::Rhs;
33use crate::scalar_fn::fns::ext_storage::ExtStorage;
34use crate::scalar_fn::fns::fill_null::FillNull;
35use crate::scalar_fn::fns::get_item::GetItem;
36use crate::scalar_fn::fns::is_nan::IsNan;
37use crate::scalar_fn::fns::is_not_null::IsNotNull;
38use crate::scalar_fn::fns::is_null::IsNull;
39use crate::scalar_fn::fns::like::Like;
40use crate::scalar_fn::fns::like::LikeOptions;
41use crate::scalar_fn::fns::list_contains::ListContains;
42use crate::scalar_fn::fns::list_contains::ListContainsOptions;
43use crate::scalar_fn::fns::list_length::ListLength;
44use crate::scalar_fn::fns::list_sum::ListSum;
45use crate::scalar_fn::fns::literal::Literal;
46use crate::scalar_fn::fns::mask::Mask;
47use crate::scalar_fn::fns::merge::DuplicateHandling;
48use crate::scalar_fn::fns::merge::Merge;
49use crate::scalar_fn::fns::not::Not;
50use crate::scalar_fn::fns::operators::CompareOperator;
51use crate::scalar_fn::fns::operators::Operator;
52use crate::scalar_fn::fns::pack::Pack;
53use crate::scalar_fn::fns::pack::PackOptions;
54use crate::scalar_fn::fns::select::FieldSelection;
55use crate::scalar_fn::fns::select::Select;
56use crate::scalar_fn::fns::variant_get::VariantGet;
57use crate::scalar_fn::fns::variant_get::VariantGetOptions;
58use crate::scalar_fn::fns::variant_get::VariantPath;
59use crate::scalar_fn::fns::zip::Zip;
60
61pub fn root() -> Expression {
66 Expression::Root
67}
68
69pub fn bound_root(dtype: DType) -> BoundExpression {
71 BoundExpression::new_root(dtype)
72}
73
74pub fn is_root(expr: &Expression) -> bool {
76 expr.is_root()
77}
78
79pub fn lit(value: impl Into<Scalar>) -> Expression {
99 Literal.new_expr(value.into(), [])
100}
101
102pub fn bound_lit(value: impl Into<Scalar>) -> BoundExpression {
104 Literal
105 .try_new_bound_expr(value.into(), [])
106 .vortex_expect("literal expressions are always well-typed")
107}
108
109pub fn col(field: impl Into<FieldName>) -> Expression {
120 GetItem.new_expr(field.into(), vec![root()])
121}
122
123pub fn bound_col(field: impl Into<FieldName>, scope: DType) -> BoundExpression {
125 bound_get_item(field, bound_root(scope))
126}
127
128pub fn get_item(field: impl Into<FieldName>, child: Expression) -> Expression {
137 GetItem.new_expr(field.into(), vec![child])
138}
139
140pub fn bound_get_item(field: impl Into<FieldName>, child: BoundExpression) -> BoundExpression {
142 GetItem
143 .try_new_bound_expr(field.into(), [child])
144 .vortex_expect("get-item expressions must reference a field in the child dtype")
145}
146
147pub fn variant_get(
154 child: Expression,
155 path: impl Into<VariantPath>,
156 dtype: Option<DType>,
157) -> Expression {
158 VariantGet.new_expr(VariantGetOptions::new(path.into(), dtype), vec![child])
159}
160
161pub fn bound_variant_get(
163 child: BoundExpression,
164 path: impl Into<VariantPath>,
165 dtype: Option<DType>,
166) -> BoundExpression {
167 VariantGet
168 .try_new_bound_expr(VariantGetOptions::new(path.into(), dtype), [child])
169 .vortex_expect("variant-get expressions require a Variant child")
170}
171
172pub fn case_when(
176 condition: Expression,
177 then_value: Expression,
178 else_value: Expression,
179) -> Expression {
180 let options = CaseWhenOptions {
181 num_when_then_pairs: 1,
182 has_else: true,
183 };
184 CaseWhen.new_expr(options, [condition, then_value, else_value])
185}
186
187pub fn bound_case_when(
189 condition: BoundExpression,
190 then_value: BoundExpression,
191 else_value: BoundExpression,
192) -> BoundExpression {
193 let options = CaseWhenOptions {
194 num_when_then_pairs: 1,
195 has_else: true,
196 };
197 CaseWhen
198 .try_new_bound_expr(options, [condition, then_value, else_value])
199 .vortex_expect("case expressions must have boolean conditions and matching branch dtypes")
200}
201
202pub fn case_when_no_else(condition: Expression, then_value: Expression) -> Expression {
204 let options = CaseWhenOptions {
205 num_when_then_pairs: 1,
206 has_else: false,
207 };
208 CaseWhen.new_expr(options, [condition, then_value])
209}
210
211pub fn bound_case_when_no_else(
213 condition: BoundExpression,
214 then_value: BoundExpression,
215) -> BoundExpression {
216 let options = CaseWhenOptions {
217 num_when_then_pairs: 1,
218 has_else: false,
219 };
220 CaseWhen
221 .try_new_bound_expr(options, [condition, then_value])
222 .vortex_expect("case expressions must have boolean conditions")
223}
224
225pub fn nested_case_when(
227 when_then_pairs: Vec<(Expression, Expression)>,
228 else_value: Option<Expression>,
229) -> Expression {
230 assert!(
231 !when_then_pairs.is_empty(),
232 "nested_case_when requires at least one when/then pair"
233 );
234
235 let has_else = else_value.is_some();
236 let mut children = Vec::with_capacity(when_then_pairs.len() * 2 + usize::from(has_else));
237 for (condition, then_value) in &when_then_pairs {
238 children.push(condition.clone());
239 children.push(then_value.clone());
240 }
241 if let Some(else_expr) = else_value {
242 children.push(else_expr);
243 }
244
245 let Ok(num_when_then_pairs) = u32::try_from(when_then_pairs.len()) else {
246 vortex_panic!("nested_case_when has too many when/then pairs");
247 };
248 let options = CaseWhenOptions {
249 num_when_then_pairs,
250 has_else,
251 };
252 CaseWhen.new_expr(options, children)
253}
254
255pub fn bound_nested_case_when(
257 when_then_pairs: Vec<(BoundExpression, BoundExpression)>,
258 else_value: Option<BoundExpression>,
259) -> BoundExpression {
260 assert!(
261 !when_then_pairs.is_empty(),
262 "nested_case_when requires at least one when/then pair"
263 );
264
265 let Ok(num_when_then_pairs) = u32::try_from(when_then_pairs.len()) else {
266 vortex_panic!("nested_case_when has too many when/then pairs");
267 };
268 let has_else = else_value.is_some();
269 let mut children = Vec::with_capacity(when_then_pairs.len() * 2 + usize::from(has_else));
270 for (condition, then_value) in when_then_pairs {
271 children.push(condition);
272 children.push(then_value);
273 }
274 if let Some(else_expr) = else_value {
275 children.push(else_expr);
276 }
277
278 let options = CaseWhenOptions {
279 num_when_then_pairs,
280 has_else,
281 };
282 CaseWhen
283 .try_new_bound_expr(options, children)
284 .vortex_expect("case expressions must have boolean conditions and matching branch dtypes")
285}
286
287pub fn binary(operator: Operator, lhs: Expression, rhs: Expression) -> Expression {
291 Binary
292 .try_new_expr(operator, [lhs, rhs])
293 .vortex_expect("Failed to create binary expression")
294}
295
296pub fn bound_binary(
298 operator: Operator,
299 lhs: BoundExpression,
300 rhs: BoundExpression,
301) -> BoundExpression {
302 Binary
303 .try_new_bound_expr(operator, [lhs, rhs])
304 .vortex_expect("binary expressions must have compatible operand dtypes")
305}
306
307pub fn eq(lhs: Expression, rhs: Expression) -> Expression {
329 Binary
330 .try_new_expr(Operator::Eq, [lhs, rhs])
331 .vortex_expect("Failed to create Eq binary expression")
332}
333
334pub fn bound_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
336 bound_binary(Operator::Eq, lhs, rhs)
337}
338
339pub fn not_eq(lhs: Expression, rhs: Expression) -> Expression {
361 Binary
362 .try_new_expr(Operator::NotEq, [lhs, rhs])
363 .vortex_expect("Failed to create NotEq binary expression")
364}
365
366pub fn bound_not_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
368 bound_binary(Operator::NotEq, lhs, rhs)
369}
370
371pub fn gt_eq(lhs: Expression, rhs: Expression) -> Expression {
393 Binary
394 .try_new_expr(Operator::Gte, [lhs, rhs])
395 .vortex_expect("Failed to create Gte binary expression")
396}
397
398pub fn bound_gt_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
400 bound_binary(Operator::Gte, lhs, rhs)
401}
402
403pub fn gt(lhs: Expression, rhs: Expression) -> Expression {
425 Binary
426 .try_new_expr(Operator::Gt, [lhs, rhs])
427 .vortex_expect("Failed to create Gt binary expression")
428}
429
430pub fn bound_gt(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
432 bound_binary(Operator::Gt, lhs, rhs)
433}
434
435pub fn lt_eq(lhs: Expression, rhs: Expression) -> Expression {
457 Binary
458 .try_new_expr(Operator::Lte, [lhs, rhs])
459 .vortex_expect("Failed to create Lte binary expression")
460}
461
462pub fn bound_lt_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
464 bound_binary(Operator::Lte, lhs, rhs)
465}
466
467pub fn lt(lhs: Expression, rhs: Expression) -> Expression {
489 Binary
490 .try_new_expr(Operator::Lt, [lhs, rhs])
491 .vortex_expect("Failed to create Lt binary expression")
492}
493
494pub fn bound_lt(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
496 bound_binary(Operator::Lt, lhs, rhs)
497}
498
499pub fn or(lhs: Expression, rhs: Expression) -> Expression {
519 Binary
520 .try_new_expr(Operator::Or, [lhs, rhs])
521 .vortex_expect("Failed to create Or binary expression")
522}
523
524pub fn bound_or(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
526 bound_binary(Operator::Or, lhs, rhs)
527}
528
529pub fn or_collect<I>(iter: I) -> Option<Expression>
536where
537 I: IntoIterator<Item = Expression>,
538{
539 iter.into_iter().reduce_balanced(or)
540}
541
542pub fn bound_or_collect<I>(iter: I) -> Option<BoundExpression>
544where
545 I: IntoIterator<Item = BoundExpression>,
546{
547 iter.into_iter().reduce_balanced(bound_or)
548}
549
550pub fn and(lhs: Expression, rhs: Expression) -> Expression {
570 Binary
571 .try_new_expr(Operator::And, [lhs, rhs])
572 .vortex_expect("Failed to create And binary expression")
573}
574
575pub fn bound_and(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
577 bound_binary(Operator::And, lhs, rhs)
578}
579
580pub fn and_collect<I>(iter: I) -> Option<Expression>
587where
588 I: IntoIterator<Item = Expression>,
589{
590 iter.into_iter().reduce_balanced(and)
591}
592
593pub fn bound_and_collect<I>(iter: I) -> Option<BoundExpression>
595where
596 I: IntoIterator<Item = BoundExpression>,
597{
598 iter.into_iter().reduce_balanced(bound_and)
599}
600
601pub fn checked_add(lhs: Expression, rhs: Expression) -> Expression {
620 Binary
621 .try_new_expr(Operator::Add, [lhs, rhs])
622 .vortex_expect("Failed to create Add binary expression")
623}
624
625pub fn bound_checked_add(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
627 bound_binary(Operator::Add, lhs, rhs)
628}
629
630pub fn not(operand: Expression) -> Expression {
641 Not.new_expr(EmptyOptions, vec![operand])
642}
643
644pub fn bound_not(operand: BoundExpression) -> BoundExpression {
646 Not.try_new_bound_expr(EmptyOptions, [operand])
647 .vortex_expect("not expressions require a boolean operand")
648}
649
650pub fn between(
668 arr: Expression,
669 lower: Expression,
670 upper: Expression,
671 options: BetweenOptions,
672) -> Expression {
673 Between
674 .try_new_expr(options, [arr, lower, upper])
675 .vortex_expect("Failed to create Between expression")
676}
677
678pub fn bound_between(
680 arr: BoundExpression,
681 lower: BoundExpression,
682 upper: BoundExpression,
683 options: BetweenOptions,
684) -> BoundExpression {
685 Between
686 .try_new_bound_expr(options, [arr, lower, upper])
687 .vortex_expect("between expressions require compatible operand dtypes")
688}
689
690pub fn select(field_names: impl Into<FieldNames>, child: Expression) -> Expression {
700 Select
701 .try_new_expr(FieldSelection::Include(field_names.into()), [child])
702 .vortex_expect("Failed to create Select expression")
703}
704
705pub fn bound_select(field_names: impl Into<FieldNames>, child: BoundExpression) -> BoundExpression {
707 Select
708 .try_new_bound_expr(FieldSelection::Include(field_names.into()), [child])
709 .vortex_expect("select expressions require fields from a struct child")
710}
711
712pub fn select_exclude(fields: impl Into<FieldNames>, child: Expression) -> Expression {
721 Select
722 .try_new_expr(FieldSelection::Exclude(fields.into()), [child])
723 .vortex_expect("Failed to create Select expression")
724}
725
726pub fn bound_select_exclude(
728 fields: impl Into<FieldNames>,
729 child: BoundExpression,
730) -> BoundExpression {
731 Select
732 .try_new_bound_expr(FieldSelection::Exclude(fields.into()), [child])
733 .vortex_expect("select expressions require fields from a struct child")
734}
735
736pub fn pack(
746 elements: impl IntoIterator<Item = (impl Into<FieldName>, Expression)>,
747 nullability: Nullability,
748) -> Expression {
749 let (names, values): (Vec<_>, Vec<_>) = elements
750 .into_iter()
751 .map(|(name, value)| (name.into(), value))
752 .unzip();
753 Pack.new_expr(
754 PackOptions {
755 names: names.into(),
756 nullability,
757 },
758 values,
759 )
760}
761
762pub fn bound_pack(
764 elements: impl IntoIterator<Item = (impl Into<FieldName>, BoundExpression)>,
765 nullability: Nullability,
766) -> BoundExpression {
767 let (names, values): (Vec<_>, Vec<_>) = elements
768 .into_iter()
769 .map(|(name, value)| (name.into(), value))
770 .unzip();
771 Pack.try_new_bound_expr(
772 PackOptions {
773 names: names.into(),
774 nullability,
775 },
776 values,
777 )
778 .vortex_expect("pack expressions must have one name per child")
779}
780
781pub fn cast(child: Expression, target: DType) -> Expression {
793 Cast.try_new_expr(target, [child])
794 .vortex_expect("Failed to create Cast expression")
795}
796
797pub fn bound_cast(child: BoundExpression, target: DType) -> BoundExpression {
799 Cast.try_new_bound_expr(target, [child])
800 .vortex_expect("cast expressions require a supported source and target dtype")
801}
802
803pub fn fill_null(child: Expression, fill_value: Expression) -> Expression {
812 FillNull.new_expr(EmptyOptions, [child, fill_value])
813}
814
815pub fn bound_fill_null(child: BoundExpression, fill_value: BoundExpression) -> BoundExpression {
817 FillNull
818 .try_new_bound_expr(EmptyOptions, [child, fill_value])
819 .vortex_expect("fill-null expressions require compatible child and fill dtypes")
820}
821
822pub fn is_null(child: Expression) -> Expression {
833 IsNull.new_expr(EmptyOptions, vec![child])
834}
835
836pub fn bound_is_null(child: BoundExpression) -> BoundExpression {
838 IsNull
839 .try_new_bound_expr(EmptyOptions, [child])
840 .vortex_expect("is-null expressions are always well-typed")
841}
842
843pub fn is_nan(child: Expression) -> Expression {
855 IsNan.new_expr(EmptyOptions, vec![child])
856}
857
858pub fn bound_is_nan(child: BoundExpression) -> BoundExpression {
860 IsNan
861 .try_new_bound_expr(EmptyOptions, [child])
862 .vortex_expect("is-nan expressions are always well-typed")
863}
864
865pub fn is_not_null(child: Expression) -> Expression {
876 IsNotNull.new_expr(EmptyOptions, vec![child])
877}
878
879pub fn bound_is_not_null(child: BoundExpression) -> BoundExpression {
881 IsNotNull
882 .try_new_bound_expr(EmptyOptions, [child])
883 .vortex_expect("is-not-null expressions are always well-typed")
884}
885
886pub fn like(child: Expression, pattern: Expression) -> Expression {
890 Like.new_expr(
891 LikeOptions {
892 negated: false,
893 case_insensitive: false,
894 },
895 [child, pattern],
896 )
897}
898
899pub fn bound_like(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
901 bound_like_with_options(child, pattern, false, false)
902}
903
904pub fn ilike(child: Expression, pattern: Expression) -> Expression {
906 Like.new_expr(
907 LikeOptions {
908 negated: false,
909 case_insensitive: true,
910 },
911 [child, pattern],
912 )
913}
914
915pub fn bound_ilike(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
917 bound_like_with_options(child, pattern, false, true)
918}
919
920pub fn not_like(child: Expression, pattern: Expression) -> Expression {
922 Like.new_expr(
923 LikeOptions {
924 negated: true,
925 case_insensitive: false,
926 },
927 [child, pattern],
928 )
929}
930
931pub fn bound_not_like(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
933 bound_like_with_options(child, pattern, true, false)
934}
935
936pub fn not_ilike(child: Expression, pattern: Expression) -> Expression {
938 Like.new_expr(
939 LikeOptions {
940 negated: true,
941 case_insensitive: true,
942 },
943 [child, pattern],
944 )
945}
946
947pub fn bound_not_ilike(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
949 bound_like_with_options(child, pattern, true, true)
950}
951
952fn bound_like_with_options(
953 child: BoundExpression,
954 pattern: BoundExpression,
955 negated: bool,
956 case_insensitive: bool,
957) -> BoundExpression {
958 Like.try_new_bound_expr(
959 LikeOptions {
960 negated,
961 case_insensitive,
962 },
963 [child, pattern],
964 )
965 .vortex_expect("like expressions require UTF-8 or binary operands")
966}
967
968pub fn mask(array: Expression, mask: Expression) -> Expression {
972 Mask.new_expr(EmptyOptions, [array, mask])
973}
974
975pub fn bound_mask(array: BoundExpression, mask: BoundExpression) -> BoundExpression {
977 Mask.try_new_bound_expr(EmptyOptions, [array, mask])
978 .vortex_expect("mask expressions require a boolean mask")
979}
980
981pub fn merge(elements: impl IntoIterator<Item = impl Into<Expression>>) -> Expression {
994 use itertools::Itertools as _;
995 let values = elements.into_iter().map(|value| value.into()).collect_vec();
996 Merge.new_expr(DuplicateHandling::default(), values)
997}
998
999pub fn bound_merge(elements: impl IntoIterator<Item = BoundExpression>) -> BoundExpression {
1001 bound_merge_opts(elements, DuplicateHandling::default())
1002}
1003
1004pub fn merge_opts(
1006 elements: impl IntoIterator<Item = impl Into<Expression>>,
1007 duplicate_handling: DuplicateHandling,
1008) -> Expression {
1009 use itertools::Itertools as _;
1010 let values = elements.into_iter().map(|value| value.into()).collect_vec();
1011 Merge.new_expr(duplicate_handling, values)
1012}
1013
1014pub fn bound_merge_opts(
1016 elements: impl IntoIterator<Item = BoundExpression>,
1017 duplicate_handling: DuplicateHandling,
1018) -> BoundExpression {
1019 Merge
1020 .try_new_bound_expr(duplicate_handling, elements)
1021 .vortex_expect("merge expressions require non-nullable struct children")
1022}
1023
1024pub fn zip_expr(mask: Expression, if_true: Expression, if_false: Expression) -> Expression {
1033 Zip.new_expr(EmptyOptions, [if_true, if_false, mask])
1034}
1035
1036pub fn bound_zip_expr(
1038 mask: BoundExpression,
1039 if_true: BoundExpression,
1040 if_false: BoundExpression,
1041) -> BoundExpression {
1042 Zip.try_new_bound_expr(EmptyOptions, [if_true, if_false, mask])
1043 .vortex_expect("zip expressions require a boolean mask and compatible value dtypes")
1044}
1045
1046pub fn dynamic_with_options(options: DynamicComparisonExpr, lhs: Expression) -> Expression {
1050 DynamicComparison.new_expr(options, [lhs])
1051}
1052
1053pub fn bound_dynamic_with_options(
1055 options: DynamicComparisonExpr,
1056 lhs: BoundExpression,
1057) -> BoundExpression {
1058 DynamicComparison
1059 .try_new_bound_expr(options, [lhs])
1060 .vortex_expect("dynamic comparisons require a compatible left-hand dtype")
1061}
1062
1063pub fn dynamic(
1065 operator: CompareOperator,
1066 rhs_value: impl Fn() -> Option<ScalarValue> + Send + Sync + 'static,
1067 rhs_dtype: DType,
1068 default: bool,
1069 lhs: Expression,
1070) -> Expression {
1071 dynamic_with_options(
1072 DynamicComparisonExpr {
1073 operator,
1074 rhs: Arc::new(Rhs {
1075 value: Arc::new(rhs_value),
1076 dtype: rhs_dtype,
1077 }),
1078 default,
1079 },
1080 lhs,
1081 )
1082}
1083
1084pub fn bound_dynamic(
1086 operator: CompareOperator,
1087 rhs_value: impl Fn() -> Option<ScalarValue> + Send + Sync + 'static,
1088 rhs_dtype: DType,
1089 default: bool,
1090 lhs: BoundExpression,
1091) -> BoundExpression {
1092 bound_dynamic_with_options(
1093 DynamicComparisonExpr {
1094 operator,
1095 rhs: Arc::new(Rhs {
1096 value: Arc::new(rhs_value),
1097 dtype: rhs_dtype,
1098 }),
1099 default,
1100 },
1101 lhs,
1102 )
1103}
1104
1105pub fn list_contains(list: Expression, value: Expression) -> Expression {
1117 list_contains_opts(list, value, ListContainsOptions::default())
1118}
1119
1120pub fn list_contains_opts(
1123 list: Expression,
1124 value: Expression,
1125 options: ListContainsOptions,
1126) -> Expression {
1127 ListContains.new_expr(options, [list, value])
1128}
1129
1130pub fn in_list(needle: Expression, list: Expression) -> Expression {
1139 list_contains_opts(
1140 list,
1141 needle,
1142 ListContainsOptions {
1143 sql_null_semantics: true,
1144 },
1145 )
1146}
1147
1148pub fn bound_list_contains(list: BoundExpression, value: BoundExpression) -> BoundExpression {
1150 ListContains
1151 .try_new_bound_expr(ListContainsOptions::default(), [list, value])
1152 .vortex_expect("list-contains expressions require a list child")
1153}
1154
1155pub fn bound_in_list(needle: BoundExpression, list: BoundExpression) -> BoundExpression {
1157 ListContains
1158 .try_new_bound_expr(
1159 ListContainsOptions {
1160 sql_null_semantics: true,
1161 },
1162 [list, needle],
1163 )
1164 .vortex_expect("list-contains expressions require a list child")
1165}
1166
1167pub fn byte_length(input: Expression) -> Expression {
1177 ByteLength.new_expr(EmptyOptions, [input])
1178}
1179
1180pub fn bound_byte_length(input: BoundExpression) -> BoundExpression {
1182 ByteLength
1183 .try_new_bound_expr(EmptyOptions, [input])
1184 .vortex_expect("byte-length expressions require a variable-length binary child")
1185}
1186
1187pub fn ext_storage(input: Expression) -> Expression {
1196 ExtStorage.new_expr(EmptyOptions, [input])
1197}
1198
1199pub fn bound_ext_storage(input: BoundExpression) -> BoundExpression {
1201 ExtStorage
1202 .try_new_bound_expr(EmptyOptions, [input])
1203 .vortex_expect("extension-storage expressions require an extension child")
1204}
1205
1206pub fn list_length(input: Expression) -> Expression {
1217 ListLength.new_expr(EmptyOptions, [input])
1218}
1219
1220pub fn bound_list_length(input: BoundExpression) -> BoundExpression {
1222 ListLength
1223 .try_new_bound_expr(EmptyOptions, [input])
1224 .vortex_expect("list-length expressions require a list child")
1225}
1226
1227pub fn list_sum(input: Expression) -> Expression {
1242 ListSum.new_expr(NumericalAggregateOpts::default(), [input])
1243}
1244
1245pub fn bound_list_sum(input: BoundExpression) -> BoundExpression {
1247 ListSum
1248 .try_new_bound_expr(NumericalAggregateOpts::default(), [input])
1249 .vortex_expect("list-sum expressions require a numeric list child")
1250}
1251
1252pub fn list_sum_opts(input: Expression, options: NumericalAggregateOpts) -> Expression {
1255 ListSum.new_expr(options, [input])
1256}
1257
1258pub fn bound_list_sum_opts(
1260 input: BoundExpression,
1261 options: NumericalAggregateOpts,
1262) -> BoundExpression {
1263 ListSum
1264 .try_new_bound_expr(options, [input])
1265 .vortex_expect("list-sum expressions require a numeric list child")
1266}
1267
1268pub mod bound {
1274 pub use super::bound_and as and;
1275 pub use super::bound_and_collect as and_collect;
1276 pub use super::bound_between as between;
1277 pub use super::bound_binary as binary;
1278 pub use super::bound_byte_length as byte_length;
1279 pub use super::bound_case_when as case_when;
1280 pub use super::bound_case_when_no_else as case_when_no_else;
1281 pub use super::bound_cast as cast;
1282 pub use super::bound_checked_add as checked_add;
1283 pub use super::bound_col as col;
1284 pub use super::bound_dynamic as dynamic;
1285 pub use super::bound_dynamic_with_options as dynamic_with_options;
1286 pub use super::bound_eq as eq;
1287 pub use super::bound_ext_storage as ext_storage;
1288 pub use super::bound_fill_null as fill_null;
1289 pub use super::bound_get_item as get_item;
1290 pub use super::bound_gt as gt;
1291 pub use super::bound_gt_eq as gt_eq;
1292 pub use super::bound_ilike as ilike;
1293 pub use super::bound_in_list as in_list;
1294 pub use super::bound_is_nan as is_nan;
1295 pub use super::bound_is_not_null as is_not_null;
1296 pub use super::bound_is_null as is_null;
1297 pub use super::bound_like as like;
1298 pub use super::bound_list_contains as list_contains;
1299 pub use super::bound_list_length as list_length;
1300 pub use super::bound_list_sum as list_sum;
1301 pub use super::bound_list_sum_opts as list_sum_opts;
1302 pub use super::bound_lit as lit;
1303 pub use super::bound_lt as lt;
1304 pub use super::bound_lt_eq as lt_eq;
1305 pub use super::bound_mask as mask;
1306 pub use super::bound_merge as merge;
1307 pub use super::bound_merge_opts as merge_opts;
1308 pub use super::bound_nested_case_when as nested_case_when;
1309 pub use super::bound_not as not;
1310 pub use super::bound_not_eq as not_eq;
1311 pub use super::bound_not_ilike as not_ilike;
1312 pub use super::bound_not_like as not_like;
1313 pub use super::bound_or as or;
1314 pub use super::bound_or_collect as or_collect;
1315 pub use super::bound_pack as pack;
1316 pub use super::bound_root as root;
1317 pub use super::bound_select as select;
1318 pub use super::bound_select_exclude as select_exclude;
1319 pub use super::bound_variant_get as variant_get;
1320 pub use super::bound_zip_expr as zip_expr;
1321}