Files
itflow/admin/database_updates/3.2.8.php
johnnyq 2c9bd0a7f2 Let the database update get past 3.2.8 on installs whose tables have different collations, and on ones already stuck there: 3.2.8 matched license names against template names across software and software_templates, the second being one of the tables 2.1.6 to 2.4.1 created without a COLLATE, so where the server default is not utf8mb4_general_ci, MariaDB 11.5 and later, the comparison failed with Illegal mix of collations after the two ALTERs above it had gone in, and every run after that stopped at the first of them with Duplicate column name software_template_id, short of 3.6.5 which puts those tables right; admin/database_updates.php now runs databaseCollationRepair before each update it applies as well as after the last, so no update meets two collations whatever version it starts from, loads functions/database_collation.php itself when the process started on code from before it, and does not try a table again in the same run once it has failed, databaseCollationRepair taking a list of tables to skip; 3.2.8.php is changed in what it can get through and not in what it makes, each ALTER checked first so it can run again from wherever it stopped, the comparison naming its collation and the UPDATE leaving licenses that already have a template; every update from 2.0.7 to 3.6.5 was run on MariaDB with those 22 tables in utf8mb4_uca1400_ai_ci and 3.2.8 was the only one that failed, then the whole history run through the new runner with the tables put wrong before every update, on an install left as the forum report had it and from a process started on older code; CONTRIBUTING.md records the exception to never editing a shipped migration and the 26.11.7 changelog section has the fix
2026-11-11 21:13:02 -05:00

49 lines
3.0 KiB
PHP

<?php
/*
* ITFlow - Database update to version 3.2.8 (from 3.2.7)
* Included by admin/database_updates.php - do not access directly
*/
defined('FROM_DB_UPDATER') || die("Direct file access is not allowed");
// Changed after it shipped, in what it can get through and not in what it does. As
// first written, the last statement compared a license's name with a template's, and on
// an install where software_templates had another collation than software (MariaDB 11.5
// and later gave it one - see 3.6.5) that stopped with "Illegal mix of collations". By
// then the columns above it were in, so every run after stopped at the first line with
// "Duplicate column name 'software_template_id'" and the install could go no further.
// Each step is now checked first, so the update can run again from wherever it was
// left, and the comparison names its collation. An install that ran it through has
// exactly what this makes.
// The license template a license was made from - 0 for none
$itflow_column = mysqli_query($mysqli, "SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'software' AND COLUMN_NAME = 'software_template_id' LIMIT 1");
if (!$itflow_column || mysqli_num_rows($itflow_column) === 0) {
mysqli_query($mysqli, "ALTER TABLE `software`
ADD `software_template_id` int(11) NOT NULL DEFAULT 0 AFTER `software_client_id`,
ADD KEY `software_template_id` (`software_template_id`)");
}
// Who made a license template and who last changed it
$itflow_column = mysqli_query($mysqli, "SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'software_templates' AND COLUMN_NAME = 'software_template_created_by' LIMIT 1");
if (!$itflow_column || mysqli_num_rows($itflow_column) === 0) {
mysqli_query($mysqli, "ALTER TABLE `software_templates`
ADD `software_template_created_by` int(11) NOT NULL DEFAULT 0 AFTER `software_template_archived_at`,
ADD `software_template_updated_by` int(11) NOT NULL DEFAULT 0 AFTER `software_template_created_by`");
}
// A license called exactly what one template - and only one - is called was made from it,
// as the New License form filled the name in from the template. It isn't counted as a change.
// Only licenses not yet given one, so a second run leaves alone what the first one set.
mysqli_query($mysqli, "UPDATE `software` JOIN (
SELECT MIN(`software_template_id`) AS `template_id`, LOWER(TRIM(`software_template_name`)) AS `template_name`
FROM `software_templates` GROUP BY LOWER(TRIM(`software_template_name`)) HAVING COUNT(*) = 1
) AS `templates` ON CONVERT(LOWER(TRIM(`software`.`software_name`)) USING utf8mb4) COLLATE utf8mb4_general_ci = `templates`.`template_name`
SET `software`.`software_template_id` = `templates`.`template_id`, `software`.`software_updated_at` = `software`.`software_updated_at`
WHERE `software`.`software_template_id` = 0");
unset($itflow_column);