Exemple #1
0
function update_structure($verbose, $action)
{
    global $a, $db;
    $errors = false;
    logger('updating structure', LOGGER_DEBUG);
    // Get the current structure
    $database = array();
    $tables = q("show tables");
    foreach ($tables as $table) {
        $table = current($table);
        $database[$table] = table_structure($table);
    }
    // Get the definition
    $definition = db_definition();
    // Compare it
    foreach ($definition as $name => $structure) {
        $sql3 = "";
        if (!isset($database[$name])) {
            $r = db_create_table($name, $structure["fields"], $verbose, $action);
            if (false === $r) {
                $errors .= t('Errors encountered creating database tables.') . $name . EOL;
            }
        } else {
            // Drop the index if it isn't present in the definition
            foreach ($database[$name]["indexes"] as $indexname => $fieldnames) {
                if (!isset($structure["indexes"][$indexname])) {
                    $sql2 = db_drop_index($indexname);
                    if ($sql3 == "") {
                        $sql3 = "ALTER TABLE `" . $name . "` " . $sql2;
                    } else {
                        $sql3 .= ", " . $sql2;
                    }
                }
            }
            // Compare the field structure field by field
            foreach ($structure["fields"] as $fieldname => $parameters) {
                if (!isset($database[$name]["fields"][$fieldname])) {
                    $sql2 = db_add_table_field($fieldname, $parameters);
                    if ($sql3 == "") {
                        $sql3 = "ALTER TABLE `" . $name . "` " . $sql2;
                    } else {
                        $sql3 .= ", " . $sql2;
                    }
                } else {
                    // Compare the field definition
                    $current_field_definition = implode(",", $database[$name]["fields"][$fieldname]);
                    $new_field_definition = implode(",", $parameters);
                    if ($current_field_definition != $new_field_definition) {
                        $sql2 = db_modify_table_field($fieldname, $parameters);
                        if ($sql3 == "") {
                            $sql3 = "ALTER TABLE `" . $name . "` " . $sql2;
                        } else {
                            $sql3 .= ", " . $sql2;
                        }
                    }
                }
            }
        }
        // Create the index
        foreach ($structure["indexes"] as $indexname => $fieldnames) {
            if (!isset($database[$name]["indexes"][$indexname])) {
                $sql2 = db_create_index($indexname, $fieldnames);
                if ($sql2 != "") {
                    if ($sql3 == "") {
                        $sql3 = "ALTER TABLE `" . $name . "` " . $sql2;
                    } else {
                        $sql3 .= ", " . $sql2;
                    }
                }
            }
        }
        if ($sql3 != "") {
            $sql3 .= ";";
            if ($verbose) {
                echo $sql3 . "\n";
            }
            if ($action) {
                $r = @$db->q($sql3);
                if (false === $r) {
                    $errors .= t('Errors encountered performing database changes.') . $sql3 . EOL;
                }
            }
        }
    }
    return $errors;
}
 public static function changeSchema(array &$field, array $column_renames = array())
 {
     // Update the field schema
     $old_schema = array_intersect_key($field, array('columns' => '', 'indexes' => '', 'foreign keys' => ''));
     module_load_install($field['module']);
     $new_schema = (array) module_invoke($field['module'], 'field_schema', $field);
     $new_schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
     $field['data']['columns'] = $new_schema['columns'];
     $field['data']['indexes'] = $new_schema['indexes'];
     $field['data']['foreign keys'] = $new_schema['foreign keys'];
     $data_table = _field_sql_storage_tablename($field);
     $revision_table = _field_sql_storage_revision_tablename($field);
     // Validate that all the columns described in the existing schema actually exist.
     foreach (array_keys($old_schema['columns']) as $old_column) {
         $old_column_name = _field_sql_storage_columnname($field['field_name'], $old_column);
         if (!db_field_exists($data_table, $old_column_name)) {
             throw new Exception();
         }
         if (!db_field_exists($revision_table, $old_column_name)) {
             throw new Exception();
         }
         // Attempt to re-use any columns that have the same name.
         // This can be skipped by setting $column_renames['column-name'] = FALSE;
         if (!empty($new_schema['columns'][$old_column]) && !isset($column_renames[$old_column])) {
             $column_renames[$old_column] = $old_column;
         }
     }
     // Validate that any columns to be renamed actually exist.
     foreach ($column_renames as $old_column => $new_column) {
         if (!isset($old_schema['columns'][$old_column])) {
             throw new Exception("Cannot rename field {$field['field_name']} column {$old_column} because it does not exist in the old schema.");
         }
         if (!isset($new_schema['columns'][$new_column])) {
             throw new Exception("Cannot rename field {$field['field_name']} column {$old_column} to {$new_column} because it does not exist in the new schema.");
         }
     }
     // Remove all existing indexes.
     foreach ($old_schema['indexes'] as $index => $index_fields) {
         $index_name = _field_sql_storage_indexname($field['field_name'], $index);
         if (db_index_exists($data_table, $index_name)) {
             watchdog('helper', "Dropped index {$data_table}.{$index_name}");
             db_drop_index($data_table, $index_name);
         }
         if (db_index_exists($revision_table, $index_name)) {
             watchdog('helper', "Dropped index {$revision_table}.{$index_name}");
             db_drop_index($revision_table, $index_name);
         }
     }
     // Rename any columns.
     foreach ($column_renames as $old_column => $new_column) {
         $old_column_name = _field_sql_storage_columnname($field['field_name'], $old_column);
         if ($new_column === FALSE) {
             db_drop_field($data_table, $old_column_name);
             watchdog('helper', "Dropped column {$data_table}.{$old_column_name}");
             db_drop_field($revision_table, $old_column_name);
             watchdog('helper', "Dropped column {$revision_table}.{$old_column_name}");
             unset($old_schema['columns'][$old_column]);
         } else {
             $new_column_name = _field_sql_storage_columnname($field['field_name'], $new_column);
             db_change_field($data_table, $old_column_name, $new_column_name, $new_schema['columns'][$new_column]);
             watchdog('helper', "Changed column {$data_table}.{$old_column_name}<br/><pre>" . print_r($new_schema['columns'][$new_column], TRUE) . '</pre>');
             db_change_field($revision_table, $old_column_name, $new_column_name, $new_schema['columns'][$new_column]);
             watchdog('helper', "Changed column {$revision_table}.{$old_column_name}<br/><pre>" . print_r($new_schema['columns'][$new_column], TRUE) . '</pre>');
             // Remove these fields so they aren't removed or added in the code below.
             unset($new_schema['columns'][$new_column]);
             unset($old_schema['columns'][$old_column]);
         }
     }
     // Remove any old columns.
     $old_columns = array_diff_key($old_schema['columns'], $new_schema['columns']);
     foreach (array_keys($old_columns) as $old_column) {
         $old_column_name = _field_sql_storage_columnname($field['field_name'], $old_column);
         db_drop_field($data_table, $old_column_name);
         watchdog('helper', "Dropped column {$data_table}.{$old_column_name}");
         db_drop_field($revision_table, $old_column_name);
         watchdog('helper', "Dropped column {$revision_table}.{$old_column_name}");
     }
     // Add any new columns.
     $new_columns = array_diff_key($new_schema['columns'], $old_schema['columns']);
     foreach (array_keys($new_columns) as $new_column) {
         $new_column_name = _field_sql_storage_columnname($field['field_name'], $new_column);
         db_add_field($data_table, $new_column_name, $new_schema['columns'][$new_column]);
         watchdog('helper', "Added column {$data_table}.{$new_column_name}");
         db_add_field($revision_table, $new_column_name, $new_schema['columns'][$new_column]);
         watchdog('helper', "Added column {$revision_table}.{$new_column_name}");
     }
     // Re-add indexes.
     foreach ($new_schema['indexes'] as $index => $index_fields) {
         foreach ($index_fields as &$index_field) {
             if (is_array($index_field)) {
                 $index_field[0] = _field_sql_storage_columnname($field['field_name'], $index_field[0]);
             } else {
                 $index_field = _field_sql_storage_columnname($field['field_name'], $index_field);
             }
         }
         $index_name = _field_sql_storage_indexname($field['field_name'], $index);
         db_add_index($data_table, $index_name, $index_fields);
         watchdog('helper', "Added index {$data_table}.{$index_name}<br/><pre>" . print_r($index_fields, TRUE) . '</pre>');
         db_add_index($revision_table, $index_name, $index_fields);
         watchdog('helper', "Added index {$revision_table}.{$index_name}<br/><pre>" . print_r($index_fields, TRUE) . '</pre>');
     }
 }