Esempio n. 1
0
/**
 * 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);
}
Esempio n. 2
0
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);
}