/** * This performs a table alter, but does it unbuffered so the script can time out professionally. * * @param string $change * @param int $substep * @param boolean $is_test */ function protected_alter($change, $substep, $is_test = false) { global $db_prefix; $table = db_table(); $db = database(); // Firstly, check whether the current index/column exists. $found = false; if ($change['type'] === 'column') { $columns = $table->db_list_columns('{db_prefix}' . $change['table'], true); foreach ($columns as $column) { // Found it? if ($column['name'] === $change['name']) { $found |= 1; // Do some checks on the data if we have it set. if (isset($change['col_type'])) { $found &= $change['col_type'] === $column['type']; } if (isset($change['null_allowed'])) { $found &= $column['null'] == $change['null_allowed']; } if (isset($change['default'])) { $found &= $change['default'] === $column['default']; } } } } elseif ($change['type'] === 'index') { $request = upgrade_query(' SHOW INDEX FROM ' . $db_prefix . $change['table']); if ($request !== false) { $cur_index = array(); while ($row = $db->fetch_assoc($request)) { if ($row['Key_name'] === $change['name']) { $cur_index[(int) $row['Seq_in_index']] = $row['Column_name']; } } ksort($cur_index, SORT_NUMERIC); $found = array_values($cur_index) === $change['target_columns']; $db->free_result($request); } } // If we're trying to add and it's added, we're done. if ($found && in_array($change['method'], array('add', 'change'))) { return true; } elseif (!$found && in_array($change['method'], array('remove', 'change_remove'))) { return true; } elseif ($is_test) { return false; } // Not found it yet? Bummer! How about we see if we're currently doing it? $running = false; $found = false; while (1 == 1) { $request = upgrade_query(' SHOW FULL PROCESSLIST'); while ($row = $db->fetch_assoc($request)) { if (strpos($row['Info'], 'ALTER TABLE ' . $db_prefix . $change['table']) !== false && strpos($row['Info'], $change['text']) !== false) { $found = true; } } // Can't find it? Then we need to run it fools! if (!$found && !$running) { $db->free_result($request); $success = upgrade_query(' ALTER TABLE ' . $db_prefix . $change['table'] . ' ' . $change['text'], true) !== false; if (!$success) { return false; } // Return $running = true; } elseif (!$found) { $db->free_result($request); return true; } // Pause execution for a sec or three. sleep(3); // Can never be too well protected. nextSubstep($substep); } // Protect it. nextSubstep($substep); }
function textfield_alter($change, $substep) { global $db_prefix; // Versions of MySQL < 4.1 wouldn't benefit from character set detection. if (version_compare('4.1.0', preg_replace('~\\-.+?$~', '', min(mysql_get_server_info(), mysql_get_client_info()))) > 0) { $column_fix = true; $null_fix = !$change['null_allowed']; } else { $request = upgrade_query("\n\t\t\tSHOW FULL COLUMNS \n\t\t\tFROM {$db_prefix}{$change['table']}\n\t\t\tLIKE '{$change['column']}'"); if (mysql_num_rows($request) === 0) { die('Unable to find column ' . $change['column'] . ' inside table ' . $db_prefix . $change['table']); } $table_row = mysql_fetch_assoc($request); mysql_free_result($request); // If something of the current column definition is different, fix it. $column_fix = $table_row['Type'] !== $change['type'] || (strtolower($table_row['Null']) === 'yes') !== $change['null_allowed'] || ($table_row['Default'] == NULL) !== !isset($change['default']) || isset($change['default']) && $change['default'] !== $table_row['Default']; // Columns that previously allowed null, need to be converted first. $null_fix = strtolower($table_row['Null']) === 'yes' && !$change['null_allowed']; // Get the character set that goes with the collation of the column. if ($column_fix && !empty($table_row['Collation'])) { $request = upgrade_query("\n\t\t\t\tSHOW COLLATION\n\t\t\t\tLIKE '{$table_row['Collation']}'"); // No results? Just forget it all together. if (mysql_num_rows($request) === 0) { unset($table_row['Collation']); } else { $collation_info = mysql_fetch_assoc($request); } mysql_free_result($request); } } if ($column_fix) { // Make sure there are no NULL's left. if ($null_fix) { upgrade_query("\n\t\t\t\tUPDATE {$db_prefix}{$change['table']}\n\t\t\t\tSET {$change['column']} = '" . (isset($change['default']) ? addslashes($change['default']) : '') . "'\n\t\t\t\tWHERE {$change['column']} IS NULL"); } // Do the actual alteration. upgrade_query("\n\t\t\tALTER TABLE {$db_prefix}{$change['table']}\n\t\t\tCHANGE COLUMN {$change['column']} {$change['column']} {$change['type']}" . (isset($collation_info['Charset']) ? " CHARACTER SET {$collation_info['Charset']} COLLATE {$collation_info['Collation']}" : '') . ($change['null_allowed'] ? '' : ' NOT NULL') . (isset($change['default']) ? " default '" . addslashes($change['default']) . "'" : '')); } nextSubstep($substep); }