Skip to content

fix(frontend): align role rule merge semantics#24929

Merged
mergify[bot] merged 5 commits into
matrixorigin:mainfrom
ouyuanning:improve-mo-from-24792
Jun 12, 2026
Merged

fix(frontend): align role rule merge semantics#24929
mergify[bot] merged 5 commits into
matrixorigin:mainfrom
ouyuanning:improve-mo-from-24792

Conversation

@ouyuanning

@ouyuanning ouyuanning commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue #23271

What this PR does / why we need it:

This PR ports the latest role rewrite-rule and SET ROLE behavior from #24792 to the current branch.

Changes:

  • Merge same-name role rewrite rules as a source-row visibility union for active roles. Compatible simple single-table SELECT rewrites are merged with WHERE (...) OR (...).
  • Clarify that this is intentionally not a UNION DISTINCT optimization for partial projections. If two visible base rows project to the same value, both rows remain visible.
  • Keep row-wise projection expressions mergeable, such as select a + 1 as b ..., while aggregate/window/table-function and other non-compatible shapes still fall back to the later rule.
  • Keep the current primary role unchanged for SET SECONDARY ROLE ALL; it only enables secondary roles.
  • After SET ROLE, switch the current role to the target role and invalidate the privilege/rule cache so subsequent privilege checks use the new role.
  • Update frontend unit tests and distributed access-control cases, including duplicate projected values and row-wise expression projection coverage.

Review note:

  • The partial-projection behavior is a deliberate semantic choice for role rules: multi-role visibility is based on base rows, not deduplicated projected result sets. The new BVT case uses two distinct visible rows that both project to a = 1 and expects count(*) = 2 after SET SECONDARY ROLE ALL.

Validation:

  • gofmt -w pkg/frontend/rewrite_rule.go pkg/frontend/rewrite_rule_test.go
  • git diff --check
  • go test ./pkg/frontend -run 'TestMergeRewriteRules|TestRewriteRuleMergeShapeForRule|TestLoadRuleCacheIncludesSecondaryRoles|TestRewriteSQLPropagatesRuleCacheLoadError|TestValidateRewriteRuleSQL' could not complete locally because vendor metadata is inconsistent with go.mod.
  • go test -mod=mod ./pkg/frontend -run 'TestMergeRewriteRules|TestRewriteRuleMergeShapeForRule|TestLoadRuleCacheIncludesSecondaryRoles|TestRewriteSQLPropagatesRuleCacheLoadError|TestValidateRewriteRuleSQL' reached CGO compilation but could not complete locally because usearch.h and xxhash.h are missing.
  • The role_rule.sql mo-tester case was updated, but not run locally because no MatrixOne server is listening on the configured 127.0.0.1:6001.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@ouyuanning ouyuanning changed the title fix(frontend): improve role rule merge and set role behavior fix(frontend): align role rule merge semantics Jun 11, 2026

@XuPeng-SH XuPeng-SH 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.

I found two blocking regressions in the frontend changes.

  1. pkg/frontend/rewrite_rule.go:428-446 narrows mergeable rewrite rules to bare column / * projections only. That makes identical row-preserving projections like select a + 1 as b from db1.t1 where ... stop merging, so the later role silently overwrites the earlier one instead of unioning both roles' visibility. The new expectation in pkg/frontend/rewrite_rule_test.go:777-779 already demonstrates this regression.

  2. pkg/frontend/authenticate.go:3503-3531 stops rebinding the current role during SET SECONDARY ROLE ALL, but the privilege/rule loaders still seed from tenant.GetDefaultRoleID() unconditionally (pkg/frontend/rewrite_rule.go:223-239, pkg/frontend/authenticate.go:7273-7287, 8688-8704). If the session's current primary role was revoked after login, SET SECONDARY ROLE ALL now keeps that stale role active and reloads caches with it, which is a privilege-revocation regression. Please either validate/fallback the primary role here or stop treating DefaultRoleID as implicitly valid downstream.

@ouyuanning

Copy link
Copy Markdown
Contributor Author

I found two blocking regressions in the frontend changes.

  1. pkg/frontend/rewrite_rule.go:428-446 narrows mergeable rewrite rules to bare column / * projections only. That makes identical row-preserving projections like select a + 1 as b from db1.t1 where ... stop merging, so the later role silently overwrites the earlier one instead of unioning both roles' visibility. The new expectation in pkg/frontend/rewrite_rule_test.go:777-779 already demonstrates this regression.
  2. pkg/frontend/authenticate.go:3503-3531 stops rebinding the current role during SET SECONDARY ROLE ALL, but the privilege/rule loaders still seed from tenant.GetDefaultRoleID() unconditionally (pkg/frontend/rewrite_rule.go:223-239, pkg/frontend/authenticate.go:7273-7287, 8688-8704). If the session's current primary role was revoked after login, SET SECONDARY ROLE ALL now keeps that stale role active and reloads caches with it, which is a privilege-revocation regression. Please either validate/fallback the primary role here or stop treating DefaultRoleID as implicitly valid downstream.

感谢指出这个问题。如果这里的目标是保持旧的 UNION DISTINCT 结果集语义,那么你的判断是对的:直接改成 OR 合并并不是等价变换。

我重新确认后,这个 PR 现在明确采用的是另一层语义:多 role rewrite rule 合并表示“基础行可见性并集”。也就是说,只要任意一个 active
role 允许某条基础表行,这条基础行就应该保持可见。在这个语义下,谓词 OR 合并是有意为之,包括 partial projection 场景。

例如两条不同的基础行都投影成 a = 1 时,返回两行是预期行为;如果用 UNION DISTINCT 按投影结果去重,反而会隐藏其中一条 role 允许可
见的基础行。

我已经更新了 PR 来明确这一点:

  • 补充代码注释,说明 OR merge 不是 partial projection 上的 UNION DISTINCT 等价优化。
  • 增加测试覆盖:两条不同可见基础行投影成相同值时,SET SECONDARY ROLE ALLcount(*) 仍为 2
  • 保持逐行投影表达式可合并,例如 select a + 1 as b ...,避免兼容的多 role 规则退化为后一个 role 覆盖前一个 role。
  • 对不适合直接 OR 合并的形态仍然 fallback,例如 aggregate/window/table-function projection、顶层 ORDER BY/LIMITGROUP BY
    HAVINGDISTINCT 等。

所以我没有把 OR 合并限制到 select *,而是把当前预期的“基础行可见性并集”语义在代码注释和测试里显式固定下来。

@mergify mergify Bot added the queued label Jun 12, 2026
@mergify

mergify Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-06-12 04:00 UTC · Rule: main
  • Checks passed · in-place
  • Merged2026-06-12 05:36 UTC · at ca9f02a0b879cd866c44080a753b9147e6388a4a · squash

This pull request spent 1 hour 36 minutes 15 seconds in the queue, including 1 hour 2 minutes 51 seconds running CI.

Required conditions to merge
  • #approved-reviews-by >= 1 [🛡 GitHub branch protection]
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-decision = APPROVED [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-neutral = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-skipped = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / SCA Test on Ubuntu/x86
    • check-neutral = Matrixone CI / SCA Test on Ubuntu/x86
    • check-skipped = Matrixone CI / SCA Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-neutral = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-skipped = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Utils CI / Coverage
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/enhancement size/L Denotes a PR that changes [500,999] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants