Skip to content

fix fk meta - #26469

Merged
XuPeng-SH merged 52 commits into
matrixorigin:mainfrom
daviszhen:0730-fix-fk-meta
Aug 6, 2026
Merged

fix fk meta#26469
XuPeng-SH merged 52 commits into
matrixorigin:mainfrom
daviszhen:0730-fix-fk-meta

Conversation

@daviszhen

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 #25388

What this PR does / why we need it:

  • information_schema.KEY_COLUMN_USAGE 改为从 mo_foreign_keys 提供 FK 本地列到引用列的映射及复合键顺序。
  • information_schema.REFERENTIAL_CONSTRAINTS 正确展示默认 NO ACTION、显式 RESTRICT,并按父表 ID 关联索引以避免同名列导致重复。
  • 新建 FK 持久化默认动作为 NO_ACTION,显式动作保持原值。
  • v4_0_6 租户升级解析历史 rel_createsql,回填旧复合 FK 的列序和默认/显式动作语义。
  • 增加 planner、升级、sysview UT,以及 FK BVT 覆盖默认/显式动作、复合 FK 与无关索引场景。

@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 →

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

Requesting changes on exact head 3d9239a.

The earlier ALTER-added/unnamed-FK, explicit RESTRICT, and competing-secondary-index findings are addressed. Three blocking closure gaps remain:

  1. pkg/bootstrap/versions/v4_0_6/upgrade.go:345 only accepts an index when candidate.columns and key.columns have the same length. That contradicts the new planner contract at pkg/sql/plan/build_ddl.go:4816, which deliberately accepts an ordered leading prefix. A legacy table with PRIMARY KEY(id, code) and an FK referencing parent(id) is valid before and after this change, but the migration returns an empty referenced_index_name; a new FK with the same shape records PRIMARY. My focused counterexample reproduced actual "" versus expected "PRIMARY". Backfill must use the same prefix and deterministic key-selection contract as new binding.

  2. referenced_index_name is denormalized at bind time and REFERENTIAL_CONSTRAINTS now trusts it unconditionally, but its index lifecycle is not closed. Both standalone DROP INDEX and ALTER TABLE ... DROP INDEX currently accept a UNIQUE index even when the parent has RefChildTbls, and neither path rejects the operation nor rebinds/updates child ForeignKeyDef and mo_foreign_keys. Therefore parent UNIQUE KEY uq_parent(id), child FK -> uq_parent, DROP INDEX uq_parent leaves UNIQUE_CONSTRAINT_NAME pointing to a constraint that no longer exists. Either reject dropping the selected referenced key or atomically rebind and update every engine/catalog consumer; add the public SQL regression.

  3. The same-version offset fix at pkg/bootstrap/service_upgrade_tenant.go:253 only repairs the background executor. Existing tenants do not yet have the three new mo_foreign_keys columns, while the new binary immediately selects/inserts them. CN startup schedules BootstrapUpgrade asynchronously and starts the SQL frontend; asyncUpgradeTenantTask waits for its timer, and MaybeUpgradeTenant returns immediately when 4.0.6 == 4.0.6. In that deterministic window, ordinary CREATE TABLE reaches GetFkReferredTo and queries missing columns, and FK DDL also inserts them. Make tenant admission/readiness offset-aware or otherwise keep old/new catalog access compatible until the tenant migration commits. Add a same-version-offset test that executes DDL before the background task runs.

Also refresh test/distributed/cases/foreign_key/fk_show_columns.result, which still contains the old 16-column mo_foreign_keys schema.

Local validation: full tests passed for pkg/bootstrap/versions/v4_0_6, pkg/util/sysview, pkg/sql/plan, pkg/bootstrap, and pkg/sql/compile; vet passed for those owning/dependent packages. The prefix counterexample fails for the semantic reason above, and a focused planner witness confirms DROP INDEX remains publicly reachable. Current CI is green, but both upgrade compatibility jobs were skipped.

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

Approved on exact head 04dc7bc.

The previous blocking findings are closed systemically:

  1. Legacy FK backfill now uses the same ordered-leading-prefix and deterministic PRIMARY/lexical-UNIQUE selection contract as new binding, with prefix, non-prefix, precedence, and tie controls.
  2. Referenced-key lifetime is closed across standalone DROP INDEX, ALTER TABLE DROP INDEX/KEY, and DROP PRIMARY KEY. New definitions protect the exact persisted binding; legacy definitions fail safe for every compatible key because their historical selection is not provable. A same-statement self-FK removal remains allowed, and an unselected compatible UNIQUE remains droppable for persisted bindings.
  3. FK catalog access negotiates the tenant-local 16/19-column layout. Before all metadata columns exist, CREATE/ALTER uses legacy reads and explicit 16-column inserts; after commit it switches to the extended layout. This removes the deterministic async same-version-offset DDL failure window without blocking tenant admission or adding shared upgrade state.
  4. fk_show_columns expectations are refreshed, and BVT coverage now verifies the selected UNIQUE/PRIMARY cannot be removed while the surviving metadata remains stable.

Fresh local validation passed for build, vet, and full tests in pkg/bootstrap/versions/v4_0_6, pkg/sql/plan, pkg/bootstrap, pkg/sql/compile, and pkg/util/sysview. CI is running and was not awaited.

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

Re-reviewed exact head 04dc7bc from first principles after refreshing all commits, comments, reviews, and checks. No blocking findings remain.

This pass independently revalidated the full closure:

  1. New binding and legacy backfill share the ordered-leading-prefix contract and deterministic PRIMARY/lexical-UNIQUE selection. Prefix, non-prefix, PRIMARY precedence, and competing-UNIQUE controls are covered.
  2. Referenced-key lifetime is closed across standalone DROP INDEX, ALTER TABLE DROP INDEX/KEY, and DROP PRIMARY KEY. Persisted bindings protect only the selected key; legacy empty bindings fail safe across every compatible key; same-statement self-FK removal remains valid.
  3. The asynchronous same-version tenant-upgrade window is safe. Catalog reads negotiate the tenant-local layout, legacy writes name all 16 columns explicitly, and DML metadata shared locks serialize against ALTER TABLE exclusive metadata locks or force a definition-changed retry. A row therefore cannot be inserted behind the migration scan and remain permanently unbackfilled.
  4. Before origin columns exist, action provenance degrades conservatively to LEGACY_AMBIGUOUS instead of inventing precision, while ON DELETE/UPDATE behavior remains exact. After all columns commit, extended 19-column writes preserve exact binding and origin metadata.
  5. The public BVT oracle verifies that an unselected compatible UNIQUE is droppable, selected UNIQUE/PRIMARY keys are rejected, and referential metadata survives the rejected DDL.

Fresh local validation passed: build, vet, and complete package tests with cache disabled for pkg/bootstrap/versions/v4_0_6, pkg/sql/plan, pkg/bootstrap, pkg/sql/compile, and pkg/util/sysview. CI is still running and was not awaited; both upgrade compatibility launch jobs are currently skipped.

@aunjgr aunjgr 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.

Reviewed the full diff at ee05af5 against merge-base ffc1603. No blocking correctness findings. The FK metadata migration, composite ordering, action provenance, referenced-index lifecycle, asynchronous tenant-upgrade compatibility, and failure-path handling are coherent. Focused tests passed for ./pkg/bootstrap/versions/v4_0_6, ./pkg/bootstrap, ./pkg/sql/plan, and ./pkg/util/sysview. The broader ./pkg/sql/compile run was blocked locally by the sandbox denying Unix socket creation in an unrelated lockservice test; PR CI is green.

# Conflicts:
#	pkg/bootstrap/service_upgrade_tenant.go
#	pkg/bootstrap/service_upgrade_tenant_test.go
#	pkg/bootstrap/versions/v4_0_6/upgrade_test.go
#	pkg/util/sysview/predefined_test.go
#	test/distributed/cases/database/system_table.result
@mergify

mergify Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-08-06 11:18 UTC · Rule: main · triggered by rule Automatic queue on approval for main
  • 🟠 Checks running · in-place
  • 🚫 Left the queue2026-08-06 12:33 UTC · at 556b422f11a7f082bb7b8b9db761cb5d58cddd91

This pull request spent 1 hour 15 minutes 38 seconds in the queue, with no time running CI.

Waiting for
  • any of: [🛡 GitHub branch protection]
    • 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)
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
    • check-success = Matrixone CI / SCA Test on Linux/arm64
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage
All conditions
  • any of [🛡 GitHub branch protection]:
    • 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)
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
    • check-success = Matrixone CI / SCA Test on Linux/arm64
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-approved [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-neutral = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-skipped = Matrixone UT Coverage / UT Coverage on Ubuntu/x86

Reason

Pull request #26469 has been dequeued

Pull request from fork cannot be queued. This pull request comes from a fork, and Mergify needs the author's permission to update its branch.

The author needs to enable "Allow edits from maintainers" on this pull request.

Failing checks:

Hint

You should look at the reason for the failure and decide if the pull request needs to be fixed or if you want to requeue it.
If you do update this pull request, it will automatically be requeued once the queue conditions match again.
If you think this was a flaky issue instead, you can requeue the pull request, without updating it, by posting a @mergifyio queue comment.

Tick the box to put this pull request back in the merge queue (same as @mergifyio queue).

  • Requeue this pull request

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

Labels

dequeued kind/bug Something isn't working size/XXL Denotes a PR that changes 2000+ lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants