diff --git a/datafusion/core/tests/sql/expr.rs b/datafusion/core/tests/sql/expr.rs index 3d8ccf86675d..1aa0e137b759 100644 --- a/datafusion/core/tests/sql/expr.rs +++ b/datafusion/core/tests/sql/expr.rs @@ -19,660 +19,6 @@ use datafusion::datasource::empty::EmptyTable; use super::*; -#[tokio::test] -async fn case_when() -> Result<()> { - let ctx = create_case_context()?; - let sql = "SELECT \ - CASE WHEN c1 = 'a' THEN 1 \ - WHEN c1 = 'b' THEN 2 \ - END \ - FROM t1"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+------------------------------------------------------------------------------------+", - "| CASE WHEN t1.c1 = Utf8(\"a\") THEN Int64(1) WHEN t1.c1 = Utf8(\"b\") THEN Int64(2) END |", - "+------------------------------------------------------------------------------------+", - "| 1 |", - "| 2 |", - "| |", - "| |", - "+------------------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn case_when_else() -> Result<()> { - let ctx = create_case_context()?; - let sql = "SELECT \ - CASE WHEN c1 = 'a' THEN 1 \ - WHEN c1 = 'b' THEN 2 \ - ELSE 999 END \ - FROM t1"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+----------------------------------------------------------------------------------------------------+", - "| CASE WHEN t1.c1 = Utf8(\"a\") THEN Int64(1) WHEN t1.c1 = Utf8(\"b\") THEN Int64(2) ELSE Int64(999) END |", - "+----------------------------------------------------------------------------------------------------+", - "| 1 |", - "| 2 |", - "| 999 |", - "| 999 |", - "+----------------------------------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn case_when_with_base_expr() -> Result<()> { - let ctx = create_case_context()?; - let sql = "SELECT \ - CASE c1 WHEN 'a' THEN 1 \ - WHEN 'b' THEN 2 \ - END \ - FROM t1"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+--------------------------------------------------------------------------+", - "| CASE t1.c1 WHEN Utf8(\"a\") THEN Int64(1) WHEN Utf8(\"b\") THEN Int64(2) END |", - "+--------------------------------------------------------------------------+", - "| 1 |", - "| 2 |", - "| |", - "| |", - "+--------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn case_when_else_with_base_expr() -> Result<()> { - let ctx = create_case_context()?; - let sql = "SELECT \ - CASE c1 WHEN 'a' THEN 1 \ - WHEN 'b' THEN 2 \ - ELSE 999 END \ - FROM t1"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+------------------------------------------------------------------------------------------+", - "| CASE t1.c1 WHEN Utf8(\"a\") THEN Int64(1) WHEN Utf8(\"b\") THEN Int64(2) ELSE Int64(999) END |", - "+------------------------------------------------------------------------------------------+", - "| 1 |", - "| 2 |", - "| 999 |", - "| 999 |", - "+------------------------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn case_when_else_with_null_contant() -> Result<()> { - let ctx = create_case_context()?; - let sql = "SELECT \ - CASE WHEN c1 = 'a' THEN 1 \ - WHEN NULL THEN 2 \ - ELSE 999 END \ - FROM t1"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+---------------------------------------------------------------------------------------+", - "| CASE WHEN t1.c1 = Utf8(\"a\") THEN Int64(1) WHEN NULL THEN Int64(2) ELSE Int64(999) END |", - "+---------------------------------------------------------------------------------------+", - "| 1 |", - "| 999 |", - "| 999 |", - "| 999 |", - "+---------------------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "SELECT CASE WHEN NULL THEN 'foo' ELSE 'bar' END"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+------------------------------------------------------+", - "| CASE WHEN NULL THEN Utf8(\"foo\") ELSE Utf8(\"bar\") END |", - "+------------------------------------------------------+", - "| bar |", - "+------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn case_expr_with_null() -> Result<()> { - let ctx = SessionContext::new(); - let sql = "select case when b is null then null else b end from (select a,b from (values (1,null),(2,3)) as t (a,b)) a;"; - let actual = execute_to_batches(&ctx, sql).await; - - let expected = vec![ - "+----------------------------------------------+", - "| CASE WHEN a.b IS NULL THEN NULL ELSE a.b END |", - "+----------------------------------------------+", - "| |", - "| 3 |", - "+----------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "select case when b is null then null else b end from (select a,b from (values (1,1),(2,3)) as t (a,b)) a;"; - let actual = execute_to_batches(&ctx, sql).await; - - let expected = vec![ - "+----------------------------------------------+", - "| CASE WHEN a.b IS NULL THEN NULL ELSE a.b END |", - "+----------------------------------------------+", - "| 1 |", - "| 3 |", - "+----------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - Ok(()) -} - -#[tokio::test] -async fn case_expr_with_nulls() -> Result<()> { - let ctx = SessionContext::new(); - let sql = "select case when b is null then null when b < 3 then null when b >=3 then b + 1 else b end from (select a,b from (values (1,null),(1,2),(2,3)) as t (a,b)) a"; - let actual = execute_to_batches(&ctx, sql).await; - - let expected = vec![ - "+---------------------------------------------------------------------------------------------------------------------+", - "| CASE WHEN a.b IS NULL THEN NULL WHEN a.b < Int64(3) THEN NULL WHEN a.b >= Int64(3) THEN a.b + Int64(1) ELSE a.b END |", - "+---------------------------------------------------------------------------------------------------------------------+", - "| |", - "| |", - "| 4 |", - "+---------------------------------------------------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "select case b when 1 then null when 2 then null when 3 then b + 1 else b end from (select a,b from (values (1,null),(1,2),(2,3)) as t (a,b)) a;"; - let actual = execute_to_batches(&ctx, sql).await; - - let expected = vec![ - "+---------------------------------------------------------------------------------------------------------+", - "| CASE a.b WHEN Int64(1) THEN NULL WHEN Int64(2) THEN NULL WHEN Int64(3) THEN a.b + Int64(1) ELSE a.b END |", - "+---------------------------------------------------------------------------------------------------------+", - "| |", - "| |", - "| 4 |", - "+---------------------------------------------------------------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - Ok(()) -} - -#[tokio::test] -async fn query_not() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(false), - None, - Some(true), - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT NOT c1 FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------------+", - "| NOT test.c1 |", - "+-------------+", - "| true |", - "| |", - "| false |", - "+-------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn csv_query_sum_cast() { - let ctx = SessionContext::new(); - register_aggregate_csv_by_sql(&ctx).await; - // c8 = i32; c6 = i64 - let sql = "SELECT c8 + c6 FROM aggregate_test_100"; - // check that the physical and logical schemas are equal - execute(&ctx, sql).await; -} - -#[tokio::test] -async fn query_is_null() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Float64, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(Float64Array::from(vec![ - Some(1.0), - None, - Some(f64::NAN), - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS NULL FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-----------------+", - "| test.c1 IS NULL |", - "+-----------------+", - "| false |", - "| true |", - "| false |", - "+-----------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_not_null() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Float64, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(Float64Array::from(vec![ - Some(1.0), - None, - Some(f64::NAN), - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS NOT NULL FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+---------------------+", - "| test.c1 IS NOT NULL |", - "+---------------------+", - "| true |", - "| false |", - "| true |", - "+---------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_true() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(true), - Some(false), - None, - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS TRUE as t FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------+", - "| t |", - "+-------+", - "| true |", - "| false |", - "| false |", - "+-------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_false() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(true), - Some(false), - None, - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS FALSE as f FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------+", - "| f |", - "+-------+", - "| false |", - "| true |", - "| false |", - "+-------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_not_true() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(true), - Some(false), - None, - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS NOT TRUE as nt FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------+", - "| nt |", - "+-------+", - "| false |", - "| true |", - "| true |", - "+-------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_not_false() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(true), - Some(false), - None, - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS NOT FALSE as nf FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------+", - "| nf |", - "+-------+", - "| true |", - "| false |", - "| true |", - "+-------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_unknown() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(true), - Some(false), - None, - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS UNKNOWN as t FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------+", - "| t |", - "+-------+", - "| false |", - "| false |", - "| true |", - "+-------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_is_not_unknown() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Boolean, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(BooleanArray::from(vec![ - Some(true), - Some(false), - None, - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT c1 IS NOT UNKNOWN as t FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------+", - "| t |", - "+-------+", - "| true |", - "| true |", - "| false |", - "+-------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn query_without_from() -> Result<()> { - // Test for SELECT without FROM. - // Should evaluate expressions in project position. - let ctx = SessionContext::new(); - - let sql = "SELECT 1"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+----------+", - "| Int64(1) |", - "+----------+", - "| 1 |", - "+----------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "SELECT 1+2, 3/4, cos(0)"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+---------------------+---------------------+---------------+", - "| Int64(1) + Int64(2) | Int64(3) / Int64(4) | cos(Int64(0)) |", - "+---------------------+---------------------+---------------+", - "| 3 | 0 | 1.0 |", - "+---------------------+---------------------+---------------+", - ]; - assert_batches_eq!(expected, &actual); - - Ok(()) -} - -#[tokio::test] -async fn query_scalar_minus_array() -> Result<()> { - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Int32, true)])); - - let data = RecordBatch::try_new( - schema.clone(), - vec![Arc::new(Int32Array::from(vec![ - Some(0), - Some(1), - None, - Some(3), - ]))], - )?; - - let ctx = SessionContext::new(); - ctx.register_batch("test", data)?; - let sql = "SELECT 4 - c1 FROM test"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+--------------------+", - "| Int64(4) - test.c1 |", - "+--------------------+", - "| 4 |", - "| 3 |", - "| |", - "| 1 |", - "+--------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn test_string_concat_operator() -> Result<()> { - let ctx = SessionContext::new(); - // concat 2 strings - let sql = "SELECT 'aa' || 'b'"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------------------------+", - "| Utf8(\"aa\") || Utf8(\"b\") |", - "+-------------------------+", - "| aab |", - "+-------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - // concat 4 strings as a string concat pipe. - let sql = "SELECT 'aa' || 'b' || 'cc' || 'd'"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+----------------------------------------------------+", - "| Utf8(\"aa\") || Utf8(\"b\") || Utf8(\"cc\") || Utf8(\"d\") |", - "+----------------------------------------------------+", - "| aabccd |", - "+----------------------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - // concat 2 strings and NULL, output should be NULL - let sql = "SELECT 'aa' || NULL || 'd'"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+---------------------------------+", - "| Utf8(\"aa\") || NULL || Utf8(\"d\") |", - "+---------------------------------+", - "| |", - "+---------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - - // concat 1 strings and 2 numeric - let sql = "SELECT 'a' || 42 || 23.3"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-----------------------------------------+", - "| Utf8(\"a\") || Int64(42) || Float64(23.3) |", - "+-----------------------------------------+", - "| a4223.3 |", - "+-----------------------------------------+", - ]; - assert_batches_eq!(expected, &actual); - Ok(()) -} - -#[tokio::test] -async fn test_not_expressions() -> Result<()> { - let ctx = SessionContext::new(); - - let sql = "SELECT not(true), not(false)"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+-------------------+--------------------+", - "| NOT Boolean(true) | NOT Boolean(false) |", - "+-------------------+--------------------+", - "| false | true |", - "+-------------------+--------------------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "SELECT not(1), not(0)"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+--------------+--------------+", - "| NOT Int64(1) | NOT Int64(0) |", - "+--------------+--------------+", - "| -2 | -1 |", - "+--------------+--------------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "SELECT null, not(null)"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+------+----------+", - "| NULL | NOT NULL |", - "+------+----------+", - "| | |", - "+------+----------+", - ]; - assert_batches_eq!(expected, &actual); - - let sql = "SELECT NOT('hi')"; - let result = plan_and_collect(&ctx, sql).await; - match result { - Ok(_) => panic!("expected error"), - Err(e) => { - assert_contains!(e.to_string(), "Can't NOT or BITWISE_NOT datatype: 'Utf8'"); - } - } - Ok(()) -} - -#[tokio::test] -async fn test_negative_expressions() -> Result<()> { - let ctx = SessionContext::new(); - - let sql = "SELECT null, -null"; - let actual = execute_to_batches(&ctx, sql).await; - let expected = vec![ - "+------+----------+", - "| NULL | (- NULL) |", - "+------+----------+", - "| | |", - "+------+----------+", - ]; - - assert_batches_eq!(expected, &actual); - Ok(()) -} - #[tokio::test] async fn test_boolean_expressions() -> Result<()> { test_expression!("true", "true"); diff --git a/datafusion/core/tests/sql/mod.rs b/datafusion/core/tests/sql/mod.rs index 8ccde3ed9ecb..2a05c918b51a 100644 --- a/datafusion/core/tests/sql/mod.rs +++ b/datafusion/core/tests/sql/mod.rs @@ -161,22 +161,6 @@ fn custom_sqrt(args: &[ColumnarValue]) -> Result { } } -fn create_case_context() -> Result { - let ctx = SessionContext::new(); - let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Utf8, true)])); - let data = RecordBatch::try_new( - schema, - vec![Arc::new(StringArray::from(vec![ - Some("a"), - Some("b"), - Some("c"), - None, - ]))], - )?; - ctx.register_batch("t1", data)?; - Ok(ctx) -} - fn create_join_context( column_left: &str, column_right: &str, diff --git a/datafusion/core/tests/sqllogictests/src/main.rs b/datafusion/core/tests/sqllogictests/src/main.rs index 93779621b7bf..46ea60da069c 100644 --- a/datafusion/core/tests/sqllogictests/src/main.rs +++ b/datafusion/core/tests/sqllogictests/src/main.rs @@ -172,6 +172,10 @@ async fn context_for_test_file(relative_path: &Path) -> SessionContext { info!("Registering aggregate tables"); setup::register_aggregate_tables(&ctx).await; } + "scalar.slt" => { + info!("Registering scalar tables"); + setup::register_scalar_tables(&ctx).await; + } _ => { info!("Using default SessionContext"); } diff --git a/datafusion/core/tests/sqllogictests/src/setup.rs b/datafusion/core/tests/sqllogictests/src/setup.rs index b52e06f3f7d1..9e3f154f5948 100644 --- a/datafusion/core/tests/sqllogictests/src/setup.rs +++ b/datafusion/core/tests/sqllogictests/src/setup.rs @@ -159,3 +159,24 @@ async fn register_aggregate_test_100(ctx: &SessionContext) { .await .unwrap(); } + +pub async fn register_scalar_tables(ctx: &SessionContext) { + register_nan_table(ctx) +} + +/// Register a table with a NaN value (different than NULL, and can +/// not be created via SQL) +fn register_nan_table(ctx: &SessionContext) { + let schema = Arc::new(Schema::new(vec![Field::new("c1", DataType::Float64, true)])); + + let data = RecordBatch::try_new( + schema, + vec![Arc::new(Float64Array::from(vec![ + Some(1.0), + None, + Some(f64::NAN), + ]))], + ) + .unwrap(); + ctx.register_batch("test_float", data).unwrap(); +} diff --git a/datafusion/core/tests/sqllogictests/test_files/scalar.slt b/datafusion/core/tests/sqllogictests/test_files/scalar.slt index 911aeb37fc31..c91ee33c253c 100644 --- a/datafusion/core/tests/sqllogictests/test_files/scalar.slt +++ b/datafusion/core/tests/sqllogictests/test_files/scalar.slt @@ -26,8 +26,8 @@ CREATE TABLE t1( c INT, d INT ) as VALUES - (1, 100, 567, 1024), - (2, 1000, 123, 256), + (1, 100, 567, 1024), + (2, 1000, 123, 256), (3, 10000, 978, 2048) ; @@ -116,3 +116,320 @@ select d << 2 from t1; 1024 4096 8192 + +statement ok +drop table t1 + + +statement ok +create table t1(c1 varchar) as values ('a'), ('b'), ('c'), (null); + +# case_when() +query I +SELECT +CASE WHEN c1 = 'a' THEN 1 + WHEN c1 = 'b' THEN 2 + END +FROM t1 +---- +1 +2 +NULL +NULL + +# case_when_else() +query I +SELECT +CASE WHEN c1 = 'a' THEN 1 + WHEN c1 = 'b' THEN 2 + ELSE 999 END +FROM t1 +---- +1 +2 +999 +999 + +# case_when_with_base_expr() +query I +SELECT +CASE c1 WHEN 'a' THEN 1 + WHEN 'b' THEN 2 + END +FROM t1 +---- +1 +2 +NULL +NULL + +# case_when_else_with_base_expr() +query I +SELECT +CASE c1 WHEN 'a' THEN 1 + WHEN 'b' THEN 2 + ELSE 999 END +FROM t1 +---- +1 +2 +999 +999 + +# case_when_else_with_null_contant() +query I + SELECT +CASE WHEN c1 = 'a' THEN 1 + WHEN NULL THEN 2 + ELSE 999 END +FROM t1 +---- +1 +999 +999 +999 + +statement ok +drop table t1 + + +query T +SELECT CASE WHEN NULL THEN 'foo' ELSE 'bar' END +---- +bar + +# case_expr_with_null() +query I +select case when b is null then null else b end from (select a,b from (values (1,null),(2,3)) as t (a,b)) a; +---- +NULL +3 + +query I +select case when b is null then null else b end from (select a,b from (values (1,1),(2,3)) as t (a,b)) a; +---- +1 +3 + +# case_expr_with_nulls() +query I +select case when b is null then null when b < 3 then null when b >=3 then b + 1 else b end from (select a,b from (values (1,null),(1,2),(2,3)) as t (a,b)) a +---- +NULL +NULL +4 + +query I +select case b when 1 then null when 2 then null when 3 then b + 1 else b end from (select a,b from (values (1,null),(1,2),(2,3)) as t (a,b)) a; +---- +NULL +NULL +4 + +# csv_query_sum_cast() { + +statement ok +CREATE EXTERNAL TABLE aggregate_test_100 ( + c1 VARCHAR NOT NULL, + c2 TINYINT NOT NULL, + c3 SMALLINT NOT NULL, + c4 SMALLINT, + c5 INT, + c6 BIGINT NOT NULL, + c7 SMALLINT NOT NULL, + c8 INT NOT NULL, + c9 BIGINT UNSIGNED NOT NULL, + c10 VARCHAR NOT NULL, + c11 FLOAT NOT NULL, + c12 DOUBLE NOT NULL, + c13 VARCHAR NOT NULL +) +STORED AS CSV +WITH HEADER ROW +LOCATION '../../testing/data/csv/aggregate_test_100.csv' + +# c8 = i32; c6 = i64 +query TTT +SELECT arrow_typeof(c8), arrow_typeof(c6), arrow_typeof(c8 + c6) FROM aggregate_test_100 limit 1; +---- +Int32 Int64 Int64 + + +statement ok +drop table aggregate_test_100 + +statement ok +create table test_boolean(c1 boolean) as values (false), (null), (true); + +statement ok +create table test_int32(c1 int) as values (0), (1), (null), (3); + +## Note that test_float has a NaN (which is not possible to create in SQL) so it is registered via rust. + +# query_not() + +query B +SELECT NOT c1 FROM test_boolean +---- +true +NULL +false + + +# query_is_null() + +# Note the last value is NaN (not NULL) +query R +SELECT c1 from test_float; +---- +1 +NULL +NaN + + +query B +SELECT c1 IS NULL FROM test_float +---- +false +true +false + +# query_is_not_null() +query B +SELECT c1 IS NOT NULL FROM test_float +---- +true +false +true + + +# query_is_true() +query B +SELECT c1 IS TRUE as t FROM test_boolean +---- +false +false +true + +# query_is_false() +query B +SELECT c1 IS FALSE as f FROM test_boolean +---- +true +false +false + +# query_is_not_true() + +query B +SELECT c1 IS NOT TRUE as nt FROM test_boolean +---- +true +true +false + +# query_is_not_false() +query B +SELECT c1 IS NOT FALSE as nf FROM test_boolean +---- +false +true +true + + +# query_is_unknown() +query B +SELECT c1 IS UNKNOWN as t FROM test_boolean +---- +false +true +false + +# query_is_not_unknown() +query B +SELECT c1 IS NOT UNKNOWN as t FROM test_boolean +---- +true +false +true + + +# query_without_from() + +query I +SELECT 1 +---- +1 + +query IIR +SELECT 1+2, 3/4, cos(0) +---- +3 0 1 + + +# query_scalar_minus_array() +query I +SELECT 4 - c1 FROM test_int32 +---- +4 +3 +NULL +1 + +# test_string_concat_operator() +# concat 2 strings +query T +SELECT 'aa' || 'b' +---- +aab + +# concat 4 strings as a string concat pipe. +query T +SELECT 'aa' || 'b' || 'cc' || 'd' +---- +aabccd + +# concat 2 strings and NULL, output should be NULL +query T +SELECT 'aa' || NULL || 'd' +---- +NULL + +# concat 1 strings and 2 numeric +query T +SELECT 'a' || 42 || 23.3 +---- +a4223.3 + +# test_not_expressions() + +query BB +SELECT not(true), not(false) +---- +false true + +query BB +SELECT not(1), not(0) +---- +-2 -1 + +query ?B +SELECT null, not(null) +---- +NULL NULL + +query error DataFusion error: Error during planning: NOT or BITWISE_NOT not supported for datatype: 'Utf8' +SELECT NOT('hi') + +# test_negative_expressions() + +query ?? +SELECT null, -null +---- +NULL NULL + +statement ok +drop table test_boolean + +statement ok +drop table test_int32 diff --git a/datafusion/physical-expr/src/expressions/not.rs b/datafusion/physical-expr/src/expressions/not.rs index ee44b91c9dfa..b27dfdfef8c3 100644 --- a/datafusion/physical-expr/src/expressions/not.rs +++ b/datafusion/physical-expr/src/expressions/not.rs @@ -77,8 +77,8 @@ impl PhysicalExpr for NotExpr { DataType::Int32 => Ok(DataType::Int32), DataType::Int64 => Ok(DataType::Int64), DataType::Null => Ok(DataType::Null), - _ => Err(DataFusionError::Internal(format!( - "Can't NOT or BITWISE_NOT datatype: '{:?}'", + _ => Err(DataFusionError::Plan(format!( + "NOT or BITWISE_NOT not supported for datatype: '{:?}'", data_type ))), }