)]}'
{
  "log": [
    {
      "commit": "63a2801c1b0b766cc206c2bbebde9c52dac66f60",
      "tree": "3ae906c7c2852a863a565a62937e1b120a818e65",
      "parents": [
        "1da3cf049fa1a7a708acc2c29eba4f2e9dece8db"
      ],
      "author": {
        "name": "Andrew Lamb",
        "email": "andrew@nerdnetworks.org",
        "time": "Fri Oct 16 19:33:14 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 19:33:14 2026 +0000"
      },
      "message": "minor: fold tpcds_planning test into core_integration binary (#26422)\n\n## Which issue does this PR close?\n\nThis follows the same rationale as earlier PRs like\n- #10588\n- #11831\n- #18226\n- #26419\n\n## Rationale for this change\n\nEach `.rs` file directly in `datafusion/core/tests` becomes its own test\nbinary. In this case, the standalone `tpcds_planning` binary requires\n**390 MB** (408,695,296 bytes, as reported by `du -h`) on my machine\n(macOS, aarch64)\n\n```shell\ncargo test -p datafusion --test tpcds_planning --no-run\n```\n\nThe binary was added in\n- #4719\n\n## What changes are included in this PR?\n\nMove `datafusion/core/tests/tpcds_planning.rs` to\n`datafusion/core/tests/sql/tpcds_planning.rs` and register it in\n`sql/mod.rs`, so it is built as part of `core_integration`.\n\nSize of `core_integration` (debug build):\n\n| | bytes |\n|---|---|\n| before | 457,595,344 |\n| after | 458,314,960 (+703 KB) |\n\nSo this saves creating a ~390 MB binary at a cost of ~703 KB in\n`core_integration`.\n\n## What is the testing strategy for this PR?\nCI\n\n## Are there any user-facing changes?\n\nNo, developer productivity / CI efficiency\n\nCo-authored-by: Claude Sonnet 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "1da3cf049fa1a7a708acc2c29eba4f2e9dece8db",
      "tree": "fb5f343c2bde56c11c08789e5b758f8ad2840ed5",
      "parents": [
        "396ea7c19e7731747b7efebf22f638bff741040c"
      ],
      "author": {
        "name": "namanjain24-sudo",
        "email": "namanjainpy@gmail.com",
        "time": "Fri Oct 16 14:37:25 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 14:37:25 2026 +0000"
      },
      "message": "chore(ci): Register the substrait check job with runs-on, route spark checks through xtask (#25195)\n\n## Which issue does this PR close?\n\n- Part of #25148. Also finishes the `cargo check` half of #21048, which\nasks for the CI steps to be reproducible locally.\n\n## Rationale for this change\n\nWhile measuring the `cargo check \u003ccrate\u003e features` jobs for #25148 I\nfound two inconsistencies in them. Neither is a policy question about\nwhich runner to use, so they seemed worth separating out.\n\n**1. The substrait check job never registers with `runs-on`.**\n\nFifteen jobs in `rust.yml` select a `runs-on` runner with\n`extras\u003ds3-cache`. Fourteen of them start with the `runs-on/action` step\nthat registers the job. `cargo check datafusion-substrait features` is\nthe one that does not, so on `push` and `merge_group` it lands on the\n`runs-on` runner but gets neither the external cache nor the job metrics\nthe other fourteen report. It looks like an oversight rather than a\nchoice; the job directly above and below it in the file both have the\nstep.\n\n**2. The spark check job is the last one not going through `xtask`.**\n\n`cargo check datafusion-spark features` calls `cargo check` directly.\nEvery other check step in the workflow goes through `cargo xtask ci step\ncheck`, which is what lets a contributor run the same thing locally.\nAfter this PR there is no raw `cargo check` left in `rust.yml`.\n\n## What changes are included in this PR?\n\nFour lines.\n\n- Add the `runs-on/action` step to\n`linux-datafusion-substrait-features`, matching its siblings.\n- Replace the three `datafusion-spark` `cargo check` invocations with\nthe `xtask` equivalents.\n\nThe commands `xtask` emits are the same ones being replaced, which\n`--explain` confirms:\n\n| step | before | `cargo xtask ci step check datafusion-spark …` |\n| --- | --- | --- |\n| default features | `cargo check --profile ci --all-targets -p\ndatafusion-spark` | `default` |\n| no-default-features | `cargo check --profile ci --no-default-features\n-p datafusion-spark` | `no-default` |\n| core | `cargo check --profile ci --no-default-features -p\ndatafusion-spark --features\u003dcore` | `core` |\n\nI deliberately left out the larger changes those jobs invite, because\nthey are the open question in #25148 rather than something to decide in\na cleanup PR. For the record, what I measured there: five of the seven\n`cargo check \u003ccrate\u003e features` jobs declare no `Rust Dependency Cache`\nstep at all, only `datafusion` and `datafusion-substrait` do; three of\nthe seven are pinned to `ubuntu-latest` rather than the\n`vars.USE_RUNS_ON` expression; and across those seven jobs about a third\nof the wall clock is setup and cache restore paid seven times over.\nHappy to follow up on any of that if it is wanted.\n\n## What is the testing strategy for this PR?\n\nThe three `xtask` commands were run locally against this branch and all\npass:\n\n```\ncargo xtask ci step check datafusion-spark default\ncargo xtask ci step check datafusion-spark no-default\ncargo xtask ci step check datafusion-spark core\n```\n\n`python3 ci/scripts/check_asf_yaml_status_checks.py` reports `OK: All 32\nrequired_status_checks match existing GitHub Actions jobs` — job names\nare unchanged, so the required checks are unaffected.\n`ci/scripts/check_no_cargo_install_in_workflows.sh` and\n`ci/scripts/typos_check.sh` are clean, and the file still parses as YAML\nwith the same 26 jobs.\n\nThe `runs-on/action` half cannot be verified outside the Apache repo,\nsince the action is a no-op on standard GitHub runners.\n\n## Are there any user-facing changes?\n\nNo. CI configuration only.\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e"
    },
    {
      "commit": "396ea7c19e7731747b7efebf22f638bff741040c",
      "tree": "b5eb24bd911b063146a3e9c69627afefe5449c3f",
      "parents": [
        "81824e8230c1189acd2243e1e4ce7aa6e8b38e82"
      ],
      "author": {
        "name": "fys",
        "email": "40801205+fengys1996@users.noreply.github.com",
        "time": "Fri Oct 16 14:16:25 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 14:16:25 2026 +0000"
      },
      "message": "feat!: pass input schema to ExprPlanner::plan_scalar (#26177)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #.\n\n## Rationale for this change\n\nScalar function planners need access to the input schema to inspect\nargument types and field metadata, enabling expression rewrites.\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\n## What changes are included in this PR?\n\nAdd a `\u0026DFSchema` parameter to `ExprPlanner::plan_scalar` and pass the\ninput schema during SQL planning.\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n## What is the testing strategy for this PR?\n\nUpdated `select_scalar_func_with_expr_planner` to verify that the\nplanner can resolve a column argument’s type using the input schema and\ncorrectly rewrite the function call.\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\n\nYes. Implementations overriding `ExprPlanner::plan_scalar` must accept\nan additional `\u0026DFSchema` parameter. This is a breaking API change.\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e"
    },
    {
      "commit": "81824e8230c1189acd2243e1e4ce7aa6e8b38e82",
      "tree": "2b721e8c4a156eda24646ec1046c102d6bbb4c6b",
      "parents": [
        "9f4b005e6e89a820e7c4d014d1ba1d1ca128c5a2"
      ],
      "author": {
        "name": "Singleton",
        "email": "135771543+SingletonYe@users.noreply.github.com",
        "time": "Fri Oct 16 14:13:08 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 14:13:08 2026 +0000"
      },
      "message": "fix: report OneOf signature mismatches as planning errors (#26329)\n\n## Which issue does this PR close?\n\nPart of #20501.\n\nThis is a deliberately narrow slice of that issue, and it is the slice a\nmaintainer previously asked for: #21032 attempted this fix as a large\nchange (it also reworked `sum`/`avg` diagnostics and the public\n`first_value`/`last_value`/`nth_value` arity contracts), was asked to be\nsplit up, and then went stale. This PR is **one behaviour change and\nnothing else**.\n\n## Rationale for this change\n\n`get_valid_types_with_udf` reports \"no `OneOf` branch matched\" with\n`internal_err!`. Every alternative signature failing means the *caller*\npassed the wrong number or types of arguments — a user mistake — yet the\nuser is told:\n\n\u003e This issue was likely caused by a bug in DataFusion\u0027s code. Please\nhelp us to resolve this by filing a bug report in our issue tracker: ...\n\nSo an ordinary SQL typo invites a bug report, and the failure surfaces\nas `Internal error: ...` even though nothing internal went wrong. The\nmaintainer comment on #20070 named exactly this (\"Can try to fix the\ndisplay + internal error reference\").\n\n### Before / after\n\n`SELECT substr(1, 2)`\n\nBefore:\n\n```text\nError during planning: Internal error: Function \u0027substr\u0027 failed to match any signature, errors: Error during planning: Function \u0027substr\u0027 requires String, but received Int64 (DataType: Int64).,Error during planning: Function \u0027substr\u0027 expects 3 arguments but received 2.\nThis issue was likely caused by a bug in DataFusion\u0027s code. Please help us to resolve this by filing a bug report in our issue tracker: https://github.com/apache/datafusion/issues\n```\n\nAfter:\n\n```text\nError during planning: Function \u0027substr\u0027 failed to match any signature, errors: Error during planning: Function \u0027substr\u0027 requires String, but received Int64 (DataType: Int64).,Error during planning: Function \u0027substr\u0027 expects 3 arguments but received 2.\n```\n\nThe message body, the candidate signatures, and the trailing \"No\nfunction matches the given name and argument types ... You might need to\nadd explicit type casts.\" line are all unchanged. Only the `Internal\nerror` kind and the bug-report boilerplate are gone.\n\n## What changes are included in this PR?\n\n- `datafusion/expr/src/type_coercion/functions.rs`: return `plan_err!`\ninstead of `internal_err!` when every `OneOf` branch rejects the\narguments. One line of behaviour change.\n- A unit test covering that failure. It mirrors `substr`\u0027s real\nsignature, so one branch fails on the argument type and the other on the\narity.\n- Ten `sqllogictest` expectations that asserted the old user-visible\ntext, in `array/array_range.slt`, `spark/math/round.slt`, `errors.slt`\nand `math.slt`.\n\n## Are these changes tested?\n\nYes.\n\n- The new unit test fails on `main` and passes with the change; `cargo\ntest -p datafusion-expr --lib` is 282 passed, 0 failed.\n- `cargo fmt --all --check` is clean.\n- I audited every other expectation of this message. The remaining ones\n— `functions.slt`, `aggregate.slt`, `string_literal.slt`,\n`named_arguments.slt`, and one assertion in\n`datafusion/optimizer/src/analyzer/type_coercion.rs` — match on a\nsubstring that does not include the removed prefix, so they are\nunaffected. No `sqllogictest` file asserted the \"This issue was likely\ncaused by a bug...\" boilerplate.\n\nI could not run the full `sqllogictest` suite locally (it needs a full\n`datafusion-core` build), so CI is the verification for the four updated\n`.slt` files.\n\n## Scope\n\nDeliberately left out, to keep this reviewable:\n\n- the message is still verbose and still prefixes every branch error\nwith `Error during planning:` — that is #19004;\n- `errors.join(\",\")` still runs the branch errors together without a\nseparator, which is why the after-message reads `...(DataType:\nInt64).,Error during planning: ...`;\n- the arity phrasing suggested on #20070 (`log expects 1 to 2 arguments,\ngot 3`) is a separate improvement.\n\nHappy to follow up on any of those in separate PRs."
    },
    {
      "commit": "9f4b005e6e89a820e7c4d014d1ba1d1ca128c5a2",
      "tree": "402725dd218ae4bd5caa379ab4132f4ad20407c0",
      "parents": [
        "09fb3f41f1e986b1ccbf2a0075aaff24d1ace01d"
      ],
      "author": {
        "name": "akashjainn",
        "email": "80935005+akashjainn@users.noreply.github.com",
        "time": "Fri Oct 16 14:04:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 14:04:57 2026 +0000"
      },
      "message": "fix: validate parquet.coerce_int96 when it is set (#25628)\n\n## Which issue does this PR close?\n\n- Part of #17498. This covers\n`datafusion.execution.parquet.coerce_int96` only.\n\n## Rationale for this change\n\nThe option is stored as a string, so a bad value is accepted and only\nfails later:\n\n```sql\n-- Succeeds, and SHOW reports \u0027nanos\u0027.\nSET datafusion.execution.parquet.coerce_int96 \u003d \u0027nanos\u0027;\n\n-- Fails here, on the first table that touches Parquet:\n-- Invalid or Unsupported Configuration: Unknown or unsupported parquet coerce_int96: nanos. Valid values are: ns, us, ms, and s.\nCREATE EXTERNAL TABLE t STORED AS PARQUET LOCATION \u0027data.parquet\u0027;\n```\n\nThe same thing happens through `CREATE EXTERNAL TABLE ... OPTIONS\n(\u0027format.coerce_int96\u0027 \u0027nanos\u0027)`. If the table has an explicit schema\nthe string is parsed again in `ParquetSource` with `unwrap()`, so that\npath panics instead.\n\n#20253 fixed this the same way and was reviewed, but went stale and was\nclosed. This picks it up with the review applied.\n\n## What changes are included in this PR?\n\n- `DFTimeUnit` in `parquet_config.rs`: `ns`, `us`, `ms`, `s`, parsed\ncase-insensitively and displayed as those strings, so `SHOW`,\n`information_schema` and the proto encoding are unchanged. The\n`ConfigField` impls follow `DFParquetStatistics`, so a rejected value\nleaves the previous one in place and an unset option stays unset.\n- `ParquetOptions.coerce_int96` becomes `Option\u003cDFTimeUnit\u003e`, and\n`ParquetFormat::coerce_int96()` / `with_coerce_int96()` use the typed\nvalue.\n- `parse_coerce_int96_string` in `datasource-parquet` is removed, along\nwith the `unwrap()` that called it. `From\u003cDFTimeUnit\u003e for\narrow::datatypes::TimeUnit` replaces it.\n- Proto conversion parses on the way in, so a bad value in a serialized\nplan is an error rather than a panic.\n- The option\u0027s docstring said \"If true, ...\" as if it were a boolean. It\nnow says what the value is and lists the valid values. `configs.md` and\n`information_schema.slt` carry that text.\n\nI kept the `Option`. #20253 looked at dropping it, but `None` means \"do\nnot coerce\" and `coerce_int96_tz` only applies when `coerce_int96` is\nset, so `None` and `Some(ns)` are not the same.\n\n## What is the testing strategy for this PR?\n\n- `set_variable.slt`: set, show, one rejected value with its full error\ntext, and that the setting is unchanged afterwards.\n- `test_parquet_coerce_int96_validation` in `config.rs`: valid values, a\nrejected value keeps the previous one, an unset value stays unset,\nnested keys are rejected.\n- `time_unit_parses_and_displays` in `parquet_config.rs`.\n- `test_invalid_parquet_coerce_int96_rejected_from_proto` in\n`proto-common`, and the two existing round-trip tests now use the typed\nvalue.\n- I also checked `CREATE EXTERNAL TABLE ... OPTIONS\n(\u0027format.coerce_int96\u0027 \u0027nanos\u0027)` fails at CREATE time with the new\nmessage. The existing `coerce_int96` data tests in `parquet.slt` and the\ncore Parquet tests pass unchanged.\n\n## Are there any user-facing changes?\n\nYes. An invalid `datafusion.execution.parquet.coerce_int96` is rejected\nby `SET` and by table options with a message, instead of being accepted\nand failing (or panicking) at scan time.\n\nThis changes the public field `ParquetOptions::coerce_int96` from\n`Option\u003cString\u003e` to `Option\u003cDFTimeUnit\u003e`, and the two `ParquetFormat`\naccessors with it, so it needs the `api change` label. SQL and\n`ConfigOptions::set` users are not affected.\n\nI searched GitHub for code that assigns the field directly. These will\nneed a one-line change on upgrade, from `Some(\"us\".to_string())` to\n`Some(DFTimeUnit::Microsecond)` or `Some(\"us\".parse()?)`:\n\n- apache/datafusion-comet: `native/core/src/parquet/parquet_exec.rs`\nhardcodes `\"us\"` for Spark, plus one test assertion.\n- delta-io/delta-rs: `crates/core/src/datafile/properties.rs` uses\n`get_or_insert_with(|| \"us\".to_string())`.\n- lakehq/sail: `crates/sail-session/src/session_factory/mod.rs` assigns\n`\"us\"`, and `crates/sail-data-source/src/formats/parquet/options.rs`\ncopies the field through its own `Option\u003cString\u003e`.\n- DoumanAsh/mishka: `src/datafusion.rs` assigns an owned string.\n\nCode that already uses `DFParquetMetadata::with_coerce_int96` or the\nopener (apache/auron does) takes an arrow `TimeUnit` and is unaffected.\n\nI can add a note to the 56.0.0 upgrade guide matching the\n`ExecutionOptions::time_zone` entry from #25788 if that\u0027s wanted."
    },
    {
      "commit": "09fb3f41f1e986b1ccbf2a0075aaff24d1ace01d",
      "tree": "1c192b9d1f6f5ee58b16a4f77703c86fe1dbe5bc",
      "parents": [
        "4391a2eec1446b3b79ea47742409f9a864649205"
      ],
      "author": {
        "name": "Mohit Gurav",
        "email": "mohitgurav20@gmail.com",
        "time": "Fri Oct 16 14:04:09 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 14:04:09 2026 +0000"
      },
      "message": "fix(physical-plan): replace approximate map_size accounting with exac… (#25825)\n\n## Which issue does this PR close?\nCloses #25734\nRelated to #25188\n\n## Rationale for this change\n`GroupValuesPrimitive::size()` was incorrectly estimating its hash-table\nallocation as `map.capacity() * size_of::\u003c(usize, u64)\u003e()`. This naive\ncalculation omitted `hashbrown`\u0027s control bytes and trailing group\nallocation.\n\nAs a result, the reported memory size was smaller than the actual\nretained allocation (which is especially problematic for small tables).\nThis PR corrects the retained-capacity accounting by utilizing\n`self.map.allocation_size()` directly, just like\n`ArrowBytesMap::size()`.\n\n## What changes are included in this PR?\n- Replaced the capacity approximation in `GroupValuesPrimitive::size()`\nwith `self.map.allocation_size()`.\n- Added a focused test `test_exact_hash_table_allocation_accounting` to\n`primitive.rs`.\n- The tests rigorously compare the reported size delta against the\nindependently observed `map.allocation_size()` across empty, grown, and\nretained-after-emit map capacity states.\n\n## Are these changes tested?\nYes, added the `test_exact_hash_table_allocation_accounting` unit test\ninside `primitive.rs`.\n\n## Are there any user-facing changes?\nNo API changes. This strictly improves the internal memory-pool\naccounting for primitive single-column grouping."
    },
    {
      "commit": "4391a2eec1446b3b79ea47742409f9a864649205",
      "tree": "73040a529b3bbe2c8097dca3f0b50e9137db8777",
      "parents": [
        "8edd071fa277f4248b5de0906de70427405fe723"
      ],
      "author": {
        "name": "Bruce Ritchie",
        "email": "bruce.ritchie@gmail.com",
        "time": "Fri Oct 16 13:52:21 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 13:52:21 2026 +0000"
      },
      "message": "feat(benchmarks): add plan diagnostics to SQL benchmark runners (#26212)\n\n## Which issue does this PR close?\n\n- Part of #21706.\n\n## Rationale for this change\n\nThe native sort-pushdown benchmark can print query plans and execution\nmetrics, but SQL benchmarks do not provide equivalent diagnostics.\nPreserve that capability in the shared SQL harness before migrating the\nsort-pushdown benchmarks.\n\n## What changes are included in this PR?\n\n- Use the existing `--debug` / `DEBUG` option to print logical,\noptimized logical, physical, and post-execution metric plans for SQL\nbenchmark run queries.\n- Support both the simple and Criterion runners, including buffered\nexecution used for result persistence and validation.\n- Retain the executed physical plan so the reported metrics come from\nthat execution. Buffered execution reuses the same plan for validation\nand collection.\n\n## What is the testing strategy for this PR?\n\nA test as written to cover the new diagnostic information. A sample of\nbenchmarks were run with and without the diagnostics to verify they\nworked.\n\n## Are there any user-facing changes?\n\nSQL benchmarks now emit plan diagnostics when `--debug` or `DEBUG\u003dtrue`\nis enabled. Diagnostics are disabled by default. As with the native\nbenchmark, diagnostic output occurs during execution and affects\nmeasured timings.\n\n---------\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e"
    },
    {
      "commit": "8edd071fa277f4248b5de0906de70427405fe723",
      "tree": "45de5d5c2d5216ce03edc64b2a4dddb36689ea84",
      "parents": [
        "cd90b6dd9f8589969624e848cbdf84060ab396df"
      ],
      "author": {
        "name": "Neil Conway",
        "email": "neil.conway@gmail.com",
        "time": "Fri Oct 16 13:51:56 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 13:51:56 2026 +0000"
      },
      "message": "perf: Optimize `array_filter` (#25754)\n\n## Which issue does this PR close?\n\n- N/A\n\n## Rationale for this change\n\nAfter applying the predicate to the input list, `array_filter` has to\ncompute two things: the row offsets for the result list, and the \"keep\"\nbitmap to pass to Arrow\u0027s `filter` kernel to copy the result values.\n\nWhen the predicate returned one or more NULLs, the previous\nimplementation computed row offsets with a bit-by-bit loop over the\nresult of applying the predicate, which is relatively slow. We can do\nbetter by first converting the predicate result bitmap into the \"keep\"\nbitmap (normalizing NULLs to cleared bits), and then using the keep\nbitmap to compute row offsets. This last step can be done in a single\npass over the keep bitmap, using popcount on 64-bit words rather than a\nbit-by-bit loop.\n\nAlong the way, avoid creating two transient copies of the input row\noffset buffer. The previous code built a vector of adjusted row offsets\nto account for slicing of the input list; we can instead account for\nslicing without an additional data structure but instead by subtracting\nthe first offset value from each row offset. This matches how sliced\ninputs are typically handled elsewhere.\n\nBenchmarks: (M4 Max)\n\n  - int32/keep10/no_nulls, 2.592 → 1.500 µs, −42.1%\n  - int32/keep50/no_nulls, 3.381 → 2.350 µs, −30.5%\n  - int32/keep90/no_nulls, 3.937 → 2.908 µs, −26.1%\n  - int32/keep50/null_elements25, 6.075 → 3.069 µs, −49.5%\n  - int32/keep_null_elements, 2.882 → 1.850 µs, −35.8%\n  - int32/keep50/null_rows50, 3.913 → 2.649 µs, −32.3%\n  - int32/keep50/null_rows99, 0.887 → 0.910 µs, +2.6%\n  - utf8/keep10/no_nulls, 10.066 → 9.021 µs, −10.4%\n  - utf8/keep50/no_nulls, 17.283 → 16.163 µs, −6.5%\n  - utf8/keep90/no_nulls, 13.333 → 12.291 µs, −7.8%\n  - utf8/keep50/null_elements25, 19.145 → 16.035 µs, −16.2%\n  - utf8/keep_null_elements, 4.276 → 3.230 µs, −24.5%\n  - utf8/keep50/null_rows50, 10.165 → 8.924 µs, −12.2%\n  - utf8/keep50/null_rows99, 0.939 → 0.956 µs, +1.8%\n  - utf8_view/keep10/no_nulls, 5.142 → 4.109 µs, −20.1%\n  - utf8_view/keep50/no_nulls, 6.160 → 5.118 µs, −16.9%\n  - utf8_view/keep90/no_nulls, 6.899 → 5.837 µs, −15.4%\n  - utf8_view/keep50/null_elements25, 9.254 → 6.166 µs, −33.4%\n  - utf8_view/keep_null_elements, 3.007 → 1.968 µs, −34.6%\n  - utf8_view/keep50/null_rows50, 5.572 → 4.294 µs, −22.9%\n  - utf8_view/keep50/null_rows99, 0.926 → 0.948 µs, +2.4%\n  - utf8/wide_128, 16.476 → 16.268 µs, −1.3%\n  - utf8/variable_0_to_32, 17.254 → 16.081 µs, −6.8%\n  - int32/large_1m/null_elements25, 3010.900 → 779.340 µs, −74.1%\n  - int32/narrow_2/null_elements25, 8.154 → 4.102 µs, −49.7%\n  - scalar/true, 0.325 → 0.271 µs, −16.5%\n  - scalar/false, 0.488 → 0.436 µs, −10.7%\n  - scalar/null, 0.485 → 0.419 µs, −13.6%\n  - int32/keep_all, 2.299 → 1.252 µs, −45.6%\n  - int32/keep_none, 2.376 → 1.356 µs, −42.9%\n  - int32/captured_column, 4.830 → 3.838 µs, −20.5%\n  - int32/keep50/null_rows50/hidden_storage, 5.091 → 3.833 µs, −24.7%\n  - utf8/sliced, 19.148 → 16.247 µs, −15.2%\n  - utf8/large_list, 19.142 → 16.190 µs, −15.4%\n\n## What changes are included in this PR?\n\n* Optimize computing row offsets for result, when predicate returns\nNULLs\n* Compute row offsets in a simpler pass when the input list has no NULL\nrows\n* Avoid needless copy/allocation for adjusted input row offsets\n* Add fast-paths for when the predicate selects all elements or no\nelements\n* Refactor `List` and `LargeList` into a single implementation,\nparameterized on offset type\n* Add benchmark for `array_filter`\n\n## What is the testing strategy for this PR?\n\nExisting tests pass, test coverage expanded.\n\n## Are there any user-facing changes?\n\nNo.\n\n---------\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "cd90b6dd9f8589969624e848cbdf84060ab396df",
      "tree": "b62230bb4259653d0ca0db27f979011b81520d38",
      "parents": [
        "d93699ce388af4153dd6e9f1a6a2c74855b42a5e"
      ],
      "author": {
        "name": "Neil Conway",
        "email": "neil.conway@gmail.com",
        "time": "Fri Oct 16 13:26:07 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 13:26:07 2026 +0000"
      },
      "message": "perf: Optimize `upper`, `lower`, `translate`, `replace` (#26377)\n\n## Which issue does this PR close?\n\n- N/A\n\n## Rationale for this change\n\nFor input arrays with at least one non-ASCII string, #23588 changed\n`upper` on `Utf8` and `LargeUtf8` to convert each value one character at\na time, writing straight into the output instead of calling\n`str::to_uppercase`, to avoid allocating a `String` per row. #26192 did\nthe same for `Utf8View`. However, `str::to_uppercase` has a fast-path\nfor inputs with leading ASCII bytes, so inputs with a mix of ASCII and\nnon-ASCII characters got slower: for example, 128-byte ASCII `Utf8View`\nvalues with one non-ASCII value in the array became 19x slower.\n\nThis PR reverts that change, but in the course of doing so, we also add\nseveral related optimizations to `upper`, `lower`, and the optimized\nstring builders; details below.\n\nBenchmarks: (x86, AMD EPYC Milan)\n\nupper\n- Some non-ASCII rows:\n  - Utf8View, 4096 rows: 952.7 µs → 254.5 µs (−73.3%)\n  - Utf8View, 4096 rows, 10% nulls: 881.7 µs → 270.6 µs (−69.3%)\n  - Utf8View, 8192 rows: 1.94 ms → 539.7 µs (−72.2%)\n  - Utf8View, 8192 rows, 10% nulls: 1.79 ms → 559.4 µs (−68.7%)\n- Non-ASCII words:\n  - Utf8: 825.5 µs → 726.6 µs (−12.0%)\n  - LargeUtf8: 824.7 µs → 726.3 µs (−11.9%)\n  - Utf8View: 759.5 µs → 727.6 µs (−4.2%)\n- Mostly ASCII:\n  - Utf8, len 8: 204.0 µs → 19.6 µs (−90.4%)\n  - Utf8View, len 8: 214.6 µs → 36.5 µs (−83.0%)\n  - Utf8, len 32: 789.6 µs → 23.2 µs (−97.1%)\n  - Utf8View, len 32: 757.4 µs → 36.2 µs (−95.2%)\n  - Utf8, len 128: 3.13 ms → 51.7 µs (−98.3%)\n  - Utf8View, len 128: 2.89 ms → 47.5 µs (−98.4%)\n- Late non-ASCII:\n  - Utf8, len 8: 268.2 µs → 154.1 µs (−42.5%)\n  - Utf8View, len 8: 259.4 µs → 156.5 µs (−39.7%)\n  - Utf8, len 32: 881.8 µs → 136.4 µs (−84.5%)\n  - Utf8View, len 32: 798.5 µs → 138.1 µs (−82.7%)\n  - Utf8, len 128: 3.20 ms → 164.5 µs (−94.9%)\n  - Utf8View, len 128: 2.95 ms → 163.9 µs (−94.4%)\n\nlower\n- Some non-ASCII rows:\n  - Utf8View, 4096 rows: 270.3 µs → 232.8 µs (−13.9%)\n  - Utf8View, 4096 rows, 10% nulls: 271.0 µs → 235.8 µs (−13.0%)\n  - Utf8View, 8192 rows: 568.8 µs → 495.8 µs (−12.8%)\n  - Utf8View, 8192 rows, 10% nulls: 572.5 µs → 502.4 µs (−12.3%)\n- Non-ASCII words:\n  - Utf8: 514.2 µs → 511.0 µs (−0.6%)\n  - LargeUtf8: 507.8 µs → 516.4 µs (+1.7%)\n  - Utf8View: 510.2 µs → 509.4 µs (−0.2%)\n- Mostly ASCII:\n  - Utf8, len 8: 67.8 µs → 18.6 µs (−72.5%)\n  - Utf8View, len 8: 73.9 µs → 36.5 µs (−50.7%)\n  - Utf8, len 32: 60.5 µs → 22.9 µs (−62.2%)\n  - Utf8View, len 32: 68.4 µs → 36.5 µs (−46.6%)\n  - Utf8, len 128: 76.7 µs → 52.1 µs (−32.1%)\n  - Utf8View, len 128: 82.6 µs → 46.8 µs (−43.3%)\n- Late non-ASCII:\n  - Utf8, len 8: 136.9 µs → 138.8 µs (+1.4%)\n  - Utf8View, len 8: 140.0 µs → 139.8 µs (−0.1%)\n  - Utf8, len 32: 115.3 µs → 124.8 µs (+8.2%)\n  - Utf8View, len 32: 117.4 µs → 125.5 µs (+6.9%)\n  - Utf8, len 128: 138.9 µs → 150.0 µs (+8.0%)\n  - Utf8View, len 128: 142.4 µs → 152.3 µs (+7.0%)\n\ntranslate (ASCII scalar from/to, no deletions)\n- Utf8:\n  - 1024 rows, len 8: 10.1 µs → 9.1 µs (−9.8%)\n  - 1024 rows, len 32: 17.9 µs → 15.9 µs (−11.2%)\n  - 1024 rows, len 128: 48.8 µs → 39.2 µs (−19.6%)\n  - 1024 rows, len 1024: 363.8 µs → 270.7 µs (−25.6%)\n  - 4096 rows, len 8: 37.5 µs → 33.7 µs (−10.1%)\n  - 4096 rows, len 32: 68.6 µs → 62.8 µs (−8.5%)\n  - 4096 rows, len 128: 195.8 µs → 154.6 µs (−21.1%)\n  - 4096 rows, len 1024: 1.42 ms → 1.07 ms (−24.7%)\n- Utf8View:\n  - 1024 rows, len 8: 9.1 µs → 8.4 µs (−8.2%)\n  - 1024 rows, len 32: 14.5 µs → 13.8 µs (−4.6%)\n  - 1024 rows, len 128: 36.2 µs → 35.0 µs (−3.3%)\n  - 1024 rows, len 1024: 236.2 µs → 235.4 µs (−0.3%)\n  - 4096 rows, len 8: 34.4 µs → 31.1 µs (−9.5%)\n  - 4096 rows, len 32: 55.4 µs → 52.5 µs (−5.2%)\n  - 4096 rows, len 128: 142.2 µs → 137.0 µs (−3.7%)\n  - 4096 rows, len 1024: 937.7 µs → 940.8 µs (+0.3%)\n\nreplace (single ASCII byte, Utf8)\n- 1024 rows, len 32: 26.2 µs → 9.0 µs (−65.6%)\n- 1024 rows, len 128: 92.6 µs → 16.4 µs (−82.3%)\n- 1024 rows, len 32, 20% nulls: 22.8 µs → 9.1 µs (−60.3%)\n- 1024 rows, len 128, 20% nulls: 76.5 µs → 14.6 µs (−80.9%)\n- 4096 rows, len 32: 103.2 µs → 31.2 µs (−69.7%)\n- 4096 rows, len 128: 372.6 µs → 61.9 µs (−83.4%)\n- 4096 rows, len 32, 20% nulls: 89.9 µs → 33.5 µs (−62.7%)\n- 4096 rows, len 128, 20% nulls: 316.5 µs → 56.8 µs (−82.1%)\n\n## What changes are included in this PR?\n\n* Add `StringViewArrayBuilder::try_append_byte_map`, a fallible variant\nof the existing `append_byte_map`. (We need this to avoid regressing\nerror handling behavior on overflow when we use this method below.)\n* `lower`, `upper`, for non-ASCII input arrays: we now check if each row\nis ASCII. If it is, we construct the result value directly via the\nstring builder\u0027s `try_append_byte_map` method, which vectorizes.\nNon-ASCII rows are converted via `std::to_uppercase /\nstd::to_lowercase`.\n* Make `GenericStringArrayBuilder::try_append_byte_map` copy the bytes\ninto the value buffer and then map them in place, instead of calling\nArrow\u0027s `MutableBuffer::extend` with a mapping iterator. The compiler\nturns the in-place loop into vector code, while the `extend` loop stayed\nscalar. This also speeds up `translate` and `replace`, which call this\nmethod.\n* Comment cleanups / improvements\n* Test consolidation: remove redundant tests, move more tests to SLT,\nimprove test coverage\n* Benchmark consolidation: move `upper` and `lower` benchmarks to the\nsame place, add benchmarks for `upper` and `lower` on mixed ASCII and\nnon-ASCII inputs, add benchmark for `translate` on `Utf8View`\n\n## What is the testing strategy for this PR?\n\nExisting tests pass; new tests added.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "d93699ce388af4153dd6e9f1a6a2c74855b42a5e",
      "tree": "1dc27632f94e23e09fa559fad03ea832a9426ca3",
      "parents": [
        "b6f6990ed5f926fd04fe04c46410f8c6ddfb7674"
      ],
      "author": {
        "name": "xavlee",
        "email": "52435309+xavlee@users.noreply.github.com",
        "time": "Fri Oct 16 09:30:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 09:30:27 2026 +0000"
      },
      "message": "refactor: use group clustering terminology in aggregate execution (#24697)\n\n## Which issue does this PR relate to?\n\n- Part of #24438.\n- Builds on the baseline test in #24737 (merged).\n\n## Rationale for this change\n\nAggregate execution currently uses `InputOrderMode` to select execution\npaths and recognize completed groups.\n\nA group can be completed incrementally when its rows form one contiguous\nrun: once the run ends, that group cannot appear again in the same input\npartition. Sorted input supplies this guarantee, and unsorted input can\nsupply it too:\n\n```text\nAAABBBCCCC -\u003e sorted; groups can be completed incrementally\nCCCAAABBB  -\u003e unsorted; groups can still be completed incrementally\n```\n\nThis PR describes the input\u0027s _**clustering**_ guarantee with\n`GroupClusteringMode` and uses clustering terminology throughout the\naggregate execution machinery. Aggregate construction derives the mode\ndirectly from the existing ordering analysis. The follow-up in #24497\nwill also derive it from grouped equivalence properties.\n\n## What changes are included in this PR?\n\n- Replace the aggregate\u0027s `InputOrderMode` field with\n`GroupClusteringMode::{None, Partial, Full}`:\n  - `None`: Groups have no apparent clustering guarantee.\n- `Partial(indices)`: rows are contiguous on a subset of grouping\nexpressions; a change in that tuple completes all groups in the\npreceding run.\n- `Full`: rows are contiguous on the complete grouping tuple; a change\nin that tuple completes the preceding group.\n- Rename the stateful `GroupOrdering` tracker and its `Partial` and\n`Full` implementations to `GroupClustering`, `GroupClusteringPartial`,\nand `GroupClusteringFull`.\n- Rename the ordered aggregate streams, shared table, and adjacent-key\ngroup-values implementation to use clustered terminology,\n- Preserve actual sort expressions and options through equivalence\nproperties and input-ordering requirements.\n- Display `group_clustering_mode` in aggregate plans and document the\npublic API migration in the DataFusion 56 upgrade guide.\n\n## Stack\n\n1. [#24737 — test: cover unsorted contiguous groups in one\npartition](https://github.com/apache/datafusion/pull/24737) (merged)\n2. [#24697 — refactor: use group clustering terminology in aggregate\nexecution](https://github.com/apache/datafusion/pull/24697) ← **this\nPR**\n3. [#24698 — feat: add Grouped equivalence\nproperties](https://github.com/apache/datafusion/pull/24698)\n4. [#24497 — feat: stream aggregates over grouped\ninput](https://github.com/apache/datafusion/pull/24497)\n\n## Are there any user-facing changes?\n\nYes. This PR changes public Rust APIs:\n\n- `AggregateExec::input_order_mode()` is replaced by\n`AggregateExec::group_clustering_mode()`, returning the public\n`GroupClusteringMode` enum.\n- `AggregateExec::compute_properties` accepts `\u0026GroupClusteringMode` in\nplace of `\u0026InputOrderMode`.\n- The public `GroupOrdering`, `GroupOrderingPartial`, and\n`GroupOrderingFull` types in `aggregates::order` are renamed to\n`GroupClustering`, `GroupClusteringPartial`, and `GroupClusteringFull`.\n- `GroupClustering::try_new` takes `\u0026GroupClusteringMode`;\n`new_group_values` takes `\u0026GroupClustering`.\n\nAggregate plan output uses `group_clustering_mode\u003dFull` and\n`group_clustering_mode\u003dPartial(indices)` in place of\n`ordering_mode\u003dSorted` and `ordering_mode\u003dPartiallySorted(indices)`. SQL\nresults and aggregate execution-path selection retain their existing\nbehavior.\n\n\n## Review this layer\n\n[View this PR\u0027s\ndiff](https://github.com/apache/datafusion/pull/24697/files)"
    },
    {
      "commit": "b6f6990ed5f926fd04fe04c46410f8c6ddfb7674",
      "tree": "e2803d65a59ed8ceb4ac3f1c37f866e1bdceb3ae",
      "parents": [
        "5009f42e4a24d231580222e5628c1e203f07614b"
      ],
      "author": {
        "name": "Isaac Emmanuel",
        "email": "35623334+1cbyc@users.noreply.github.com",
        "time": "Fri Oct 16 06:59:49 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 06:59:49 2026 +0000"
      },
      "message": "refactor: extract aggregate physical planning (#26403)\n\n## Which issue does this PR close?\n\n- Part of #26300.\n\n## Rationale for this change\n\n`DefaultPhysicalPlanner::map_logical_node_to_physical` contains the\ncomplete aggregate planning implementation inline. Moving this arm\nbehind a focused method makes the top-level logical-plan dispatcher\neasier to navigate and reduces conflict pressure around planner changes.\n\n## What changes are included in this PR?\n\nThis PR extracts only the `Aggregate` arm into a private\n`plan_aggregate` method. Schema validation, grouping expression\nlowering, async expression planning, repartition selection, and\npartial/final aggregate construction are unchanged.\n\n## What is the testing strategy for this PR?\n\n- `cargo test -p datafusion --lib physical_planner::tests`\n- `cargo clippy -p datafusion --all-targets --all-features -- -D\nwarnings`\n- `cargo fmt --all -- --check`\n- `git diff --check`\n\nThe existing physical planner tests cover aggregate schema checks,\ngrouping sets, repartitioning, aliases, and scalar subqueries; no new\nbehavior is introduced.\n\n## Are there any user-facing changes?\n\nNo. This is an internal refactor with no public API or behavior change."
    },
    {
      "commit": "5009f42e4a24d231580222e5628c1e203f07614b",
      "tree": "7acef7e869831bafa1953e027eac07f529538acc",
      "parents": [
        "cdc2fc041b6a812a24933abc40da6475dbbf5729"
      ],
      "author": {
        "name": "kosiew",
        "email": "kosiew@gmail.com",
        "time": "Fri Oct 16 02:30:23 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 16 02:30:23 2026 +0000"
      },
      "message": "Account for TopK common-prefix converter memory (#26286)\n\n## Which issue does this PR close?\n\n- Part of #23393\n\n## Rationale for this change\n\n`TopK` underreports retained memory when a common sort prefix is present\nbecause its memory accounting omits the optional\n`common_sort_prefix_converter`. This can cause memory reservations to\nunderestimate TopK\u0027s retained memory, weakening memory-limit\nenforcement.\n\n## What changes are included in this PR?\n\n- Include `common_sort_prefix_converter.size()` exactly once in\n`TopK::size()` when the converter is present.\n- Preserve the existing size calculation when the converter is absent.\n- Add a regression test covering both construction paths and checking\nthat the memory reservation matches the reported size after batch\ninsertion.\n\n## Are these changes tested?\n\nAdded `test_topk_size_common_sort_prefix_converter`, which verifies:\n\n- A common-prefix converter is created and reports a nonzero size.\n- Without a common prefix, `TopK::size()` retains its existing formula.\n- With a common prefix, the reported size increases by the converter\u0027s\nsize.\n- After `insert_batch()`, the memory reservation matches `TopK::size()`.\n\nThe test does not rely on global allocator measurements.\n\n## Are there any user-facing changes?\n\nNo changes to query results or public APIs. The change corrects internal\nmemory accounting for TopK with a common sort prefix, potentially\nimproving memory-limit enforcement.\n\n## LLM-generated code disclosure\n\nThis PR includes LLM-generated code and comments. All LLM-generated\ncontent has been manually reviewed."
    },
    {
      "commit": "cdc2fc041b6a812a24933abc40da6475dbbf5729",
      "tree": "c156419899d49819f14fb51e7b948daf48020cbb",
      "parents": [
        "b645de03f3d8b48e413b6ca38c4a9a4f48acdd6a"
      ],
      "author": {
        "name": "Adrian Garcia Badaracco",
        "email": "1755071+adriangb@users.noreply.github.com",
        "time": "Thu Oct 15 21:30:04 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 21:30:04 2026 +0000"
      },
      "message": "feat: support `WITH ... AS [NOT] MATERIALIZED` CTEs (#25580)\n\n## Which issue does this PR close?\n\n- Closes #17737.\n- Related: #8777, #22676, #10337.\n\n## Rationale for this change\n\nDataFusion inlines every CTE reference. When a query references the same\nCTE several times, the CTE body is planned and executed once for each\nreference. Postgres lets users opt out of this with `WITH x AS\nMATERIALIZED (...)`. `sqlparser` already parses the directive into\n`Cte.materialized`, but the SQL planner ignores it.\n\nEarlier attempts (#22551, #22675) bundled automatic materialization,\nheuristics and filter pushdown. This PR is limited to the explicit\ndirective, as proposed in\nhttps://github.com/apache/datafusion/issues/17737#issuecomment-5767781260:\n\n- No config flag.\n- No heuristic.\n- Queries without `MATERIALIZED` plan exactly as before.\n\nDeciding automatically when to materialize can be discussed separately.\n\nExample:\n\n```sql\nWITH r AS MATERIALIZED (SELECT random() AS v)\nSELECT a.v \u003d b.v FROM r a, r b;\n-- true: the body runs once. With NOT MATERIALIZED (or no directive) each reference evaluates random() separately.\n```\n\n## What changes are included in this PR?\n\n- **Planner:** `datafusion/sql/src/cte.rs` and `query.rs` plan a\n`MATERIALIZED` CTE as a `MaterializedCte` node, whose children are the\nCTE body and the rest of the query, plus one `MaterializedCteScan` leaf\nfor each reference. These are `UserDefinedLogicalNode`s in\n`datafusion-expr`.\n  - `NOT MATERIALIZED` and the default keep today\u0027s inlining.\n- `MATERIALIZED` also applies in a `WITH RECURSIVE` block. A recursive\nCTE is still planned as `RecursiveQuery`, and its reference to itself\nstays a work table scan.\n- `head_output_expr`, `PullUpCorrelatedExpr` and `PushDownFilter` look\nthrough `MaterializedCte` to its continuation, so `IN` / `EXISTS`\nsubqueries and filters from an outer query work as with an inlined CTE.\nThe body is never filtered.\n- Each occurrence of a CTE in a plan gets its own id before physical\nplanning, so a view that is referenced two times runs its CTE two times,\nas in PostgreSQL.\n- **Physical plan:** `MaterializedCteExec` and `MaterializedCteScanExec`\nin `datafusion-physical-plan`, and a physical planner pass that binds\neach scan to its producer.\n- **Execution:** the body is run to completion once, all body partitions\nin parallel, on the first poll of any scan. It is started by one shared\nfuture and runs in a `JoinSet` that is aborted when dropped. Every scan\nthen replays the buffered batches.\n- **Why full buffering:** a bounded streaming fan-out deadlocks when,\nfor example, both sides of one hash join read the same CTE (see #8777).\nThis design cannot deadlock.\n- **Memory:** buffered batches are tracked by a `MemoryReservation`\ncreated with `can_spill(true)`. When the reservation cannot grow, the\nrest of that partition is written to a spill file through\n`SpillManager`. `SpillFile::read_stream` can be called by any number of\nreaders at the same time, so every scan replays both the in-memory\nbatches and the spill files. Scans read spill files without read-ahead,\nand after buffering one decoded batch per concurrent reader is reserved.\nIf the pool cannot grant this, in-memory batches are moved to spill\nfiles until it can. Each scan reserves memory for the largest batch on\ndisk, so an in-memory batch that is larger than the batches on disk is\nwritten in pieces, and a move is made only when it releases more memory\nthan it adds to the scans.\nhttps://github.com/apache/datafusion/pull/25910 adds a byte bound to\nspill files with a better size model; when it merges, this operator can\nuse it and drop its own slicing. A body that reads an unbounded source\nis rejected at planning time, because it would be buffered forever.\n\n### Notes on earlier review feedback (#22675)\n\n- **CTE names are not unique:** each scan binds to its producer through\nan id allocated by the planner, not through the CTE name. Sibling\nsubqueries that declare CTEs with the same name are tested.\n- **Alignment with `ScalarSubqueryExec`:** `MaterializedCteExec` follows\nthe same shape. The rest of the query is its output and passes through\ninput order, partitioning and statistics. A scan inside a scalar\nsubquery can start the body itself (tested).\n- **Why not `WorkTable`:** `WorkTable` gives its batches to exactly one\nconsumer (`take()`) and returns an error when memory runs out;\n`RecursiveQueryExec` does not spill. A materialized CTE needs N readers\nand spilling. The scan does follow the same pattern as `WorkTableExec`:\na leaf that reads a handle bound at planning time.\n- **Statistics:** the scans report unknown statistics for now. A leaf\ncannot ask its producer for statistics through `StatisticsContext`. I\nwould like to do this in a follow-up. This is a known limitation that\ncan make a plan worse than the plan of the inlined CTE, not only leave\nit the same: `JoinSelection` does not know that a scan is small, and can\nput the other, larger input of a hash join on the build side (pinned in\n`cte_materialized.slt`).\n\n### Out of scope, possible follow-ups\n\nTracked under the EPIC #22676:\n\n- Protobuf serialization. These nodes have no proto encoding yet, so\nserializing a plan that contains them fails in the default extension\ncodec (#26231).\n- Statistics, ordering and partitioning on the scans (#26230).\n- Release the buffer when the last scan finishes rather than when the\nplan is dropped (#26233).\n- Byte-bounded spill files (#26232).\n- Keep the output per run, so that `reset_state` follows its contract\n(#26229).\n- Deciding automatically when to materialize (#26237).\n- First-class `LogicalPlan` variants (#26238).\n- Pushing filters that all references share into the CTE body (#26239).\n- Pruning unused columns from the CTE body (#26240).\n- `sqlparser` parses `[NOT] MATERIALIZED` only in `PostgreSqlDialect`,\nso the tests set that dialect (apache/datafusion-sqlparser-rs#2622).\n- A streaming fan-out for consumers that are known to be independent.\n\n## Are these changes tested?\n\nYes. The new file\n`datafusion/sqllogictest/test_files/cte_materialized.slt` covers:\n\n- a volatile body, which returns one value when `MATERIALIZED` and\ndiffers per reference when `NOT MATERIALIZED` or with no directive;\n- `EXPLAIN`, which shows one `DataSourceExec` for three references;\n- `EXPLAIN ANALYZE`, where the body buffers 4 rows once and each of the\nthree scans outputs 4 rows;\n- a hash join whose two sides both read the CTE, with no deadlock;\n- a scalar subquery reference;\n- a CTE that reads an earlier CTE;\n- sibling CTEs with the same name;\n- `IN`, `NOT IN` and correlated `EXISTS` / `NOT EXISTS` / `IN`\nsubqueries that declare a materialized CTE;\n- `WITH RECURSIVE` with recursive and non-recursive materialized CTEs;\n- a view referenced two times (separate CTEs) and one reference with two\nscans (one shared CTE);\n- a filter from an outer query, which is pushed into the continuation;\n- column aliases;\n- a spill under `memory_limit`: 200k rows, about 184k spilled (part of\nthe in-memory prefix moves to disk to make room for the two readers),\nand both scans still return 200k rows.\n- a spill where the first batch is larger than the batches on disk: the\nquery finishes under an 18 MB limit, and failed before with an empty\npool.\n\nThe full sqllogictest suite passes.\n\n## Are there any user-facing changes?\n\nYes. `WITH ... AS MATERIALIZED` is now honored when the Postgres dialect\nis used. Queries without the directive are unchanged. There is no new\nconfig option and no public API break. The new nodes are additions.\n\n## Open questions for reviewers\n\n1. Should these be a new `LogicalPlan` variant, like `RecursiveQuery`,\nor stay as built-in `UserDefinedLogicalNode`s, as in this PR, which\nkeeps the change smaller?\n2. Is it acceptable for protobuf serialization of these nodes to fail\nuntil a follow-up PR adds it?\n\n---------\n\nCo-authored-by: Claude Opus 5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "b645de03f3d8b48e413b6ca38c4a9a4f48acdd6a",
      "tree": "16d3ef49db805da97485b28c31b7645a9f9bb467",
      "parents": [
        "db425eb58fe2d0715a79b153b2cbfffe9bc8c5b3"
      ],
      "author": {
        "name": "kosiew",
        "email": "kosiew@gmail.com",
        "time": "Thu Oct 15 14:50:33 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 14:50:33 2026 +0000"
      },
      "message": "Keep ClickBench SQL in sync across runners (#25773)\n\n## Which issue does this PR close?\n\n- Part of #25031\n\n## Rationale for this change\n\nThe extended Q6 benchmark uses different SQL from the other ClickBench\nrunners, while Q15 and Q16 are absent from the SQL-benchmark suite and\nSQL logic test. These copies can drift again when a query is edited in\nonly one place.\n\n## What changes are included in this PR?\n\n- Remove the URL cast from the extended Q6 benchmark query.\n- Add extended Q15 and Q16 SQL benchmarks and corresponding SQL logic\ntest entries.\n- Add a parity test for standard and extended ClickBench. It checks that\neach benchmark query appears in its SQL logic test and that benchmark\nand legacy query files have matching IDs and normalized SQL.\n- Update both SQL logic test headers to identify the mirrored query\nlocations.\n\n## Are these changes tested?\n\nThe patch adds `clickbench_parity.rs` and six unit tests covering SQL\nlogic test parsing and SQL normalization. It also adds Q15/Q16 SQL logic\ntest entries with expected value `0`.\n\nThe diff does not show test execution, generation of those expected\nvalues, or the requested Q6 comparisons in single and partitioned\nconfigurations.\n\n## Are there any user-facing changes?\n\nThe extended Q6 SQL benchmark now runs without the URL cast. Q15 and Q16\nare added to the extended SQL-benchmark suite. The diff does not\nestablish whether removing the cast changes Q6 results. No public API\nchange is shown.\n\n## LLM-generated code disclosure\n\nThis PR includes LLM-generated code and comments. All LLM-generated\ncontent has been manually reviewed."
    },
    {
      "commit": "db425eb58fe2d0715a79b153b2cbfffe9bc8c5b3",
      "tree": "a62ed6e55405714f07f0e862a3351e565555ebf9",
      "parents": [
        "519e4c51a715d4c4152c003b77a8443c497eb847"
      ],
      "author": {
        "name": "Liang-Chi Hsieh",
        "email": "viirya@gmail.com",
        "time": "Thu Oct 15 13:09:34 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 13:09:34 2026 +0000"
      },
      "message": "test: use WITH ORDER tables for date_bin/date_trunc ordering plan tests (#26332)\n\n## Which issue does this PR close?\n\n- Follow-up to #25815, from\nhttps://github.com/apache/datafusion/pull/25815#discussion_r4122735316.\n\n## Rationale for this change\n\nIn #25815, @alamb asked why a plan still had a `SortExec` when ordering\npropagation should remove it. That sort was the `TopK(fetch\u003dn)` from the\n`ORDER BY ... LIMIT n` subquery used to produce ordered input. The outer\nsort, the one the test was about, had already been removed. Reading the\ninput from a table declared sorted makes the plans show this directly:\nno sort at all when the ordering propagates, and only the final sort\nwhen it does not.\n\n## What changes are included in this PR?\n\nTest-only. In `datetime/timestamps.slt`, the seven ordering-propagation\n`EXPLAIN` tests through `date_bin`, `date_trunc` and `from_unixtime`\n(plus the result queries next to them) now read from CSV files written\nwith `COPY ... TO` and registered with `CREATE EXTERNAL TABLE ... WITH\nORDER`. This follows the pattern in `order.slt`. Each `DataSourceExec`\nreports the declared `output_ordering`.\n\n- The five cases where the sort is removed (timezone-free\n`from_unixtime`, timezone-free `date_bin`, coarse-precision values\noutside the nanosecond range, positive month stride, nested\n`date_trunc`) now have no `SortExec`.\n- The `America/Goose_Bay` case keeps exactly one `SortExec`, the\nrequired final sort.\n- The data is unchanged: `Timestamp(Second)` columns come from\n`TIMESTAMP(0)`, the coarse-precision case still uses ±10,000,000,000\nseconds, and every query result is unchanged. The Goose Bay result query\nmoved next to its `EXPLAIN`.\n\nI did not find any other `date_bin`/`date_trunc` ordering plan tests\nthat use the `ORDER BY ... LIMIT` subquery pattern. The related tests in\n`group_by.slt` and `sort_pushdown.slt` already use `WITH ORDER`.\n\n## What is the testing strategy for this PR?\n\nThis PR only changes tests. `datetime/timestamps.slt` passes.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "519e4c51a715d4c4152c003b77a8443c497eb847",
      "tree": "7185a344568948a6526c22f6aba50cbccc8691ce",
      "parents": [
        "c52eb9734b4c968ad9880fb82f3214efd88cd82b"
      ],
      "author": {
        "name": "Isaac Emmanuel",
        "email": "35623334+1cbyc@users.noreply.github.com",
        "time": "Thu Oct 15 12:48:51 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:48:51 2026 +0000"
      },
      "message": "fix: propagate CASE unparser errors (#26311)\n\n## Which issue does this PR close?\n\n- Closes #26295.\n\n## Rationale for this change\n\nWhen a simple CASE operand or ELSE branch cannot be unparsed, the\nunparser currently drops that child and returns valid-looking SQL with\ndifferent semantics. Callers should receive the original unparse error\ninstead.\n\n## What changes are included in this PR?\n\nPropagate errors from CASE operands and ELSE branches, matching the\nexisting WHEN/THEN behavior. Add regression coverage for both paths.\n\n## What is the testing strategy for this PR?\n\n- `cargo test -p datafusion-sql --lib` (95 passed)\n- `cargo clippy -p datafusion-sql --all-targets --all-features -- -D\nwarnings`\n- `cargo fmt --all --check`\n\nThe regression test was also run against the pre-fix implementation and\nfailed because unparsing returned a CASE AST instead of an error.\n\n## Are there any user-facing changes?\n\nYes. CASE expressions with unsupported operands or ELSE branches now\nreturn an error instead of producing SQL with altered semantics."
    },
    {
      "commit": "c52eb9734b4c968ad9880fb82f3214efd88cd82b",
      "tree": "07da3ce0d51f3c4d7ad94881c66db0630dc75b58",
      "parents": [
        "91211237689551dfae0f6bd8299ac54bcc1fb1f1"
      ],
      "author": {
        "name": "Patrick Ribbsaeter",
        "email": "patrickswedish@gmail.com",
        "time": "Thu Oct 15 12:48:50 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:48:50 2026 +0000"
      },
      "message": "fix: downcast to FixedSizeBinaryArray in CASE literal lookup table (#26096)\n\n## Which issue does this PR close?\n\nCloses #26012.\n\n## Rationale for this change\n\nIn `LiteralLookupTable`, evaluation of `CASE \u003cexpr\u003e WHEN \u003cliteral\u003e ...`\nwith byte-like literals delegates to `BytesLikeIndexMap`. In\n`try_get_bytes_iterator`, the `DataType::FixedSizeBinary(_)` match arm\nerroneously attempted to downcast the array via `as_binary::\u003ci64\u003e()`\n(inherited from `DataType::LargeBinary`), rather than handling\n`FixedSizeBinaryArray`.\n\nWhen a query contained 2 or more `FixedSizeBinary` WHEN literals,\n`LiteralLookupTable` was constructed and panicked during evaluation when\ndowncasting to `GenericBinaryArray\u003ci64\u003e`:\n```text\nthread \u0027main\u0027 panicked at arrow-array-60.0.0/src/cast.rs:938:29:\nbinary array\n```\n\n## What changes are included in this PR?\n\n1. **Fix Downcast in Lookup Table**: Updated\n`DataType::FixedSizeBinary(_)` arm in `try_get_bytes_iterator`\n(`bytes_like_lookup_table.rs`) to downcast via\n`array.as_fixed_size_binary().iter()`, matching the dictionary\ndowncasting path and returning byte slices correctly.\n2. **Unit Test**: Added\n`test_case_when_literal_lookup_fixed_size_binary_to_int32` in\n`datafusion/physical-expr/src/expressions/case.rs` testing\n`LiteralLookupTable` evaluation with `FixedSizeBinary` literals with and\nwithout ELSE, with and without NULLs.\n3. **Sqllogictest**: Added regression tests in\n`datafusion/sqllogictest/test_files/case.slt` verifying\n`FixedSizeBinary` `CASE` evaluation against branch 1, branch 2,\nfallback, NULL inputs, and multiple rows.\n\n## Are these changes tested?\n\nYes:\n- Unit test in `datafusion/physical-expr/src/expressions/case.rs`\n(`test_case_when_literal_lookup_fixed_size_binary_to_int32`)\n- Sqllogictest in `datafusion/sqllogictest/test_files/case.slt`\n- Validated locally with `cargo test` and `cargo clippy`.\n\n## Are there any user-facing changes?\n\nBug fix: queries with `CASE` expressions containing multiple\n`FixedSizeBinary` literals now evaluate correctly instead of panicking.\n\n---\n*Diff minimization and pre-flight validation performed with [ZeroSlop™\nCI](https://github.com/marketplace/actions/zeroslop-by-ribbsaeter-systems)\n— [Ribbsaeter Systems](https://ribbsaetersystems.com/).*\n\nSigned-off-by: Patrick Ribbsaeter \u003cpatrickswedish@users.noreply.github.com\u003e"
    },
    {
      "commit": "91211237689551dfae0f6bd8299ac54bcc1fb1f1",
      "tree": "48c0b1a726859e5a0ef723277f191d2414d75e8b",
      "parents": [
        "6d99017255bb33db6e8595172ab48e2147c0c19c"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:48:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:48:27 2026 +0000"
      },
      "message": "chore(deps): bump pydata-sphinx-theme from 0.21.0 to 0.23.0 in the all-uv-deps group (#26320)\n\nBumps the all-uv-deps group with 1 update:\n[pydata-sphinx-theme](https://github.com/pydata/pydata-sphinx-theme).\n\nUpdates `pydata-sphinx-theme` from 0.21.0 to 0.23.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/releases\"\u003epydata-sphinx-theme\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev0.23.0\u003c/h2\u003e\n\u003ch2\u003eWhat\u0027s Changed\u003c/h2\u003e\n\u003ch3\u003eImprovements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eLoosen what keys can be cached in the sidebar by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2500\"\u003epydata/pydata-sphinx-theme#2500\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eDeclare color-scheme support and recommend light-dark() in the docs\nby \u003ca\nhref\u003d\"https://github.com/anandghegde\"\u003e\u003ccode\u003e@​anandghegde\u003c/code\u003e\u003c/a\u003e in\n\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2492\"\u003epydata/pydata-sphinx-theme#2492\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePost-merge review for light-dark by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2506\"\u003epydata/pydata-sphinx-theme#2506\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixes\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ePrevent unwanted renders of PST sidebar, even if disabled in\nconfiguration by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2507\"\u003epydata/pydata-sphinx-theme#2507\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFix shortening GitHub organization projects root links by \u003ca\nhref\u003d\"https://github.com/Junaid-PK\"\u003e\u003ccode\u003e@​Junaid-PK\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2498\"\u003epydata/pydata-sphinx-theme#2498\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFix spacing between unnamed API return types by \u003ca\nhref\u003d\"https://github.com/haoran3160-afk\"\u003e\u003ccode\u003e@​haoran3160-afk\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2499\"\u003epydata/pydata-sphinx-theme#2499\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eMaintenance\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eRun npm audit; bump node version; add dep cooldown by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2508\"\u003epydata/pydata-sphinx-theme#2508\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eDependencies\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eBump py-cov-action/python-coverage-comment-action from 4.3 to 4.5 by\n\u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e[bot]\nin \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2513\"\u003epydata/pydata-sphinx-theme#2513\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e[pre-commit.ci] pre-commit autoupdate hooks by \u003ca\nhref\u003d\"https://github.com/pre-commit-ci\"\u003e\u003ccode\u003e@​pre-commit-ci\u003c/code\u003e\u003c/a\u003e[bot]\nin \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2518\"\u003epydata/pydata-sphinx-theme#2518\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eBump astral-sh/setup-uv from 10.0.1 to 10.1.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e[bot]\nin \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2489\"\u003epydata/pydata-sphinx-theme#2489\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eNew Contributors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/anandghegde\"\u003e\u003ccode\u003e@​anandghegde\u003c/code\u003e\u003c/a\u003e\nmade their first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2492\"\u003epydata/pydata-sphinx-theme#2492\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/haoran3160-afk\"\u003e\u003ccode\u003e@​haoran3160-afk\u003c/code\u003e\u003c/a\u003e\nmade their first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2499\"\u003epydata/pydata-sphinx-theme#2499\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eFull Changelog\u003c/strong\u003e: \u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/compare/v0.22.0...v0.23.0\"\u003ehttps://github.com/pydata/pydata-sphinx-theme/compare/v0.22.0...v0.23.0\u003c/a\u003e\u003c/p\u003e\n\u003ch2\u003ev0.23.0rc0\u003c/h2\u003e\n\u003ch2\u003eWhat\u0027s Changed\u003c/h2\u003e\n\u003ch3\u003eImprovements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eLoosen what keys can be cached in the sidebar by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2500\"\u003epydata/pydata-sphinx-theme#2500\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eDeclare color-scheme support and recommend light-dark() in the docs\nby \u003ca\nhref\u003d\"https://github.com/anandghegde\"\u003e\u003ccode\u003e@​anandghegde\u003c/code\u003e\u003c/a\u003e in\n\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2492\"\u003epydata/pydata-sphinx-theme#2492\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixes\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix shortening GitHub organization projects root links by \u003ca\nhref\u003d\"https://github.com/Junaid-PK\"\u003e\u003ccode\u003e@​Junaid-PK\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2498\"\u003epydata/pydata-sphinx-theme#2498\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePrevent unwanted renders of PST sidebar, even if disabled in\nconfiguration by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2507\"\u003epydata/pydata-sphinx-theme#2507\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFix spacing between unnamed API return types by \u003ca\nhref\u003d\"https://github.com/haoran3160-afk\"\u003e\u003ccode\u003e@​haoran3160-afk\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2499\"\u003epydata/pydata-sphinx-theme#2499\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eMaintenance\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eRun npm audit; bump node version; add dep cooldown by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2508\"\u003epydata/pydata-sphinx-theme#2508\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePost-merge review for light-dark by \u003ca\nhref\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2506\"\u003epydata/pydata-sphinx-theme#2506\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eNew Contributors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/anandghegde\"\u003e\u003ccode\u003e@​anandghegde\u003c/code\u003e\u003c/a\u003e\nmade their first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2492\"\u003epydata/pydata-sphinx-theme#2492\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/haoran3160-afk\"\u003e\u003ccode\u003e@​haoran3160-afk\u003c/code\u003e\u003c/a\u003e\nmade their first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/pull/2499\"\u003epydata/pydata-sphinx-theme#2499\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/560ca12ea53e6ba8966ce9b63b07f6f5b9383679\"\u003e\u003ccode\u003e560ca12\u003c/code\u003e\u003c/a\u003e\nBump 0.23.0rc0 -\u0026gt; 0.23.0\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/1a2a2c3edf9adc562bbfdc0dd0258c97bbd96597\"\u003e\u003ccode\u003e1a2a2c3\u003c/code\u003e\u003c/a\u003e\nBump astral-sh/setup-uv from 10.0.1 to 10.1.0 (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2489\"\u003e#2489\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/8a6784534e822056e9c6cba968f28ade1917e5c3\"\u003e\u003ccode\u003e8a67845\u003c/code\u003e\u003c/a\u003e\n[pre-commit.ci] pre-commit autoupdate hooks (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2518\"\u003e#2518\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/ea0a5294b3c3fbec4760cf480473bee60de71826\"\u003e\u003ccode\u003eea0a529\u003c/code\u003e\u003c/a\u003e\nBump py-cov-action/python-coverage-comment-action from 4.3 to 4.5 (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2513\"\u003e#2513\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/daccf136467185acba7e5b1d087eb463593ddf4e\"\u003e\u003ccode\u003edaccf13\u003c/code\u003e\u003c/a\u003e\nBump 0.22.0 -\u0026gt; 0.23.0rc0\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/642ca72266abb05a0848dc02264239c5848da373\"\u003e\u003ccode\u003e642ca72\u003c/code\u003e\u003c/a\u003e\nLoosen what keys can be cached in the sidebar (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2500\"\u003e#2500\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/c223b8223f50098aca52f1a571c366c3c04410a3\"\u003e\u003ccode\u003ec223b82\u003c/code\u003e\u003c/a\u003e\nFix spacing between unnamed API return types (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2499\"\u003e#2499\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/9cfdc3ebebd26d1a9e1a4a4c25a32186f6ae8a3c\"\u003e\u003ccode\u003e9cfdc3e\u003c/code\u003e\u003c/a\u003e\nRun npm audit; bump node version; add dep cooldown (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2508\"\u003e#2508\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/e0a5d5c3ec1b563ce259da45fd5c108e816273aa\"\u003e\u003ccode\u003ee0a5d5c\u003c/code\u003e\u003c/a\u003e\nPrevent unwanted renders of PST sidebar, even if disabled in\nconfiguration (#...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/commit/46a8149ef662eb9c942c200361b411e517322c3f\"\u003e\u003ccode\u003e46a8149\u003c/code\u003e\u003c/a\u003e\nPost-merge review for light-dark (\u003ca\nhref\u003d\"https://redirect.github.com/pydata/pydata-sphinx-theme/issues/2506\"\u003e#2506\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/pydata/pydata-sphinx-theme/compare/v0.21.0...v0.23.0\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dpydata-sphinx-theme\u0026package-manager\u003duv\u0026previous-version\u003d0.21.0\u0026new-version\u003d0.23.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore \u003cdependency name\u003e major version` will close this\ngroup update PR and stop Dependabot creating any more for the specific\ndependency\u0027s major version (unless you unignore this specific\ndependency\u0027s major version or upgrade to it yourself)\n- `@dependabot ignore \u003cdependency name\u003e minor version` will close this\ngroup update PR and stop Dependabot creating any more for the specific\ndependency\u0027s minor version (unless you unignore this specific\ndependency\u0027s minor version or upgrade to it yourself)\n- `@dependabot ignore \u003cdependency name\u003e` will close this group update PR\nand stop Dependabot creating any more for the specific dependency\n(unless you unignore this specific dependency or upgrade to it yourself)\n- `@dependabot unignore \u003cdependency name\u003e` will remove all of the ignore\nconditions of the specified dependency\n- `@dependabot unignore \u003cdependency name\u003e \u003cignore condition\u003e` will\nremove the ignore condition of the specified dependency and ignore\nconditions\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "6d99017255bb33db6e8595172ab48e2147c0c19c",
      "tree": "6f1a2222f83ac2ff6cd6aee4da81830f269b19b6",
      "parents": [
        "6bf43f298b02c92855573b9f21780a20dfbfc2ea"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:48:15 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:48:15 2026 +0000"
      },
      "message": "chore(deps): bump the codeql-actions group across 1 directory with 2 updates (#26321)\n\nBumps the codeql-actions group with 2 updates in the / directory:\n[github/codeql-action/init](https://github.com/github/codeql-action) and\n[github/codeql-action/analyze](https://github.com/github/codeql-action).\n\nUpdates `github/codeql-action/init` from 4.38.2 to 4.38.3\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases\"\u003egithub/codeql-action/init\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev4.38.3\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eUpcoming breaking change\u003c/em\u003e: CodeQL version 2.21.2 and earlier\nwere discontinued on 24 September 2026 alongside GitHub Enterprise\nServer 3.17, and will be unsupported by the next minor release of the\nCodeQL Action. Added a deprecation warning for customers using these\nversions of CodeQL. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4188\"\u003e#4188\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2\"\u003e2.27.2\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4203\"\u003e#4203\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFixed a bug where the decision of whether to use a per-language\nbundle did not account for custom configurations that reference queries\noutside of compiled CodeQL packs. This issue was caught during internal\ntesting and did not affect any customer repositories. We will resume the\nroll out of per-language bundles in the coming weeks. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4184\"\u003e#4184\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/github/codeql-action/blob/main/CHANGELOG.md\"\u003egithub/codeql-action/init\u0027s\nchangelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eCodeQL Action Changelog\u003c/h1\u003e\n\u003cp\u003eSee the \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases\"\u003ereleases\npage\u003c/a\u003e for the relevant changes to the CodeQL CLI and language\npacks.\u003c/p\u003e\n\u003ch2\u003e[UNRELEASED]\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eBreaking change\u003c/em\u003e: Bump the minimum required CodeQL bundle\nversion to 2.20.7. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4205\"\u003e#4205\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.3 - 08 Oct 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eUpcoming breaking change\u003c/em\u003e: CodeQL version 2.21.2 and earlier\nwere discontinued on 24 September 2026 alongside GitHub Enterprise\nServer 3.17, and will be unsupported by the next minor release of the\nCodeQL Action. Added a deprecation warning for customers using these\nversions of CodeQL. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4188\"\u003e#4188\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2\"\u003e2.27.2\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4203\"\u003e#4203\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFixed a bug where the decision of whether to use a per-language\nbundle did not account for custom configurations that reference queries\noutside of compiled CodeQL packs. This issue was caught during internal\ntesting and did not affect any customer repositories. We will resume the\nroll out of per-language bundles in the coming weeks. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4184\"\u003e#4184\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.2 - 24 Sept 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1\"\u003e2.27.1\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4160\"\u003e#4160\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.1 - 18 Sept 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eThe CodeQL Action now has experimental support for CodeQL releases\nfor which per-language bundles are available. Per-language bundles\nsupport analysis for a single language and are therefore smaller than\nthe combined bundles that allow analysis for all supported languages. As\na result, per-language bundles take up less space on disk and are faster\nto download. We expect to roll this change out to everyone in the coming\nweeks. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4146\"\u003e#4146\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.0 - 09 Sept 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOn GitHub-hosted runners, the CodeQL Action now deletes unused\nCodeQL bundles from the toolcache before downloading a different bundle,\nwhich frees up disk space for the analysis. We expect to roll this\nchange out to everyone in September. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4124\"\u003e#4124\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eThe CodeQL Action now supports CodeQL releases that are compatible\nwith Linux Arm64 and downloads the native \u003ccode\u003elinux-arm64\u003c/code\u003e\nCodeQL bundle when available. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4072\"\u003e#4072\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0\"\u003e2.27.0\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4129\"\u003e#4129\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.9 - 26 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4\"\u003e2.26.4\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4106\"\u003e#4106\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.8 - 21 Aug 2026\u003c/h2\u003e\n\u003cp\u003eNo user facing changes.\u003c/p\u003e\n\u003ch2\u003e4.37.7 - 13 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3\"\u003e2.26.3\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4085\"\u003e#4085\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.6 - 04 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChanged the default filepath for the new remote file address format\nthat was introduced in CodeQL Action 4.37.0 / 3.37.0 to\n\u003ccode\u003e.github/codeql-config.yml\u003c/code\u003e to align it with the suggested\npath that is used elsewhere. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4070\"\u003e#4070\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.5 - 03 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFixed a bug where a network error while streaming the download of\nthe CodeQL bundle could terminate the \u003ccode\u003einit\u003c/code\u003e Action instead\nof falling back to downloading the bundle before extracting it. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4061\"\u003e#4061\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.4 - 29 Jul 2026\u003c/h2\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/24c54180a607b1449ed407dd24f251e4e9147c8d\"\u003e\u003ccode\u003e24c5418\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4214\"\u003e#4214\u003c/a\u003e\nfrom github/update-v4.38.3-e0b52dbdc\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/69e87c56c1db5253592f61da177da1d20d033bd8\"\u003e\u003ccode\u003e69e87c5\u003c/code\u003e\u003c/a\u003e\nAdd changelog note for \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4184\"\u003e#4184\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/23b682830be5e93afb6466bfc0197142d70268aa\"\u003e\u003ccode\u003e23b6828\u003c/code\u003e\u003c/a\u003e\nUpdate changelog for v4.38.3\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/e0b52dbdc5c3376dd8cb78e956fd23fa07ca2c5b\"\u003e\u003ccode\u003ee0b52db\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4210\"\u003e#4210\u003c/a\u003e\nfrom github/henrymercer/pin-python-for-older-clis-in-ci\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/6b99698c8cda6115e2bc7c52226b508dc558d7dc\"\u003e\u003ccode\u003e6b99698\u003c/code\u003e\u003c/a\u003e\nPin Python 3.13.15 for older CLI versions in multi-language check\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/63d3d632fc7cbd91c8089c7fea5322f1bc73d7d8\"\u003e\u003ccode\u003e63d3d63\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4203\"\u003e#4203\u003c/a\u003e\nfrom github/update-bundle/codeql-bundle-v2.27.2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/7377a10091aa5d781c1d36dc3834817d8ad0acfe\"\u003e\u003ccode\u003e7377a10\u003c/code\u003e\u003c/a\u003e\nAdd changelog note\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/c1a30cda114f23a88a09ab61f4ec08c312d2c524\"\u003e\u003ccode\u003ec1a30cd\u003c/code\u003e\u003c/a\u003e\nUpdate default bundle to codeql-bundle-v2.27.2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/d208ec71e39ae46397cbf6569bef8439b9aab974\"\u003e\u003ccode\u003ed208ec7\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4200\"\u003e#4200\u003c/a\u003e\nfrom github/mbg/esm/migrate-pr-checks\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/a71b0c6684dea6ca627a472a11bf5b80bd47c845\"\u003e\u003ccode\u003ea71b0c6\u003c/code\u003e\u003c/a\u003e\nReplace \u003ccode\u003e__dirname\u003c/code\u003e in \u003ccode\u003esync.ts\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/github/codeql-action/compare/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...24c54180a607b1449ed407dd24f251e4e9147c8d\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `github/codeql-action/analyze` from 4.38.2 to 4.38.3\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases\"\u003egithub/codeql-action/analyze\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev4.38.3\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eUpcoming breaking change\u003c/em\u003e: CodeQL version 2.21.2 and earlier\nwere discontinued on 24 September 2026 alongside GitHub Enterprise\nServer 3.17, and will be unsupported by the next minor release of the\nCodeQL Action. Added a deprecation warning for customers using these\nversions of CodeQL. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4188\"\u003e#4188\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2\"\u003e2.27.2\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4203\"\u003e#4203\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFixed a bug where the decision of whether to use a per-language\nbundle did not account for custom configurations that reference queries\noutside of compiled CodeQL packs. This issue was caught during internal\ntesting and did not affect any customer repositories. We will resume the\nroll out of per-language bundles in the coming weeks. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4184\"\u003e#4184\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/github/codeql-action/blob/main/CHANGELOG.md\"\u003egithub/codeql-action/analyze\u0027s\nchangelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eCodeQL Action Changelog\u003c/h1\u003e\n\u003cp\u003eSee the \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases\"\u003ereleases\npage\u003c/a\u003e for the relevant changes to the CodeQL CLI and language\npacks.\u003c/p\u003e\n\u003ch2\u003e[UNRELEASED]\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eBreaking change\u003c/em\u003e: Bump the minimum required CodeQL bundle\nversion to 2.20.7. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4205\"\u003e#4205\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.3 - 08 Oct 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eUpcoming breaking change\u003c/em\u003e: CodeQL version 2.21.2 and earlier\nwere discontinued on 24 September 2026 alongside GitHub Enterprise\nServer 3.17, and will be unsupported by the next minor release of the\nCodeQL Action. Added a deprecation warning for customers using these\nversions of CodeQL. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4188\"\u003e#4188\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2\"\u003e2.27.2\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4203\"\u003e#4203\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFixed a bug where the decision of whether to use a per-language\nbundle did not account for custom configurations that reference queries\noutside of compiled CodeQL packs. This issue was caught during internal\ntesting and did not affect any customer repositories. We will resume the\nroll out of per-language bundles in the coming weeks. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4184\"\u003e#4184\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.2 - 24 Sept 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1\"\u003e2.27.1\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4160\"\u003e#4160\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.1 - 18 Sept 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eThe CodeQL Action now has experimental support for CodeQL releases\nfor which per-language bundles are available. Per-language bundles\nsupport analysis for a single language and are therefore smaller than\nthe combined bundles that allow analysis for all supported languages. As\na result, per-language bundles take up less space on disk and are faster\nto download. We expect to roll this change out to everyone in the coming\nweeks. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4146\"\u003e#4146\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.38.0 - 09 Sept 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOn GitHub-hosted runners, the CodeQL Action now deletes unused\nCodeQL bundles from the toolcache before downloading a different bundle,\nwhich frees up disk space for the analysis. We expect to roll this\nchange out to everyone in September. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4124\"\u003e#4124\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eThe CodeQL Action now supports CodeQL releases that are compatible\nwith Linux Arm64 and downloads the native \u003ccode\u003elinux-arm64\u003c/code\u003e\nCodeQL bundle when available. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4072\"\u003e#4072\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0\"\u003e2.27.0\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4129\"\u003e#4129\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.9 - 26 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4\"\u003e2.26.4\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4106\"\u003e#4106\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.8 - 21 Aug 2026\u003c/h2\u003e\n\u003cp\u003eNo user facing changes.\u003c/p\u003e\n\u003ch2\u003e4.37.7 - 13 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate default CodeQL bundle version to \u003ca\nhref\u003d\"https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3\"\u003e2.26.3\u003c/a\u003e.\n\u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4085\"\u003e#4085\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.6 - 04 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChanged the default filepath for the new remote file address format\nthat was introduced in CodeQL Action 4.37.0 / 3.37.0 to\n\u003ccode\u003e.github/codeql-config.yml\u003c/code\u003e to align it with the suggested\npath that is used elsewhere. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4070\"\u003e#4070\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.5 - 03 Aug 2026\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFixed a bug where a network error while streaming the download of\nthe CodeQL bundle could terminate the \u003ccode\u003einit\u003c/code\u003e Action instead\nof falling back to downloading the bundle before extracting it. \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/pull/4061\"\u003e#4061\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e4.37.4 - 29 Jul 2026\u003c/h2\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/24c54180a607b1449ed407dd24f251e4e9147c8d\"\u003e\u003ccode\u003e24c5418\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4214\"\u003e#4214\u003c/a\u003e\nfrom github/update-v4.38.3-e0b52dbdc\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/69e87c56c1db5253592f61da177da1d20d033bd8\"\u003e\u003ccode\u003e69e87c5\u003c/code\u003e\u003c/a\u003e\nAdd changelog note for \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4184\"\u003e#4184\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/23b682830be5e93afb6466bfc0197142d70268aa\"\u003e\u003ccode\u003e23b6828\u003c/code\u003e\u003c/a\u003e\nUpdate changelog for v4.38.3\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/e0b52dbdc5c3376dd8cb78e956fd23fa07ca2c5b\"\u003e\u003ccode\u003ee0b52db\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4210\"\u003e#4210\u003c/a\u003e\nfrom github/henrymercer/pin-python-for-older-clis-in-ci\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/6b99698c8cda6115e2bc7c52226b508dc558d7dc\"\u003e\u003ccode\u003e6b99698\u003c/code\u003e\u003c/a\u003e\nPin Python 3.13.15 for older CLI versions in multi-language check\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/63d3d632fc7cbd91c8089c7fea5322f1bc73d7d8\"\u003e\u003ccode\u003e63d3d63\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4203\"\u003e#4203\u003c/a\u003e\nfrom github/update-bundle/codeql-bundle-v2.27.2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/7377a10091aa5d781c1d36dc3834817d8ad0acfe\"\u003e\u003ccode\u003e7377a10\u003c/code\u003e\u003c/a\u003e\nAdd changelog note\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/c1a30cda114f23a88a09ab61f4ec08c312d2c524\"\u003e\u003ccode\u003ec1a30cd\u003c/code\u003e\u003c/a\u003e\nUpdate default bundle to codeql-bundle-v2.27.2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/d208ec71e39ae46397cbf6569bef8439b9aab974\"\u003e\u003ccode\u003ed208ec7\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/github/codeql-action/issues/4200\"\u003e#4200\u003c/a\u003e\nfrom github/mbg/esm/migrate-pr-checks\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/github/codeql-action/commit/a71b0c6684dea6ca627a472a11bf5b80bd47c845\"\u003e\u003ccode\u003ea71b0c6\u003c/code\u003e\u003c/a\u003e\nReplace \u003ccode\u003e__dirname\u003c/code\u003e in \u003ccode\u003esync.ts\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/github/codeql-action/compare/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...24c54180a607b1449ed407dd24f251e4e9147c8d\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore \u003cdependency name\u003e major version` will close this\ngroup update PR and stop Dependabot creating any more for the specific\ndependency\u0027s major version (unless you unignore this specific\ndependency\u0027s major version or upgrade to it yourself)\n- `@dependabot ignore \u003cdependency name\u003e minor version` will close this\ngroup update PR and stop Dependabot creating any more for the specific\ndependency\u0027s minor version (unless you unignore this specific\ndependency\u0027s minor version or upgrade to it yourself)\n- `@dependabot ignore \u003cdependency name\u003e` will close this group update PR\nand stop Dependabot creating any more for the specific dependency\n(unless you unignore this specific dependency or upgrade to it yourself)\n- `@dependabot unignore \u003cdependency name\u003e` will remove all of the ignore\nconditions of the specified dependency\n- `@dependabot unignore \u003cdependency name\u003e \u003cignore condition\u003e` will\nremove the ignore condition of the specified dependency and ignore\nconditions\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "6bf43f298b02c92855573b9f21780a20dfbfc2ea",
      "tree": "711b8b02807b998f912d22d0bdb79f793a8d4667",
      "parents": [
        "bfd9d9efa9e8499038258e6b0f72be0068c922d9"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:47:55 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:47:55 2026 +0000"
      },
      "message": "chore(deps): bump taiki-e/install-action from 2.87.23 to 2.87.27 (#26322)\n\nBumps\n[taiki-e/install-action](https://github.com/taiki-e/install-action) from\n2.87.23 to 2.87.27.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/releases\"\u003etaiki-e/install-action\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e2.87.27\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003evacuum@latest\u003c/code\u003e to 0.32.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003euv@latest\u003c/code\u003e to 0.12.24.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003etypos@latest\u003c/code\u003e to 1.51.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003etombi@latest\u003c/code\u003e to 1.7.3.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003esyft@latest\u003c/code\u003e to 1.54.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003erelease-plz@latest\u003c/code\u003e to 0.3.170.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003emise@latest\u003c/code\u003e to 2026.10.4.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ekingfisher@latest\u003c/code\u003e to 2.11.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ehyperfine@latest\u003c/code\u003e to 2.0.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003edprint@latest\u003c/code\u003e to 0.61.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ecargo-nextest@latest\u003c/code\u003e to 0.9.148.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ecargo-neat@latest\u003c/code\u003e to 0.6.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ecargo-binstall@latest\u003c/code\u003e to 1.25.2.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e2.87.26\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003etombi@latest\u003c/code\u003e to 1.7.2.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003eprek@latest\u003c/code\u003e to 0.5.5.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003emise@latest\u003c/code\u003e to 2026.10.3.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ekache@latest\u003c/code\u003e to 1.0.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ehyperfine@latest\u003c/code\u003e to 1.21.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e2.87.25\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003euv@latest\u003c/code\u003e to 0.12.23.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003emise@latest\u003c/code\u003e to 2026.10.2.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ekingfisher@latest\u003c/code\u003e to 2.10.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003edprint@latest\u003c/code\u003e to 0.60.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ecargo-semver-checks@latest\u003c/code\u003e to 0.51.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ecargo-binstall@latest\u003c/code\u003e to 1.25.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md\"\u003etaiki-e/install-action\u0027s\nchangelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eChangelog\u003c/h1\u003e\n\u003cp\u003eAll notable changes to this project will be documented in this\nfile.\u003c/p\u003e\n\u003cp\u003eThis project adheres to \u003ca href\u003d\"https://semver.org\"\u003eSemantic\nVersioning\u003c/a\u003e.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003ch2\u003e[Unreleased]\u003c/h2\u003e\n\u003ch2\u003e[2.87.28] - 2026-10-12\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003edprint@latest\u003c/code\u003e to 0.62.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003evacuum@latest\u003c/code\u003e to 0.33.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003euv@latest\u003c/code\u003e to 0.13.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003etombi@latest\u003c/code\u003e to 1.8.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003erelease-plz@latest\u003c/code\u003e to 0.3.171.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003erclone@latest\u003c/code\u003e to 1.75.2.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003emise@latest\u003c/code\u003e to 2026.10.7.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ecargo-binstall@latest\u003c/code\u003e to 1.25.3.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[2.87.27] - 2026-10-09\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003evacuum@latest\u003c/code\u003e to 0.32.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003euv@latest\u003c/code\u003e to 0.12.24.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003etypos@latest\u003c/code\u003e to 1.51.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003etombi@latest\u003c/code\u003e to 1.7.3.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003esyft@latest\u003c/code\u003e to 1.54.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003erelease-plz@latest\u003c/code\u003e to 0.3.170.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003emise@latest\u003c/code\u003e to 2026.10.4.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ekingfisher@latest\u003c/code\u003e to 2.11.1.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate \u003ccode\u003ehyperfine@latest\u003c/code\u003e to 2.0.0.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/ab6895351a88b908e96a4697860d4ffea5e57dbe\"\u003e\u003ccode\u003eab68953\u003c/code\u003e\u003c/a\u003e\nRelease 2.87.27\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/62530fde5eae2d21742c80f8d06d4ddc2e1fc849\"\u003e\u003ccode\u003e62530fd\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003evacuum@latest\u003c/code\u003e to 0.32.0\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/f684ea4ef45b30adbd27018b3a8c8eff832d693e\"\u003e\u003ccode\u003ef684ea4\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003euv@latest\u003c/code\u003e to 0.12.24\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/8aa87a079f6df0fefe32ea81cbf89957adfc4fb2\"\u003e\u003ccode\u003e8aa87a0\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003etypos@latest\u003c/code\u003e to 1.51.1\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/5ffcf4325f316f6461163dbceae21814184cc867\"\u003e\u003ccode\u003e5ffcf43\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003etombi@latest\u003c/code\u003e to 1.7.3\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/99266369a536fa5485f3e5b59913a332a0af45ff\"\u003e\u003ccode\u003e9926636\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003esyft@latest\u003c/code\u003e to 1.54.1\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/4647f42698f08ac3c2a60181bceea72db3556908\"\u003e\u003ccode\u003e4647f42\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003erelease-plz@latest\u003c/code\u003e to 0.3.170\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/df0256079f1b5aae055d9e9826e16e43e37734d1\"\u003e\u003ccode\u003edf02560\u003c/code\u003e\u003c/a\u003e\nUpdate rclone manifest\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/d7c82f4c669484f523dfcd90e184702c32babdb1\"\u003e\u003ccode\u003ed7c82f4\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003emise@latest\u003c/code\u003e to 2026.10.4\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/commit/a6142d0c42332af2f8b733abb6a554272b9f5880\"\u003e\u003ccode\u003ea6142d0\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003ekingfisher@latest\u003c/code\u003e to 2.11.1\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/taiki-e/install-action/compare/861a07ce7084f55488e375df125cdc99bba60eb7...ab6895351a88b908e96a4697860d4ffea5e57dbe\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dtaiki-e/install-action\u0026package-manager\u003dgithub_actions\u0026previous-version\u003d2.87.23\u0026new-version\u003d2.87.27)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "bfd9d9efa9e8499038258e6b0f72be0068c922d9",
      "tree": "38e0bb7f5c8aa09209ad03b0a0baf01e9d6c165b",
      "parents": [
        "f0ee13efde6c434461c5b7ff177a2a0c47b68cf7"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:43:00 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:43:00 2026 +0000"
      },
      "message": "chore(deps): bump actions/setup-node from 7.0.0 to 7.1.0 (#26326)\n\nBumps [actions/setup-node](https://github.com/actions/setup-node) from\n7.0.0 to 7.1.0.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/actions/setup-node/releases\"\u003eactions/setup-node\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev7.1.0\u003c/h2\u003e\n\u003ch2\u003eWhat\u0027s Changed\u003c/h2\u003e\n\u003ch3\u003eEnhancements:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdd support for mise.toml file by \u003ca\nhref\u003d\"https://github.com/gperdomor\"\u003e\u003ccode\u003e@​gperdomor\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1421\"\u003eactions/setup-node#1421\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eSupport absolute paths in node-version-file by \u003ca\nhref\u003d\"https://github.com/v-mahabaleshwars\"\u003e\u003ccode\u003e@​v-mahabaleshwars\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1633\"\u003eactions/setup-node#1633\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdd Node version validation and manifest fetch retry by \u003ca\nhref\u003d\"https://github.com/v-jitenderpalsingh\"\u003e\u003ccode\u003e@​v-jitenderpalsingh\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1580\"\u003eactions/setup-node#1580\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eDocumentation updates:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eREADME.md: bump actions/checkout to latest version 7 by \u003ca\nhref\u003d\"https://github.com/deining\"\u003e\u003ccode\u003e@​deining\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1578\"\u003eactions/setup-node#1578\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003edocs: add V7 ESM migration and NODE_AUTH_TOKEN behavior change by \u003ca\nhref\u003d\"https://github.com/v-gowridurgad\"\u003e\u003ccode\u003e@​v-gowridurgad\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1593\"\u003eactions/setup-node#1593\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eFixed cache recommendation syntax by \u003ca\nhref\u003d\"https://github.com/SubJunk\"\u003e\u003ccode\u003e@​SubJunk\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1603\"\u003eactions/setup-node#1603\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eDependency updates:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate workflow pins and migrate Node matrices to modern versions by\n\u003ca\nhref\u003d\"https://github.com/v-HarithaVattikuti\"\u003e\u003ccode\u003e@​v-HarithaVattikuti\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1583\"\u003eactions/setup-node#1583\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade \u003ccode\u003e@​actions/cache\u003c/code\u003e to 6.2.0 by \u003ca\nhref\u003d\"https://github.com/philip-gai\"\u003e\u003ccode\u003e@​philip-gai\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1584\"\u003eactions/setup-node#1584\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePin \u003ccode\u003e@​types/node\u003c/code\u003e to v24 by \u003ca\nhref\u003d\"https://github.com/v-priyagupta108\"\u003e\u003ccode\u003e@​v-priyagupta108\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1585\"\u003eactions/setup-node#1585\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eOverride brace-expansion to 5.0.8 by \u003ca\nhref\u003d\"https://github.com/v-priyagupta108\"\u003e\u003ccode\u003e@​v-priyagupta108\u003c/code\u003e\u003c/a\u003e\nwith \u003ca href\u003d\"https://github.com/Copilot\"\u003e\u003ccode\u003e@​Copilot\u003c/code\u003e\u003c/a\u003e in\n\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1599\"\u003eactions/setup-node#1599\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade actions/checkout from 7.0.0 to 7.0.1 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1598\"\u003eactions/setup-node#1598\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade prettier from 3.8.4 to 3.9.6 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1590\"\u003eactions/setup-node#1590\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade \u003ccode\u003e@​vercel/ncc\u003c/code\u003e from 0.44.0 to 0.45.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1610\"\u003eactions/setup-node#1610\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade pnpm/action-setup from 6.0.9 to 6.0.10 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1602\"\u003eactions/setup-node#1602\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade baseline-browser-mapping from 2.10.38 to 2.11.22 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1629\"\u003eactions/setup-node#1629\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade \u003ccode\u003e@​types/semver\u003c/code\u003e from 7.7.1 to 7.8.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1616\"\u003eactions/setup-node#1616\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade \u003ccode\u003e@​typescript-eslint/parser\u003c/code\u003e from 8.62.0 to\n8.70.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1615\"\u003eactions/setup-node#1615\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade pnpm/action-setup from 6.0.10 to 6.1.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1631\"\u003eactions/setup-node#1631\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade jest-each from 30.4.1 to 30.5.2 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1636\"\u003eactions/setup-node#1636\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade eslint-plugin-n from 18.1.0 to 18.3.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1638\"\u003eactions/setup-node#1638\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpdate dependencies and add license files by \u003ca\nhref\u003d\"https://github.com/v-HarithaVattikuti\"\u003e\u003ccode\u003e@​v-HarithaVattikuti\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1642\"\u003eactions/setup-node#1642\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUpgrade eslint from 10.5.0 to 10.11.0 and package.json from 7.0.0 to\n7.1.0 by \u003ca\nhref\u003d\"https://github.com/dependabot\"\u003e\u003ccode\u003e@​dependabot\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1635\"\u003eactions/setup-node#1635\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eNew Contributors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/v-jitenderpalsingh\"\u003e\u003ccode\u003e@​v-jitenderpalsingh\u003c/code\u003e\u003c/a\u003e\nmade their first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1580\"\u003eactions/setup-node#1580\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/philip-gai\"\u003e\u003ccode\u003e@​philip-gai\u003c/code\u003e\u003c/a\u003e made\ntheir first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1584\"\u003eactions/setup-node#1584\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href\u003d\"https://github.com/gperdomor\"\u003e\u003ccode\u003e@​gperdomor\u003c/code\u003e\u003c/a\u003e\nmade their first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1421\"\u003eactions/setup-node#1421\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href\u003d\"https://github.com/SubJunk\"\u003e\u003ccode\u003e@​SubJunk\u003c/code\u003e\u003c/a\u003e made\ntheir first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/pull/1603\"\u003eactions/setup-node#1603\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eFull Changelog\u003c/strong\u003e: \u003ca\nhref\u003d\"https://github.com/actions/setup-node/compare/v7.0.0...v7.1.0\"\u003ehttps://github.com/actions/setup-node/compare/v7.0.0...v7.1.0\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/949feb2413d6458794dcd2491c4babbbce0c15c1\"\u003e\u003ccode\u003e949feb2\u003c/code\u003e\u003c/a\u003e\nBump eslint from 10.5.0 to 10.11.0 and package.json from 7.0.0 to 7.1.0\n(\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1635\"\u003e#1635\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/7207c4f1189c7ee83ddf20c7c68bd1af6fdd751c\"\u003e\u003ccode\u003e7207c4f\u003c/code\u003e\u003c/a\u003e\nchore: update dependencies and add license files (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1642\"\u003e#1642\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/54337e0d02de9202d0948aaff36ad556375497b9\"\u003e\u003ccode\u003e54337e0\u003c/code\u003e\u003c/a\u003e\nBump eslint-plugin-n from 18.1.0 to 18.3.0 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1638\"\u003e#1638\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/fb54fa8c14c63410cc752f0ae3b7b3ca6af161fc\"\u003e\u003ccode\u003efb54fa8\u003c/code\u003e\u003c/a\u003e\nBump jest-each from 30.4.1 to 30.5.2 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1636\"\u003e#1636\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/7f84f1d52d0c56afb45c62fee31a93b843cea4d6\"\u003e\u003ccode\u003e7f84f1d\u003c/code\u003e\u003c/a\u003e\nBump pnpm/action-setup from 6.0.10 to 6.1.0 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1631\"\u003e#1631\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/0c54c7b07420dcba69a7d832587f55ebdf771c9e\"\u003e\u003ccode\u003e0c54c7b\u003c/code\u003e\u003c/a\u003e\nBump \u003ccode\u003e@​typescript-eslint/parser\u003c/code\u003e from 8.62.0 to 8.70.0 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1615\"\u003e#1615\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/a8294190049a9c296f01b9a432aff41dd83d8284\"\u003e\u003ccode\u003ea829419\u003c/code\u003e\u003c/a\u003e\nBump \u003ccode\u003e@​types/semver\u003c/code\u003e from 7.7.1 to 7.8.0 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1616\"\u003e#1616\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/680d1e489b82f1243de15bc7665c0007e3c9a860\"\u003e\u003ccode\u003e680d1e4\u003c/code\u003e\u003c/a\u003e\nSupport absolute paths in node-version-file (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1633\"\u003e#1633\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/db0fb3a98ed314b69026b6e8c9be26a7e2fe65a8\"\u003e\u003ccode\u003edb0fb3a\u003c/code\u003e\u003c/a\u003e\nBump baseline-browser-mapping from 2.10.38 to 2.11.22 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1629\"\u003e#1629\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/setup-node/commit/94196ee1d15439c1b6651cd87ef14e88ec435966\"\u003e\u003ccode\u003e94196ee\u003c/code\u003e\u003c/a\u003e\nBump pnpm/action-setup from 6.0.9 to 6.0.10 (\u003ca\nhref\u003d\"https://redirect.github.com/actions/setup-node/issues/1602\"\u003e#1602\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dactions/setup-node\u0026package-manager\u003dgithub_actions\u0026previous-version\u003d7.0.0\u0026new-version\u003d7.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "f0ee13efde6c434461c5b7ff177a2a0c47b68cf7",
      "tree": "a724623334a407aa367d95c8180cf1282ee20279",
      "parents": [
        "18348dbac3564e11b0f2f87aa3656e3df37d9cd3"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:40:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:40:22 2026 +0000"
      },
      "message": "chore(deps): bump astral-sh/setup-uv from 10.2.0 to 10.3.0 (#26323)\n\nBumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from\n10.2.0 to 10.3.0.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/releases\"\u003eastral-sh/setup-uv\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev10.3.0 🌈 Add Python architecture selection\u003c/h2\u003e\n\u003ch2\u003eChanges\u003c/h2\u003e\n\u003cp\u003eThis release adds the \u003ccode\u003epython-arch\u003c/code\u003e input to select a\nPython architecture independently of the Python version. With\n\u003ccode\u003euv\u003c/code\u003e 0.13.0 or later, set \u003ccode\u003epython-arch: x86_64\u003c/code\u003e to\nuse x64 Python on Windows ARM64 runners.\u003c/p\u003e\n\u003cp\u003eIt also includes embedded checksums for \u003ccode\u003euv\u003c/code\u003e releases\nthrough 0.13.0.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUse macOS 15 runners for tests \u003ca\nhref\u003d\"https://github.com/charliermarsh\"\u003e\u003ccode\u003e@​charliermarsh\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1081\"\u003e#1081\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e🚀 Enhancements\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAdd \u003ccode\u003epython-arch\u003c/code\u003e support \u003ca\nhref\u003d\"https://github.com/zanieb\"\u003e\u003ccode\u003e@​zanieb\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1079\"\u003e#1079\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e🧰 Maintenance\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003echore: update known checksums for 0.13.0 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1089\"\u003e#1089\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.24 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1084\"\u003e#1084\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.23 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1082\"\u003e#1082\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.22 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1080\"\u003e#1080\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.21 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1078\"\u003e#1078\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.20 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1076\"\u003e#1076\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.19 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1068\"\u003e#1068\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003echore: update known checksums for 0.12.18 @\u003ca\nhref\u003d\"https://github.com/apps/github-actions\"\u003egithub-actions[bot]\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1065\"\u003e#1065\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e⬆️ Dependency updates\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003echore(deps): bump zizmorcore/zizmor-action from 0.6.2 to 0.6.3 @\u003ca\nhref\u003d\"https://github.com/apps/dependabot\"\u003edependabot[bot]\u003c/a\u003e (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1077\"\u003e#1077\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/1c37ad07a6a961277cf70c0d37d6f313000f5884\"\u003e\u003ccode\u003e1c37ad0\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.13.0 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1089\"\u003e#1089\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/b3c9b5fc56ebc90760c43b1ac9552c0d1705d3ca\"\u003e\u003ccode\u003eb3c9b5f\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.12.24 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1084\"\u003e#1084\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/b06acff4b6a41bdd9cdac56507ead0bd7734e757\"\u003e\u003ccode\u003eb06acff\u003c/code\u003e\u003c/a\u003e\nAdd \u003ccode\u003epython-arch\u003c/code\u003e support (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1079\"\u003e#1079\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/c84232ca4fde9b022e20a930bfbbecd386b56fdf\"\u003e\u003ccode\u003ec84232c\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.12.23 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1082\"\u003e#1082\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/51fdd265d38a27ffcbca0da885510bc6fcc0ff55\"\u003e\u003ccode\u003e51fdd26\u003c/code\u003e\u003c/a\u003e\nUse macOS 15 runners for tests (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1081\"\u003e#1081\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/a96208bed1fb5efb8da349c9bcc6cc58af9e7d74\"\u003e\u003ccode\u003ea96208b\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.12.22 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1080\"\u003e#1080\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/0e3884b860e20d3f4d5daa2347130beb51ccde47\"\u003e\u003ccode\u003e0e3884b\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.12.21 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1078\"\u003e#1078\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/bcf05803b55ef01a5ec6368521ee1b42f97bc438\"\u003e\u003ccode\u003ebcf0580\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.12.20 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1076\"\u003e#1076\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/b92a892142bde7280cd163c2abff341413314f9f\"\u003e\u003ccode\u003eb92a892\u003c/code\u003e\u003c/a\u003e\nchore(deps): bump zizmorcore/zizmor-action from 0.6.2 to 0.6.3 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1077\"\u003e#1077\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/commit/227a0f6bea25cde3444f52decccf4a18de6635f4\"\u003e\u003ccode\u003e227a0f6\u003c/code\u003e\u003c/a\u003e\nchore: update known checksums for 0.12.19 (\u003ca\nhref\u003d\"https://redirect.github.com/astral-sh/setup-uv/issues/1068\"\u003e#1068\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/astral-sh/setup-uv/compare/c18668ad3cf93ea998bef934396af7bb5c839dc7...1c37ad07a6a961277cf70c0d37d6f313000f5884\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dastral-sh/setup-uv\u0026package-manager\u003dgithub_actions\u0026previous-version\u003d10.2.0\u0026new-version\u003d10.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "18348dbac3564e11b0f2f87aa3656e3df37d9cd3",
      "tree": "d0c5ce8037c365e6013de87ba91c77e1906fb2f3",
      "parents": [
        "00a2f60b14a892d3a5f356b185499d5835c28052"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:39:35 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:39:35 2026 +0000"
      },
      "message": "chore(deps): bump actions/download-artifact from 8.0.1 to 8.0.2 (#26325)\n\nBumps\n[actions/download-artifact](https://github.com/actions/download-artifact)\nfrom 8.0.1 to 8.0.2.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/actions/download-artifact/releases\"\u003eactions/download-artifact\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev8.0.2\u003c/h2\u003e\n\u003ch2\u003eWhat\u0027s Changed\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate the readme by \u003ca\nhref\u003d\"https://github.com/danwkennedy\"\u003e\u003ccode\u003e@​danwkennedy\u003c/code\u003e\u003c/a\u003e in\n\u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/pull/473\"\u003eactions/download-artifact#473\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eImproves artifact download retries when the service returns HTTP 429\n(rate limiting), including honoring valid Retry-After headers.\u003c/li\u003e\n\u003cli\u003eUpdate \u003ccode\u003e@​actions/artifact\u003c/code\u003e to 6.3.1 by \u003ca\nhref\u003d\"https://github.com/tunc-d\"\u003e\u003ccode\u003e@​tunc-d\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/pull/492\"\u003eactions/download-artifact#492\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePrepare download-artifact v8.0.2 by \u003ca\nhref\u003d\"https://github.com/tunc-d\"\u003e\u003ccode\u003e@​tunc-d\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/pull/493\"\u003eactions/download-artifact#493\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eNew Contributors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href\u003d\"https://github.com/tunc-d\"\u003e\u003ccode\u003e@​tunc-d\u003c/code\u003e\u003c/a\u003e made\ntheir first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/pull/492\"\u003eactions/download-artifact#492\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eFull Changelog\u003c/strong\u003e: \u003ca\nhref\u003d\"https://github.com/actions/download-artifact/compare/v8.0.1...v8.0.2\"\u003ehttps://github.com/actions/download-artifact/compare/v8.0.1...v8.0.2\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/download-artifact/commit/9000827ccba6bdab643e8b6fd33ac0654aef8333\"\u003e\u003ccode\u003e9000827\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/issues/493\"\u003e#493\u003c/a\u003e\nfrom actions/tunc-d-prepare-download-v8-0-2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/download-artifact/commit/e455989ae00f5bdd4054f05d3e972c6bf8a62dc5\"\u003e\u003ccode\u003ee455989\u003c/code\u003e\u003c/a\u003e\nPrepare download-artifact v8.0.2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/download-artifact/commit/a00b90c4a2f01d73a8c89552caabca6ea3b43137\"\u003e\u003ccode\u003ea00b90c\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/issues/492\"\u003e#492\u003c/a\u003e\nfrom actions/tunc-d-download-artifact-package-bump\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/download-artifact/commit/29bb7ce6af5345aeab5bb4774ce7249ee3ccc27f\"\u003e\u003ccode\u003e29bb7ce\u003c/code\u003e\u003c/a\u003e\nUpdate \u003ccode\u003e@​actions/artifact\u003c/code\u003e to 6.3.1\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/download-artifact/commit/484a0b528fb4d7bd804637ccb632e47a0e638317\"\u003e\u003ccode\u003e484a0b5\u003c/code\u003e\u003c/a\u003e\nUpdate the readme (\u003ca\nhref\u003d\"https://redirect.github.com/actions/download-artifact/issues/473\"\u003e#473\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSee full diff in \u003ca\nhref\u003d\"https://github.com/actions/download-artifact/compare/3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c...9000827ccba6bdab643e8b6fd33ac0654aef8333\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dactions/download-artifact\u0026package-manager\u003dgithub_actions\u0026previous-version\u003d8.0.1\u0026new-version\u003d8.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "00a2f60b14a892d3a5f356b185499d5835c28052",
      "tree": "fea31c68d4f3484e0b58571c09c366405df0dbce",
      "parents": [
        "cf4869cd834dfa2756a257cbd5b66f8a5f2ec7a6"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Thu Oct 15 12:39:18 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 12:39:18 2026 +0000"
      },
      "message": "chore(deps): bump actions/upload-artifact from 7.0.1 to 7.0.2 (#26324)\n\nBumps\n[actions/upload-artifact](https://github.com/actions/upload-artifact)\nfrom 7.0.1 to 7.0.2.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/releases\"\u003eactions/upload-artifact\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev7.0.2\u003c/h2\u003e\n\u003ch2\u003eWhat\u0027s Changed\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eImproves artifact download retries when the service returns HTTP 429\n(rate limiting), including honoring valid Retry-After headers.\u003c/li\u003e\n\u003cli\u003eUpdates \u003ccode\u003e@​actions/artifact\u003c/code\u003e to v6.3.1.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eNew Contributors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href\u003d\"https://github.com/tunc-d\"\u003e\u003ccode\u003e@​tunc-d\u003c/code\u003e\u003c/a\u003e made\ntheir first contribution in \u003ca\nhref\u003d\"https://redirect.github.com/actions/upload-artifact/pull/821\"\u003eactions/upload-artifact#821\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eFull Changelog\u003c/strong\u003e: \u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/compare/v7.0.1...v7.0.2\"\u003ehttps://github.com/actions/upload-artifact/compare/v7.0.1...v7.0.2\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/commit/cf430e030ddbb5b0abf93d22962f4752f3646cd9\"\u003e\u003ccode\u003ecf430e0\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/actions/upload-artifact/issues/822\"\u003e#822\u003c/a\u003e\nfrom actions/tunc-d-prepare-upload-v7-0-2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/commit/c2acdedd35a8824a1552c7137f8c18288c3ea469\"\u003e\u003ccode\u003ec2acded\u003c/code\u003e\u003c/a\u003e\nchore: prepare v7.0.2 release\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/commit/4687c1bbaa0a58abb517d90b4bbade6754c80c1a\"\u003e\u003ccode\u003e4687c1b\u003c/code\u003e\u003c/a\u003e\nMerge pull request \u003ca\nhref\u003d\"https://redirect.github.com/actions/upload-artifact/issues/821\"\u003e#821\u003c/a\u003e\nfrom actions/tunc-d-upload-artifact-package-bump\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/commit/8cbe1bebdb858105d8fdd88f81404d4de4595719\"\u003e\u003ccode\u003e8cbe1be\u003c/code\u003e\u003c/a\u003e\nBump \u003ccode\u003e@​actions/artifact\u003c/code\u003e to 6.3.1\u003c/li\u003e\n\u003cli\u003eSee full diff in \u003ca\nhref\u003d\"https://github.com/actions/upload-artifact/compare/043fb46d1a93c77aae656e7c1c64a875d1fc6a0a...cf430e030ddbb5b0abf93d22962f4752f3646cd9\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dactions/upload-artifact\u0026package-manager\u003dgithub_actions\u0026previous-version\u003d7.0.1\u0026new-version\u003d7.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "cf4869cd834dfa2756a257cbd5b66f8a5f2ec7a6",
      "tree": "cae77ee5d02ca7264b9f757ca4f817bb42789861",
      "parents": [
        "20a46295a4a89037443595ba6e65098dd34c606f"
      ],
      "author": {
        "name": "siddu",
        "email": "siddusbakka@gmail.com",
        "time": "Thu Oct 15 10:37:51 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 10:37:51 2026 +0000"
      },
      "message": "fix: skip HashJoinExec nodes carrying dynamic filters in JoinSelection (#26123)\n\n## Which issue does this PR close?\n\n- Closes #26106.\n\n## Rationale for this change\n\n`JoinSelection` is not safe to run on plans that already carry dynamic\nfilters. This happens during re-optimization passes (e.g. downstream\npipelines that wrap an already-optimized plan into a writer sink and\nre-run physical optimization).\n\nOnce `FilterPushdown` has wired up a dynamic filter between the build\nside and probe side of a `HashJoinExec`, swapping the inputs via\n`swap_inputs` panics with:\n```\nInternal error: Cannot swap HashJoinExec inputs after dynamic filters have been constructed.\n```\n\nThe join\u0027s build side is already committed at that stage, and swapping\ninputs would invalidate the dynamic filter expressions that reference\nprobe-side columns. `JoinSelection` should detect this and leave the\n`HashJoinExec` unchanged instead of failing the plan.\n\n## What changes are included in this PR?\n\n- In `JoinSelection::statistical_join_selection_subrule`, check if\n`!hash_join.dynamic_expressions_produced().is_empty()` and return `None`\n(leaving the plan unchanged).\n- In `can_swap_hash_join`, guard against swapping when dynamic\nexpressions are produced.\n- In `hash_join_swap_subrule`, guard against swapping unbounded left\ninputs when dynamic expressions are produced.\n- Added tests in\n`datafusion/core/tests/physical_optimizer/join_selection.rs` verifying\nthat `JoinSelection` skips `HashJoinExec` carrying dynamic filters in\nboth `CollectLeft` and `Partitioned` modes.\n\n## What is the testing strategy for this PR?\n\nAdded `test_join_selection_skips_hash_join_with_dynamic_filter` in\n`datafusion/core/tests/physical_optimizer/join_selection.rs` verifying\nthat `JoinSelection` leaves the plan unchanged for both `CollectLeft`\nand `Partitioned` modes without error.\n\n## Are there any user-facing changes?\n\nNo API changes. Fixes an internal error when re-optimizing plans that\ncontain dynamic filters.\n\n---------\n\nCo-authored-by: Qi Zhu \u003czhuqilucas@gmail.com\u003e"
    },
    {
      "commit": "20a46295a4a89037443595ba6e65098dd34c606f",
      "tree": "965c7a1ab05965bb5d209bbfce3179fb09de463a",
      "parents": [
        "d5f5ad46657924cfc0ef587cd0aed6bdd705da17"
      ],
      "author": {
        "name": "Subham Singhal",
        "email": "SubhamSinghal@users.noreply.github.com",
        "time": "Thu Oct 15 10:37:48 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 10:37:48 2026 +0000"
      },
      "message": "perf: Partitioned topk emit row number (#26133)\n\n## Which issue does this PR close?\n\n- Part of [#24608](https://github.com/apache/datafusion/issues/24608)\n\n## Rationale for this change\n\nWith `enable_window_topn`, `WindowTopN` rewrites `Filter(rn \u003c\u003d K) →\nBoundedWindowAggExec → SortExec` into:\n\n```text\nBoundedWindowAggExec: row_number() PARTITION BY [pk] ORDER BY [val], mode\u003dSorted\n  PartitionedTopKExec: fn\u003drow_number, fetch\u003d2, partition\u003d[pk], order\u003d[val ASC]\n```\n\nThe window node stays only to produce `rn`, but the operator already\nknows every retained row\u0027s rank when it emits it: rows leave in\n`(partition keys, order keys)` order, and the retained set is exactly\nthe rows with rank ≤ K. The node\u0027s cost scales with the operator\u0027s\noutput (K × partitions) and never amortizes, because every batch it sees\nis dense in partition boundaries.\n\n## What changes are included in this PR?\n\n- `PartitionedTopKExec::try_new` takes `ranking_field:\nOption\u003cFieldRef\u003e`. When set, the operator appends a `UInt64` column with\neach row\u0027s rank, and `WindowTopN` drops the window node:\n\n  ```text\nPartitionedTopKExec: fn\u003drow_number, fetch\u003d2, partition\u003d[pk], order\u003d[val\nASC], emit\u003d[rn]\n  ```\n- Each policy derives the rank from what it already holds. `ROW_NUMBER`:\nposition in the partition\u0027s drain. `RANK`: position of the first row\nwith the same key; boundary ties take the boundary key\u0027s. `DENSE_RANK`:\nindex of the distinct-key group. All three rely on the retained set\nbeing a complete order-prefix of its partition.\n- Applied only when the window node has exactly one expression, since\nthe operator appends one column. Otherwise the node is kept, as today.\nThe output schema is the node\u0027s (input fields plus that field), so\ncolumn indices above are unchanged and `schema_check()` holds.\n- `compute_properties` declares the ordering the removed node published,\n`[partition keys..., rank ASC NULLS LAST]`, so `ORDER BY pk, rn` stays\nsort-free.\n\n## Are these changes tested?\n\n- `topk/mod.rs`: the rank column for each policy, including boundary\nties, an eviction that moves a row to the tie list, a `DENSE_RANK` group\ngathered from several input batches, and output spanning several\n`batch_size` chunks.\n- `sorts/partitioned_topk.rs`: the widened schema, and the `[pk, rn]`\nordering (but not `[rn]` alone).\n- `core/tests/physical_optimizer/window_topn.rs`: the node is removed\nfor one expression and kept for two; `ORDER BY pk, rn` plans no\n`SortExec` for all three functions; end to end, the emitted column\nequals the flag-off result (ties, 4 partitions, batch size 4).\n- `window_topn.slt` and `range_partitioning.slt`: EXPLAIN output\nupdated, query results unchanged.\n\n## Benchmark\n\nh2o `window.sql` k\u003d2 sweeps on `J1_1e7_1e7_NA.parquet` (10 M rows, 14\npartitions), `enable_window_topn \u003d true` in both arms.\n\n| partitions | `ROW_NUMBER` | `RANK` | `DENSE_RANK` |\n|---|---|---|---|\n| 100 | 0.037 → 0.035 s (1.06×) | 0.036 → 0.037 s (0.97×) | 0.037 →\n0.037 s (1.00×) |\n| 1 K | 0.036 → 0.035 s (1.03×) | 0.038 → 0.039 s (0.97×) | 0.040 →\n0.040 s (1.00×) |\n| 10 K | 0.041 → 0.038 s (1.08×) | 0.034 → 0.032 s (1.06×) | 0.047 →\n0.044 s (1.07×) |\n| 100 K | **0.075 → 0.050 s (1.50×)** | **0.092 → 0.060 s (1.53×)** |\n**0.147 → 0.118 s (1.25×)** |\n\n## Are there any user-facing changes?\n\nOnly with enable_window_topn (default false): EXPLAIN no longer shows\nthe window node for single-expression ranking queries, and\nPartitionedTopKExec shows emit\u003d[...]. Results for the built-in functions\nare unchanged.\n\nA user-defined window function registered as row_number, rank or\ndense_rank is no longer rewritten. WindowTopN used to match these\nfunctions by name; it now compares the WindowUDF with the built-in\n(row_number_udwf(), rank_udwf(), dense_rank_udwf()). Without this, the\noperator\u0027s column would replace the custom evaluator\u0027s output, or the\nquery would fail at execution if the return type isn\u0027t UInt64. On main,\nsuch a function already had its input pruned.\ndatafusion-functions-window becomes a regular dependency of\ndatafusion-physical-optimizer.\n\nNo breaking API change: PartitionedTopKExec::try_new keeps its\nsignature. with_ranking_field() and ranking_field() are new public\nmethods."
    },
    {
      "commit": "d5f5ad46657924cfc0ef587cd0aed6bdd705da17",
      "tree": "e1a749149b08c378308c7b04c8af796456ecd0a7",
      "parents": [
        "91cd7ffb927b5a4f9fee1907db50a9610759de5b"
      ],
      "author": {
        "name": "Jeffrey Vo",
        "email": "jeffrey.vo.australia@gmail.com",
        "time": "Thu Oct 15 10:36:24 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 10:36:24 2026 +0000"
      },
      "message": "chore: bump rustls to fix audit (#26352)\n\nfix security audit CI\n\n```sh\ncargo update -p rustls\n```"
    },
    {
      "commit": "91cd7ffb927b5a4f9fee1907db50a9610759de5b",
      "tree": "9a53364a2245cec975a3c1a45c9039afa5f30064",
      "parents": [
        "b51a94ddc66c6824ece3fdc97cd4bd7f0bdff62f"
      ],
      "author": {
        "name": "Shayan Gh",
        "email": "98089795+ShayanGho@users.noreply.github.com",
        "time": "Thu Oct 15 07:37:59 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 07:37:59 2026 +0000"
      },
      "message": "feat: align multi-key equi-join keys with Range partitioning order (#25589)\n\n## Which issue does this PR close?\n\n- Closes #25435.\n\nPart of epic #25421.\n\n## Rationale for this change\n\nTwo inputs that are both range-partitioned on `(a, b)` with identical\nsplit points are co-partitioned, so a partitioned join can run within\neach partition with no shuffle. Whether the planner produced that plan\ndepended on the order the equality conjuncts were written in:\n\n```sql\nSELECT ... FROM t1 JOIN t2 ON t1.b \u003d t2.b AND t1.a \u003d t2.a\n```\n\ngives `HashJoinExec` `on \u003d [(b, b), (a, a)]`, so the join required\n`KeyPartitioned([b, a])`. `Partitioning::satisfaction` compares key\nlists positionally, reported `NotSatisfied` against `Range([a, b])`, and\n`EnsureRequirements` hash-repartitioned both already co-partitioned\ninputs.\n\nBefore, from `range_join_key_alignment_reversed_keys` (both inputs\nranged on `(a, b)`, the right one aliased to `(a1, b1)`, joined `b \u003d b1\nAND a \u003d a1`):\n\n```\nHashJoinExec: mode\u003dPartitioned, join_type\u003dInner, on\u003d[(b@1, b1@1), (a@0, a1@0)]\n  RepartitionExec: partitioning\u003dHash([b@1, a@0], 4), input_partitions\u003d4\n    DataSourceExec: file_groups\u003d{4 groups: [[p0], [p1], [p2], [p3]]}, projection\u003d[a, b, c, d, e], output_partitioning\u003dRange([a@0 ASC, b@1 ASC], [(10, 0), (20, 0), (30, 0)], 4), file_type\u003dparquet\n  RepartitionExec: partitioning\u003dHash([b1@1, a1@0], 4), input_partitions\u003d4\n    ProjectionExec: expr\u003d[a@0 as a1, b@1 as b1]\n      DataSourceExec: file_groups\u003d{4 groups: [[p0], [p1], [p2], [p3]]}, projection\u003d[a, b, c, d, e], output_partitioning\u003dRange([a@0 ASC, b@1 ASC], [(10, 0), (20, 0), (30, 0)], 4), file_type\u003dparquet\n```\n\nAfter:\n\n```\nHashJoinExec: mode\u003dPartitioned, join_type\u003dInner, on\u003d[(a@0, a1@0), (b@1, b1@1)]\n  DataSourceExec: file_groups\u003d{4 groups: [[p0], [p1], [p2], [p3]]}, projection\u003d[a, b, c, d, e], output_partitioning\u003dRange([a@0 ASC, b@1 ASC], [(10, 0), (20, 0), (30, 0)], 4), file_type\u003dparquet\n  ProjectionExec: expr\u003d[a@0 as a1, b@1 as b1]\n    DataSourceExec: file_groups\u003d{4 groups: [[p0], [p1], [p2], [p3]]}, projection\u003d[a, b, c, d, e], output_partitioning\u003dRange([a@0 ASC, b@1 ASC], [(10, 0), (20, 0), (30, 0)], 4), file_type\u003dparquet\n```\n\n## What changes are included in this PR?\n\n- In `ensure_distribution_with_stats`, before a node\u0027s distribution\nrequirements are read, a new `reorder_join_keys_to_range_inputs`\nreorders a `Partitioned` `HashJoinExec`\u0027s or a `SortMergeJoinExec`\u0027s\n`on` pairs (and, for sort-merge joins, the matching `sort_options`) to\nfollow the left, else the right, input\u0027s Range key order, when the join\nkeys are a complete permutation of that input\u0027s range keys. Whole pairs\nmove together, so the join condition is unchanged. It runs in the\nbottom-up distribution pass so each join sees its inputs\u0027 partitioning\nafter their own requirements have been enforced, and it applies\nregardless of `datafusion.optimizer.top_down_join_key_reordering`.\n- Matching is per input (`range_join_key_positions`): an input\u0027s range\nkey expressions are compared only with that same input\u0027s join keys,\nusing that input\u0027s equivalence classes. The existing `try_reorder` also\ncompares against the other side\u0027s keys, which for an unaliased crossed\njoin (left `Range([a, b])`, right `Range([b, a])`, `ON l.b \u003d r.a AND l.a\n\u003d r.b`) reports \"already aligned\" and misses the permutation.\n- Distribution satisfaction is deliberately left positional; reordering\nthe pairs is what makes the requirement satisfiable. Making satisfaction\norder-insensitive instead would be unsound: a row with `a \u003d 10, b \u003d 20`\nis in partition 1 under `Range([a, b])` but in partition 2 under\n`Range([b, a])`, so inputs with the same split values in a different key\norder are still repartitioned (covered by\n`range_join_key_alignment_swapped_range_keys_still_repartition`).\n- The existing hash-key reordering in the join-key reordering phase is\nunchanged. Doc comments updated to say where each kind of alignment\nhappens.\n- Behavior note: when one side\u0027s layout is the swapped one, the\nreference side changes. Previously the left input was repartitioned to\nmatch the right; now the join is aligned to the left and the right input\nis repartitioned. Both plans are correct.\n\n## What is the testing strategy for this PR?\n\n- `datafusion/core/tests/physical_optimizer/enforce_distribution.rs`:\n`range_join_key_alignment_reversed_keys`,\n`range_join_key_alignment_crossed_keys`,\n`range_join_key_alignment_sort_merge_join` (asserts `sort_options` are\npermuted with `on` and the projection survives the rebuild), and\n`range_join_key_alignment_swapped_range_keys_still_repartition`. Each\nruns under both `top_down_join_key_reordering` settings, passes\n`SanityCheckPlan`, and is unchanged by a second `EnsureRequirements`\npass.\n- `datafusion/sqllogictest/test_files/range_partitioning.slt` TEST 49,\nover a new composite-key fixture `range_partitioned_composite`\nregistered in `test_context/range_partitioning.rs`: `EXPLAIN` of the\nquery from the issue plus result verification, with rows on the split\nboundaries and duplicate matching keys.\n\n## Are there any user-facing changes?\n\nNo API changes. Partitioned hash joins and sort-merge joins can now\nreuse compatible Range partitioning when equality keys are written in a\ndifferent order.\n\n## AI assistance\nI used Claude and Codex for code exploration, implementation\nguidance, review, and documentation drafting. I applied the changes and\nran\nthe tests myself.\n\n---------\n\nCo-authored-by: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Jay Zhan \u003cjayzhan211@gmail.com\u003e"
    },
    {
      "commit": "b51a94ddc66c6824ece3fdc97cd4bd7f0bdff62f",
      "tree": "73ffed164acdf662dee1adcb7a297191f4f0f757",
      "parents": [
        "e732212cabd030d500efc35049448b3714017c7b"
      ],
      "author": {
        "name": "Thomas Tanon",
        "email": "thomas@pellissier-tanon.fr",
        "time": "Thu Oct 15 07:30:43 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 15 07:30:43 2026 +0000"
      },
      "message": "DiskManager: include the description in file names (#26110)\n\nEase debugging: the file names are now `.tmp.{description}.{randomness}`\ninstead of `.tmp{randomness}`\n\nThis PR only changes the temporary file names, a test is extended to\nensure that escaping works properly.\n\n---------\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e"
    },
    {
      "commit": "e732212cabd030d500efc35049448b3714017c7b",
      "tree": "e9a74073ae1f0d34fc0aaacdc856d6380ada68ea",
      "parents": [
        "7f00b30d66e878bdfd779e4b114cd486c25f3117"
      ],
      "author": {
        "name": "Adrian Garcia Badaracco",
        "email": "1755071+adriangb@users.noreply.github.com",
        "time": "Wed Oct 14 23:15:48 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:15:48 2026 +0000"
      },
      "message": "feat: allow extension `ExecutionPlan`s to decode via a per-type registry instead of `PhysicalExtensionCodec` (#24631)\n\n## Which issue does this PR close?\n\n- Closes https://github.com/apache/datafusion/issues/24625.\n\n## Rationale for this change\n\n### The user-visible problem\n\nA library that ships its own `ExecutionPlan` (datafusion-distributed\nships six) has to write a `PhysicalExtensionCodec` to serialize it: a\ncentral `downcast_ref` chain for encode and a matching `match` for\ndecode, in a file separate from the plan. Two such libraries on one\nsession also have to compose their codecs by hand through\n`ComposedPhysicalExtensionCodec`, and their users have to remember to\ninstall the composed codec on every process that decodes a plan.\n\nThat composition is fragile in a way that is easy to miss.\n`PhysicalExtensionNode` carries no type discriminator, so the codec *is*\nthe discriminator. `ComposedPhysicalExtensionCodec` copes by writing the\n**position** of the encoding codec into the payload bytes. The decoding\nside must therefore register the same codecs in the same order, a plan\nthat two codecs both accept resolves to whichever was registered first,\nand a name collision between two independent crates cannot be detected.\ndatafusion-python and datafusion-distributed have each built their own\nworkaround for this (a codec-id layer and a `user_codec.rs` composition\nfile respectively).\n\n### Where this sits in the bigger picture\n\nPhysical-plan serialization is moving from central `downcast_ref` chains\nin `datafusion-proto` to per-type hooks that live next to each type:\n`try_to_proto` (a trait method, dispatched through the vtable) plus an\ninherent `try_from_proto` (a constructor, so it cannot be a trait\nmethod). https://github.com/apache/datafusion/issues/23494 did this for\nevery built-in `ExecutionPlan`;\nhttps://github.com/apache/datafusion/issues/22418 did it for\n`PhysicalExpr`.\n\nThird-party types could use the encode half of that but not the decode\nhalf, because decoding an extension node always routed through\n`PhysicalExtensionCodec::try_decode`. This PR closes the loop for\n`ExecutionPlan`; https://github.com/apache/datafusion/pull/24628 does\nthe same for `PhysicalExpr` with the same shape and the same names\n(`Extension*FromProto` pairing the wire name with the constructor,\n`register_*` / `decode_*` facades over one shared registry, attached\nthrough `SessionConfig::with_extension`). **#24628 is stacked on this\nPR**, which adds the shared registry, and must land second.\n\n### How this relates to `PhysicalExtensionCodec`\n\nThe codec is **not deprecated** and this PR does not touch\n`ComposedPhysicalExtensionCodec`. The decode rule is:\n\n- A `PhysicalExtensionNode` **with a `plan_name` that the decoding\nsession has registered** decodes through the plan\u0027s own\n`try_from_proto`. A failure there is fatal: falling through to the codec\nwould let it wrongly decode a payload it never wrote, which is the bug\nthe name exists to prevent.\n- **Anything else** (no name, because a codec wrote it, or a name this\nsession does not know) takes the codec chain exactly as before. If the\ncodec also fails, the missing registration is added as *context* on the\ncodec\u0027s own error, and lists what the session does know. The codec\u0027s\nerror kind is kept, because a codec can fail for a reason that has\nnothing to do with a missing registration.\n\nThe codec keeps three jobs the registry does not take: UDF/UDAF/UDWF\npayloads (a function is an *instance*, not a type, so a type-keyed\nregistry does not fit), anything not yet migrated, and the released\n`FFI_PhysicalExtensionCodec` in `datafusion-ffi`, which\ndatafusion-python exposes as public API. What becomes deprecable once\nplans and expressions are registry-backed is\n`ComposedPhysicalExtensionCodec`, whose reason to exist was composition;\nthat is a later, separate decision. Making the composed codec itself\nname-keyed instead of position-keyed (as suggested on the issue) is also\northogonal to this PR and can be done independently.\n\n### How FFI will work\n\nToday `FFI_ExecutionPlan` has no serialization slot, so a foreign plan\nalways goes through the codec. This PR does not change that. It is\ndesigned so FFI can plug in later with no breaking change:\n\n- The registry stores decoders as a **private** `fn` pointer. The public\nsurface is `ExtensionPlanFromProto` and the three facade functions. The\nstorage can grow to carry an FFI vtable and private data, and a\nlower-level entry point that takes a name and a decoder object can be\nadded, both without breaking anything shipped here.\n- `PhysicalPlanNode` is a prost message, so it crosses the ABI as bytes,\nthe same way `FFI_ExecutionPlan::partition_statistics` already ships a\nprost-encoded `Statistics`. Protobuf\u0027s field-skipping gives version-skew\ntolerance that a `#[repr(C)]` struct cannot.\n- One limit FFI inherits from the codec rather than from this PR:\n`ForeignPhysicalExtensionCodec::try_decode` discards the caller\u0027s\n`TaskContext` and rebuilds one from the provider\u0027s side, so a decoder\nthat reads the *decoding* session\u0027s state (the second test below) would\nnot see it across FFI.\n\n## What changes are included in this PR?\n\nThree stacked commits, each green on its own. Built-in plan\nserialization is untouched: they keep the inherent `try_from_proto` they\nhave had since 55.0.0, dispatched from their own `PhysicalPlanType`\nvariant.\n\n1. **`feat: add an optional plan_name discriminator to\nPhysicalExtensionNode`.** `optional string plan_name \u003d 3;` — additive on\nthe binary wire format: old writers omit it and old readers skip it. The\ngenerated JSON codec is stricter, see \"user-facing changes\" below.\nNothing reads it yet.\n2. **`feat: add ProtoDecoderRegistry, one decoder store for every\nextension kind`.** A `(trait, name)`-keyed store of type-erased decoders\nin `datafusion-proto-models`, with no knowledge of any decode context.\nNothing uses it yet.\n3. **`feat: decode extension ExecutionPlans through a session-scoped\nregistry`.**\n- An extension plan implements one trait, `ExtensionPlanFromProto`,\nwhich pairs the name it is dispatched by with the constructor that\nrebuilds it. Built-ins do not implement it — they have a wire variant of\ntheir own — so `register_execution_plan::\u003cFilterExec\u003e(..)` does not\ncompile, and **no built-in code or caller changes at all**. Its\n`try_to_proto` writes itself with `ctx.extension_node::\u003cSelf\u003e(payload,\nself.children())`, which builds the `PhysicalExtensionNode` and stamps\n`Self::NAME`, so the name on the wire and the registry key cannot drift\napart. Its `try_from_proto` receives the whole `PhysicalPlanNode`,\nmatches the `Extension` variant, and decodes `inputs` with\n`ctx.decode_children`.\n- `ProtoDecoderRegistry` (new, in `datafusion-proto-models`): build one,\n`register_execution_plan::\u003cT\u003e(\u0026mut registry)` for every extension plan\nthe session must decode, and attach it with the existing\n`SessionConfig::with_extension`. Registering the same type twice is a\nno-op (keyed by `TypeId`); a *different* type under a taken name is an\nerror, so collisions surface at registration. `decode_execution_plan`\nreads the name off the node rather than taking it as an argument, so a\ncaller cannot pair a node with a name it does not carry.\n- The registry is **keyed by the trait as well as the name**, and is\nshared by every extension kind DataFusion can decode. This crate\ncontributes only the `dyn ExecutionPlan` face of it. A session therefore\ncarries **one** registry rather than one per kind, a plan and an\nexpression may use the same name without colliding, and\nhttps://github.com/apache/datafusion/pull/24628 registers into the same\nobject. It lives in `datafusion-proto-models` because that crate already\nsits below every crate that owns one of these traits, behind the same\n`proto` feature; it stores each decoder type-erased and never names a\ndecode context.\n- A session carries one registry and `with_extension` replaces it, so\nthe **application** that owns the session builds it. A library exposes\n`pub fn register(registry: \u0026mut ProtoDecoderRegistry) -\u003e Result\u003c()\u003e` —\nwhich can register its plans *and* its expressions — and the application\ncomposes the libraries it uses. The libraries need to know nothing about\neach other and the call order does not matter. There is no\n`SessionConfig` extension trait and no merge-on-register helper: public\nAPI is added when a use needs it, not ahead of one.\n- It is attached through the `SessionConfig` extension map because\n`datafusion-execution` sits *below* the crates that own these traits and\ncannot name them; the extension map is the one type-erased hole through\nthat layering, and it reaches every `TaskContext` derived from the\nsession with no new plumbing.\n- Decode dispatch in `datafusion-proto`, per the rule above, plus the\nupgrade-guide entry (in 56.0.0, the guide for the next release).\n\n## What is the testing strategy for this PR?\n\n12 unit tests across `datafusion-proto-models` and\n`datafusion-physical-plan`, 10 integration tests in\n`datafusion/proto/tests/cases/plans/extensions.rs`, and doctests on the\npublic traits:\n\n- `ProtoDecoderRegistry` itself: 6 unit tests, including the same name\nunder two different traits resolving to two different decoders.\n- Registration: idempotent for the same type, an error for a different\ntype under the same name, empty names rejected, a name registered for\nanother kind invisible to the `ExecutionPlan` face, and a `compile_fail`\ndoctest for `register_execution_plan::\u003cFilterExec\u003e(..)` (verified to\nfail on the `ExtensionPlanFromProto` bound, not on anything incidental).\n- A runnable example,\n`datafusion-examples/examples/proto/extension_plan_registry.rs`: the\nsame two-crate tree `composed_extension_codec.rs` builds, decoded by\nname with no composed codec, plus the error a session that forgot to\nregister gets.\n- A plan round-tripping with `DefaultPhysicalExtensionCodec`, which\ndecodes nothing, so whatever survives came from the registry.\n- A **session-dependent** plan modeled on datafusion-distributed\u0027s\n`NetworkShuffleExec`: its worker pool is rebuilt from the *decoding*\nsession through `ExecutionPlanDecodeCtx::task_ctx()`, and never rides\nthe wire.\n- Two independent crates\u0027 plans nested inside each other, decoding with\nno `ComposedPhysicalExtensionCodec`.\n- The registry taking precedence over a codec that claims every payload,\nand a registered decoder\u0027s failure *not* falling back to that codec.\n- A codec failing for an unrelated reason: the missing-registration hint\nis added, and the codec\u0027s own error kind still reaches `find_root()`.\n- Back-compat both ways: codec-encoded plans stay anonymous on the wire\nand decode as before; a name the session does not know (on a session\nthat *does* have a registry with other plans in it) still decodes if a\ncodec understands the payload; a node re-encoded without the field reads\nback as unnamed.\n- A bytes-level `encode_to_vec` / `decode` hop, so tag 3 is exercised as\nwire bytes and not just as a struct field.\n\nVerified locally on the final tree and with `cargo check` on every\ncommit of the stack: the `datafusion-physical-expr`,\n`datafusion-physical-plan` and `datafusion-proto` test suites, the\nexamples crate, CI\u0027s clippy script, rustdoc with private items under `-D\nwarnings`, prettier, typos and fmt.\n\n## Are there any user-facing changes?\n\nNew public API, all opt-in; no behavior change for existing code. One\nmechanical break, in the 56.0.0 upgrade guide: `PhysicalExtensionNode`\ngained a field, so exhaustive struct literals must set `plan_name`\n(`None` reproduces the previous behavior). Built-in plans are untouched\n— no signature, trait or import change for anyone calling\n`FilterExec::try_from_proto(..)`.\n\nTwo things worth a reviewer\u0027s attention:\n\n- **JSON is not as forgiving as the binary format.** The generated\n`pbjson` deserializer rejects a field it does not know, so a *named*\nnode written by a new writer cannot be read as JSON by a reader on an\nolder DataFusion. The binary prost path skips the unknown field as\nusual, and a plan that does not opt in writes no name and is unaffected.\nIf you serialize plans as JSON across versions, upgrade the readers\nbefore you opt a plan in.\n- **Opting a plan in changes what the codec fallback means for that\nplan.** Once its `try_to_proto` writes its own payload, a reader that\nfails to register the type hands that payload to the codec it removed,\nand a codec that still recognizes the plan may decode the new payload as\nthe old message rather than fail. The upgrade guide says to register\nmigrated plans everywhere their plans are read.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nhttps://claude.ai/code/session_017UzVkTrKmRRc2fKCdMkqBp\n\n---------\n\nCo-authored-by: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "7f00b30d66e878bdfd779e4b114cd486c25f3117",
      "tree": "a166c4f95a1a31c9ef402b981686743f46d75946",
      "parents": [
        "cda4dd65c968103891bb1ba7352811124a6dd7f9"
      ],
      "author": {
        "name": "Aleksandr Efimov",
        "email": "horsodilo@gmail.com",
        "time": "Wed Oct 14 23:04:19 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:04:19 2026 +0000"
      },
      "message": "fix: avoid shifting zero grouping ordinals by 64 (#26136)\n\n## Which issue does this PR close?\n\nCloses #26134.\n\n## Rationale for this change\n\nA representable 64-column grouping-set query can panic while\nconstructing its grouping ID.\n\n## What changes are included in this PR?\n\nUse the semantic mask directly when the duplicate ordinal is zero.\nPreserve the existing checks for layouts requiring more than 64 bits.\n\n## What is the testing strategy for this PR?\n\nSQL cases in `grouping.slt` cover 64-bit masks, real versus rolled-up\nNULLs, duplicates and capacity refusals using the default aggregate\nkernel. One unit test covers zero-row array construction.\n\n## Are there any user-facing changes?\n\nValid 64-column grouping sets execute successfully. Unrepresentable\nlayouts continue to return NotImplemented.\n\n---------\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e"
    },
    {
      "commit": "cda4dd65c968103891bb1ba7352811124a6dd7f9",
      "tree": "20ef271429bc78ce16cddf86fb0b9374ee90a003",
      "parents": [
        "c280a4b47be1f02f3994dc461d6b6335581cda18"
      ],
      "author": {
        "name": "Alexy Khrabrov",
        "email": "deliverable@gmail.com",
        "time": "Wed Oct 14 23:01:41 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 23:01:41 2026 +0000"
      },
      "message": "perf: compare nested ScalarValues by type before converting to ArrayData (#26066)\n\n## Which issue does this PR close?\n\n- Closes #26065.\n\n## Rationale for this change\n\nPhysical planning slows down, faster than the query grows, when\nprojections carry many typed NULL struct literals: a `UNION ALL` of 35\nbranches with 35 struct columns of 20 fields takes 862 ms in\n`create_physical_plan` on `main`. `EquivalenceGroup::add_constant`\ncompares each new constant with every existing class, and\n`ScalarValue::eq` compares nested values with arrow\u0027s array equality,\nwhich converts both arrays to `ArrayData` before it compares anything,\neven when the two values have different types.\n\n## What changes are included in this PR?\n\n`ScalarValue::eq` compares the nested variants (`List`, `LargeList`,\n`FixedSizeList`, `ListView`, `LargeListView`, `Struct`, `Map`) through a\nhelper that returns early for the same `Arc`, and compares lengths and\ndata types before arrow\u0027s array equality. Results are unchanged; only\nvalues of the same type and length reach the `ArrayData` comparison.\n\nWith the reproducer from the issue (release build, Apple M1 Max),\n`create_physical_plan`:\n\n| struct columns x fields | main | this PR |\n|---|---:|---:|\n| 10 x 20 | 31 ms | 17 ms |\n| 20 x 20 | 179 ms | 47 ms |\n| 35 x 20 | 862 ms | 147 ms |\n| 35 x 40 | 1,766 ms | 253 ms |\n\n## What is the testing strategy for this PR?\n\n`test_nested_scalar_eq` covers typed NULL structs of the same and of\ndifferent types, struct values that are equal and unequal, and lists of\ndifferent element types. The scalar tests in `datafusion-common` pass.\n\n## Are there any user-facing changes?\n\nNo.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---------\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Adrian Garcia Badaracco \u003c1755071+adriangb@users.noreply.github.com\u003e"
    },
    {
      "commit": "c280a4b47be1f02f3994dc461d6b6335581cda18",
      "tree": "30d444a13524fac7d1b29b130155a54c06ea4535",
      "parents": [
        "07077ff83ffe1d44f61ff7557a3b2d8b927220b3"
      ],
      "author": {
        "name": "kosiew",
        "email": "kosiew@gmail.com",
        "time": "Wed Oct 14 22:49:54 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 22:49:54 2026 +0000"
      },
      "message": "Fix GroupOrdering memory descriptor double-counting (#26074)\n\n## Which issue does this PR close?\n\n- Part of #23393\n\n## Rationale for this change\n\n`GroupOrdering::size()` currently counts both the outer enum descriptor\nand the inline active variant descriptor. Because the active variant is\nstored inside `GroupOrdering`, this double-counts inline memory for\npartial and full ordering states.\n\nThis change makes the `GroupOrdering` enum the single owner of the\ndescriptor charge. Partial ordering continues to include retained\n`order_indices` capacity and state-owned allocations, while full\nordering adds no additional descriptor charge.\n\n## What changes are included in this PR?\n\n- Make `GroupOrdering::size()` charge `size_of::\u003cGroupOrdering\u003e()`\nexactly once for `None`, `Partial`, and `Full`.\n- Rename `GroupOrderingPartial::size()` to `heap_size()` and make it\nreport only:\n  - retained `order_indices` allocation\n  - allocations owned by the partial ordering state\n- Remove `GroupOrderingFull::size()`, since full ordering has no\nadditional heap allocation to add beyond the outer enum descriptor.\n- Document the ownership boundary in `GroupOrdering::size()` and\n`GroupOrderingPartial::heap_size()`.\n- Add deterministic size-accounting tests for none, full, and partial\nordering states.\n\n## Are these changes tested?\n\nYes. This PR adds:\n\n- `test_size_none`, which verifies that `GroupOrdering::None` reports\nexactly `size_of::\u003cGroupOrdering\u003e()`.\n- `test_size_full`, which verifies that full ordering reports exactly\none `GroupOrdering` descriptor before and after `new_groups`,\n`remove_groups`, `input_done`, and `reset`.\n- `test_size_partial_retained_allocations`, which verifies that:\n  - grown-and-truncated `order_indices` capacity remains charged\n- a variable-width `ScalarValue::Utf8` sort key is included in the\nreported size\n- replacing the sort key charges the replacement rather than retaining\nthe old key\n- `input_done` and `reset` drop state-owned key allocations while\nretaining the `order_indices` capacity\n  - repopulating the state causes the key allocation to be charged again\n\nThe tests use deterministic `size_of`, vector capacity, and\n`ScalarValue::size()` expectations rather than allocator-observed byte\ncounts.\n\n## Are there any user-facing changes?\n\nNo public API changes are introduced.\n\nThis changes internal memory accounting reported by\n`GroupOrdering::size()` so that inline descriptor memory is no longer\ndouble-counted. Grouping and aggregation behavior is otherwise unchanged\nby this patch.\n\n## LLM-generated code disclosure\n\nThis PR includes LLM-generated code and comments. All LLM-generated\ncontent has been manually reviewed."
    },
    {
      "commit": "07077ff83ffe1d44f61ff7557a3b2d8b927220b3",
      "tree": "22a4489a4086840851665552a35463a755c0ace1",
      "parents": [
        "0eb098a03e9cd6e683c71769c410f7927e8a5381"
      ],
      "author": {
        "name": "siddu",
        "email": "siddusbakka@gmail.com",
        "time": "Wed Oct 14 20:48:31 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:48:31 2026 +0000"
      },
      "message": "Add tests fpr nullability of AND/OR expressions (#26164)\n\nFixes #25978\n\nThis PR fixes an internal error where the physical input schema\nmismatches the logical input schema due to incorrect nullability\npropagation for AND/OR expressions in CommonSubexprEliminate.\n\nIt adds robust contains_is_not_null and contains_is_null helper\nfunctions to accurately determine if binary expressions are nullable.\n\ncc @alamb @jayzhan211"
    },
    {
      "commit": "0eb098a03e9cd6e683c71769c410f7927e8a5381",
      "tree": "ca03b0792113e7354edac2c3965fb488f2550ffd",
      "parents": [
        "e0d64fca0f5e59030cfba21b18da003be3b20e0b"
      ],
      "author": {
        "name": "Subham Singhal",
        "email": "SubhamSinghal@users.noreply.github.com",
        "time": "Wed Oct 14 20:46:46 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:46:46 2026 +0000"
      },
      "message": "bench: classic pwmj sql benchmark (#25839)\n\n## Which issue does this PR close?\n\n- Part of #18221 (and the PWMJ epic #17427).\n\n## Rationale for this change\n\nThere is no benchmark for `PiecewiseMergeJoin`\u0027s classic joins (`INNER`\n/ `LEFT` / `RIGHT` / `FULL`). `nlj`, `hj` and `smj` each have a suite\nunder `benchmarks/sql_benchmarks/`, but PWMJ doesn\u0027t. It is also off by\ndefault (`enable_piecewise_merge_join \u003d false`), so none of the existing\nsuites reach it.\n\nThe follow-up #PERF_PR changes two things in the classic stream: how it\nfinds each streamed row\u0027s first match, and how it handles rows that\ncan\u0027t match. That change needs a benchmark on `main` to compare against.\n\n## What changes are included in this PR?\n\nA new `pwmj` suite in `benchmarks/sql_benchmarks/pwmj/`, plus one row in\nthat directory\u0027s README. It doesn\u0027t change any library code.\n\nEvery query is `SELECT lhs.payload, rhs.payload FROM lhs \u003cJOIN\u003e rhs ON\nlhs.key \u003c rhs.key`:\n\n- **`lhs` (buffered):** the keys `1..\u003d100000`, scrambled with a fixed\nmultiplicative hash, so every run and every branch sees the same data. A\nstreamed key `b` matches exactly the buffered keys `1..b`.\n- **`rhs` (streamed):** 2M rows. The five subgroups are match regimes.\nThey separate the two costs per streamed row: finding its first match,\nand building its output.\n\n| subgroup | queries | streamed keys | what it exercises |\n|---|---|---|---|\n| `no_match` | Q01–Q04 | all below every buffered key | rows that can\u0027t\nmatch anything |\n| `null_heavy` | Q05–Q08 | half NULL, the rest as `no_match` | NULL keys\n|\n| `half_match` | Q09–Q12 | half `no_match`, half `selective` | a mix |\n| `selective` | Q13–Q16 | each matches only the 1–4 smallest buffered\nkeys | a first match at the far end of the buffered side, with small\noutput |\n| `all_match` | Q17–Q20 | all above every buffered key; only 2K rows,\nsince the output is `lhs × rhs` \u003d 2×10⁸ rows | output-bound; the first\nmatch is the first buffered row |\n\nEach subgroup runs `INNER`, `LEFT`, `RIGHT` and `FULL`, in that order.\nAll 20 files share `pwmj.benchmark.template`:\n\n- `load` builds both tables in memory from `range()`, so there\u0027s no data\nto generate and key generation is never timed.\n- `init` turns on `enable_piecewise_merge_join`, and an `assert` checks\nit took effect. Without the flag every query would plan as a nested-loop\njoin.\n- An `assert` checks the join\u0027s row count against the value that follows\nfrom the keys. A wrong result fails here rather than showing up as a\nplausible timing.\n- `expect_plan` pins `PiecewiseMergeJoinExec`, `operator: Lt` and the\n`join_type`. If the planner swapped the inputs, the query would measure\nthe mirrored join.\n\nThe runner re-plans every iteration and counts rows as they stream, so\nthe buffered side is rebuilt each time and `all_match`\u0027s 2×10⁸ rows are\nnever held in memory.\n\nThere is no nested-loop arm. At these sizes it is 2×10¹¹ predicate\nevaluations.\n\n## What is the testing strategy for this PR?\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "e0d64fca0f5e59030cfba21b18da003be3b20e0b",
      "tree": "300a323217544a26610bcf508bc6860b7513a1ca",
      "parents": [
        "d173279fd8af20093a0d2bedf694125f92168e9f"
      ],
      "author": {
        "name": "Andy Grove",
        "email": "agrove@apache.org",
        "time": "Wed Oct 14 20:46:20 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:46:20 2026 +0000"
      },
      "message": "fix: count buffers shared between sort input batches once (#25820)\n\n## Which issue does this PR close?\n\n- Part of #25804 (finding 5).\n- Related to #22526.\n\n## Rationale for this change\n\nA grouped aggregate emits its output as zero-copy slices of one batch.\n`SortExec` reserves every buffered batch\u0027s full buffer capacity, so each\nslice is charged for the whole aggregate output. A sort after a `GROUP\nBY` therefore reserves several times the memory it holds: it spills when\nit doesn\u0027t need to, and with spilling disabled it fails with\n`ResourcesExhausted`. For example, `select group_key, sum(payload) as s\nfrom t group by group_key order by group_key` over 100,000 groups needs\na 24 MB memory limit on `main` and runs in 6 MB with this change.\n\n## What changes are included in this PR?\n\n- `ExternalSorter` counts its buffered batches with a\n`RecordBatchMemoryCounter`, as #22862 did for the hash join build side,\nso a buffer shared between batches is reserved once. Each batch still\nreserves its sliced size for sorting it.\n- When the buffered batches are sorted as separate runs and the runs\nshare buffers, the reservation for the runs\u0027 input is held until every\nrun is sorted, because a run still waiting to be sorted keeps the shared\nbuffers alive. Runs that share nothing release their input as soon as\nthey are sorted, as before.\n- Coalescing batches into runs for single-column sorts sizes the batches\nthe same way.\n- Schemas with view, dictionary or list view types keep reserving each\nbatch on its own. Sorting those types keeps referencing the input\u0027s data\nbuffers or values, and the sorted runs and the merge charge those\nbuffers once per run. Counting them once at insert would let a spill\ntake more runs than the merge can then hold\n(`sort_spill_is_compacted_for_view_arrays` fails that way). Counting\nthem once needs the merge side to change too; see #25800 and #25791.\n\n## What is the testing strategy for this PR?\n\n- `sort_after_group_by_reserves_shared_output_once` in `memory_limit`\nruns `GROUP BY ... ORDER BY` with one sort key and with two, under a 12\nMB limit with spilling disabled. It fails on `main` with `Memory\nExhausted while Sorting` for either ordering.\n- The `spill_tests` fixture now builds each batch separately. Its\nbatches were slices of one batch, and the tests relied on each slice\nbeing charged for the whole batch to create memory pressure.\n\nBenchmarks: `cargo bench -p datafusion --bench sort` with the\n`release-nonlto` profile, running `main` and this PR alternately, median\nof three runs:\n\n| benchmark | `main` | this PR | change |\n|---|---|---|---|\n| sort i64 1M | 24.11 ms | 23.94 ms | -0.7% |\n| sort partitioned i64 1M | 3.05 ms | 3.21 ms | +5.3% |\n| sort utf8 high cardinality 1M | 59.54 ms | 60.72 ms | +2.0% |\n| sort partitioned utf8 high cardinality 1M | 4.84 ms | 4.93 ms | +2.0%\n|\n| sort utf8 dictionary tuple 1M | 510.35 ms | 511.02 ms | +0.1% |\n| sort partitioned utf8 dictionary tuple 1M | 10.44 ms | 10.65 ms |\n+2.0% |\n| sort mixed tuple 1M | 106.05 ms | 106.43 ms | +0.4% |\n| sort partitioned mixed tuple 1M | 11.51 ms | 11.12 ms | -3.4% |\n\n`sort partitioned i64 1M` was 5-12% slower across longer runs. The\ndifference comes from moving the shared reservation, empty in this\nbenchmark, into each run\u0027s sort future: a build that doesn\u0027t move it\nmatches `main`. The counting itself costs about 2 µs per partition. The\ndictionary cases don\u0027t take the new path, which puts the noise at about\n2%.\n\n## Are there any user-facing changes?\n\nSorts over sliced input without view or dictionary columns, such as the\noutput of a grouped aggregate, reserve less memory and spill less. No\nAPI changes."
    },
    {
      "commit": "d173279fd8af20093a0d2bedf694125f92168e9f",
      "tree": "87063e67b680cd7d0f5af96ae9805d119ccf04a5",
      "parents": [
        "8f0280be40e3d8a7a735fe02bdb09bc007e94542"
      ],
      "author": {
        "name": "Emily Matheys",
        "email": "55631053+EmilyMatt@users.noreply.github.com",
        "time": "Wed Oct 14 20:45:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:45:27 2026 +0000"
      },
      "message": "fix: Account for buffered rows in `RowCursorStream` (#25372)\n\nCurrently the behaviour is to only keep the current batch reserved per\ncursor, meaning we don\u0027t *actually* reserve all the rows we are keeping\nowned.\nThis leads to a lot of invisible memory, that is held, but not accounted\nby the pool.\n(This scales fairly linearly with the number of partitions, in a regular\nround-robin case, for example.)\nWhile the mem overhead was greatly reduced by @ariel-miculas \u0027s\nhttps://github.com/apache/datafusion/pull/23619 and\nhttps://github.com/apache/datafusion/pull/23802\nIt is still a very problematic area in terms of memory visibility.\n(Round-robin is an extreme case by nature)\n\nThis PR does *not* reduce the mem usage or anything, it just makes the\nmemory *visible* and keeps everything that needs to be reserved -\nreserved.\n\nI believe in order to ensure robustness, once this is merged another PR\nwill need to be made to cap the merge reservation to the peak of the\nExternalSorter reservation (due to some behaviours I\u0027ve seen with\nfair-type pools, which treat spillable and non-spillable operators\ndifferently)\n\n---------\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "8f0280be40e3d8a7a735fe02bdb09bc007e94542",
      "tree": "692d376ea21d39e566910f0dafe5cf5f1024fb6f",
      "parents": [
        "9dec77584ea39d93aa01bba7f880b318b37d2c24"
      ],
      "author": {
        "name": "Mason",
        "email": "mason.hall@coralogix.com",
        "time": "Wed Oct 14 20:40:40 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:40:40 2026 +0000"
      },
      "message": "Document and enforce compatibility between an aggregate\u0027s accumulators (#25710)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #25660.\n\n## Rationale for this change\n\nSee #25660.\n\nThis change only documents/enforces this requirement for built-in\naggregate UDF functions. Anyone who implements their own aggregate UDFs\ndo not need to adhere to this requirement since vanilla datafusion\ndoesn\u0027t require it. This does add a public test that user\u0027s can use to\nmake sure this requirement is satisfied if they desire.\n\n## What changes are included in this PR?\n\nThis change adds:\n- Internal documentation explaining this requirement and how to check\nfor it using the provided test function.\n-\n`datafusion_functions_aggregate::testing::check_state_compatibility()`:\nA generic test that identifies cases where the `Accumulator` and\n`GroupsAccumulator` of an `AggregateUDF` differ. This is exposed as a\npublic function that can be used to test this requirement on\n`AggregateUDFImpl`s implemented by downstream consumers. The test is run\non all built-in default aggregation functions.\n- Fixes for `approx_distinct()` and `avg()`, which both violated this\nrequirement\n  - This takes the changes from #25659 to fix `approx_distinct()`\n- The `Accumulator` for `avg()` would return `0` for the count if it\nhasn\u0027t seen any non-null values. The `GroupsAccumulator` would return\n`null` instead. This change updates the `Accumulator`s to also return\n`null` for the count in this case.\n\n## What is the testing strategy for this PR?\n\nThis adds a test to enforce this new requirement in a generic way.\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\n\nThis changes the intermediate state of the `avg()` accumulator to match\nthe `avg()` groups accumulator, which some users may be affected by.\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e"
    },
    {
      "commit": "9dec77584ea39d93aa01bba7f880b318b37d2c24",
      "tree": "87002c7ac6c8ef9b5fa401ab6f6e47c4e001dd05",
      "parents": [
        "4e43ad6e412a248a6f5729f005a20cc007eb5594"
      ],
      "author": {
        "name": "David Greven",
        "email": "davidgreven@outlook.com",
        "time": "Wed Oct 14 20:34:33 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:34:33 2026 +0000"
      },
      "message": "fix: support RunEndEncoded arguments in MIN/MAX (#26248)\n\n## Which issue does this PR close?\n\n- Closes #26247.\n\n## Rationale for this change\n\n`MIN` and `MAX` fail with an internal error on `RunEndEncoded` columns,\nwhile they work on `Dictionary` columns. See #26247 for a reproducer.\n\n## What changes are included in this PR?\n\n`MIN`/`MAX` use a user-defined signature, so `get_min_max_result_type`\nalone decides the argument type. It unwraps `Dictionary` to its value\ntype but passes `RunEndEncoded` through unchanged, so no cast is planned\nand the accumulator receives a type it has no implementation for. #24565\nadded `RunEndEncoded` handling to `coerced_from`, but user-defined\nsignatures don\u0027t go through it.\n\nThis PR adds a `RunEndEncoded` arm that recurses into the value type.\nWith the recursion, `RunEndEncoded\u003c_, Dictionary\u003cK, V\u003e\u003e` coerces to `V`,\nthe same result type `MAX` gives a plain `Dictionary\u003cK, V\u003e` column.\nUnwrapping one level would return the correct value, but type it as\n`Dictionary\u003cK, V\u003e`.\n\nThe existing `Dictionary` arm unwraps only one level. I left it\nunchanged, because a dictionary whose values are themselves encoded\nseems rare. I\u0027m happy to make it recursive in this PR if you\u0027d prefer\nthe two arms to match.\n\n## What is the testing strategy for this PR?\n\n- `test_get_min_max_return_type_coerce_run_end_encoded` in `min_max.rs`\ncovers `RunEndEncoded\u003cInt32, UInt32\u003e` → `UInt32` and\n`RunEndEncoded\u003cInt32, Dictionary\u003cUInt32, Utf8\u003e\u003e` → `Utf8`.\n- New cases in `run_end_encoded.slt` go through SQL planning, so they\nexercise the UDAF\u0027s coercion path rather than calling the accumulator\ndirectly:\n  - ungrouped `MIN`/`MAX`;\n  - their result types, via `arrow_typeof`;\n  - grouped `MIN`/`MAX`;\n  - `MAX` as a window function;\n  - `MAX` over `RunEndEncoded\u003cInt32, Dictionary\u003cUInt32, Utf8\u003e\u003e`.\n\nWithout the fix, the four `RunEndEncoded\u003cInt32, UInt32\u003e` cases fail with\nthe internal error from #26247.\n\n## Are there any user-facing changes?\n\n`MIN` and `MAX` now accept `RunEndEncoded` arguments and return the\nvalue type. There are no API changes.\n\nGenerated-by: Claude Code (Claude Opus 5.5). I reviewed the change and\ncan answer for it."
    },
    {
      "commit": "4e43ad6e412a248a6f5729f005a20cc007eb5594",
      "tree": "6ff3554adacac3e1f5a30074ff26c69ea256e8af",
      "parents": [
        "ac60d990182936af3416ae82ba887c264d0cf87c"
      ],
      "author": {
        "name": "Bruce Ritchie",
        "email": "bruce.ritchie@gmail.com",
        "time": "Wed Oct 14 20:33:58 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:33:58 2026 +0000"
      },
      "message": "fix: remove duplicate predicate benchmark result (#26244)\n\n## Which issue does this PR close?\n\nNo linked issue.\n\n## Rationale for this change\n\nRunning `benchmark_runner predicate_eval --query 1 --iterations 1 --rows\n1000000` fails while parsing the template with `multiple results found`.\n\n## What changes are included in this PR?\n\nRemove the duplicate `result` directive from\n`predicate_eval.benchmark.template`.\n\n## What is the testing strategy for this PR?\n\nUsing the existing debug benchmark runner, reproduced the parser error\nwith the original template and verified the fixed template completes\nquery 1 successfully with one result row. `cargo fmt --all` passed.\n\n`cargo clippy --all-targets --all-features -- -D warnings` fails on\nthree `mutable_key_type` diagnostics in unchanged\n`datafusion/optimizer/src/push_down_filter.rs` on upstream main. The\nstandard `./dev/rust_lint.sh` suite passed. Extended workspace tests are\nstill running; they have reached the SQL logic tests after passing the\npreceding Rust test binaries. Test data is supplied from the existing\ncheckout via `ARROW_TEST_DATA` and `PARQUET_TEST_DATA`.\n\n## Are there any user-facing changes?\n\nThe predicate evaluation benchmark can run again."
    },
    {
      "commit": "ac60d990182936af3416ae82ba887c264d0cf87c",
      "tree": "d455056f6089669e57fa4f8ef005b75c5109465d",
      "parents": [
        "2aab9731ca02e98a5462ee6524b72f93898bf518"
      ],
      "author": {
        "name": "Roshan Ramani",
        "email": "154859727+rawsun007@users.noreply.github.com",
        "time": "Wed Oct 14 20:33:50 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:33:50 2026 +0000"
      },
      "message": "docs: document ^ as the bitwise xor operator (#26224)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- None; documentation fix. Follows up #22314.\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\nThe operators page documents `#` as bitwise xor, \"interchangeable with\n`^`\". On `main`, `SELECT 5 # 3;` fails with the default dialect\n(`ParserError(\"No infix parser for token Sharp ...\")`); `#` is only xor\nin the PostgreSQL and Redshift dialects. The page describes the default\ndialect, where `^` is xor.\n\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\nThe xor section and its index entry now document `^` instead of `#`,\nwith the current column name (`BIT_XOR`) in the example output. Per\nreview, the page sticks to the default dialect rather than listing\nper-dialect exceptions.\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\nRan the new example against `datafusion-cli` built from `main`;\n`./ci/scripts/doc_prettier_check.sh` passes. Docs only, no test.\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e\n\nDocumentation only.\n\nGenerated with Claude Code (claude-opus-5-5). It came from running the\ndocumented SQL examples against `main`, not from an issue."
    },
    {
      "commit": "2aab9731ca02e98a5462ee6524b72f93898bf518",
      "tree": "a0e5b39ea4f9fea129569498ceb76a8fee56f8f8",
      "parents": [
        "53232ba2914d9cda09b887f7c2c016ea1cfa0a63"
      ],
      "author": {
        "name": "Yu-Chuan Hung",
        "email": "86523891+CuteChuanChuan@users.noreply.github.com",
        "time": "Wed Oct 14 20:33:35 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:33:35 2026 +0000"
      },
      "message": "refactor: replace MapOffset tuple with ProbeOffset enum (#26203)\n\n## Which issue does this PR close?\n\n- Closes #25332 .\n\n## Rationale for this change\n\n`MapOffset` was a `(usize, Option\u003cu64\u003e)` tuple that encoded the resume\npoint of chunked hash map lookups by convention. One position had two\nencodings (`(row, Some(0))` and `(row + 1, None)`), the unique-key fast\npaths read only `offset.0`, and `HashJoinStream` relied on an\nundocumented invariant (`offset \u003d\u003d (0, None)` only before the first\nchunk).\n\n## What changes are included in this PR?\n\n- Replace the tuple with `pub enum ProbeOffset { AtRow { row }, MidChain\n{ row, next } }` in `join_hash_map.rs`, re-exported from `joins::utils`\nnext to `JoinHashMapType`.\n- Normalize at the producer: `traverse_chain` returns `AtRow { row: row\n+ 1 }` once a row\u0027s chain is finished, so every position has one\nencoding and readers no longer handle `Some(0)`.\n\n  | Old | New |\n  |---|---|\n  | `(row, None)` | `AtRow { row }` |\n  | `(row, Some(next))`, `next !\u003d 0` | `MidChain { row, next }` |\n  | `(row, Some(0))` | `AtRow { row: row + 1 }` |\n\n- Unique-key fast paths (`JoinHashMap`, `ArrayMap`) `debug_assert!` that\nthey only receive `AtRow`. The invariant holds by construction (`unique`\nis fixed when the build side is built, and every chunk of a probe batch\nuses the same map), so a check in debug builds and CI is enough to catch\na regression without adding a panic path to query execution.\n- Add `ProcessProbeBatchState::is_first_chunk()` and use it at the three\nfirst-chunk checks. The invariant it relies on (a returned offset is\nnever `AtRow { row: 0 }`) is documented on `ProbeOffset`.\n\n## What is the testing strategy for this PR?\n\nCovered by existing tests, with expected offsets updated to the new\nencoding.\n\n`test_unique_fast_path_with_uninserted_row` (#26018) told the fast path\napart from the chain walk by their different offset encodings, which\nthis PR removes. This PR added an unmatched probe row so the two paths\nnow emit different results (the fast path limits by probe rows, the\nchain walk by matches), and checked that the test fails when the fast\npath is disabled. cc @jayzhan211\n\n\n## Are there any user-facing changes?\n\nNo behavior change. \nAPI change: `JoinHashMapType::get_matched_indices_with_limit_offset` and\nthe public `get_matched_indices_with_limit_offset` function now take and\nreturn `ProbeOffset` instead of `(usize, Option\u003cu64\u003e)`.\n\nCo-authored-by: Jay Zhan \u003cjayzhan211@gmail.com\u003e"
    },
    {
      "commit": "53232ba2914d9cda09b887f7c2c016ea1cfa0a63",
      "tree": "c66a01e58858498b864ea02d1ca6af6aebadd2c4",
      "parents": [
        "390d2107d10b03af078fb8cddf48e4fdbb734053"
      ],
      "author": {
        "name": "Pepijn Van Eeckhoudt",
        "email": "pepijn@vaneeckhoudt.net",
        "time": "Wed Oct 14 20:32:50 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:32:50 2026 +0000"
      },
      "message": "Add Arrow IPC format options (#26155)\n\n## Which issue does this PR close?\n\n- Closes #8635\n\n## Rationale for this change\n\nIt can sometimes be useful to not spend CPU cycles compressing and\ndecompressing data. The Arrow IPC write support currently only supports\nLZ4 compression even though the writer supports no compression and zstd.\nThis PR adds config options to make the compression settings user\nconfigurable.\n\n## What changes are included in this PR?\n\n- Add Arrow config options for compression type, compression level, and\nalignment\n- Add glue code to pass config options to the file format implementation\n\n## What is the testing strategy for this PR?\n\nAdded SLTs to cover new options\n\n## Are there any user-facing changes?\n\nYes, additional options become available, but the default behaviour\nremains the same."
    },
    {
      "commit": "390d2107d10b03af078fb8cddf48e4fdbb734053",
      "tree": "be5b909a67caf723e1df0f22b02193bcc9695c97",
      "parents": [
        "7d4893cac33e6e81eb16bf0f58981fc8633c5085"
      ],
      "author": {
        "name": "Artem Osipov",
        "email": "59066880+osipovartem@users.noreply.github.com",
        "time": "Wed Oct 14 20:30:50 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:30:50 2026 +0000"
      },
      "message": "Preserve list element metadata when rebuilding scalar values (#26092)\n\n## Summary\n\n`ScalarValue::cast_to` reconstructs LIST values through\n`SingleRowListArrayBuilder::with_field`. That builder copied the child\nfield name and nullability but dropped its metadata. Casting a LIST to a\ntarget field containing nested metadata (for example an Iceberg\n`PARQUET:field_id`) therefore produced a scalar with a different type\nfrom the requested target, and subsequent batch expansion could fail\nschema validation.\n\nCopy the field metadata as well. This only runs when constructing a\nscalar LIST; columnar cast and batch fast paths are unchanged.\n\n## Validation\n\n- New regression test covers LIST scalar cast to a metadata-bearing\nelement field and batch expansion.\n- `cargo +1.95.0 test --offline -p datafusion-common --lib`: 624 passed.\n- `cargo +1.95.0 fmt --all --check`: passed.\n- Independent read-only review: approved, no blocking findings."
    },
    {
      "commit": "7d4893cac33e6e81eb16bf0f58981fc8633c5085",
      "tree": "a98cde48ade7e291670aba833200349c8ea2dd55",
      "parents": [
        "678751ff7e7fdd4706e4c9f8d4eb6bea284ef6f2"
      ],
      "author": {
        "name": "Luca Bigon",
        "email": "luca.bigon@bauplanlabs.com",
        "time": "Wed Oct 14 20:29:48 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:29:48 2026 +0000"
      },
      "message": "fix(proto): preserve EmptyRelation schema across logical plan round trip (#25944)\n\n## Which issue does this PR close?\n\n- Closes #25937.\n\n## Rationale for this change\n\nThe optimizer reduces queries like `SELECT * FROM t LIMIT 0` or `...\nWHERE false` to an `EmptyRelation` that keeps the schema of its input,\nbut `EmptyRelationNode` only stored `produce_one_row`. After a protobuf\nround trip the plan came back without columns, and plans where another\nnode refers to those columns, like `SELECT max(id), count(*) FROM t\nWHERE false`, failed to decode.\n\n## What changes are included in this PR?\n\n- Add a `schema` field to `EmptyRelationNode`, encoded and decoded like\n`DropViewNode`.\n- Fall back to the previous empty schema for older payloads without it.\n- Regenerate the prost and pbjson models.\n- Add `roundtrip_empty_relation_schema` and update the expected JSON in\n`plan_to_json`.\n- Document the new generated field in the 56.0.0 upgrade guide.\n\n## Are these changes tested?\n\nYes:\n\n- `cargo test -p datafusion-proto --features json,avro --test\nproto_integration`\n- `cargo fmt --all -- --check`\n- `cargo clippy -p datafusion-proto -p datafusion-proto-models\n--all-targets --all-features -- -D warnings`\n- `./dev/rust_lint.sh`\n\n`json_to_plan` still decodes `{\"emptyRelation\":{}}`, which covers\npayloads from older versions.\n\n## Are there any user-facing changes?\n\nLogical plans reduced to an `EmptyRelation` keep their schema across\nprotobuf round trips. The wire format remains backward compatible; the\ngenerated `EmptyRelationNode` struct gains a `schema` field, documented\nin the upgrade guide."
    },
    {
      "commit": "678751ff7e7fdd4706e4c9f8d4eb6bea284ef6f2",
      "tree": "27e75f00c6d0360ed0e565dac79e7ad5109b7367",
      "parents": [
        "47135be91cf1edfcb04ee009680d2ee467500e86"
      ],
      "author": {
        "name": "Adrian Garcia Badaracco",
        "email": "1755071+adriangb@users.noreply.github.com",
        "time": "Wed Oct 14 20:11:37 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:11:37 2026 +0000"
      },
      "message": "bench: model remote object storage faithfully for --simulate-latency (#24093)\n\n## Which issue does this PR close?\n\n- None.\n\n## Rationale for this change\n\n`--simulate-latency` must make benchmarks pay what S3 or GCS would\ncharge. The current `LatencyObjectStore` does not, for three reasons:\n\n1. **It charges one request for a vectored read.** It overrides\n`get_ranges` and sleeps once. `AmazonS3` and `GoogleCloudStorage` do not\noverride `get_ranges`. The trait default merges ranges that are less\nthan 1MiB apart, and sends each merged range as a separate GET. Thus a\nParquet scan that reads 2 distant column chunks costs 2 requests on S3,\nbut 1 request in the simulation. An IO change that alters the request\ncount is invisible to the benchmark.\n2. **Bytes are free.** A 4 byte read and a 100MB read cost the same.\nThus merging ranges across a gap always looks free.\n3. **A LIST costs one request, independent of the key count.** S3 and\nGCS return 1000 keys per page, and each page needs the token of the\nprevious page. Thus a listing of 5000 keys costs 5 serial requests.\n\n## What changes are included in this PR?\n\n`SimulatedObjectStore` replaces `LatencyObjectStore`. Each GET costs:\n\n1. one connection from a pool of 128,\n2. a time to first byte, drawn at random from a measured distribution\n(see below),\n3. a transfer time at 90MiB/s per connection, charged while the caller\nreads the body.\n\nA HEAD costs one connection and one HEAD time to first byte. Each LIST\npage costs one connection and one LIST time to first byte.\n\nThe store does not override `get_ranges`, so arrow-rs merges and fans\nout the ranges exactly as it does against S3. The store overrides\n`list_with_offset`, because S3 and GCS start that listing on the server.\nWrites, copies and deletes go directly to the local filesystem without a\ncost, because benchmarks do not measure them.\n\nThese are not modelled: request failures, retries, and a shared network\nlimit across connections.\n\n### Calibration\n\nI measured S3 and GCS on 2026-10-13 with the `object_store` clients,\nfrom a VM in the same region as the bucket:\n\n- S3: c7i.2xlarge in us-east-2, new bucket with 20k small keys and 64\nobjects of 128MiB.\n- GCS: e2-standard-8 in europe-west1, existing bucket with real data,\n200k keys listed.\n\n| | S3 | GCS |\n|---|---|---|\n| GET time to first byte, P50 / P95 | 24 / 30 ms | 75 / 210 ms |\n| HEAD, P50 / P95 | 11 / 16 ms | 18 / 28 ms |\n| LIST page, P50 / P95 | 50 / 60 ms | 83 / 170 ms |\n| One connection, 64MiB GET | ~100 MiB/s | ~80 MiB/s |\n| Total, all connections | ~1.4 GiB/s at 32 connections | ~1.9 GiB/s at\n128 connections |\n\nS3 is approximately 3x faster to the first byte than GCS, thus one\ndistribution cannot fit both. Each latency table is an equal mix: 10\nvalues at the 5%, 15%, ..., 95% quantiles of S3, and 10 values at the\nsame quantiles of GCS. Thus each request is S3-like or GCS-like with\nequal probability. The throughput of one connection is 90MiB/s, the mean\nof the two. The total limit is the network limit of the VM, not of the\nstore, thus it is not modelled.\n\n## Are these changes tested?\n\nYes. 7 tests use tokio\u0027s paused clock, so the costs are exact and not\nflaky:\n\n| Test | What it shows |\n|---|---|\n| `distant_ranges_are_separate_requests` | Ranges more than 1MiB apart\nare 2 requests. |\n| `near_ranges_are_one_request` | Ranges less than 1MiB apart are 1\nmerged request. |\n| `distant_column_chunks_cost_more_requests` | A real DataFusion Parquet\nscan of 2 distant columns costs 1 more request than a scan of 1 column.\n|\n| `get_costs_ttfb_plus_transfer` | 256KiB at 1MiB/s costs TTFB + 250ms.\n|\n| `head_pays_only_the_head_ttfb` | A HEAD costs only the HEAD time to\nfirst byte, not a transfer. |\n| `list_costs_one_request_per_page` | 0, 1, 3, 4, 6 and 7 keys at 3 keys\nper page cost 1, 1, 1, 2, 2 and 3 pages. |\n| `list_with_offset_skips_earlier_pages` | A listing that starts at key\n6 of 9 costs 1 page, not 3. |\n\n### Benchmark results\n\nThe benchmark CI (`c4a-highmem-16`), with `SIMULATE_LATENCY\u003dtrue` on\nboth sides. The baseline is `LatencyObjectStore` on main (45de64c).\nMinimum time per query:\n\n| Suite | Main | This PR | Change | Queries slower / faster / no change\n|\n|---|---|---|---|---|\n| tpch | 16.9 s | 18.2 s | 1.08x slower | 14 / 6 / 2 |\n| tpcds | 57.1 s | 47.9 s | 1.19x faster | 16 / 75 / 8 |\n| clickbench_partitioned | 85.3 s | 126.0 s | 1.48x slower | 29 / 2 / 12\n|\n\n- **ClickBench is slower because bytes have a cost now.** Q23 (`SELECT\n*` with `LIKE`) reads almost all columns and is 3.3x slower. Q36-Q42\n(selective on one `CounterID`) send many small, scattered reads and are\n1.6-3.3x slower, because each merged range is a separate request.\n- **TPC-DS is faster because metadata is cheaper.** It reads many small\ntables. HEAD now has its own, lower latency, and LIST pages are cheaper.\n- **TPC-H is approximately the same.** The bandwidth cost of the large\ntables and the lower metadata cost approximately cancel.\n\nResults of `--simulate-latency` before this change are not comparable\nwith results after it.\n\n## Are there any user-facing changes?\n\nNo. This change is in the benchmarks only. `--simulate-latency` and\n`SIMULATE_LATENCY` keep their names.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---------\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "47135be91cf1edfcb04ee009680d2ee467500e86",
      "tree": "8d6866d7323d00756db5499b58d3ab4522d06bf7",
      "parents": [
        "28cefb7f1e52b54a0e518642c510db0d4411dc6a"
      ],
      "author": {
        "name": "Adrian Garcia Badaracco",
        "email": "1755071+adriangb@users.noreply.github.com",
        "time": "Wed Oct 14 20:05:14 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 20:05:14 2026 +0000"
      },
      "message": "fix: resolve pass-through columns against the input when merging an extraction projection (#25412)\n\n## Which issue does this PR close?\n\nNone filed.\n\n## Rationale for this change\n\nThis query fails to plan on `main`:\n\n```sql\ncreate table t(v int, s struct\u003ca int\u003e, env varchar) as values (1, {a: 10}, \u0027prod\u0027), (2, {a: 20}, \u0027dev\u0027);\n\nwith samples as (\n  select v, s, env from t\n),\nexpanded as (\n  select v, s, env from samples\n  union all\n  select v, s, env from samples where 1 \u003d 2\n)\nselect env, sum(s[\u0027a\u0027]) from expanded group by env;\n```\n\n```\nOptimizer rule \u0027push_down_leaf_projections\u0027 failed\ncaused by\nSchema error: Schema contains qualified field name samples.env and unqualified\nfield name env which would be ambiguous\n```\n\n`enable_leaf_expression_pushdown` is on by default, so this is a plain\nplanning\nfailure for a valid statement. A `union all` whose one side is provably\nempty is\nwhat produces the shape, and query generators emit that: a dashboard\npanel adds a\nsecond branch behind a comparison of two constants and the panel stops\nworking.\n\n## What changes are included in this PR?\n\n`build_extraction_projection_impl` merges an extraction projection into\nthe\nprojection below it, and then adds the pass-through columns the merged\nprojection\ndoes not already carry. It compared the columns it was about to add\nagainst the\nprojection\u0027s own expressions without putting the two in the same space.\n\nA projection can list bare column names over a qualified input. Removing\nthe empty\nside of the union leaves exactly that. The comparison then misses, the\ncolumn is\nadded a second time under its bare name, and `Projection::try_new`\nrejects a schema\nthat holds `samples.env` and a bare `env` together.\n\nThis PR resolves both sides against the input schema before the\ncomparison, and\npushes the column under the name the input gives it. A needed column\nthat is not in\nthe input, or that is ambiguous there, is skipped. Before this change\nsuch a column\nwas added and `Projection::try_new` failed at the merge.\nA same-name alias such as `t.c AS c` counts as a pass-through on the\nexisting side too, the same as a bare `t.c`.\n\n## Are these changes tested?\n\nYes. The statement above is added to `struct.slt`, with a result check\nand an\n`EXPLAIN` plan pin. It fails on `main` with the error above and passes\nwith this change.\n\nThree unit tests in `extract_leaf_expressions.rs` cover the merge\ndirectly. All three fail on `main`:\n- `test_merge_bare_column_into_qualified_projection`: a filter names `a`\nover a projection that outputs `test.a`.\n- `test_merge_into_projection_with_same_name_alias`: the projection\nspells the pass-through as `test.a AS a`.\n- `test_merge_appends_qualified_column_for_bare_request`: the projection\nkeeps only `test.a` and the merge needs a bare `b`. The appended column\nmust be `test.b`. On `main` it is a bare `b`.\n\n`cargo test --workspace --exclude datafusion-sqllogictest` passes: 126\nsuites,\n12479 tests, 0 failures. The sqllogictest suite passes too: 520 files, 0\nfailures. `cargo clippy -p datafusion-optimizer --all-targets` and\n`cargo fmt --all -- --check` are clean.\n\n## Are there any user-facing changes?\n\nA statement of this shape plans instead of failing. No API change.\n\n## Note on overlapping work\n\nhttps://github.com/apache/datafusion/pull/25388 (draft) edits the same\narm of\n`build_extraction_projection_impl`, for a different problem: duplicated\nevaluation of `KeepInPlace` expressions,\nhttps://github.com/apache/datafusion/issues/25329.\nIt does not touch the qualifier comparison this PR changes, so the two\nare\nindependent in behaviour, but whichever lands second will need a small\nrebase at\nthe tail of the `columns_needed` loop.\n\nhttps://github.com/apache/datafusion/pull/25282 also appends to the end\nof\n`struct.slt`, as this PR does. Keeping both blocks is the whole\nresolution.\n\nPart of the leaf-pushdown EPIC:\nhttps://github.com/apache/datafusion/issues/25459\n\n---------\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "28cefb7f1e52b54a0e518642c510db0d4411dc6a",
      "tree": "d7b302f96cd9723c9070c9f11813ccffb8a7c616",
      "parents": [
        "6023600b95ca7ac5cacf51ef2cbafa552c6e9090"
      ],
      "author": {
        "name": "Jay Zhan",
        "email": "jayzhan211@gmail.com",
        "time": "Wed Oct 14 17:44:56 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 17:44:56 2026 +0000"
      },
      "message": "fix: match functional dependencies by column position, not by name (#26150)\n\n## Which issue does this PR close?\n\n- None yet. The bug and its repro are below.\n\n## Rationale for this change\n\nIf `x` is a primary key, the optimizer treats `CAST(x AS ...)` as `x`.\nIt then drops the other ORDER BY or GROUP BY keys that `x` determines,\nso the query returns wrong results:\n\n```sql\nCREATE TABLE t (x DOUBLE, y VARCHAR, PRIMARY KEY (x))\n  AS VALUES (1.1, \u0027b\u0027), (1.2, \u0027a\u0027), (2.1, \u0027c\u0027);\n\nSELECT x, y FROM t ORDER BY CAST(x AS INT), y;\n-- main:     1.1 b / 1.2 a / 2.1 c   (`y` is dropped from the sort)\n-- expected: 1.2 a / 1.1 b / 2.1 c\n\nSELECT CAST(x AS INT) k, count(*) n FROM t GROUP BY CAST(x AS INT), y;\n-- main:     (1, 2) / (2, 1)         (`y` is dropped from the grouping)\n-- expected: (1, 1) / (1, 1) / (2, 1)\n\nSELECT y, count(*) FROM t GROUP BY CAST(x AS INT);\n-- main:     accepted\n-- expected: Error: Column in SELECT must be in GROUP BY or an aggregate function\n```\n\n`CAST(x AS INT)` is named `t.x`, because casts are left out of\nexpression names. The functional dependency helpers matched GROUP BY and\nORDER BY expressions to key columns by comparing names, so the cast\nmatched the key `t.x`.\n\nThe same happens with `TRY_CAST`, with a `UNIQUE NOT NULL` key, and with\na key that comes from an inner GROUP BY. The ORDER BY case comes from\nthe sort key pruning added in #21362 (54.0.0).\n\n## What changes are included in this PR?\n\n- **Index-based helpers.** The four helpers in\n`functional_dependencies.rs` now take, for each GROUP BY or ORDER BY\nexpression, the index of the input field it references (`Option\u003cusize\u003e`)\ninstead of its name. A computed expression has no index, so it never\nmatches a key. The new `datafusion_expr::utils::passthrough_field_index`\nreturns the index for a column reference, aliased or not.\n- **One GROUP BY list.** The dependencies of an `Aggregate`\u0027s output use\nthe GROUP BY list that its schema is built from\n(`grouping_set_to_exprlist`). Before, they used a list de-duplicated by\nname, which merged `CAST(x AS INT)` and `x`.\n- **Projections resolve columns.** A projection now finds each input\ncolumn with `DFSchema::index_of_column_by_name` instead of comparing\n`\"qualifier.name\"` strings. The unit test\n`projection_duplicate_flattened_name_uses_first_input_index` asserted\nthe old string behaviour: a column named `\"orders.id\"` got the\ndependency of the different field `orders.id`. It is renamed and now\nasserts that each column keeps its own dependency.\n\n## What is the testing strategy for this PR?\n\n- **New tests.** Section 6 of `functional_dependencies.slt` has one\nquery for each user of the helpers:\n  - ORDER BY pruning;\n  - GROUP BY pruning;\n  - `Aggregate` output dependencies;\n  - GROUP BY expansion.\n\nOn `main`, each of these returns a wrong result or accepts an invalid\nquery. The same queries also run over `TRY_CAST` on a `UNIQUE NOT NULL`\nkey and over a key from an inner GROUP BY. One more query pins that a\nwidening cast (`INT` to `BIGINT`) of a key does not carry its\ndependencies.\n- **New unit tests.** `passthrough_field_index` resolves an ambiguous\nunqualified column to nothing. A key that is in the GROUP BY list two\ntimes (`id, id AS k`, builder API only) still determines the row.\n- **Existing tests** are unchanged, apart from the rewritten unit test.\n- **Planning time.** Planning is not slower. The `sql_planner` TPC-H and\nTPC-DS benchmarks, whose tables have primary keys, are about 5% faster,\nbecause the new code no longer renders expression names.\n\n\u003cdetails\u003e\u003csummary\u003eBenchmark numbers (3 interleaved runs per\nside)\u003c/summary\u003e\n\n| Benchmark | `main` | This PR |\n|---|---|---|\n| `physical_plan_tpch_all` | 17.3 / 17.8 / 18.0 ms | 16.1 / 17.0 / 17.2\nms |\n| `physical_plan_tpcds_all` | 291 / 300 / 301 ms | 276 / 280 / 282 ms |\n\n\u003c/details\u003e\n\n## Are there any user-facing changes?\n\n- **Results.** The queries above return correct results.\n- **Rejected queries.** Only a column reference to a key carries its\ndependencies. A query that selects other columns while grouping by an\nexpression over the key is now rejected, even when the expression keeps\ndistinct values distinct, like `GROUP BY CAST(x AS BIGINT)` over an\n`INT` key. `main` accepts it and its result is correct. PostgreSQL and\nDuckDB reject it too. Group by the key column itself instead.\n- **API change.** Four `pub` functions in `datafusion_common` take\n`\u0026[Option\u003cusize\u003e]` instead of `\u0026[String]`:\n  - `aggregate_functional_dependencies`\n  - `get_target_functional_dependencies`\n  - `get_required_group_by_exprs_indices`\n  - `get_required_sort_exprs_indices`\n\n  The upgrade guide has a migration note."
    },
    {
      "commit": "6023600b95ca7ac5cacf51ef2cbafa552c6e9090",
      "tree": "3357fee687f43936db20de49c4737d46acd7e7a9",
      "parents": [
        "0d79252f61bd8777990b2749c216ffd07079c30d"
      ],
      "author": {
        "name": "Andrew Lamb",
        "email": "andrew@nerdnetworks.org",
        "time": "Wed Oct 14 16:26:20 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 21:26:20 2026 +0100"
      },
      "message": "ci: raise the merge queue status check timeout to 360 minutes (#26293)"
    },
    {
      "commit": "0d79252f61bd8777990b2749c216ffd07079c30d",
      "tree": "351f6a4fb1d61251354a0ada137442445518ae4f",
      "parents": [
        "92323f7f146bb43931193bf005f35804dbca15b7"
      ],
      "author": {
        "name": "kosiew",
        "email": "kosiew@gmail.com",
        "time": "Wed Oct 14 05:35:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 05:35:27 2026 +0000"
      },
      "message": "Fix retained-capacity accounting for grouped byte MIN/MAX (#26154)\n\n## Which issue does this PR close?\n\n- Part of #23393\n\n## Rationale for this change\n\nGrouped byte MIN/MAX accumulators can underreport memory usage because\ntheir accounting is based on the current data length and number of group\nslots rather than the memory allocations they retain.\n\nFor example, replacing a 128-byte string with a one-byte string reuses\nthe existing vector allocation, but the previous accounting reports only\nthe new string length. Similarly, unused capacity in the outer group\nvector is not counted.\n\nThis change makes memory accounting reflect retained allocations,\nproviding more accurate memory usage estimates for grouped MIN/MAX\noperations.\n\n## What changes are included in this PR?\n\n- Add `total_data_capacity` to `MinMaxBytesState` to track retained\ninner `Vec\u003cu8\u003e` capacities independently of `total_data_bytes`, which\nremains responsible for output preallocation.\n- Update `set_value()` to maintain capacity accounting when values are\ninserted, replaced, or cause an existing vector to grow.\n- Update `size()` to account for the outer `min_max` vector\u0027s capacity\nand the cached inner vector capacities, without double-counting the\ninline `Option\u003cVec\u003cu8\u003e\u003e` descriptors.\n- Keep `size()` O(1) by maintaining the inner capacity total\nincrementally.\n- Update `emit_to()` to reset capacity accounting on full emission and\nsubtract emitted inner vector capacities on partial emission.\n\n## Are these changes tested?\n\nThree regression tests are added:\n\n- `size_counts_outer_capacity`: Verifies that memory accounting includes\nallocated outer vector capacity, even when fewer group slots are\ninitialized.\n- `size_retains_inner_capacity`: Tests both MIN and MAX accumulators,\nverifying that replacing a long string with a shorter one preserves\nretained-capacity accounting and that partial and full emission update\nit correctly.\n- `size_tracks_growth_and_emit_reuse`: Verifies capacity accounting when\nan inner vector grows, groups are partially emitted, and the state is\nreused after full emission.\n\n## Are there any user-facing changes?\n\nNo changes to SQL MIN/MAX results or public APIs are intended.\n\nThe change corrects internal memory accounting for grouped byte MIN/MAX\naccumulators, allowing retained allocations to be reported more\naccurately.\n\n## LLM-generated code disclosure\n\nThis PR includes LLM-generated code and comments. All LLM-generated\ncontent has been manually reviewed."
    },
    {
      "commit": "92323f7f146bb43931193bf005f35804dbca15b7",
      "tree": "e5fd3435afc1125ee1889234af8b60850111703d",
      "parents": [
        "7fe6d477328505421f3e050ec7f026831c9afd02"
      ],
      "author": {
        "name": "Burak Şen",
        "email": "buraksenb@gmail.com",
        "time": "Wed Oct 14 05:30:30 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 05:30:30 2026 +0000"
      },
      "message": "fix(proto): preserve physical cast expression state (#25056)\n\n## Which issue does this PR close?\n\n- Closes #24615.\n\n## Rationale for this change\n\nPhysical cast protobuf hooks did not serialize `CastExpr` options or\nexplicit target-field metadata. A round trip could therefore change cast\nbehavior, nullability, or metadata. The hooks also accessed fields\nindividually, so future fields could be omitted silently.\n\n## What changes are included in this PR?\n\n- Exhaustively destructure `CastExpr`, `TryCastExpr`, and their protobuf\nmessages.\n- Preserve explicit target fields for `CAST` and `TRY_CAST` while\nkeeping legacy type-only payload behavior.\n- Preserve all serializable Arrow cast/format options; reject custom\nformatter factories instead of silently dropping them.\n- Store decoded format strings in owned cast options.\n- Regenerate protobuf models and document the `CastExpr::cast_options`\nAPI adjustment.\n\nThe protobuf changes are additive and backward compatible.\n\n## What is the testing strategy for this PR?\n\nAdded unit coverage for:\n\n- target-field and cast-option round trips\n- legacy payloads without the new fields\n- explicit default-shaped targets\n- malformed target-field types\n- unsupported formatter factories\n\nValidated with:\n\n- `cargo test -p datafusion-physical-expr --features proto\nexpressions::cast::`\n- `cargo test -p datafusion-physical-expr --features proto\nexpressions::try_cast::`\n- `cargo clippy -p datafusion-physical-expr -p\ndatafusion-physical-expr-adapter --all-features --tests -- -D warnings`\n- `cargo check -p datafusion-proto --all-features`\n- `./ci/scripts/doc_prettier_check.sh --write --allow-dirty`\n\n## Are there any user-facing changes?\n\nCast expressions now retain their options and explicit output-field\nsemantics across protobuf round trips. `CastExpr::cast_options()`\nreturns a borrowing `CastOptions\u003c\u0027_\u003e` value rather than\n`\u0026CastOptions\u003c\u0027static\u003e`; the upgrade guide documents migration for code\nrebuilding casts.\n\n---------\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "7fe6d477328505421f3e050ec7f026831c9afd02",
      "tree": "7673011c4e6fe23836035b441b83ac0a3c4a8f7d",
      "parents": [
        "473ff694552550b0a74ca1100d4c60c7b341a815"
      ],
      "author": {
        "name": "Huaijin",
        "email": "haohuaijin@gmail.com",
        "time": "Wed Oct 14 04:32:21 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 04:32:21 2026 +0000"
      },
      "message": "fix: update quinn-proto to resolve cargo audit failures (#26253)\n\n## Which issue does this PR close?\n\nN/A (CI fix).\n\n## Rationale for this change\n\nFix `cargo audit` failures, matching apache/arrow-rs#11531.\n\n## What changes are included in this PR?\n\nBump locked `quinn-proto` from `0.11.15` to `0.11.18`.\n\n## What is the testing strategy for this PR?\n\n`cargo audit` passes (zero vulnerabilities). No new tests for this\nlockfile-only update.\n\n## Are there any user-facing changes?\n\nDependency security fixes only.\n\nPrepared with Codex."
    },
    {
      "commit": "473ff694552550b0a74ca1100d4c60c7b341a815",
      "tree": "a5ca4f89f848df9228f4a9de34580db663427d34",
      "parents": [
        "0566b55a4766e280b36c73d11b0bffe9aa5a7fcb"
      ],
      "author": {
        "name": "Oleks V",
        "email": "comphead@users.noreply.github.com",
        "time": "Wed Oct 14 04:22:48 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 04:22:48 2026 +0000"
      },
      "message": "refactor: simplify redundant iterator chains (#26251)\n\n## Which issue does this PR close?\n\n- N/A\n\n## Rationale for this change\n\nA few iterator chains do more work than needed. Some build an\nintermediate `Vec` only to iterate it again, some use several adaptors\nwhere one would do, and some reimplement `rfind`, `rposition`, `last` or\n`to_vec` by hand. Each case is small, but the simpler forms avoid\nallocations and clones and are easier to read.\n\n## What changes are included in this PR?\n\n- `invariants.rs`: a `map`, `collect::\u003cResult\u003cVec\u003e\u003e`, `into_iter`,\n`flatten` chain becomes one `flat_map` over `column_refs()`. Columns are\nno longer cloned.\n- `window_agg_exec.rs`: drop a\n`collect::\u003cVec\u003c_\u003e\u003e().into_iter().collect::\u003cResult\u003c_\u003e\u003e()` round trip.\n- `sql/utils.rs`: `take_while`, `to_owned`, `cloned` and `map(unwrap)`\nbecome a single `map_while`.\n- `sql/statement.rs`: `iter().last()` becomes `last()`.\n`rev().position()` with manual index math becomes `rposition`.\n- `aggregates/mod.rs`: merge two consecutive `filter` calls.\n- `bytes_view.rs`: `iter().rev().find()` becomes `rfind()`.\n- `information_schema.rs` and `ffi/config/mod.rs`: fuse `filter_map`\nfollowed by `map`.\n- `file_scan_config/proto.rs`: `iter().cloned().collect::\u003cVec\u003c_\u003e\u003e()`\nbecomes `to_vec()`.\n\n## What is the testing strategy for this PR?\n\nNo behavior change, so existing tests cover it. Passed locally:\n- `cargo fmt --all` and `cargo clippy -D warnings` on the touched\ncrates.\n- Lib and integration tests for `datafusion-sql`, `datafusion-expr`,\n`datafusion-ffi`, `datafusion-datasource`, and the\n`datafusion-physical-plan` lib tests.\n- sqllogictests matching `information_schema`, `window` and `aggregate`.\n\nI did not run the full workspace suite or any benchmarks.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "0566b55a4766e280b36c73d11b0bffe9aa5a7fcb",
      "tree": "822f3ca9be082fe4d6b94fbadb185d407cd89cbb",
      "parents": [
        "1814c6c97d64989e24f47b50456fa75b8a47d88f"
      ],
      "author": {
        "name": "Peter L",
        "email": "cetra3@hotmail.com",
        "time": "Wed Oct 14 04:03:19 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 04:03:19 2026 +0000"
      },
      "message": "fix: preserve grouping set member names during type coercion (#25891)\n\n## Which issue does this PR close?\n\n- Closes #25890.\n\n## Rationale for this change\n\n`GROUP BY ROLLUP`, `CUBE`, or `GROUPING SETS` fails during analysis when\na member is a scalar function with an implicitly coerced literal\nargument, such as `date_bin(\u00275 minutes\u0027, ts)`:\n\n```\ntype_coercion\ncaused by\nSchema error: No field named \"date_bin(Utf8(\"\"5 minutes\"\"),t.ts)\". Did you mean \u0027\"ROLLUP (date_bin(Utf8(\"\"5 minutes\"\"),t.ts))\"\u0027?\n```\n\nType coercion now turns the literal into an interval value, which\nrenames the member. `TypeCoercion` then restored the original name by\naliasing the whole `Expr::GroupingSet`. An aliased grouping set is no\nlonger recognized as a grouping set: it becomes one ordinary group key\nnamed `ROLLUP (...)`, with no `__grouping_id`, and the projection above\ncan no longer find the member.\n\n## What changes are included in this PR?\n\n`TypeCoercion` now coerces each grouping set member individually through\n`map_children`, saving and restoring each member\u0027s name, and leaves the\ngrouping set itself unaliased. This is the same approach\n`SimplifyExpressions` has used since #14888.\n\n## What is the testing strategy for this PR?\n\n- New sqllogictest cases in `grouping.slt`: `ROLLUP` over the coerced\nmember with `grouping()` in the select list, and `GROUPING SETS` with a\nqualified column next to the coerced member, which is repeated across\nsets. Both fail without this change.\n- New unit test `scalar_udf_in_grouping_set` in `type_coercion.rs`,\nchecking the analyzed plan shape and that a second coercion pass leaves\nthe plan unchanged.\n\n## Are there any user-facing changes?\n\nQueries of this shape now plan and run. No public API changes.\n\n## AI assistance\n\nThis change was prepared with AI assistance. Assumptions called out for\nreviewers:\n\n- The fix is scoped to `TypeCoercion`. `SimplifyExpressions` already\ncarries the same grouping set workaround, and other rules that use\n`NamePreserver` on an `Aggregate` could in principle hit the same\nwhole-grouping-set alias. Moving this into `NamePreserver` would fix it\nin one place, but changes the public `SavedName` API, so I left that for\na possible follow-up.\n- Skipping `TypeCoercionRewriter` on the `Expr::GroupingSet` node itself\nrelies on the rewriter passing grouping sets through unchanged, which it\ndoes today.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "1814c6c97d64989e24f47b50456fa75b8a47d88f",
      "tree": "1697056348d2b7d6fbaa4b316d49663cdfd38cce",
      "parents": [
        "c1fdd6e7936be9b4b8ecc900236571e47834d2b0"
      ],
      "author": {
        "name": "Yin Li",
        "email": "kxl474@student.bham.ac.uk",
        "time": "Wed Oct 14 03:47:15 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 03:47:15 2026 +0000"
      },
      "message": "bench: expand dictionary group-by coverage (#25303)\n\n## Which issue does this PR close?\n\n- Part of #24117.\n\n## Rationale for this change\n\nThe existing dictionary benchmark only measures pre-encoded dictionaries\nwith cardinality expressed as a fraction of row count. That is not\nenough to derive a safe automatic encoding policy: native dictionaries,\nper-batch dictionaries, `Utf8View`, plain strings, and runtime encoding\nhave materially different costs, and the crossover also depends on\nabsolute NDV, value width, and batch layout.\n\nI rebased this PR onto current `main` after #25185 merged and reran the\nrelevant matrix, so the evidence includes the new cached\ndictionary-value-hash path. The crossover remains clear; the cache\noptimization does not make dictionary grouping universally profitable.\n\nCurrent-main results (`700ad9cf2`, release/LTO, Apple M5 Max, Rust\n1.98.1; 10M rows, 8,192-row input batches, one target partition; median\nof iterations 2-6 after two warmups; output normalized back to `Utf8`):\n\n| value bytes | NDV | `Utf8View` | dict/shared | vs view |\ndict/per-batch | vs view |\n|---:|---:|---:|---:|---:|---:|---:|\n| 16 | 1,000 | 50.29 ms | 43.48 ms | -13.5% | 43.52 ms | -13.5% |\n| 16 | 10,000 | 54.24 ms | 91.61 ms | +68.9% | 94.03 ms | +73.3% |\n| 64 | 1,000 | 72.65 ms | 47.02 ms | -35.3% | 47.69 ms | -34.4% |\n| 64 | 10,000 | 79.69 ms | 115.85 ms | +45.4% | 115.04 ms | +44.4% |\n\nThese are local measurements, not a proposed universal threshold. They\nshow why #24117 needs a cost decision based on absolute NDV and value\nwidth rather than a blanket dictionary rewrite. Runtime encoding also\nlost in every earlier measured case, which is why the planned optimizer\nwork targets native Parquet dictionary reads rather than inserting a\nruntime cast.\n\n## What changes are included in this PR?\n\n- Compare pre-encoded dictionaries, `Utf8View`, plain strings, and\nruntime dictionary casts.\n- Configure absolute NDV, value width, and input batch size.\n- Model shared dictionary values and independent per-batch values.\n- Optionally normalize dictionary group keys back to `Utf8` in the\noutput so output-type preservation is included in the measurement.\n- Preserve the existing default benchmark behavior and case names.\n- Reject invalid benchmark configurations instead of silently changing\nthe requested workload.\n- Verify that all encodings produce identical grouped counts.\n\nThis PR only establishes the benchmark surface needed to evaluate\n#24117; it does not add an optimizer rule or select a universal\nthreshold.\n\n## What is the testing strategy for this PR?\n\nOn rebased head `5fb605471`:\n\n- `cargo test -p datafusion-benchmarks --lib` (153 passed)\n- `cargo test -p datafusion-benchmarks --lib --no-default-features` (153\npassed)\n- `cargo clippy -p datafusion-benchmarks --all-targets --no-deps -- -D\nwarnings`\n- `cargo clippy -p datafusion-benchmarks --all-targets --all-features\n--no-deps -- -D warnings`\n- `cargo fmt --all -- --check`\n- Current-main CLI benchmark matrix above; every case returned exactly\nthe requested NDV\n\n## Are there any user-facing changes?\n\nNo DataFusion runtime or public API behavior changes. This only adds\nbenchmark CLI controls.\n\n---------\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "c1fdd6e7936be9b4b8ecc900236571e47834d2b0",
      "tree": "64ce0cd7215355060b6364d68cc4ab98612831b9",
      "parents": [
        "c89852c58e42b4f6f33e81053ce89df47ba34995"
      ],
      "author": {
        "name": "Yousef Mahmoud",
        "email": "yosefkhalil610@gmail.com",
        "time": "Wed Oct 14 03:45:55 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 03:45:55 2026 +0000"
      },
      "message": "perf: copy bitmaps a word at a time in `pre_selection_scatter` (#25494)\n\n## Which issue does this PR close?\n\n- N/A\n\n## Rationale for this change\n\n`pre_selection_scatter` puts the short-circuited RHS result back at full\nbatch length. For each run of selected rows it slices the RHS and\nappends one `Option\u003cbool\u003e` at a time, even though both sides are\nbit-packed, and every `slice` clones and drops an `Arc`.\n\nSince #25771, `AND` chains of cheap comparisons no longer reach this\nfunction, so TPC-H is unchanged. It still runs for `OR`, and for `AND`\nwith a conjunct that is not cheap.\n\nTPC-H SF30 `lineitem`, 24 threads, `l_quantity \u003e K or l_discount \u003e\n0.05`, by share of rows that reach the RHS:\n\n- 4%: 86.0ms -\u003e 82.0ms\n- 8%: 96.5ms -\u003e 89.5ms\n- 12%: 107.5ms -\u003e 96.0ms\n- 16%: 115.0ms -\u003e 102.0ms\n- 20%: 102.0ms -\u003e 92.0ms\n\n`l_quantity \u003c K and l_comment like \u0027%special%\u0027` is 1-2% faster. The 22\nTPC-H queries are within noise.\n\n## What changes are included in this PR?\n\nBorrow the RHS buffers once, copy each run with `append_packed_range`,\nand only build a validity bitmap when the RHS has nulls.\n\n## Are these changes tested?\n\nYes, by the existing tests, including `test_pre_selection_scatter`.\n\n## Are there any user-facing changes?\n\nNo.\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e"
    },
    {
      "commit": "c89852c58e42b4f6f33e81053ce89df47ba34995",
      "tree": "c6e9f3b9e65aa642c2297ba3b001ff1bb8bda026",
      "parents": [
        "44e5403be20fd61e1c601be6b75efd8e8514fa1c"
      ],
      "author": {
        "name": "Qi Zhu",
        "email": "zhuqilucas@gmail.com",
        "time": "Wed Oct 14 01:12:52 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Oct 14 01:12:52 2026 +0000"
      },
      "message": "perf(sort-merge): skip null checks in ArrayValues when neither cursor has nulls (#26215)\n\n## Which issue does this PR close?\n\n- Part of #23840. Second of the three units that umbrella PR was split\ninto; #23990 (the `RowValues` cache) was the first.\n\n## Rationale for this change\n\n`ArrayValues` wraps every sort-key cursor to add null handling, so its\n`compare` / `eq` / `eq_to_previous` sit in the merge\u0027s inner loop. Each\none opens with the same shape:\n\n```rust\nmatch (l.is_null(l_idx), r.is_null(r_idx)) {\n    (true, true) \u003d\u003e Ordering::Equal,\n    (true, false) \u003d\u003e ...,\n    (false, true) \u003d\u003e ...,\n    (false, false) \u003d\u003e T::compare(...),\n}\n```\n\nThat is two comparisons against `null_threshold` plus the match,\nevaluated once per comparison the loser tree makes.\n\nSort keys are usually null-free, and whether an array has any nulls is\nknown when the cursor is built (`array.null_count()`, already read there\nto compute `null_threshold`). When neither side has nulls, the match\nabove picks its `(false, false)` arm every single time.\n\n## What changes are included in this PR?\n\n- `ArrayValues` records `has_nulls: bool` at construction, from the\n`null_count` it already reads.\n- `compare`, `eq` and `eq_to_previous` take a direct path when no cursor\ninvolved has nulls, skipping the `is_null` checks.\n\n`has_nulls` is purely a shortcut around checks whose outcome is already\ndetermined; `is_null` still decides every case where a null can occur,\nso behaviour is unchanged.\n\nNot touched: `get_value` and `eq_to_single_row_value` also call\n`is_null`, but they are not in the merge\u0027s inner loop, so they keep the\nplain path rather than growing another branch.\n\n## Are these changes tested?\n\nYes. `test_array_values_has_nulls_fast_path_agrees_with_slow_path`\nbuilds two cursors over the *same* values: one null-free, so the fast\npath is taken, and one carrying a single extra null in the slot where\n`SortOptions` places nulls, so the null-aware path runs while every\nindex the test touches stays non-null. It then asserts `compare`, `eq`\nand `eq_to_previous` agree across all index pairs, both sort directions\nand both null placements.\n\nVerified by mutation — each of these fails the test:\n\n| Mutation | Caught by |\n|---|---|\n| fast-path `compare` ignores `options.descending` | `compare(0, 1)`,\n`descending: true` |\n| fast-path `compare` inverts `options.descending` | `compare(0, 1)`,\n`descending: false` |\n| fast-path `eq` returns `true` | `eq(0, 1)` |\n| fast-path `eq_to_previous` returns `true` | `eq_to_previous(1)` |\n\n`cargo test -p datafusion-physical-plan --lib sorts::` — 145 passed.\n`cargo clippy --all-targets -p datafusion-physical-plan -- -D warnings`\nclean.\n\n## Benchmark\n\nBenchmark bot, sort_tpch, this change in isolation:\n\n| Query | HEAD | branch | |\n|---|---|---|---|\n| Q1 | 125.16 ±0.91 ms | 111.10 ±1.27 ms | **+1.13x faster** |\n| Q2 | 106.91 ±1.55 ms | 97.74 ±1.30 ms | **+1.09x faster** |\n| Q3–Q11 | | | no change |\n\n2 faster, 0 slower, 0 failures.\n\nQ11 shows no change here, which is expected: the Q11 effect I measured\nearlier was for the full #23840 stack, where StringView cursor caching\nalone regressed Q11 by ~3% and this fast path moved it to -7.3%. On its\nown there is no such regression to recover.\n\n## Are there any user-facing changes?\n\nNo. No API change; `ArrayValues` is internal to the sort-merge cursors."
    },
    {
      "commit": "44e5403be20fd61e1c601be6b75efd8e8514fa1c",
      "tree": "7fde552f09b8fc1881c211d500c0f4f7a8f33c2b",
      "parents": [
        "2c568b478b3aff18de52609c7237f1c3f494d5b1"
      ],
      "author": {
        "name": "xudong.w",
        "email": "wxd963996380@gmail.com",
        "time": "Tue Oct 13 23:56:47 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 13 23:56:47 2026 +0000"
      },
      "message": "feat: simplify contradictory ranges across AND/OR predicates (#26132)\n\n## Which issue does this PR close?\n\n- Closes #26131.\n\n## Rationale for this change\n\nAn outer range can make every branch of an OR impossible, but the\nlogical optimizer currently considers the direct comparisons and the\ndisjunction independently. For example, `x \u003e\u003d 10 AND ((x \u003e\u003d 1 AND x \u003c 3)\nOR (x \u003e\u003d 5 AND x \u003c 7))` retains a scan despite never matching a row.\n\nThis matters for a `UNION ALL` containing historical backfill branches:\na request outside their time windows should eliminate those branches\nbefore physical planning calls their table providers, including when the\nquery has an outer `ORDER BY ... LIMIT`.\n\n## What changes are included in this PR?\n\n- Carry direct column/literal comparisons from enclosing conjunctions\ninto positive AND/OR descendants. Reuse the existing per-column\ncomparison simplifier to prove contradictions and remove impossible\ndisjuncts.\n- Retain the original assumption predicates. Do not infer through NOT,\ncasts, arbitrary functions, or across sibling OR branches. Bound\ncontextual analysis by depth and work limits without expanding\nexpressions into DNF.\n- Preserve predicate rewrites even when the number of conjuncts is\nunchanged, and report their transformation status when pushdown itself\nis unavailable. Preserve existing predicate order, including within OR\nbranches, when comparison grouping only permutes the conjuncts.\n- Convert an impossible filter directly into an `EmptyRelation` before\nprovider pushdown; an `Exact` provider must not absorb FALSE into its\nscan and still receive a `scan()` call.\n\n## What is the testing strategy for this PR?\n\n- `simplify_predicate_disjunctions.slt`: empty intersections, gaps,\npartial overlap, retained outer assumptions, equality/inequality\npredicates, NULL, NOT, casts, arithmetic, timestamp precision/time\nzones, and union branch removal with an outer sort/limit.\n- `simplify_predicates.slt`: existing regression coverage and an updated\nplan expectation for independently simplified OR arms.\n- A public API test with a provider whose `scan()` returns an error\nverifies that the eliminated union branch is never scanned under Exact,\nInexact, or Unsupported pushdown.\n- Unit tests cover conservative fallback when contextual analysis\nreaches its work/depth limits.\n- Existing `predicates.slt` and TPC-H Q19 plan/answer tests verify that\nunchanged OR branches retain their predicate order. The two CI failures\nwere due to predicate-order differences; their existing plan\nexpectations now pass without snapshot updates.\n\n\n\nAll checks above passed (`predicates.slt` also matches\n`simplify_predicates.slt`). TPC-H Q19 was additionally run with CI\u0027s\nSF0.1 data and a temporary SQL logic test wrapper including only its\ntable setup, plan, answer, and cleanup files. The full lint script used\nan isolated current `cargo-audit` and a temporary workspace boundary for\n`dev/depcheck` because this checkout is nested inside another Cargo\nworkspace. On the final lint run, `cargo-audit --no-fetch` used the\nadvisory database and registry index downloaded earlier the same day\nbecause local DNS could not resolve `index.crates.io`. No tooling or\nmanifest changes are included in the patch. Only targeted tests were\nrun, not the full workspace test suite.\n\n## Are there any user-facing changes?\n\nQueries with contradictory ranges across AND/OR can avoid planning and\nscanning impossible inputs. Partial simplification retains all matching\nrows. No public API or configuration changes.\n\nThis reasoning is specific to filter truth sets; it does not change\nnullable Boolean projection results or derive cross-column\ndate/timestamp equivalences.\n\n---------\n\nCo-authored-by: Jay Zhan \u003cjayzhan211@gmail.com\u003e"
    },
    {
      "commit": "2c568b478b3aff18de52609c7237f1c3f494d5b1",
      "tree": "17e0fde672add5ee0fe5c99925a455131065fc52",
      "parents": [
        "45de64cfc199345c8f218acd6d18634105403776"
      ],
      "author": {
        "name": "Alessandro Solimando",
        "email": "asolimando@apache.org",
        "time": "Tue Oct 13 06:29:47 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 13 06:29:47 2026 +0000"
      },
      "message": "perf: share one StatisticsContext across all physical optimizer rules (#26094)\n\n## Which issue does this PR close?\n\n- Part of #8227.\n- Related to #25141.\n\n## Rationale for this change\n\nEach physical optimizer rule that reads statistics creates its own\n`StatisticsContext`, so the statistics of the same plan nodes are\ncomputed again in every rule. `JoinSelection` creates a new context for\nevery `get_stats` call, so it has no caching at all, even within its own\npass.\n\n#25098 showed the gain of sharing one context inside\n`EnsureDistribution`. #25929 made cache entries keep the plan node they\nwere computed for, so a context can now be shared safely across plan\nrewrites. This PR uses that to share one `StatisticsContext` across all\nthe rules of one `optimize_physical_plan` call.\n\nOn TPC-DS (98 queries) and TPC-H (21 queries), sf1 Parquet, planned with\na local harness (not part of this PR):\n\n| | `main` | this PR |\n|---|---|---|\n| Statistics cache misses (statistics computed from scratch) | 46,022 |\n25,428 (-45%) |\n| Physical planning time, sum over all queries | 294.8 / 293.5 ms |\n274.3 / 279.7 ms (about -6%) |\n| Physical plans | | identical for all 119 queries |\n\nThe largest gain is TPC-DS q64: cache misses go from 3,785 to 531 and\nplanning time drops by about 21%.\n\n## What changes are included in this PR?\n\n- `StatisticsContext` stores its cache in a `parking_lot::Mutex` instead\nof `Rc\u003cRefCell\u003e`, so it is `Send + Sync`. This is needed because\n`PhysicalOptimizerContext: Send + Sync`. The lock is held only for\nsingle map lookups and inserts, never across the recursive walk. The\n`compute_statistics` benchmark shows no difference from `main` (all\ncases within ±4%, in both directions).\n- New `PhysicalOptimizerContext::statistics_context()`, which returns\n`None` by default. `DefaultPhysicalPlanner` creates one context per\n`optimize_physical_plan` call, built from the session\u0027s statistics\nregistry, and returns it to every rule.\n- `ConfigOnlyContext` also owns a `StatisticsContext`, so a rule called\nthrough `optimize()` shares one cache for its whole pass.\n- `JoinSelection`, `EnsureRequirements` (including\n`PlanSize::from_plan`), `AggregateStatistics` and `LimitPushdown` use\nthe shared context. When a context does not share one (for example, a\ncontext received through FFI), the rules create a new context from the\nstatistics registry, as they did before.\n- New default method `PhysicalOptimizerContext::compute_statistics`,\nwhich custom rules can call on the context they already receive. Without\nit, a custom rule would have to repeat the fallback itself (use the\nshared context, otherwise build one from `statistics_registry()`), and\nthe obvious shortcut, `StatisticsContext::new()`, does not consult the\nregistered statistics providers. With it, custom rules behave exactly\nlike the built-in ones.\n- The fallback itself is the public function `with_statistics_context`.\nRules that walk the plan (`EnsureRequirements`, `LimitPushdown`) use it\nto get one `StatisticsContext` for the whole traversal, so a fallback\ncontext still caches within the pass.\n- `pushdown_limit_helper` is deprecated in favour of the new\n`pushdown_limit_helper_with_stats`, which takes a `\u0026StatisticsContext`.\nThis is the same pattern as `ensure_distribution_with_stats`.\n- The shared cache keeps every plan node whose statistics were computed\nalive until `optimize_physical_plan` returns, including nodes that a\nlater rule replaces. Only the rules that read statistics add entries,\nand the memory is released at the end of physical planning.\n\n## What is the testing strategy for this PR?\n\n- New `optimizer_rules_share_statistics_context` test in\n`physical_planner.rs`: two rules compute the root statistics through the\nshared context, and the second one gets the `Arc` cached by the first.\n- Existing tests cover the rewired rules. All sqllogictests pass with no\nplan changes.\n\n## Are there any user-facing changes?\n\nNo breaking changes.\n\n- New default methods `PhysicalOptimizerContext::statistics_context()`\nand `PhysicalOptimizerContext::compute_statistics()`.\n- New public functions `datafusion_session::with_statistics_context` and\n`pushdown_limit_helper_with_stats`; `pushdown_limit_helper` is\ndeprecated. All are described in the 56.0.0 upgrade guide.\n- `StatisticsContext` is now `Send + Sync`.\n- `AggregateStatistics`, `LimitPushdown` and `PlanSize::from_plan` now\nconsult the session\u0027s statistics providers, as `JoinSelection` and\n`EnsureRequirements` already do. Without registered providers (the\ndefault), their results are unchanged.\n\n----\n\nDisclaimer: I used AI to assist in the code generation, I have manually\nreviewed the output and it matches my intention and understanding.\n\n---------\n\nCo-authored-by: Qi Zhu \u003czhuqilucas@gmail.com\u003e"
    },
    {
      "commit": "45de64cfc199345c8f218acd6d18634105403776",
      "tree": "facf9a25fec257f6acd588eb7890f257e18ecd35",
      "parents": [
        "9551051f13ee321eb0d41bf437f3718a138e12a2"
      ],
      "author": {
        "name": "Liang-Chi Hsieh",
        "email": "viirya@gmail.com",
        "time": "Tue Oct 13 02:11:10 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Oct 13 02:11:10 2026 +0000"
      },
      "message": "fix: reject date_bin strides that are not positive (#26070)\n\n## Which issue does this PR close?\n\n- Closes #25856.\n\n## Rationale for this change\n\n`date_bin` accepted negative strides, but they had no defined semantics:\n\n- A negative fixed stride rounds toward the origin, so a timestamp\nbefore the origin can land in a bin after it.\n- A negative month stride is not monotonic. `date_bin(INTERVAL \u0027-1\nmonth\u0027, ts, TIMESTAMP \u00272023-01-31\u0027)` bins 2023-01-01 to 2023-02-28 and\n2023-01-31 to itself.\n\n#25815 worked around the second one by not propagating ordering for\nnegative month strides. As discussed in #25856, `date_bin` now rejects\nstrides that are not positive. This matches PostgreSQL for fixed strides\n(PostgreSQL does not support month strides at all), and DataFusion\napplies the same rule to month strides. A positive stride already bins\ntimestamps before the origin, so a negative stride adds nothing, and an\nerror is better than silently taking the absolute value of an accidental\nnegative.\n\n## What changes are included in this PR?\n\n- `date_bin` returns `DATE_BIN stride must be greater than zero` for a\nstride that is not positive. This covers negative months, negative days\nor nanoseconds, intervals whose parts add up to a negative stride, and\nTIME inputs. The zero-stride error is folded into this message.\n- `output_ordering` no longer special-cases negative month strides: any\nconstant stride preserves the order of the source.\n- With only positive strides, `compute_distance` and\n`compute_distance_wide` round down with `rem_euclid`. For a positive\nstride this is the same as the old truncate-then-step-back logic, and\nthe two functions still match. Overflow near `i64::MIN` still returns an\nerror, which becomes NULL.\n- The `date_bin` docs say the interval must be greater than zero, and\nthe 56.0.0 upgrade guide describes the change.\n\n## What is the testing strategy for this PR?\n\n- `date_bin_errors.slt`: error cases for negative month, year, minute,\nday and nanosecond strides, an interval whose parts add up to a negative\nstride, scalar and column inputs at second and nanosecond precision, and\nTIME inputs. The `-1 nanosecond` case replaces the unit test for the\n`i64::MIN % -1` overflow from #22215, which can no longer be reached.\n- `timestamps.slt`: the negative-month ordering cases from #25815 are\nreplaced by the error tests above. The positive-month control stays, and\nthe zero-stride cases expect the new message.\n- Unit tests: `test_date_bin` covers negative `IntervalDayTime` strides,\nwhich SQL interval literals cannot produce.\n`output_ordering_requires_constant_stride` replaces\n`output_ordering_requires_monotonic_stride`.\n\n## Are there any user-facing changes?\n\nYes, this is a breaking change: a negative `date_bin` stride is now an\nerror. Previously it returned the same bins as the positive stride when\nthe source was at or after the origin (for month strides, only when the\nsource\u0027s day of month was not earlier than the origin\u0027s), and a bin\nlater than the source otherwise. The zero-stride error message also\nchanges. Both are documented in the 56.0.0 upgrade guide."
    },
    {
      "commit": "9551051f13ee321eb0d41bf437f3718a138e12a2",
      "tree": "048d6ba38d79b5802de7254ae672f56e63432773",
      "parents": [
        "39be5f279717206a96ab78c43ea9a6f07d58a1bd"
      ],
      "author": {
        "name": "Oleks V",
        "email": "comphead@users.noreply.github.com",
        "time": "Mon Oct 12 19:18:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 19:18:57 2026 +0000"
      },
      "message": "perf: pre-size collections and reuse per-iteration buffers (#26192)\n\n## Which issue does this PR close?\n\n- N/A\n\n## Rationale for this change\n\nMany execution paths allocate more than they need. Collections start\nempty although their final size is known, and some temporaries are\nallocated again on every row, batch, partition or column. Each case is\nsmall, but together they add avoidable allocator traffic on hot paths.\n\n## What changes are included in this PR?\n\nTwo mechanical rules applied across the workspace:\n- `with_capacity` where the size is known or tightly bounded by\nin-memory data.\n- Per-iteration temporaries hoisted out of loops and reused with\n`clear()` when they don\u0027t escape the iteration.\n\nFor example, `RepartitionExec` no longer allocates a `Vec` per batch per\noutput partition, `TDigest` merging reuses one buffer instead of a\nfull-size `Vec` per merge step, and hive-partitioned writes no longer\nbuild a `Vec\u003cString\u003e` key per row.\n\n## What is the testing strategy for this PR?\n\nNo behavior change, so existing tests cover it. The workspace `--lib\n--tests --bins` suite and sqllogictest pass locally. Criterion benches\nagainst `main` (`regexp_replace`, `reverse`, `array_slice`,\n`bounded_window`) are neutral to a few percent faster.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "39be5f279717206a96ab78c43ea9a6f07d58a1bd",
      "tree": "b2b5480f6ec3c0f049c62bbecb71cdbd876b660d",
      "parents": [
        "46bff840b93207dd270376a4fc2be7d9a009d216"
      ],
      "author": {
        "name": "Liang-Chi Hsieh",
        "email": "viirya@gmail.com",
        "time": "Mon Oct 12 18:52:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 18:52:27 2026 +0000"
      },
      "message": "fix(substrait): Preserve pushed-down table scan offsets and limits (#26035)\n\n## Which issue does this PR close?\n\n- Closes #26034.\n\n## Rationale for this change\n\nSubstrait roundtripping loses pushed-down TableScan offsets and limits\nwhen no parent Limit exists. A Projection between the scan and a parent\nLimit also bypasses the existing offset compensation, changing query\nresults.\n\n## What changes are included in this PR?\n\n- Encode a scan\u0027s skip/fetch in a FetchRel wrapping its ReadRel.\n- Serialize each parent Limit\u0027s own offset without adding the scan\noffset again.\n- Use checked conversions for scan offsets and fetch counts; values\nabove `i64::MAX` return an explicit unsupported-range error instead of\nbeing encoded as negative values.\n- Add execution-based roundtrip coverage for 96 combinations of scan\noffsets, fetch counts, optional projections, and parent limits,\nincluding zero limits and offsets beyond the input.\n\n## What is the testing strategy for this PR?\n\nVerified the offset-only regression against upstream\n60477917bd9eadd1a299185db6a8a08ccae7a4c7: the original scan returns [2,\n3, 4, 5], while the roundtripped scan incorrectly returns all six rows.\nThe new regression test passes with the fix. An additional regression\ntest verifies that the pushed-down fetch from `SELECT * FROM t LIMIT\n9223372036854775807 OFFSET 1` is rejected with an explicit\nunsupported-range error.\n\nPassed:\n- cargo fmt --all\n- cargo clippy --all-targets --all-features -- -D warnings\n- All Substrait integration tests: 227 passed, 6 ignored.\n- Required extended workspace tests: 12,388 passed, 0 failed, 8 ignored;\nall 526 SQLLogicTests files completed.\n- Contributor lint suite through formatting, its feature-specific Clippy\ncheck, TOML formatting, license headers, typos, documentation formatting\nand generation, workflow checks, large-file checks, Markdown links, and\nsecurity audit.\n- Rust documentation check.\n\nNo relevant local Substrait producer benchmark is defined.\n\n## Are there any user-facing changes?\n\nSubstrait roundtrips preserve pushed-down table-scan offsets and limits,\nincluding across projections and nested limits. No public API changes."
    },
    {
      "commit": "46bff840b93207dd270376a4fc2be7d9a009d216",
      "tree": "2fec1dbed6d1fc18abe7fd8b1dc34da6cb40550f",
      "parents": [
        "e7d99712c0127925c509c94eb48a1101dde2e96d"
      ],
      "author": {
        "name": "Ignatius Pang",
        "email": "2321366+IgnatiusPang@users.noreply.github.com",
        "time": "Mon Oct 12 18:23:25 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 18:23:25 2026 +0000"
      },
      "message": "fix(functions): prevent invalid sort omission in log monotonicity when base \u003c\u003d 1 (#25746)\n\n## Rationale for this change\n\nIn `LogFunc::output_ordering`, DataFusion previously assumed that\n$\\log_{\\text{base}}(x)$ always preserves sort order. However:\n$$\\frac{\\partial}{\\partial x} \\log_b(x) \u003d \\frac{1}{x \\ln(b)}$$\n- For $\\text{base} \u003e 1.0$: $\\ln(b) \u003e 0 \\implies$ order is preserved\n(increasing).\n- For $\\text{base} \\in (0, 1)$ (e.g. constant $0.5$): $\\ln(b) \u003c 0\n\\implies$ order is **inverted** (strictly decreasing).\n\nWithout interval checking, the physical optimizer assumes that rows\ncomputed with `log(0.5, x)` are already sorted in ascending order if `x`\nwas sorted ascending, eliminating the necessary `SortExec` operator and\nsilently returning rows in descending order to the user.\n\n\n## What changes are included in this PR?\n\n1. `datafusion/functions/src/math/log.rs`: `LogFunc::output_ordering`\nnow only reports an ordering when the base is provably `\u003e 1`. When both\nbase and argument vary, the argument must also be provably `\u003e 1`.\nOtherwise it returns `SortProperties::Unordered`.\n2. `datafusion/sqllogictest/test_files/order.slt`: updated the expected\nplans for `log(c12, c11)` and `log(c11, c12)`. Both columns are in `(0,\n1)`, so the sort can\u0027t be removed there. Added regression tests for\n`log(0.5, x)`, plus `log(2.0, x)` to show the optimization still applies\nwhen the base is greater than 1.\n\n## Reproducer\n\n```sql\nSELECT log(0.5, x) AS l\nFROM (SELECT x FROM (VALUES (1.0), (2.0), (4.0), (8.0)) AS t(x) ORDER BY x LIMIT 10)\nORDER BY l ASC;\n```\n\nOn `main` this returns `0, -1, -2, -3`: the optimizer drops the outer\nsort because it assumes `log` keeps the input order. With this PR it\nreturns `-3, -2, -1, 0`.\n\n## What is the testing strategy for this PR?\n\n- New sqllogictest cases in `order.slt` (plan and results) for the\nreproducer above, and for `log(2.0, x)` to confirm the sort is still\nremoved when the base is greater than 1.\n- Unit tests in `math/log.rs` covering bases in `(0, 1)` and bases with\nunknown bounds.\n\n---------\n\nCo-authored-by: ignatiuspang \u003cIgnatiusPang@users.noreply.git.com\u003e\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "e7d99712c0127925c509c94eb48a1101dde2e96d",
      "tree": "6bdfe1b5487f51128e108375410b22fbd212cda7",
      "parents": [
        "4ab4721fbfa7ed5c9adac59958c6eec2b0bacf4e"
      ],
      "author": {
        "name": "Adrian Garcia Badaracco",
        "email": "1755071+adriangb@users.noreply.github.com",
        "time": "Mon Oct 12 18:22:20 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 18:22:20 2026 +0000"
      },
      "message": "fix: do not extract common subexpressions from the arguments of an aggregate with a FILTER (#26184)\n\n## Which issue does this PR close?\n\n- Closes #26183.\n\n## Rationale for this change\n\nAn aggregate with a `FILTER` clause evaluates its arguments only for the\nrows that pass the filter, so a fallible argument does not fail on a\nrejected row.\nWhen two aggregates have the same argument, `CommonSubexprEliminate`\nmoves that argument into a projection below the aggregate.\nThe projection evaluates it for every row, and the query fails on a row\nthat the filter rejects:\n\n```sql\nCREATE TABLE t AS\nSELECT * FROM (VALUES (CAST(-950 AS SMALLINT), 0), (CAST(5 AS SMALLINT), 1)) AS v(x, y);\n\n-- Succeeds.\nSELECT avg(arrow_cast(x, \u0027UInt64\u0027)) FILTER (WHERE y \u003e 0) AS a FROM t;\n\n-- Fails: Arrow error: Cast error: Can\u0027t cast value -950 to type UInt64\nSELECT\n    sum(arrow_cast(x, \u0027UInt64\u0027)) FILTER (WHERE y \u003e 0) AS s,\n    count(arrow_cast(x, \u0027UInt64\u0027)) FILTER (WHERE y \u003e 0) AS c\nFROM t;\n```\n\nThe rule already has a model for this: a conditionally evaluated\nsubexpression (a `CASE` branch, the right side of `AND` / `OR`, a lazy\nfunction argument) is extracted only if it is also surely evaluated\nsomewhere else.\nThe arguments of a filtered aggregate are conditionally evaluated in the\nsame sense, but the rule did not know that.\n\n## What changes are included in this PR?\n\n1. `ExprCSEController::conditional_children` now reports the arguments\nand the `ORDER BY` expressions of an `Expr::AggregateFunction` with a\n`FILTER` as conditionally evaluated.\nThe filter itself stays a normal child, because the aggregate evaluates\nit for every row.\n   A filter that several aggregates share is still extracted.\n2. The same function reports the arguments of an `Expr::WindowFunction`\nwith a `FILTER` as conditionally evaluated.\nThe `PARTITION BY` expressions, the `ORDER BY` expressions and the\nfilter stay normal children.\nThe window executor does not yet evaluate the filter first (#24507,\n#24508), so this part has no visible effect today.\n   It keeps the rule correct when that fix merges.\n3. `CSEVisitor::f_down` in `datafusion/common/src/cse.rs` now visits the\nchildren of a node with conditional children in tree order.\nBefore, it visited all normal children and then all conditional\nchildren.\n`CSERewriter` reads `id_array` in pre-order, so that was correct only\nwhen every normal child came before every conditional child in the tree.\nThe children of an aggregate are `args`, `filter`, `order_by`, so the\nnormal child is in the middle.\n   The `CSEController` trait is unchanged.\n\nThe rule keeps every extraction that is safe:\n\n| Query shape | Before | After |\n|---|---|---|\n| `sum(f(x)) FILTER (WHERE p), count(f(x)) FILTER (WHERE p)` | `f(x)`\nand `p` extracted | only `p` extracted |\n| `sum(f(x)) FILTER (WHERE p), count(f(x))` | `f(x)` extracted | `f(x)`\nextracted (the second aggregate evaluates it for every row) |\n| `sum(f(x)) FILTER (WHERE f(x) \u003e 0)` | `f(x)` extracted | `f(x)`\nextracted (the filter evaluates it for every row) |\n| `sum(f(x)) FILTER (WHERE p) AS a, sum(f(x)) FILTER (WHERE p) AS b` |\none aggregate | one aggregate |\n\nThe cost is the first row: when an expression occurs only under filtered\naggregates, each aggregate now evaluates it, on the rows that pass its\nfilter.\nAn alternative keeps that extraction when every aggregate has the same\nfilter, with a guard such as `CASE WHEN p THEN f(x) END` in the\nprojection.\nI did not do that here because it is a larger change with its own plan\nshape, and it can be a follow-up.\n\n## What is the testing strategy for this PR?\n\n- Unit tests in `common_subexpr_eliminate.rs`:\n`test_aggregate_filter_arguments` (the four rows of the table above),\n`test_aggregate_filter_order_by` and `test_window_filter_arguments`.\n- `cse.slt`: the reproduction above, with and without `GROUP BY`, the\n`EXPLAIN` that shows the cast stays in the aggregate, and the case where\nan unfiltered aggregate shares the argument.\n- `aggregates_simplify.slt`: one expected plan changes. `SUM(column1 +\n1) FILTER (WHERE column1 \u003e 1), SUM(column1 + 1) FILTER (WHERE column1 \u003e\n0)` no longer extracts `column1 + 1`.\n\n## Are there any user-facing changes?\n\nQueries that failed with an error from a row that an aggregate `FILTER`\nrejects now succeed.\nPlans for queries where a subexpression occurs only in the arguments of\nfiltered aggregates no longer have that subexpression in a\n`__common_expr` projection.\nThere are no API changes."
    },
    {
      "commit": "4ab4721fbfa7ed5c9adac59958c6eec2b0bacf4e",
      "tree": "9423d28134c0ee4fee423489ba1959ffb9abfe0d",
      "parents": [
        "6663e4348049cc7b70109c9e0f8e39049794ea23"
      ],
      "author": {
        "name": "Bruce Ritchie",
        "email": "bruce.ritchie@gmail.com",
        "time": "Mon Oct 12 18:14:05 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 18:14:05 2026 +0000"
      },
      "message": "feat(benchmarks): enable Criterion automatically when a benchmark namespace is set (#26210)\n\n## Is your feature request related to a problem or challenge?\n\nRunning a SQL benchmark with `--criterion-namespace` or\n`BENCH_NAMESPACE` currently requires a separate `--criterion` flag.\nSince namespaces apply to Criterion benchmark groups, selecting a\nnamespace should also select Criterion mode.\n\n## Describe the solution you\u0027d like\n\nEnable Criterion when either namespace option is set. Apply the existing\nmode checks after inferring Criterion mode, so incompatible `--output`\nand `--iterations` options still fail and `--save-baseline` works. Print\nthe inferred-mode notice to stderr to preserve stdout output.\n\n## Describe alternatives you\u0027ve considered\n\nKeeping the explicit `--criterion` requirement would preserve the\ncurrent behavior but require callers to specify both options.\n\n## Additional context\n\nThis follows the SQL benchmark migration preparation in #24806.\n\n## Willingness to contribute\n\nImplementation included in this draft PR.\n\n## Which issue does this PR close?\n\n  - Part of #21706.\n  - Prepares for #24311 and #24312.\n  - This PR does not close these issues.\n\n## Rationale for this change\n\nAllow benchmark callers to select namespaced Criterion runs with a\nsingle option or environment variable.\n\n## What changes are included in this PR?\n\n- Infer Criterion mode from `--criterion-namespace` and\n`BENCH_NAMESPACE` and update the CLI help.\n- Share namespace validation between the CLI and the Criterion runner.\n- Extend CLI tests for inferred mode, environment defaults, CLI\noverrides, list and dry-run behavior, conflicting options, saved\nbaselines, and stderr notices.\n\n## What is the testing strategy for this PR?\n\nThe benchmark-runner tests exercise argument parsing and environment\nhandling, including a subprocess test for `BENCH_NAMESPACE`. Existing\ntests cover invalid namespaces and distinct Criterion artifacts.\n\n## Are there any user-facing changes?\n\nYes. `--criterion-namespace` and `BENCH_NAMESPACE` now enable Criterion\nwithout an explicit `--criterion` flag. The runner reports inferred mode\non stderr."
    },
    {
      "commit": "6663e4348049cc7b70109c9e0f8e39049794ea23",
      "tree": "a6738874321762a555bc954953dfe6107c63a83c",
      "parents": [
        "2951e1271e949b84aff34c1aef4f5f2e28339ed8"
      ],
      "author": {
        "name": "Michal Piatkowski",
        "email": "291740709+MassivePizza@users.noreply.github.com",
        "time": "Mon Oct 12 07:56:31 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 07:56:31 2026 +0000"
      },
      "message": "perf: Concretely typed TopK StringHeap, and StringHashTable slot reuse (#24105)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\nN/A.\n\nContinuation of https://github.com/apache/datafusion/pull/23609.\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n--\u003e\nImprove perf of TopK.\n\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\nEliminate overhead of casting with `dyn Any` for every String in\n`topk::StringHeap`.\n\nRearrange `HashTableItem\u003cID\u003e` `Option`-ness to avoid unnecessary unwraps\non lookups in `topk::TopKHashTable`.\nRewrite inserts to take a borrowable type, delaying clones and allowing\nreuse of storage slots (mostly Strings).\n\n## Are these changes tested?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nIf tests are not included in your PR, please explain why (for example,\nare they covered by existing tests)?\n--\u003e\nShould be covered by existing tests.\n\nMaking `ID` an `Option\u003cID\u003e` inside `HashTableItem` should be fine, since\nthe internal `HashTable` keeps track of valid items (although this could\nbe hard to verify properly). It runs with the assumption that \"if\neverything needed an unwrap, nothing needs an unwrap\".\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n--\u003e\nNo.\n\n\u003c!--\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e\n\n---------\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "2951e1271e949b84aff34c1aef4f5f2e28339ed8",
      "tree": "08df33e67954f6b064fc855425c797dfe424d4d5",
      "parents": [
        "e6a11e5f1dd5a19e5f76d3fb12393fe89d43b680"
      ],
      "author": {
        "name": "Nuno Faria",
        "email": "nunofpfaria@gmail.com",
        "time": "Mon Oct 12 07:27:07 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 07:27:07 2026 +0000"
      },
      "message": "fix: Unparse `random` as `rand` for some dialects (#26009)\n\n## Which issue does this PR close?\n\n- Closes #26008.\n\n## Rationale for this change\n\nGenerate valid SQL for the dialects that do not support the `random()`\nfunction\n\n## What changes are included in this PR?\n\n- Updated the MySQL and BigQuery dialects.\n\n## What is the testing strategy for this PR?\n\nUnit test.\n\n## Are there any user-facing changes?\n\nNo.\n\n---------\n\nCo-authored-by: Martin Grigorov \u003cmartin-g@users.noreply.github.com\u003e\nCo-authored-by: Martin Tzvetanov Grigorov \u003cmgrigorov@apache.org\u003e"
    },
    {
      "commit": "e6a11e5f1dd5a19e5f76d3fb12393fe89d43b680",
      "tree": "2efc26eaab6cf6bdc175b909e2c8312f2e612179",
      "parents": [
        "de0665699724e170e2f04fe83ce27835bcc66b9b"
      ],
      "author": {
        "name": "Huaijin",
        "email": "haohuaijin@gmail.com",
        "time": "Mon Oct 12 07:26:15 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 07:26:15 2026 +0000"
      },
      "message": "chore(optimizer): remove deprecated `supports_rewrite` (#26180)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\nno related issue\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\n`OptimizerRule::supports_rewrite` has been deprecated since DataFusion\n47.0.0 and is no longer called by the optimizer. Its deprecation exceeds\nboth the six-major-version and six-month retention periods in the [API\nhealth\npolicy](https://datafusion.apache.org/contributor-guide/api-health.html#deprecation-guidelines).\n\n\n## What changes are included in this PR?\n\nremove `OptimizerRule::supports_rewrite` \n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e"
    },
    {
      "commit": "de0665699724e170e2f04fe83ce27835bcc66b9b",
      "tree": "f5b76513638e1a5a12421d7976d8c742053f5d14",
      "parents": [
        "b295a672ce6fcef216c94aaca88987c98449803c"
      ],
      "author": {
        "name": "Andrew Lamb",
        "email": "andrew@nerdnetworks.org",
        "time": "Mon Oct 12 06:38:14 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 06:38:14 2026 +0000"
      },
      "message": "docs: Add distributed DataFusion blog post to readings page (#26206)\n\n## Which issue does this PR close?\n\nN/A\n\n## Rationale for this change\n\nDatadog / @gabotechs published a blog post on how they extended\nDataFusion to run a single query across many machines. It is a good\nresource for the community and is not yet listed on the readings page.\n\n## What changes are included in this PR?\n\nAdd a link to [How we extended Apache DataFusion to execute one query\nacross many\nmachines](https://www.datadoghq.com/blog/engineering/distributed-datafusion/)\n(2026-10-01) to the \"Blog Posts\" list in\n`docs/source/user-guide/concepts-readings-events.md`.\n\n## Are these changes tested?\n\nCI\n\n## Are there any user-facing changes?\n\nDocumentation only.\n\nCo-authored-by: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "b295a672ce6fcef216c94aaca88987c98449803c",
      "tree": "3801cfdb2c462de67d10920d6f967aaf5e795e7e",
      "parents": [
        "b40ef06a7aaacd7adec278eb8130202d2304326f"
      ],
      "author": {
        "name": "Qi Zhu",
        "email": "zhuqilucas@gmail.com",
        "time": "Mon Oct 12 01:50:51 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Oct 12 01:50:51 2026 +0000"
      },
      "message": "fix: infer a Parquet column as nullable when some files lack it (#26104)\n\n## Which issue does this PR close?\n\n- Closes #26103\n\n## Rationale for this change\n\n`ListingTable` schema inference over Parquet merges the per-file schemas\nwith `Schema::try_merge`, which widens nullability only for fields that\nappear in more than one schema. A column that is `required` in some\nfiles and absent from the others therefore comes out `NOT NULL`, but\nreading the files without it fills it with nulls, and the scan fails:\n\n```\nArrow error: Invalid argument error: Column \u0027c\u0027 is declared as non-nullable but contains null values\n```\n\nPure SQL reproducer (on `main`):\n\n```sql\nCOPY (SELECT 1 AS id, 10 AS c) TO \u0027/tmp/evo/a.parquet\u0027;\nCOPY (SELECT 2 AS id)          TO \u0027/tmp/evo/b.parquet\u0027;\nCREATE EXTERNAL TABLE t STORED AS PARQUET LOCATION \u0027/tmp/evo/\u0027;\nSELECT * FROM t;  -- fails; DESCRIBE shows c Int64 NO\n```\n\nBefore DataFusion 52 this was masked by `SchemaAdapter::map_batch`,\nwhich rebuilt batches under the table schema without validating\nnullability (removed in #18998). The strict check is right; the inferred\nschema is what is wrong.\n\n## What changes are included in this PR?\n\nIn `ParquetFormat::infer_schema`, count in how many files each top-level\nfield appears and, after the merge, mark every field that is missing\nfrom at least one file as nullable. Fields present in every file keep\nwhatever `try_merge` produced, so tables whose files all share a schema\nare unchanged.\n\n## Are these changes tested?\n\n- New `schema_evolution.slt` case: two `COPY TO` files, `CREATE EXTERNAL\nTABLE` without a schema, `DESCRIBE` shows the partial column as\nnullable, `SELECT` returns the null. Fails on `main` with the error\nabove.\n- New `schema_merge_marks_partially_present_columns_nullable` in\n`core/tests/parquet/schema.rs`: three files, column in a different\nposition, an already-nullable partial column, and both `skip_metadata`\npaths.\n\n## Are there any user-facing changes?\n\nAn inferred Parquet table schema now reports a column as nullable when\nsome files do not contain it. Tables where every file has every column\nare unaffected. Explicitly declared schemas are not touched."
    },
    {
      "commit": "b40ef06a7aaacd7adec278eb8130202d2304326f",
      "tree": "50bd0ab90e6c9c74f6cb3f3c8f93fbce39a01774",
      "parents": [
        "454ca08b43fd8bb83362f575750850d5745ddee3"
      ],
      "author": {
        "name": "RIchard Baah",
        "email": "137434454+Rich-T-kid@users.noreply.github.com",
        "time": "Sun Oct 11 22:01:47 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Oct 11 22:01:47 2026 +0000"
      },
      "message": "perf: speed up DictionaryArray hashing (#26159)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #26168.\n\n## Rationale for this change\n\nsee issue, the cost for hashing dictionary arrays comes down to a\nwriting corresponding values to their key indices, we can speed this up\nwith branchless code.\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\n## What changes are included in this PR?\n\nRewrites the scatter as four const-generic specializations:\n- 8-way unrolled gather for the no-nulls case\n- single-check loop for nullable values\n- 64-key bitmask-driven path for nullable keys (branchless gather+csel\nfor\n  valid values, `trailing_zeros` bit-walk otherwise)\n- scalar tail for non-multiple-of-64 lengths\n\n\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n## What is the testing strategy for this PR?\n\nexisting test cover this path\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\nno\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e"
    },
    {
      "commit": "454ca08b43fd8bb83362f575750850d5745ddee3",
      "tree": "3b21b0d82daac5ba92becc2a28023300ef21e78e",
      "parents": [
        "75ddead2b765ff6c574c4cc989538fabcf250c9f"
      ],
      "author": {
        "name": "Vova Kot",
        "email": "volodymyr.kot.ua@gmail.com",
        "time": "Sun Oct 11 13:22:25 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Oct 11 13:22:25 2026 +0000"
      },
      "message": "fix(spark): derive concat_ws nullability from separator (#26205)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\nPart of the work towards\nhttps://github.com/apache/datafusion/issues/15914\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\n`concat_ws` return value is always nullable in DF, which is incorrect.\nPer upstream Spark implementation, this is only true when separator\nitself is null.\n\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\nDerive the nullability based on the separator nullability.\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\nAdd SLT tests for schema.\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e\n\nI believe this doesn\u0027t count as an API change but would like guidance\nfrom a committer."
    },
    {
      "commit": "75ddead2b765ff6c574c4cc989538fabcf250c9f",
      "tree": "4c81630d411de861305161280d4bca9e02e8fb20",
      "parents": [
        "a4b8198cfa2419394df966f815d284e745f06653"
      ],
      "author": {
        "name": "kosiew",
        "email": "kosiew@gmail.com",
        "time": "Sun Oct 11 09:12:07 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Oct 11 09:12:07 2026 +0000"
      },
      "message": "Deprecate CsvSource::newlines_in_values and preserve proto coverage (#26179)\n\n## Which issue does this PR close?\n\n- Part of #24612\n\n## Rationale for this change\n\nDeprecate `CsvSource::newlines_in_values()` as part of the CSV API\ncleanup while preserving compatibility and existing CSV serialization\nbehavior.\n\nThe getter simply returns\n`CsvOptions.newlines_in_values.unwrap_or(false)`. There is no\nreplacement getter, so callers should retain their original `CsvOptions`\nwhen they need to inspect this setting.\n\nThe public getter remains callable during the deprecation window, and\nCSV reading and repartitioning behavior are unchanged.\n\n## What changes are included in this PR?\n\n- Mark `CsvSource::newlines_in_values()` as deprecated starting in\n56.0.0, with an accurate migration note.\n- Replace the internal encoder\u0027s getter call with\n`self.options.newlines_in_values.unwrap_or(false)`, preserving the\nexisting boolean mapping.\n- Extend `roundtrip_csv_scan_preserves_format_options` to cover\n`Some(true)`, `Some(false)`, and `None`.\n- Assert the protobuf `CsvScan.newlines_in_values` field after\nround-tripping the physical plan, while retaining all existing CSV\nformat-option assertions.\n- Preserve malformed terminator validation for empty and two-byte\nterminators.\n- Document the deprecation and migration guidance in the 56.0.0 upgrade\nguide.\n\nNo protobuf wire-format changes or new public APIs are introduced.\n\n## Are these changes tested?\n\nExtended `roundtrip_csv_scan_preserves_format_options` to verify:\n\n- `Some(true)` serializes as `true`.\n- `Some(false)` serializes as `false`.\n- `None` serializes as `false`.\n- Existing CSV format options, including delimiter, quote, escape,\ncomment, terminator, truncated rows, header, and GZIP compression,\nsurvive the round-trip.\n- Invalid zero-byte and two-byte terminators continue to produce\ndecoding errors.\n\nThe patch includes these regression tests, but does not establish\nwhether they have been executed successfully.\n\nRecommended verification commands:\n\n```bash\ncargo test -p datafusion-proto --test proto_integration roundtrip_csv_scan_preserves_format_options\ncargo test -p datafusion-datasource-csv\ncargo fmt --all\ncargo clippy --all-targets --all-features -- -D warnings\n./ci/scripts/doc_prettier_check.sh --write --allow-dirty\n```\n\n## Are there any user-facing changes?\n\n`CsvSource::newlines_in_values()` is deprecated starting in 56.0.0 but\nremains callable with unchanged behavior.\n\nExisting callers may receive deprecation warnings, potentially affecting\ndownstream builds that treat warnings as errors.\n\nThere is no replacement getter. Callers should retain the `CsvOptions`\nused to configure the source and read\n`options.newlines_in_values.unwrap_or(false)`.\n\nThe 56.0.0 upgrade guide documents this migration.\n\nCSV parsing, repartitioning, and protobuf serialization behavior are\nunchanged.\n\n## LLM-generated code disclosure\n\nThis PR includes LLM-generated code and comments. All LLM-generated\ncontent has been manually reviewed."
    },
    {
      "commit": "a4b8198cfa2419394df966f815d284e745f06653",
      "tree": "f4bedac8eaad58b16a7f88af6d765f7fdf711ad8",
      "parents": [
        "aaf5df1db1f9fb5e56c3f2912f712bb222929202"
      ],
      "author": {
        "name": "Liang-Chi Hsieh",
        "email": "viirya@gmail.com",
        "time": "Sat Oct 10 22:33:53 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 22:33:53 2026 +0000"
      },
      "message": "fix: handle dictionary nulls in null-aware left mark joins (#25693)\n\n## Which issue does this PR close?\n\n- Closes #25691.\n\n## Rationale for this change\n\nNull-aware `LeftMark` joins use physical null checks for dictionary\nkeys. They miss valid dictionary keys that point to `NULL` dictionary\nvalues and return `FALSE` marks where SQL three-valued logic requires\n`NULL`.\n\n## What changes are included in this PR?\n\nNull-aware `LeftMark` joins now use Arrow\u0027s logical-null APIs on both\nprobe and build keys. The build-side logical-null bitmap is computed\nonce during build collection, retained with memory accounting, and\nreused by final output chunks. Probe-side null summaries are computed\nonce per input batch even when hash lookup resumes across several\nchunks. Correlated joins continue using their precomputed per-row null\nbitmap.\n\n## What is the testing strategy for this PR?\n\nThe diff adds three `HashJoinExec` test functions covering logical\ndictionary nulls on the build and probe sides, including nested\ndictionary build keys. `#[apply(hash_join_exec_configs)]` expands each\nfunction across five batch sizes, so Cargo reports 15 new test\ninstances. The probe-side function also checks both probe-partition\ncompletion orders inside each instance.\n\nAblation testing confirmed that the original build- and probe-side\nfunctions fail at every batch size without the correctness fix. With the\nfix, all 109 null-aware tests and the complete 2,409-test\n`datafusion-physical-plan` all-features suite pass.\n\nFor 524,288-row debug diagnostics, bounding the original flat-dictionary\nscan reduced runtime from about 693ms to 141ms. The follow-up\nnested-dictionary diagnostic dropped from about 561ms to 177ms, and the\noversized resumed-probe diagnostic dropped from about 1.29s to 910ms.\n\n## Are there any user-facing changes?\n\nNull-aware mark joins over dictionary-encoded keys now return the\ncorrect nullable marks. There are no public API changes."
    },
    {
      "commit": "aaf5df1db1f9fb5e56c3f2912f712bb222929202",
      "tree": "578b5e4496b2f5dbcc88e1bca507fa2da9004dc3",
      "parents": [
        "334f29317c1040cc83ee0dd2954562f4fb3ba257"
      ],
      "author": {
        "name": "Subham Singhal",
        "email": "SubhamSinghal@users.noreply.github.com",
        "time": "Sat Oct 10 20:02:39 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 20:02:39 2026 +0000"
      },
      "message": "perf(pwmj):settle never-matching streamed rows against the buffered extreme… (#25840)\n\n## Which issue does this PR close?\n\n- Part of #18221 (and the PWMJ epic #17427).\n\nIt doesn\u0027t close #18221. On the issue\u0027s 100K × 100K shape, the join\u0027s\ntime goes to its huge output, so this change leaves it about the same.\nSee the benchmarks below.\n\n## Rationale for this change\n\nThe classic `PiecewiseMergeJoin` stream (`INNER` / `LEFT` / `RIGHT` /\n`FULL`) sorts each streamed batch, then walks the sorted buffered side\nrow by row to find each streamed row\u0027s first match. Two costs are\navoidable:\n\n- **Rows that can\u0027t match anything still pay full price.** They are\nsorted, gathered and walked through the buffered side like every other\nrow. This covers keys below every buffered key for `\u003c`, and NULL keys.\nWhen most streamed rows can\u0027t match, which is common for a selective\nrange predicate, the operator does all this work and outputs nothing for\nthem.\n- **The first match is found by a linear walk.** Every match set is a\nsuffix `[k, len)` of the sorted buffered side, so `k` can be found with\na binary search instead of stepping over every non-matching buffered\nrow.\n\n## What changes are included in this PR?\n\nAll changes are in `joins/piecewise_merge_join/`, plus a new benchmark.\n\n- **Rows that can\u0027t match are removed before the sort\n(`classic_join.rs`).** Because every match set is a suffix, a streamed\nrow matches anything at all only if it matches the last buffered key.\n- One vectorized comparison against that key, cached once when the\nbuffered side is ready, finds those rows.\n- They are emitted as unmatched rows for `Right`/`Full` and dropped for\n`Inner`/`Left`. Only the remaining rows are sorted, gathered and\nscanned.\n- When no rows were removed, the path is unchanged except for that one\ncomparison per batch. When some were, the sort indices are mapped back\nto positions in the batch, so it is still gathered only once.\n- An empty buffered side, or one whose keys are all NULL, short-circuits\nwithout the comparison.\n- **The comparison must agree exactly with the scan, or it would change\nresults.**\n- Flat keys use one `apply_cmp`, which normalizes `-0.0`/`+0.0` just as\nthe scan\u0027s `JoinKeyComparator` does.\n- Nested keys are decided with the scan\u0027s own comparator. `apply_cmp`\norders NULL elements inside a key ascending, while the comparator\napplies the sort options, descending for `\u003c`/`\u003c\u003d`, at every nesting\nlevel.\n- The scan\u0027s nested ordering for `\u003c`/`\u003c\u003d` gives different results from\n`NestedLoopJoinExec` when keys contain NULL elements. That is a\npre-existing bug on `main`, which I\u0027ll file and fix separately. This PR\nkeeps PWMJ\u0027s current results unchanged.\n- **Binary search for each row\u0027s first match (`utils.rs`).**\n- `first_match(lo, hi, matches)` replaces the linear walk in\n`resolve_classic_join`.\n- It searches `[previous row\u0027s match, len)`. The streamed batch is\nsorted, so each row\u0027s first match is at or after the previous row\u0027s.\n- The existence stream already did an inline binary search. It now calls\nthe same helper, with no change in behavior.\n- The operator dispatch moves into two small helpers, `matches_on_equal`\nand `is_match`, used by both streams.\n- **Streamed NULL keys never reach the scan now,** since the new\npre-sort step removes them. The scan\u0027s streamed-NULL skip was dead code\nand is replaced by a `debug_assert`. The buffered-side NULL skip stays.\n\n### Benchmarks\n\nThe `pwmj` suite from #25839 (100K buffered keys, 2M streamed rows, five\nmatch regimes × `INNER`/`LEFT`/`RIGHT`/`FULL`). Reproduce with:\n\n```\ncargo run -p datafusion-benchmarks --release --bin benchmark_runner -- pwmj\n```\n\n| regime | `main` (median) | Inner | Left | Right | Full |\n|---|---|---|---|---|---|\n| `no_match`: no streamed row matches | 47–50 ms | −95.9% (25×) | −95.9%\n(24×) | −94.0% (17×) | −93.7% (16×) |\n| `null_heavy`: half NULL, rest `no_match` | 45–50 ms | −95.7% (23×) |\n−95.7% (23×) | −94.0% (17×) | −93.7% (16×) |\n| `half_match`: half `no_match`, half `selective` | 371–375 ms | −9.2% |\n−8.7% | −8.2% | −8.4% |\n| `selective`: every row matches the 1–4 smallest buffered keys |\n694–699 ms | −2.9% | −3.9% | −3.6% | −3.2% |\n| `all_match`: every row matches every buffered key | 162–163 ms | +0.1%\n| −0.6% | −0.0% | +0.3% |\n\n## What is the testing strategy for this PR?\n\n- `first_match_agrees_with_linear_scan` (`utils.rs`): exhaustive over\nevery range, answer and start position up to 40. It checks the result\nagainst a linear scan and bounds the number of comparisons by `⌈log2(hi\n− lo + 1)⌉`.\n- `matchable_rows_agrees_with_scan` (`classic_join.rs`): the pre-sort\ncheck against a brute-force version of the scan\u0027s own definition of a\nmatch. It covers 12 key types, 4 operators, and a normal, all-NULL and\nempty buffered side.\n- The key types: Int32, Float64 with `±0.0`/NaN/`±inf`, Utf8, Utf8View,\nBinary, Dictionary, Decimal128, Date32, Timestamp, Boolean, and two List\ncases with NULL elements.\n  - With the nested-key branch removed, this test fails.\n- `join_right_less_than_signed_zero_prefilter_agrees_with_scan`: end to\nend with `-0.0`/`+0.0` keys.\n- Existing tests:\n  - all PWMJ unit tests;\n- the NLJ differential fuzz test `fuzz_pwmj_matches_nested_loop`\n(`--features extended_tests`), covering Inner/Left/Right/Full, NULL\nkeys, small batches and multiple partitions;\n  - the PWMJ and join sqllogictests.\n\n## Are there any user-facing changes?\n\nNo API or configuration changes."
    },
    {
      "commit": "334f29317c1040cc83ee0dd2954562f4fb3ba257",
      "tree": "7e3d99cbefd590525f625839fded7e75b8a00779",
      "parents": [
        "4e6e564e586f37457316ab4bef74a9766716f6a9"
      ],
      "author": {
        "name": "linfeng",
        "email": "33561138+lyne7-sc@users.noreply.github.com",
        "time": "Sat Oct 10 15:59:53 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 15:59:53 2026 +0000"
      },
      "message": "perf: Add an adaptive integer membership prefilter for hash joins (#25363)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #.\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\nHash joins can spend substantial time looking up probe keys that do not\nexist on the build side. For a single integer key with a bounded range,\nan exact membership bitmap can reject these keys cheaply before hash\ntable lookup. This helps when many nonmatching keys reach the join,\nincluding when dynamic filters cannot be pushed down to the input.\n\nFor example, in the measured TPC-H SF1 plans, the `RightSemi` join on\n`part.p_partkey \u003d lineitem.l_partkey` receives approximately 6 million\nprobe rows. With memtable inputs or the default Parquet configuration:\n\n- **Q8:** Only **0.73%** of probe rows match the filtered build side,\nresulting in approximately 5.96 million unsuccessful hash table lookups.\n- **Q9:** Only **5.32%** of probe rows match the filtered build side,\nresulting in approximately 5.68 million unsuccessful hash table lookups.\n\nThese low probe hit rates leave substantial room to avoid unsuccessful\nlookups, reflected in both the query-latency and operator-level\nmeasurements below.\n\nThe extra membership check is less useful when most keys match. An\nadaptive policy pauses filtering when the observed pruning ratio is low\nand periodically samples again as the input changes.\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n- Build an optional integer membership bitmap for eligible single-key\nHashMap joins in both CollectLeft and Partitioned modes. ArrayMap and\nnull-aware joins retain their existing paths.\n- Generate a lookup mask for each probe batch, skipping hash table\nlookups for absent keys. Preserve the original probe rows and NULL\nhandling so outer, anti, and mark join semantics remain unchanged. Hash\ncomputation is unchanged.\n- Track pruning independently in each probe stream. Unproductive\nsampling windows trigger progressively longer pauses; productive samples\nreset the pause interval.\n- Account for bitmap and mask memory through the memory pool, falling\nback to normal lookup when an optional reservation cannot be satisfied.\n- Add configuration, documentation, creation/pruning metrics, and the\n`hash_join_probe` microbenchmark.\n\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n- Unit tests cover membership and integer boundaries, range overflow,\nbitmap boundaries, adaptive sampling/backoff, and sliced validity masks.\n- HashJoin tests cover fallback paths, memory reservation failures, and\nindependent probe-stream adaptation with a shared build bitmap.\n- `hash_join_integer_prefilter.slt` covers duplicate matches, unmatched\nrows, NULL equality, inner/full/semi/anti joins, null-aware IN/NOT IN\nbehavior, range limits, and creation/pruning metrics.\n\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e\n\nThe feature is opt-in and disabled by default. It can be enabled with:\n\n```sql\nSET datafusion.execution.enable_join_integer_prefilter \u003d true;\n```\n\nAdditional execution options control the maximum key range (default\n`262144`), minimum pruning ratio (`0.5`), and sampling window (`12288`\ninput rows). The metrics `integer_prefilter_created_count` and\n`probe_prefilter_rows_pruned` expose whether the prefilter was created\nand how many probe rows skipped lookup.\n\nQuery results are unchanged.\n\n## Benchmarks\n\n### Microbench: `hash_join_probe`\n\n| Workload | Main | Off | On | On vs main |\n|---|---:|---:|---:|---:|\n| RightSemi, 10% interleaved hits | 5.335 | 5.293 | 3.985 | -25.3% |\n| RightAnti, 10% interleaved hits | 10.849 | 10.933 | 9.479 | -12.6% |\n| Inner, 10% interleaved hits | 6.114 | 6.164 | 4.802 | -21.4% |\n| RightSemi, 10% clustered hits | 4.286 | 4.338 | 3.549 | -17.2% |\n| RightAnti, 10% clustered hits | 10.172 | 11.633 | 8.969 | -11.8% |\n| RightSemi, all hits | 13.066 | 12.897 | 13.061 | -0.0% |\n| RightAnti, all hits | 5.920 | 5.924 | 6.112 | +3.2% |\n| Inner, all hits | 19.235 | 19.567 | 19.565 | +1.7% |\n| RightSemi, high-to-low hit rate | 9.096 | 9.405 | 9.203 | +1.2% |\n| RightAnti, high-to-low hit rate | 8.480 | 8.478 | 8.408 | -0.8% |\n| RightSemi, single probe batch, all hits | 0.205 | 0.217 | 0.258 |\n+25.9% |\n| RightSemi, dense 100K build, all hits | 10.172 | 10.264 | 10.107 |\n-0.6% |\n| RightSemi, sparse 100K build, all hits | 15.579 | 15.568 | 15.567 |\n-0.1% |\n\n### TPC-H with memtable\n| Query | Main | Off | On | On vs main |\n|---|---:|---:|---:|---:|\n| Q8 | 25.332 | 23.381 | 16.080 | -36.5% |\n| Q9 | 48.990 | 46.381 | 41.653 | -15.0% |\n| Q17 | 67.344 | 66.039 | 43.156 | -35.9% |\n\n### TPC-H with parquet\nwith the default `datafusion.execution.parquet.pushdown_filters\u003dfalse`\n\n| Query |   Main |    Off |     On | On vs main |\n| ----- | -----: | -----: | -----: | ---------: |\n| Q8    | 63.736 | 63.243 | 58.271 |      -8.6% |\n| Q9    | 76.014 | 74.103 | 70.175 |      -7.7% |\n\n### Target HashJoin `join_time`\n\nThe following table measures the `CollectLeft` / `RightSemi` HashMap\njoin on `part.p_partkey \u003d lineitem.l_partkey` described above. It\nreports **operator `join_time`, summed across the four probe\npartitions**, separately from end-to-end query latency.\n\n| Input             | Query |   Main |    Off |     On | On vs main |\n| ----------------- | ----- | -----: | -----: | -----: | ---------: |\n| MemTable          | Q8    | 29.330 | 29.625 | 12.045 |     -58.9% |\n| MemTable          | Q9    | 39.985 | 40.010 | 26.415 |     -33.9% |\n| Parquet (default) | Q8    | 29.685 | 29.820 | 11.190 |     -62.3% |\n| Parquet (default) | Q9    | 35.830 | 35.305 | 20.525 |     -42.7% |"
    },
    {
      "commit": "4e6e564e586f37457316ab4bef74a9766716f6a9",
      "tree": "853df399cc9705a292ac6e0485289910ef50865b",
      "parents": [
        "d1371370a5c647bb48aeccdd082618b96bb717ed"
      ],
      "author": {
        "name": "Yongting You",
        "email": "2010youy01@gmail.com",
        "time": "Sat Oct 10 02:29:27 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Oct 10 02:29:27 2026 +0000"
      },
      "message": "chore: Hide internal public utility APIs (#25963)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #.\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\nSee the previous PR for rationale\n\n- https://github.com/apache/datafusion/pull/25495\n\nThis PR adds #[doc(hidden)] and comments for public APIs that is used as\ninternal utility.\n\nThe major categories are\n- already includes `#doc(hidden)`\n- Already explained in the comment that this public API is internal-only\n- Optimizer utilities, with strict preconditions to use it correctly.\n\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\ncomments only\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e"
    },
    {
      "commit": "d1371370a5c647bb48aeccdd082618b96bb717ed",
      "tree": "663c27b65ea0f15009428dc1731d61b05806ac9c",
      "parents": [
        "1c49b7f6d38a6c38ff0763855814db2ef5d4a352"
      ],
      "author": {
        "name": "ranflarion",
        "email": "ran@flarion.io",
        "time": "Fri Oct 09 19:40:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 19:40:22 2026 +0000"
      },
      "message": "fix: build the IN list static filter only from literal-only items (#26083)\n\n## Which issue does this PR close?\n\n- Closes #26082.\n\n## Rationale for this change\n\n`n IN (2, 100, 101, CASE WHEN d \u003e 5 THEN 1 ELSE d END * 5)` returns\nwrong results on every row (repro in #26082).\n`try_evaluate_constant_list` decides that a list is constant by\nevaluating it on an empty batch, and `CaseExpr` returns its THEN branch\nas a scalar for a zero-length WHEN mask, so the CASE item is frozen to\n`5` in the static filter and never evaluated per row.\n\n## What changes are included in this PR?\n\n`try_evaluate_constant_list` returns `None` unless every leaf of every\nlist item is a `Literal`, so any other list takes the per-batch\nevaluation `InListExpr` already uses for items that return arrays. Lists\nof literals, casts of literals and other expressions over literals still\nbuild the static filter from their empty-batch evaluation, as before.\n\nChecking leaves rather than `collect_columns` keeps the rule independent\nof which leaf types read the input (`Column`, `LambdaVariable`, or a\nleaf defined outside DataFusion). The cost is that an item with a\nnon-literal leaf that is nonetheless constant, such as a stable function\nthe optimizer did not fold, is now evaluated per batch instead of once.\n\n## What is the testing strategy for this PR?\n\nA new section in `in_list.slt` runs the repro as a projection and as a\nfilter, and `test_in_list_case_item_reading_a_column` builds the same\nexpression through `in_list()`. Both fail on main and pass with this\nchange. The other `in_list` unit tests, the `physical-expr` lib tests,\nthe full sqllogictest suite and the `filter_pushdown` integration tests\npass unchanged.\n\n## Are there any user-facing changes?\n\nNo API changes. IN lists whose items have a non-literal leaf return\ncorrect results, evaluated per batch rather than through the static\nfilter.\n\n---------\n\nCo-authored-by: Jay Zhan \u003cjayzhan211@gmail.com\u003e"
    },
    {
      "commit": "1c49b7f6d38a6c38ff0763855814db2ef5d4a352",
      "tree": "5728c94477e558be9566af896daa84b5fee570fa",
      "parents": [
        "5218379fac30106965295f39a692da15b556b6c9"
      ],
      "author": {
        "name": "Xiaozhe Yu",
        "email": "664920313@qq.com",
        "time": "Fri Oct 09 18:07:09 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 18:07:09 2026 +0000"
      },
      "message": "perf: optimize aggregate functions over literal arguments (#25849)\n\n## Which issue does this PR close?\n\n- Closes #25847.\n\n## Rationale for this change\n\nUnlike scalar functions, aggregate functions cannot be passed scalar\nvalues directly. When an aggregate function is passed a literal argument\n(e.g., `count(1)`), for every input batch we expand the literal value\ninto an 8k-element array before invoking the aggregate. Since we started\nwith a constant, this repeated scalar -\u003e array conversion is wasted\nwork, and the cost can be non-trivial: for example, scalar -\u003e array\nconversion takes up about 20% of total query execution time for a simple\n`count(*)` query on a 5M row in-memory table.\n\n## What changes are included in this PR?\n\n- Add `AggregateArgument` to identify literal aggregate arguments when\naggregate execution is created.\n- Evaluate literal arguments once and reuse their expanded arrays across\nbatches with zero-copy slices.\n- Retain expanded arrays up to 1 MiB in ungrouped and hash-table\naggregation paths.\n\n## What is the testing strategy for this PR?\n\nUnit tests cover literal reuse, larger batches, non-literal arguments,\nselection handling, and the 1 MiB limit.\n\nA local `release-nonlto` benchmark used one partition, the default batch\nsize, and a 5,000,000-row in-memory table with a non-null `Int64` column\n`v`:\n\n```sql\nSELECT COUNT(*) FROM t WHERE v \u003c 900;\n```\n\nCached constant-argument `COUNT` was about 24% faster than uncached\nevaluation.\n\nThe `aggregate_filter` Criterion benchmark now includes literal\n`COUNT(1)` cases. Local comparisons against main show 2–5% improvements\nfor grouped aggregation.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "5218379fac30106965295f39a692da15b556b6c9",
      "tree": "eeef2599146aff1a031d350689a55794207690b8",
      "parents": [
        "3310fd59a743dad59329779451278518ac32d90a"
      ],
      "author": {
        "name": "Efe",
        "email": "gokdemirefe1903@gmail.com",
        "time": "Fri Oct 09 17:35:12 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 17:35:12 2026 +0000"
      },
      "message": "docs: add DataFusion security guidance (#26064)\n\n## Which issue does this PR close?\n\n- Closes #26061.\n\n## Rationale for this change\n\nApplications embedding DataFusion may accept SQL from users, but the\nlibrary guide does not explain security-relevant defaults or how\navailable controls contribute to hardening.\n\n## What changes are included in this PR?\n\nAdds a library guide covering SQL statement restrictions, opt-in\nlocal-file access, query memory limits, spill storage location and size\nlimits, and the authorization and isolation responsibilities of the\nhosting application.\n\n## What is the testing strategy for this PR?\n\n- `./ci/scripts/doc_prettier_check.sh` (passed after the documentation\nupdate).\n\n## Are there any user-facing changes?\n\nAdds a “Securing DataFusion” page to the Library User Guide and links it\nfrom the guide and documentation navigation. The page now explains that\nmemory limits do not cap spill disk use and names the runtime settings\nfor controlling temporary storage.\n\nAI assistance was used in preparing this contribution.\n\n---------\n\nSigned-off-by: Efe Gökdemir \u003cgokdemirefe1903@gmail.com\u003e"
    },
    {
      "commit": "3310fd59a743dad59329779451278518ac32d90a",
      "tree": "103ec2973ceff713fc27e9eccaeec032dce335a3",
      "parents": [
        "7833125a50ff660228e72a66d67db072b28927b9"
      ],
      "author": {
        "name": "Alessandro Solimando",
        "email": "asolimando@apache.org",
        "time": "Fri Oct 09 16:39:19 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 16:39:19 2026 +0000"
      },
      "message": "fix: report `LowerEqual` cardinality effect for `CoalescePartitionsExec` with fetch (#26051)\n\n## Which issue does this PR close?\n\n- Closes #26050.\n\n## Rationale for this change\n\n`CoalescePartitionsExec::cardinality_effect` returns\n`CardinalityEffect::Equal` even when `fetch` is set, although the\noperator can then produce fewer rows than its input. Code that relies on\n`cardinality_effect` gets the wrong answer, for example\n`PassthroughStatisticsProvider` reports the input row count and drops\nthe fetch.\n\n## What changes are included in this PR?\n\n- `CoalescePartitionsExec::cardinality_effect` returns\n`CardinalityEffect::LowerEqual` when `fetch` is set, as `SortExec` and\n`SortPreservingMergeExec` already do.\n\n## What is the testing strategy for this PR?\n\n- New unit test for `cardinality_effect` with and without `fetch`.\n- New unit test showing that `PassthroughStatisticsProvider` no longer\ndrops the fetch (`Exact(10)` instead of `Exact(1000)`).\n- `sqllogictest` and the core `physical_optimizer` integration tests\npass with no plan changes.\n\n## Are there any user-facing changes?\n\nNo.\n\n----\n\nDisclaimer: I used AI to assist in the code generation, I have manually\nreviewed the output and it matches my intention and understanding."
    },
    {
      "commit": "7833125a50ff660228e72a66d67db072b28927b9",
      "tree": "d3ba5c3c570ef15ec7f66fc079697fd672e1c6d0",
      "parents": [
        "d9d7be8787764ecdd95b1cee26b10508a89f5d60"
      ],
      "author": {
        "name": "Roshan Ramani",
        "email": "154859727+rawsun007@users.noreply.github.com",
        "time": "Fri Oct 09 16:32:00 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 16:32:00 2026 +0000"
      },
      "message": "docs: show array_distinct keeping first-seen order (#25930)\n\n## Which issue does this PR close?\n\n- None; documentation fix.\n\n## Rationale for this change\n\nThe `array_distinct` example says `select array_distinct([1, 3, 2, 3, 1,\n2, 4])` returns `[1, 2, 3, 4]`. It returns `[1, 3, 2, 4]`: #20364\nchanged it to keep elements in the order they first appear, matching\n`array_union` and `array_intersect`, and the example was not updated.\n\n## What changes are included in this PR?\n\nThe `#[user_doc]` example and description in `set_ops.rs`, the matching\ncode comment, and `scalar_functions.md` regenerated with\n`./dev/update_function_docs.sh`. Also a sqllogictest case for the order,\nsince every existing `array_distinct` case used input whose sorted and\nfirst-seen orders coincide.\n\n## What is the testing strategy for this PR?\n\nRan the example against `datafusion-cli` built from `main`. The new case\nin `array_distinct.slt` passes; `cargo fmt --check`, `cargo clippy -p\ndatafusion-functions-nested --all-targets -- -D warnings` and\n`./ci/scripts/doc_prettier_check.sh` pass.\n\n## Are there any user-facing changes?\n\nDocumentation and a test only.\n\nGenerated with Claude Code (claude-opus-5-5); I checked the output\nabove."
    },
    {
      "commit": "d9d7be8787764ecdd95b1cee26b10508a89f5d60",
      "tree": "1e0316661a46128d4f3a54053f73ea8f2daaf229",
      "parents": [
        "754d3c1ae30a4dc29f149ce5d1675589813a50dd"
      ],
      "author": {
        "name": "singhpratech",
        "email": "42719720+singhpratech@users.noreply.github.com",
        "time": "Fri Oct 09 16:30:40 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 16:30:40 2026 +0000"
      },
      "message": "docs: add datafusion-arrowmetal to the integrations list (#26004)\n\n## Which issue does this PR close?\n\nNone; a one-line addition to the integrations list in the user guide.\n\n## Rationale for this change\n\n`datafusion-arrowmetal` is a published crate (crates.io) that extends\nDataFusion through a `PhysicalOptimizerRule`: registered on a\n`SessionContext`, it replaces full sorts and measured group-by shapes\nwith plans that run on the Apple silicon GPU through Metal and hand back\nthe `RecordBatch`es DataFusion expects. It is the kind of project the\n\"Integrations\" list in `docs/source/user-guide/introduction.md` points\nat.\n\n## What changes are included in this PR?\n\nOne line under \"Integrations\" in\n`docs/source/user-guide/introduction.md`, in the list\u0027s alphabetical\norder.\n\n## What is the testing strategy for this PR?\n\nDocumentation only; the page renders as before.\n\n## Are there any user-facing changes?\n\nThe user guide lists one more integration."
    },
    {
      "commit": "754d3c1ae30a4dc29f149ce5d1675589813a50dd",
      "tree": "5f95b27a1aa07c491d52f0be13b156bdf7f2d2fc",
      "parents": [
        "be8afbb14777ff8b8459d01e10058d05cfbe0e3a"
      ],
      "author": {
        "name": "Ilya Krasnov",
        "email": "ilyaantonievich@gmail.com",
        "time": "Fri Oct 09 16:16:22 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 16:16:22 2026 +0000"
      },
      "message": "docs: preserve released documentation during deployment (#25880)\n\n- related to https://github.com/apache/datafusion/issues/17071\n\nThe documentation deploy uses rsync --delete, which would erase manually\npublished versions/ directories. Exclude /versions/ so normal\ndevelopment-site deployments preserve release documentation. This\none-line deployment change is intentionally separate from #24792.\n\n---------\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e\nCo-authored-by: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "be8afbb14777ff8b8459d01e10058d05cfbe0e3a",
      "tree": "936141a4fceb1b64a6d96375d68c80342b5a92bf",
      "parents": [
        "06aa131cda0d6829c517e77f3b8b08f3a24569f0"
      ],
      "author": {
        "name": "Qi Zhu",
        "email": "zhuqilucas@gmail.com",
        "time": "Fri Oct 09 16:15:12 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 16:15:12 2026 +0000"
      },
      "message": "feat: push window predicates on expression PARTITION BY keys (#25865)\n\n## Which issue does this PR close?\n\n- Closes #25864.\n\n## Rationale for this change\n\nA predicate that depends only on a window\u0027s `PARTITION BY` keys is\nconstant within every partition, so applying it below the window drops\nwhole partitions and leaves every surviving row\u0027s window value\nunchanged. `push_down_filter` already does this, but only for plain\ncolumn keys.\n\nThe key set is built by mapping each partition key through\n`qualified_name()` into a `Column`, so `PARTITION BY a + b` becomes a\ncolumn literally named `\"a + b\"`. A predicate on `a + b` reads the real\ncolumns `a` and `b`, which never match that synthesised name, so it\nstays above the window. The optimization simply does not exist for\nexpression keys such as `a + b`, `NULLIF(c, \u0027\u0027)` or `COALESCE(x, y)`.\n\nIt also affects *mixed* predicates. With `PARTITION BY year, num * num`:\n\n```sql\nSELECT * FROM (\n    SELECT year, num, SUM(num) OVER (PARTITION BY year, num * num) AS s FROM t\n)\nWHERE year \u003d \u00272021\u0027 OR num * num \u003e 4\n```\n\nthe predicate is constant within every partition and safe to push, but\nits column refs are `{year, num}` against a key set of `{year, \"num *\nnum\"}`, so `num` is not found and the whole conjunct is kept.\n\n## What changes are included in this PR?\n\n**Keep a volatile predicate above the window** (first commit,\nindependent of the rest)\n\nA volatile predicate that reads no columns, such as `random() \u003c 0.5`,\nsatisfies the subset test vacuously and was pushed below the window,\nwhere it changes which rows the window function sees. The aggregate arm\nalready drops volatile group expressions before the equivalent check;\nthis does the same here. Split out as its own commit so it can be taken\nseparately.\n\n**Match against the key expressions** (second commit)\n\nThe key set holds the partition key `Expr`s rather than names\nsynthesised from them, and each conjunct is walked: a subtree exactly\nequal to one of the keys counts as read in full, and the predicate is\nrejected only on reaching a `Column` that no key covered.\n\nThis is a strict generalization. For a plain column key, the reference\nto that column is itself a subtree equal to the key, so every predicate\npushed today is still pushed; expression keys and mixed predicates are\nadded on top. Matching is structural, so it stays conservative: a\npredicate written `b + a` does not match a key written `a + b` and is\nleft in place.\n\n**Keep a subquery predicate above the window** (third commit, from\nCopilot\u0027s review of this PR)\n\n`Expr::apply` does not enter a subquery\u0027s plan, so the columns it\ncorrelates on are invisible to the key test: `Exists` and\n`ScalarSubquery` are leaves, and `InSubquery` and `SetComparison` expose\nonly their left-hand expression. With `PARTITION BY a + b`, the\npredicate\n\n```sql\na + b \u003e (SELECT ... WHERE inner.x \u003d outer.a)\n```\n\nlooks like it reads nothing but the key. `outer.a` varies inside a\nsingle partition, so the predicate is not constant there and pushing it\nchanges the result. The same blind spot hides a volatile function inside\na subquery from the `is_volatile()` check that runs first.\n\nThe previous column-key matching happened to keep this expression above\nthe window, because the predicate\u0027s column refs `{a, b}` never matched\nthe synthesised key name. For a plain column key the hole predates this\nbranch, but expression-key matching would have widened it, so a\nsubquery-bearing node now counts as reading something the walk cannot\naccount for.\n\nNo predicate rewriting is involved. The existing comment in that arm\nnotes that a window partition expression, unlike an aggregate group\nexpression, is not exposed as a standalone column, so there is nothing\nto rewrite `a + b` into. The predicate is pushed unchanged.\n\n## Are these changes tested?\n\nYes, in `push_down_filter`\u0027s unit tests.\n\nBehavior the change turns on:\n\n- `filter_expression_move_window`: a predicate on `PARTITION BY a + b`\nis now pushed. This replaces `filter_expression_keep_window`, which\npinned the previous behavior.\n- `filter_move_window_mixed_column_and_expression_keys`: `PARTITION BY\na, a + b` with `a \u003e 1 OR a + b \u003e 10` is pushed, the case neither the old\nmatching nor an expression-key-only rule could see.\n- `filter_move_window_function_expression_key`: a function key,\n`PARTITION BY f(c)` with `f(c) IS NOT NULL`, the shape this exists for.\n- `filter_move_window_expression_key_subtree`: a predicate built on top\nof a key, `(a + b) + 1 \u003e 10`, where the key subtree accounts for\neverything read and the surrounding literal reads nothing.\n- `filter_multiple_windows_common_expression_partition`: an expression\nkey shared by every window function is pushed.\n\nBehavior it deliberately leaves alone, each verified to fail without the\ncorresponding guard:\n\n- `filter_keep_window_column_underlying_expression_key`: an expression\nkey does not make the columns it reads pushable on their own, so `a \u003e\n10` under `PARTITION BY a + b` stays above.\n- `filter_keep_window_expression_key_operand_order`: matching is\nstructural, so `b + a` does not match a key written `a + b`.\n- `filter_multiple_windows_disjoint_expression_partition`: an expression\nkey present in only one of the window functions is not pushed.\n- `filter_volatile_keep_window` and\n`filter_volatile_keep_window_expression_key`: the volatility check still\nruns first, including when the predicate\u0027s operand matches a key.\n- `filter_keep_window_scalar_subquery_over_expression_key` and\n`filter_keep_window_in_subquery_over_expression_key`: the subquery guard\nfrom the third commit.\n\nThe existing window tests (`filter_move_window`,\n`filter_move_partial_window`, `filter_order_keep_window`,\n`filter_multiple_windows_common_partitions`,\n`filter_multiple_windows_disjoint_partitions`, and the rest) are\nunchanged and pass, which is the evidence for the \"strict\ngeneralization\" claim.\n\nOn plan churn: there is none to report. Matching against the key\nexpressions only ever adds pushes that the name-based matching could not\nsee, and every window plan the test suite pins is either unaffected or\nalready covered by the unit tests above. No `.slt` expectations needed\nupdating.\n\n## Are there any user-facing changes?\n\nBetter plans for window queries filtered on expression partition keys,\nand a correctness fix for volatile predicates over windows. No API\nchanges."
    },
    {
      "commit": "06aa131cda0d6829c517e77f3b8b08f3a24569f0",
      "tree": "ad995f4dd276695f3b49af03f875b86fea22de77",
      "parents": [
        "816e002fe8c0932db891d1783d1ba94121c369ed"
      ],
      "author": {
        "name": "Shoryamishra61",
        "email": "140916461+Shoryamishra61@users.noreply.github.com",
        "time": "Fri Oct 09 08:57:59 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 08:57:59 2026 +0000"
      },
      "message": "fix: preserve null treatment when unparsing window and aggregate functions (#25475)\n\n## Which issue does this PR close?\n\n- Closes #25462\n\n## Rationale for this change\n\nWhen converting DataFusion logical expressions back to SQL AST in\n`datafusion-sql`, both `Expr::WindowFunction` and\n`Expr::AggregateFunction` previously dropped the `null_treatment` field\nstored in `WindowFunctionParams` and `AggregateFunctionParams` and\nhardcoded `null_treatment: None` on the generated\n`sqlparser::ast::Function`.\n\nAs a result, expressions using `IGNORE NULLS` or `RESPECT NULLS` (such\nas `FIRST_VALUE(v IGNORE NULLS) OVER (...)` or aggregate `FIRST_VALUE(v\nIGNORE NULLS)`) lost their explicit NULL treatment clause during\nunparsing, altering query semantics upon re-execution.\n\n## What changes are included in this PR?\n\n- Extracted `null_treatment` from `WindowFunctionParams` in\n`Expr::WindowFunction` and forwarded it to\n`ast::Function.null_treatment`.\n- Extracted `null_treatment` from `AggregateFunctionParams` in\n`Expr::AggregateFunction` and forwarded it to\n`ast::Function.null_treatment`.\n- Added helper function `null_treatment_to_sql` mapping\n`datafusion_expr::expr::NullTreatment` to\n`sqlparser::ast::NullTreatment`.\n- Added unit tests covering `IGNORE NULLS`, `RESPECT NULLS`, and `None`\n(control) for both window and aggregate functions.\n\n## What is the testing strategy for this PR?\n\n- Added `test_unparse_null_treatment_window_and_aggregate` in\n`datafusion/sql/src/unparser/expr.rs` covering:\n  - Window functions with `IGNORE NULLS`\n  - Window functions with `RESPECT NULLS`\n- Window functions without explicit NULL treatment (control case\nensuring no clause is emitted)\n  - Aggregate functions with `IGNORE NULLS`\n  - Aggregate functions with `RESPECT NULLS`\n  - Aggregate functions without explicit NULL treatment (control case)\n- Verified test fails on pre-fix code and passes with the fix.\n- Ran all unparser unit tests: `cargo test -p datafusion-sql --lib\nunparser` (38 passed, 0 failed).\n- Verified lints and formatting: `cargo fmt --all -- --check` and `cargo\nclippy -p datafusion-sql --all-targets --all-features -- -D warnings`.\n\n## Are there any user-facing changes?\n\nBug fix: SQL unparsing now preserves explicit `IGNORE NULLS` and\n`RESPECT NULLS` clauses on window and aggregate functions rather than\nomitting them."
    },
    {
      "commit": "816e002fe8c0932db891d1783d1ba94121c369ed",
      "tree": "a1f56d9eb160151c3cffc32d7f0d2f3c2a3b3e36",
      "parents": [
        "057f77f41e7dc74ce9b7a4af54a411faf2015a48"
      ],
      "author": {
        "name": "Rishabh Gupta",
        "email": "rishabhg.swe@gmail.com",
        "time": "Fri Oct 09 08:50:59 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 08:50:59 2026 +0000"
      },
      "message": "test: cover CrossJoinExec row metrics across batched inputs (#25530)\n\n## Which issue does this PR close?\n\nPart of #25333 (`CrossJoinExec` test coverage only).\n\n## Rationale for this change\n\nJoin metrics can be incorrect without affecting query results. Existing\n`CrossJoinExec` tests did not assert `build_input_rows` or `input_rows`\nacross different input batch layouts.\n\n## What changes are included in this PR?\n\nAdds Rust test coverage that:\n\n* Verifies `build_input_rows`, `input_rows`, and `output_rows` for the\nexisting single-batch case.\n* Runs the same 3 × 2 cross join with input batch sizes of 2 and 1.\n* Confirms the row metrics remain 3, 2, and 6 regardless of input\nbatching.\n\nThis is a test-only change.\n\n## What is the testing strategy for this PR?\n\n```bash\ncargo fmt --check\ncargo test -p datafusion-physical-plan --lib joins::cross_join\ncargo clippy -p datafusion-physical-plan --all-targets --all-features -- -D warnings\n```\n\nAll checks pass locally.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "057f77f41e7dc74ce9b7a4af54a411faf2015a48",
      "tree": "a0413a2a5c51884470fa765d73a61c4282319b88",
      "parents": [
        "bc693cc9c8ef72bddff57fcb06bc24fae4a49f22"
      ],
      "author": {
        "name": "linfeng",
        "email": "33561138+lyne7-sc@users.noreply.github.com",
        "time": "Fri Oct 09 07:47:32 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 07:47:32 2026 +0000"
      },
      "message": "perf: Prune matched right rows in nested loop semi and anti joins (#25413)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #.\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\nFor `RightSemi` and `RightAnti` nested loop joins, each right row only\nneeds one match to determine whether it belongs in the result.\nCurrently, matched right rows continue participating in comparisons with\nsubsequent left rows.\n\nSkipping these comparisons can significantly reduce execution time when\nmatches are found early.\n\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n- Add `RightExistenceProbe` to track matches and right-side candidates.\n- Compact the right-side filter columns when at least half the\ncandidates have matched and more left rows remain.\n- Stop probing the current right batch when all its rows have matched.\n- Preserve matches in original right-row coordinates for output and\nspill handling.\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n- Add unit tests for match tracking and candidate compaction.\n- Add SQL coverage in `nested_loop_join_existence.slt` for\nRightSemi/RightAnti joins, including NULLs, repeated matches, and\nmultiple left rows per probe.\n- Extend `nested_loop_join_spill.slt` to cover RightSemi/RightAnti joins\nacross spilled left chunks.\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e\n\nNo. This is an internal performance optimization.\n\n## Benchmark results\n\n| Case | Scenario | main | This PR | Time change |\n|---|---|---:|---:|---:|\n| Q15 | Right Semi, early matches | 307.659 | 0.365 | -99.88% |\n| Q16 | Right Anti, early matches | 306.225 | 0.338 | -99.89% |\n| Q18 | Right Semi, no matches | 7.964 | 7.728 | -2.95% |\n| Q19 | Right Anti, no matches | 8.100 | 7.770 | -4.07% |\n| Q20 | Right Semi, staged compaction | 56.082 | 7.182 | -87.19% |\n| Q21 | Right Anti, staged compaction | 56.057 | 7.115 | -87.31% |\n| Q22 | Right Semi, repeated 40% matches (4,096 left × 8,192 right) |\n12.185 | 12.410 | +1.84% |\n| Q23 | Right Anti, final-left-row matches with wide Utf8 | 0.305125 |\n0.309042 | +1.28% |\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "bc693cc9c8ef72bddff57fcb06bc24fae4a49f22",
      "tree": "91b395bed2ab60801fc19787831bbb6e751d5677",
      "parents": [
        "791660cd54f0196978c98e9bca165c1beb7bbc78"
      ],
      "author": {
        "name": "Mason",
        "email": "mason@jmh.fyi",
        "time": "Fri Oct 09 07:17:51 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 07:17:51 2026 +0000"
      },
      "message": "Make `TopKDynamicFilters` public (#25429)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #.\n\n## Rationale for this change\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\n`TopKDynamicFilters` is needed as an argument to `TopK::try_new()`, so\nwithout it it\u0027s impossible to construct a `TopK`.\n\n## What changes are included in this PR?\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n## What is the testing strategy for this PR?\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\n\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e\n\n---------\n\nCo-authored-by: kosiew \u003ckosiew@gmail.com\u003e"
    },
    {
      "commit": "791660cd54f0196978c98e9bca165c1beb7bbc78",
      "tree": "9a57d162f651d52a08678e3e6978b152901841da",
      "parents": [
        "6a31aa8d1dc433c8f5bebefa138c3fca93cf8fd9"
      ],
      "author": {
        "name": "limadog9",
        "email": "jakewallin42@gmail.com",
        "time": "Fri Oct 09 03:51:24 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 03:51:24 2026 +0000"
      },
      "message": "fix: Estimate string equality and LIKE filter selectivity (#25835)\n\n## Which issue does this PR close?\n\nCloses #25614.\n\n## Rationale for this change\n\nString equality, LIKE, and NOT LIKE currently receive the same fallback\nestimate. For a column with 1,000 rows, 200 NULLs, and 20 distinct\nnon-null values, equality should estimate 40 matching rows and\ninequality 760, instead of estimating 200 for both.\n\n## What changes are included in this PR?\n\n- Estimate direct string equality/inequality using the distinct count\nwhen available, under the existing uniform-distribution assumption.\n- Classify LIKE patterns as literal, all-percent, or wildcard patterns.\nWildcard estimates use the configured fallback, halved for each anchored\nend. Recognize escaped wildcards and Arrow\u0027s literal trailing-backslash\nbehavior.\n- Complement negated estimates over non-null rows and propagate zero\nnull counts for LIKE operands. Literal ILIKE retains a heuristic because\ncase folding can merge distinct values.\n- Retain existing estimates for compound or otherwise unsupported\nexpressions.\n- Remove an unnecessary semicolon in the Windows rounding implementation\nso the required Clippy check can run without that pre-existing warning.\n\n## What is the testing strategy for this PR?\n\nPublic SQL planning tests in\n`datafusion/core/tests/custom_sources_cases/statistics.rs` inject known\nstatistics through the existing table-provider fixture. They cover Utf8,\nLargeUtf8, Utf8View, equality/inequality, pattern forms, escaped\ncharacters, ILIKE, unknown distinct counts, and configured fallback\nselectivity. Direct physical-plan tests cover patterns eliminated by SQL\nsimplification, NULL/empty inputs, and column-valued patterns.\n\nValidation:\n- 51 filter tests passed, including the unsupported-literal fallback.\n- 3 new public SQL regression tests passed.\n- `cargo fmt --all` passed.\n- Targeted physical-plan Clippy passed with warnings denied.\n- Ablation passed: all 3 new SQL tests fail with the original `main`\nfilter implementation, with the expected row-count assertion failures.\n- TOML/Markdown formatting, license headers, typos, workflow checks, and\nASF YAML checks passed.\n\n\n## Are there any user-facing changes?\n\nString filter row estimates change. No public API changes. Wildcard\nestimates remain heuristics in the absence of string histograms."
    },
    {
      "commit": "6a31aa8d1dc433c8f5bebefa138c3fca93cf8fd9",
      "tree": "7d056457a1d6b101ff00a8b1d048395ddee4c3da",
      "parents": [
        "9fc84aec61658be91a56e1b89abe851204dfe294"
      ],
      "author": {
        "name": "namanjain24-sudo",
        "email": "namanjainpy@gmail.com",
        "time": "Fri Oct 09 02:47:57 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 02:47:57 2026 +0000"
      },
      "message": "fix: keep a DISTINCT aggregate\u0027s arity in `SingleDistinctToGroupBy` (#25461)\n\n## Which issue does this PR close?\n\n- Closes #25417.\n\n## Rationale for this change\n\n`is_single_distinct_agg` requires that every distinct argument in the\naggregation is the same expression. It checks that by collecting the\narguments into a set and requiring the set to hold exactly one element:\n\n```rust\nif *distinct {\n    for e in args {\n        fields_set.insert(e);\n    }\n```\n\nA call that passes that expression more than once satisfies the check,\nbecause its arguments collapse to a single entry. `corr(DISTINCT x, x)`\nis such a call, and the rewrite below then assumed one argument per\ndistinct aggregate and returned an internal error.\n\nThis is also why the neighbouring cases in the issue are unaffected:\n`corr(DISTINCT x, y)` and `corr(DISTINCT x, x + 0.0)` put two entries in\nthe set, so the rule bails out early and leaves the plan alone.\n\n## What changes are included in this PR?\n\nThe distinct branch keeps the call\u0027s arity, repeating the alias that the\ninner group by produces, so `corr(DISTINCT x, x)` becomes a group by `x`\nwith `corr(alias1, alias1)` above it.\n\nThat is sound because of the check above. Every distinct argument is the\nsame expression, so the distinct argument tuples the call aggregates are\nexactly the distinct values of that expression, which is what grouping\nby it produces.\n\nThe assertion stays, now stating the invariant the rewrite actually\nrelies on rather than an arity the rule does not enforce. It also covers\nan empty argument list, which would otherwise panic in\n`args.swap_remove(0)` instead of reporting an internal error.\n\n## What is the testing strategy for this PR?\n\nRule tests in `single_distinct_to_groupby.rs`:\n\n- `single_distinct_repeated_arg_and_groupby`: `corr(DISTINCT b, b)` is\nrewritten, and the plan keeps both arguments and the original output\ncolumn name.\n- `single_distinct_two_args_and_groupby`: `corr(DISTINCT b, c)` is still\nleft alone.\n\nTwo queries in `aggregate.slt` cover it end to end. One is `covar_samp`,\nchosen because its value depends on the de-duplication rather than only\non the absence of the error: over the same input it returns `0.5` with\n`DISTINCT` and `0.333333333333` without, so the expected value pins the\nsemantics.\n\nMeasured, rather than assumed:\n\n| check | result |\n| --- | --- |\n| both halves of the fix reverted | the two `aggregate.slt` queries and\n`single_distinct_repeated_arg_and_groupby` fail with an `Assertion\nfailed: args.len() \u003d\u003d 1` internal error, which is the failure in the\nissue |\n| the rewrite against a reference the rule does not touch | the same\naggregates over a manually de-duplicated input return the same values |\n\n`cargo test -p datafusion-optimizer` (915 tests), the sqllogictest suite\n(521 files), and `./ci/scripts/rust_clippy.sh` pass.\n\n## Are there any user-facing changes?\n\nQueries that failed with an internal error now run. No plan that the\nrule rewrote before is rewritten differently: a single argument call\nproduces the same outer aggregate as it did, and the only calls that\nreach this branch with more than one argument are the ones that\npreviously returned the error."
    },
    {
      "commit": "9fc84aec61658be91a56e1b89abe851204dfe294",
      "tree": "ea4beaa371e77e8929797e88aa9630dceb814afb",
      "parents": [
        "f868d604b658cf2d671f93f08fb8bb3033320e61"
      ],
      "author": {
        "name": "Vova Kot",
        "email": "volodymyr.kot.ua@gmail.com",
        "time": "Fri Oct 09 02:44:29 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 02:44:29 2026 +0000"
      },
      "message": "fix: preserve local direnv settings (#26122)\n\n## Which issue does this PR close?\n\nCloses #26101 , which was introduced in\nhttps://github.com/apache/datafusion/pull/26005. cc @kumarUjjawal\n@kosiew\n\n## What changes are included in this PR?\n\nLoad an ignored .envrc.local after the shared Nix environment so\ncontributors can keep machine-specific settings without modifying\ntracked files.\n\nDocument the Nix, direnv, and local override workflow in the development\nenvironment guide.\n\nFollowing recommendation from direnv:\nhttps://github.com/direnv/direnv/blob/e24ea74873aff78d5e371c85061dc7fafdeedd5a/README.md#quick-demo\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "f868d604b658cf2d671f93f08fb8bb3033320e61",
      "tree": "cdfcdb25aed1dc3f5b4507d34522313fce5fb17e",
      "parents": [
        "048fc192a9b0366ac3c61e44482bbfa60450b169"
      ],
      "author": {
        "name": "namanjain24-sudo",
        "email": "namanjainpy@gmail.com",
        "time": "Fri Oct 09 02:41:29 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 02:41:29 2026 +0000"
      },
      "message": "fix: Emit LIKE the way the Substrait extension defines it (#25442)\n\n## Which issue does this PR close?\n\n- Closes #25368.\n\n## Rationale for this change\n\n`functions_string.yaml` defines one function for this, with two\narguments and an option:\n\n```yaml\n    name: like\n    impls:\n      - args:\n          - value: \"varchar\u003cL1\u003e\"\n            name: \"input\"\n          - value: \"varchar\u003cL2\u003e\"\n            name: \"match\"\n        options:\n          case_sensitivity:\n            values: [ CASE_SENSITIVE, CASE_INSENSITIVE, CASE_INSENSITIVE_ASCII ]\n        return: \"boolean\"\n```\n\nThe producer emitted three arguments, registered `ilike` for the case\ninsensitive form, and never set the option. Neither `ilike` nor an\nescape argument appears in any extension file, in the pinned crate or\nupstream.\n\n## What changes are included in this PR?\n\n- `make_substrait_like_expr` registers `like`, emits the two arguments\nthe definition takes, and sets `case_sensitivity` to `CASE_INSENSITIVE`\nfor `ILIKE`. A plain `LIKE` sets no option, which leaves the default.\n- `LIKE ... ESCAPE` is now `not_impl_err`. There is no escape in the\ndefinition, so the third argument only produced a call a consumer cannot\nbind.\n- The consumer reads `case_sensitivity`, taking the first value it\nsupports and refusing the ones it does not, as Substrait requires. It\nstill accepts the `ilike` name and the three argument form, so plans\nwritten by an older DataFusion still load.\n\n## What is the testing strategy for this PR?\n\n- New producer tests: `LIKE` emits `like` with two arguments and no\noption, `ILIKE` emits the `case_sensitivity` option, and an escape\ncharacter is rejected.\n- `roundtrip_like` and `roundtrip_ilike` still pass, which is what\ncovers the consumer: with the option reading removed, `roundtrip_ilike`\nfails because `ILIKE` comes back as `LIKE`. Removing the producer half\nlikewise fails the new producer test.\n- `cargo test -p datafusion-substrait` passes and\n`./ci/scripts/rust_clippy.sh` is clean.\n\nMeasured against substrait-java 0.103.0 and Spark 3.5.4, over `t(s)`\nholding `abc` and `ABC`, with the #11545 URN patched and `output_type`\nfilled (#25049):\n\n| plan | before | after |\n| --- | --- | --- |\n| `s LIKE \u0027a%\u0027` | `AnalysisException: WRONG_NUM_ARGS ... requires 2\nparameters but the actual number is 3` | runs, returns `abc` |\n| `s ILIKE \u0027a%\u0027` | `IllegalArgumentException: Unexpected scalar function\nwith key ilike:str_str` | runs, returns `abc` |\n\n**The second row is a trade-off worth stating.** `ILIKE` used to fail\nloudly there, and now it is accepted but answered case sensitively,\nbecause substrait-spark does not read the option: `case_sensitivity`\nappears nowhere in its sources. Substrait says a consumer that does not\nrecognise an option must reject the call, so that looks like a gap on\nthat side, and I am happy to report it there. If you would rather not\nemit something a known consumer mishandles, the alternative is to reject\n`ILIKE` as well until a consumer honours the option, and I will change\nit.\n\n## Are there any user-facing changes?\n\n`LIKE` and `ILIKE` are emitted in the form the extension defines, so\nconsumers that bind arguments by the declaration can now read them.\n`LIKE ... ESCAPE` is rejected instead of being emitted in a shape no\nconsumer can bind; DataFusion round trips it today only because its own\nconsumer reads the same private convention.\n\nThis touches `make_substrait_like_expr`, which #25367 folds into\n`from_like`, so whichever lands second needs a small rebase.\n\n---------\n\nCo-authored-by: namanjain24-sudo \u003c180642416+namanjain24-sudo@users.noreply.github.com\u003e"
    },
    {
      "commit": "048fc192a9b0366ac3c61e44482bbfa60450b169",
      "tree": "9c9d46709ec1ccad85d430c904853e0b2dcf09a3",
      "parents": [
        "f84b82c24938f09db87915936e16d03986568c44"
      ],
      "author": {
        "name": "Adrian Garcia Badaracco",
        "email": "1755071+adriangb@users.noreply.github.com",
        "time": "Fri Oct 09 01:38:38 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 01:38:38 2026 +0000"
      },
      "message": "fix: apply `spill_compression` to `RepartitionExec` spill files (#26142)\n\n## Which issue does this PR close?\n\n- Closes #26141.\n\n## Rationale for this change\n\n`RepartitionExec` does not apply\n`datafusion.execution.spill_compression`, so its spill files are always\nuncompressed. All other spilling operators (sort, aggregate, sort-merge\njoin, nested loop join) apply the setting. A user who sets a codec to\ndecrease spill disk usage gets no decrease for the data that\n`RepartitionExec` spills.\n\n## What changes are included in this PR?\n\n- `RepartitionExec::execute` now builds its `SpillManager` with\n`.with_compression_type(context.session_config().spill_compression())`,\nthe same as the other operators.\n- No change is necessary on the read side. Spill files use the Arrow IPC\nStream format, and the reader gets the codec from the stream.\n- I checked the other non-test `SpillManager::new` call sites.\n`RepartitionExec` was the only one that did not pass the setting.\n\n## What is the testing strategy for this PR?\n\nThe new test `repartition_spill_honors_spill_compression` runs a\nspilling `RepartitionExec` on constant (highly compressible) data with\n`uncompressed`, `lz4_frame` and `zstd`. It asserts that the same rows\nspill, that the data reads back intact, and that `spilled_bytes` with a\ncodec is less than half of the uncompressed value.\n\nThe test fails on `main` (`679264 vs 679264 bytes`) and passes with the\nfix:\n\n| `spill_compression` | `spilled_bytes` on `main` | `spilled_bytes` with\nthis PR |\n| --- | --- | --- |\n| `uncompressed` | 679,264 | 679,264 |\n| `lz4_frame` | 679,264 | 7,744 |\n| `zstd` | 679,264 | 5,024 |\n\n## Are there any user-facing changes?\n\nYes. Spill files from `RepartitionExec` now use the codec from\n`datafusion.execution.spill_compression`. The default (`uncompressed`)\ndoes not change. There are no API changes."
    },
    {
      "commit": "f84b82c24938f09db87915936e16d03986568c44",
      "tree": "e06e78d79ab2677798a443c3433c7773bf93a551",
      "parents": [
        "d6875ff6fb467c99c706474c54f103683e0273bd"
      ],
      "author": {
        "name": "RIchard Baah",
        "email": "137434454+Rich-T-kid@users.noreply.github.com",
        "time": "Fri Oct 09 01:29:44 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 01:29:44 2026 +0000"
      },
      "message": "Feat(parquet) : Introduce support for optionally writing  Distinct Values to statistics (#25576)\n\n## Which issue does this PR close?\n\n\u003c!--\nWe generally require a GitHub issue to be filed for all bug fixes and\nenhancements and this helps us generate change logs for our releases.\nYou can link an issue to this PR using the GitHub syntax. For example\n`Closes #123` indicates that this PR will close issue #123.\n--\u003e\n\n- Closes #24114.\n\n## Rationale for this change\n\nDataFusion can use NDV (number of distinct values) from Parquet row\ngroup statistics to power optimizations like COUNT(DISTINCT) aggregation\npushdown and cardinality estimation (#24111) . However, currently the\nParquet writers doesn\u0027t emit NDV by default, so these statistics are\nabsent for roundtrip queries.\n\nTwo recent arrow-rs additions make it possible to close this gap\nend-to-end:\n- [arrow-rs #10652 —\n`StatisticsConverter::row_group_distinct_counts()`](https://github.com/apache/arrow-rs/pull/10652)\n: a typed API for reading NDV from row group metadata\n- [arrow-rs #10654 —\n`WriterPropertiesBuilder::set_write_row_group_number_distinct_values()`](https://github.com/apache/arrow-rs/pull/10654):\na writer-side option to track and emit NDV during write\n\nThis PR wires both into DataFusion so that users can write parquet files\nwith NDV and have DataFusion read them back correctly.\n\n\u003c!--\nWhy are you proposing this change? If this is already explained clearly\nin the issue then this section is not needed.\nExplaining clearly why changes are proposed helps reviewers understand\nyour changes and offer better suggestions for fixes.\n\nPlease explain the problem you are trying to solve in terms of the\nuser-visible\nbehavior, rather than the implementation.\n\nFor example, \"The code in `foo.rs` doesn\u0027t handle nulls\" is a symptom of\nthe\nimplementation. \"COUNT(DISTINCT) returns wrong results when the column\ncontains\nnulls\" is the user-visible problem.\n--\u003e\n\n## What changes are included in this PR?\n\n- summarize_distinct_counts now calls\n`StatisticsConverter::row_group_distinct_counts()` instead of manually\nwalking column chunk statistics.\n- Adds\n`datafusion.execution.parquet.write_row_group_number_distinct_values`\n(bool, default false) to ParquetOptions. When enabled, the ArrowWriter\nhashes every non-null value per column per row group and writes the\ndistinct count into the Parquet statistics footer.\n\n\u003c!--\nThere is no need to duplicate the description in the issue here, but it\nis sometimes worth providing a summary of the individual changes in this\nPR.\n--\u003e\n\n## What is the testing strategy for this PR?\n\n- The NDV read change is covered by the 8 existing unit tests in\nmetadata.rs (test_distinct_count_*), which all continue to pass.\n- The write config is tested by\nsqllogictest/test_files/parquet_ndv_write.slt, which writes 4 rows with\n3 distinct values and verifies:\n- Without the option: Distinct is absent from DataSourceExec statistics\n- With the option: Distinct\u003dExact(3) appears in DataSourceExec\nstatistics\n\n\n\u003c!--\nWe typically require tests for all PRs in order to:\n1. Prevent the code from being accidentally broken by subsequent changes\n2. Serve as another way to document the expected behavior of the code\n\nBriefly describe how this PR is tested, and point to the specific tests\nyou added. For example: \u0027This new feature is covered by the\n`sqllogictest` cases added in `foo.slt`\u0027.\n\nIf this PR does not add tests, explain why. For example, if the change\nis already covered by existing tests, please mention it.\n\nYou should also check the `codecov` bot reply on this PR to confirm the\nchanged code is exercised.\n--\u003e\n\n## Are there any user-facing changes?\nyes, new `write_row_group_number_distinct_values` to parquet config\noptions.\n\u003c!--\nIf there are user-facing changes then we may require documentation to be\nupdated before approving the PR.\n\nIf there are any breaking changes to public APIs, please add the `api\nchange` label.\n--\u003e"
    },
    {
      "commit": "d6875ff6fb467c99c706474c54f103683e0273bd",
      "tree": "dae1f4ea1b676c8011062e2a4e8d81f7823e4bd6",
      "parents": [
        "a23b89ff9262c8b41e2fc42364fcfc3ae51085b6"
      ],
      "author": {
        "name": "theirix",
        "email": "theirix@gmail.com",
        "time": "Fri Oct 09 01:01:29 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Oct 09 01:01:29 2026 +0000"
      },
      "message": "feat: Use NativeType in get_example_type, information schema (#21737)\n\n## Which issue does this PR close?\n\n- Closes #14761 \n\n## Rationale for this change\n\nMoving from physical types: `get_example_types` and the information\nschema use Arrow `DataType`, but it is usually sufficient to use\nDatafusion\u0027s `NativeType` instead.\n\nLet\u0027s introduce a new API `get_representative_types`, based on\n`NativeType`, and deprecate the public `get_example_types` API\n\nIt is a logical continuation of #15965\n\n## What changes are included in this PR?\n\n- Introduce `get_representative_types` to provide `NativeType` via\n`LogicalType::default_cast_for`\n- Add missing conversions for `Union` to that helper\n- Deprecate `NUMERICS` finally (a brush-up for #18092)\n- Switch information schema to use native type.\n\n## Are these changes tested?\n\n- Tests are passing\n- Added more tests to check schema for different types of functions\n\n## Are there any user-facing changes?\n\n- Deprecation of the `TypeSignature::get_example_types` API\n\n---------\n\nCo-authored-by: Martin Grigorov \u003cmartin-g@users.noreply.github.com\u003e\nCo-authored-by: Jay Zhan \u003cjayzhan211@gmail.com\u003e"
    },
    {
      "commit": "a23b89ff9262c8b41e2fc42364fcfc3ae51085b6",
      "tree": "fc376fd9bd0a9e4c081b7f977e96857742933d9d",
      "parents": [
        "409e3b89ba425fa9740b6c10de600d91f11ad6be"
      ],
      "author": {
        "name": "Ryu",
        "email": "177669517+ryux1@users.noreply.github.com",
        "time": "Thu Oct 08 20:36:38 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 20:36:38 2026 +0000"
      },
      "message": "fix: reject unsupported DELETE LIMIT (#25005)\n\n## Which issue does this PR close?\n\n- Part of #24998; this PR adds a safe rejection until bounded DELETE is\nimplemented.\n\n## Rationale for this change\n\nDELETE with LIMIT currently appears to plan successfully, but the table\nprovider receives only the filters and deletes every matching row.\nRejecting the unsupported clause prevents a bounded delete from silently\nbecoming an unbounded one and matches the existing UPDATE LIMIT\nbehavior.\n\n## What changes are included in this PR?\n\n- reject DELETE LIMIT during SQL planning\n- remove the unreachable limit construction from delete_to_plan\n- replace the misleading EXPLAIN snapshots with error regressions, both\nwith and without WHERE\n- directly cover both planner rejection branches in the SQL integration\nsuite\n\n## What is the testing strategy for this PR?\n\n- cargo test -p datafusion-sqllogictest --test sqllogictests -- delete\n- cargo test -p datafusion-sql --lib (88 passed)\n- cargo test -p datafusion-sql --test sql_integration\nplan_delete_rejects_limit (2 passed)\n- cargo clippy -p datafusion-sql --all-targets -- -D warnings\n- cargo fmt --all -- --check\n\n## Are there any user-facing changes?\n\nYes. DELETE statements containing LIMIT now return a not-implemented\nplanning error instead of accepting the limit and potentially deleting\nevery matching row. There is no public Rust API change.\n\nImplementation and validation were completed with AI coding assistance\nunder the account owner’s direction.\n\n---------\n\nCo-authored-by: Andrew Lamb \u003candrew@nerdnetworks.org\u003e\nCo-authored-by: Martin Grigorov \u003cmartin-g@users.noreply.github.com\u003e\nCo-authored-by: Martin Tzvetanov Grigorov \u003cmgrigorov@apache.org\u003e"
    },
    {
      "commit": "409e3b89ba425fa9740b6c10de600d91f11ad6be",
      "tree": "e1dee7cae9aa3cd1787a358566a4d944ec997672",
      "parents": [
        "54a4bbf58b010e9f4c0e4deee1691e0b3883de92"
      ],
      "author": {
        "name": "Oleks V",
        "email": "comphead@users.noreply.github.com",
        "time": "Thu Oct 08 18:24:41 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 18:24:41 2026 +0000"
      },
      "message": "chore: Add \"Willingness to contribute\" dropdown to issue templates (#26120)\n\n## Which issue does this PR close?\n\n- No tracking issue, this is a small repository chore.\n\n## Rationale for this change\n\nPorts https://github.com/apache/datafusion-comet/pull/6688, which took\nthe idea from the [iceberg-rust issue\ntemplates](https://github.com/apache/iceberg-rust/tree/main/.github/ISSUE_TEMPLATE).\nReporters say up front whether they can contribute the fix or feature,\nso reviewers don\u0027t have to ask in a follow-up comment.\n\n## What changes are included in this PR?\n\nAdds an optional \"Willingness to contribute\" dropdown with three options\nto `bug_report.yml` and `feature_request.yml`. The wording is specific\nto bug fixes in the bug template and to features in the feature\ntemplate.\n\n## What is the testing strategy for this PR?\n\nIssue templates have no automated tests. Both files parse as YAML and\nthe dropdown has the same shape as in the iceberg-rust and Comet\ntemplates.\n\n## Are there any user-facing changes?\n\nNew issues filed from the bug report and feature request forms get one\nextra optional dropdown. There are no API changes."
    },
    {
      "commit": "54a4bbf58b010e9f4c0e4deee1691e0b3883de92",
      "tree": "ed208de30b5231774afa71be6e96c10a83f0cfd6",
      "parents": [
        "03204c0c84126fcfcc77ba3ef60c59b076d5538f"
      ],
      "author": {
        "name": "geographybuff",
        "email": "31372572+geographybuff@users.noreply.github.com",
        "time": "Thu Oct 08 16:44:32 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 16:44:32 2026 +0000"
      },
      "message": "fix: do not panic when displaying a Date64 scalar of i64::MIN (#26139)\n\n## Which issue does this PR close?\n\n- Closes #24892.\n\n## Rationale for this change\n\n`impl fmt::Display for ScalarValue` unwraps\n`chrono::Duration::try_milliseconds(v)` in the `Date64` arm. That\nreturns `None` for `i64::MIN`, which `Duration` cannot represent, so\nprinting such a literal panics, for example `EXPLAIN SELECT\narrow_cast(-9223372036854775808, \u0027Date64\u0027)`.\n\n#24893 proposed the same change and was closed as part of a batch of\nPRs, not on its merits. This PR redoes it on current `main`.\n\n## What changes are included in this PR?\n\n`try_milliseconds` and `checked_add_signed` are chained with `and_then`,\nso a value `Duration` cannot hold falls into the existing `None \u003d\u003e \"\"`\nbranch. That\u0027s how the neighbouring out-of-range case already formats\n(added for apache/arrow-rs#7728). One file, +7/-1.\n\n## What is the testing strategy for this PR?\n\n`test_display_date64_large_values` now also checks `i64::MIN` and\n`i64::MAX`:\n- Without the fix it panics at the same `unwrap` (`scalar/mod.rs:5651`).\n- With the fix, `cargo test -p datafusion-common --lib` passes 623\ntests, and `rustfmt --check` is clean.\n\n`cargo clippy -p datafusion-common --all-targets -- -D warnings` fails\nlocally on an unused import in `config.rs:4157`. That happens on\nunmodified `main` too, probably because I ran without the `parquet`\nfeature, so it\u0027s unrelated.\n\n**Not verified:** the issue\u0027s second reproduction, a `RANGE` window\nframe over a `Date64` column containing `i64::MIN`. I only ran the unit\ntest. If that path panics somewhere other than this `Display` impl, this\nPR doesn\u0027t fix it.\n\n## Are there any user-facing changes?\n\nNo panic: a `Date64` of `i64::MIN` displays as an empty string, like\nother out-of-range dates.\n\n**AI disclosure:** prepared with Claude Code (Claude Opus 5.5), which\nwrote the change and the test and ran the commands above.\n\nCo-authored-by: Claude Opus 5.5 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "03204c0c84126fcfcc77ba3ef60c59b076d5538f",
      "tree": "5fd0a86c037efddd030c093c55acf86503ccffbd",
      "parents": [
        "4978b3061c72753f73784f92d573eb0d903bcaca"
      ],
      "author": {
        "name": "Varun",
        "email": "tohuya6@gmail.com",
        "time": "Thu Oct 08 16:01:24 2026 +0000"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Oct 08 16:01:24 2026 +0000"
      },
      "message": "fix: keep the running hash for nested dictionaries in Spark xxhash64 (#25813)\n\n## Which issue does this PR close?\n\n- Closes #25799.\n\n## Rationale for this change\n\nSpark `xxhash64` returns different results for the same data depending\non whether a value inside a struct or list is dictionary-encoded. The\ndictionary fast path restarted from the default seed, so earlier\narguments and earlier list elements had no effect.\n\n## What changes are included in this PR?\n\nPorts the fix from apache/datafusion-comet#5757:\n\n- The dictionary fast path is used only when every row has the same\nrunning hash.\n- The fast path starts from that running hash instead of 42.\n\n## What is the testing strategy for this PR?\n\nTwo unit tests ported from Comet, both fail on main:\n\n- `test_dictionary_element_in_list_matches_decoded`: a dictionary inside\na list hashes the same as its decoded values.\n- `test_dictionary_with_nonuniform_seeds_matches_decoded`: rows with\ndifferent running hashes hash the same as the decoded values.\n\nThe existing Spark hash unit tests and sqllogictests pass. Both queries\nfrom the issue now return matching results for dictionary and plain\nvalues.\n\n## Are there any user-facing changes?\n\n`xxhash64` now matches Spark for dictionary-encoded values inside\nstructs and lists. No API changes.\n\nCo-authored-by: tohuya6 \u003c201355151+tohuya6@users.noreply.github.com\u003e\nCo-authored-by: Neil Conway \u003cneil.conway@gmail.com\u003e"
    }
  ],
  "next": "4978b3061c72753f73784f92d573eb0d903bcaca"
}
