Skip to content

GH-39688: [R] "Error: Filter expression not supported for Arrow Datasets" using "date" expression rigth hand side of a filter - #51291

Merged
thisisnic merged 3 commits into
apache:mainfrom
thisisnic:GH-39688-shadowed-names
Sep 23, 2026
Merged

thisisnic merged 3 commits into
apache:mainfrom
thisisnic:GH-39688-shadowed-names

Conversation

@thisisnic

@thisisnic thisisnic commented Sep 10, 2026 •

Copy link
Copy Markdown
Member

Rationale for this change

Error when user tries to use local variable in dplyr pipeline in Arrow

What changes are included in this PR?

Make sure we attach them to the mask

Are these changes tested?

Yup

Are there any user-facing changes?

Yep

@thisisnic
thisisnic requested a review from jonkeane as a code owner September 10, 2026 17:25
Copilot AI lite review requested due to automatic review settings September 10, 2026 17:25
@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #39688 has been automatically assigned in GitHub to PR creator.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

add_user_variables_to_mask() uses get0() without inherits=TRUE, which can fail to find lexically-scoped variables in parent environments and still diverge from dplyr’s name resolution.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR addresses GH-39688 in Arrow’s R dplyr integration by ensuring that user-defined variables referenced in expressions (e.g., date, day) are correctly resolved even when they share names with Arrow’s function bindings, matching dplyr’s intended masking behavior.

Changes:

  • Extend arrow_eval() to bind user variables into the evaluation mask when they would otherwise be shadowed by function bindings.
  • Add regression tests covering both filter() and mutate() when symbols like date/day collide with function bindings.
File summaries
File Description
r/R/dplyr-eval.R Adds logic to detect and bind shadowed user variables into the evaluation mask.
r/tests/testthat/test-dplyr-filter.R Adds a regression test for filter() symbol collisions with bindings (date, day).
r/tests/testthat/test-dplyr-mutate.R Adds a regression test for mutate() symbol collisions with bindings (day).
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread r/R/dplyr-eval.R

@jonkeane jonkeane left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few questions on this one

Comment thread r/R/dplyr-eval.R Outdated
Comment thread r/tests/testthat/test-dplyr-filter.R
Copilot AI review requested due to automatic review settings September 17, 2026 21:12
@thisisnic
thisisnic force-pushed the GH-39688-shadowed-names branch from 106a836 to 746d095 Compare September 17, 2026 21:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The newly added mutate regression test doesn’t actually exercise the function-binding-vs-variable resolution scenario it claims to cover, leaving the key behavior under-tested.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

r/tests/testthat/test-dplyr-mutate.R:788

  • This new test claims to verify that the day binding is still used when day appears in function position, but lubridate::day(date) bypasses that resolution (it will work even if the unqualified day() binding were broken). To actually cover the GH-39688 scenario, call day(date) unqualified (with lubridate attached so regular dplyr can resolve it) while still using the local day variable as a value.
      mutate(avg_int = mean(int)) |>
      collect(),
    tbl
  )
  # A row limit between arrange() and mutate() still uses the sorted rows
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 17, 2026 21:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The core fix targets Dataset behavior (GH-39688) but the added tests only exercise the Table path, and the new mask-binding logic adds avoidable per-expression overhead.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread r/R/dplyr-eval.R
# all.vars() returns symbols that aren't in function position
vars_in_expr <- all.vars(quo_get_expr(expr))
columns <- names(mask$.data)
shadowed <- setdiff(intersect(vars_in_expr, ls(function_env, all.names = TRUE)), columns)
Comment on lines +568 to +572
test_that("filter() with a variable from the calling environment", {
my_constant <- "d"
compare_dplyr_binding(
.input |>
filter(chr == my_constant) |>
Copilot AI review requested due to automatic review settings September 21, 2026 22:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The fix targets a Dataset-specific failure mode, but the new regression tests appear to exercise only the Table path, so a Dataset regression test should be added to prevent recurrence.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 Low severity

Open (3)

Comment thread r/R/dplyr-eval.R
Comment on lines +26 to +29
# Likewise, look for R variables referenced in expr that share a name with a
# function binding (like `date` or `day`) and add them to the mask, so that
# the user's variable is found rather than the binding, as dplyr would do.
add_user_variables_to_mask(expr, mask)

@jonkeane jonkeane left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, that my_constant test might be slightly duplicative of tests elsewhere, but having that in line is nice and clear that we care about both of those.

@github-actions github-actions Bot added awaiting merge Awaiting merge and removed awaiting committer review Awaiting committer review labels Sep 22, 2026
@thisisnic
thisisnic merged commit aea76a1 into apache:main Sep 23, 2026
36 checks passed
@thisisnic thisisnic removed the awaiting merge Awaiting merge label Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants