Skip to content

Commit bcc9a35

Browse files
committed
Merge branch 'main' into fix-scalar-val-num-ops
2 parents b2849d9 + 1e58928 commit bcc9a35

43 files changed

Lines changed: 643 additions & 109 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/rust.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,9 @@ jobs:
697697
with:
698698
rust-version: stable
699699
- name: Install taplo
700-
run: cargo +stable install taplo-cli --version ^0.9 --locked
700+
uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2
701+
with:
702+
tool: taplo-cli@0.9
701703
# if you encounter an error, try running 'taplo format' to fix the formatting automatically.
702704
- name: Check Cargo.toml formatting
703705
run: taplo format --check

ci/scripts/check_no_cargo_install_in_workflows.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ set -euo pipefail
2222
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
2323
WORKFLOWS_DIR=".github/workflows"
2424

25-
if grep -R -n --include='*.yml' --include='*.yaml' -- 'cargo install' "${WORKFLOWS_DIR}"; then
25+
if grep -R -E -w -n --include='*.yml' --include='*.yaml' -- 'cargo.*install' "${WORKFLOWS_DIR}"; then
2626
echo "[${SCRIPT_NAME}] Found workflow Rust tool installs that should use taiki-e/install-action instead." >&2
2727
exit 1
2828
fi

datafusion-examples/examples/data_io/parquet_embedded_index.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
//! 2. Read and deserialize the index.
8888
//!
8989
//! 3. Create a `TableProvider` that knows how to use the index to quickly find
90-
//! the relevant files, row groups, data pages or rows based on on pushed down
90+
//! the relevant files, row groups, data pages or rows based on pushed down
9191
//! filters.
9292
//!
9393
//! # FAQ: Why do other Parquet readers skip over the custom index?

datafusion-examples/examples/execution_monitoring/memory_pool_execution_plan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
//! - Handle memory pressure by spilling to disk
2727
//! - Release memory when done
2828
29+
use arrow::array::record_batch;
2930
use arrow::record_batch::RecordBatch;
3031
use arrow_schema::SchemaRef;
31-
use datafusion::common::record_batch;
3232
use datafusion::common::{exec_datafusion_err, internal_err};
3333
use datafusion::datasource::{DefaultTableSource, memory::MemTable};
3434
use datafusion::error::Result;

datafusion-examples/examples/ffi/ffi_example_table_provider/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717

1818
use std::sync::Arc;
1919

20-
use arrow::array::RecordBatch;
20+
use arrow::array::{RecordBatch, record_batch};
21+
use arrow::datatypes as arrow_schema;
2122
use arrow::datatypes::{DataType, Field, Schema};
22-
use datafusion::{common::record_batch, datasource::MemTable};
23+
use datafusion::datasource::MemTable;
2324
use datafusion_ffi::proto::logical_extension_codec::FFI_LogicalExtensionCodec;
2425
use datafusion_ffi::table_provider::FFI_TableProvider;
2526
use ffi_module_interface::TableProviderModule;

datafusion/catalog/src/information_schema.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
//! [Information Schema]: https://en.wikipedia.org/wiki/Information_schema
2121
2222
use crate::streaming::StreamingTable;
23+
use crate::table::TableFunction;
2324
use crate::{CatalogProviderList, SchemaProvider, TableProvider};
2425
use arrow::array::builder::{BooleanBuilder, UInt8Builder};
2526
use arrow::{
@@ -81,14 +82,28 @@ impl InformationSchemaProvider {
8182
/// Creates a new [`InformationSchemaProvider`] for the provided `catalog_list`
8283
pub fn new(catalog_list: Arc<dyn CatalogProviderList>) -> Self {
8384
Self {
84-
config: InformationSchemaConfig { catalog_list },
85+
config: InformationSchemaConfig {
86+
catalog_list,
87+
table_functions: HashMap::new(),
88+
},
8589
}
8690
}
91+
92+
/// Attach the session's table (UDTF) functions so that they appear in
93+
/// `information_schema.routines` / `SHOW FUNCTIONS`.
94+
pub fn with_table_functions(
95+
mut self,
96+
table_functions: HashMap<String, Arc<TableFunction>>,
97+
) -> Self {
98+
self.config.table_functions = table_functions;
99+
self
100+
}
87101
}
88102

89103
#[derive(Clone, Debug)]
90104
struct InformationSchemaConfig {
91105
catalog_list: Arc<dyn CatalogProviderList>,
106+
table_functions: HashMap<String, Arc<TableFunction>>,
92107
}
93108

94109
impl InformationSchemaConfig {
@@ -301,6 +316,26 @@ impl InformationSchemaConfig {
301316
)
302317
}
303318
}
319+
320+
// Table functions (UDTFs) don't have scalar signatures; their return
321+
// type is always a table, so emit a single row per UDTF with
322+
// routine_type = "FUNCTION", function_type = "TABLE" and
323+
// data_type = "TABLE".
324+
for name in self.table_functions.keys() {
325+
builder.add_routine(
326+
catalog_name,
327+
schema_name,
328+
name,
329+
"FUNCTION",
330+
// No signature is available for UDTFs; report deterministic
331+
// = false to stay conservative.
332+
false,
333+
Some(&"TABLE"),
334+
"TABLE",
335+
None::<String>,
336+
None::<String>,
337+
)
338+
}
304339
Ok(())
305340
}
306341

@@ -400,6 +435,14 @@ impl InformationSchemaConfig {
400435
}
401436
}
402437

438+
// UDTFs deliberately do NOT appear in `information_schema.parameters`.
439+
// A same-named scalar UDF (e.g. `generate_series` exists as both a
440+
// scalar UDF in functions-nested and a UDTF in functions-table) would
441+
// cross-join with a UDTF row keyed only by (name, rid) and produce
442+
// spurious `TABLE`-typed variants of every scalar signature in
443+
// SHOW FUNCTIONS. `show_functions_to_plan` sources UDTFs directly
444+
// from `information_schema.routines` via a UNION branch instead.
445+
403446
Ok(())
404447
}
405448

@@ -1522,6 +1565,7 @@ mod tests {
15221565
async fn make_tables_uses_table_type() {
15231566
let config = InformationSchemaConfig {
15241567
catalog_list: Arc::new(Fixture),
1568+
table_functions: HashMap::new(),
15251569
};
15261570
let mut builder = InformationSchemaTablesBuilder {
15271571
catalog_names: StringBuilder::new(),

datafusion/common/src/pruning.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ impl PruningStatistics for PartitionPruningStatistics {
305305
/// that has statistics of its columns.
306306
///
307307
/// It is up to the caller to decide what each container represents. For
308-
/// example, they can come from a file (e.g. [`PartitionedFile`]) or a set of of
308+
/// example, they can come from a file (e.g. [`PartitionedFile`]) or a set of
309309
/// files (e.g. [`FileGroup`])
310310
///
311311
/// [`PartitionedFile`]: https://docs.rs/datafusion/latest/datafusion/datasource/listing/struct.PartitionedFile.html

datafusion/common/src/test_util.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ macro_rules! assert_contains {
174174
}
175175

176176
/// A macro to assert that one string is NOT contained within another with
177-
/// a nice error message if they are are.
177+
/// a nice error message if they are.
178178
///
179179
/// Usage: `assert_not_contains!(actual, unexpected)`
180180
///
@@ -364,15 +364,20 @@ macro_rules! create_array {
364364
/// Creates a record batch from literal slice of values, suitable for rapid
365365
/// testing and development.
366366
///
367+
/// **Deprecated**: prefer the upstream macro from `arrow`,
368+
/// [`arrow::array::record_batch`], which now supports both the literal slice
369+
/// form shown below and a variable/expression form.
370+
///
367371
/// Example:
368372
/// ```
369-
/// use datafusion_common::record_batch;
373+
/// use arrow::array::record_batch;
370374
/// let batch = record_batch!(
371375
/// ("a", Int32, vec![1, 2, 3]),
372376
/// ("b", Float64, vec![Some(4.0), None, Some(5.0)]),
373377
/// ("c", Utf8, vec!["alpha", "beta", "gamma"])
374378
/// );
375379
/// ```
380+
#[deprecated(since = "55.0.0", note = "Use `arrow::array::record_batch` instead")]
376381
#[macro_export]
377382
macro_rules! record_batch {
378383
($(($name: expr, $type: ident, $values: expr)),*) => {
@@ -776,6 +781,10 @@ mod tests {
776781
}
777782

778783
#[test]
784+
#[expect(
785+
deprecated,
786+
reason = "testing the deprecated record_batch! macro itself"
787+
)]
779788
fn test_create_record_batch() -> Result<()> {
780789
use arrow::array::Array;
781790

datafusion/core/src/execution/session_state.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,10 @@ impl SessionState {
349349
let resolved_ref = self.resolve_table_ref(table_ref);
350350
if self.config.information_schema() && *resolved_ref.schema == *INFORMATION_SCHEMA
351351
{
352-
return Ok(Arc::new(InformationSchemaProvider::new(Arc::clone(
353-
&self.catalog_list,
354-
))));
352+
return Ok(Arc::new(
353+
InformationSchemaProvider::new(Arc::clone(&self.catalog_list))
354+
.with_table_functions(self.table_functions.clone()),
355+
));
355356
}
356357

357358
self.catalog_list

datafusion/core/tests/dataframe/mod.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use datafusion_functions_aggregate::expr_fn::{
3939
array_agg, avg, avg_distinct, count, count_distinct, max, median, min, sum,
4040
sum_distinct,
4141
};
42+
use datafusion_functions_nested::expr_fn::{array_filter, array_transform, make_array};
4243
use datafusion_functions_nested::make_array::make_array_udf;
4344
use datafusion_functions_window::expr_fn::{first_value, lead, row_number};
4445
use insta::assert_snapshot;
@@ -78,8 +79,8 @@ use datafusion_expr::{
7879
CreateMemoryTable, CreateView, DdlStatement, Expr, ExprFunctionExt, ExprSchemable,
7980
LogicalPlan, LogicalPlanBuilder, ScalarFunctionImplementation, SortExpr, TableType,
8081
WindowFrame, WindowFrameBound, WindowFrameUnits, WindowFunctionDefinition, cast, col,
81-
create_udf, exists, in_subquery, lit, out_ref_col, placeholder, scalar_subquery,
82-
when, wildcard,
82+
create_udf, exists, in_subquery, lambda, lambda_var, lit, out_ref_col, placeholder,
83+
scalar_subquery, when, wildcard,
8384
};
8485
use datafusion_physical_expr::Partitioning;
8586
use datafusion_physical_expr::aggregate::AggregateExprBuilder;
@@ -90,7 +91,9 @@ use datafusion_physical_plan::aggregates::{
9091
AggregateExec, AggregateMode, PhysicalGroupBy,
9192
};
9293
use datafusion_physical_plan::empty::EmptyExec;
93-
use datafusion_physical_plan::{ExecutionPlan, ExecutionPlanProperties, displayable};
94+
use datafusion_physical_plan::{
95+
ExecutionPlan, ExecutionPlanProperties, collect, displayable,
96+
};
9497

9598
use datafusion::error::Result as DataFusionResult;
9699
use datafusion::execution::options::JsonReadOptions;
@@ -7238,3 +7241,45 @@ async fn test_grouping_with_alias() -> Result<()> {
72387241

72397242
Ok(())
72407243
}
7244+
7245+
#[tokio::test]
7246+
async fn test_unresolved_lambda_variable() -> Result<()> {
7247+
let plan = table_with_mixed_lists()
7248+
.await?
7249+
.with_column(
7250+
"c",
7251+
array_transform(
7252+
make_array(vec![col("list")]),
7253+
lambda(
7254+
["x"],
7255+
array_filter(
7256+
lambda_var("x"),
7257+
lambda(["y"], lambda_var("y").gt_eq(lit(2))),
7258+
),
7259+
),
7260+
),
7261+
)?
7262+
.select_columns(&["list", "c"])?
7263+
.into_unoptimized_plan()
7264+
.resolve_lambda_variables()?
7265+
.data;
7266+
7267+
let session = SessionContext::new();
7268+
let exec = session.state().create_physical_plan(&plan).await?;
7269+
let context = session.task_ctx();
7270+
let results = collect(exec, context).await?;
7271+
7272+
let expected = [
7273+
"+-----------+----------+",
7274+
"| list | c |",
7275+
"+-----------+----------+",
7276+
"| [1, 2, 3] | [[2, 3]] |",
7277+
"| | [] |",
7278+
"| [] | [[]] |",
7279+
"| | [] |",
7280+
"+-----------+----------+",
7281+
];
7282+
assert_batches_eq!(expected, &results);
7283+
7284+
Ok(())
7285+
}

0 commit comments

Comments
 (0)