matthewgapp opened a new issue, #7636:
URL: https://github.com/apache/arrow-datafusion/issues/7636

   ### Describe the bug
   
   Row_number function places a non-nullable constraint on its generated field 
and thus the resulting schema should result in a schema that shows that column 
as nulllable: false. But instead, the logical plan resulting from a table 
created using `create table ...` shows a schema with that field as `nullable: 
true`. This results in a runtime panic with queries that involve joins. (not 
quite sure why it doesn't complain on queries that aren't joins).  
   
   ### Error message produced with minimal repo below 
   ```text 
   hread 'main' panicked at 'query failed to execute: 
External(ArrowError(InvalidArgumentError("batches[0] schema is different with 
argument schema.\n            batches[0] schema: Schema { fields: [Field { 
name: \"id\", data_type: Int32, nullable: false, dict_id: 0, dict_is_ordered: 
false, metadata: {} }, Field { name: \"name\", data_type: Utf8, nullable: 
false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: 
\"row_num\", data_type: UInt64, nullable: false, dict_id: 0, dict_is_ordered: 
false, metadata: {} }], metadata: {} },\n            argument schema: Schema { 
fields: [Field { name: \"id\", data_type: Int32, nullable: false, dict_id: 0, 
dict_is_ordered: false, metadata: {} }, Field { name: \"name\", data_type: 
Utf8, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, 
Field { name: \"row_num\", data_type: UInt64, nullable: true, dict_id: 0, 
dict_is_ordered: false, metadata: {} }], metadata: {} }\n            ")))', 
src/main.rs:42:10
   ```
   
   
   
   A bit more context: 
   
   This is where nullable false is set. It's not being picked up in the create 
table statement.
   
https://github.com/apache/arrow-datafusion/blob/78d9613e81557ca5e5db8b75e5c7dec47ccee0a1/datafusion/physical-expr/src/window/row_number.rs#L54
   ```rust
     fn field(&self) -> Result<Field> {
           let nullable = false;
           let data_type = DataType::UInt64;
           Ok(Field::new(self.name(), data_type, nullable))
       }
   ```
   
   
   I haven't investigated how this field property on the `WindowExpr` is 
actually used (or omitted) when constructing the logical plan. 
   
   
   ### To Reproduce
   
   ### Minimal repro 
   
   Run this script which will result in the error 
   
   ```text 
   hread 'main' panicked at 'query failed to execute: 
External(ArrowError(InvalidArgumentError("batches[0] schema is different with 
argument schema.\n            batches[0] schema: Schema { fields: [Field { 
name: \"id\", data_type: Int32, nullable: false, dict_id: 0, dict_is_ordered: 
false, metadata: {} }, Field { name: \"name\", data_type: Utf8, nullable: 
false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: 
\"row_num\", data_type: UInt64, nullable: false, dict_id: 0, dict_is_ordered: 
false, metadata: {} }], metadata: {} },\n            argument schema: Schema { 
fields: [Field { name: \"id\", data_type: Int32, nullable: false, dict_id: 0, 
dict_is_ordered: false, metadata: {} }, Field { name: \"name\", data_type: 
Utf8, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, 
Field { name: \"row_num\", data_type: UInt64, nullable: true, dict_id: 0, 
dict_is_ordered: false, metadata: {} }], metadata: {} }\n            ")))', 
src/main.rs:42:10
   ```
   
   
   
   ```rust
   use std::sync::Arc;
   
   use datafusion::{
       arrow::{
           array::{Int32Array, StringArray},
           datatypes::{DataType, Field, Schema},
           record_batch::RecordBatch,
           util::pretty::print_batches,
       },
       datasource::MemTable,
       prelude::{SessionConfig, SessionContext},
   };
   
   #[tokio::main(flavor = "current_thread")]
   async fn main() {
       let config = SessionConfig::new()
           .with_create_default_catalog_and_schema(true)
           .with_information_schema(true);
   
       let ctx = SessionContext::with_config(config);
   
       ctx.register_table("source_table", Arc::new(create_mem_table()))
           .unwrap();
   
       let create_table_query = r#"create table customers as SELECT *, 
ROW_NUMBER() OVER (ORDER BY id) AS row_num FROM source_table"#;
   
       let _ = ctx
           .sql(create_table_query)
           .await
           .unwrap()
           .collect()
           .await
           .unwrap();
   
       let batches = ctx
           // join query because joins seem to complain about execution schema 
vs plan schema mismatch
           .sql("select a.*, b.* from customers a, customers b")
           .await
           .unwrap()
           .collect()
           .await
           .expect("query failed to execute");
   
       print_batches(&batches).unwrap();
   }
   
   // just some random able that we'll append a row_num column to
   fn create_mem_table() -> MemTable {
       let schema = Arc::new(Schema::new(vec![
           Field::new("id", DataType::Int32, false),
           Field::new("name", DataType::Utf8, false),
       ]));
   
       let ids = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
       let names = Arc::new(StringArray::from(vec![
           "Alice", "Bob", "Charlie", "David", "Eve",
       ]));
   
       let batch = RecordBatch::try_new(schema.clone(), vec![ids as _, names as 
_]).unwrap();
   
       MemTable::try_new(schema, vec![vec![batch]]).unwrap()
   }
   ```
   
   ### Expected behavior
   
   The logical plan shouldn't conflict with the observed record batches during 
execution. No panic should occur. 
   
   ### Additional context
   
   _No response_


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to