docs/plans/2025-12-20-remove-database-iscasesensitive-design.md
Date: 2025-12-20 Status: Proposed
The IsCaseSensitive field in FindDatabaseMessage adds unnecessary complexity to database store lookups:
Current behavior:
IsCaseSensitive=true: Uses db.name = ? (exact match)IsCaseSensitive=false: Uses LOWER(db.name) = LOWER(?) (case-insensitive)Why it exists:
lower_case_table_names, TiDB, MSSQL)Why it's unnecessary:
Database names are synced exactly - The sync pipeline stores database names exactly as returned by the engine with no normalization (mysql/sync.go:102, tidb/sync.go:94, pg/pg.go:305)
Clients use exact names - API clients get resource names from our responses (e.g., GET /v1/instances/prod/databases returns {name: "instances/prod/databases/MyDB"}) and reuse them verbatim in subsequent requests
Internal references are exact - Tasks, rollouts, and other internal components store the exact database name from database records
Performance cost - LOWER(db.name) = LOWER(?) prevents efficient index usage on the UNIQUE(instance, name) constraint
Remove the IsCaseSensitive field entirely and always use exact matching in store layer queries.
Code change:
// Before (database.go:147-151)
if find.IsCaseSensitive {
where.And("db.name = ?", *v)
} else {
where.And("LOWER(db.name) = LOWER(?)", *v)
}
// After
where.And("db.name = ?", *v)
Scope of changes:
Store layer (remove case-insensitive logic):
backend/store/database.go - Remove IsCaseSensitive field from FindDatabaseMessage (line 71)IsCaseSensitive: store.IsObjectCaseSensitive(instance):
backend/api/v1/database_service.gobackend/api/v1/database_service_changelog.gobackend/api/v1/common.gobackend/api/v1/rollout_service.gobackend/component/export/resources.gobackend/component/sampleinstance/manager.gobackend/runner/approval/runner.gobackend/runner/taskrun/database_migrate_executor.goQuery/LSP layer (keep existing logic):
IsObjectCaseSensitive() function in backend/store/instance.go:348SELECT * FROM mydb.users, the Query/LSP layer needs to match "mydb" against stored metadata using case-sensitivity rulesIsObjectCaseSensitive(instance) for auto-completion and span analysisParser contexts (keep existing):
backend/plugin/parser/base/ - Keep IsCaseSensitive field in parser contextsIf a database name mismatch occurs (e.g., from manual DB manipulation or API bug):
Before implementing the change:
Verify no case duplicates exist:
SELECT instance, name FROM db
GROUP BY instance, LOWER(name)
HAVING COUNT(*) > 1;
Expected: Zero rows (enforced by UNIQUE(instance, name) constraint)
Grep for manual database name construction:
grep -r "DatabaseName.*=" backend/ | grep -v "database.DatabaseName"
Verify callers get names from database records, not constructing them
Existing tests should pass - If tests break, they were relying on incorrect fuzzy matching
Add explicit test for exact matching:
func TestGetDatabase_ExactMatchRequired(t *testing.T) {
// Create database "MyDatabase"
// Query with "mydatabase" should return nil (not found)
// Query with "MyDatabase" should succeed
}
Integration test: Sync a real MySQL/TiDB instance, verify databases are found with their exact synced names
UNIQUE(instance, name) constraintIsCaseSensitive field from FindDatabaseMessage structIsCaseSensitive assignments from all ~15 call sitesIsCaseSensitive logic if needed (though it shouldn't be)