Commit f3f6504
committed
fix(lambda): only push referenced params into the merged batch
`LambdaExpr` compresses the body's column-index projection by enumerating
every referenced `Column`/`LambdaVariable` index and packing them into a
dense range. That compression is correct for outer captures, but it
silently broke multi-parameter lambdas: a body like `(k, v) -> v` (where
`k` is unused) would have its `LambdaVariable("v")` re-projected from
index 1 to index 0 and then, at runtime, read the slot the higher-order
function had filled with `k`.
Per maintainer feedback on #22853, fix it without a breaking
change to `LambdaExpr::try_new` / `expressions::lambda(...)`:
* `LambdaExpr` now tracks `used_params: HashSet<String>` — the subset of
its own declared parameters that the body actually references. The set
is computed during a single walk of the body in `LambdaExpr::new`,
with a shadow stack that ignores `LambdaVariable`s bound by nested
lambdas. For
`(k, v) -> func(col, (k, v2) -> k + v2 + v)` the inner `k` shadows the
outer `k`, so only `v` flows up as used by the outer lambda.
* `LambdaArgument` gets an `Option<HashSet<String>>` for used parameter
names plus a non-breaking `new_with_used_params(...)` constructor.
The existing `new(...)` calls it with `None`, which preserves the old
"push every declared parameter" behavior.
* `LambdaArgument::evaluate` (through `merge_captures_with_variables`)
only evaluates and pushes the closures whose parameter name appears
in `used_params`, preserving the original declaration order. Unused
declared parameters therefore leave no slot in the merged batch, so
the body's compressed indices line up directly with the columns the
evaluator actually built.
* `HigherOrderFunctionExpr::evaluate` calls `new_with_used_params` and
forwards `lambda.used_params().clone()`, so all in-tree higher-order
UDFs benefit automatically without any callsite change.
No public API breakage: `LambdaExpr::try_new`, `expressions::lambda(...)`
and `LambdaArgument::new` keep their existing signatures. Two new
tests cover the unused-parameter case and the nested-lambda shadowing
case; existing tests in `physical-expr` and `expr` continue to pass.1 parent 46b508e commit f3f6504
4 files changed
Lines changed: 340 additions & 31 deletions
File tree
- datafusion
- expr/src
- physical-expr/src
- expressions
- sqllogictest/test_files/map
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
239 | 239 | | |
240 | 240 | | |
241 | 241 | | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
242 | 251 | | |
243 | 252 | | |
244 | 253 | | |
| |||
257 | 266 | | |
258 | 267 | | |
259 | 268 | | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
260 | 274 | | |
261 | 275 | | |
262 | 276 | | |
263 | 277 | | |
264 | 278 | | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
265 | 311 | | |
266 | 312 | | |
267 | 313 | | |
268 | 314 | | |
269 | 315 | | |
270 | 316 | | |
271 | | - | |
| 317 | + | |
272 | 318 | | |
273 | | - | |
| 319 | + | |
274 | 320 | | |
275 | 321 | | |
276 | 322 | | |
277 | 323 | | |
278 | 324 | | |
279 | 325 | | |
| 326 | + | |
280 | 327 | | |
281 | 328 | | |
282 | 329 | | |
| |||
344 | 391 | | |
345 | 392 | | |
346 | 393 | | |
| 394 | + | |
347 | 395 | | |
348 | 396 | | |
349 | 397 | | |
| |||
355 | 403 | | |
356 | 404 | | |
357 | 405 | | |
| 406 | + | |
358 | 407 | | |
359 | 408 | | |
360 | 409 | | |
| |||
365 | 414 | | |
366 | 415 | | |
367 | 416 | | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
368 | 433 | | |
369 | 434 | | |
370 | 435 | | |
371 | | - | |
372 | | - | |
373 | | - | |
374 | | - | |
375 | | - | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
376 | 446 | | |
377 | 447 | | |
378 | | - | |
379 | | - | |
380 | | - | |
381 | | - | |
382 | | - | |
383 | 448 | | |
384 | 449 | | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
385 | 467 | | |
386 | 468 | | |
387 | 469 | | |
| |||
0 commit comments