Skip to content

[WIP]#4411

Open
lidezhu wants to merge 1 commit intomasterfrom
ldz/fix-batch-add-table
Open

[WIP]#4411
lidezhu wants to merge 1 commit intomasterfrom
ldz/fix-batch-add-table

Conversation

@lidezhu
Copy link
Collaborator

@lidezhu lidezhu commented Mar 10, 2026

What problem does this PR solve?

Issue Number: close #xxx

What is changed and how it works?

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 reliability of multi-table database schema creation operations with enhanced error handling, recovery mechanisms, and validation to ensure accurate schema reconstruction.
  • Tests

    • Added test coverage for multi-table database object creation scenarios.

@ti-chi-bot ti-chi-bot bot added do-not-merge/needs-linked-issue do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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 wlwilliamx 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

@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 refactors the schema store's DDL event processing for CREATE TABLES operations. It introduces a more resilient method to parse and generate SQL queries, particularly when a single DDL statement might create multiple tables or when the provided query string is ambiguous. The changes ensure that the system can accurately derive individual CREATE TABLE statements from table metadata, thereby preventing potential panics and enhancing the reliability of DDL event propagation.

Highlights

  • Robust CREATE TABLES DDL Handling: Introduced a new function, splitCreateTablesQueries, to enhance the processing of CREATE TABLES DDL events. This function intelligently handles cases where the initial DDL query string might not perfectly align with the number of table information objects, by reconstructing individual CREATE TABLE statements from the available table metadata.
  • Error Prevention: Replaced log.Panic calls with a more graceful error handling and logging mechanism when the count of split queries does not match the number of table information objects, improving system stability.
  • New Unit Test: Added a dedicated unit test, TestBuildDDLEventForCreateTablesQueryCountMismatch, to validate the new query reconstruction logic, ensuring its correctness and robustness in edge cases.

🧠 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 buildDDLEventForCreateTables to utilize a new helper function for splitting queries.
    • Added splitCreateTablesQueries function to reconstruct CREATE TABLE statements from TableInfo when the initial query split is mismatched or erroneous.
    • Imported necessary packages (bytes, executor, autoid, mock) to support query reconstruction.
  • logservice/schemastore/persist_storage_test.go
    • Added TestBuildDDLEventForCreateTablesQueryCountMismatch to verify the new logic for handling CREATE TABLES DDL events where the query count initially mismatches the table count.
Activity
  • The pull request is currently marked as '[WIP]', indicating it is a Work In Progress and may not yet be ready for a full review.
  • The description body is a standard template, suggesting no specific human-written comments or detailed context have been added by the author yet.
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 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

📝 Walkthrough

Walkthrough

Changes add logic to reconstruct CREATE TABLE statements when multi-table DDL events have mismatched query counts. A new helper function attempts to split queries, detects mismatches, and rebuilds queries using SHOW CREATE TABLE results via executor, with a corresponding test verifying this reconstruction behavior.

Changes

Cohort / File(s) Summary
Multi-table DDL query reconstruction
logservice/schemastore/persist_storage_ddl_handlers.go
Introduces splitCreateTablesQueries helper that splits CREATE TABLE queries and reconstructs them from SHOW CREATE TABLE results when count mismatches occur. Updates imports for bytes, executor, autoid, mock. Replaces panic path with error return for query mismatches.
Query reconstruction test
logservice/schemastore/persist_storage_test.go
Adds TestBuildDDLEventForCreateTablesQueryCountMismatch to verify multi-table DDL handling with two table infos, confirming proper query reconstruction and NeedAddedTables population.

Sequence Diagram

sequenceDiagram
    participant Handler as DDL Handler
    participant Splitter as Query Splitter
    participant Comparator as Count Validator
    participant Executor as TiDB Executor
    participant Result as Result Builder

    Handler->>Splitter: SplitQueries(rawEvent)
    Splitter-->>Handler: parsed queries
    Handler->>Comparator: Compare counts
    
    alt Count matches
        Comparator-->>Result: Use original queries
    else Count mismatches
        Comparator->>Executor: For each table, ConstructResultOfShowCreateTable
        Executor-->>Executor: Generate CREATE TABLE from metadata
        Executor-->>Result: Rebuilt query per table
    end
    
    Result-->>Handler: Final queries
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

lgtm, size/M

Suggested reviewers

  • wlwilliamx
  • wk989898

Poem

🐰 Multiple tables, one DDL so grand,
When queries split, we reconstruct by hand,
With SHOW CREATE TABLE's mystic art,
We rebuild each statement, part by part,
A mismatch fixed with elegance and might! 🌟

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title '[WIP]' is vague and does not describe the actual changes, which involve fixing multi-table CREATE TABLE DDL handling and query reconstruction. Replace '[WIP]' with a clear, descriptive title that summarizes the main change, e.g., 'Fix CREATE TABLE query reconstruction for multi-table DDLs'.
Description check ⚠️ Warning The PR description is incomplete and contains only template placeholders. The 'Issue Number', 'What is changed and how it works?', and release note sections lack substantive content. Fill in the concrete issue number, describe the changes and implementation details, specify which tests are included, answer the questions section, and provide a release note.
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.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ldz/fix-batch-add-table

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.

@ti-chi-bot
Copy link

ti-chi-bot bot commented Mar 10, 2026

[FORMAT CHECKER NOTIFICATION]

Notice: To remove the do-not-merge/needs-linked-issue label, please provide the linked issue number on one line in the PR body, for example: Issue Number: close #123 or Issue Number: ref #456.

📖 For more info, you can check the "Contribute Code" section in the development guide.

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_ddl_handlers.go (1)

2797-2832: The query reconstruction logic is well-structured.

The splitCreateTablesQueries function handles the edge case where the original query cannot be properly split to match the table count. The approach of using ConstructResultOfShowCreateTable to rebuild queries from table info is reasonable.

A few observations:

  1. The variable name querys should conventionally be queries (proper English plural), though this is consistent with usage elsewhere in the file.
  2. Good defensive check for nil tableInfo at line 2816-2818.
  3. Proper error wrapping with cerror.WrapError.
Minor: Consider consistent naming with English plural
-func splitCreateTablesQueries(rawEvent *PersistedDDLEvent) ([]string, error) {
-	querys, err := commonEvent.SplitQueries(rawEvent.Query)
-	if err == nil && len(querys) == len(rawEvent.MultipleTableInfos) {
-		return querys, nil
+func splitCreateTablesQueries(rawEvent *PersistedDDLEvent) ([]string, error) {
+	queries, err := commonEvent.SplitQueries(rawEvent.Query)
+	if err == nil && len(queries) == len(rawEvent.MultipleTableInfos) {
+		return queries, nil
 	}
 
 	fields := []zap.Field{
-		zap.Int("queryCount", len(querys)),
+		zap.Int("queryCount", len(queries)),
 		zap.Int("tableCount", len(rawEvent.MultipleTableInfos)),
🤖 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 2797 -
2832, In splitCreateTablesQueries rename the misspelled local variable querys to
queries (and update all uses within the function including the len(querys)
checks and zap.Int("queryCount", ...) reference) to use the correct English
plural; ensure you update the early-return return queries, nil and the
rebuiltQuerys logic so names are consistent and compile cleanly, keeping all
error handling and behavior unchanged.
🤖 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`:
- Line 2813: Replace the test-only mocked context usage: remove
mock.NewContext() and instead obtain a real session/context for production use
(for example, create a session from the TiDB domain/session pool or use
session.CreateSession and its returned context) so that
ConstructResultOfShowCreateTable() can access real session state (e.g.,
ctx.GetSessionVars().SQLMode); alternatively, if this handler is for external
callers, execute SHOW CREATE TABLE as SQL and use that result rather than
calling ConstructResultOfShowCreateTable() with a mocked ctx. Ensure the new
code uses the domain/session pool API to create or borrow a session, sets any
required SessionVars, calls ConstructResultOfShowCreateTable() (or runs SHOW
CREATE TABLE) with that real context, and properly closes/returns the session.

---

Nitpick comments:
In `@logservice/schemastore/persist_storage_ddl_handlers.go`:
- Around line 2797-2832: In splitCreateTablesQueries rename the misspelled local
variable querys to queries (and update all uses within the function including
the len(querys) checks and zap.Int("queryCount", ...) reference) to use the
correct English plural; ensure you update the early-return return queries, nil
and the rebuiltQuerys logic so names are consistent and compile cleanly, keeping
all error handling and behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 45d1d5f3-fdc9-42bb-ae81-9207a76979d0

📥 Commits

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

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

}
log.Warn("create tables query count not match table count rebuild queries by table info", fields...)

ctx := mock.NewContext()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

TiDB mock.NewContext usage in production code ConstructResultOfShowCreateTable

💡 Result:

mock.NewContext() (from github.com/pingcap/tidb/util/mock) is intended for tests only, not production use. The package docs explicitly say: “Package mock is just for test only.” [1]

ConstructResultOfShowCreateTable(ctx sessionctx.Context, ...) depends on real session state (e.g., it reads ctx.GetSessionVars().SQLMode, escapes identifiers accordingly, etc.), so a mocked context can silently produce wrong output or miss required behavior/config. [3]

What to do instead (production):

  • If you’re outside TiDB (normal app code): don’t call this internal helper—just run SQL: SHOW CREATE TABLE ... against TiDB.
  • If you’re inside TiDB/embedding TiDB: use a real session (sessionctx.Context) created by TiDB’s session creation flow (new connections call session.CreateSession(); internal ops typically obtain sessions from domain’s session pool), rather than util/mock. [2]

Sources

  1. TiDB util/mock package docs (test-only) — (pkg.go.dev)
  2. TiDB dev guide: how real sessions are created/obtained — (pingcap.github.io)
  3. ConstructResultOfShowCreateTable uses ctx.GetSessionVars().SQLMode etc. — (seaxiang.com)

Citations:


Remove mock.NewContext() from production code path.

mock.NewContext() from github.com/pingcap/tidb/util/mock is explicitly documented as test-only. Using it in production code is unsafe because ConstructResultOfShowCreateTable() depends on real session state (e.g., ctx.GetSessionVars().SQLMode) that a mocked context does not provide. This can silently produce incorrect results.

Replace with a real session created via TiDB's session creation flow (e.g., from domain's session pool for internal operations, or run SHOW CREATE TABLE as SQL for external callers).

🤖 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` at line 2813, Replace
the test-only mocked context usage: remove mock.NewContext() and instead obtain
a real session/context for production use (for example, create a session from
the TiDB domain/session pool or use session.CreateSession and its returned
context) so that ConstructResultOfShowCreateTable() can access real session
state (e.g., ctx.GetSessionVars().SQLMode); alternatively, if this handler is
for external callers, execute SHOW CREATE TABLE as SQL and use that result
rather than calling ConstructResultOfShowCreateTable() with a mocked ctx. Ensure
the new code uses the domain/session pool API to create or borrow a session,
sets any required SessionVars, calls ConstructResultOfShowCreateTable() (or runs
SHOW CREATE TABLE) with that real context, and properly closes/returns the
session.

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 improves the robustness of handling CREATE TABLES DDLs by introducing a fallback mechanism. When splitting the DDL query string fails or results in a mismatched number of queries, it now reconstructs the CREATE TABLE statements from the table metadata. This is a solid improvement that makes the system more resilient to unexpected DDL query formats. I've added one suggestion to make the fallback logic even more robust.

Comment on lines +2825 to +2828
query := queryBuilder.String()
if !strings.HasSuffix(query, ";") {
query += ";"
}

Choose a reason for hiding this comment

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

medium

The current logic for appending a semicolon is not robust against trailing whitespace. If queryBuilder.String() were to return a query with a semicolon followed by spaces (e.g., "CREATE TABLE ...; "), this code would append another semicolon. While executor.ConstructResultOfShowCreateTable is unlikely to produce such output, making this fallback logic more robust by trimming whitespace is a good practice.

Suggested change
query := queryBuilder.String()
if !strings.HasSuffix(query, ";") {
query += ";"
}
query := strings.TrimSpace(queryBuilder.String())
if !strings.HasSuffix(query, ";") {
query += ";"
}

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

Labels

do-not-merge/needs-linked-issue do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant