1use std::fmt::Debug;
21use std::hash::{Hash, Hasher};
22use std::sync::Arc;
23
24use crate::PhysicalExpr;
25use crate::physical_expr::physical_exprs_bag_equal;
26
27use arrow::array::*;
28use arrow::buffer::{BooleanBuffer, NullBuffer};
29use arrow::compute::SortOptions;
30use arrow::compute::kernels::boolean::{not, or_kleene};
31use arrow::compute::kernels::cmp::eq as arrow_eq;
32use arrow::datatypes::*;
33
34use datafusion_common::{
35 DFSchema, Result, ScalarValue, assert_or_internal_err, exec_err,
36};
37use datafusion_expr::{ColumnarValue, expr_vec_fmt};
38
39mod array_static_filter;
40mod branchless_filter;
41mod primitive_filter;
42mod result;
43mod static_filter;
44mod strategy;
45
46use static_filter::StaticFilter;
47use strategy::instantiate_static_filter;
48
49pub struct InListExpr {
51 expr: Arc<dyn PhysicalExpr>,
52 list: Vec<Arc<dyn PhysicalExpr>>,
53 negated: bool,
54 static_filter: Option<Arc<dyn StaticFilter + Send + Sync>>,
55}
56
57impl Debug for InListExpr {
58 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
59 f.debug_struct("InListExpr")
60 .field("expr", &self.expr)
61 .field("list", &self.list)
62 .field("negated", &self.negated)
63 .finish()
64 }
65}
66
67fn supports_arrow_eq(dt: &DataType) -> bool {
74 use DataType::*;
75 match dt {
76 Boolean | Binary | LargeBinary | BinaryView | FixedSizeBinary(_) => true,
77 Dictionary(_, v) => supports_arrow_eq(v.as_ref()),
78 _ => dt.is_primitive() || dt.is_null() || dt.is_string(),
79 }
80}
81
82fn evaluate_list(
84 list: &[Arc<dyn PhysicalExpr>],
85 batch: &RecordBatch,
86) -> Result<ArrayRef> {
87 let scalars = list
88 .iter()
89 .map(|expr| {
90 expr.evaluate(batch).and_then(|r| match r {
91 ColumnarValue::Array(_) => {
92 exec_err!("InList expression must evaluate to a scalar")
93 }
94 ColumnarValue::Scalar(ScalarValue::Dictionary(_, v)) => Ok(*v),
96 ColumnarValue::Scalar(s) => Ok(s),
97 })
98 })
99 .collect::<Result<Vec<_>>>()?;
100
101 ScalarValue::iter_to_array(scalars)
102}
103
104fn try_evaluate_constant_list(
114 list: &[Arc<dyn PhysicalExpr>],
115 schema: &Schema,
116) -> Result<Option<ArrayRef>> {
117 let batch = RecordBatch::new_empty(Arc::new(schema.clone()));
118 match evaluate_list(list, &batch) {
119 Ok(array) => Ok(Some(array)),
120 Err(_) => {
121 Ok(None)
124 }
125 }
126}
127
128fn assert_inlist_data_types_match(
133 expr_data_type: &DataType,
134 list_data_type: &DataType,
135) -> Result<()> {
136 if *list_data_type != DataType::Null {
137 assert_or_internal_err!(
138 DFSchema::datatype_is_logically_equal(expr_data_type, list_data_type),
139 "The data type inlist should be same, the value type is {expr_data_type}, one of list expr type is {list_data_type}"
140 );
141 }
142 Ok(())
143}
144
145impl InListExpr {
146 fn new(
148 expr: Arc<dyn PhysicalExpr>,
149 list: Vec<Arc<dyn PhysicalExpr>>,
150 negated: bool,
151 static_filter: Option<Arc<dyn StaticFilter + Send + Sync>>,
152 ) -> Self {
153 Self {
154 expr,
155 list,
156 negated,
157 static_filter,
158 }
159 }
160
161 pub fn expr(&self) -> &Arc<dyn PhysicalExpr> {
163 &self.expr
164 }
165
166 pub fn list(&self) -> &[Arc<dyn PhysicalExpr>] {
168 &self.list
169 }
170
171 pub fn is_empty(&self) -> bool {
172 self.list.is_empty()
173 }
174
175 pub fn len(&self) -> usize {
176 self.list.len()
177 }
178
179 pub fn negated(&self) -> bool {
181 self.negated
182 }
183
184 pub fn try_new_from_array(
200 expr: Arc<dyn PhysicalExpr>,
201 array: ArrayRef,
202 negated: bool,
203 schema: &Schema,
204 ) -> Result<Self> {
205 let expr_data_type = expr.data_type(schema)?;
206 assert_inlist_data_types_match(&expr_data_type, array.data_type())?;
207
208 let list = (0..array.len())
209 .map(|i| {
210 let scalar = ScalarValue::try_from_array(array.as_ref(), i)?;
211 Ok(crate::expressions::lit(scalar) as Arc<dyn PhysicalExpr>)
212 })
213 .collect::<Result<Vec<_>>>()?;
214 Ok(Self::new(
215 expr,
216 list,
217 negated,
218 Some(instantiate_static_filter(array)?),
219 ))
220 }
221
222 pub fn try_new(
231 expr: Arc<dyn PhysicalExpr>,
232 list: Vec<Arc<dyn PhysicalExpr>>,
233 negated: bool,
234 schema: &Schema,
235 ) -> Result<Self> {
236 let expr_data_type = expr.data_type(schema)?;
238 for list_expr in list.iter() {
239 let list_expr_data_type = list_expr.data_type(schema)?;
240 assert_inlist_data_types_match(&expr_data_type, &list_expr_data_type)?;
241 }
242
243 let static_filter = match try_evaluate_constant_list(&list, schema)? {
245 Some(in_array) => Some(instantiate_static_filter(in_array)?),
246 None => None, };
248
249 Ok(Self::new(expr, list, negated, static_filter))
250 }
251
252 #[cfg(feature = "proto")]
253 pub fn try_from_proto(
254 node: &datafusion_proto_models::protobuf::PhysicalExprNode,
255 ctx: &datafusion_physical_expr_common::physical_expr::proto_decode::PhysicalExprDecodeCtx<'_>,
256 ) -> Result<Arc<dyn PhysicalExpr>> {
257 use datafusion_physical_expr_common::expect_expr_variant;
258 use datafusion_proto_models::protobuf;
259
260 let node = expect_expr_variant!(
261 node,
262 protobuf::physical_expr_node::ExprType::InList,
263 "InList",
264 );
265
266 let expr =
267 ctx.decode_required_expression(node.expr.as_deref(), "InListExpr", "expr")?;
268 let list = ctx.decode_children_expressions(&node.list)?;
269
270 Ok(Arc::new(InListExpr::try_new(
271 expr,
272 list,
273 node.negated,
274 ctx.schema(),
275 )?))
276 }
277}
278impl std::fmt::Display for InListExpr {
279 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
280 let list = expr_vec_fmt!(self.list);
281
282 if self.negated {
283 if self.static_filter.is_some() {
284 write!(f, "{} NOT IN (SET) ([{list}])", self.expr)
285 } else {
286 write!(f, "{} NOT IN ([{list}])", self.expr)
287 }
288 } else if self.static_filter.is_some() {
289 write!(f, "{} IN (SET) ([{list}])", self.expr)
290 } else {
291 write!(f, "{} IN ([{list}])", self.expr)
292 }
293 }
294}
295
296impl PhysicalExpr for InListExpr {
297 fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
298 Ok(DataType::Boolean)
299 }
300
301 fn nullable(&self, input_schema: &Schema) -> Result<bool> {
302 if self.expr.nullable(input_schema)? {
303 return Ok(true);
304 }
305
306 if let Some(static_filter) = &self.static_filter {
307 Ok(static_filter.null_count() > 0)
308 } else {
309 for expr in &self.list {
310 if expr.nullable(input_schema)? {
311 return Ok(true);
312 }
313 }
314 Ok(false)
315 }
316 }
317
318 fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> {
319 let num_rows = batch.num_rows();
320 let value = self.expr.evaluate(batch)?;
321 let r = match &self.static_filter {
322 Some(filter) => {
323 match value {
324 ColumnarValue::Array(array) => {
325 filter.contains(&array, self.negated)?
326 }
327 ColumnarValue::Scalar(scalar) => {
328 if scalar.is_null() {
329 let nulls = NullBuffer::new_null(num_rows);
332 return Ok(ColumnarValue::Array(Arc::new(
333 BooleanArray::new(
334 BooleanBuffer::new_unset(num_rows),
335 Some(nulls),
336 ),
337 )));
338 }
339 let array = scalar.to_array()?;
342 let result_array =
343 filter.contains(array.as_ref(), self.negated)?;
344 if result_array.is_null(0) {
347 let nulls = NullBuffer::new_null(num_rows);
348 BooleanArray::new(
349 BooleanBuffer::new_unset(num_rows),
350 Some(nulls),
351 )
352 } else if result_array.value(0) {
353 BooleanArray::new(BooleanBuffer::new_set(num_rows), None)
354 } else {
355 BooleanArray::new(BooleanBuffer::new_unset(num_rows), None)
356 }
357 }
358 }
359 }
360 None => {
361 let value = value.into_array(num_rows)?;
366 let lhs_supports_arrow_eq = supports_arrow_eq(value.data_type());
367
368 let compare_one = |expr: &Arc<dyn PhysicalExpr>| -> Result<BooleanArray> {
370 match expr.evaluate(batch)? {
371 ColumnarValue::Array(array) => {
372 if lhs_supports_arrow_eq
373 && supports_arrow_eq(array.data_type())
374 {
375 Ok(arrow_eq(&value, &array)?)
376 } else {
377 let cmp = make_comparator(
378 value.as_ref(),
379 array.as_ref(),
380 SortOptions::default(),
381 )?;
382 let buffer = BooleanBuffer::collect_bool(num_rows, |i| {
383 cmp(i, i).is_eq()
384 });
385 let nulls =
386 NullBuffer::union(value.nulls(), array.nulls());
387 Ok(BooleanArray::new(buffer, nulls))
388 }
389 }
390 ColumnarValue::Scalar(scalar) => {
391 if scalar.is_null() {
393 Ok(BooleanArray::from(vec![None; num_rows]))
395 } else if lhs_supports_arrow_eq {
396 let scalar_datum = scalar.to_scalar()?;
397 Ok(arrow_eq(&value, &scalar_datum)?)
398 } else {
399 let array = scalar.to_array()?;
401 let cmp = make_comparator(
402 value.as_ref(),
403 array.as_ref(),
404 SortOptions::default(),
405 )?;
406 let buffer = BooleanBuffer::collect_bool(num_rows, |i| {
408 cmp(i, 0).is_eq()
409 });
410 Ok(BooleanArray::new(buffer, value.nulls().cloned()))
411 }
412 }
413 }
414 };
415
416 let mut found = if let Some(first) = self.list.first() {
419 compare_one(first)?
420 } else {
421 BooleanArray::new(BooleanBuffer::new_unset(num_rows), None)
422 };
423
424 for expr in self.list.iter().skip(1) {
425 if found.null_count() == 0 && !found.has_false() {
428 break;
429 }
430 found = or_kleene(&found, &compare_one(expr)?)?;
431 }
432
433 if self.negated { not(&found)? } else { found }
434 }
435 };
436 Ok(ColumnarValue::Array(Arc::new(r)))
437 }
438
439 fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {
440 let mut children = vec![&self.expr];
441 children.extend(&self.list);
442 children
443 }
444
445 fn with_new_children(
446 self: Arc<Self>,
447 children: Vec<Arc<dyn PhysicalExpr>>,
448 ) -> Result<Arc<dyn PhysicalExpr>> {
449 Ok(Arc::new(InListExpr::new(
451 Arc::clone(&children[0]),
452 children[1..].to_vec(),
453 self.negated,
454 self.static_filter.as_ref().map(Arc::clone),
455 )))
456 }
457
458 fn fmt_sql(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459 self.expr.fmt_sql(f)?;
460 if self.negated {
461 write!(f, " NOT")?;
462 }
463
464 write!(f, " IN (")?;
465 for (i, expr) in self.list.iter().enumerate() {
466 if i > 0 {
467 write!(f, ", ")?;
468 }
469 expr.fmt_sql(f)?;
470 }
471 write!(f, ")")
472 }
473
474 #[cfg(feature = "proto")]
475 fn try_to_proto(
476 &self,
477 ctx: &datafusion_physical_expr_common::physical_expr::proto_encode::PhysicalExprEncodeCtx<'_>,
478 ) -> Result<Option<datafusion_proto_models::protobuf::PhysicalExprNode>> {
479 use datafusion_proto_models::protobuf;
480
481 Ok(Some(protobuf::PhysicalExprNode {
482 expr_id: None,
483 expr_type: Some(protobuf::physical_expr_node::ExprType::InList(Box::new(
484 protobuf::PhysicalInListNode {
485 expr: Some(Box::new(ctx.encode_child(&self.expr)?)),
486 list: ctx.encode_children_expressions(&self.list)?,
487 negated: self.negated,
488 },
489 ))),
490 }))
491 }
492}
493
494impl PartialEq for InListExpr {
495 fn eq(&self, other: &Self) -> bool {
496 self.expr.eq(&other.expr)
497 && physical_exprs_bag_equal(&self.list, &other.list)
498 && self.negated == other.negated
499 }
500}
501
502impl Eq for InListExpr {}
503
504impl Hash for InListExpr {
505 fn hash<H: Hasher>(&self, state: &mut H) {
506 self.expr.hash(state);
507 self.negated.hash(state);
508 self.list.hash(state);
510 }
511}
512
513pub fn in_list(
515 expr: Arc<dyn PhysicalExpr>,
516 list: Vec<Arc<dyn PhysicalExpr>>,
517 negated: &bool,
518 schema: &Schema,
519) -> Result<Arc<dyn PhysicalExpr>> {
520 Ok(Arc::new(InListExpr::try_new(expr, list, *negated, schema)?))
521}
522
523#[cfg(test)]
524mod tests {
525 use super::*;
526 use crate::expressions::{col, lit, try_cast};
527 use arrow::datatypes::{IntervalDayTime, IntervalMonthDayNano, i256};
528 use datafusion_common::plan_err;
529 use datafusion_expr::type_coercion::binary::comparison_coercion;
530 use datafusion_physical_expr_common::physical_expr::fmt_sql;
531 use insta::assert_snapshot;
532 use itertools::Itertools;
533
534 type InListCastResult = (Arc<dyn PhysicalExpr>, Vec<Arc<dyn PhysicalExpr>>);
535
536 fn in_list_cast(
539 expr: Arc<dyn PhysicalExpr>,
540 list: Vec<Arc<dyn PhysicalExpr>>,
541 input_schema: &Schema,
542 ) -> Result<InListCastResult> {
543 let expr_type = &expr.data_type(input_schema)?;
544 let list_types: Vec<DataType> = list
545 .iter()
546 .map(|list_expr| list_expr.data_type(input_schema).unwrap())
547 .collect();
548 let result_type = get_coerce_type(expr_type, &list_types);
549 match result_type {
550 None => plan_err!(
551 "Can not find compatible types to compare {expr_type} with [{}]",
552 list_types.iter().join(", ")
553 ),
554 Some(data_type) => {
555 let cast_expr = try_cast(expr, input_schema, data_type.clone())?;
557 let cast_list_expr = list
558 .into_iter()
559 .map(|list_expr| {
560 try_cast(list_expr, input_schema, data_type.clone()).unwrap()
561 })
562 .collect();
563 Ok((cast_expr, cast_list_expr))
564 }
565 }
566 }
567
568 fn get_coerce_type(expr_type: &DataType, list_type: &[DataType]) -> Option<DataType> {
571 list_type
572 .iter()
573 .try_fold(expr_type.clone(), |left_type, right_type| {
574 comparison_coercion(&left_type, right_type)
575 })
576 }
577
578 macro_rules! in_list {
591 ($BATCH:expr, $LIST:expr, $NEGATED:expr, $EXPECTED:expr, $COL:expr, $SCHEMA:expr) => {{
592 let (cast_expr, cast_list_exprs) = in_list_cast($COL, $LIST, $SCHEMA)?;
593 in_list_raw!(
594 $BATCH,
595 cast_list_exprs,
596 $NEGATED,
597 $EXPECTED,
598 cast_expr,
599 $SCHEMA
600 );
601 }};
602 }
603
604 macro_rules! in_list_raw {
618 ($BATCH:expr, $LIST:expr, $NEGATED:expr, $EXPECTED:expr, $COL:expr, $SCHEMA:expr) => {{
619 let col_expr = $COL;
620 let expr = in_list(Arc::clone(&col_expr), $LIST, $NEGATED, $SCHEMA).unwrap();
621 let result = expr
622 .evaluate(&$BATCH)?
623 .into_array($BATCH.num_rows())
624 .expect("Failed to convert to array");
625 let result = as_boolean_array(&result);
626 let expected = &BooleanArray::from($EXPECTED);
627 assert_eq!(
628 expected,
629 result,
630 "Failed for: {}\n{}: {:?}",
631 fmt_sql(expr.as_ref()),
632 fmt_sql(col_expr.as_ref()),
633 col_expr
634 .evaluate(&$BATCH)?
635 .into_array($BATCH.num_rows())
636 .unwrap()
637 );
638 }};
639 }
640
641 struct InListPrimitiveTestCase {
650 name: &'static str,
651 value_in: ScalarValue,
652 value_not_in: ScalarValue,
653 other_list_values: Vec<ScalarValue>,
654 null_value: Option<ScalarValue>,
655 }
656
657 #[derive(Clone)]
662 struct PrimitiveTestCaseData<T> {
663 value_in: T,
664 value_not_in: T,
665 other_list_values: Vec<T>,
666 }
667
668 fn primitive_test_case<T, D, F>(
674 name: &'static str,
675 constructor: F,
676 data: PrimitiveTestCaseData<D>,
677 ) -> InListPrimitiveTestCase
678 where
679 D: TryInto<T> + Clone,
680 <D as TryInto<T>>::Error: Debug,
681 F: Fn(Option<T>) -> ScalarValue,
682 T: Clone,
683 {
684 InListPrimitiveTestCase {
685 name,
686 value_in: constructor(Some(data.value_in.try_into().unwrap())),
687 value_not_in: constructor(Some(data.value_not_in.try_into().unwrap())),
688 other_list_values: data
689 .other_list_values
690 .into_iter()
691 .map(|v| constructor(Some(v.try_into().unwrap())))
692 .collect(),
693 null_value: Some(constructor(None)),
694 }
695 }
696
697 fn primitive_test_case_no_nulls<T, D, F>(
700 name: &'static str,
701 constructor: F,
702 data: PrimitiveTestCaseData<D>,
703 ) -> InListPrimitiveTestCase
704 where
705 D: TryInto<T> + Clone,
706 <D as TryInto<T>>::Error: Debug,
707 F: Fn(Option<T>) -> ScalarValue,
708 T: Clone,
709 {
710 InListPrimitiveTestCase {
711 name,
712 value_in: constructor(Some(data.value_in.try_into().unwrap())),
713 value_not_in: constructor(Some(data.value_not_in.try_into().unwrap())),
714 other_list_values: data
715 .other_list_values
716 .into_iter()
717 .map(|v| constructor(Some(v.try_into().unwrap())))
718 .collect(),
719 null_value: None,
720 }
721 }
722
723 fn run_test_cases(test_cases: Vec<InListPrimitiveTestCase>) -> Result<()> {
729 for test_case in test_cases {
730 let test_name = test_case.name;
731
732 let data_type = test_case.value_in.data_type();
734
735 let build_base_list = || -> Vec<Arc<dyn PhysicalExpr>> {
737 let mut list = vec![lit(test_case.value_in.clone())];
738 list.extend(test_case.other_list_values.iter().map(|v| lit(v.clone())));
739 list
740 };
741
742 match &test_case.null_value {
743 Some(null_val) => {
744 let schema =
746 Schema::new(vec![Field::new("a", data_type.clone(), true)]);
747
748 let array = ScalarValue::iter_to_array(vec![
750 test_case.value_in.clone(),
751 test_case.value_not_in.clone(),
752 null_val.clone(),
753 ])?;
754
755 let col_a = col("a", &schema)?;
756 let batch = RecordBatch::try_new(
757 Arc::new(schema.clone()),
758 vec![Arc::clone(&array)],
759 )?;
760
761 let list = build_base_list();
763 in_list!(
764 batch,
765 list,
766 &false,
767 vec![Some(true), Some(false), None],
768 Arc::clone(&col_a),
769 &schema
770 );
771
772 let list = build_base_list();
774 in_list!(
775 batch,
776 list,
777 &true,
778 vec![Some(false), Some(true), None],
779 Arc::clone(&col_a),
780 &schema
781 );
782
783 let mut list = build_base_list();
785 list.push(lit(null_val.clone()));
786 in_list!(
787 batch,
788 list,
789 &false,
790 vec![Some(true), None, None],
791 Arc::clone(&col_a),
792 &schema
793 );
794
795 let mut list = build_base_list();
797 list.push(lit(null_val.clone()));
798 in_list!(
799 batch,
800 list,
801 &true,
802 vec![Some(false), None, None],
803 Arc::clone(&col_a),
804 &schema
805 );
806 }
807 None => {
808 let schema =
810 Schema::new(vec![Field::new("a", data_type.clone(), false)]);
811
812 let array = ScalarValue::iter_to_array(vec![
814 test_case.value_in.clone(),
815 test_case.value_not_in.clone(),
816 ])?;
817
818 let col_a = col("a", &schema)?;
819 let batch = RecordBatch::try_new(
820 Arc::new(schema.clone()),
821 vec![Arc::clone(&array)],
822 )?;
823
824 let list = build_base_list();
826 in_list!(
827 batch,
828 list,
829 &false,
830 vec![Some(true), Some(false)],
831 Arc::clone(&col_a),
832 &schema
833 );
834
835 let list = build_base_list();
837 in_list!(
838 batch,
839 list,
840 &true,
841 vec![Some(false), Some(true)],
842 Arc::clone(&col_a),
843 &schema
844 );
845
846 eprintln!(
847 "Test '{test_name}': exercised (false, true) branch (no nulls, negated)",
848 );
849 }
850 }
851 }
852
853 Ok(())
854 }
855
856 #[test]
860 fn in_list_int_types() -> Result<()> {
861 let int_data = PrimitiveTestCaseData {
862 value_in: 0,
863 value_not_in: 2,
864 other_list_values: vec![1, 3, 5],
865 };
866
867 run_test_cases(vec![
868 primitive_test_case("int8", ScalarValue::Int8, int_data.clone()),
870 primitive_test_case("int16", ScalarValue::Int16, int_data.clone()),
871 primitive_test_case("int32", ScalarValue::Int32, int_data.clone()),
872 primitive_test_case("int64", ScalarValue::Int64, int_data.clone()),
873 primitive_test_case("uint8", ScalarValue::UInt8, int_data.clone()),
874 primitive_test_case("uint16", ScalarValue::UInt16, int_data.clone()),
875 primitive_test_case("uint32", ScalarValue::UInt32, int_data.clone()),
876 primitive_test_case("uint64", ScalarValue::UInt64, int_data.clone()),
877 primitive_test_case_no_nulls("int32_no_nulls", ScalarValue::Int32, int_data),
879 ])
880 }
881
882 #[test]
886 fn in_list_string_types() -> Result<()> {
887 let string_data = PrimitiveTestCaseData {
888 value_in: "a",
889 value_not_in: "d",
890 other_list_values: vec!["b", "c"],
891 };
892
893 run_test_cases(vec![
894 primitive_test_case("utf8", ScalarValue::Utf8, string_data.clone()),
895 primitive_test_case(
896 "large_utf8",
897 ScalarValue::LargeUtf8,
898 string_data.clone(),
899 ),
900 primitive_test_case("utf8_view", ScalarValue::Utf8View, string_data),
901 ])
902 }
903
904 #[test]
908 fn in_list_binary_types() -> Result<()> {
909 let binary_data = PrimitiveTestCaseData {
910 value_in: vec![1_u8, 2, 3],
911 value_not_in: vec![1_u8, 2, 2],
912 other_list_values: vec![vec![4_u8, 5, 6], vec![7_u8, 8, 9]],
913 };
914
915 run_test_cases(vec![
916 primitive_test_case("binary", ScalarValue::Binary, binary_data.clone()),
917 primitive_test_case(
918 "large_binary",
919 ScalarValue::LargeBinary,
920 binary_data.clone(),
921 ),
922 primitive_test_case("binary_view", ScalarValue::BinaryView, binary_data),
923 ])
924 }
925
926 #[test]
930 fn in_list_date_types() -> Result<()> {
931 let date_data = PrimitiveTestCaseData {
932 value_in: 0,
933 value_not_in: 2,
934 other_list_values: vec![1, 3],
935 };
936
937 run_test_cases(vec![
938 primitive_test_case("date32", ScalarValue::Date32, date_data.clone()),
939 primitive_test_case("date64", ScalarValue::Date64, date_data),
940 ])
941 }
942
943 #[test]
947 fn in_list_decimal() -> Result<()> {
948 run_test_cases(vec![InListPrimitiveTestCase {
949 name: "decimal128",
950 value_in: ScalarValue::Decimal128(Some(0), 10, 2),
951 value_not_in: ScalarValue::Decimal128(Some(200), 10, 2),
952 other_list_values: vec![
953 ScalarValue::Decimal128(Some(100), 10, 2),
954 ScalarValue::Decimal128(Some(300), 10, 2),
955 ],
956 null_value: Some(ScalarValue::Decimal128(None, 10, 2)),
957 }])
958 }
959
960 #[test]
964 fn in_list_timestamp_types() -> Result<()> {
965 run_test_cases(vec![
966 InListPrimitiveTestCase {
967 name: "timestamp_nanosecond",
968 value_in: ScalarValue::TimestampNanosecond(Some(0), None),
969 value_not_in: ScalarValue::TimestampNanosecond(Some(2000), None),
970 other_list_values: vec![
971 ScalarValue::TimestampNanosecond(Some(1000), None),
972 ScalarValue::TimestampNanosecond(Some(3000), None),
973 ],
974 null_value: Some(ScalarValue::TimestampNanosecond(None, None)),
975 },
976 InListPrimitiveTestCase {
977 name: "timestamp_millisecond_with_tz",
978 value_in: ScalarValue::TimestampMillisecond(
979 Some(1500000),
980 Some("+05:00".into()),
981 ),
982 value_not_in: ScalarValue::TimestampMillisecond(
983 Some(2500000),
984 Some("+05:00".into()),
985 ),
986 other_list_values: vec![ScalarValue::TimestampMillisecond(
987 Some(3500000),
988 Some("+05:00".into()),
989 )],
990 null_value: Some(ScalarValue::TimestampMillisecond(
991 None,
992 Some("+05:00".into()),
993 )),
994 },
995 InListPrimitiveTestCase {
996 name: "timestamp_millisecond_mixed_tz",
997 value_in: ScalarValue::TimestampMillisecond(
998 Some(1500000),
999 Some("+05:00".into()),
1000 ),
1001 value_not_in: ScalarValue::TimestampMillisecond(
1002 Some(2500000),
1003 Some("+05:00".into()),
1004 ),
1005 other_list_values: vec![
1006 ScalarValue::TimestampMillisecond(
1007 Some(3500000),
1008 Some("+01:00".into()),
1009 ),
1010 ScalarValue::TimestampMillisecond(Some(4500000), Some("UTC".into())),
1011 ],
1012 null_value: Some(ScalarValue::TimestampMillisecond(
1013 None,
1014 Some("+05:00".into()),
1015 )),
1016 },
1017 ])
1018 }
1019
1020 #[test]
1021 fn in_list_float64() -> Result<()> {
1022 let schema = Schema::new(vec![Field::new("a", DataType::Float64, true)]);
1023 let a = Float64Array::from(vec![
1024 Some(0.0),
1025 Some(0.2),
1026 None,
1027 Some(f64::NAN),
1028 Some(-f64::NAN),
1029 ]);
1030 let col_a = col("a", &schema)?;
1031 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1032
1033 let list = vec![lit(0.0f64), lit(0.1f64)];
1035 in_list!(
1036 batch,
1037 list,
1038 &false,
1039 vec![Some(true), Some(false), None, Some(false), Some(false)],
1040 Arc::clone(&col_a),
1041 &schema
1042 );
1043
1044 let list = vec![lit(0.0f64), lit(0.1f64)];
1046 in_list!(
1047 batch,
1048 list,
1049 &true,
1050 vec![Some(false), Some(true), None, Some(true), Some(true)],
1051 Arc::clone(&col_a),
1052 &schema
1053 );
1054
1055 let list = vec![lit(0.0f64), lit(0.1f64), lit(ScalarValue::Null)];
1057 in_list!(
1058 batch,
1059 list,
1060 &false,
1061 vec![Some(true), None, None, None, None],
1062 Arc::clone(&col_a),
1063 &schema
1064 );
1065
1066 let list = vec![lit(0.0f64), lit(0.1f64), lit(ScalarValue::Null)];
1068 in_list!(
1069 batch,
1070 list,
1071 &true,
1072 vec![Some(false), None, None, None, None],
1073 Arc::clone(&col_a),
1074 &schema
1075 );
1076
1077 let list = vec![lit(0.0f64), lit(0.1f64), lit(f64::NAN)];
1079 in_list!(
1080 batch,
1081 list,
1082 &false,
1083 vec![Some(true), Some(false), None, Some(true), Some(false)],
1084 Arc::clone(&col_a),
1085 &schema
1086 );
1087
1088 let list = vec![lit(0.0f64), lit(0.1f64), lit(f64::NAN)];
1090 in_list!(
1091 batch,
1092 list,
1093 &true,
1094 vec![Some(false), Some(true), None, Some(false), Some(true)],
1095 Arc::clone(&col_a),
1096 &schema
1097 );
1098
1099 let list = vec![lit(0.0f64), lit(0.1f64), lit(-f64::NAN)];
1101 in_list!(
1102 batch,
1103 list,
1104 &false,
1105 vec![Some(true), Some(false), None, Some(false), Some(true)],
1106 Arc::clone(&col_a),
1107 &schema
1108 );
1109
1110 let list = vec![lit(0.0f64), lit(0.1f64), lit(-f64::NAN)];
1112 in_list!(
1113 batch,
1114 list,
1115 &true,
1116 vec![Some(false), Some(true), None, Some(true), Some(false)],
1117 Arc::clone(&col_a),
1118 &schema
1119 );
1120
1121 Ok(())
1122 }
1123
1124 #[test]
1125 fn in_list_bool() -> Result<()> {
1126 let schema = Schema::new(vec![Field::new("a", DataType::Boolean, true)]);
1127 let a = BooleanArray::from(vec![Some(true), None]);
1128 let col_a = col("a", &schema)?;
1129 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1130
1131 let list = vec![lit(true)];
1133 in_list!(
1134 batch,
1135 list,
1136 &false,
1137 vec![Some(true), None],
1138 Arc::clone(&col_a),
1139 &schema
1140 );
1141
1142 let list = vec![lit(true)];
1144 in_list!(
1145 batch,
1146 list,
1147 &true,
1148 vec![Some(false), None],
1149 Arc::clone(&col_a),
1150 &schema
1151 );
1152
1153 let list = vec![lit(true), lit(ScalarValue::Null)];
1155 in_list!(
1156 batch,
1157 list,
1158 &false,
1159 vec![Some(true), None],
1160 Arc::clone(&col_a),
1161 &schema
1162 );
1163
1164 let list = vec![lit(true), lit(ScalarValue::Null)];
1166 in_list!(
1167 batch,
1168 list,
1169 &true,
1170 vec![Some(false), None],
1171 Arc::clone(&col_a),
1172 &schema
1173 );
1174
1175 Ok(())
1176 }
1177
1178 macro_rules! test_nullable {
1179 ($COL:expr, $LIST:expr, $SCHEMA:expr, $EXPECTED:expr) => {{
1180 let (cast_expr, cast_list_exprs) = in_list_cast($COL, $LIST, $SCHEMA)?;
1181 let expr = in_list(cast_expr, cast_list_exprs, &false, $SCHEMA).unwrap();
1182 let result = expr.nullable($SCHEMA)?;
1183 assert_eq!($EXPECTED, result);
1184 }};
1185 }
1186
1187 #[test]
1188 fn in_list_nullable() -> Result<()> {
1189 let schema = Schema::new(vec![
1190 Field::new("c1_nullable", DataType::Int64, true),
1191 Field::new("c2_non_nullable", DataType::Int64, false),
1192 ]);
1193
1194 let c1_nullable = col("c1_nullable", &schema)?;
1195 let c2_non_nullable = col("c2_non_nullable", &schema)?;
1196
1197 let list = vec![lit(1_i64), lit(2_i64)];
1199 test_nullable!(Arc::clone(&c1_nullable), list.clone(), &schema, true);
1200 test_nullable!(Arc::clone(&c2_non_nullable), list.clone(), &schema, false);
1201
1202 let list = vec![lit(1_i64), lit(2_i64), lit(ScalarValue::Null)];
1204 test_nullable!(Arc::clone(&c1_nullable), list.clone(), &schema, true);
1205 test_nullable!(Arc::clone(&c2_non_nullable), list.clone(), &schema, true);
1206
1207 let list = vec![Arc::clone(&c1_nullable)];
1208 test_nullable!(Arc::clone(&c2_non_nullable), list.clone(), &schema, true);
1209
1210 let list = vec![Arc::clone(&c2_non_nullable)];
1211 test_nullable!(Arc::clone(&c1_nullable), list.clone(), &schema, true);
1212
1213 let list = vec![Arc::clone(&c2_non_nullable), Arc::clone(&c2_non_nullable)];
1214 test_nullable!(Arc::clone(&c2_non_nullable), list.clone(), &schema, false);
1215
1216 Ok(())
1217 }
1218
1219 #[test]
1220 fn in_list_no_cols() -> Result<()> {
1221 let schema = Schema::new(vec![Field::new("a", DataType::Int32, true)]);
1223 let a = Int32Array::from(vec![Some(1), Some(2), None]);
1224 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1225
1226 let list = vec![lit(ScalarValue::from(1i32)), lit(ScalarValue::from(6i32))];
1227
1228 let expr = lit(ScalarValue::Int32(Some(1)));
1230 in_list!(
1231 batch,
1232 list.clone(),
1233 &false,
1234 vec![Some(true), Some(true), Some(true)],
1236 expr,
1237 &schema
1238 );
1239
1240 let expr = lit(ScalarValue::Int32(Some(2)));
1242 in_list!(
1243 batch,
1244 list.clone(),
1245 &false,
1246 vec![Some(false), Some(false), Some(false)],
1248 expr,
1249 &schema
1250 );
1251
1252 let expr = lit(ScalarValue::Int32(None));
1254 in_list!(
1255 batch,
1256 list.clone(),
1257 &false,
1258 vec![None, None, None],
1260 expr,
1261 &schema
1262 );
1263
1264 Ok(())
1265 }
1266
1267 #[test]
1268 fn in_list_utf8_with_dict_types() -> Result<()> {
1269 fn dict_lit(key_type: DataType, value: &str) -> Arc<dyn PhysicalExpr> {
1270 lit(ScalarValue::Dictionary(
1271 Box::new(key_type),
1272 Box::new(ScalarValue::new_utf8(value.to_string())),
1273 ))
1274 }
1275
1276 fn null_dict_lit(key_type: DataType) -> Arc<dyn PhysicalExpr> {
1277 lit(ScalarValue::Dictionary(
1278 Box::new(key_type),
1279 Box::new(ScalarValue::Utf8(None)),
1280 ))
1281 }
1282
1283 let schema = Schema::new(vec![Field::new(
1284 "a",
1285 DataType::Dictionary(Box::new(DataType::UInt16), Box::new(DataType::Utf8)),
1286 true,
1287 )]);
1288 let a: UInt16DictionaryArray =
1289 vec![Some("a"), Some("d"), None].into_iter().collect();
1290 let col_a = col("a", &schema)?;
1291 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1292
1293 let lists = [
1295 vec![lit("a"), lit("b")],
1296 vec![
1297 dict_lit(DataType::Int8, "a"),
1298 dict_lit(DataType::UInt16, "b"),
1299 ],
1300 ];
1301 for list in lists.iter() {
1302 in_list_raw!(
1303 batch,
1304 list.clone(),
1305 &false,
1306 vec![Some(true), Some(false), None],
1307 Arc::clone(&col_a),
1308 &schema
1309 );
1310 }
1311
1312 for list in lists.iter() {
1314 in_list_raw!(
1315 batch,
1316 list.clone(),
1317 &true,
1318 vec![Some(false), Some(true), None],
1319 Arc::clone(&col_a),
1320 &schema
1321 );
1322 }
1323
1324 let lists = [
1326 vec![lit("a"), lit("b"), lit(ScalarValue::Utf8(None))],
1327 vec![
1328 dict_lit(DataType::Int8, "a"),
1329 dict_lit(DataType::UInt16, "b"),
1330 null_dict_lit(DataType::UInt16),
1331 ],
1332 ];
1333 for list in lists.iter() {
1334 in_list_raw!(
1335 batch,
1336 list.clone(),
1337 &false,
1338 vec![Some(true), None, None],
1339 Arc::clone(&col_a),
1340 &schema
1341 );
1342 }
1343
1344 for list in lists.iter() {
1346 in_list_raw!(
1347 batch,
1348 list.clone(),
1349 &true,
1350 vec![Some(false), None, None],
1351 Arc::clone(&col_a),
1352 &schema
1353 );
1354 }
1355
1356 Ok(())
1357 }
1358
1359 #[test]
1360 fn test_fmt_sql_1() -> Result<()> {
1361 let schema = Schema::new(vec![Field::new("a", DataType::Utf8, true)]);
1362 let col_a = col("a", &schema)?;
1363
1364 let list = vec![lit("a"), lit("b")];
1366 let expr = in_list(Arc::clone(&col_a), list, &false, &schema)?;
1367 let sql_string = fmt_sql(expr.as_ref()).to_string();
1368 let display_string = expr.to_string();
1369 assert_snapshot!(sql_string, @"a IN (a, b)");
1370 assert_snapshot!(display_string, @"a@0 IN (SET) ([a, b])");
1371 Ok(())
1372 }
1373
1374 #[test]
1375 fn test_fmt_sql_2() -> Result<()> {
1376 let schema = Schema::new(vec![Field::new("a", DataType::Utf8, true)]);
1377 let col_a = col("a", &schema)?;
1378
1379 let list = vec![lit("a"), lit("b")];
1381 let expr = in_list(Arc::clone(&col_a), list, &true, &schema)?;
1382 let sql_string = fmt_sql(expr.as_ref()).to_string();
1383 let display_string = expr.to_string();
1384
1385 assert_snapshot!(sql_string, @"a NOT IN (a, b)");
1386 assert_snapshot!(display_string, @"a@0 NOT IN (SET) ([a, b])");
1387 Ok(())
1388 }
1389
1390 #[test]
1391 fn test_fmt_sql_3() -> Result<()> {
1392 let schema = Schema::new(vec![Field::new("a", DataType::Utf8, true)]);
1393 let col_a = col("a", &schema)?;
1394 let list = vec![lit("a"), lit("b"), lit(ScalarValue::Utf8(None))];
1396 let expr = in_list(Arc::clone(&col_a), list, &false, &schema)?;
1397 let sql_string = fmt_sql(expr.as_ref()).to_string();
1398 let display_string = expr.to_string();
1399
1400 assert_snapshot!(sql_string, @"a IN (a, b, NULL)");
1401 assert_snapshot!(display_string, @"a@0 IN (SET) ([a, b, NULL])");
1402 Ok(())
1403 }
1404
1405 #[test]
1406 fn test_fmt_sql_4() -> Result<()> {
1407 let schema = Schema::new(vec![Field::new("a", DataType::Utf8, true)]);
1408 let col_a = col("a", &schema)?;
1409 let list = vec![lit("a"), lit("b"), lit(ScalarValue::Utf8(None))];
1411 let expr = in_list(Arc::clone(&col_a), list, &true, &schema)?;
1412 let sql_string = fmt_sql(expr.as_ref()).to_string();
1413 let display_string = expr.to_string();
1414 assert_snapshot!(sql_string, @"a NOT IN (a, b, NULL)");
1415 assert_snapshot!(display_string, @"a@0 NOT IN (SET) ([a, b, NULL])");
1416 Ok(())
1417 }
1418
1419 #[test]
1420 fn in_list_struct() -> Result<()> {
1421 let struct_fields = Fields::from(vec![
1423 Field::new("x", DataType::Int32, false),
1424 Field::new("y", DataType::Utf8, false),
1425 ]);
1426 let schema = Schema::new(vec![Field::new(
1427 "a",
1428 DataType::Struct(struct_fields.clone()),
1429 true,
1430 )]);
1431
1432 let x_array = Arc::new(Int32Array::from(vec![1, 2, 3]));
1434 let y_array = Arc::new(StringArray::from(vec!["a", "b", "c"]));
1435 let struct_array =
1436 StructArray::new(struct_fields.clone(), vec![x_array, y_array], None);
1437
1438 let col_a = col("a", &schema)?;
1439 let batch =
1440 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(struct_array)])?;
1441
1442 let struct1 = ScalarValue::Struct(Arc::new(StructArray::new(
1445 struct_fields.clone(),
1446 vec![
1447 Arc::new(Int32Array::from(vec![1])),
1448 Arc::new(StringArray::from(vec!["a"])),
1449 ],
1450 None,
1451 )));
1452
1453 let struct3 = ScalarValue::Struct(Arc::new(StructArray::new(
1455 struct_fields.clone(),
1456 vec![
1457 Arc::new(Int32Array::from(vec![3])),
1458 Arc::new(StringArray::from(vec!["c"])),
1459 ],
1460 None,
1461 )));
1462
1463 let list = vec![lit(struct1.clone()), lit(struct3.clone())];
1465 in_list_raw!(
1466 batch,
1467 list.clone(),
1468 &false,
1469 vec![Some(true), Some(false), Some(true)],
1470 Arc::clone(&col_a),
1471 &schema
1472 );
1473
1474 in_list_raw!(
1476 batch,
1477 list,
1478 &true,
1479 vec![Some(false), Some(true), Some(false)],
1480 Arc::clone(&col_a),
1481 &schema
1482 );
1483
1484 Ok(())
1485 }
1486
1487 #[test]
1488 fn in_list_struct_with_nulls() -> Result<()> {
1489 let struct_fields = Fields::from(vec![
1491 Field::new("x", DataType::Int32, false),
1492 Field::new("y", DataType::Utf8, false),
1493 ]);
1494 let schema = Schema::new(vec![Field::new(
1495 "a",
1496 DataType::Struct(struct_fields.clone()),
1497 true,
1498 )]);
1499
1500 let x_array = Arc::new(Int32Array::from(vec![1, 2]));
1502 let y_array = Arc::new(StringArray::from(vec!["a", "b"]));
1503 let struct_array = StructArray::new(
1504 struct_fields.clone(),
1505 vec![x_array, y_array],
1506 Some(NullBuffer::from(vec![true, false])),
1507 );
1508
1509 let col_a = col("a", &schema)?;
1510 let batch =
1511 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(struct_array)])?;
1512
1513 let struct1 = ScalarValue::Struct(Arc::new(StructArray::new(
1515 struct_fields.clone(),
1516 vec![
1517 Arc::new(Int32Array::from(vec![1])),
1518 Arc::new(StringArray::from(vec!["a"])),
1519 ],
1520 None,
1521 )));
1522
1523 let list = vec![lit(struct1.clone())];
1525 in_list_raw!(
1526 batch,
1527 list.clone(),
1528 &false,
1529 vec![Some(true), None],
1530 Arc::clone(&col_a),
1531 &schema
1532 );
1533
1534 in_list_raw!(
1536 batch,
1537 list,
1538 &true,
1539 vec![Some(false), None],
1540 Arc::clone(&col_a),
1541 &schema
1542 );
1543
1544 Ok(())
1545 }
1546
1547 #[test]
1548 fn in_list_struct_with_null_in_list() -> Result<()> {
1549 let struct_fields = Fields::from(vec![
1551 Field::new("x", DataType::Int32, false),
1552 Field::new("y", DataType::Utf8, false),
1553 ]);
1554 let schema = Schema::new(vec![Field::new(
1555 "a",
1556 DataType::Struct(struct_fields.clone()),
1557 true,
1558 )]);
1559
1560 let x_array = Arc::new(Int32Array::from(vec![1, 2, 3]));
1562 let y_array = Arc::new(StringArray::from(vec!["a", "b", "c"]));
1563 let struct_array =
1564 StructArray::new(struct_fields.clone(), vec![x_array, y_array], None);
1565
1566 let col_a = col("a", &schema)?;
1567 let batch =
1568 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(struct_array)])?;
1569
1570 let struct1 = ScalarValue::Struct(Arc::new(StructArray::new(
1572 struct_fields.clone(),
1573 vec![
1574 Arc::new(Int32Array::from(vec![1])),
1575 Arc::new(StringArray::from(vec!["a"])),
1576 ],
1577 None,
1578 )));
1579
1580 let null_struct = ScalarValue::Struct(Arc::new(StructArray::new_null(
1581 struct_fields.clone(),
1582 1,
1583 )));
1584
1585 let list = vec![lit(struct1), lit(null_struct.clone())];
1587 in_list_raw!(
1588 batch,
1589 list.clone(),
1590 &false,
1591 vec![Some(true), None, None],
1592 Arc::clone(&col_a),
1593 &schema
1594 );
1595
1596 in_list_raw!(
1598 batch,
1599 list,
1600 &true,
1601 vec![Some(false), None, None],
1602 Arc::clone(&col_a),
1603 &schema
1604 );
1605
1606 Ok(())
1607 }
1608
1609 #[test]
1610 fn in_list_nested_struct() -> Result<()> {
1611 let inner_struct_fields = Fields::from(vec![
1613 Field::new("a", DataType::Int32, false),
1614 Field::new("b", DataType::Utf8, false),
1615 ]);
1616 let outer_struct_fields = Fields::from(vec![
1617 Field::new(
1618 "inner",
1619 DataType::Struct(inner_struct_fields.clone()),
1620 false,
1621 ),
1622 Field::new("c", DataType::Int32, false),
1623 ]);
1624 let schema = Schema::new(vec![Field::new(
1625 "x",
1626 DataType::Struct(outer_struct_fields.clone()),
1627 true,
1628 )]);
1629
1630 let inner1 = Arc::new(StructArray::new(
1632 inner_struct_fields.clone(),
1633 vec![
1634 Arc::new(Int32Array::from(vec![1, 2])),
1635 Arc::new(StringArray::from(vec!["x", "y"])),
1636 ],
1637 None,
1638 ));
1639 let c_array = Arc::new(Int32Array::from(vec![10, 20]));
1640 let outer_array =
1641 StructArray::new(outer_struct_fields.clone(), vec![inner1, c_array], None);
1642
1643 let col_x = col("x", &schema)?;
1644 let batch =
1645 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(outer_array)])?;
1646
1647 let inner_match = Arc::new(StructArray::new(
1649 inner_struct_fields.clone(),
1650 vec![
1651 Arc::new(Int32Array::from(vec![1])),
1652 Arc::new(StringArray::from(vec!["x"])),
1653 ],
1654 None,
1655 ));
1656 let outer_match = ScalarValue::Struct(Arc::new(StructArray::new(
1657 outer_struct_fields.clone(),
1658 vec![inner_match, Arc::new(Int32Array::from(vec![10]))],
1659 None,
1660 )));
1661
1662 let list = vec![lit(outer_match)];
1664 in_list_raw!(
1665 batch,
1666 list.clone(),
1667 &false,
1668 vec![Some(true), Some(false)],
1669 Arc::clone(&col_x),
1670 &schema
1671 );
1672
1673 in_list_raw!(
1675 batch,
1676 list,
1677 &true,
1678 vec![Some(false), Some(true)],
1679 Arc::clone(&col_x),
1680 &schema
1681 );
1682
1683 Ok(())
1684 }
1685
1686 #[test]
1687 fn in_list_struct_with_exprs_not_array() -> Result<()> {
1688 let struct_fields = Fields::from(vec![
1694 Field::new("x", DataType::Int32, false),
1695 Field::new("y", DataType::Utf8, false),
1696 ]);
1697 let schema = Schema::new(vec![Field::new(
1698 "a",
1699 DataType::Struct(struct_fields.clone()),
1700 true,
1701 )]);
1702
1703 let x_array = Arc::new(Int32Array::from(vec![1, 2, 3]));
1705 let y_array = Arc::new(StringArray::from(vec!["a", "b", "c"]));
1706 let struct_array =
1707 StructArray::new(struct_fields.clone(), vec![x_array, y_array], None);
1708
1709 let col_a = col("a", &schema)?;
1710 let batch =
1711 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(struct_array)])?;
1712
1713 let struct1 = ScalarValue::Struct(Arc::new(StructArray::new(
1716 struct_fields.clone(),
1717 vec![
1718 Arc::new(Int32Array::from(vec![1])),
1719 Arc::new(StringArray::from(vec!["a"])),
1720 ],
1721 None,
1722 )));
1723
1724 let struct3 = ScalarValue::Struct(Arc::new(StructArray::new(
1726 struct_fields.clone(),
1727 vec![
1728 Arc::new(Int32Array::from(vec![3])),
1729 Arc::new(StringArray::from(vec!["c"])),
1730 ],
1731 None,
1732 )));
1733
1734 let list = vec![lit(struct1), lit(struct3)];
1736
1737 let expr = Arc::new(InListExpr::new(Arc::clone(&col_a), list, false, None));
1740
1741 let display_string = expr.to_string();
1744 assert!(
1745 !display_string.contains("(SET)"),
1746 "Expected display string to NOT contain '(SET)' (should use Exprs variant), but got: {display_string}",
1747 );
1748
1749 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
1751 let result = as_boolean_array(&result);
1752
1753 let expected = BooleanArray::from(vec![Some(true), Some(false), Some(true)]);
1757 assert_eq!(result, &expected);
1758
1759 let expr_not = Arc::new(InListExpr::new(
1761 Arc::clone(&col_a),
1762 vec![
1763 lit(ScalarValue::Struct(Arc::new(StructArray::new(
1764 struct_fields.clone(),
1765 vec![
1766 Arc::new(Int32Array::from(vec![1])),
1767 Arc::new(StringArray::from(vec!["a"])),
1768 ],
1769 None,
1770 )))),
1771 lit(ScalarValue::Struct(Arc::new(StructArray::new(
1772 struct_fields.clone(),
1773 vec![
1774 Arc::new(Int32Array::from(vec![3])),
1775 Arc::new(StringArray::from(vec!["c"])),
1776 ],
1777 None,
1778 )))),
1779 ],
1780 true,
1781 None,
1782 ));
1783
1784 let result_not = expr_not.evaluate(&batch)?.into_array(batch.num_rows())?;
1785 let result_not = as_boolean_array(&result_not);
1786
1787 let expected_not = BooleanArray::from(vec![Some(false), Some(true), Some(false)]);
1788 assert_eq!(result_not, &expected_not);
1789
1790 Ok(())
1791 }
1792
1793 #[test]
1794 fn test_in_list_null_handling_comprehensive() -> Result<()> {
1795 let schema = Schema::new(vec![Field::new("a", DataType::Int64, true)]);
1798
1799 let a = Int64Array::from(vec![Some(1), Some(2), Some(3), None]);
1805 let col_a = col("a", &schema)?;
1806 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1807
1808 let list = vec![lit(1i64), lit(4i64)];
1811 in_list!(
1812 batch,
1813 list,
1814 &false,
1815 vec![
1816 Some(true), Some(false), Some(false), None, ],
1821 Arc::clone(&col_a),
1822 &schema
1823 );
1824
1825 let list = vec![lit(1i64), lit(ScalarValue::Int64(None))];
1828 in_list!(
1829 batch,
1830 list,
1831 &false,
1832 vec![
1833 Some(true), None, None, None, ],
1838 Arc::clone(&col_a),
1839 &schema
1840 );
1841
1842 Ok(())
1843 }
1844
1845 #[test]
1846 fn test_in_list_with_only_nulls() -> Result<()> {
1847 let schema = Schema::new(vec![Field::new("a", DataType::Int64, true)]);
1849 let a = Int64Array::from(vec![Some(1), Some(2), None]);
1850 let col_a = col("a", &schema)?;
1851 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1852
1853 let list = vec![lit(ScalarValue::Int64(None)), lit(ScalarValue::Int64(None))];
1855
1856 in_list!(
1860 batch,
1861 list.clone(),
1862 &false,
1863 vec![None, None, None],
1864 Arc::clone(&col_a),
1865 &schema
1866 );
1867
1868 in_list!(
1871 batch,
1872 list,
1873 &true,
1874 vec![None, None, None],
1875 Arc::clone(&col_a),
1876 &schema
1877 );
1878
1879 Ok(())
1880 }
1881
1882 #[test]
1883 fn test_in_list_multiple_nulls_deduplication() -> Result<()> {
1884 let schema = Schema::new(vec![Field::new("a", DataType::Int64, true)]);
1887 let col_a = col("a", &schema)?;
1888
1889 let array = Arc::new(Int64Array::from(vec![
1891 Some(1),
1892 Some(2),
1893 None,
1894 None,
1895 Some(3),
1896 None,
1897 ])) as ArrayRef;
1898
1899 let expr = Arc::new(InListExpr::try_new_from_array(
1901 Arc::clone(&col_a),
1902 array,
1903 false,
1904 &schema,
1905 )?) as Arc<dyn PhysicalExpr>;
1906
1907 let a = Int64Array::from(vec![Some(1), Some(2), Some(3), Some(4), None]);
1909 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1910
1911 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
1913 let result = as_boolean_array(&result);
1914
1915 let expected = BooleanArray::from(vec![
1920 Some(true), Some(true), Some(true), None, None, ]);
1926 assert_eq!(result, &expected);
1927
1928 Ok(())
1929 }
1930
1931 #[test]
1932 fn test_not_in_null_handling_comprehensive() -> Result<()> {
1933 let schema = Schema::new(vec![Field::new("a", DataType::Int64, true)]);
1936
1937 let a = Int64Array::from(vec![Some(1), Some(2), Some(3), None]);
1939 let col_a = col("a", &schema)?;
1940 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1941
1942 let list = vec![lit(1i64), lit(4i64)];
1945 in_list!(
1946 batch,
1947 list,
1948 &true,
1949 vec![
1950 Some(false), Some(true), Some(true), None, ],
1955 Arc::clone(&col_a),
1956 &schema
1957 );
1958
1959 let list = vec![lit(1i64), lit(ScalarValue::Int64(None))];
1962 in_list!(
1963 batch,
1964 list,
1965 &true,
1966 vec![
1967 Some(false), None, None, None, ],
1972 Arc::clone(&col_a),
1973 &schema
1974 );
1975
1976 Ok(())
1977 }
1978
1979 #[test]
1980 fn test_in_list_null_type_column() -> Result<()> {
1981 let schema = Schema::new(vec![Field::new("a", DataType::Null, true)]);
1984 let a = NullArray::new(3);
1985 let col_a = col("a", &schema)?;
1986 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
1987
1988 let list = vec![lit(1i64), lit(2i64)];
1991
1992 in_list!(
1996 batch,
1997 list.clone(),
1998 &false,
1999 vec![None, None, None],
2000 Arc::clone(&col_a),
2001 &schema
2002 );
2003
2004 in_list!(
2007 batch,
2008 list,
2009 &true,
2010 vec![None, None, None],
2011 Arc::clone(&col_a),
2012 &schema
2013 );
2014
2015 Ok(())
2016 }
2017
2018 #[test]
2019 fn test_in_list_null_type_list() -> Result<()> {
2020 let schema = Schema::new(vec![Field::new("a", DataType::Int64, true)]);
2022 let a = Int64Array::from(vec![Some(1), Some(2), None]);
2023 let col_a = col("a", &schema)?;
2024
2025 let null_array = Arc::new(NullArray::new(2)) as ArrayRef;
2027
2028 let expr = Arc::new(InListExpr::try_new_from_array(
2031 Arc::clone(&col_a),
2032 null_array,
2033 false,
2034 &schema,
2035 )?) as Arc<dyn PhysicalExpr>;
2036 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
2037 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
2038 let result = as_boolean_array(&result);
2039
2040 let expected = BooleanArray::from(vec![None, None, None]);
2043 assert_eq!(result, &expected);
2044
2045 Ok(())
2046 }
2047
2048 #[test]
2049 fn test_in_list_null_type_both() -> Result<()> {
2050 let schema = Schema::new(vec![Field::new("a", DataType::Null, true)]);
2052 let a = NullArray::new(3);
2053 let col_a = col("a", &schema)?;
2054
2055 let null_array = Arc::new(NullArray::new(2)) as ArrayRef;
2057
2058 let expr = Arc::new(InListExpr::try_new_from_array(
2060 Arc::clone(&col_a),
2061 null_array,
2062 false,
2063 &schema,
2064 )?) as Arc<dyn PhysicalExpr>;
2065
2066 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
2067 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
2068 let result = as_boolean_array(&result);
2069
2070 let expected = BooleanArray::from(vec![None, None, None]);
2073 assert_eq!(result, &expected);
2074
2075 Ok(())
2076 }
2077
2078 #[test]
2079 fn test_in_list_comprehensive_null_handling() -> Result<()> {
2080 let schema = Arc::new(Schema::new(vec![Field::new("b", DataType::Int32, true)]));
2088 let col_b = col("b", &schema)?;
2089 let null_i32 = ScalarValue::Int32(None);
2090
2091 let make_batch = |values: Vec<Option<i32>>| -> Result<RecordBatch> {
2093 let array = Arc::new(Int32Array::from(values));
2094 Ok(RecordBatch::try_new(Arc::clone(&schema), vec![array])?)
2095 };
2096
2097 let run_test = |batch: &RecordBatch,
2099 expr: Arc<dyn PhysicalExpr>,
2100 list: Vec<Arc<dyn PhysicalExpr>>,
2101 expected: Vec<Option<bool>>|
2102 -> Result<()> {
2103 let in_expr = in_list(expr, list, &false, schema.as_ref())?;
2104 let result = in_expr.evaluate(batch)?.into_array(batch.num_rows())?;
2105 let result = as_boolean_array(&result);
2106 assert_eq!(result, &BooleanArray::from(expected));
2107 Ok(())
2108 };
2109
2110 let batch = make_batch(vec![Some(1)])?;
2116 run_test(
2117 &batch,
2118 Arc::clone(&col_b),
2119 vec![lit(1i32), lit(2i32)],
2120 vec![Some(true)],
2121 )?;
2122
2123 let batch = make_batch(vec![Some(1), Some(2)])?;
2125 run_test(
2126 &batch,
2127 Arc::clone(&col_b),
2128 vec![lit(1i32), lit(2i32)],
2129 vec![Some(true), Some(true)],
2130 )?;
2131
2132 let batch = make_batch(vec![Some(3), Some(4)])?;
2134 run_test(
2135 &batch,
2136 Arc::clone(&col_b),
2137 vec![lit(1i32), lit(2i32)],
2138 vec![Some(false), Some(false)],
2139 )?;
2140
2141 let batch = make_batch(vec![Some(1), None])?;
2143 run_test(
2144 &batch,
2145 Arc::clone(&col_b),
2146 vec![lit(1i32), lit(2i32)],
2147 vec![Some(true), None],
2148 )?;
2149
2150 let batch = make_batch(vec![Some(3), None])?;
2152 run_test(
2153 &batch,
2154 Arc::clone(&col_b),
2155 vec![lit(1i32), lit(2i32)],
2156 vec![Some(false), None],
2157 )?;
2158
2159 let batch = make_batch(vec![Some(1)])?;
2165 run_test(
2166 &batch,
2167 Arc::clone(&col_b),
2168 vec![lit(null_i32.clone()), lit(1i32)],
2169 vec![Some(true)],
2170 )?;
2171
2172 let batch = make_batch(vec![Some(2)])?;
2174 run_test(
2175 &batch,
2176 Arc::clone(&col_b),
2177 vec![lit(null_i32.clone()), lit(1i32)],
2178 vec![None],
2179 )?;
2180
2181 let batch = make_batch(vec![None])?;
2183 run_test(
2184 &batch,
2185 Arc::clone(&col_b),
2186 vec![lit(null_i32.clone()), lit(1i32)],
2187 vec![None],
2188 )?;
2189
2190 let batch = make_batch(vec![Some(1)])?;
2196 run_test(
2197 &batch,
2198 Arc::clone(&col_b),
2199 vec![lit(null_i32.clone()), lit(null_i32.clone())],
2200 vec![None],
2201 )?;
2202
2203 let batch = make_batch(vec![None])?;
2205 run_test(
2206 &batch,
2207 Arc::clone(&col_b),
2208 vec![lit(null_i32.clone()), lit(null_i32.clone())],
2209 vec![None],
2210 )?;
2211
2212 let batch = make_batch(vec![Some(1)])?;
2218 run_test(
2219 &batch,
2220 lit(1i32),
2221 vec![lit(2i32), Arc::clone(&col_b)],
2222 vec![Some(true)],
2223 )?;
2224
2225 let batch = make_batch(vec![Some(3)])?;
2227 run_test(
2228 &batch,
2229 lit(1i32),
2230 vec![lit(2i32), Arc::clone(&col_b)],
2231 vec![Some(false)],
2232 )?;
2233
2234 let batch = make_batch(vec![None])?;
2236 run_test(
2237 &batch,
2238 lit(1i32),
2239 vec![lit(2i32), Arc::clone(&col_b)],
2240 vec![None],
2241 )?;
2242
2243 let batch = make_batch(vec![Some(1)])?;
2249 run_test(
2250 &batch,
2251 Arc::clone(&col_b),
2252 vec![lit(1i32), Arc::clone(&col_b)],
2253 vec![Some(true)],
2254 )?;
2255
2256 let batch = make_batch(vec![Some(2)])?;
2258 run_test(
2259 &batch,
2260 Arc::clone(&col_b),
2261 vec![lit(1i32), Arc::clone(&col_b)],
2262 vec![Some(true)],
2263 )?;
2264
2265 let batch = make_batch(vec![None])?;
2267 run_test(
2268 &batch,
2269 Arc::clone(&col_b),
2270 vec![lit(1i32), Arc::clone(&col_b)],
2271 vec![None],
2272 )?;
2273
2274 Ok(())
2275 }
2276
2277 #[test]
2278 fn test_in_list_scalar_literal_cases() -> Result<()> {
2279 let schema = Arc::new(Schema::new(vec![Field::new("b", DataType::Int32, true)]));
2284 let null_i32 = ScalarValue::Int32(None);
2285
2286 let make_batch = |values: Vec<Option<i32>>| -> Result<RecordBatch> {
2288 let array = Arc::new(Int32Array::from(values));
2289 Ok(RecordBatch::try_new(Arc::clone(&schema), vec![array])?)
2290 };
2291
2292 let run_test = |batch: &RecordBatch,
2294 expr: Arc<dyn PhysicalExpr>,
2295 list: Vec<Arc<dyn PhysicalExpr>>,
2296 negated: bool,
2297 expected: Vec<Option<bool>>|
2298 -> Result<()> {
2299 let in_expr = in_list(expr, list, &negated, schema.as_ref())?;
2300 let result = in_expr.evaluate(batch)?.into_array(batch.num_rows())?;
2301 let result = as_boolean_array(&result);
2302 let expected_array = BooleanArray::from(expected);
2303 assert_eq!(
2304 result,
2305 &expected_array,
2306 "Expected {:?}, got {:?}",
2307 expected_array,
2308 result.iter().collect::<Vec<_>>()
2309 );
2310 Ok(())
2311 };
2312
2313 let batch = make_batch(vec![Some(1)])?;
2314
2315 run_test(
2322 &batch,
2323 lit(null_i32.clone()),
2324 vec![lit(1i32), lit(1i32)],
2325 false,
2326 vec![None],
2327 )?;
2328
2329 run_test(
2331 &batch,
2332 lit(null_i32.clone()),
2333 vec![lit(null_i32.clone()), lit(1i32)],
2334 false,
2335 vec![None],
2336 )?;
2337
2338 run_test(
2340 &batch,
2341 lit(null_i32.clone()),
2342 vec![lit(null_i32.clone()), lit(null_i32.clone())],
2343 false,
2344 vec![None],
2345 )?;
2346
2347 run_test(
2355 &batch,
2356 lit(3i32),
2357 vec![lit(0i32), lit(1i32), lit(2i32), lit(null_i32.clone())],
2358 false,
2359 vec![None],
2360 )?;
2361
2362 run_test(
2364 &batch,
2365 lit(3i32),
2366 vec![lit(0i32), lit(1i32), lit(2i32), lit(null_i32.clone())],
2367 true,
2368 vec![None],
2369 )?;
2370
2371 run_test(
2373 &batch,
2374 lit(1i32),
2375 vec![lit(0i32), lit(1i32), lit(2i32), lit(null_i32.clone())],
2376 false,
2377 vec![Some(true)],
2378 )?;
2379
2380 run_test(
2382 &batch,
2383 lit(1i32),
2384 vec![lit(0i32), lit(1i32), lit(2i32), lit(null_i32.clone())],
2385 true,
2386 vec![Some(false)],
2387 )?;
2388
2389 let schema_str =
2395 Arc::new(Schema::new(vec![Field::new("s", DataType::Utf8, true)]));
2396 let batch_str = RecordBatch::try_new(
2397 Arc::clone(&schema_str),
2398 vec![Arc::new(StringArray::from(vec![Some("dummy")]))],
2399 )?;
2400 let null_str = ScalarValue::Utf8(None);
2401
2402 let run_test_str = |expr: Arc<dyn PhysicalExpr>,
2403 list: Vec<Arc<dyn PhysicalExpr>>,
2404 negated: bool,
2405 expected: Vec<Option<bool>>|
2406 -> Result<()> {
2407 let in_expr = in_list(expr, list, &negated, schema_str.as_ref())?;
2408 let result = in_expr
2409 .evaluate(&batch_str)?
2410 .into_array(batch_str.num_rows())?;
2411 let result = as_boolean_array(&result);
2412 let expected_array = BooleanArray::from(expected);
2413 assert_eq!(
2414 result,
2415 &expected_array,
2416 "Expected {:?}, got {:?}",
2417 expected_array,
2418 result.iter().collect::<Vec<_>>()
2419 );
2420 Ok(())
2421 };
2422
2423 run_test_str(
2425 lit("c"),
2426 vec![lit("a"), lit("b"), lit(null_str.clone())],
2427 false,
2428 vec![None],
2429 )?;
2430
2431 run_test_str(
2433 lit("c"),
2434 vec![lit("a"), lit("b"), lit(null_str.clone())],
2435 true,
2436 vec![None],
2437 )?;
2438
2439 run_test_str(
2441 lit("a"),
2442 vec![lit("a"), lit("b"), lit(null_str.clone())],
2443 false,
2444 vec![Some(true)],
2445 )?;
2446
2447 run_test_str(
2449 lit("a"),
2450 vec![lit("a"), lit("b"), lit(null_str.clone())],
2451 true,
2452 vec![Some(false)],
2453 )?;
2454
2455 Ok(())
2456 }
2457
2458 #[test]
2459 fn test_in_list_tuple_cases() -> Result<()> {
2460 let schema = Arc::new(Schema::new(vec![Field::new("b", DataType::Int32, true)]));
2464
2465 let make_struct = |v1: Option<i32>, v2: Option<i32>| -> ScalarValue {
2467 let fields = Fields::from(vec![
2468 Field::new("field_0", DataType::Int32, true),
2469 Field::new("field_1", DataType::Int32, true),
2470 ]);
2471 ScalarValue::Struct(Arc::new(StructArray::new(
2472 fields,
2473 vec![
2474 Arc::new(Int32Array::from(vec![v1])),
2475 Arc::new(Int32Array::from(vec![v2])),
2476 ],
2477 None,
2478 )))
2479 };
2480
2481 let batch = RecordBatch::try_new(
2483 Arc::clone(&schema),
2484 vec![Arc::new(Int32Array::from(vec![Some(1)]))],
2485 )?;
2486
2487 let run_tuple_test = |lhs: ScalarValue,
2489 list: Vec<ScalarValue>,
2490 expected: Vec<Option<bool>>|
2491 -> Result<()> {
2492 let expr = in_list(
2493 lit(lhs),
2494 list.into_iter().map(lit).collect(),
2495 &false,
2496 schema.as_ref(),
2497 )?;
2498 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
2499 let result = as_boolean_array(&result);
2500 assert_eq!(result, &BooleanArray::from(expected));
2501 Ok(())
2502 };
2503
2504 run_tuple_test(
2506 make_struct(None, None),
2507 vec![make_struct(Some(1), Some(2))],
2508 vec![Some(false)],
2509 )?;
2510
2511 run_tuple_test(
2513 make_struct(None, None),
2514 vec![make_struct(None, Some(1))],
2515 vec![Some(false)],
2516 )?;
2517
2518 run_tuple_test(
2520 make_struct(None, None),
2521 vec![make_struct(None, None)],
2522 vec![Some(true)],
2523 )?;
2524
2525 run_tuple_test(
2527 make_struct(None, Some(1)),
2528 vec![make_struct(Some(1), Some(2))],
2529 vec![Some(false)],
2530 )?;
2531
2532 run_tuple_test(
2534 make_struct(None, Some(1)),
2535 vec![make_struct(None, Some(1))],
2536 vec![Some(true)],
2537 )?;
2538
2539 run_tuple_test(
2541 make_struct(None, Some(1)),
2542 vec![make_struct(None, None)],
2543 vec![Some(false)],
2544 )?;
2545
2546 run_tuple_test(
2548 make_struct(Some(1), Some(2)),
2549 vec![make_struct(Some(1), Some(2))],
2550 vec![Some(true)],
2551 )?;
2552
2553 run_tuple_test(
2555 make_struct(Some(1), Some(3)),
2556 vec![make_struct(Some(1), Some(2))],
2557 vec![Some(false)],
2558 )?;
2559
2560 run_tuple_test(
2562 make_struct(Some(4), Some(4)),
2563 vec![make_struct(Some(1), Some(2))],
2564 vec![Some(false)],
2565 )?;
2566
2567 run_tuple_test(
2569 make_struct(Some(1), Some(1)),
2570 vec![make_struct(None, Some(1))],
2571 vec![Some(false)],
2572 )?;
2573
2574 run_tuple_test(
2576 make_struct(Some(1), Some(1)),
2577 vec![make_struct(None, None)],
2578 vec![Some(false)],
2579 )?;
2580
2581 Ok(())
2582 }
2583
2584 #[test]
2585 fn test_in_list_dictionary_int32() -> Result<()> {
2586 let dict_type =
2588 DataType::Dictionary(Box::new(DataType::Int8), Box::new(DataType::Int32));
2589 let schema = Schema::new(vec![Field::new("a", dict_type.clone(), false)]);
2590 let col_a = col("a", &schema)?;
2591
2592 let list = vec![lit(100i32), lit(200i32), lit(300i32)];
2594
2595 let expr = in_list(col_a, list, &false, &schema)?;
2597
2598 let keys = Int8Array::from(vec![0, 1, 2]);
2602 let values = Int32Array::from(vec![100, 200, 500]);
2603 let dict_array: ArrayRef =
2604 Arc::new(DictionaryArray::try_new(keys, Arc::new(values))?);
2605 let batch = RecordBatch::try_new(Arc::new(schema), vec![dict_array])?;
2606
2607 let result = expr.evaluate(&batch)?.into_array(3)?;
2609 let result = as_boolean_array(&result);
2610 assert_eq!(result, &BooleanArray::from(vec![true, true, false]));
2611 Ok(())
2612 }
2613
2614 #[test]
2615 fn test_in_list_dictionary_types() -> Result<()> {
2616 fn dict_lit_int64(key_type: DataType, value: i64) -> Arc<dyn PhysicalExpr> {
2618 lit(ScalarValue::Dictionary(
2619 Box::new(key_type),
2620 Box::new(ScalarValue::Int64(Some(value))),
2621 ))
2622 }
2623
2624 fn dict_lit_float64(key_type: DataType, value: f64) -> Arc<dyn PhysicalExpr> {
2625 lit(ScalarValue::Dictionary(
2626 Box::new(key_type),
2627 Box::new(ScalarValue::Float64(Some(value))),
2628 ))
2629 }
2630
2631 struct DictNeedleTest {
2633 list_values: Vec<Arc<dyn PhysicalExpr>>,
2634 expected: Vec<Option<bool>>,
2635 }
2636
2637 struct DictionaryInListTestCase {
2638 name: &'static str,
2639 dict_type: DataType,
2640 dict_keys: Vec<Option<i8>>,
2641 dict_values: ArrayRef,
2642 list_values_no_null: Vec<Arc<dyn PhysicalExpr>>,
2643 list_values_with_null: Vec<Arc<dyn PhysicalExpr>>,
2644 expected_1: Vec<Option<bool>>,
2645 expected_2: Vec<Option<bool>>,
2646 expected_3: Vec<Option<bool>>,
2647 expected_4: Vec<Option<bool>>,
2648 dict_needle_test: Option<DictNeedleTest>,
2649 }
2650
2651 fn run_dictionary_in_list_test(
2653 test_case: DictionaryInListTestCase,
2654 ) -> Result<()> {
2655 let schema =
2657 Schema::new(vec![Field::new("a", test_case.dict_type.clone(), true)]);
2658 let col_a = col("a", &schema)?;
2659
2660 let keys = Int8Array::from(test_case.dict_keys.clone());
2662 let dict_array: ArrayRef =
2663 Arc::new(DictionaryArray::try_new(keys, test_case.dict_values)?);
2664 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![dict_array])?;
2665
2666 let exp1 = test_case.expected_1.clone();
2667 let exp2 = test_case.expected_2.clone();
2668 let exp3 = test_case.expected_3.clone();
2669 let exp4 = test_case.expected_4;
2670
2671 in_list!(
2673 batch,
2674 test_case.list_values_no_null.clone(),
2675 &false,
2676 exp1,
2677 Arc::clone(&col_a),
2678 &schema
2679 );
2680
2681 in_list!(
2683 batch,
2684 test_case.list_values_no_null.clone(),
2685 &true,
2686 exp2,
2687 Arc::clone(&col_a),
2688 &schema
2689 );
2690
2691 in_list!(
2693 batch,
2694 test_case.list_values_with_null.clone(),
2695 &false,
2696 exp3,
2697 Arc::clone(&col_a),
2698 &schema
2699 );
2700
2701 in_list!(
2703 batch,
2704 test_case.list_values_with_null,
2705 &true,
2706 exp4,
2707 Arc::clone(&col_a),
2708 &schema
2709 );
2710
2711 if let Some(needle_test) = test_case.dict_needle_test {
2713 in_list_raw!(
2714 batch,
2715 needle_test.list_values,
2716 &false,
2717 needle_test.expected,
2718 Arc::clone(&col_a),
2719 &schema
2720 );
2721 }
2722
2723 Ok(())
2724 }
2725
2726 let utf8_case = DictionaryInListTestCase {
2730 name: "dictionary_utf8",
2731 dict_type: DataType::Dictionary(
2732 Box::new(DataType::Int8),
2733 Box::new(DataType::Utf8),
2734 ),
2735 dict_keys: vec![Some(0), Some(1), None],
2736 dict_values: Arc::new(StringArray::from(vec![Some("a"), Some("d")])),
2737 list_values_no_null: vec![lit("a"), lit("b")],
2738 list_values_with_null: vec![lit("a"), lit("b"), lit(ScalarValue::Utf8(None))],
2739 expected_1: vec![Some(true), Some(false), None],
2740 expected_2: vec![Some(false), Some(true), None],
2741 expected_3: vec![Some(true), None, None],
2742 expected_4: vec![Some(false), None, None],
2743 dict_needle_test: None,
2744 };
2745
2746 let int64_case = DictionaryInListTestCase {
2750 name: "dictionary_int64",
2751 dict_type: DataType::Dictionary(
2752 Box::new(DataType::Int8),
2753 Box::new(DataType::Int64),
2754 ),
2755 dict_keys: vec![Some(0), Some(1), None],
2756 dict_values: Arc::new(Int64Array::from(vec![Some(10), Some(20)])),
2757 list_values_no_null: vec![lit(10i64), lit(15i64)],
2758 list_values_with_null: vec![
2759 lit(10i64),
2760 lit(15i64),
2761 lit(ScalarValue::Int64(None)),
2762 ],
2763 expected_1: vec![Some(true), Some(false), None],
2764 expected_2: vec![Some(false), Some(true), None],
2765 expected_3: vec![Some(true), None, None],
2766 expected_4: vec![Some(false), None, None],
2767 dict_needle_test: Some(DictNeedleTest {
2768 list_values: vec![
2769 dict_lit_int64(DataType::Int16, 10),
2770 dict_lit_int64(DataType::Int16, 15),
2771 ],
2772 expected: vec![Some(true), Some(false), None],
2773 }),
2774 };
2775
2776 let float64_case = DictionaryInListTestCase {
2781 name: "dictionary_float64",
2782 dict_type: DataType::Dictionary(
2783 Box::new(DataType::Int8),
2784 Box::new(DataType::Float64),
2785 ),
2786 dict_keys: vec![Some(0), Some(1), None, Some(2)],
2787 dict_values: Arc::new(Float64Array::from(vec![
2788 Some(1.5), Some(3.7), Some(f64::NAN), ])),
2792 list_values_no_null: vec![lit(1.5f64), lit(2.0f64)],
2793 list_values_with_null: vec![
2794 lit(1.5f64),
2795 lit(2.0f64),
2796 lit(ScalarValue::Float64(None)),
2797 ],
2798 expected_1: vec![Some(true), Some(false), None, Some(false)],
2801 expected_2: vec![Some(false), Some(true), None, Some(true)],
2804 expected_3: vec![Some(true), None, None, None],
2807 expected_4: vec![Some(false), None, None, None],
2810 dict_needle_test: Some(DictNeedleTest {
2811 list_values: vec![
2812 dict_lit_float64(DataType::UInt16, 1.5),
2813 dict_lit_float64(DataType::UInt16, 2.0),
2814 ],
2815 expected: vec![Some(true), Some(false), None, Some(false)],
2816 }),
2817 };
2818
2819 let test_name = utf8_case.name;
2821 run_dictionary_in_list_test(utf8_case).map_err(|e| {
2822 datafusion_common::DataFusionError::Execution(format!(
2823 "Dictionary test '{test_name}' failed: {e}"
2824 ))
2825 })?;
2826
2827 let test_name = int64_case.name;
2828 run_dictionary_in_list_test(int64_case).map_err(|e| {
2829 datafusion_common::DataFusionError::Execution(format!(
2830 "Dictionary test '{test_name}' failed: {e}"
2831 ))
2832 })?;
2833
2834 let test_name = float64_case.name;
2835 run_dictionary_in_list_test(float64_case).map_err(|e| {
2836 datafusion_common::DataFusionError::Execution(format!(
2837 "Dictionary test '{test_name}' failed: {e}"
2838 ))
2839 })?;
2840
2841 let dedup_case = DictionaryInListTestCase {
2845 name: "dictionary_deduplication",
2846 dict_type: DataType::Dictionary(
2847 Box::new(DataType::Int8),
2848 Box::new(DataType::Utf8),
2849 ),
2850 dict_keys: vec![Some(0), Some(1), Some(0), Some(1), None],
2853 dict_values: Arc::new(StringArray::from(vec![Some("a"), Some("d")])),
2854 list_values_no_null: vec![lit("a"), lit("b")],
2855 list_values_with_null: vec![lit("a"), lit("b"), lit(ScalarValue::Utf8(None))],
2856 expected_1: vec![Some(true), Some(false), Some(true), Some(false), None],
2859 expected_2: vec![Some(false), Some(true), Some(false), Some(true), None],
2861 expected_3: vec![Some(true), None, Some(true), None, None],
2864 expected_4: vec![Some(false), None, Some(false), None, None],
2866 dict_needle_test: None,
2867 };
2868
2869 let test_name = dedup_case.name;
2870 run_dictionary_in_list_test(dedup_case).map_err(|e| {
2871 datafusion_common::DataFusionError::Execution(format!(
2872 "Dictionary test '{test_name}' failed: {e}"
2873 ))
2874 })?;
2875
2876 let dict_type =
2878 DataType::Dictionary(Box::new(DataType::Int8), Box::new(DataType::Float64));
2879 let schema = Schema::new(vec![Field::new("a", dict_type.clone(), true)]);
2880 let col_a = col("a", &schema)?;
2881
2882 let keys = Int8Array::from(vec![Some(0), Some(1), None, Some(2)]);
2883 let values = Float64Array::from(vec![Some(1.5), Some(3.7), Some(f64::NAN)]);
2884 let dict_array: ArrayRef =
2885 Arc::new(DictionaryArray::try_new(keys, Arc::new(values))?);
2886 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![dict_array])?;
2887
2888 let list_with_nan = vec![lit(1.5f64), lit(2.0f64), lit(f64::NAN)];
2890 in_list!(
2891 batch,
2892 list_with_nan,
2893 &false,
2894 vec![Some(true), Some(false), None, Some(true)],
2895 col_a,
2896 &schema
2897 );
2898
2899 Ok(())
2900 }
2901
2902 #[test]
2903 fn test_in_list_esoteric_types() -> Result<()> {
2904 let test_type = |data_type: DataType,
2910 in_array: ArrayRef,
2911 list_values: Vec<ScalarValue>|
2912 -> Result<()> {
2913 let schema = Schema::new(vec![Field::new("a", data_type.clone(), false)]);
2914 let col_a = col("a", &schema)?;
2915 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![in_array])?;
2916
2917 let list = list_values.into_iter().map(lit).collect();
2918 in_list!(
2919 batch,
2920 list,
2921 &false,
2922 vec![Some(true), Some(false)],
2923 col_a,
2924 &schema
2925 );
2926 Ok(())
2927 };
2928
2929 test_type(
2931 DataType::Timestamp(TimeUnit::Second, None),
2932 Arc::new(TimestampSecondArray::from(vec![Some(1000), Some(2000)])),
2933 vec![
2934 ScalarValue::TimestampSecond(Some(1000), None),
2935 ScalarValue::TimestampSecond(Some(1500), None),
2936 ],
2937 )?;
2938
2939 test_type(
2940 DataType::Timestamp(TimeUnit::Millisecond, None),
2941 Arc::new(TimestampMillisecondArray::from(vec![
2942 Some(1000000),
2943 Some(2000000),
2944 ])),
2945 vec![
2946 ScalarValue::TimestampMillisecond(Some(1000000), None),
2947 ScalarValue::TimestampMillisecond(Some(1500000), None),
2948 ],
2949 )?;
2950
2951 test_type(
2952 DataType::Timestamp(TimeUnit::Microsecond, None),
2953 Arc::new(TimestampMicrosecondArray::from(vec![
2954 Some(1000000000),
2955 Some(2000000000),
2956 ])),
2957 vec![
2958 ScalarValue::TimestampMicrosecond(Some(1000000000), None),
2959 ScalarValue::TimestampMicrosecond(Some(1500000000), None),
2960 ],
2961 )?;
2962
2963 test_type(
2965 DataType::Time32(TimeUnit::Second),
2966 Arc::new(Time32SecondArray::from(vec![Some(3600), Some(7200)])),
2967 vec![
2968 ScalarValue::Time32Second(Some(3600)),
2969 ScalarValue::Time32Second(Some(5400)),
2970 ],
2971 )?;
2972
2973 test_type(
2974 DataType::Time32(TimeUnit::Millisecond),
2975 Arc::new(Time32MillisecondArray::from(vec![
2976 Some(3600000),
2977 Some(7200000),
2978 ])),
2979 vec![
2980 ScalarValue::Time32Millisecond(Some(3600000)),
2981 ScalarValue::Time32Millisecond(Some(5400000)),
2982 ],
2983 )?;
2984
2985 test_type(
2986 DataType::Time64(TimeUnit::Microsecond),
2987 Arc::new(Time64MicrosecondArray::from(vec![
2988 Some(3600000000),
2989 Some(7200000000),
2990 ])),
2991 vec![
2992 ScalarValue::Time64Microsecond(Some(3600000000)),
2993 ScalarValue::Time64Microsecond(Some(5400000000)),
2994 ],
2995 )?;
2996
2997 test_type(
2998 DataType::Time64(TimeUnit::Nanosecond),
2999 Arc::new(Time64NanosecondArray::from(vec![
3000 Some(3600000000000),
3001 Some(7200000000000),
3002 ])),
3003 vec![
3004 ScalarValue::Time64Nanosecond(Some(3600000000000)),
3005 ScalarValue::Time64Nanosecond(Some(5400000000000)),
3006 ],
3007 )?;
3008
3009 test_type(
3011 DataType::Duration(TimeUnit::Second),
3012 Arc::new(DurationSecondArray::from(vec![Some(86400), Some(172800)])),
3013 vec![
3014 ScalarValue::DurationSecond(Some(86400)),
3015 ScalarValue::DurationSecond(Some(129600)),
3016 ],
3017 )?;
3018
3019 test_type(
3020 DataType::Duration(TimeUnit::Millisecond),
3021 Arc::new(DurationMillisecondArray::from(vec![
3022 Some(86400000),
3023 Some(172800000),
3024 ])),
3025 vec![
3026 ScalarValue::DurationMillisecond(Some(86400000)),
3027 ScalarValue::DurationMillisecond(Some(129600000)),
3028 ],
3029 )?;
3030
3031 test_type(
3032 DataType::Duration(TimeUnit::Microsecond),
3033 Arc::new(DurationMicrosecondArray::from(vec![
3034 Some(86400000000),
3035 Some(172800000000),
3036 ])),
3037 vec![
3038 ScalarValue::DurationMicrosecond(Some(86400000000)),
3039 ScalarValue::DurationMicrosecond(Some(129600000000)),
3040 ],
3041 )?;
3042
3043 test_type(
3044 DataType::Duration(TimeUnit::Nanosecond),
3045 Arc::new(DurationNanosecondArray::from(vec![
3046 Some(86400000000000),
3047 Some(172800000000000),
3048 ])),
3049 vec![
3050 ScalarValue::DurationNanosecond(Some(86400000000000)),
3051 ScalarValue::DurationNanosecond(Some(129600000000000)),
3052 ],
3053 )?;
3054
3055 test_type(
3057 DataType::Interval(IntervalUnit::YearMonth),
3058 Arc::new(IntervalYearMonthArray::from(vec![Some(12), Some(24)])),
3059 vec![
3060 ScalarValue::IntervalYearMonth(Some(12)),
3061 ScalarValue::IntervalYearMonth(Some(18)),
3062 ],
3063 )?;
3064
3065 test_type(
3066 DataType::Interval(IntervalUnit::DayTime),
3067 Arc::new(IntervalDayTimeArray::from(vec![
3068 Some(IntervalDayTime {
3069 days: 1,
3070 milliseconds: 0,
3071 }),
3072 Some(IntervalDayTime {
3073 days: 2,
3074 milliseconds: 0,
3075 }),
3076 ])),
3077 vec![
3078 ScalarValue::IntervalDayTime(Some(IntervalDayTime {
3079 days: 1,
3080 milliseconds: 0,
3081 })),
3082 ScalarValue::IntervalDayTime(Some(IntervalDayTime {
3083 days: 1,
3084 milliseconds: 500,
3085 })),
3086 ],
3087 )?;
3088
3089 test_type(
3090 DataType::Interval(IntervalUnit::MonthDayNano),
3091 Arc::new(IntervalMonthDayNanoArray::from(vec![
3092 Some(IntervalMonthDayNano {
3093 months: 1,
3094 days: 0,
3095 nanoseconds: 0,
3096 }),
3097 Some(IntervalMonthDayNano {
3098 months: 2,
3099 days: 0,
3100 nanoseconds: 0,
3101 }),
3102 ])),
3103 vec![
3104 ScalarValue::IntervalMonthDayNano(Some(IntervalMonthDayNano {
3105 months: 1,
3106 days: 0,
3107 nanoseconds: 0,
3108 })),
3109 ScalarValue::IntervalMonthDayNano(Some(IntervalMonthDayNano {
3110 months: 1,
3111 days: 15,
3112 nanoseconds: 0,
3113 })),
3114 ],
3115 )?;
3116
3117 let precision = 38;
3119 let scale = 10;
3120 test_type(
3121 DataType::Decimal256(precision, scale),
3122 Arc::new(
3123 Decimal256Array::from(vec![
3124 Some(i256::from(12345)),
3125 Some(i256::from(67890)),
3126 ])
3127 .with_precision_and_scale(precision, scale)?,
3128 ),
3129 vec![
3130 ScalarValue::Decimal256(Some(i256::from(12345)), precision, scale),
3131 ScalarValue::Decimal256(Some(i256::from(54321)), precision, scale),
3132 ],
3133 )?;
3134
3135 Ok(())
3136 }
3137
3138 fn make_in_list_with_columns(
3141 expr: Arc<dyn PhysicalExpr>,
3142 list: Vec<Arc<dyn PhysicalExpr>>,
3143 negated: bool,
3144 ) -> Arc<InListExpr> {
3145 Arc::new(InListExpr::new(expr, list, negated, None))
3146 }
3147
3148 #[test]
3149 fn test_in_list_with_columns_int32_scalars() -> Result<()> {
3150 let schema = Schema::new(vec![Field::new("a", DataType::Int32, true)]);
3152 let col_a = col("a", &schema)?;
3153 let batch = RecordBatch::try_new(
3154 Arc::new(schema),
3155 vec![Arc::new(Int32Array::from(vec![
3156 Some(1),
3157 Some(2),
3158 Some(3),
3159 None,
3160 ]))],
3161 )?;
3162
3163 let list = vec![
3164 lit(ScalarValue::Int32(Some(1))),
3165 lit(ScalarValue::Int32(Some(3))),
3166 ];
3167 let expr = make_in_list_with_columns(col_a, list, false);
3168
3169 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3170 let result = as_boolean_array(&result);
3171 assert_eq!(
3172 result,
3173 &BooleanArray::from(vec![Some(true), Some(false), Some(true), None,])
3174 );
3175 Ok(())
3176 }
3177
3178 #[test]
3179 fn test_in_list_with_columns_int32_column_refs() -> Result<()> {
3180 let schema = Schema::new(vec![
3182 Field::new("a", DataType::Int32, true),
3183 Field::new("b", DataType::Int32, true),
3184 Field::new("c", DataType::Int32, true),
3185 ]);
3186 let batch = RecordBatch::try_new(
3187 Arc::new(schema.clone()),
3188 vec![
3189 Arc::new(Int32Array::from(vec![Some(1), Some(2), Some(3), None])),
3190 Arc::new(Int32Array::from(vec![
3191 Some(1),
3192 Some(99),
3193 Some(99),
3194 Some(99),
3195 ])),
3196 Arc::new(Int32Array::from(vec![Some(99), Some(99), Some(3), None])),
3197 ],
3198 )?;
3199
3200 let col_a = col("a", &schema)?;
3201 let list = vec![col("b", &schema)?, col("c", &schema)?];
3202 let expr = make_in_list_with_columns(col_a, list, false);
3203
3204 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3205 let result = as_boolean_array(&result);
3206 assert_eq!(
3211 result,
3212 &BooleanArray::from(vec![Some(true), Some(false), Some(true), None,])
3213 );
3214 Ok(())
3215 }
3216
3217 #[test]
3218 fn test_in_list_with_columns_utf8_column_refs() -> Result<()> {
3219 let schema = Schema::new(vec![
3221 Field::new("a", DataType::Utf8, false),
3222 Field::new("b", DataType::Utf8, false),
3223 ]);
3224 let batch = RecordBatch::try_new(
3225 Arc::new(schema.clone()),
3226 vec![
3227 Arc::new(StringArray::from(vec!["x", "y", "z"])),
3228 Arc::new(StringArray::from(vec!["x", "x", "z"])),
3229 ],
3230 )?;
3231
3232 let col_a = col("a", &schema)?;
3233 let list = vec![col("b", &schema)?];
3234 let expr = make_in_list_with_columns(col_a, list, false);
3235
3236 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3237 let result = as_boolean_array(&result);
3238 assert_eq!(result, &BooleanArray::from(vec![true, false, true]));
3242 Ok(())
3243 }
3244
3245 #[test]
3246 fn test_in_list_with_columns_negated() -> Result<()> {
3247 let schema = Schema::new(vec![
3249 Field::new("a", DataType::Int32, false),
3250 Field::new("b", DataType::Int32, false),
3251 ]);
3252 let batch = RecordBatch::try_new(
3253 Arc::new(schema.clone()),
3254 vec![
3255 Arc::new(Int32Array::from(vec![1, 2, 3])),
3256 Arc::new(Int32Array::from(vec![1, 99, 3])),
3257 ],
3258 )?;
3259
3260 let col_a = col("a", &schema)?;
3261 let list = vec![col("b", &schema)?];
3262 let expr = make_in_list_with_columns(col_a, list, true);
3263
3264 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3265 let result = as_boolean_array(&result);
3266 assert_eq!(result, &BooleanArray::from(vec![false, true, false]));
3270 Ok(())
3271 }
3272
3273 #[test]
3274 fn test_in_list_with_columns_null_in_list() -> Result<()> {
3275 let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
3277 let col_a = col("a", &schema)?;
3278 let batch = RecordBatch::try_new(
3279 Arc::new(schema),
3280 vec![Arc::new(Int32Array::from(vec![1, 2]))],
3281 )?;
3282
3283 let list = vec![
3284 lit(ScalarValue::Int32(None)),
3285 lit(ScalarValue::Int32(Some(1))),
3286 ];
3287 let expr = make_in_list_with_columns(col_a, list, false);
3288
3289 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3290 let result = as_boolean_array(&result);
3291 assert_eq!(result, &BooleanArray::from(vec![Some(true), None]));
3294 Ok(())
3295 }
3296
3297 #[test]
3298 fn test_in_list_with_columns_float_nan() -> Result<()> {
3299 let schema = Schema::new(vec![
3302 Field::new("a", DataType::Float64, false),
3303 Field::new("b", DataType::Float64, false),
3304 ]);
3305 let batch = RecordBatch::try_new(
3306 Arc::new(schema.clone()),
3307 vec![
3308 Arc::new(Float64Array::from(vec![f64::NAN, 1.0, f64::NAN])),
3309 Arc::new(Float64Array::from(vec![f64::NAN, 2.0, 0.0])),
3310 ],
3311 )?;
3312
3313 let col_a = col("a", &schema)?;
3314 let list = vec![col("b", &schema)?];
3315 let expr = make_in_list_with_columns(col_a, list, false);
3316
3317 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3318 let result = as_boolean_array(&result);
3319 assert_eq!(result, &BooleanArray::from(vec![true, false, false]));
3323 Ok(())
3324 }
3325
3326 #[test]
3330 fn test_in_list_with_columns_short_circuit() -> Result<()> {
3331 let schema = Schema::new(vec![
3334 Field::new("a", DataType::Int32, false),
3335 Field::new("b", DataType::Int32, false),
3336 Field::new("c", DataType::Int32, false),
3337 ]);
3338 let batch = RecordBatch::try_new(
3339 Arc::new(schema.clone()),
3340 vec![
3341 Arc::new(Int32Array::from(vec![1, 2, 3])),
3342 Arc::new(Int32Array::from(vec![1, 2, 3])), Arc::new(Int32Array::from(vec![99, 99, 99])),
3344 ],
3345 )?;
3346
3347 let col_a = col("a", &schema)?;
3348 let list = vec![col("b", &schema)?, col("c", &schema)?];
3349 let expr = make_in_list_with_columns(col_a, list, false);
3350
3351 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3352 let result = as_boolean_array(&result);
3353 assert_eq!(result, &BooleanArray::from(vec![true, true, true]));
3354 Ok(())
3355 }
3356
3357 #[test]
3360 fn test_in_list_with_columns_short_circuit_with_nulls() -> Result<()> {
3361 let schema = Schema::new(vec![
3364 Field::new("a", DataType::Int32, true),
3365 Field::new("b", DataType::Int32, false),
3366 Field::new("c", DataType::Int32, false),
3367 ]);
3368 let batch = RecordBatch::try_new(
3369 Arc::new(schema.clone()),
3370 vec![
3371 Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])),
3372 Arc::new(Int32Array::from(vec![1, 2, 3])), Arc::new(Int32Array::from(vec![99, 99, 99])),
3374 ],
3375 )?;
3376
3377 let col_a = col("a", &schema)?;
3378 let list = vec![col("b", &schema)?, col("c", &schema)?];
3379 let expr = make_in_list_with_columns(col_a, list, false);
3380
3381 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3382 let result = as_boolean_array(&result);
3383 assert_eq!(
3387 result,
3388 &BooleanArray::from(vec![Some(true), None, Some(true)])
3389 );
3390 Ok(())
3391 }
3392
3393 #[test]
3396 fn test_in_list_with_columns_struct() -> Result<()> {
3397 let struct_fields = Fields::from(vec![
3398 Field::new("x", DataType::Int32, false),
3399 Field::new("y", DataType::Utf8, false),
3400 ]);
3401 let struct_dt = DataType::Struct(struct_fields.clone());
3402
3403 let schema = Schema::new(vec![
3404 Field::new("a", struct_dt.clone(), true),
3405 Field::new("b", struct_dt.clone(), false),
3406 Field::new("c", struct_dt.clone(), false),
3407 ]);
3408
3409 let a = Arc::new(StructArray::new(
3413 struct_fields.clone(),
3414 vec![
3415 Arc::new(Int32Array::from(vec![1, 2, 3, 4])),
3416 Arc::new(StringArray::from(vec!["a", "b", "c", "d"])),
3417 ],
3418 Some(vec![true, true, false, true].into()),
3419 ));
3420 let b = Arc::new(StructArray::new(
3421 struct_fields.clone(),
3422 vec![
3423 Arc::new(Int32Array::from(vec![1, 9, 3, 4])),
3424 Arc::new(StringArray::from(vec!["a", "z", "c", "d"])),
3425 ],
3426 None,
3427 ));
3428 let c = Arc::new(StructArray::new(
3429 struct_fields.clone(),
3430 vec![
3431 Arc::new(Int32Array::from(vec![9, 2, 9, 9])),
3432 Arc::new(StringArray::from(vec!["z", "b", "z", "z"])),
3433 ],
3434 None,
3435 ));
3436
3437 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![a, b, c])?;
3438
3439 let col_a = col("a", &schema)?;
3440 let list = vec![col("b", &schema)?, col("c", &schema)?];
3441 let expr = make_in_list_with_columns(col_a, list, false);
3442
3443 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3444 let result = as_boolean_array(&result);
3445 assert_eq!(
3450 result,
3451 &BooleanArray::from(vec![Some(true), Some(true), None, Some(true)])
3452 );
3453
3454 let col_a = col("a", &schema)?;
3456 let list = vec![col("b", &schema)?, col("c", &schema)?];
3457 let expr = make_in_list_with_columns(col_a, list, true);
3458
3459 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3460 let result = as_boolean_array(&result);
3461 assert_eq!(
3466 result,
3467 &BooleanArray::from(vec![Some(false), Some(false), None, Some(false)])
3468 );
3469 Ok(())
3470 }
3471
3472 fn wrap_in_dict(array: ArrayRef) -> ArrayRef {
3484 let keys = Int32Array::from((0..array.len() as i32).collect::<Vec<_>>());
3485 Arc::new(DictionaryArray::new(keys, array))
3486 }
3487
3488 fn eval_in_list_from_array(
3492 needle: ArrayRef,
3493 in_array: ArrayRef,
3494 ) -> Result<BooleanArray> {
3495 let schema =
3496 Schema::new(vec![Field::new("a", needle.data_type().clone(), false)]);
3497 let col_a = col("a", &schema)?;
3498 let expr = Arc::new(InListExpr::try_new_from_array(
3499 col_a, in_array, false, &schema,
3500 )?) as Arc<dyn PhysicalExpr>;
3501 let batch = RecordBatch::try_new(Arc::new(schema), vec![needle])?;
3502 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3503 Ok(as_boolean_array(&result).clone())
3504 }
3505
3506 #[test]
3507 fn test_in_list_from_array_type_combinations() -> Result<()> {
3508 use arrow::compute::cast;
3509
3510 let expected = BooleanArray::from(vec![Some(true), Some(false), Some(true)]);
3512
3513 let base_in = Arc::new(Int64Array::from(vec![1i64, 2, 3])) as ArrayRef;
3515 let base_needle = Arc::new(Int64Array::from(vec![1i64, 4, 2])) as ArrayRef;
3516
3517 let primitive_types = vec![
3519 DataType::Int8,
3520 DataType::Int16,
3521 DataType::Int32,
3522 DataType::Int64,
3523 DataType::UInt8,
3524 DataType::UInt16,
3525 DataType::UInt32,
3526 DataType::UInt64,
3527 DataType::Float16,
3528 DataType::Float32,
3529 DataType::Float64,
3530 ];
3531
3532 for dt in &primitive_types {
3533 let in_array = cast(&base_in, dt)?;
3534 let needle = cast(&base_needle, dt)?;
3535
3536 assert_eq!(
3538 expected,
3539 eval_in_list_from_array(Arc::clone(&needle), Arc::clone(&in_array))?,
3540 "same-type failed for {dt:?}"
3541 );
3542
3543 assert_eq!(
3545 expected,
3546 eval_in_list_from_array(wrap_in_dict(needle), in_array)?,
3547 "dict-needle failed for {dt:?}"
3548 );
3549 }
3550
3551 let utf8_in = Arc::new(StringArray::from(vec!["a", "b", "c"])) as ArrayRef;
3553 let utf8_needle = Arc::new(StringArray::from(vec!["a", "d", "b"])) as ArrayRef;
3554
3555 assert_eq!(
3557 expected,
3558 eval_in_list_from_array(Arc::clone(&utf8_needle), Arc::clone(&utf8_in),)?
3559 );
3560
3561 assert_eq!(
3563 expected,
3564 eval_in_list_from_array(
3565 wrap_in_dict(Arc::clone(&utf8_needle)),
3566 Arc::clone(&utf8_in),
3567 )?
3568 );
3569
3570 assert_eq!(
3572 expected,
3573 eval_in_list_from_array(
3574 wrap_in_dict(Arc::clone(&utf8_needle)),
3575 wrap_in_dict(Arc::clone(&utf8_in)),
3576 )?
3577 );
3578
3579 let struct_fields = Fields::from(vec![
3581 Field::new("c0", DataType::Utf8, true),
3582 Field::new("c1", DataType::Int64, true),
3583 ]);
3584 let make_struct = |c0: ArrayRef, c1: ArrayRef| -> ArrayRef {
3585 let pairs: Vec<(FieldRef, ArrayRef)> =
3586 struct_fields.iter().cloned().zip([c0, c1]).collect();
3587 Arc::new(StructArray::from(pairs))
3588 };
3589 assert_eq!(
3590 expected,
3591 eval_in_list_from_array(
3592 make_struct(
3593 Arc::clone(&utf8_needle),
3594 Arc::new(Int64Array::from(vec![1, 4, 2])),
3595 ),
3596 make_struct(
3597 Arc::clone(&utf8_in),
3598 Arc::new(Int64Array::from(vec![1, 2, 3])),
3599 ),
3600 )?
3601 );
3602
3603 let dict_struct_fields = Fields::from(vec![
3605 Field::new(
3606 "c0",
3607 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
3608 true,
3609 ),
3610 Field::new("c1", DataType::Int64, true),
3611 ]);
3612 let make_dict_struct = |c0: ArrayRef, c1: ArrayRef| -> ArrayRef {
3613 let pairs: Vec<(FieldRef, ArrayRef)> =
3614 dict_struct_fields.iter().cloned().zip([c0, c1]).collect();
3615 Arc::new(StructArray::from(pairs))
3616 };
3617 assert_eq!(
3618 expected,
3619 eval_in_list_from_array(
3620 make_dict_struct(
3621 wrap_in_dict(Arc::clone(&utf8_needle)),
3622 Arc::new(Int64Array::from(vec![1, 4, 2])),
3623 ),
3624 make_dict_struct(
3625 wrap_in_dict(Arc::clone(&utf8_in)),
3626 Arc::new(Int64Array::from(vec![1, 2, 3])),
3627 ),
3628 )?
3629 );
3630
3631 Ok(())
3632 }
3633
3634 fn make_int32_dict_array(values: Vec<Option<i32>>) -> ArrayRef {
3635 let mut builder = PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::new();
3636 for v in values {
3637 match v {
3638 Some(val) => builder.append_value(val),
3639 None => builder.append_null(),
3640 }
3641 }
3642 Arc::new(builder.finish())
3643 }
3644
3645 fn make_f64_dict_array(values: Vec<Option<f64>>) -> ArrayRef {
3646 let mut builder = PrimitiveDictionaryBuilder::<Int8Type, Float64Type>::new();
3647 for v in values {
3648 match v {
3649 Some(val) => builder.append_value(val),
3650 None => builder.append_null(),
3651 }
3652 }
3653 Arc::new(builder.finish())
3654 }
3655
3656 #[test]
3657 fn test_try_new_from_array_dict_haystack_int32() -> Result<()> {
3658 let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
3659 let needle = Int32Array::from(vec![1, 2, 3, 4]);
3660 let batch =
3661 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(needle)])?;
3662
3663 let haystack = make_int32_dict_array(vec![Some(1), None, Some(3)]);
3664
3665 let col_a = col("a", &schema)?;
3666 let expr = InListExpr::try_new_from_array(col_a, haystack, false, &schema)?;
3667 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3668 let result = as_boolean_array(&result);
3669 assert_eq!(
3670 result,
3671 &BooleanArray::from(vec![Some(true), None, Some(true), None])
3672 );
3673
3674 Ok(())
3675 }
3676
3677 #[test]
3678 fn test_in_list_from_array_type_mismatch_errors() -> Result<()> {
3679 assert_eq!(
3681 BooleanArray::from(vec![Some(true), Some(false), Some(true)]),
3682 eval_in_list_from_array(
3683 Arc::new(StringArray::from(vec!["a", "d", "b"])),
3684 wrap_in_dict(Arc::new(StringArray::from(vec!["a", "b", "c"]))),
3685 )?
3686 );
3687
3688 let err = eval_in_list_from_array(
3690 wrap_in_dict(Arc::new(StringArray::from(vec!["a", "d", "b"]))),
3691 Arc::new(Int64Array::from(vec![1, 2, 3])),
3692 )
3693 .unwrap_err()
3694 .to_string();
3695 assert!(err.contains("The data type inlist should be same"), "{err}");
3696
3697 let err = eval_in_list_from_array(
3700 wrap_in_dict(Arc::new(Int64Array::from(vec![1, 4, 2]))),
3701 wrap_in_dict(Arc::new(StringArray::from(vec!["a", "b", "c"]))),
3702 )
3703 .unwrap_err()
3704 .to_string();
3705 assert!(err.contains("The data type inlist should be same"), "{err}");
3706
3707 Ok(())
3708 }
3709
3710 #[test]
3711 fn test_try_new_from_array_dict_haystack_negated() -> Result<()> {
3712 let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
3713 let needle = Int32Array::from(vec![1, 2, 3, 4]);
3714 let batch =
3715 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(needle)])?;
3716
3717 let haystack = make_int32_dict_array(vec![Some(1), None, Some(3)]);
3718
3719 let col_a = col("a", &schema)?;
3720 let expr = InListExpr::try_new_from_array(col_a, haystack, true, &schema)?;
3721 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3722 let result = as_boolean_array(&result);
3723 assert_eq!(
3724 result,
3725 &BooleanArray::from(vec![Some(false), None, Some(false), None])
3726 );
3727
3728 Ok(())
3729 }
3730
3731 #[test]
3732 fn test_try_new_from_array_dict_haystack_utf8() -> Result<()> {
3733 let schema = Schema::new(vec![Field::new("a", DataType::Utf8, false)]);
3734 let needle = StringArray::from(vec!["a", "b", "c"]);
3735 let batch =
3736 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(needle)])?;
3737
3738 let dict_builder = StringDictionaryBuilder::<Int8Type>::new();
3739 let mut builder = dict_builder;
3740 builder.append_value("a");
3741 builder.append_value("c");
3742 let haystack: ArrayRef = Arc::new(builder.finish());
3743
3744 let col_a = col("a", &schema)?;
3745 let expr = InListExpr::try_new_from_array(col_a, haystack, false, &schema)?;
3746 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3747 let result = as_boolean_array(&result);
3748 assert_eq!(
3749 result,
3750 &BooleanArray::from(vec![Some(true), Some(false), Some(true)])
3751 );
3752
3753 Ok(())
3754 }
3755
3756 #[test]
3757 fn test_try_new_from_array_dict_needle_and_plain_haystack() -> Result<()> {
3758 let schema = Schema::new(vec![Field::new(
3759 "a",
3760 DataType::Dictionary(Box::new(DataType::Int8), Box::new(DataType::Int32)),
3761 false,
3762 )]);
3763
3764 let needle = make_int32_dict_array(vec![Some(1), Some(2), Some(3), Some(4)]);
3765 let batch =
3766 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::clone(&needle)])?;
3767
3768 let haystack: ArrayRef = Arc::new(Int32Array::from(vec![1, 3]));
3769 let col_a = col("a", &schema)?;
3770 let expr = InListExpr::try_new_from_array(col_a, haystack, false, &schema)?;
3771 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3772 let result = as_boolean_array(&result);
3773 assert_eq!(
3774 result,
3775 &BooleanArray::from(vec![Some(true), Some(false), Some(true), Some(false)])
3776 );
3777
3778 Ok(())
3779 }
3780
3781 #[test]
3782 fn test_try_new_from_array_dict_haystack_float64() -> Result<()> {
3783 let schema = Schema::new(vec![Field::new("a", DataType::Float64, false)]);
3784 let needle = Float64Array::from(vec![1.0, 2.0, 3.0]);
3785 let batch =
3786 RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(needle)])?;
3787
3788 let haystack = make_f64_dict_array(vec![Some(1.0), Some(3.0)]);
3789
3790 let col_a = col("a", &schema)?;
3791 let expr = InListExpr::try_new_from_array(col_a, haystack, false, &schema)?;
3792 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3793 let result = as_boolean_array(&result);
3794 assert_eq!(
3795 result,
3796 &BooleanArray::from(vec![Some(true), Some(false), Some(true)])
3797 );
3798
3799 Ok(())
3800 }
3801
3802 #[test]
3803 fn test_try_new_from_array_type_mismatch_rejects() -> Result<()> {
3804 let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
3805 let col_a = col("a", &schema)?;
3806 let haystack: ArrayRef = Arc::new(Float64Array::from(vec![1.0, 2.0]));
3807
3808 let result = InListExpr::try_new_from_array(col_a, haystack, false, &schema);
3809 assert!(result.is_err());
3810 Ok(())
3811 }
3812
3813 #[test]
3814 fn test_try_new_from_array_struct_haystack() -> Result<()> {
3815 let struct_fields = Fields::from(vec![
3816 Field::new("x", DataType::Int32, false),
3817 Field::new("y", DataType::Utf8, false),
3818 ]);
3819 let struct_dt = DataType::Struct(struct_fields.clone());
3820 let schema = Schema::new(vec![Field::new("a", struct_dt, true)]);
3821
3822 let needle = Arc::new(StructArray::new(
3824 struct_fields.clone(),
3825 vec![
3826 Arc::new(Int32Array::from(vec![1, 2, 3, 4])),
3827 Arc::new(StringArray::from(vec!["a", "b", "c", "d"])),
3828 ],
3829 Some(vec![true, true, false, true].into()),
3830 ));
3831 let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![needle])?;
3832
3833 let haystack: ArrayRef = Arc::new(StructArray::new(
3835 struct_fields,
3836 vec![
3837 Arc::new(Int32Array::from(vec![1, 4])),
3838 Arc::new(StringArray::from(vec!["a", "d"])),
3839 ],
3840 None,
3841 ));
3842
3843 let col_a = col("a", &schema)?;
3844 let expr = InListExpr::try_new_from_array(
3845 Arc::clone(&col_a),
3846 Arc::clone(&haystack),
3847 false,
3848 &schema,
3849 )?;
3850 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3851 let result = as_boolean_array(&result);
3852 assert_eq!(
3854 result,
3855 &BooleanArray::from(vec![Some(true), Some(false), None, Some(true)])
3856 );
3857
3858 let expr = InListExpr::try_new_from_array(col_a, haystack, true, &schema)?;
3860 let result = expr.evaluate(&batch)?.into_array(batch.num_rows())?;
3861 let result = as_boolean_array(&result);
3862 assert_eq!(
3863 result,
3864 &BooleanArray::from(vec![Some(false), Some(true), None, Some(false)])
3865 );
3866
3867 Ok(())
3868 }
3869}
3870
3871#[cfg(all(test, feature = "proto"))]
3872mod proto_tests {
3873 use super::*;
3874 use crate::expressions::{Column, col, lit};
3875 use crate::proto_test_util::{
3876 StubDecoder, StubEncoder, UnreachableDecoder, column_node,
3877 };
3878 use arrow::datatypes::Field;
3879 use datafusion_common::DataFusionError;
3880 use datafusion_physical_expr_common::physical_expr::proto_decode::PhysicalExprDecodeCtx;
3881 use datafusion_physical_expr_common::physical_expr::proto_encode::PhysicalExprEncodeCtx;
3882 use datafusion_proto_models::protobuf::{
3883 PhysicalExprNode, PhysicalInListNode, physical_expr_node,
3884 };
3885
3886 fn in_list_node(
3888 expr: Option<Box<PhysicalExprNode>>,
3889 list: Vec<PhysicalExprNode>,
3890 negated: bool,
3891 ) -> PhysicalExprNode {
3892 PhysicalExprNode {
3893 expr_id: None,
3894 expr_type: Some(physical_expr_node::ExprType::InList(Box::new(
3895 PhysicalInListNode {
3896 expr,
3897 list,
3898 negated,
3899 },
3900 ))),
3901 }
3902 }
3903
3904 fn in_list_fixture() -> InListExpr {
3906 let schema = Schema::new(vec![Field::new("a", DataType::Int32, true)]);
3907 InListExpr::try_new(col("a", &schema).unwrap(), vec![lit(1)], false, &schema)
3908 .unwrap()
3909 }
3910
3911 #[test]
3912 fn try_to_proto_encodes_in_list() {
3913 let in_list = in_list_fixture();
3914 let encoder = StubEncoder::ok();
3915 let ctx = PhysicalExprEncodeCtx::new(&encoder);
3916
3917 let node = in_list
3918 .try_to_proto(&ctx)
3919 .unwrap()
3920 .expect("InListExpr should encode to Some(node)");
3921
3922 assert!(node.expr_id.is_none());
3924 let in_list_node = match node.expr_type {
3925 Some(physical_expr_node::ExprType::InList(boxed)) => *boxed,
3926 other => panic!("expected an InList node, got {other:?}"),
3927 };
3928 assert!(!in_list_node.negated);
3929 assert!(in_list_node.expr.is_some());
3930 assert_eq!(in_list_node.list.len(), 1);
3931 }
3932
3933 #[test]
3934 fn try_to_proto_propagates_expr_encode_error() {
3935 let in_list = in_list_fixture();
3936 let encoder = StubEncoder::failing_on(1);
3937 let ctx = PhysicalExprEncodeCtx::new(&encoder);
3938 let err = in_list.try_to_proto(&ctx).unwrap_err();
3939 assert!(matches!(err, DataFusionError::Internal(msg) if msg.contains("call 1")));
3940 }
3941
3942 #[test]
3943 fn try_to_proto_propagates_list_encode_error() {
3944 let in_list = in_list_fixture();
3945 let encoder = StubEncoder::failing_on(2);
3947 let ctx = PhysicalExprEncodeCtx::new(&encoder);
3948 let err = in_list.try_to_proto(&ctx).unwrap_err();
3949 assert!(matches!(err, DataFusionError::Internal(msg) if msg.contains("call 2")));
3950 }
3951
3952 #[test]
3953 fn try_from_proto_decodes_in_list() {
3954 let node = in_list_node(
3955 Some(Box::new(column_node("a"))),
3956 vec![column_node("b")],
3957 true,
3958 );
3959 let schema = Schema::new(vec![Field::new("decoded", DataType::Int32, true)]);
3960 let decoder = StubDecoder::ok();
3961 let ctx = PhysicalExprDecodeCtx::new(&schema, &decoder);
3962
3963 let decoded = InListExpr::try_from_proto(&node, &ctx).unwrap();
3964 let in_list = decoded
3965 .downcast_ref::<InListExpr>()
3966 .expect("decoded expr should be an InListExpr");
3967
3968 assert!(in_list.negated());
3969 assert!(in_list.expr().downcast_ref::<Column>().is_some());
3970 assert_eq!(in_list.list().len(), 1);
3971 }
3972
3973 #[test]
3974 fn try_from_proto_rejects_non_in_list_node() {
3975 let node = column_node("a");
3976 let schema = Schema::empty();
3977 let decoder = UnreachableDecoder;
3978 let ctx = PhysicalExprDecodeCtx::new(&schema, &decoder);
3979
3980 let err = InListExpr::try_from_proto(&node, &ctx).unwrap_err();
3981 assert!(matches!(
3982 err,
3983 DataFusionError::Internal(msg) if msg.contains("PhysicalExprNode is not a InList")
3984 ));
3985 }
3986
3987 #[test]
3988 fn try_from_proto_rejects_missing_expr() {
3989 let node = in_list_node(None, vec![column_node("b")], false);
3990 let schema = Schema::empty();
3991 let decoder = UnreachableDecoder;
3992 let ctx = PhysicalExprDecodeCtx::new(&schema, &decoder);
3993
3994 let err = InListExpr::try_from_proto(&node, &ctx).unwrap_err();
3995 assert!(matches!(
3996 err,
3997 DataFusionError::Internal(msg) if msg.contains("InListExpr is missing required field 'expr'")
3998 ));
3999 }
4000
4001 #[test]
4002 fn try_from_proto_propagates_expr_decode_error() {
4003 let node = in_list_node(
4004 Some(Box::new(column_node("a"))),
4005 vec![column_node("b")],
4006 false,
4007 );
4008 let schema = Schema::empty();
4009 let decoder = StubDecoder::failing_on(1);
4010 let ctx = PhysicalExprDecodeCtx::new(&schema, &decoder);
4011 let err = InListExpr::try_from_proto(&node, &ctx).unwrap_err();
4012 assert!(matches!(err, DataFusionError::Internal(msg) if msg.contains("call 1")));
4013 }
4014
4015 #[test]
4016 fn try_from_proto_propagates_list_decode_error() {
4017 let node = in_list_node(
4018 Some(Box::new(column_node("a"))),
4019 vec![column_node("b")],
4020 false,
4021 );
4022 let schema = Schema::empty();
4023 let decoder = StubDecoder::failing_on(2);
4025 let ctx = PhysicalExprDecodeCtx::new(&schema, &decoder);
4026 let err = InListExpr::try_from_proto(&node, &ctx).unwrap_err();
4027 assert!(matches!(err, DataFusionError::Internal(msg) if msg.contains("call 2")));
4028 }
4029}