Skip to content

Fix drop constraint unique pk#19420

Open
anshikavashistha wants to merge 8 commits intovitessio:mainfrom
anshikavashistha:fix-drop-constraint-unique-pk
Open

Fix drop constraint unique pk#19420
anshikavashistha wants to merge 8 commits intovitessio:mainfrom
anshikavashistha:fix-drop-constraint-unique-pk

Conversation

@anshikavashistha
Copy link
Collaborator

@anshikavashistha anshikavashistha commented Feb 18, 2026

Summary

This PR extends the ALTER TABLE ... DROP CONSTRAINT <name> support in Vitess to correctly handle the dropping of named PRIMARY KEY and UNIQUE constraints, aligning with MySQL 8.0.19+ behavior.

Previously, PR #19183 added support for dropping FOREIGN KEY and CHECK constraints using named constraints, but did not handle named UNIQUE and PRIMARY KEY constraints.

The root cause was that DROP CONSTRAINT logic only searched TableSpec.Constraints. However, named UNIQUE and PRIMARY KEY constraints are stored in TableSpec.Indexes under IndexDefinition.ConstraintName.

With this change, users can now drop explicitly named PRIMARY KEY or UNIQUE constraints using standard ALTER TABLE ... DROP CONSTRAINT <name> syntax, matching MySQL behavior.

What changed?

  • DROP CONSTRAINT handling extended – Now searches both TableSpec.Constraints and TableSpec.Indexes
  • Named PRIMARY KEY constraints – Properly removed when dropped
  • Named UNIQUE constraints – Properly removed when dropped
  • Unit tests added – Comprehensive test coverage for both constraint types
  • Backward compatibility – All existing behavior preserved
  • MySQL 8.0.19+ alignment – Behavior now matches MySQL standard

Related Issue(s)

Fixes #19232

Checklist

  • "Backport to:" labels have been added if this change should be back-ported to release branches
  • If this change is to be back-ported to previous releases, a justification is included in the PR description
  • Tests were added or are not required
  • Did the new or modified tests pass consistently locally and on CI?
  • Documentation was added or is not required

Deployment Notes

None.

@github-actions github-actions bot added Component: VTAdmin VTadmin interface Type: Dependencies Dependency updates labels Feb 18, 2026
@vitess-bot vitess-bot bot added NeedsWebsiteDocsUpdate What it says NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request NeedsBackportReason If backport labels have been applied to a PR, a justification is required labels Feb 18, 2026
@anshikavashistha anshikavashistha changed the base branch from fix-drop-constraint-unique-pk to main February 18, 2026 20:32
Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
@anshikavashistha anshikavashistha force-pushed the fix-drop-constraint-unique-pk branch from b5e808e to ddad7a6 Compare February 18, 2026 21:52
Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
@codecov
Copy link

codecov bot commented Feb 23, 2026

Codecov Report

❌ Patch coverage is 88.23529% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.73%. Comparing base (06f2aa7) to head (0d14873).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
go/vt/sqlparser/parser.go 72.22% 5 Missing ⚠️
go/vt/schemadiff/onlineddl.go 84.61% 2 Missing ⚠️
go/vt/schemadiff/table.go 95.23% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #19420      +/-   ##
==========================================
+ Coverage   69.62%   69.73%   +0.11%     
==========================================
  Files        1614     1614              
  Lines      216398   216870     +472     
==========================================
+ Hits       150658   151235     +577     
+ Misses      65740    65635     -105     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
@anshikavashistha
Copy link
Collaborator Author

@mattlord ,please take a look.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You accidentally left this Go toolchain artifact.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I have removed this file

Comment on lines 650 to 660
case *sqlparser.IndexDefinition:
// Handle named UNIQUE/PRIMARY KEY constraints stored in IndexInfo.ConstraintName
if node.Info.ConstraintName.String() != "" {
oldName := node.Info.ConstraintName.String()
// For CREATE TABLE, named UNIQUE/PRIMARY KEY constraints should just append "_" suffix
// (hash suffixing is only for specific OnlineDDL flows, not regular CREATE TABLE)
newName := oldName + "_"
node.Info.ConstraintName = sqlparser.NewIdentifierCI(newName)
constraintMap[oldName] = newName
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I might be missing something, but why do we need this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch on the inconsistency. Named UNIQUE/PRIMARY constraints stored in IndexInfo.ConstraintName are part of MySQL's schema-wide constraint namespace, so they do need renaming during table duplication — but you're right that "_" suffix is wrong here. I've updated this to use generateConstraintNameWithHash consistent with how FK/check constraints are handled.

b.WriteString(sql[start:])
}
sql = b.String()
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This logic is really brittle. It matches the substring anywhere, including inside string literals, comments, or DEFAULT values. For example, drop constraint primary_key would become invalid drop primary key_key.

Furthermore, DROP CONSTRAINT PRIMARY (unquoted) is not actually valid MySQL syntax. PRIMARY is a reserved keyword, not a constraint symbol. MySQL docs state that the type-specific form must be used for primary keys:

The SQL standard specifies that all types of constraints (primary key, unique index, foreign key, check) belong to the same namespace. In MySQL, each constraint type has its own namespace per schema. Consequently, names for each type of constraint must be unique per schema, but constraints of different types can have the same name. When multiple constraints have the same name, DROP CONSTRAINT and ADD CONSTRAINT are ambiguous and an error occurs. In such cases, constraint-specific syntax must be used to modify the constraint. For example, use DROP PRIMARY KEY or DROP FOREIGN KEY to drop a primary key or foreign key.

https://dev.mysql.com/doc/refman/8.4/en/alter-table.html

I suggest we drop this logic and any related logic. Was there a reason this was added in the first place? Am I missing some Vitess-specific behavior that requires this? In the case we would need this, it would better fit in the grammar and not as string replacements.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You're absolutely right — the substring rewrite in parser.go was brittle and DROP CONSTRAINT PRIMARY is not valid MySQL syntax at the parser level.
I've removed the entire pre-parse string replacement block from parser.go and reverted ParseStrictDDL to its original state.

Comment on lines +2288 to +2322
case sqlparser.ConstraintType:
// ConstraintType can refer to any constraint type: foreign key, check, or named UNIQUE/PRIMARY KEY
// First check TableSpec.Constraints for foreign keys and check constraints
for i, constraint := range c.TableSpec.Constraints {
if strings.EqualFold(constraint.Name.String(), opt.Name.String()) {
found = true
c.TableSpec.Constraints = append(c.TableSpec.Constraints[0:i], c.TableSpec.Constraints[i+1:]...)
break
}
}
// If not found in Constraints, check TableSpec.Indexes for named UNIQUE/PRIMARY KEY constraints
if !found {
for i, index := range c.TableSpec.Indexes {
// Only match UNIQUE or PRIMARY KEY indexes
if index.Info.Type != sqlparser.IndexTypeUnique && index.Info.Type != sqlparser.IndexTypePrimary {
continue
}
// Prefer matching on ConstraintName when present
if index.Info.ConstraintName.String() != "" &&
strings.EqualFold(index.Info.ConstraintName.String(), opt.Name.String()) {
found = true
c.TableSpec.Indexes = append(c.TableSpec.Indexes[0:i], c.TableSpec.Indexes[i+1:]...)
break
}
// Fallback: allow DROP CONSTRAINT <name> to target a UNIQUE KEY defined without the CONSTRAINT
// keyword (i.e. created via `UNIQUE KEY uk_name (...)`). In that case ConstraintName is empty
// and the index is identified by its Name.
if index.Info.ConstraintName.String() == "" &&
strings.EqualFold(index.Info.Name.String(), opt.Name.String()) {
found = true
c.TableSpec.Indexes = append(c.TableSpec.Indexes[0:i], c.TableSpec.Indexes[i+1:]...)
break
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This may not needed right now, but MySQL returns an error when multiple constraints have the same name (when using DROP CONSTRAINT). We should likely match that behavior.

Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
@anshikavashistha anshikavashistha force-pushed the fix-drop-constraint-unique-pk branch from 34974f8 to 07209a3 Compare February 24, 2026 19:37
…on case

Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
Signed-off-by: anshikavashistha <anshikav1534@gmail.com>
@anshikavashistha anshikavashistha force-pushed the fix-drop-constraint-unique-pk branch from 8e3e0cd to 55a8252 Compare February 24, 2026 20:35
Signed-off-by: anshikavashistha <93611566+anshikavashistha@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component: VTAdmin VTadmin interface NeedsBackportReason If backport labels have been applied to a PR, a justification is required NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request NeedsWebsiteDocsUpdate What it says Type: Dependencies Dependency updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug Report: DROP CONSTRAINT does not work for UNIQUE/PRIMARY KEY constraints

2 participants