Skip to content

*: honor task collation across DXF encoding and expression paths - #69734

Merged
ti-chi-bot[bot] merged 39 commits into
pingcap:masterfrom
joechenrh:dxf-collation-followup
Aug 24, 2026
Merged

ti-chi-bot[bot] merged 39 commits into
pingcap:masterfrom
joechenrh:dxf-collation-followup

Conversation

@joechenrh

@joechenrh joechenrh commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #69563

Problem Summary:

DXF executes tasks in the SYSTEM keyspace. If its new-collation setting differs from the submitting user keyspace, collation-sensitive encoding and expression paths can use the worker setting and produce incompatible data.

What changed and how does it work?

  • Capture the submitting keyspace's new-collation mode in DXF task metadata, then use that snapshot when reconstructing worker-side objects. Legacy task metadata still falls back to the process setting for compatibility.
  • Keep the runtime state on the objects that own the affected semantics:
    • Table and Index own the encoder used for comparable table and index keys, restored-data decisions, partition routing, and partial-index evaluation.
    • Since BuildContext take charges of the expression evaluation, it also owns the mode used to construct collation-sensitive scalar expressions for DDL reorganization and IMPORT generated-column or assignment evaluation.
  • Let lower-level consumers derive the mode from those owners instead of threading independent booleans through parallel WithCollate APIs. This keeps one task snapshot consistent across key encoding and expression evaluation.
  • Roll back collation-aware Encoder propagation from row/value encoding. New collation changes comparable string sort keys, while row values, old-row values, and generic HashCode serialization use non-comparable encoding and produce identical bytes in either mode. Their original APIs therefore do not need this state.
  • Preserve legacy binary matching for IMPORT ENUM/SET casts without modifying shared schema metadata.

Expression scope: this PR covers scalar expression evaluation used by DXF. Vectorized builtin implementations and the historical INSTR evaluation remain unchanged.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

The local NextGen cluster used new_collations_enabled_on_first_bootstrap = false in the user keyspace and true in the SYSTEM keyspace. Every case ran ADMIN CHECK TABLE, checked index/table results where applicable, performed INSERT/UPDATE/DELETE, and ran ADMIN CHECK TABLE again.

ADD INDEX

Case Schema DDL PR result
Clustered VARCHAR handle PRIMARY KEY(id) CLUSTERED, id/fk VARCHAR ALTER TABLE t ADD INDEX idx_fk(fk) Passed
Composite VARCHAR/INT handle PRIMARY KEY(id1,id2) CLUSTERED, fk INT ALTER TABLE t ADD INDEX idx_fk(fk) Passed
Generated string functions LOWER(raw), UPPER(raw), CONCAT(id,':',raw), SUBSTR(raw,1,2) generated columns Add one index for each generated column Passed
Functional indexes id/raw VARCHAR, clustered VARCHAR PK Add indexes on LOWER, UPPER, CONCAT, and SUBSTR Passed
LIST COLUMNS partition id VARCHAR COLLATE utf8mb4_general_ci, PARTITION BY LIST COLUMNS(id) ALTER TABLE t ADD INDEX idx_fk(fk) Passed
KEY partition id VARCHAR COLLATE utf8mb4_general_ci, PARTITION BY KEY(id) PARTITIONS 4 ALTER TABLE t ADD INDEX idx_fk(fk) Passed
RANGE COLUMNS partition id VARCHAR COLLATE utf8mb4_general_ci, PARTITION BY RANGE COLUMNS(id) ALTER TABLE t ADD INDEX idx_fk(fk) Passed
Partial index raw VARCHAR COLLATE utf8mb4_general_ci ALTER TABLE t ADD INDEX idx_partial(fk) WHERE raw='A' Passed
Collation-sensitive generated expressions Generated columns using =, IN, LIKE, IF, CASE, STRCMP, LOCATE, and GREATEST Add indexes for all generated columns Passed; latest upstream fails ADMIN CHECK TABLE
ENUM/SET indexes ENUM('A','a','B'), SET('A','a','B') with utf8mb4_general_ci Add indexes on ENUM and SET columns Passed

IMPORT INTO

The table omits storage URLs; each operation is IMPORT INTO ... FROM <CSV>.

Case Schema IMPORT SQL or assignment PR result
Clustered VARCHAR handle, VARCHAR index PRIMARY KEY(id) CLUSTERED, KEY(fk) IMPORT INTO t(@1,id,fk) Passed
Clustered VARCHAR handle, INT index PRIMARY KEY(id) CLUSTERED, fk INT, KEY(fk) IMPORT INTO t(fk,id,@3) Passed
Composite VARCHAR/INT handle PRIMARY KEY(id1,id2) CLUSTERED, KEY(fk) IMPORT INTO t(id2,fk,id1) Passed
Composite INT handle, VARCHAR index PRIMARY KEY(id1,id2) CLUSTERED, fk VARCHAR, KEY(fk) IMPORT INTO t(id1,id2,fk) Passed
Composite CHAR handle PRIMARY KEY(id1,id2) CLUSTERED, id1/id2 CHAR, KEY(fk) IMPORT INTO t(fk,id1,id2) Passed
Prefix index Clustered VARCHAR PK, KEY(fk(2)) IMPORT INTO t(@1,id,fk) Passed
Extra payload Clustered VARCHAR PK, VARCHAR index, defaulted payload IMPORT INTO t(@1,id,fk) Passed
Generated string functions Stored generated LOWER, UPPER, CONCAT, and SUBSTR, all indexed IMPORT INTO t(@1,id,raw) Passed
Assignment string functions Assigned/indexed LOWER, UPPER, CONCAT, and SUBSTR results IMPORT INTO t(@1,@2,@3) SET ... Passed
INT-handle control Clustered INT PK, VARCHAR index IMPORT INTO t(id,fk,payload) Passed
LIST COLUMNS partition VARCHAR clustered PK, PARTITION BY LIST COLUMNS(id) IMPORT INTO t(id,fk) Passed; physical partitions match a local-DML control table
RANGE COLUMNS partition VARCHAR clustered PK, PARTITION BY RANGE COLUMNS(id) IMPORT INTO t(id,fk) Passed; physical partitions match a local-DML control table
KEY partition VARCHAR clustered PK, PARTITION BY KEY(id) PARTITIONS 4 IMPORT INTO t(id,fk) Passed; all four physical partitions match a local-DML control table
Partial index KEY idx_partial(fk) WHERE raw='A' IMPORT INTO t(@id,@raw) SET fk=CONCAT('v',@id) Passed
Generated comparisons Stored/indexed =, IN, LIKE, IF, CASE, STRCMP, LOCATE, GREATEST IMPORT INTO t(id,raw) Passed; imported values match local-DML control values
Assignment comparisons Assigned/indexed =, IN, LIKE, IF, CASE, STRCMP, LOCATE, GREATEST IMPORT INTO t(@id,@raw) SET ... Passed; values match legacy binary expectations
ENUM/SET conversion ENUM('A','a','B'), SET('A','a','B'), both indexed IMPORT INTO t(id,e,s) Passed; names and numeric values match local DML
Additional scalar expressions Assigned/indexed <=>, !=, <, >=, ILIKE, REGEXP, FIELD, LEAST, WEIGHT_STRING IMPORT INTO t(@id,@raw) SET ... Passed; values match legacy binary expectations

Latest upstream and this PR were tested with the same cluster and input files:

Validation Latest upstream This PR
LIST partition mismatches 2 0
RANGE COLUMNS partition mismatches 2 0
KEY partition mismatches 3 0
Generated-expression row mismatches 2 0
ENUM/SET row mismatches 1 0
Assignment-expression row mismatches 0 0
Advanced assignment-expression row mismatches 0 0
Unfinished IMPORT jobs 0 0

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

Fix an issue that DXF ADD INDEX or IMPORT INTO might use the worker keyspace's new-collation setting instead of the submitted task's setting in collation-sensitive paths.

Summary by CodeRabbit

  • Bug Fixes

    • Improved consistency for legacy and new collation behavior across string comparisons, pattern matching, casting, indexing, partitioning, imports, and table reorganization.
    • Preserved each table’s configured collation when evaluating partial indexes and routing partitioned data.
    • Prevented incompatible expression pushdown when collation settings differ.
    • Improved handling of ENUM and SET values under legacy collation settings.
  • Tests

    • Added regression coverage for collation-sensitive expressions, indexes, partitions, and data conversion.

@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. labels Jul 9, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@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 Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

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

The change moves new-collation selection into expression contexts. It updates expression builtins, table indexes, partition encoding, DDL backfilling, importer plans, and Lightning codecs to use context-specific collation settings. Tests cover legacy and new-collation behavior.

Changes

Collation context and expression operations

Layer / File(s) Summary
Expression context collation state
pkg/expression/..., pkg/planner/core/...
Expression contexts expose NewCollationEnabled(). Expression construction and planner checks use this state instead of explicit builder flags.
Context-aware expression operations
pkg/expression/builtin*.go, pkg/expression/util.go
String comparisons, pattern matching, lookup, location, and weight-string operations use configured collators.

Table and task integration

Layer / File(s) Summary
Table indexes and partition encoding
pkg/table/tables/..., pkg/table/column.go
Index conditions, partition expressions, partition keys, pruning, and ENUM/SET casts use table-specific collation settings.
DDL task collation integration
pkg/ddl/...
Coprocessor constructors no longer accept explicit collation flags. Backfill indexes come from physical tables, and pushdown checks collation-mode compatibility.
Importer and Lightning encoding
pkg/executor/importer/..., pkg/lightning/backend/kv/..., pkg/meta/model/reorg.go
Import plans capture keyspace collation state. Lightning contexts use table collation settings. Reorganization metadata documentation reflects captured task settings.

Validation

Layer / File(s) Summary
Collation regression coverage
pkg/expression/.../*_test.go, pkg/ddl/.../*_test.go, pkg/table/.../*_test.go, pkg/lightning/backend/kv/base_test.go
Tests cover expression evaluation, coprocessor conditions, reorganization metadata, partition collation snapshots, table indexes, casts, and Lightning contexts.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Task
  participant ExpressionContext
  participant TableEncoder
  participant IndexOrPartition
  Task->>ExpressionContext: configure target collation mode
  ExpressionContext->>TableEncoder: expose NewCollationEnabled
  TableEncoder->>IndexOrPartition: encode values with configured collator
  IndexOrPartition-->>Task: return encoded index or partition result
Loading

Possibly related PRs

  • pingcap/tidb#69677: Refactors and completes captured-collation handling across the same DDL, importer, expression, and table paths.
  • pingcap/tidb#70145: Validates persisted Plan.UseNewCollate handling for import tasks.

Suggested labels: component/import

Suggested reviewers: d3hunter, windtalker, yangkeao

Poem

I’m a rabbit with collators neat,
Making old and new modes meet.
Indexes hop, partitions spin,
Contexts tell the right mode in.
Tests nibble bugs away—
Then leap through merge day!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.50% 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
Linked Issues check ✅ Passed The changes address issue [#69563] by applying the target keyspace collation mode across DXF encoding, partitioning, indexes, expressions, and conversions.
Out of Scope Changes check ✅ Passed The code and test changes remain focused on collation handling for DXF ADD INDEX and IMPORT INTO workflows.
Description check ✅ Passed The description includes the issue number, problem summary, implementation details, extensive test coverage, side effects, documentation impact, and release note.
Title check ✅ Passed The title clearly summarizes the main change: preserving task collation across DXF encoding and expression paths.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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.

@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. sig/planner SIG: Planner labels Jul 9, 2026
@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 Jul 9, 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/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 9, 2026
@joechenrh joechenrh changed the title *: extend DXF collation snapshot coverage *: extend DXF collation coverage Jul 10, 2026
@joechenrh joechenrh changed the title *: extend DXF collation coverage *: extend DXF collation handling to support partition table and partial index Jul 10, 2026
@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 Aug 5, 2026
Comment thread pkg/table/column.go Outdated

@D3Hunter D3Hunter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

rest lgtm

@D3Hunter

D3Hunter commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

/retest

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Aug 10, 2026
astNodeStack []ast.Node

planCtx *exprRewriterPlanCtx
useNewCollate bool

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reverted, now this value is obtained from context.

@YangKeao YangKeao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Aug 10, 2026
@ti-chi-bot

ti-chi-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-08-10 04:07:06.009114102 +0000 UTC m=+3019412.045209148: ☑️ agreed by D3Hunter.
  • 2026-08-10 10:03:59.392993194 +0000 UTC m=+3040825.429088250: ☑️ agreed by YangKeao.

@qw4990 qw4990 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM for the optimizer part

Comment thread pkg/table/column.go
matchEnumSetElementsAsBinary := (ft.GetType() == mysql.TypeEnum || ft.GetType() == mysql.TypeSet) && !ctx.NewCollationEnabled()
if matchEnumSetElementsAsBinary {
// Legacy ENUM/SET element matching is binary even when the field metadata has a non-binary collation.
ft = ft.Clone()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This introduce a per datum's clone, which I think we might run into some efficiency issues

@joechenrh joechenrh Aug 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 801e25b

The background here is: some users migrating to premium retain new-collation=false in the user keyspace, while DXF IMPORT INTO and ADD INDEX tasks execute from the SYSTEM keyspace (tidb-worker) with the process-global setting set to true. The temporary FieldType is only needed for that mismatch, so the condition now also requires collate.NewCollationEnabled() to be true. Normal user execution, where the context and process-global setting agree, keeps using the original FieldType.

Besides, FieldType.Clone() is a shallow struct copy, which is inlined and the temporary value does not escape to the heap, so the remaining mismatched DXF ENUM/SET path has no per-datum heap allocation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it looks to me that it is the code path that only for some corner cases

Comment thread pkg/expression/builtin.go Outdated
useNewCollate bool
// collatorPinned prevents an explicit collator from following later
// collation metadata changes.
collatorPinned bool

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it looks to me useNewCollate/ctor can be inconsistant after introduce this collatorPinned, for example, if useNewCollate is set to true, and later setPinnedCollator is called to set a non-new collation collator. I think the current implementation is prone to introducing inconsistency bugs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 801e25b . Removed the generic pinned-collator state, so the base builtin now has one invariant: its collator is derived from useNewCollate and its collation metadata. The two exceptional functions now own their behavior locally: ILIKE recomputes its binary counterpart in its concrete SetCharsetAndCollation, while WEIGHT_STRING stores the collator derived from its first argument.

@joechenrh

Copy link
Copy Markdown
Contributor Author

/cherry-pick release-202603

@ti-chi-bot

Copy link
Copy Markdown
Member

@joechenrh: once the present PR merges, I will cherry-pick it on top of release-202603 in the new PR and assign it to you.

Details

In response to this:

/cherry-pick release-202603

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 ti-community-infra/tichi repository.

@joechenrh
joechenrh requested a review from windtalker August 21, 2026 06:11

@windtalker windtalker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

@ti-chi-bot

ti-chi-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: D3Hunter, qw4990, windtalker, YangKeao

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 ti-chi-bot Bot added the approved label Aug 21, 2026
@D3Hunter

Copy link
Copy Markdown
Contributor

/retest

@ti-chi-bot
ti-chi-bot Bot merged commit 6eff575 into pingcap:master Aug 24, 2026
37 checks passed
@ti-chi-bot

Copy link
Copy Markdown
Member

@joechenrh: cannot checkout release-202603: error checking out release-202603: exit status 1. output: error: pathspec 'release-202603' did not match any file(s) known to git

Details

In response to this:

/cherry-pick release-202603

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 ti-community-infra/tichi repository.

@joechenrh

Copy link
Copy Markdown
Contributor Author

/cherry-pick release-nextgen-202603

@ti-chi-bot

Copy link
Copy Markdown
Member

@joechenrh: new pull request created to branch release-nextgen-202603: #70621.
But this PR has conflicts, please resolve them!

Details

In response to this:

/cherry-pick release-nextgen-202603

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 ti-community-infra/tichi repository.

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

Labels

approved lgtm release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/planner SIG: Planner 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.

nextgen: tasks can use SYSTEM new_collation_enabled when encoding user keyspace KV

7 participants