diff --git a/migrations/20250618184304-volumes-truncate-hostPath.js b/migrations/20250618184304-volumes-truncate-hostPath.js new file mode 100644 index 000000000..db040a7e5 --- /dev/null +++ b/migrations/20250618184304-volumes-truncate-hostPath.js @@ -0,0 +1,11 @@ +'use strict'; + +exports.up = async function (db) { + // InnoDB has a strict maximum index key length. utf8mb8 (next migration) means 1024*4=4096. max in our db is 3072 + await db.runSql('UPDATE volumes SET hostPath=LEFT(hostPath, 768)'); + await db.runSql('ALTER TABLE volumes MODIFY hostPath VARCHAR(768) NOT NULL UNIQUE'); +}; + +exports.down = async function (db) { + await db.runSql('ALTER TABLE tasks DROP COLUMN pending'); +}; diff --git a/migrations/20250618200400-fix-charset-collate.js b/migrations/20250618200400-fix-charset-collate.js new file mode 100644 index 000000000..c92e5beda --- /dev/null +++ b/migrations/20250618200400-fix-charset-collate.js @@ -0,0 +1,29 @@ +'use strict'; + +exports.up = async function (db) { + const tableNames = [ + 'userGroups', 'users', 'domains', 'tasks', 'volumes', 'apps', 'backups', 'mail', + + 'appAddonConfigs', 'appEnvVars', 'appMounts', 'appPasswords', 'appPortBindings', 'applinks', 'archives', + 'blobs', 'dockerRegistries', 'eventlog', 'groupMembers', 'locations', 'locks', 'mailboxes', + 'migrations', 'notifications', 'oidcClients', 'settings', 'tokens' + ]; + + await db.runSql('SET foreign_key_checks = 0'); + + // this should already be the default + console.log('Changing database charset'); + await db.runSql('ALTER DATABASE box CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin'); + + for (const tableName of tableNames) { + // this update all applicable columns (VARCHAR, TEXT, etc.) to use the new character set and collation and not just the table! + console.log(`Changing charset of ${tableName}`); + await db.runSql(`ALTER TABLE ${tableName} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin`); + } + + await db.runSql('SET foreign_key_checks = 1'); +}; + +exports.down = async function (db) { + // no going back! +}; diff --git a/migrations/schema.sql b/migrations/schema.sql index b2d3e2528..f5da902b7 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -2,7 +2,7 @@ #### This file is not used by any code and is here to document the latest schema #### General ideas -#### Default char set is utf8 and DEFAULT COLLATE is utf8_bin. Collate affects comparisons in WHERE and ORDER +#### Default char set is utf8mb4 and DEFAULT COLLATE is utf8mb4_bin. Collate affects comparisons in WHERE and ORDER #### Strict mode is enabled #### VARCHAR - stored as part of table row (use for strings) #### TEXT - stored offline from table row (use for strings) @@ -193,10 +193,7 @@ CREATE TABLE IF NOT EXISTS domains( fallbackCertificateJson MEDIUMTEXT, - PRIMARY KEY (domain)) - - /* the default db collation is utf8mb4_unicode_ci but for the app table domain constraint we have to use the old one */ - CHARACTER SET utf8 COLLATE utf8_bin; + PRIMARY KEY (domain)); CREATE TABLE IF NOT EXISTS mail( domain VARCHAR(128) NOT NULL UNIQUE, @@ -211,9 +208,7 @@ CREATE TABLE IF NOT EXISTS mail( dkimSelector VARCHAR(128) NOT NULL DEFAULT "cloudron", FOREIGN KEY(domain) REFERENCES domains(domain), - PRIMARY KEY(domain)) - - CHARACTER SET utf8 COLLATE utf8_bin; + PRIMARY KEY(domain)); /* NOTE: this table contains only real mailboxes. And has unique constraint to handle conflict with aliases and mailbox names