Skip to content

redo: add column info for redo ddl event#4809

Open
wk989898 wants to merge 6 commits intopingcap:masterfrom
wk989898:redo-0413
Open

redo: add column info for redo ddl event#4809
wk989898 wants to merge 6 commits intopingcap:masterfrom
wk989898:redo-0413

Conversation

@wk989898
Copy link
Copy Markdown
Collaborator

@wk989898 wk989898 commented Apr 13, 2026

What problem does this PR solve?

Issue Number: close #4699

What is changed and how it works?

Add column info for Redo DDL event to avoid panic if the column type is time default with origin_default

This PR #3991 will use column info in the DDL event to align the upstream current timestamp. TiCDC has to encode column info for redo ddl event, and redo apply will decode the column info for replicating the ddl event.

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

  • New Features

    • Redo logs now persist full column metadata (name, type, origin default, version) enabling richer DDL reconstruction.
  • Bug Fixes

    • Conversion to/from redo logs now safely handles missing or nil table schema without panics; preserves nil vs empty columns appropriately.
  • Tests

    • Added serialization tests, benchmarks, and round-trip coverage to validate column metadata preservation.

Signed-off-by: wk989898 <nhsmwk@gmail.com>
@ti-chi-bot ti-chi-bot bot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Apr 13, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 39f4a387-8227-45e0-b3ae-79c5a351ab0d

📥 Commits

Reviewing files that changed from the base of the PR and between 7a9101f and 8156bd7.

📒 Files selected for processing (2)
  • pkg/common/event/redo_test.go
  • pkg/common/table_info.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/common/event/redo_test.go

📝 Walkthrough

Walkthrough

Added persistent per-column metadata to DDL redo logs: introduced exported ColumnInfo and DDLEventInRedoLog.Columns, serialized table columns in DDLEvent.ToRedoLog(), reconstructed full timodel.TableInfo.Columns in RedoDDLEvent.ToDDLEvent(), added msgp serialization for ColumnInfo, and added tests and benchmarks.

Changes

Cohort / File(s) Summary
DDL redo structures & conversion
pkg/common/event/redo.go
Added exported ColumnInfo and DDLEventInRedoLog.Columns; DDLEvent.ToRedoLog() now serializes TableInfo columns when present; RedoDDLEvent.ToDDLEvent() rebuilds timodel.TableInfo.Columns including Name, Type, Version, OriginDefaultValue, and sets StatePublic / IsPartition.
MessagePack serialization
pkg/common/event/redo_gen.go
Added full msgp methods for ColumnInfo and extended DDLEventInRedoLog msgp encode/decode/marshal/unmarshal/Msgsize to include "columns" array (handles nil elements) and updated map header sizing.
Serialization tests & benchmarks
pkg/common/event/redo_gen_test.go
Added marshal/unmarshal roundtrip tests and benchmarks for ColumnInfo (MarshalMsg, append-style marshal, UnmarshalMsg, EncodeMsg, DecodeMsg).
Round-trip integration tests
pkg/common/event/redo_test.go
Added tests verifying DDL→redo→DDL round-trip preserves per-column metadata and that DDLEvent.ToRedoLog() handles nil or uninitialized TableInfo without panicking.
TableInfo nil-safety
pkg/common/table_info.go
Made TableInfo.GetColumns() defensively return nil when receiver or internal schema is nil to avoid nil dereference.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

lgtm, size/XL

Suggested reviewers

  • wlwilliamx
  • hongyunyan
  • 3AceShowHand

Poem

🐰 I hopped through schemas, tucked defaults with care,
Packed names, types, versions — stored them all in a lair.
Bytes hopped in boxes, then danced back in line,
Round-trip brought them home — I nibbled a carrot, fine. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'redo: add column info for redo ddl event' accurately reflects the main change: adding column information persistence to redo DDL events.
Description check ✅ Passed The PR description includes Issue Number (close #4699), explains the change and motivation, addresses the checklist items (Unit test included), but leaves questions and release-note sections incomplete.
Linked Issues check ✅ Passed The PR addresses the root cause of issue #4699 by encoding column metadata in redo DDL events, enabling proper handling of TIME columns with origin_default values.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #4699: redo event serialization now includes column info, tests verify round-trip preservation, and TableInfo.GetColumns is hardened against nil receivers.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 ti-chi-bot bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Apr 13, 2026
Copy link
Copy Markdown

@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 ColumnInfo struct and adds a Columns field to DDLEventInRedoLog to store column metadata in redo logs, addressing a bug related to timestamp default values in different time zones. The changes include updating the ToRedoLog and ToDDLEvent methods to handle this new metadata, along with generated serialization code and tests. A potential nil pointer dereference was identified in the ToRedoLog function when accessing TableInfo before a nil check.

Copy link
Copy Markdown
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/common/event/redo.go`:
- Around line 219-227: The code in ToRedoLog() accesses d.TableInfo.GetColumns()
and builds columns before checking d.TableInfo for nil, causing a panic for DDL
events without table metadata; guard the access by first verifying d.TableInfo
!= nil (and optionally d.TableInfo.GetColumns() != nil) before iterating, and
only construct the columns slice and append ColumnInfo entries when d.TableInfo
is non-nil; refer to d.TableInfo, ToRedoLog(), and ColumnInfo to locate and fix
the offending block.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7132d7da-c277-4fdd-beb0-cfcfda7fefc4

📥 Commits

Reviewing files that changed from the base of the PR and between 0a418b4 and 4c87d10.

📒 Files selected for processing (3)
  • pkg/common/event/redo.go
  • pkg/common/event/redo_gen.go
  • pkg/common/event/redo_gen_test.go

Signed-off-by: wk989898 <nhsmwk@gmail.com>
Signed-off-by: wk989898 <nhsmwk@gmail.com>
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
pkg/common/event/redo.go (1)

394-418: ⚠️ Potential issue | 🟠 Major

Handle older redo payloads without columns.

Line 394 still treats r.DDL.Columns == nil as “table with zero columns”. For redo files written before this field existed, replay will silently build an incomplete TableInfo instead of failing fast or version-gating the format, so the applier is still not semantically backward-compatible with persisted pre-change redo logs.

Suggested direction
 func (r *RedoDDLEvent) ToDDLEvent() *DDLEvent {
 	blockedTables := r.DDL.BlockedTables
 	blockedTableNames := r.DDL.BlockedTableNames
 	if blockedTables == nil {
 		blockedTables = &InfluencedTables{InfluenceType: InfluenceTypeNormal}
 		blockedTableNames = []SchemaTableName{{SchemaName: r.TableName.Schema, TableName: r.TableName.Table}}
 	}
+	if r.DDL.Columns == nil && r.TableName.Table != "" {
+		log.Panic("redo ddl column metadata missing",
+			zap.String("schema", r.TableName.Schema),
+			zap.String("table", r.TableName.Table),
+			zap.Uint64("commitTs", r.DDL.CommitTs))
+	}
 	columns := make([]*timodel.ColumnInfo, 0, len(r.DDL.Columns))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/common/event/redo.go` around lines 394 - 418, The code currently treats
r.DDL.Columns == nil as an empty column list which silently accepts older redo
payloads; update the DDLEvent construction to detect a nil r.DDL.Columns and
fail fast (return an error or log.Panic) instead of building a TableInfo with
zero columns. Specifically, in the block that iterates r.DDL.Columns (used to
build columns and call commonType.NewTableInfo4Decoder and create the DDLEvent),
add an explicit nil check for r.DDL.Columns and emit a clear error message
indicating an unsupported/older redo format (include identifying info like
r.TableName and any available redo version metadata) so replaying pre-change
redo logs does not produce an invalid TableInfo.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@pkg/common/event/redo.go`:
- Around line 394-418: The code currently treats r.DDL.Columns == nil as an
empty column list which silently accepts older redo payloads; update the
DDLEvent construction to detect a nil r.DDL.Columns and fail fast (return an
error or log.Panic) instead of building a TableInfo with zero columns.
Specifically, in the block that iterates r.DDL.Columns (used to build columns
and call commonType.NewTableInfo4Decoder and create the DDLEvent), add an
explicit nil check for r.DDL.Columns and emit a clear error message indicating
an unsupported/older redo format (include identifying info like r.TableName and
any available redo version metadata) so replaying pre-change redo logs does not
produce an invalid TableInfo.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 884b9299-2968-4bcf-be28-98ccd4fea24a

📥 Commits

Reviewing files that changed from the base of the PR and between 4c87d10 and 2253947.

📒 Files selected for processing (2)
  • pkg/common/event/redo.go
  • pkg/common/event/redo_test.go

Signed-off-by: wk989898 <nhsmwk@gmail.com>
Copy link
Copy Markdown
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

♻️ Duplicate comments (1)
pkg/common/event/redo.go (1)

390-410: ⚠️ Potential issue | 🟠 Major

Distinguish missing Columns from a real zero-column schema.

On Lines 390-410, r.DDL.Columns == nil takes the same path as an intentionally empty column list and silently rebuilds an empty TableInfo. Older redo payloads decode exactly that way when the new field is absent, so pre-change redo files still replay without the metadata this fix depends on. Please version-gate the format or fail fast when Columns is missing instead of continuing with zero columns.

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

In `@pkg/common/event/redo.go` around lines 390 - 410, The code treats
r.DDL.Columns == nil the same as an intentionally empty column list, which hides
older redo payloads that omitted the field; update the handler to detect a nil
Columns slice and fail-fast or enforce a format version check before rebuilding
TableInfo: when r.DDL.Columns == nil (use the r.DDL or envelope version field or
add one), return/raise a clear error mentioning r.TableName and that Columns is
missing (instead of constructing an empty []*timodel.ColumnInfo), or gate the
path behind a version check so only payloads with the new schema proceed to
build timodel.ColumnInfo via SetOriginDefaultValue and
commonType.NewTableInfo4Decoder.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/common/event/redo.go`:
- Around line 406-410: The code is calling the test-only helper
commonType.NewTableInfo4Decoder from redo replay; replace this with the
production initializer for table metadata (i.e., use the supported
constructor/factory that the package exposes for runtime use instead of
NewTableInfo4Decoder). Update the creation of tableInfo in redo.go by invoking
the production API (for example the package's NewTableInfo /
NewTableInfoFromTiTable or equivalent factory that accepts schema, ID, name and
columns) and populate it with r.TableName.Schema, r.TableName.TableID,
ast.NewCIStr(r.TableName.Table) and columns so redo replay no longer depends on
the test-only NewTableInfo4Decoder.

---

Duplicate comments:
In `@pkg/common/event/redo.go`:
- Around line 390-410: The code treats r.DDL.Columns == nil the same as an
intentionally empty column list, which hides older redo payloads that omitted
the field; update the handler to detect a nil Columns slice and fail-fast or
enforce a format version check before rebuilding TableInfo: when r.DDL.Columns
== nil (use the r.DDL or envelope version field or add one), return/raise a
clear error mentioning r.TableName and that Columns is missing (instead of
constructing an empty []*timodel.ColumnInfo), or gate the path behind a version
check so only payloads with the new schema proceed to build timodel.ColumnInfo
via SetOriginDefaultValue and commonType.NewTableInfo4Decoder.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: feba35b4-36da-4206-9537-e34d7fb7bfb3

📥 Commits

Reviewing files that changed from the base of the PR and between 2253947 and 7b0c438.

📒 Files selected for processing (1)
  • pkg/common/event/redo.go

Copy link
Copy Markdown
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)
pkg/common/event/redo.go (1)

390-405: Consider setting column ID for consistency with DML reconstruction.

The DML reconstruction in ToDMLEvent() (line 297) sets ID: int64(idx) for each column, but this DDL path omits the column ID. If downstream code relies on ColumnInfo.ID, this could cause unexpected behavior.

♻️ Proposed fix to set column ID
 for _, col := range r.DDL.Columns {
 	colInfo := &timodel.ColumnInfo{
+		ID:      int64(len(columns)),
 		Name:    ast.NewCIStr(col.Name),
 		State:   timodel.StatePublic,
 		Version: col.Version,
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/common/event/redo.go` around lines 390 - 405, The DDL reconstruction loop
builds []*timodel.ColumnInfo from r.DDL.Columns but never sets ColumnInfo.ID,
causing inconsistency with ToDMLEvent() which sets ID: int64(idx); update the
loop that creates colInfo in redo.go to assign colInfo.ID = int64(idx) (use the
loop index) before appending to columns so DDL-created ColumnInfo objects have
the same ID semantics as DML reconstruction and downstream code that reads
ColumnInfo.ID works correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/common/event/redo.go`:
- Around line 390-405: The DDL reconstruction loop builds []*timodel.ColumnInfo
from r.DDL.Columns but never sets ColumnInfo.ID, causing inconsistency with
ToDMLEvent() which sets ID: int64(idx); update the loop that creates colInfo in
redo.go to assign colInfo.ID = int64(idx) (use the loop index) before appending
to columns so DDL-created ColumnInfo objects have the same ID semantics as DML
reconstruction and downstream code that reads ColumnInfo.ID works correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c7e0fb72-9826-4ddf-b778-9c20fe3aaf68

📥 Commits

Reviewing files that changed from the base of the PR and between 7b0c438 and 7a9101f.

📒 Files selected for processing (1)
  • pkg/common/event/redo.go

@ti-chi-bot ti-chi-bot bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Apr 13, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot bot commented Apr 13, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: 3AceShowHand

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:

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
Copy link
Copy Markdown

ti-chi-bot bot commented Apr 13, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-04-13 09:26:23.323104469 +0000 UTC m=+1380388.528464526: ☑️ agreed by 3AceShowHand.

@ti-chi-bot ti-chi-bot bot added the approved label Apr 13, 2026
Signed-off-by: wk989898 <nhsmwk@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved needs-1-more-lgtm Indicates a PR needs 1 more LGTM. 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.

unstable test checkpoint_race_ddl_crash

2 participants