diff --git a/migrations/dlu/mysql/29_dashboard_moderation.sql b/migrations/dlu/mysql/29_dashboard_moderation.sql index a3a9f7669..48d25d322 100644 --- a/migrations/dlu/mysql/29_dashboard_moderation.sql +++ b/migrations/dlu/mysql/29_dashboard_moderation.sql @@ -1,6 +1,22 @@ -/* Columns used by the web dashboard. Names match NexusDashboard so databases it already migrated keep their data, - statements for columns that already exist fail individually and are skipped. */ -ALTER TABLE play_keys ADD COLUMN notes TEXT NULL; -ALTER TABLE bug_reports ADD COLUMN resolved_time TIMESTAMP NULL DEFAULT NULL; -ALTER TABLE bug_reports ADD COLUMN resoleved_by_id INT NULL; -ALTER TABLE bug_reports ADD COLUMN resolution TEXT NULL; +/* Columns used by the web dashboard. Names match NexusDashboard so databases it already migrated keep their data: + each column is only added when it is not there yet. */ +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE play_keys ADD COLUMN notes TEXT NULL', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'play_keys' AND column_name = 'notes'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE bug_reports ADD COLUMN resolved_time TIMESTAMP NULL DEFAULT NULL', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'bug_reports' AND column_name = 'resolved_time'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE bug_reports ADD COLUMN resoleved_by_id INT NULL', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'bug_reports' AND column_name = 'resoleved_by_id'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE bug_reports ADD COLUMN resolution TEXT NULL', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'bug_reports' AND column_name = 'resolution'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; diff --git a/migrations/dlu/mysql/30_account_email.sql b/migrations/dlu/mysql/30_account_email.sql index 1c141fa33..9909e90d1 100644 --- a/migrations/dlu/mysql/30_account_email.sql +++ b/migrations/dlu/mysql/30_account_email.sql @@ -1,7 +1,15 @@ -/* Account email for password resets. email/email_confirmed_at match NexusDashboard's columns so existing data is kept, - statements for columns that already exist fail individually and are skipped. */ -ALTER TABLE accounts ADD COLUMN email VARCHAR(255) NULL DEFAULT ''; -ALTER TABLE accounts ADD COLUMN email_confirmed_at DATETIME NULL DEFAULT NULL; +/* Account email for password resets. email/email_confirmed_at match NexusDashboard's columns so existing data is kept: + they are only added when they are not there yet. */ +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE accounts ADD COLUMN email VARCHAR(255) NULL DEFAULT ''''', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'accounts' AND column_name = 'email'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE accounts ADD COLUMN email_confirmed_at DATETIME NULL DEFAULT NULL', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'accounts' AND column_name = 'email_confirmed_at'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; /* Sessions issued before this unix time are rejected, e.g. after a password reset */ ALTER TABLE accounts ADD COLUMN sessions_valid_after BIGINT NOT NULL DEFAULT 0; CREATE TABLE IF NOT EXISTS account_tokens ( diff --git a/migrations/dlu/mysql/40_pet_name_owner.sql b/migrations/dlu/mysql/40_pet_name_owner.sql index f49240ab6..cf76ad8b4 100644 --- a/migrations/dlu/mysql/40_pet_name_owner.sql +++ b/migrations/dlu/mysql/40_pet_name_owner.sql @@ -1,4 +1,17 @@ /* Who owns each named pet, written by the game when the name is set. NULL: not looked up yet (the dashboard fills those in once from the characters' inventories); 0: no character has the pet any more. */ -ALTER TABLE pet_names ADD COLUMN owner_id BIGINT NULL DEFAULT NULL; -CREATE INDEX pet_names_owner ON pet_names (owner_id); +SET @dlu_column = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE pet_names ADD COLUMN owner_id BIGINT NULL DEFAULT NULL', 'DO 0') FROM information_schema.columns + WHERE table_schema = DATABASE() AND table_name = 'pet_names' AND column_name = 'owner_id'); +PREPARE dlu_column_stmt FROM @dlu_column; +EXECUTE dlu_column_stmt; +DEALLOCATE PREPARE dlu_column_stmt; +/* Some servers added this column (and an index on it) themselves: only index it when nothing does yet */ +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX pet_names_owner ON pet_names (owner_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'pet_names' AND column_name = 'owner_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +/* Those servers' character ids written before 23_store_character_id_as_objectid.sql, which did not convert this + column, have no persistent bit and match no character. Give them the bit, as 23 did for every other character id + column. Does nothing on a column just added (every row is NULL). */ +UPDATE pet_names SET owner_id = owner_id | 0x1000000000000000 WHERE owner_id > 0 AND owner_id < 0x1000000000000000; diff --git a/migrations/dlu/mysql/57_lookup_indexes.sql b/migrations/dlu/mysql/57_lookup_indexes.sql index d6aae3461..ae8349284 100644 --- a/migrations/dlu/mysql/57_lookup_indexes.sql +++ b/migrations/dlu/mysql/57_lookup_indexes.sql @@ -2,17 +2,51 @@ * Indexes for lookups by owner/parent that otherwise scan the whole table: a property's models (and the model count * on every property list row), a character's properties, an account's characters, a play key's accounts, friends * both ways, a character's mail, a leaderboard's scores, and the dashboard's per-character/account related data. - * The columns' inline REFERENCES clauses in 0_initial.sql create no foreign key (and so no index) in MySQL/MariaDB. + * Whether the columns' inline REFERENCES clauses in 0_initial.sql made a foreign key (and with it an index) depends on + * the server: MySQL before 9.0 ignores them, MariaDB 10.5 and later creates them. So each index on such a column is + * only created when no index starts with that column yet; a second one would only slow down writes. */ -CREATE INDEX properties_contents_property ON properties_contents (property_id); -CREATE INDEX properties_contents_ugc ON properties_contents (ugc_id); -CREATE INDEX properties_owner ON properties (owner_id); -CREATE INDEX charinfo_account ON charinfo (account_id); -CREATE INDEX accounts_play_key ON accounts (play_key_id); -CREATE INDEX friends_friend ON friends (friend_id); -CREATE INDEX mail_receiver ON mail (receiver_id); +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX properties_contents_property ON properties_contents (property_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'properties_contents' AND column_name = 'property_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX properties_contents_ugc ON properties_contents (ugc_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'properties_contents' AND column_name = 'ugc_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX properties_owner ON properties (owner_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'properties' AND column_name = 'owner_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX charinfo_account ON charinfo (account_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'charinfo' AND column_name = 'account_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX accounts_play_key ON accounts (play_key_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'accounts' AND column_name = 'play_key_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX friends_friend ON friends (friend_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'friends' AND column_name = 'friend_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX mail_receiver ON mail (receiver_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'mail' AND column_name = 'receiver_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; +SET @dlu_index = (SELECT IF(COUNT(*) = 0, 'CREATE INDEX player_cheat_detections_account ON player_cheat_detections (account_id)', 'DO 0') FROM information_schema.statistics + WHERE table_schema = DATABASE() AND table_name = 'player_cheat_detections' AND column_name = 'account_id' AND seq_in_index = 1); +PREPARE dlu_index_stmt FROM @dlu_index; +EXECUTE dlu_index_stmt; +DEALLOCATE PREPARE dlu_index_stmt; CREATE INDEX leaderboard_game ON leaderboard (game_id, character_id); CREATE INDEX bug_reports_reporter ON bug_reports (reporter_id); CREATE INDEX economy_flags_character ON economy_flags (character_id, id); -CREATE INDEX player_cheat_detections_account ON player_cheat_detections (account_id); CREATE INDEX chat_log_recipient ON chat_log (recipient_id);