1use std::sync::Arc;
7use std::sync::LazyLock;
8
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_panic;
12use vortex_utils::iter::ReduceBalancedIterExt;
13
14use crate::aggregate_fn::NumericalAggregateOpts;
15use crate::dtype::DType;
16use crate::dtype::FieldName;
17use crate::dtype::FieldNames;
18use crate::dtype::Nullability;
19use crate::expr::BoundExpression;
20use crate::expr::Expression;
21use crate::scalar::Scalar;
22use crate::scalar::ScalarValue;
23use crate::scalar_fn::EmptyOptions;
24use crate::scalar_fn::ScalarFnVTableExt;
25use crate::scalar_fn::fns::between::Between;
26use crate::scalar_fn::fns::between::BetweenOptions;
27use crate::scalar_fn::fns::binary::Binary;
28use crate::scalar_fn::fns::byte_length::ByteLength;
29use crate::scalar_fn::fns::case_when::CaseWhen;
30use crate::scalar_fn::fns::case_when::CaseWhenOptions;
31use crate::scalar_fn::fns::cast::Cast;
32use crate::scalar_fn::fns::dynamic::DynamicComparison;
33use crate::scalar_fn::fns::dynamic::DynamicComparisonExpr;
34use crate::scalar_fn::fns::dynamic::Rhs;
35use crate::scalar_fn::fns::ext_storage::ExtStorage;
36use crate::scalar_fn::fns::fill_null::FillNull;
37use crate::scalar_fn::fns::get_item::GetItem;
38use crate::scalar_fn::fns::is_not_null::IsNotNull;
39use crate::scalar_fn::fns::is_null::IsNull;
40use crate::scalar_fn::fns::like::Like;
41use crate::scalar_fn::fns::like::LikeOptions;
42use crate::scalar_fn::fns::list_contains::ListContains;
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::root::Root;
55use crate::scalar_fn::fns::select::FieldSelection;
56use crate::scalar_fn::fns::select::Select;
57use crate::scalar_fn::fns::variant_get::VariantGet;
58use crate::scalar_fn::fns::variant_get::VariantGetOptions;
59use crate::scalar_fn::fns::variant_get::VariantPath;
60use crate::scalar_fn::fns::zip::Zip;
61
62static ROOT: LazyLock<Expression> = LazyLock::new(|| {
63 Root.try_new_expr(EmptyOptions, vec![])
64 .vortex_expect("Creating root() shouldn't fail")
65});
66
67pub fn root() -> Expression {
72 ROOT.clone()
73}
74
75pub fn bound_root(dtype: DType) -> BoundExpression {
77 BoundExpression::new_root(dtype)
78}
79
80pub fn is_root(expr: &Expression) -> bool {
82 (expr.scalar_fn().id() == ROOT.scalar_fn().id()) || expr.is::<Root>()
85}
86
87pub fn lit(value: impl Into<Scalar>) -> Expression {
107 Literal.new_expr(value.into(), [])
108}
109
110pub fn bound_lit(value: impl Into<Scalar>) -> BoundExpression {
112 Literal
113 .try_new_bound_expr(value.into(), [])
114 .vortex_expect("literal expressions are always well-typed")
115}
116
117pub fn col(field: impl Into<FieldName>) -> Expression {
128 GetItem.new_expr(field.into(), vec![root()])
129}
130
131pub fn bound_col(field: impl Into<FieldName>, scope: DType) -> BoundExpression {
133 bound_get_item(field, bound_root(scope))
134}
135
136pub fn get_item(field: impl Into<FieldName>, child: Expression) -> Expression {
145 GetItem.new_expr(field.into(), vec![child])
146}
147
148pub fn bound_get_item(field: impl Into<FieldName>, child: BoundExpression) -> BoundExpression {
150 GetItem
151 .try_new_bound_expr(field.into(), [child])
152 .vortex_expect("get-item expressions must reference a field in the child dtype")
153}
154
155pub fn variant_get(
162 child: Expression,
163 path: impl Into<VariantPath>,
164 dtype: Option<DType>,
165) -> Expression {
166 VariantGet.new_expr(VariantGetOptions::new(path.into(), dtype), vec![child])
167}
168
169pub fn bound_variant_get(
171 child: BoundExpression,
172 path: impl Into<VariantPath>,
173 dtype: Option<DType>,
174) -> BoundExpression {
175 VariantGet
176 .try_new_bound_expr(VariantGetOptions::new(path.into(), dtype), [child])
177 .vortex_expect("variant-get expressions require a Variant child")
178}
179
180pub fn case_when(
184 condition: Expression,
185 then_value: Expression,
186 else_value: Expression,
187) -> Expression {
188 let options = CaseWhenOptions {
189 num_when_then_pairs: 1,
190 has_else: true,
191 };
192 CaseWhen.new_expr(options, [condition, then_value, else_value])
193}
194
195pub fn bound_case_when(
197 condition: BoundExpression,
198 then_value: BoundExpression,
199 else_value: BoundExpression,
200) -> BoundExpression {
201 let options = CaseWhenOptions {
202 num_when_then_pairs: 1,
203 has_else: true,
204 };
205 CaseWhen
206 .try_new_bound_expr(options, [condition, then_value, else_value])
207 .vortex_expect("case expressions must have boolean conditions and matching branch dtypes")
208}
209
210pub fn case_when_no_else(condition: Expression, then_value: Expression) -> Expression {
212 let options = CaseWhenOptions {
213 num_when_then_pairs: 1,
214 has_else: false,
215 };
216 CaseWhen.new_expr(options, [condition, then_value])
217}
218
219pub fn bound_case_when_no_else(
221 condition: BoundExpression,
222 then_value: BoundExpression,
223) -> BoundExpression {
224 let options = CaseWhenOptions {
225 num_when_then_pairs: 1,
226 has_else: false,
227 };
228 CaseWhen
229 .try_new_bound_expr(options, [condition, then_value])
230 .vortex_expect("case expressions must have boolean conditions")
231}
232
233pub fn nested_case_when(
235 when_then_pairs: Vec<(Expression, Expression)>,
236 else_value: Option<Expression>,
237) -> Expression {
238 assert!(
239 !when_then_pairs.is_empty(),
240 "nested_case_when requires at least one when/then pair"
241 );
242
243 let has_else = else_value.is_some();
244 let mut children = Vec::with_capacity(when_then_pairs.len() * 2 + usize::from(has_else));
245 for (condition, then_value) in &when_then_pairs {
246 children.push(condition.clone());
247 children.push(then_value.clone());
248 }
249 if let Some(else_expr) = else_value {
250 children.push(else_expr);
251 }
252
253 let Ok(num_when_then_pairs) = u32::try_from(when_then_pairs.len()) else {
254 vortex_panic!("nested_case_when has too many when/then pairs");
255 };
256 let options = CaseWhenOptions {
257 num_when_then_pairs,
258 has_else,
259 };
260 CaseWhen.new_expr(options, children)
261}
262
263pub fn bound_nested_case_when(
265 when_then_pairs: Vec<(BoundExpression, BoundExpression)>,
266 else_value: Option<BoundExpression>,
267) -> BoundExpression {
268 assert!(
269 !when_then_pairs.is_empty(),
270 "nested_case_when requires at least one when/then pair"
271 );
272
273 let Ok(num_when_then_pairs) = u32::try_from(when_then_pairs.len()) else {
274 vortex_panic!("nested_case_when has too many when/then pairs");
275 };
276 let has_else = else_value.is_some();
277 let mut children = Vec::with_capacity(when_then_pairs.len() * 2 + usize::from(has_else));
278 for (condition, then_value) in when_then_pairs {
279 children.push(condition);
280 children.push(then_value);
281 }
282 if let Some(else_expr) = else_value {
283 children.push(else_expr);
284 }
285
286 let options = CaseWhenOptions {
287 num_when_then_pairs,
288 has_else,
289 };
290 CaseWhen
291 .try_new_bound_expr(options, children)
292 .vortex_expect("case expressions must have boolean conditions and matching branch dtypes")
293}
294
295pub fn binary(operator: Operator, lhs: Expression, rhs: Expression) -> Expression {
299 Binary
300 .try_new_expr(operator, [lhs, rhs])
301 .vortex_expect("Failed to create binary expression")
302}
303
304pub fn bound_binary(
306 operator: Operator,
307 lhs: BoundExpression,
308 rhs: BoundExpression,
309) -> BoundExpression {
310 Binary
311 .try_new_bound_expr(operator, [lhs, rhs])
312 .vortex_expect("binary expressions must have compatible operand dtypes")
313}
314
315pub fn eq(lhs: Expression, rhs: Expression) -> Expression {
337 Binary
338 .try_new_expr(Operator::Eq, [lhs, rhs])
339 .vortex_expect("Failed to create Eq binary expression")
340}
341
342pub fn bound_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
344 bound_binary(Operator::Eq, lhs, rhs)
345}
346
347pub fn not_eq(lhs: Expression, rhs: Expression) -> Expression {
369 Binary
370 .try_new_expr(Operator::NotEq, [lhs, rhs])
371 .vortex_expect("Failed to create NotEq binary expression")
372}
373
374pub fn bound_not_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
376 bound_binary(Operator::NotEq, lhs, rhs)
377}
378
379pub fn gt_eq(lhs: Expression, rhs: Expression) -> Expression {
401 Binary
402 .try_new_expr(Operator::Gte, [lhs, rhs])
403 .vortex_expect("Failed to create Gte binary expression")
404}
405
406pub fn bound_gt_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
408 bound_binary(Operator::Gte, lhs, rhs)
409}
410
411pub fn gt(lhs: Expression, rhs: Expression) -> Expression {
433 Binary
434 .try_new_expr(Operator::Gt, [lhs, rhs])
435 .vortex_expect("Failed to create Gt binary expression")
436}
437
438pub fn bound_gt(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
440 bound_binary(Operator::Gt, lhs, rhs)
441}
442
443pub fn lt_eq(lhs: Expression, rhs: Expression) -> Expression {
465 Binary
466 .try_new_expr(Operator::Lte, [lhs, rhs])
467 .vortex_expect("Failed to create Lte binary expression")
468}
469
470pub fn bound_lt_eq(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
472 bound_binary(Operator::Lte, lhs, rhs)
473}
474
475pub fn lt(lhs: Expression, rhs: Expression) -> Expression {
497 Binary
498 .try_new_expr(Operator::Lt, [lhs, rhs])
499 .vortex_expect("Failed to create Lt binary expression")
500}
501
502pub fn bound_lt(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
504 bound_binary(Operator::Lt, lhs, rhs)
505}
506
507pub fn or(lhs: Expression, rhs: Expression) -> Expression {
527 Binary
528 .try_new_expr(Operator::Or, [lhs, rhs])
529 .vortex_expect("Failed to create Or binary expression")
530}
531
532pub fn bound_or(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
534 bound_binary(Operator::Or, lhs, rhs)
535}
536
537pub fn or_collect<I>(iter: I) -> Option<Expression>
544where
545 I: IntoIterator<Item = Expression>,
546{
547 iter.into_iter().reduce_balanced(or)
548}
549
550pub fn bound_or_collect<I>(iter: I) -> Option<BoundExpression>
552where
553 I: IntoIterator<Item = BoundExpression>,
554{
555 iter.into_iter().reduce_balanced(bound_or)
556}
557
558pub fn and(lhs: Expression, rhs: Expression) -> Expression {
578 Binary
579 .try_new_expr(Operator::And, [lhs, rhs])
580 .vortex_expect("Failed to create And binary expression")
581}
582
583pub fn bound_and(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
585 bound_binary(Operator::And, lhs, rhs)
586}
587
588pub fn and_collect<I>(iter: I) -> Option<Expression>
595where
596 I: IntoIterator<Item = Expression>,
597{
598 iter.into_iter().reduce_balanced(and)
599}
600
601pub fn bound_and_collect<I>(iter: I) -> Option<BoundExpression>
603where
604 I: IntoIterator<Item = BoundExpression>,
605{
606 iter.into_iter().reduce_balanced(bound_and)
607}
608
609pub fn union_child_validities(expression: &Expression) -> VortexResult<Option<Expression>> {
617 let child_validities = expression
618 .children()
619 .iter()
620 .map(Expression::validity)
621 .collect::<VortexResult<Vec<_>>>()?;
622 Ok(and_collect(child_validities))
623}
624
625pub fn checked_add(lhs: Expression, rhs: Expression) -> Expression {
644 Binary
645 .try_new_expr(Operator::Add, [lhs, rhs])
646 .vortex_expect("Failed to create Add binary expression")
647}
648
649pub fn bound_checked_add(lhs: BoundExpression, rhs: BoundExpression) -> BoundExpression {
651 bound_binary(Operator::Add, lhs, rhs)
652}
653
654pub fn not(operand: Expression) -> Expression {
665 Not.new_expr(EmptyOptions, vec![operand])
666}
667
668pub fn bound_not(operand: BoundExpression) -> BoundExpression {
670 Not.try_new_bound_expr(EmptyOptions, [operand])
671 .vortex_expect("not expressions require a boolean operand")
672}
673
674pub fn between(
692 arr: Expression,
693 lower: Expression,
694 upper: Expression,
695 options: BetweenOptions,
696) -> Expression {
697 Between
698 .try_new_expr(options, [arr, lower, upper])
699 .vortex_expect("Failed to create Between expression")
700}
701
702pub fn bound_between(
704 arr: BoundExpression,
705 lower: BoundExpression,
706 upper: BoundExpression,
707 options: BetweenOptions,
708) -> BoundExpression {
709 Between
710 .try_new_bound_expr(options, [arr, lower, upper])
711 .vortex_expect("between expressions require compatible operand dtypes")
712}
713
714pub fn select(field_names: impl Into<FieldNames>, child: Expression) -> Expression {
724 Select
725 .try_new_expr(FieldSelection::Include(field_names.into()), [child])
726 .vortex_expect("Failed to create Select expression")
727}
728
729pub fn bound_select(field_names: impl Into<FieldNames>, child: BoundExpression) -> BoundExpression {
731 Select
732 .try_new_bound_expr(FieldSelection::Include(field_names.into()), [child])
733 .vortex_expect("select expressions require fields from a struct child")
734}
735
736pub fn select_exclude(fields: impl Into<FieldNames>, child: Expression) -> Expression {
745 Select
746 .try_new_expr(FieldSelection::Exclude(fields.into()), [child])
747 .vortex_expect("Failed to create Select expression")
748}
749
750pub fn bound_select_exclude(
752 fields: impl Into<FieldNames>,
753 child: BoundExpression,
754) -> BoundExpression {
755 Select
756 .try_new_bound_expr(FieldSelection::Exclude(fields.into()), [child])
757 .vortex_expect("select expressions require fields from a struct child")
758}
759
760pub fn pack(
770 elements: impl IntoIterator<Item = (impl Into<FieldName>, Expression)>,
771 nullability: Nullability,
772) -> Expression {
773 let (names, values): (Vec<_>, Vec<_>) = elements
774 .into_iter()
775 .map(|(name, value)| (name.into(), value))
776 .unzip();
777 Pack.new_expr(
778 PackOptions {
779 names: names.into(),
780 nullability,
781 },
782 values,
783 )
784}
785
786pub fn bound_pack(
788 elements: impl IntoIterator<Item = (impl Into<FieldName>, BoundExpression)>,
789 nullability: Nullability,
790) -> BoundExpression {
791 let (names, values): (Vec<_>, Vec<_>) = elements
792 .into_iter()
793 .map(|(name, value)| (name.into(), value))
794 .unzip();
795 Pack.try_new_bound_expr(
796 PackOptions {
797 names: names.into(),
798 nullability,
799 },
800 values,
801 )
802 .vortex_expect("pack expressions must have one name per child")
803}
804
805pub fn cast(child: Expression, target: DType) -> Expression {
817 Cast.try_new_expr(target, [child])
818 .vortex_expect("Failed to create Cast expression")
819}
820
821pub fn bound_cast(child: BoundExpression, target: DType) -> BoundExpression {
823 Cast.try_new_bound_expr(target, [child])
824 .vortex_expect("cast expressions require a supported source and target dtype")
825}
826
827pub fn fill_null(child: Expression, fill_value: Expression) -> Expression {
836 FillNull.new_expr(EmptyOptions, [child, fill_value])
837}
838
839pub fn bound_fill_null(child: BoundExpression, fill_value: BoundExpression) -> BoundExpression {
841 FillNull
842 .try_new_bound_expr(EmptyOptions, [child, fill_value])
843 .vortex_expect("fill-null expressions require compatible child and fill dtypes")
844}
845
846pub fn is_null(child: Expression) -> Expression {
857 IsNull.new_expr(EmptyOptions, vec![child])
858}
859
860pub fn bound_is_null(child: BoundExpression) -> BoundExpression {
862 IsNull
863 .try_new_bound_expr(EmptyOptions, [child])
864 .vortex_expect("is-null expressions are always well-typed")
865}
866
867pub fn is_not_null(child: Expression) -> Expression {
878 IsNotNull.new_expr(EmptyOptions, vec![child])
879}
880
881pub fn bound_is_not_null(child: BoundExpression) -> BoundExpression {
883 IsNotNull
884 .try_new_bound_expr(EmptyOptions, [child])
885 .vortex_expect("is-not-null expressions are always well-typed")
886}
887
888pub fn like(child: Expression, pattern: Expression) -> Expression {
892 Like.new_expr(
893 LikeOptions {
894 negated: false,
895 case_insensitive: false,
896 },
897 [child, pattern],
898 )
899}
900
901pub fn bound_like(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
903 bound_like_with_options(child, pattern, false, false)
904}
905
906pub fn ilike(child: Expression, pattern: Expression) -> Expression {
908 Like.new_expr(
909 LikeOptions {
910 negated: false,
911 case_insensitive: true,
912 },
913 [child, pattern],
914 )
915}
916
917pub fn bound_ilike(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
919 bound_like_with_options(child, pattern, false, true)
920}
921
922pub fn not_like(child: Expression, pattern: Expression) -> Expression {
924 Like.new_expr(
925 LikeOptions {
926 negated: true,
927 case_insensitive: false,
928 },
929 [child, pattern],
930 )
931}
932
933pub fn bound_not_like(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
935 bound_like_with_options(child, pattern, true, false)
936}
937
938pub fn not_ilike(child: Expression, pattern: Expression) -> Expression {
940 Like.new_expr(
941 LikeOptions {
942 negated: true,
943 case_insensitive: true,
944 },
945 [child, pattern],
946 )
947}
948
949pub fn bound_not_ilike(child: BoundExpression, pattern: BoundExpression) -> BoundExpression {
951 bound_like_with_options(child, pattern, true, true)
952}
953
954fn bound_like_with_options(
955 child: BoundExpression,
956 pattern: BoundExpression,
957 negated: bool,
958 case_insensitive: bool,
959) -> BoundExpression {
960 Like.try_new_bound_expr(
961 LikeOptions {
962 negated,
963 case_insensitive,
964 },
965 [child, pattern],
966 )
967 .vortex_expect("like expressions require UTF-8 or binary operands")
968}
969
970pub fn mask(array: Expression, mask: Expression) -> Expression {
974 Mask.new_expr(EmptyOptions, [array, mask])
975}
976
977pub fn bound_mask(array: BoundExpression, mask: BoundExpression) -> BoundExpression {
979 Mask.try_new_bound_expr(EmptyOptions, [array, mask])
980 .vortex_expect("mask expressions require a boolean mask")
981}
982
983pub fn merge(elements: impl IntoIterator<Item = impl Into<Expression>>) -> Expression {
996 use itertools::Itertools as _;
997 let values = elements.into_iter().map(|value| value.into()).collect_vec();
998 Merge.new_expr(DuplicateHandling::default(), values)
999}
1000
1001pub fn bound_merge(elements: impl IntoIterator<Item = BoundExpression>) -> BoundExpression {
1003 bound_merge_opts(elements, DuplicateHandling::default())
1004}
1005
1006pub fn merge_opts(
1008 elements: impl IntoIterator<Item = impl Into<Expression>>,
1009 duplicate_handling: DuplicateHandling,
1010) -> Expression {
1011 use itertools::Itertools as _;
1012 let values = elements.into_iter().map(|value| value.into()).collect_vec();
1013 Merge.new_expr(duplicate_handling, values)
1014}
1015
1016pub fn bound_merge_opts(
1018 elements: impl IntoIterator<Item = BoundExpression>,
1019 duplicate_handling: DuplicateHandling,
1020) -> BoundExpression {
1021 Merge
1022 .try_new_bound_expr(duplicate_handling, elements)
1023 .vortex_expect("merge expressions require non-nullable struct children")
1024}
1025
1026pub fn zip_expr(mask: Expression, if_true: Expression, if_false: Expression) -> Expression {
1035 Zip.new_expr(EmptyOptions, [if_true, if_false, mask])
1036}
1037
1038pub fn bound_zip_expr(
1040 mask: BoundExpression,
1041 if_true: BoundExpression,
1042 if_false: BoundExpression,
1043) -> BoundExpression {
1044 Zip.try_new_bound_expr(EmptyOptions, [if_true, if_false, mask])
1045 .vortex_expect("zip expressions require a boolean mask and compatible value dtypes")
1046}
1047
1048pub fn dynamic_with_options(options: DynamicComparisonExpr, lhs: Expression) -> Expression {
1052 DynamicComparison.new_expr(options, [lhs])
1053}
1054
1055pub fn bound_dynamic_with_options(
1057 options: DynamicComparisonExpr,
1058 lhs: BoundExpression,
1059) -> BoundExpression {
1060 DynamicComparison
1061 .try_new_bound_expr(options, [lhs])
1062 .vortex_expect("dynamic comparisons require a compatible left-hand dtype")
1063}
1064
1065pub fn dynamic(
1067 operator: CompareOperator,
1068 rhs_value: impl Fn() -> Option<ScalarValue> + Send + Sync + 'static,
1069 rhs_dtype: DType,
1070 default: bool,
1071 lhs: Expression,
1072) -> Expression {
1073 dynamic_with_options(
1074 DynamicComparisonExpr {
1075 operator,
1076 rhs: Arc::new(Rhs {
1077 value: Arc::new(rhs_value),
1078 dtype: rhs_dtype,
1079 }),
1080 default,
1081 },
1082 lhs,
1083 )
1084}
1085
1086pub fn bound_dynamic(
1088 operator: CompareOperator,
1089 rhs_value: impl Fn() -> Option<ScalarValue> + Send + Sync + 'static,
1090 rhs_dtype: DType,
1091 default: bool,
1092 lhs: BoundExpression,
1093) -> BoundExpression {
1094 bound_dynamic_with_options(
1095 DynamicComparisonExpr {
1096 operator,
1097 rhs: Arc::new(Rhs {
1098 value: Arc::new(rhs_value),
1099 dtype: rhs_dtype,
1100 }),
1101 default,
1102 },
1103 lhs,
1104 )
1105}
1106
1107pub fn list_contains(list: Expression, value: Expression) -> Expression {
1118 ListContains.new_expr(EmptyOptions, [list, value])
1119}
1120
1121pub fn bound_list_contains(list: BoundExpression, value: BoundExpression) -> BoundExpression {
1123 ListContains
1124 .try_new_bound_expr(EmptyOptions, [list, value])
1125 .vortex_expect("list-contains expressions require a compatible list and value dtype")
1126}
1127
1128pub fn byte_length(input: Expression) -> Expression {
1138 ByteLength.new_expr(EmptyOptions, [input])
1139}
1140
1141pub fn bound_byte_length(input: BoundExpression) -> BoundExpression {
1143 ByteLength
1144 .try_new_bound_expr(EmptyOptions, [input])
1145 .vortex_expect("byte-length expressions require a variable-length binary child")
1146}
1147
1148pub fn ext_storage(input: Expression) -> Expression {
1157 ExtStorage.new_expr(EmptyOptions, [input])
1158}
1159
1160pub fn bound_ext_storage(input: BoundExpression) -> BoundExpression {
1162 ExtStorage
1163 .try_new_bound_expr(EmptyOptions, [input])
1164 .vortex_expect("extension-storage expressions require an extension child")
1165}
1166
1167pub fn list_length(input: Expression) -> Expression {
1178 ListLength.new_expr(EmptyOptions, [input])
1179}
1180
1181pub fn bound_list_length(input: BoundExpression) -> BoundExpression {
1183 ListLength
1184 .try_new_bound_expr(EmptyOptions, [input])
1185 .vortex_expect("list-length expressions require a list child")
1186}
1187
1188pub fn list_sum(input: Expression) -> Expression {
1203 ListSum.new_expr(NumericalAggregateOpts::default(), [input])
1204}
1205
1206pub fn bound_list_sum(input: BoundExpression) -> BoundExpression {
1208 ListSum
1209 .try_new_bound_expr(NumericalAggregateOpts::default(), [input])
1210 .vortex_expect("list-sum expressions require a numeric list child")
1211}
1212
1213pub fn list_sum_opts(input: Expression, options: NumericalAggregateOpts) -> Expression {
1216 ListSum.new_expr(options, [input])
1217}
1218
1219pub fn bound_list_sum_opts(
1221 input: BoundExpression,
1222 options: NumericalAggregateOpts,
1223) -> BoundExpression {
1224 ListSum
1225 .try_new_bound_expr(options, [input])
1226 .vortex_expect("list-sum expressions require a numeric list child")
1227}
1228
1229pub mod bound {
1235 pub use super::bound_and as and;
1236 pub use super::bound_and_collect as and_collect;
1237 pub use super::bound_between as between;
1238 pub use super::bound_binary as binary;
1239 pub use super::bound_byte_length as byte_length;
1240 pub use super::bound_case_when as case_when;
1241 pub use super::bound_case_when_no_else as case_when_no_else;
1242 pub use super::bound_cast as cast;
1243 pub use super::bound_checked_add as checked_add;
1244 pub use super::bound_col as col;
1245 pub use super::bound_dynamic as dynamic;
1246 pub use super::bound_dynamic_with_options as dynamic_with_options;
1247 pub use super::bound_eq as eq;
1248 pub use super::bound_ext_storage as ext_storage;
1249 pub use super::bound_fill_null as fill_null;
1250 pub use super::bound_get_item as get_item;
1251 pub use super::bound_gt as gt;
1252 pub use super::bound_gt_eq as gt_eq;
1253 pub use super::bound_ilike as ilike;
1254 pub use super::bound_is_not_null as is_not_null;
1255 pub use super::bound_is_null as is_null;
1256 pub use super::bound_like as like;
1257 pub use super::bound_list_contains as list_contains;
1258 pub use super::bound_list_length as list_length;
1259 pub use super::bound_list_sum as list_sum;
1260 pub use super::bound_list_sum_opts as list_sum_opts;
1261 pub use super::bound_lit as lit;
1262 pub use super::bound_lt as lt;
1263 pub use super::bound_lt_eq as lt_eq;
1264 pub use super::bound_mask as mask;
1265 pub use super::bound_merge as merge;
1266 pub use super::bound_merge_opts as merge_opts;
1267 pub use super::bound_nested_case_when as nested_case_when;
1268 pub use super::bound_not as not;
1269 pub use super::bound_not_eq as not_eq;
1270 pub use super::bound_not_ilike as not_ilike;
1271 pub use super::bound_not_like as not_like;
1272 pub use super::bound_or as or;
1273 pub use super::bound_or_collect as or_collect;
1274 pub use super::bound_pack as pack;
1275 pub use super::bound_root as root;
1276 pub use super::bound_select as select;
1277 pub use super::bound_select_exclude as select_exclude;
1278 pub use super::bound_variant_get as variant_get;
1279 pub use super::bound_zip_expr as zip_expr;
1280}