diff --git a/packages/cubejs-backend-native/Cargo.lock b/packages/cubejs-backend-native/Cargo.lock index 92252a358b190..d95706df09f15 100644 --- a/packages/cubejs-backend-native/Cargo.lock +++ b/packages/cubejs-backend-native/Cargo.lock @@ -118,7 +118,7 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "arrow" version = "11.1.0" -source = "git+https://github.com/cube-js/arrow-rs.git?rev=7e9519cbe4a994094c142a0a3e254c114df5c9ab#7e9519cbe4a994094c142a0a3e254c114df5c9ab" +source = "git+https://github.com/cube-js/arrow-rs.git?rev=31c0d8f5e99e5c3da462e58bf23a45502c7416db#31c0d8f5e99e5c3da462e58bf23a45502c7416db" dependencies = [ "bitflags 1.3.2", "chrono", @@ -701,7 +701,7 @@ dependencies = [ [[package]] name = "cube-ext" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "arrow", "chrono", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "datafusion" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "ahash 0.7.7", "arrow", @@ -843,7 +843,7 @@ dependencies = [ [[package]] name = "datafusion-common" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "arrow", "ordered-float 2.10.1", @@ -854,7 +854,7 @@ dependencies = [ [[package]] name = "datafusion-data-access" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "async-trait", "chrono", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "datafusion-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "ahash 0.7.7", "arrow", @@ -878,7 +878,7 @@ dependencies = [ [[package]] name = "datafusion-physical-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "ahash 0.7.7", "arrow", @@ -2254,7 +2254,7 @@ dependencies = [ [[package]] name = "parquet" version = "11.1.0" -source = "git+https://github.com/cube-js/arrow-rs.git?rev=7e9519cbe4a994094c142a0a3e254c114df5c9ab#7e9519cbe4a994094c142a0a3e254c114df5c9ab" +source = "git+https://github.com/cube-js/arrow-rs.git?rev=31c0d8f5e99e5c3da462e58bf23a45502c7416db#31c0d8f5e99e5c3da462e58bf23a45502c7416db" dependencies = [ "arrow", "base64 0.13.1", diff --git a/rust/cubesql/Cargo.lock b/rust/cubesql/Cargo.lock index 592409fe873a9..8a5bdfeb91cff 100644 --- a/rust/cubesql/Cargo.lock +++ b/rust/cubesql/Cargo.lock @@ -133,7 +133,7 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "arrow" version = "11.1.0" -source = "git+https://github.com/cube-js/arrow-rs.git?rev=7e9519cbe4a994094c142a0a3e254c114df5c9ab#7e9519cbe4a994094c142a0a3e254c114df5c9ab" +source = "git+https://github.com/cube-js/arrow-rs.git?rev=31c0d8f5e99e5c3da462e58bf23a45502c7416db#31c0d8f5e99e5c3da462e58bf23a45502c7416db" dependencies = [ "bitflags 1.3.2", "chrono", @@ -1005,7 +1005,7 @@ dependencies = [ [[package]] name = "cube-ext" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "arrow", "chrono", @@ -1141,7 +1141,7 @@ dependencies = [ [[package]] name = "datafusion" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "ahash 0.7.6", "arrow", @@ -1174,7 +1174,7 @@ dependencies = [ [[package]] name = "datafusion-common" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "arrow", "ordered-float 2.10.0", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "datafusion-data-access" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "async-trait", "chrono", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "datafusion-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "ahash 0.7.6", "arrow", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "datafusion-physical-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=208a6889c6067b760c6cc2775036570c30a086b5#208a6889c6067b760c6cc2775036570c30a086b5" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=a044caa3a4e5892b27002eef21e925342ab0cbe9#a044caa3a4e5892b27002eef21e925342ab0cbe9" dependencies = [ "ahash 0.7.6", "arrow", @@ -2905,7 +2905,7 @@ dependencies = [ [[package]] name = "parquet" version = "11.1.0" -source = "git+https://github.com/cube-js/arrow-rs.git?rev=7e9519cbe4a994094c142a0a3e254c114df5c9ab#7e9519cbe4a994094c142a0a3e254c114df5c9ab" +source = "git+https://github.com/cube-js/arrow-rs.git?rev=31c0d8f5e99e5c3da462e58bf23a45502c7416db#31c0d8f5e99e5c3da462e58bf23a45502c7416db" dependencies = [ "arrow", "base64 0.13.0", diff --git a/rust/cubesql/cubesql/Cargo.toml b/rust/cubesql/cubesql/Cargo.toml index f193f7f63eb57..3ffd360c6fc31 100644 --- a/rust/cubesql/cubesql/Cargo.toml +++ b/rust/cubesql/cubesql/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://cube.dev" [dependencies] arc-swap = "1" -datafusion = { git = 'https://github.com/cube-js/arrow-datafusion.git', rev = "208a6889c6067b760c6cc2775036570c30a086b5", default-features = false, features = ["regex_expressions", "unicode_expressions"] } +datafusion = { git = 'https://github.com/cube-js/arrow-datafusion.git', rev = "a044caa3a4e5892b27002eef21e925342ab0cbe9", default-features = false, features = ["regex_expressions", "unicode_expressions"] } anyhow = "1.0" thiserror = "1.0.50" cubeclient = { path = "../cubeclient" } diff --git a/rust/cubesql/cubesql/e2e/tests/snapshots/e2e__tests__postgres__pg_test_types.snap b/rust/cubesql/cubesql/e2e/tests/snapshots/e2e__tests__postgres__pg_test_types.snap index f2cd80bdc6d6a..657699c7890fd 100644 --- a/rust/cubesql/cubesql/e2e/tests/snapshots/e2e__tests__postgres__pg_test_types.snap +++ b/rust/cubesql/cubesql/e2e/tests/snapshots/e2e__tests__postgres__pg_test_types.snap @@ -1,9 +1,8 @@ --- source: cubesql/e2e/tests/postgres.rs -assertion_line: 297 expression: "self.print_query_result(res, with_description, true).await" --- -Utf8(NULL) type: 25 (text) +NULL type: 25 (text) f32 type: 700 (float4) f64 type: 701 (float8) i16 type: 21 (int2) @@ -27,8 +26,8 @@ interval_month_day_nano type: 1186 (interval) str_arr type: 1009 (_text) i64_arr type: 1016 (_int8) f64_arr type: 1022 (_float8) -+------------+-------+-------+-----+-----+-----+-----+-----+-----+-----------+------------+------+----+------+---------+--------------+------------+----------------------------+---------------------+-------------------+-------------------------------+-------------+---------+-------------+ -| Utf8(NULL) | f32 | f64 | i16 | u16 | i32 | u32 | i64 | u64 | bool_true | bool_false | str | d0 | d2 | d5 | d10 | date | tsmp | interval_year_month | interval_day_time | interval_month_day_nano | str_arr | i64_arr | f64_arr | -+------------+-------+-------+-----+-----+-----+-----+-----+-----+-----------+------------+------+----+------+---------+--------------+------------+----------------------------+---------------------+-------------------+-------------------------------+-------------+---------+-------------+ -| NULL | 1.234 | 1.234 | 1 | 1 | 1 | 1 | 1 | 1 | true | false | test | 1 | 1.25 | 1.25000 | 1.2500000000 | 2022-04-25 | 2022-04-25 16:25:01.164774 | 1 year 1 mons | 01:30:00 | 1 year 1 mons 1 days 01:30:00 | test1,test2 | 1,2,3 | 1.2,2.3,3.4 | -+------------+-------+-------+-----+-----+-----+-----+-----+-----+-----------+------------+------+----+------+---------+--------------+------------+----------------------------+---------------------+-------------------+-------------------------------+-------------+---------+-------------+ ++------+-------+-------+-----+-----+-----+-----+-----+-----+-----------+------------+------+----+------+---------+--------------+------------+----------------------------+---------------------+-------------------+-------------------------------+-------------+---------+-------------+ +| NULL | f32 | f64 | i16 | u16 | i32 | u32 | i64 | u64 | bool_true | bool_false | str | d0 | d2 | d5 | d10 | date | tsmp | interval_year_month | interval_day_time | interval_month_day_nano | str_arr | i64_arr | f64_arr | ++------+-------+-------+-----+-----+-----+-----+-----+-----+-----------+------------+------+----+------+---------+--------------+------------+----------------------------+---------------------+-------------------+-------------------------------+-------------+---------+-------------+ +| NULL | 1.234 | 1.234 | 1 | 1 | 1 | 1 | 1 | 1 | true | false | test | 1 | 1.25 | 1.25000 | 1.2500000000 | 2022-04-25 | 2022-04-25 16:25:01.164774 | 1 year 1 mons | 01:30:00 | 1 year 1 mons 1 days 01:30:00 | test1,test2 | 1,2,3 | 1.2,2.3,3.4 | ++------+-------+-------+-----+-----+-----+-----+-----+-----+-----------+------------+------+----+------+---------+--------------+------------+----------------------------+---------------------+-------------------+-------------------------------+-------------+---------+-------------+ diff --git a/rust/cubesql/cubesql/src/compile/engine/df/coerce.rs b/rust/cubesql/cubesql/src/compile/engine/df/coerce.rs index 8ff92cdbc7eca..f7ed94455ed70 100644 --- a/rust/cubesql/cubesql/src/compile/engine/df/coerce.rs +++ b/rust/cubesql/cubesql/src/compile/engine/df/coerce.rs @@ -10,6 +10,7 @@ pub fn is_signed_numeric(dt: &DataType) -> bool { | DataType::Float16 | DataType::Float32 | DataType::Float64 + | DataType::Null ) } @@ -33,6 +34,9 @@ pub fn numerical_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option Some(lhs_type.clone()), + (DataType::Null, _) => Some(rhs_type.clone()), + // (_, DataType::UInt64) => Some(DataType::UInt64), (DataType::UInt64, _) => Some(DataType::UInt64), // @@ -50,6 +54,9 @@ pub fn if_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option } let hack_ty = match (lhs_type, rhs_type) { + (_, DataType::Null) => Some(lhs_type.clone()), + (DataType::Null, _) => Some(rhs_type.clone()), + // (DataType::Utf8, DataType::UInt64) => Some(DataType::Utf8), (DataType::Utf8, DataType::Int64) => Some(DataType::Utf8), // @@ -69,6 +76,9 @@ pub fn least_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option Some(lhs_type.clone()), + (DataType::Null, _) => Some(rhs_type.clone()), + // (DataType::Utf8, DataType::UInt64) => Some(DataType::Utf8), (DataType::Utf8, DataType::Int64) => Some(DataType::Utf8), // diff --git a/rust/cubesql/cubesql/src/compile/engine/df/columar.rs b/rust/cubesql/cubesql/src/compile/engine/df/columar.rs index bc0125130b970..8b12b3003e509 100644 --- a/rust/cubesql/cubesql/src/compile/engine/df/columar.rs +++ b/rust/cubesql/cubesql/src/compile/engine/df/columar.rs @@ -9,13 +9,23 @@ use std::sync::Arc; macro_rules! if_then_else { ($BUILDER_TYPE:ty, $ARRAY_TYPE:ty, $BOOLS:expr, $TRUE:expr, $FALSE:expr) => {{ - let true_values = $TRUE + let true_values = if $TRUE.data_type() == &DataType::Null { + Arc::new(<$ARRAY_TYPE>::from(vec![None; $TRUE.len()])) + } else { + $TRUE + }; + let true_values = true_values .as_ref() .as_any() .downcast_ref::<$ARRAY_TYPE>() .expect("true_values downcast failed"); - let false_values = $FALSE + let false_values = if $FALSE.data_type() == &DataType::Null { + Arc::new(<$ARRAY_TYPE>::from(vec![None; $FALSE.len()])) + } else { + $FALSE + }; + let false_values = false_values .as_ref() .as_any() .downcast_ref::<$ARRAY_TYPE>() diff --git a/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs b/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs index fd23b3fd4a6a3..0052a81fc0dfd 100644 --- a/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs +++ b/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs @@ -1258,6 +1258,7 @@ impl CubeScanWrapperNode { } // ScalarValue::IntervalMonthDayNano(_) => {} // ScalarValue::Struct(_, _) => {} + ScalarValue::Null => ("NULL".to_string(), sql_query), x => { return Err(DataFusionError::Internal(format!( "Can't generate SQL for literal: {:?}", diff --git a/rust/cubesql/cubesql/src/compile/engine/udf.rs b/rust/cubesql/cubesql/src/compile/engine/udf.rs index 28b09f79415f9..b77b731f90546 100644 --- a/rust/cubesql/cubesql/src/compile/engine/udf.rs +++ b/rust/cubesql/cubesql/src/compile/engine/udf.rs @@ -395,17 +395,31 @@ pub fn create_isnull_udf() -> ScalarUDF { Arc::new(builder.finish()) as ArrayRef } 2 => { - if args[0].data_type() != &DataType::Utf8 || args[1].data_type() != &DataType::Utf8 - { - return Err(DataFusionError::Internal(format!( - "isnull with 2 arguments supports only (Utf8, Utf8), actual: ({}, {})", - args[0].data_type(), - args[1].data_type(), - ))); - } + let expr = match args[0].data_type() { + DataType::Utf8 => Arc::clone(&args[0]), + DataType::Null => cast(&args[0], &DataType::Utf8)?, + _ => { + return Err(DataFusionError::Internal(format!( + "isnull with 2 arguments supports only (Utf8, Utf8), actual: ({}, {})", + args[0].data_type(), + args[1].data_type(), + ))) + } + }; + let replacement = match args[1].data_type() { + DataType::Utf8 => Arc::clone(&args[1]), + DataType::Null => cast(&args[1], &DataType::Utf8)?, + _ => { + return Err(DataFusionError::Internal(format!( + "isnull with 2 arguments supports only (Utf8, Utf8), actual: ({}, {})", + args[0].data_type(), + args[1].data_type(), + ))) + } + }; - let exprs = downcast_string_arg!(&args[0], "expr", i32); - let replacements = downcast_string_arg!(&args[1], "replacement", i32); + let exprs = downcast_string_arg!(expr, "expr", i32); + let replacements = downcast_string_arg!(replacement, "replacement", i32); let result = exprs .iter() diff --git a/rust/cubesql/cubesql/src/compile/mod.rs b/rust/cubesql/cubesql/src/compile/mod.rs index 80d795ea411f7..f67110baa6978 100644 --- a/rust/cubesql/cubesql/src/compile/mod.rs +++ b/rust/cubesql/cubesql/src/compile/mod.rs @@ -20830,4 +20830,31 @@ limit .sql .contains("DATE(")); } + + #[tokio::test] + async fn test_case_mixed_values_with_null() -> Result<(), CubeError> { + init_logger(); + + insta::assert_snapshot!( + "test_case_mixed_values_with_null", + execute_query( + " + SELECT ACOS( + CASE i + WHEN 0 THEN NULL + ELSE (i::float / 10.0) + END + ) AS acos + FROM ( + SELECT generate_series(0, 5) AS i + ) AS t + " + .to_string(), + DatabaseProtocol::PostgreSQL + ) + .await? + ); + + Ok(()) + } } diff --git a/rust/cubesql/cubesql/src/compile/rewrite/mod.rs b/rust/cubesql/cubesql/src/compile/rewrite/mod.rs index f30282d69b647..b22a7d03c2b54 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/mod.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/mod.rs @@ -17,8 +17,7 @@ use datafusion::{ JoinConstraint, JoinType, Operator, }, physical_plan::{ - aggregates::AggregateFunction, functions::BuiltinScalarFunction, - window_functions::WindowFunction, + aggregates::AggregateFunction, functions::BuiltinScalarFunction, windows::WindowFunction, }, scalar::ScalarValue, }; diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/window_function.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/window_function.rs index fcb92832d2d99..0c2010e06cb72 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/window_function.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/window_function.rs @@ -6,7 +6,7 @@ use crate::{ }, var, var_iter, }; -use datafusion::physical_plan::window_functions::WindowFunction; +use datafusion::physical_plan::windows::WindowFunction; use egg::{EGraph, Rewrite, Subst}; impl WrapperRules { diff --git a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__psqlodbc_null.snap b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__psqlodbc_null.snap index 342dafa609b14..74eb1af4682ff 100644 --- a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__psqlodbc_null.snap +++ b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__psqlodbc_null.snap @@ -2,8 +2,8 @@ source: cubesql/src/compile/mod.rs expression: "execute_query(\"select NULL, NULL, NULL\".to_string(),\n DatabaseProtocol::PostgreSQL).await?" --- -+------------+-------+-------+ -| Utf8(NULL) | NULL2 | NULL3 | -+------------+-------+-------+ -| NULL | NULL | NULL | -+------------+-------+-------+ ++------+-------+-------+ +| NULL | NULL2 | NULL3 | ++------+-------+-------+ +| NULL | NULL | NULL | ++------+-------+-------+ diff --git a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__test_case_mixed_values_with_null.snap b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__test_case_mixed_values_with_null.snap new file mode 100644 index 0000000000000..80e48fc944e6c --- /dev/null +++ b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__test_case_mixed_values_with_null.snap @@ -0,0 +1,14 @@ +--- +source: cubesql/src/compile/mod.rs +expression: "execute_query(\"\n SELECT ACOS(\n CASE i\n WHEN 0 THEN NULL\n ELSE (i::float / 10.0)\n END\n ) AS acos\n FROM (\n SELECT generate_series(0, 5) AS i\n ) AS t\n \".to_string(),\n DatabaseProtocol::PostgreSQL).await?" +--- ++--------------------+ +| acos | ++--------------------+ +| NULL | +| 1.4706289056333368 | +| 1.3694384060045657 | +| 1.266103672779499 | +| 1.1592794807274085 | +| 1.0471975511965976 | ++--------------------+ diff --git a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__to_char_3.snap b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__to_char_3.snap index 54a5c9576fd19..59ff78760d3d0 100644 --- a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__to_char_3.snap +++ b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__to_char_3.snap @@ -1,22 +1,21 @@ --- source: cubesql/src/compile/mod.rs -assertion_line: 10330 expression: "execute_query(\"\n SELECT TO_CHAR(CAST(NULL AS TIMESTAMP), 'FMDay')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-01 00:00:00' AS TIMESTAMP), 'FMDay')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-02 00:00:00' AS TIMESTAMP), 'FMDay')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-07 00:00:00' AS TIMESTAMP), 'FMDay')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-01 00:00:00' AS TIMESTAMP), 'Day')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-02 00:00:00' AS TIMESTAMP), 'Day')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-07 00:00:00' AS TIMESTAMP), 'Day')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-01 00:00:00' AS TIMESTAMP), 'FMMonth')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-03-01 00:00:00' AS TIMESTAMP), 'FMMonth')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-12-01 00:00:00' AS TIMESTAMP), 'FMMonth')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-01-01 00:00:00' AS TIMESTAMP), 'Month')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-03-01 00:00:00' AS TIMESTAMP), 'Month')\n UNION ALL\n SELECT TO_CHAR(CAST('2024-12-01 00:00:00' AS TIMESTAMP), 'Month')\n \".to_string(),\n DatabaseProtocol::PostgreSQL).await?" --- -+------------------------------------------------------------------------+ -| to_char(CAST(Utf8(NULL) AS Timestamp(Nanosecond, None)),Utf8("FMDay")) | -+------------------------------------------------------------------------+ -| NULL | -| Monday | -| Tuesday | -| Sunday | -| Monday | -| Tuesday | -| Sunday | -| January | -| March | -| December | -| January | -| March | -| December | -+------------------------------------------------------------------------+ ++------------------------------------------------------------------+ +| to_char(CAST(NULL AS Timestamp(Nanosecond, None)),Utf8("FMDay")) | ++------------------------------------------------------------------+ +| NULL | +| Monday | +| Tuesday | +| Sunday | +| Monday | +| Tuesday | +| Sunday | +| January | +| March | +| December | +| January | +| March | +| December | ++------------------------------------------------------------------+ diff --git a/rust/cubesql/cubesql/src/sql/dataframe.rs b/rust/cubesql/cubesql/src/sql/dataframe.rs index 3fc241b5080ab..966afdf6b1d86 100644 --- a/rust/cubesql/cubesql/src/sql/dataframe.rs +++ b/rust/cubesql/cubesql/src/sql/dataframe.rs @@ -392,6 +392,7 @@ pub fn arrow_to_column_type(arrow_type: DataType) -> Result Ok(ColumnType::Int64), + DataType::Null => Ok(ColumnType::String), x => Err(CubeError::internal(format!("unsupported type {:?}", x))), } } @@ -625,6 +626,11 @@ pub fn batch_to_dataframe( }); } } + DataType::Null => { + for i in 0..num_rows { + rows[i].push(TableValue::Null) + } + } x => panic!("Unsupported data type: {:?}", x), } } diff --git a/rust/cubesql/cubesql/src/sql/postgres/extended.rs b/rust/cubesql/cubesql/src/sql/postgres/extended.rs index 9a412ef97466a..8b1536ebc2651 100644 --- a/rust/cubesql/cubesql/src/sql/postgres/extended.rs +++ b/rust/cubesql/cubesql/src/sql/postgres/extended.rs @@ -344,7 +344,7 @@ impl Portal { for row in frame.to_rows().into_iter() { for value in row.to_values() { match value { - TableValue::Null => writer.write_value::>(None)?, + TableValue::Null => writer.write_value::>(None)?, TableValue::String(v) => writer.write_value(v)?, TableValue::Int16(v) => writer.write_value(v)?, TableValue::Int32(v) => writer.write_value(v)?, diff --git a/rust/cubesql/cubesql/src/sql/postgres/pg_type.rs b/rust/cubesql/cubesql/src/sql/postgres/pg_type.rs index fe2010e09f7e1..dda52d0f07600 100644 --- a/rust/cubesql/cubesql/src/sql/postgres/pg_type.rs +++ b/rust/cubesql/cubesql/src/sql/postgres/pg_type.rs @@ -20,7 +20,7 @@ pub fn df_type_to_pg_tid(dt: &DataType) -> Result { None => Ok(PgTypeId::TIMESTAMP), Some(_) => Ok(PgTypeId::TIMESTAMPTZ), }, - DataType::Null => Ok(PgTypeId::BOOL), + DataType::Null => Ok(PgTypeId::TEXT), DataType::List(field) => match field.data_type() { DataType::Boolean => Ok(PgTypeId::ARRAYBOOL), DataType::Int8 => Ok(PgTypeId::ARRAYINT2), diff --git a/rust/cubesql/cubesql/src/transport/service.rs b/rust/cubesql/cubesql/src/transport/service.rs index 2f6e58aebad55..65e451c6447a1 100644 --- a/rust/cubesql/cubesql/src/transport/service.rs +++ b/rust/cubesql/cubesql/src/transport/service.rs @@ -7,7 +7,7 @@ use cubeclient::{ use datafusion::{ arrow::{datatypes::SchemaRef, record_batch::RecordBatch}, logical_plan::window_frames::WindowFrame, - physical_plan::{aggregates::AggregateFunction, window_functions::WindowFunction}, + physical_plan::{aggregates::AggregateFunction, windows::WindowFunction}, }; use minijinja::{context, value::Value, Environment}; use serde_derive::*;