| 292 | /// Create a new execution plan from a list of constant values (`ValuesExec`) |
| 293 | #[expect(clippy::needless_pass_by_value)] |
| 294 | pub fn try_new_as_values( |
| 295 | schema: SchemaRef, |
| 296 | data: Vec<Vec<Arc<dyn PhysicalExpr>>>, |
| 297 | ) -> Result<Arc<DataSourceExec>> { |
| 298 | if data.is_empty() { |
| 299 | return plan_err!("Values list cannot be empty"); |
| 300 | } |
| 301 | |
| 302 | let n_row = data.len(); |
| 303 | let n_col = schema.fields().len(); |
| 304 | |
| 305 | // We have this single row batch as a placeholder to satisfy evaluation argument |
| 306 | // and generate a single output row |
| 307 | let placeholder_schema = Arc::new(Schema::empty()); |
| 308 | let placeholder_batch = RecordBatch::try_new_with_options( |
| 309 | Arc::clone(&placeholder_schema), |
| 310 | vec![], |
| 311 | &RecordBatchOptions::new().with_row_count(Some(1)), |
| 312 | )?; |
| 313 | |
| 314 | // Evaluate each column |
| 315 | let arrays = (0..n_col) |
| 316 | .map(|j| { |
| 317 | (0..n_row) |
| 318 | .map(|i| { |
| 319 | let expr = &data[i][j]; |
| 320 | let result = expr.evaluate(&placeholder_batch)?; |
| 321 | |
| 322 | match result { |
| 323 | ColumnarValue::Scalar(scalar) => Ok(scalar), |
| 324 | ColumnarValue::Array(array) if array.len() == 1 => { |
| 325 | ScalarValue::try_from_array(&array, 0) |
| 326 | } |
| 327 | ColumnarValue::Array(_) => { |
| 328 | plan_err!("Cannot have array values in a values list") |
| 329 | } |
| 330 | } |
| 331 | }) |
| 332 | .collect::<Result<Vec<_>>>() |
| 333 | .and_then(ScalarValue::iter_to_array) |
| 334 | }) |
| 335 | .collect::<Result<Vec<_>>>()?; |
| 336 | |
| 337 | let batch = RecordBatch::try_new_with_options( |
| 338 | Arc::clone(&schema), |
| 339 | arrays, |
| 340 | &RecordBatchOptions::new().with_row_count(Some(n_row)), |
| 341 | )?; |
| 342 | |
| 343 | let partitions = vec![batch]; |
| 344 | Self::try_new_from_batches(Arc::clone(&schema), partitions) |
| 345 | } |
| 346 | |
| 347 | /// Create a new plan using the provided schema and batches. |
| 348 | /// |