Skip to content

schemastore: fix rename tables when tidb version <= v8.1.x#4388

Merged
ti-chi-bot[bot] merged 19 commits intomasterfrom
ldz/fix-schema-store0306
Mar 9, 2026
Merged

schemastore: fix rename tables when tidb version <= v8.1.x#4388
ti-chi-bot[bot] merged 19 commits intomasterfrom
ldz/fix-schema-store0306

Conversation

@lidezhu
Copy link
Collaborator

@lidezhu lidezhu commented Mar 7, 2026

What problem does this PR solve?

Issue Number: close #4392

What is changed and how it works?

This pull request significantly improves the robustness and correctness of DDL event handling within the schema store, particularly for RENAME TABLES operations. It addresses a critical issue where older TiDB versions might provide incomplete old table information, by introducing a fallback mechanism that parses this data directly from the DDL query. Furthermore, it fortifies the system against potential SQL injection by ensuring all generated DDL queries properly quote schema and table identifiers. These changes enhance the reliability of schema synchronization and DDL application.

Highlights

  • Robust RENAME TABLES Handling: Implemented a fallback mechanism for RENAME TABLES DDL events to derive missing old table names from the original SQL query, specifically addressing issues in TiDB versions <= v8.1.x where this information might be incomplete.
  • Enhanced Identifier Quoting: Refactored DDL query generation across various DDL types (DROP VIEW, DROP TABLE, RENAME TABLE, EXCHANGE PARTITION) to consistently use common.QuoteSchema and common.QuoteName for proper identifier escaping, mitigating potential SQL injection vulnerabilities.
  • Case-Insensitive Name Lookups: Updated schema and table name lookup functions (findSchemaIDByName, findTableIDByName) to perform case-insensitive comparisons, improving flexibility and correctness.
  • Improved Error Handling for Multi-Table Renames: Changed a warning to a panic for length mismatches in RENAME TABLES operations, ensuring that multi-table DDLs are applied atomically and preventing partial schema updates.
  • Comprehensive Testing: Added extensive unit tests covering the new fallback logic for RENAME TABLES, cyclic rename scenarios, identifier escaping, and case-insensitive name matching.

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 persisted RENAME TABLE handling: safely derive missing old identifiers from SQL and stored metadata as fallbacks, prefer store metadata on conflicts (e.g., cycles), truncate mismatched inputs to a safe length, emit warnings when fallbacks/mismatches occur, and ensure emitted RENAME statements use the resolved identifiers.
  • Tests

    • Added tests covering fallback recovery from parsed queries, metadata-driven reconciliation, and cyclic/temporary-table rename scenarios.

@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 7, 2026
@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 an issue with RENAME TABLES operations by enhancing the schema store's ability to construct DDL events. It introduces a more resilient approach to handling cases where old table identifiers might be incomplete, ensuring that schema changes are accurately persisted and applied. This fix improves the stability and correctness of schema management, particularly for TiCDC v8.1.2.

Highlights

  • Robust RENAME TABLES DDL Event Generation: Implemented a fallback mechanism in the buildPersistedDDLEventForRenameTables function to retrieve missing old schema and table identifiers from the schema store metadata if they are not provided in the initial rename arguments. This ensures that RENAME TABLES DDL events are correctly constructed even when partial information is available.
  • Improved Error Handling and Logging: Added a warning log when the fallback mechanism is triggered, providing detailed information about the missing arguments and the values retrieved from the schema store, which aids in debugging and monitoring.
  • New Test Case for Fallback Logic: Introduced a new unit test, TestBuildPersistedDDLEventForRenameTablesFallbackOldTableName, to specifically validate the correct behavior of the fallback logic when old table names and schema names are initially empty.

🧠 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
    • Modified buildPersistedDDLEventForRenameTables to include a fallback for missing OldSchemaID, OldSchemaName, and OldTableName by querying the tableMap.
    • Added logging for instances where fallback to schema store metadata is necessary for rename table arguments.
  • logservice/schemastore/persist_storage_test.go
    • Added TestBuildPersistedDDLEventForRenameTablesFallbackOldTableName to verify the new fallback logic for rename tables.
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.

@ti-chi-bot ti-chi-bot bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed do-not-merge/needs-linked-issue labels Mar 7, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 7, 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

Adds parsing helpers and resilient handling for RENAME TABLE jobs: extracts rename mappings from SQL when job args are incomplete, reconciles identifiers with schema-store metadata, logs warnings on fallbacks/mismatches, and updates persisted DDL assembly. Tests for fallback and cyclic rename cases are added.

Changes

Cohort / File(s) Summary
Rename-Table DDL handler
logservice/schemastore/persist_storage_ddl_handlers.go
Add renameTableQueryInfo type and helpers (parseRenameTablesQueryInfos, matchRenameQueryInfoByNewTable, getSchemaIDByName); refactor rename handling to parse Query for missing old identifiers, reconcile with schema-store metadata, add fallback/warning paths, and build consistent persisted RENAME TABLE SQL and Extra* fields.
Unit tests for fallback & recovery
logservice/schemastore/persist_storage_test.go
Add tests covering fallback when old names are missing, fallback-from-query behavior, and cyclic rename with temporary table; assertions verify constructed DDL, ExtraTableNames/ExtraSchemaNames, and SchemaNames. (Tests appear duplicated in diff.)

Sequence Diagram(s)

sequenceDiagram
    participant Job as JobArgs
    participant Handler as DDLHandler
    participant Parser as SQLParser
    participant Store as SchemaStore
    participant Logger as Logger
    participant Emitter as EventEmitter

    Job->>Handler: provide job (Args, maybe Query)
    Handler->>Handler: safe decode rename args
    alt decoded has complete old identifiers
        Handler->>Handler: use decoded old/new identifiers
    else decoded incomplete
        Handler->>Parser: parse Query (parseRenameTablesQueryInfos)
        Parser-->>Handler: rename pairs
        Handler->>Store: lookup schema IDs/names (getSchemaIDByName / metadata)
        Store-->>Handler: metadata (table info)
        Handler->>Handler: match parsed info to entries (matchRenameQueryInfoByNewTable)
        Handler->>Logger: warn about fallbacks/mismatches
    end
    Handler->>Emitter: emit persisted DDL event (resolved old/new identifiers, RENAME TABLE SQL)
    Emitter-->>Handler: ack
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

size/M

Suggested reviewers

  • 3AceShowHand
  • tenfyzhong

Poem

🐰 I nibbled through queries when names went missing,
I hopped to the store and found old tables hissing.
With parser and map I stitched every name,
Warned with a twitch, and produced a clean rename.
Hooray — no panic, just tidy change.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.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 lacks critical information required by the template, specifically answers to the questions section and the release note content. Complete the Questions section by answering whether this causes performance regression or breaks compatibility, and whether documentation updates are needed. Fill in the release note section with appropriate content or 'None'.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'schemastore: fix rename tables when tidb version <= v8.1.x' is clear, specific, and directly relates to the main change: fixing rename table handling for older TiDB versions.
Linked Issues check ✅ Passed The code changes directly address issue #4392 by implementing fallback logic for rename table parsing when tidb version <= v8.1.x, including parse/query info correlation and metadata-driven fallbacks.
Out of Scope Changes check ✅ Passed All changes are scoped to the rename tables DDL handling in schemastore; added helpers and refactored logic are directly relevant to resolving the rename table sync issue.

✏️ 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-schema-store0306

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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

@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 introduces a fallback mechanism in buildPersistedDDLEventForRenameTables to handle cases where DDL job arguments for RENAME TABLES might be incomplete, using metadata from the schema store to fill in missing identifiers and including a unit test for this new logic. However, the manual reconstruction of the RENAME TABLE SQL query at line 850 remains vulnerable to SQL injection because it does not escape backticks in schema or table names, which could allow an attacker with DDL privileges to execute arbitrary SQL; it is recommended to use the common.QuoteSchema utility for safe reconstruction. Additionally, a potential inconsistency in the fallback logic regarding the schema ID used for looking up the schema name should be addressed to ensure it aligns with the schema ID being used for the event, preventing potential discrepancies.

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 (2)
logservice/schemastore/persist_storage_ddl_handlers.go (2)

848-849: Rename SchemaName to schemaName.

Uppercase local names read like exported identifiers and break the repo's Go naming rule.

As per coding guidelines, "Use lowerCamelCase for variable names in Go (e.g., flushInterval, not flush_interval)".

🤖 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 848 -
849, The local variable name SchemaName should be renamed to lowerCamelCase
schemaName to follow Go naming conventions; update the assignment from
getSchemaName(args.databaseMap, info.NewSchemaID) to assign to schemaName and
then append schemaName to event.SchemaNames so references around getSchemaName,
args.databaseMap, info.NewSchemaID, and event.SchemaNames use the new variable
name.

820-846: Resolve fallback old identifiers as one tuple.

Once fallback is needed, this block only patches the missing fields. That can leave ExtraSchemaIDs coming from RenameTableInfo while ExtraSchemaNames / ExtraTableNames come from schema-store metadata, and those are consumed by different downstream paths in this file. Prefer rebuilding the full old (schemaID, schemaName, tableName) tuple from schema-store state once fallback is triggered, and fail fast if info.TableID cannot be found.

Suggested hardening
 		oldSchemaID := info.OldSchemaID
 		oldSchemaName := info.OldSchemaName.O
 		oldTableName := info.OldTableName.O
 		if oldSchemaName == "" || oldTableName == "" || oldSchemaID == 0 {
-			if tableInfo, ok := args.tableMap[info.TableID]; ok {
-				if oldSchemaID == 0 {
-					oldSchemaID = tableInfo.SchemaID
-				}
-				if oldSchemaName == "" {
-					oldSchemaName = getSchemaName(args.databaseMap, tableInfo.SchemaID)
-				}
-				if oldTableName == "" {
-					oldTableName = tableInfo.Name
-				}
-				log.Warn("rename tables args miss old table identifiers fallback to schema store metadata",
-					zap.Int64("tableID", info.TableID),
-					zap.Int64("oldSchemaIDInArgs", info.OldSchemaID),
-					zap.String("oldSchemaNameInArgs", info.OldSchemaName.O),
-					zap.String("oldTableNameInArgs", info.OldTableName.O),
-					zap.Int64("oldSchemaIDInStore", tableInfo.SchemaID),
-					zap.String("oldTableNameInStore", tableInfo.Name))
-			}
+			tableInfo, ok := args.tableMap[info.TableID]
+			if !ok {
+				log.Panic("rename tables old table not found in schema store",
+					zap.Int64("tableID", info.TableID),
+					zap.Int64("oldSchemaIDInArgs", info.OldSchemaID),
+					zap.String("oldSchemaNameInArgs", info.OldSchemaName.O),
+					zap.String("oldTableNameInArgs", info.OldTableName.O))
+			}
+			oldSchemaID = tableInfo.SchemaID
+			oldSchemaName = getSchemaName(args.databaseMap, tableInfo.SchemaID)
+			oldTableName = tableInfo.Name
+			log.Warn("rename tables args miss old table identifiers fallback to schema store metadata",
+				zap.Int64("tableID", info.TableID),
+				zap.Int64("oldSchemaIDInArgs", info.OldSchemaID),
+				zap.String("oldSchemaNameInArgs", info.OldSchemaName.O),
+				zap.String("oldTableNameInArgs", info.OldTableName.O),
+				zap.Int64("oldSchemaIDInStore", tableInfo.SchemaID),
+				zap.String("oldSchemaNameInStore", oldSchemaName),
+				zap.String("oldTableNameInStore", tableInfo.Name))
 		}
🤖 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 820 -
846, When any of info.OldSchemaID, info.OldSchemaName.O, or info.OldTableName.O
is missing, don't patch fields individually; instead require lookup of
args.tableMap[info.TableID], fail fast if not found, and rebuild the full old
tuple (schemaID := tableInfo.SchemaID; schemaName :=
getSchemaName(args.databaseMap, schemaID); tableName := tableInfo.Name) so
event.ExtraSchemaIDs, event.ExtraSchemaNames and event.ExtraTableNames are all
appended from the same source. Replace the existing partial-field-fallback logic
around those symbols (info, args.tableMap, tableInfo, getSchemaName,
event.ExtraSchemaIDs/Names/TableNames) with this atomic replacement and adjust
the log to reflect that a full tuple fallback occurred.
🤖 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_test.go`:
- Around line 3134-3162: The test for rename fallback is non-discriminative
because both source and destination names are identical; update the test data in
buildRenameTablesJobForTest/buildPersistedDDLEventForRenameTables to use
different destination table/schema names (e.g., "orders_new", "users_new" and
corresponding "sc_predeleted_test_predelete_new") so the expected ddl.Query,
ddl.ExtraTableNames, ddl.ExtraSchemaNames and ddl.SchemaNames assertions will
fail if the code erroneously reads NewTableName instead of the old one, and
replace assert.Equal calls with require.Equal from testify/require to make each
assertion a prerequisite (referencing ddl.Query, ddl.ExtraTableNames,
ddl.ExtraSchemaNames, ddl.SchemaNames and the helper builders
buildRenameTablesJobForTest and buildPersistedDDLEventForRenameTables).

---

Nitpick comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 848-849: The local variable name SchemaName should be renamed to
lowerCamelCase schemaName to follow Go naming conventions; update the assignment
from getSchemaName(args.databaseMap, info.NewSchemaID) to assign to schemaName
and then append schemaName to event.SchemaNames so references around
getSchemaName, args.databaseMap, info.NewSchemaID, and event.SchemaNames use the
new variable name.
- Around line 820-846: When any of info.OldSchemaID, info.OldSchemaName.O, or
info.OldTableName.O is missing, don't patch fields individually; instead require
lookup of args.tableMap[info.TableID], fail fast if not found, and rebuild the
full old tuple (schemaID := tableInfo.SchemaID; schemaName :=
getSchemaName(args.databaseMap, schemaID); tableName := tableInfo.Name) so
event.ExtraSchemaIDs, event.ExtraSchemaNames and event.ExtraTableNames are all
appended from the same source. Replace the existing partial-field-fallback logic
around those symbols (info, args.tableMap, tableInfo, getSchemaName,
event.ExtraSchemaIDs/Names/TableNames) with this atomic replacement and adjust
the log to reflect that a full tuple fallback occurred.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2566de92-5fca-4b53-bff4-720d7f61c285

📥 Commits

Reviewing files that changed from the base of the PR and between 989f859 and 6845700.

📒 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/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Mar 7, 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.

Actionable comments posted: 1

🤖 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 1023-1035: The current code silently truncates renameTableInfos
and multipleTableInfos to minLen which can partially apply a committed
multi-table RENAME; instead, detect the length mismatch (the if block comparing
len(renameTableInfos) and len(multipleTableInfos)) and fail fast: log an error
with context (use zap fields like renameArgsLen, multipleTableInfosLen, query
from args.job.Query), and return an error (or mark the job as failed) rather
than slicing the slices; do this in the same scope where renameTableInfos and
multipleTableInfos are compared so no partial application occurs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ab8d3e9f-0f4c-4533-818a-6561f463cb0f

📥 Commits

Reviewing files that changed from the base of the PR and between 9bca9cb and 238b999.

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

@lidezhu lidezhu changed the title schemastore: fix rename tables for v8.1.2 schemastore: fix rename tables when tidb version is below v8.1.x Mar 8, 2026
@ti-chi-bot ti-chi-bot bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Mar 8, 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.

🧹 Nitpick comments (3)
logservice/schemastore/persist_storage_test.go (2)

3165-3194: Use require.Equal instead of assert.Equal for consistency.

Same concern as the previous test function. Use require.Equal for fail-fast behavior.

♻️ Suggested fix
-	assert.Equal(t,
+	require.Equal(t,
 		"RENAME TABLE `source_db`.`source_t1` TO `target_db`.`target_t1`;"+
 			"RENAME TABLE `source_db`.`source_t2` TO `target_db`.`target_t2`;",
 		ddl.Query)
-	assert.Equal(t, []string{"source_t1", "source_t2"}, ddl.ExtraTableNames)
-	assert.Equal(t, []string{"source_db", "source_db"}, ddl.ExtraSchemaNames)
+	require.Equal(t, []string{"source_t1", "source_t2"}, ddl.ExtraTableNames)
+	require.Equal(t, []string{"source_db", "source_db"}, ddl.ExtraSchemaNames)

As per coding guidelines, "**/*_test.go: Use unit test files named *_test.go in Go; favor deterministic tests and use testify/require".

🤖 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 3165 - 3194, The
test TestBuildPersistedDDLEventForRenameTablesFallbackQueryOldTableName is using
assert.Equal which is inconsistent with project guidelines; replace the three
assert.Equal calls for ddl.Query, ddl.ExtraTableNames, and ddl.ExtraSchemaNames
with require.Equal to make the test fail fast (and ensure the test file imports
testify/require if not already). Locate the assertions in
TestBuildPersistedDDLEventForRenameTablesFallbackQueryOldTableName and change
assert.Equal(...) to require.Equal(...), adding or updating the require import
as needed.

3133-3163: Use require.Equal instead of assert.Equal per coding guidelines.

The test correctly discriminates between old and new table names by using distinct values. However, per coding guidelines, tests should use testify/require for assertions to fail fast on the first mismatch.

♻️ Suggested fix
-	assert.Equal(t,
+	require.Equal(t,
 		"RENAME TABLE `source_db`.`source_t1` TO `target_db`.`target_t1`;"+
 			"RENAME TABLE `source_db`.`source_t2` TO `target_db`.`target_t2`;",
 		ddl.Query)
-	assert.Equal(t, []string{"source_t1", "source_t2"}, ddl.ExtraTableNames)
-	assert.Equal(t, []string{"source_db", "source_db"}, ddl.ExtraSchemaNames)
-	assert.Equal(t, []string{"target_db", "target_db"}, ddl.SchemaNames)
+	require.Equal(t, []string{"source_t1", "source_t2"}, ddl.ExtraTableNames)
+	require.Equal(t, []string{"source_db", "source_db"}, ddl.ExtraSchemaNames)
+	require.Equal(t, []string{"target_db", "target_db"}, ddl.SchemaNames)

As per coding guidelines, "**/*_test.go: Use unit test files named *_test.go in Go; favor deterministic tests and use testify/require".

🤖 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 3133 - 3163, The
test TestBuildPersistedDDLEventForRenameTablesFallbackOldTableName uses
assert.Equal which should be changed to require.Equal to fail fast; update the
three assert.Equal calls (comparing ddl.Query, ddl.ExtraTableNames,
ddl.ExtraSchemaNames, ddl.SchemaNames) to require.Equal and add the require
import ("github.com/stretchr/testify/require") in the test file (removing or
keeping the assert import only as needed) so the test fails immediately on the
first mismatch.
logservice/schemastore/persist_storage_ddl_handlers.go (1)

880-887: getSchemaIDByName returns 0 on not-found, which may be ambiguous.

Returning 0 when the schema is not found could be confused with a valid (though unlikely) schema ID. Consider returning (int64, bool) to explicitly signal whether the schema was found, similar to the existing findSchemaIDByName function defined at lines 521-528.

♻️ Suggested signature change
-func getSchemaIDByName(databaseMap map[int64]*BasicDatabaseInfo, schemaName string) int64 {
+func getSchemaIDByName(databaseMap map[int64]*BasicDatabaseInfo, schemaName string) (int64, bool) {
 	for schemaID, databaseInfo := range databaseMap {
 		if strings.EqualFold(databaseInfo.Name, schemaName) {
-			return schemaID
+			return schemaID, true
 		}
 	}
-	return 0
+	return 0, false
 }

Then update call sites to handle the boolean return value.

🤖 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 880 -
887, Change getSchemaIDByName to return (int64, bool) instead of int64 and
mirror the behavior of findSchemaIDByName: iterate databaseMap
(map[int64]*BasicDatabaseInfo) and return (schemaID, true) when
strings.EqualFold matches, otherwise return (0, false); then update all call
sites of getSchemaIDByName to handle the boolean (check the found flag and
handle the not-found case explicitly rather than assuming 0 is invalid).
🤖 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 880-887: Change getSchemaIDByName to return (int64, bool) instead
of int64 and mirror the behavior of findSchemaIDByName: iterate databaseMap
(map[int64]*BasicDatabaseInfo) and return (schemaID, true) when
strings.EqualFold matches, otherwise return (0, false); then update all call
sites of getSchemaIDByName to handle the boolean (check the found flag and
handle the not-found case explicitly rather than assuming 0 is invalid).

In `@logservice/schemastore/persist_storage_test.go`:
- Around line 3165-3194: The test
TestBuildPersistedDDLEventForRenameTablesFallbackQueryOldTableName is using
assert.Equal which is inconsistent with project guidelines; replace the three
assert.Equal calls for ddl.Query, ddl.ExtraTableNames, and ddl.ExtraSchemaNames
with require.Equal to make the test fail fast (and ensure the test file imports
testify/require if not already). Locate the assertions in
TestBuildPersistedDDLEventForRenameTablesFallbackQueryOldTableName and change
assert.Equal(...) to require.Equal(...), adding or updating the require import
as needed.
- Around line 3133-3163: The test
TestBuildPersistedDDLEventForRenameTablesFallbackOldTableName uses assert.Equal
which should be changed to require.Equal to fail fast; update the three
assert.Equal calls (comparing ddl.Query, ddl.ExtraTableNames,
ddl.ExtraSchemaNames, ddl.SchemaNames) to require.Equal and add the require
import ("github.com/stretchr/testify/require") in the test file (removing or
keeping the assert import only as needed) so the test fails immediately on the
first mismatch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29757d1e-f8bf-435d-9458-a6afc5b6ef14

📥 Commits

Reviewing files that changed from the base of the PR and between 238b999 and 61294c1.

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

@lidezhu lidezhu changed the title schemastore: fix rename tables when tidb version is below v8.1.x schemastore: fix rename tables when tidb version <= v8.1.x Mar 8, 2026
@ti-chi-bot ti-chi-bot bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 9, 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.

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

976-984: Consider adding debug/warning logs for final fallback assignments.

When old identifiers cannot be determined from any source (args, parsed query, or schema store), the code silently falls back to using new identifiers as old identifiers. This could mask underlying issues and make debugging difficult.

Suggested logging addition
 	if oldSchemaID == 0 {
 		oldSchemaID = info.NewSchemaID
+		log.Warn("rename tables cannot determine old schema ID fallback to new schema ID",
+			zap.Int64("tableID", info.TableID),
+			zap.Int64("newSchemaID", info.NewSchemaID))
 	}
 	if oldSchemaName == "" {
 		oldSchemaName = newSchemaName
+		log.Warn("rename tables cannot determine old schema name fallback to new schema name",
+			zap.Int64("tableID", info.TableID),
+			zap.String("newSchemaName", newSchemaName))
 	}
 	if oldTableName == "" {
 		oldTableName = info.NewTableName.O
+		log.Warn("rename tables cannot determine old table name fallback to new table name",
+			zap.Int64("tableID", info.TableID),
+			zap.String("newTableName", info.NewTableName.O))
 	}
🤖 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 976 -
984, The code silently falls back to new identifiers when old ones are missing
(the blocks setting oldSchemaID = info.NewSchemaID, oldSchemaName =
newSchemaName, oldTableName = info.NewTableName.O); add logging to surface these
fallback events by emitting a debug or warning log that includes which
identifier was missing and the fallback value (e.g., log oldSchemaID fallback
with info.NewSchemaID, oldSchemaName fallback with newSchemaName, and
oldTableName fallback with info.NewTableName.O) so callers can trace unexpected
fallbacks; ensure logs reference the context (operation/statement id or
function) and use the existing logger used elsewhere in this file.

880-887: Consider consolidating with findSchemaIDByName for consistency.

There's a similar function findSchemaIDByName at line 521 that returns (int64, bool) and uses exact string comparison. This new function uses case-insensitive comparison and returns 0 for not found.

While the case-insensitive matching aligns with the matchRenameQueryInfoByNewTable logic, having two similar functions with different behaviors could be confusing. Consider:

  1. Reusing findSchemaIDByName and handling case-insensitivity at the call site if needed, or
  2. Adding a comment explaining why case-insensitive matching is required here.
🤖 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 880 -
887, There are two similar helpers—getSchemaIDByName (case-insensitive, returns
0) and findSchemaIDByName (exact match, returns (int64,bool)) which is
confusing; either consolidate by changing findSchemaIDByName to accept a
caseInsensitive bool (or add an overloaded helper) and update callers to use the
unified function, or keep the current case-insensitive behavior but add a clear
comment above getSchemaIDByName explaining why case-insensitive matching is
required (and document the 0-not-found sentinel) so callers understand the
difference; reference the functions findSchemaIDByName and getSchemaIDByName
when making the change.
🤖 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 976-984: The code silently falls back to new identifiers when old
ones are missing (the blocks setting oldSchemaID = info.NewSchemaID,
oldSchemaName = newSchemaName, oldTableName = info.NewTableName.O); add logging
to surface these fallback events by emitting a debug or warning log that
includes which identifier was missing and the fallback value (e.g., log
oldSchemaID fallback with info.NewSchemaID, oldSchemaName fallback with
newSchemaName, and oldTableName fallback with info.NewTableName.O) so callers
can trace unexpected fallbacks; ensure logs reference the context
(operation/statement id or function) and use the existing logger used elsewhere
in this file.
- Around line 880-887: There are two similar helpers—getSchemaIDByName
(case-insensitive, returns 0) and findSchemaIDByName (exact match, returns
(int64,bool)) which is confusing; either consolidate by changing
findSchemaIDByName to accept a caseInsensitive bool (or add an overloaded
helper) and update callers to use the unified function, or keep the current
case-insensitive behavior but add a clear comment above getSchemaIDByName
explaining why case-insensitive matching is required (and document the
0-not-found sentinel) so callers understand the difference; reference the
functions findSchemaIDByName and getSchemaIDByName when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad0e37fd-7f17-4012-a575-e047dc9f0077

📥 Commits

Reviewing files that changed from the base of the PR and between 61294c1 and 5fd6282.

📒 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

@ti-chi-bot ti-chi-bot bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 9, 2026
@ti-chi-bot ti-chi-bot bot added the lgtm label Mar 9, 2026
@ti-chi-bot
Copy link

ti-chi-bot bot commented Mar 9, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: wk989898, wlwilliamx

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

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [wk989898,wlwilliamx]

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 removed the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Mar 9, 2026
@ti-chi-bot
Copy link

ti-chi-bot bot commented Mar 9, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-03-09 10:31:46.455642743 +0000 UTC m=+259737.967700394: ☑️ agreed by wk989898.
  • 2026-03-09 11:11:09.471604052 +0000 UTC m=+262100.983661733: ☑️ agreed by wlwilliamx.

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all-v7-5

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all-v7-5

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all-v8-1

f
(cherry picked from commit e021af1)
@ti-chi-bot ti-chi-bot bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Mar 9, 2026
@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all-v8-1

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all-v8-1

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/test all

@ti-chi-bot
Copy link

ti-chi-bot bot commented Mar 9, 2026

@lidezhu: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-cdc-mysql-integration-light-v7-5 aee4278 link false /test pull-cdc-mysql-integration-light-v7-5
pull-cdc-mysql-integration-heavy-v7-5 aee4278 link false /test pull-cdc-mysql-integration-heavy-v7-5
pull-cdc-mysql-integration-heavy-v8-1 0ee7a0a link false /test pull-cdc-mysql-integration-heavy-v8-1
pull-cdc-mysql-integration-light-v8-1 0ee7a0a link false /test pull-cdc-mysql-integration-light-v8-1

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 9, 2026

/unhold

@ti-chi-bot ti-chi-bot bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 9, 2026
@ti-chi-bot ti-chi-bot bot merged commit 6423bf1 into master Mar 9, 2026
29 of 33 checks passed
@ti-chi-bot ti-chi-bot bot deleted the ldz/fix-schema-store0306 branch March 9, 2026 16:20
@lidezhu lidezhu added the needs-cherry-pick-release-8.5 Should cherry pick this PR to release-8.5 branch. label Mar 10, 2026
@lidezhu
Copy link
Collaborator Author

lidezhu commented Mar 10, 2026

/run-cherry-picker

@ti-chi-bot
Copy link
Member

In response to a cherrypick label: new pull request created to branch release-8.5: #4410.

ti-chi-bot pushed a commit to ti-chi-bot/ticdc-1 that referenced this pull request Mar 10, 2026
lidezhu added a commit that referenced this pull request Mar 10, 2026
…4410)

* schemastore: fix rename tables when tidb version <= v8.1.x (#4388)

close #4392

* fix unit test

---------

Co-authored-by: lidezhu <47731263+lidezhu@users.noreply.github.com>
Co-authored-by: lidezhu <lidezhu@pingcap.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm needs-cherry-pick-release-8.5 Should cherry pick this PR to release-8.5 branch. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ticdc cannot sync rename tables when upstream tidb version <= v8.1

5 participants