Skip to content

schemastore: fix rename table when source database is not specified#4416

Open
lidezhu wants to merge 21 commits intomasterfrom
ldz/fix-rename-table0310
Open

schemastore: fix rename table when source database is not specified#4416
lidezhu wants to merge 21 commits intomasterfrom
ldz/fix-rename-table0310

Conversation

@lidezhu
Copy link
Collaborator

@lidezhu lidezhu commented Mar 10, 2026

What problem does this PR solve?

Issue Number: close #4424

What is changed and how it works?

This pull request addresses a bug in the schema store's handling of RENAME TABLE DDL events, particularly when dealing with cross-database renames. The changes enhance the accuracy of identifying the original schema and table names, ensuring that the persisted DDL events correctly reflect the source and target qualifiers. This leads to more reliable DDL event generation and improved data consistency across different database operations.

Highlights

  • Improved Rename Table DDL Handling: The logic for determining the original schema and table names during RENAME TABLE DDL event processing has been enhanced to ensure accurate identification, especially for cross-database renames.
  • New Query Parsing Helper: A dedicated helper function, parseRenameTableQueryInfo, was introduced to robustly extract old schema and table names from DDL queries, centralizing and improving parsing logic.
  • Expanded Test Coverage: New unit tests were added to cover various cross-database table rename scenarios, validating the correct generation of DDL events.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code

Questions

Will it cause performance regression or break compatibility?
Do you need to update user documentation, design documentation or monitoring documentation?

Release note

Please refer to [Release Notes Language Style Guide](https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/release-notes-style-guide.html) to write a quality release note.

If you don't think this PR needs a release note then fill it with `None`.

Summary by CodeRabbit

  • Bug Fixes
    • Improved rename handling to derive original schema/table names from multiple sources (including parsed query info), handle multi-table renames, and emit reconstructed persisted DDL only when both source identifiers are known; logging updated for consistent name reporting.
  • Tests
    • Added tests for cross-database rename scenarios (including raw-args/JSON paths) to validate persisted DDL generation and identifier mapping.

@ti-chi-bot ti-chi-bot bot added do-not-merge/needs-linked-issue release-note Denotes a PR that will be considered when it comes time to generate release notes. labels Mar 10, 2026
@ti-chi-bot
Copy link

ti-chi-bot bot commented Mar 10, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign lidezhu for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Mar 10, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Reworks rename-table handling to reconstruct old schema/table names from parsed query, RenameTableArgs (with compatibility for older job versions), and InvolvingSchemaInfo; defers rebuilding persisted event.Query until both old names are known; adds parsing/compatibility helpers and cross-database rename tests.

Changes

Cohort / File(s) Summary
RenameTable DDL Handler Enhancement
logservice/schemastore/persist_storage_ddl_handlers.go
Consolidates old-name reconstruction from multiple sources (parsed query, RenameTableArgs, InvolvingSchemaInfo); adds parseRenameTableQueryInfo and getRenameTableArgsCompatible; applies post-parse overrides and only updates event.Query when both old schema/table are available.
RenameTable Test Coverage
logservice/schemastore/persist_storage_test.go
Adds cross-database rename scenarios to TestRenameTable (including JSON raw-args path) to validate SalesDB → ArchiveDB mappings; imports encoding/json for test construction.

Sequence Diagram(s)

sequenceDiagram
  participant JobProducer as JobProducer
  participant Handler as PersistHandler
  participant Parser as SQLParser
  participant Storage as SchemaStore

  JobProducer->>Handler: submit RenameTable job (RawArgs / InvolvingSchemaInfo)
  Handler->>Parser: parse query via parseRenameTableQueryInfo
  Parser-->>Handler: parsed old/new schema.table info
  Handler->>Handler: getRenameTableArgsCompatible(RenameTableArgs)
  Handler->>Handler: reconcile old names (parsed, args, involvingInfo)
  alt old schema/table both present
    Handler->>Storage: build persisted DDL with updated event.Query
  else incomplete old names
    Handler->>Storage: persist event without modifying event.Query
  end
  Storage-->>Handler: ack
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

lgtm, size/XXL, needs-cherry-pick-release-8.5

Suggested reviewers

  • wk989898
  • wlwilliamx

Poem

🐰 I hop through AST and byte,
I stitch old names from dark and light,
From SalesDB hills to Archive vale,
I patch the query and leave a trail,
A tiny hop — the rename's right!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description is incomplete with missing critical information required by the template. Complete the PR description by: (1) answering the 'Will it cause performance regression or break compatibility?' question, (2) answering the 'Do you need to update documentation?' question, and (3) providing an actual release note instead of the template placeholder.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'schemastore: fix rename table when source database is not specified' directly describes the main change: handling rename table operations when the source database is missing, which aligns with the code changes adding multi-source fallback logic for deriving old schema/table names.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ldz/fix-rename-table0310

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
logservice/schemastore/persist_storage_test.go (1)

3137-3154: Exercise both supported job versions.

The production branch now special-cases model.JobVersion1 and model.JobVersion2, but this test only covers model.JobVersion2. Please add a JobVersion1 case, or table-drive the version, so the older format can't regress unnoticed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@logservice/schemastore/persist_storage_test.go` around lines 3137 - 3154,
Test only exercises model.JobVersion2; add coverage for model.JobVersion1 (or
convert to a table-driven subtest iterating over
[]model.JobVersion{model.JobVersion1, model.JobVersion2}) so both formats are
validated. For each iteration set job.Version accordingly, call
job.FillArgs(...) and
buildPersistedDDLEventForRenameTable(buildPersistedDDLEventFuncArgs{...}) using
the same databaseMap/tableMap, then assert the expected ddl.Query for that
version (referencing job.Version, FillArgs,
buildPersistedDDLEventForRenameTable, buildPersistedDDLEventFuncArgs, and
ddl.Query); ensure test names reflect the version for easier debug.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 733-738: model.GetRenameTableArgs(args.job) failures are currently
ignored causing silent fallback to InvolvingSchemaInfo; change this by catching
the error from model.GetRenameTableArgs (while still preserving the existing
behavior) and log the failure with context (include args.job identifier/version
and the error) before falling back. Update the block that calls
model.GetRenameTableArgs (around renameArgs) to log the error when err != nil,
referencing renameArgs, args.job and InvolvingSchemaInfo so the diagnostic
contains which job/version failed and the error message.

---

Nitpick comments:
In `@logservice/schemastore/persist_storage_test.go`:
- Around line 3137-3154: Test only exercises model.JobVersion2; add coverage for
model.JobVersion1 (or convert to a table-driven subtest iterating over
[]model.JobVersion{model.JobVersion1, model.JobVersion2}) so both formats are
validated. For each iteration set job.Version accordingly, call
job.FillArgs(...) and
buildPersistedDDLEventForRenameTable(buildPersistedDDLEventFuncArgs{...}) using
the same databaseMap/tableMap, then assert the expected ddl.Query for that
version (referencing job.Version, FillArgs,
buildPersistedDDLEventForRenameTable, buildPersistedDDLEventFuncArgs, and
ddl.Query); ensure test names reflect the version for easier debug.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec8027be-f37c-48e9-a37e-b8226868bbf5

📥 Commits

Reviewing files that changed from the base of the PR and between 6423bf1 and 840c32a.

📒 Files selected for processing (2)
  • logservice/schemastore/persist_storage_ddl_handlers.go
  • logservice/schemastore/persist_storage_test.go

@ti-chi-bot ti-chi-bot bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Mar 10, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
logservice/schemastore/persist_storage_ddl_handlers.go (1)

736-755: ⚠️ Potential issue | 🟠 Major

Apply the recovered old schema/table back to the persisted rename fields.

This block only uses RenameTableArgs / parsed SQL to rebuild event.Query. event.ExtraSchemaID, event.ExtraSchemaName, and event.ExtraTableName still come from tableMap, but later code uses those fields to detect cross-schema renames and to populate BlockedTableNames, UpdatedSchemas, and TableNameChange.DropName. In the stale-snapshot case described above, the query becomes correct while the persisted old side of the rename is still wrong.

💡 Suggested fix
 	// RenameTableArgs keeps the old schema name even when the query omits it.
 	if args.job.Version == model.JobVersion1 || args.job.Version == model.JobVersion2 {
 		renameArgs, err := model.GetRenameTableArgs(args.job)
-		if err == nil && renameArgs.OldSchemaName.O != "" {
-			oldSchemaName = renameArgs.OldSchemaName.O
+		if err == nil {
+			if renameArgs.OldSchemaID != 0 {
+				event.ExtraSchemaID = renameArgs.OldSchemaID
+			}
+			if renameArgs.OldSchemaName.O != "" {
+				oldSchemaName = renameArgs.OldSchemaName.O
+			}
 		}
 	}
 	if queryInfo, parsed := parseRenameTableQueryInfo(args.job.Query); parsed {
 		if queryInfo.oldTableName != "" {
 			oldTableName = queryInfo.oldTableName
@@
 		if queryInfo.oldSchemaName != "" {
 			oldSchemaName = queryInfo.oldSchemaName
 		}
 	}
-	if oldSchemaName != "" && oldTableName != "" {
+	if oldSchemaName != "" {
+		event.ExtraSchemaName = oldSchemaName
+	}
+	if oldTableName != "" {
+		event.ExtraTableName = oldTableName
+	}
+	if event.ExtraSchemaName != "" && event.ExtraTableName != "" {
 		event.Query = fmt.Sprintf("RENAME TABLE %s TO %s",
-			common.QuoteSchema(oldSchemaName, oldTableName),
+			common.QuoteSchema(event.ExtraSchemaName, event.ExtraTableName),
 			common.QuoteSchema(event.SchemaName, event.TableName))
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@logservice/schemastore/persist_storage_ddl_handlers.go` around lines 736 -
755, The persisted rename handling builds event.Query from RenameTableArgs /
parseRenameTableQueryInfo but fails to update the persisted rename fields
(event.ExtraSchemaID, event.ExtraSchemaName, event.ExtraTableName) causing
downstream logic to see stale old-side values; after you compute oldSchemaName
and oldTableName (from model.GetRenameTableArgs and parseRenameTableQueryInfo),
update event.ExtraSchemaName and event.ExtraTableName to those recovered values
and set event.ExtraSchemaID appropriately (lookup the schema ID like tableMap
did or clear it if unknown) so the persisted event fields match the
reconstructed query and downstream cross-schema detection (BlockedTableNames,
UpdatedSchemas, TableNameChange.DropName) uses the corrected old side.
♻️ Duplicate comments (1)
logservice/schemastore/persist_storage_ddl_handlers.go (1)

736-742: ⚠️ Potential issue | 🟡 Minor

Don't silently swallow GetRenameTableArgs failures.

If decoding rename args fails here, we quietly fall back to InvolvingSchemaInfo, which is exactly the normalized-name path this change is trying to avoid. Please at least emit a warning with the job id/version before falling back.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@logservice/schemastore/persist_storage_ddl_handlers.go` around lines 736 -
742, The code currently swallows errors from model.GetRenameTableArgs when
extracting RenameTableArgs for args.job.Version 1 or 2, which can mask decoding
failures and cause silent fallback to InvolvingSchemaInfo; update the block that
calls model.GetRenameTableArgs (and handles renameArgs/OldSchemaName) to log a
warning including the job identifier and version when err != nil (use
args.job.ID or equivalent and args.job.Version), then continue the existing
fallback behavior—do not change control flow, just emit a clear
processLogger.Warn/processLogger.Warning (or the project's logger) message
referencing GetRenameTableArgs, args.job.ID, and args.job.Version so failures
aren’t silent.
🧹 Nitpick comments (1)
logservice/schemastore/persist_storage_test.go (1)

3132-3174: These new cases still don't reproduce the stale-snapshot bug.

tableMap[101].SchemaID is left as 200, so the old schema is already available from the store even if RenameTableArgs are ignored. The regression described in the handler comment only appears when the snapshot already shows the table in ArchiveDB; please set the table-map entry to the new schema and assert ddl.ExtraSchemaID / ddl.ExtraSchemaName as well.

🧪 Suggested test tightening
 		databaseMap: map[int64]*BasicDatabaseInfo{
 		},
 		tableMap: map[int64]*BasicTableInfo{
-			101: {SchemaID: 200, Name: "t1"},
+			101: {SchemaID: 100, Name: "t1"},
 		},
 	})
+	assert.Equal(t, int64(200), ddl.ExtraSchemaID)
+	assert.Equal(t, "SalesDB", ddl.ExtraSchemaName)
+	assert.Equal(t, "t1", ddl.ExtraTableName)
 	assert.Equal(t, "RENAME TABLE `SalesDB`.`t1` TO `ArchiveDB`.`t1`", ddl.Query)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@logservice/schemastore/persist_storage_test.go` around lines 3132 - 3174, The
failing test doesn't reproduce the stale-snapshot bug because
tableMap[101].SchemaID remains 200 (old schema) so the old schema is present;
change the second case's tableMap entry for table id 101 to have SchemaID: 100
(the new ArchiveDB schema) and then add assertions that ddl.ExtraSchemaID == 100
and ddl.ExtraSchemaName == "ArchiveDB" (use the persisted DDL from
buildPersistedDDLEventForRenameTable and check ddl.ExtraSchemaID /
ddl.ExtraSchemaName) so the test covers the scenario where the snapshot already
shows the table in ArchiveDB; reference: buildRenameTableJobForTest,
RenameTableArgs, buildPersistedDDLEventForRenameTable, BasicTableInfo,
ddl.ExtraSchemaID, ddl.ExtraSchemaName.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 736-755: The persisted rename handling builds event.Query from
RenameTableArgs / parseRenameTableQueryInfo but fails to update the persisted
rename fields (event.ExtraSchemaID, event.ExtraSchemaName, event.ExtraTableName)
causing downstream logic to see stale old-side values; after you compute
oldSchemaName and oldTableName (from model.GetRenameTableArgs and
parseRenameTableQueryInfo), update event.ExtraSchemaName and
event.ExtraTableName to those recovered values and set event.ExtraSchemaID
appropriately (lookup the schema ID like tableMap did or clear it if unknown) so
the persisted event fields match the reconstructed query and downstream
cross-schema detection (BlockedTableNames, UpdatedSchemas,
TableNameChange.DropName) uses the corrected old side.

---

Duplicate comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 736-742: The code currently swallows errors from
model.GetRenameTableArgs when extracting RenameTableArgs for args.job.Version 1
or 2, which can mask decoding failures and cause silent fallback to
InvolvingSchemaInfo; update the block that calls model.GetRenameTableArgs (and
handles renameArgs/OldSchemaName) to log a warning including the job identifier
and version when err != nil (use args.job.ID or equivalent and
args.job.Version), then continue the existing fallback behavior—do not change
control flow, just emit a clear processLogger.Warn/processLogger.Warning (or the
project's logger) message referencing GetRenameTableArgs, args.job.ID, and
args.job.Version so failures aren’t silent.

---

Nitpick comments:
In `@logservice/schemastore/persist_storage_test.go`:
- Around line 3132-3174: The failing test doesn't reproduce the stale-snapshot
bug because tableMap[101].SchemaID remains 200 (old schema) so the old schema is
present; change the second case's tableMap entry for table id 101 to have
SchemaID: 100 (the new ArchiveDB schema) and then add assertions that
ddl.ExtraSchemaID == 100 and ddl.ExtraSchemaName == "ArchiveDB" (use the
persisted DDL from buildPersistedDDLEventForRenameTable and check
ddl.ExtraSchemaID / ddl.ExtraSchemaName) so the test covers the scenario where
the snapshot already shows the table in ArchiveDB; reference:
buildRenameTableJobForTest, RenameTableArgs,
buildPersistedDDLEventForRenameTable, BasicTableInfo, ddl.ExtraSchemaID,
ddl.ExtraSchemaName.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3eff6e30-1c19-40ed-8665-738606e98a49

📥 Commits

Reviewing files that changed from the base of the PR and between 332bbfc and 1b3fcf0.

📒 Files selected for processing (2)
  • logservice/schemastore/persist_storage_ddl_handlers.go
  • logservice/schemastore/persist_storage_test.go

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a bug in the schema store's handling of RENAME TABLE DDL events, particularly when dealing with cross-database renames. The changes enhance the accuracy of identifying the original schema and table names, ensuring that the persisted DDL events correctly reflect the source and target qualifiers. This leads to more reliable DDL event generation and improved data consistency across different database operations.

Highlights

  • Improved Rename Table DDL Handling: The logic for determining the original schema and table names during RENAME TABLE DDL event processing has been enhanced to ensure accurate identification, especially for cross-database renames.
  • New Query Parsing Helper: A dedicated helper function, parseRenameTableQueryInfo, was introduced to robustly extract old schema and table names from DDL queries, centralizing and improving parsing logic.
  • Expanded Test Coverage: New unit tests were added to cover various cross-database table rename scenarios, validating the correct generation of DDL events.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • logservice/schemastore/persist_storage_ddl_handlers.go
    • Refactored the logic for determining the original schema and table names in buildPersistedDDLEventForRenameTable.
    • Introduced parseRenameTableQueryInfo to centralize SQL statement parsing for rename operations.
  • logservice/schemastore/persist_storage_test.go
    • Added new test cases to validate the correct handling of cross-database table renames.
Activity
  • CodeRabbit provided a summary of the changes, highlighting bug fixes related to rename handling and the addition of test coverage.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a bug in handling RENAME TABLE DDLs, ensuring the original schema name is correctly determined, especially in cross-database rename scenarios where the schema is not explicit in the query. The fix correctly prioritizes RenameTableArgs from the DDL job as a source for the old schema name, which is more reliable than InvolvingSchemaInfo. The change is accompanied by a targeted unit test that validates the fix. The overall approach is sound. I have one suggestion to improve error logging for better observability.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
logservice/schemastore/persist_storage_ddl_handlers.go (1)

754-767: Consider wrapping errors from library calls.

Per coding guidelines, errors from library calls should be wrapped with stack traces. The errors from model.GetRenameTableArgs at lines 757 and 763 are returned unwrapped.

Suggested fix
 func getRenameTableArgsCompatible(job *model.Job) (*model.RenameTableArgs, error) {
 	switch job.Version {
 	case model.JobVersion1, model.JobVersion2:
-		return model.GetRenameTableArgs(job)
+		args, err := model.GetRenameTableArgs(job)
+		if err != nil {
+			return nil, cerror.WrapError(cerror.ErrDecodeFailed, err)
+		}
+		return args, nil
 	case 0:
 		// TiDB v7.5.0 historical jobs still encode rename-table args in v1 layout,
 		// but the version field is left as zero.
 		jobClone := *job
 		jobClone.Version = model.JobVersion1
-		return model.GetRenameTableArgs(&jobClone)
+		args, err := model.GetRenameTableArgs(&jobClone)
+		if err != nil {
+			return nil, cerror.WrapError(cerror.ErrDecodeFailed, err)
+		}
+		return args, nil
 	default:
-		return nil, errors.New("unsupported rename table job version")
+		return nil, cerror.ErrDecodeFailed.GenWithStackByArgs("unsupported rename table job version")
 	}
 }

As per coding guidelines: "When an error comes from a third-party or library call in Go, wrap it immediately with errors.Trace(err) or errors.WrapError(...) to attach a stack trace."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@logservice/schemastore/persist_storage_ddl_handlers.go` around lines 754 -
767, The function getRenameTableArgsCompatible returns errors straight from
model.GetRenameTableArgs; wrap those errors with a stack trace before returning
(e.g., call errors.Trace(err) or the project's wrap helper) so callers get
traceable errors. Update both call sites inside getRenameTableArgsCompatible
(the branch returning model.GetRenameTableArgs(job) and the branch returning
model.GetRenameTableArgs(&jobClone)) to capture the returned args and err, and
if err != nil return nil, errors.Trace(err) (or errors.WrapError(err, "...") if
your project prefers) instead of returning the raw err.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 754-767: The function getRenameTableArgsCompatible returns errors
straight from model.GetRenameTableArgs; wrap those errors with a stack trace
before returning (e.g., call errors.Trace(err) or the project's wrap helper) so
callers get traceable errors. Update both call sites inside
getRenameTableArgsCompatible (the branch returning model.GetRenameTableArgs(job)
and the branch returning model.GetRenameTableArgs(&jobClone)) to capture the
returned args and err, and if err != nil return nil, errors.Trace(err) (or
errors.WrapError(err, "...") if your project prefers) instead of returning the
raw err.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b626536b-a272-4ada-b931-9e3215f28ae9

📥 Commits

Reviewing files that changed from the base of the PR and between 1b3fcf0 and c6233db.

📒 Files selected for processing (2)
  • logservice/schemastore/persist_storage_ddl_handlers.go
  • logservice/schemastore/persist_storage_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • logservice/schemastore/persist_storage_test.go

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
logservice/schemastore/persist_storage_ddl_handlers.go (1)

703-767: ⚠️ Potential issue | 🔴 Critical

This only fixes the SQL text, not the old rename identity.

Line 751 rewrites event.Query, but Line 1361 and Line 2239 later still consume event.ExtraSchemaID, event.ExtraSchemaName, and event.ExtraTableName as the pre-rename identity. In the stale-snapshot case you call out at Line 703, those fields stay on the post-rename state, so cross-database moves can still miss the schema change and rename filtering / TableNameChange can still target the new name as if it were the old one. Please persist the recovered old schema ID/name/table name back into event.Extra* before rebuilding the query.

🐛 Suggested fix
-	oldSchemaName := ""
-	oldTableName := ""
+	oldSchemaID := event.ExtraSchemaID
+	oldSchemaName := ""
+	oldTableName := ""
 	if renameArgs, err := getRenameTableArgsCompatible(args.job); err == nil {
+		if renameArgs.OldSchemaID != 0 {
+			oldSchemaID = renameArgs.OldSchemaID
+		}
 		if renameArgs.OldSchemaName.O != "" {
 			oldSchemaName = renameArgs.OldSchemaName.O
 		}
 	}
...
+	if oldSchemaName != "" {
+		if resolvedID, ok := findSchemaIDByName(args.databaseMap, oldSchemaName); ok {
+			oldSchemaID = resolvedID
+		}
+	}
+	if oldSchemaID != 0 {
+		event.ExtraSchemaID = oldSchemaID
+	}
+	if oldSchemaName != "" {
+		event.ExtraSchemaName = oldSchemaName
+	}
+	if oldTableName != "" {
+		event.ExtraTableName = oldTableName
+	}
-	if oldSchemaName != "" && oldTableName != "" {
+	if event.ExtraSchemaName != "" && event.ExtraTableName != "" {
 		event.Query = fmt.Sprintf("RENAME TABLE %s TO %s",
-			common.QuoteSchema(oldSchemaName, oldTableName),
+			common.QuoteSchema(event.ExtraSchemaName, event.ExtraTableName),
 			common.QuoteSchema(event.SchemaName, event.TableName))
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@logservice/schemastore/persist_storage_ddl_handlers.go` around lines 703 -
767, The rebuild fixes only event.Query but not the pre-rename identity fields;
update event.ExtraSchemaName, event.ExtraTableName (and event.ExtraSchemaID when
available) with the recovered old values before rewriting the query. Concretely:
after you compute oldSchemaName/oldTableName (using
getRenameTableArgsCompatible, args.job.InvolvingSchemaInfo, and
parseRenameTableQueryInfo) assign event.ExtraSchemaName = oldSchemaName and
event.ExtraTableName = oldTableName, and if renameArgs.OldSchemaID is set assign
event.ExtraSchemaID = renameArgs.OldSchemaID, then proceed to set event.Query =
fmt.Sprintf(...). This ensures later consumers that read event.Extra* see the
true pre-rename identity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 703-767: The rebuild fixes only event.Query but not the pre-rename
identity fields; update event.ExtraSchemaName, event.ExtraTableName (and
event.ExtraSchemaID when available) with the recovered old values before
rewriting the query. Concretely: after you compute oldSchemaName/oldTableName
(using getRenameTableArgsCompatible, args.job.InvolvingSchemaInfo, and
parseRenameTableQueryInfo) assign event.ExtraSchemaName = oldSchemaName and
event.ExtraTableName = oldTableName, and if renameArgs.OldSchemaID is set assign
event.ExtraSchemaID = renameArgs.OldSchemaID, then proceed to set event.Query =
fmt.Sprintf(...). This ensures later consumers that read event.Extra* see the
true pre-rename identity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc57fdac-5a99-409c-abba-e1126a78c775

📥 Commits

Reviewing files that changed from the base of the PR and between c6233db and 56a0edc.

📒 Files selected for processing (1)
  • logservice/schemastore/persist_storage_ddl_handlers.go

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 10, 2026

/gemini summary

@lidezhu lidezhu changed the title schemastore: fix rename table schemastore: fix rename table when source database is not specified Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RENAME TABLE will fail if the source database name is not specified in a cross-database rename operation

1 participant