예제 #1
0
 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>');
     }
 }
예제 #2
0
 /**
  * Asserts that a given field can be added and removed from a table.
  *
  * The addition test covers both defining a field of a given specification
  * when initially creating at table and extending an existing table.
  *
  * @param $field_spec
  *   The schema specification of the field.
  */
 protected function assertFieldAdditionRemoval($field_spec)
 {
     // Try creating the field on a new table.
     $table_name = 'test_table_' . $this->counter++;
     $table_spec = array('fields' => array('serial_column' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE), 'test_field' => $field_spec), 'primary key' => array('serial_column'));
     db_create_table($table_name, $table_spec);
     $this->pass(format_string('Table %table created.', array('%table' => $table_name)));
     // Check the characteristics of the field.
     $this->assertFieldCharacteristics($table_name, 'test_field', $field_spec);
     // Clean-up.
     db_drop_table($table_name);
     // Try adding a field to an existing table.
     $table_name = 'test_table_' . $this->counter++;
     $table_spec = array('fields' => array('serial_column' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE)), 'primary key' => array('serial_column'));
     db_create_table($table_name, $table_spec);
     $this->pass(format_string('Table %table created.', array('%table' => $table_name)));
     // Insert some rows to the table to test the handling of initial values.
     for ($i = 0; $i < 3; $i++) {
         db_insert($table_name)->useDefaults(array('serial_column'))->execute();
     }
     db_add_field($table_name, 'test_field', $field_spec);
     $this->pass(format_string('Column %column created.', array('%column' => 'test_field')));
     // Check the characteristics of the field.
     $this->assertFieldCharacteristics($table_name, 'test_field', $field_spec);
     // Clean-up.
     db_drop_field($table_name, 'test_field');
     // Add back the field and then try to delete a field which is also a primary
     // key.
     db_add_field($table_name, 'test_field', $field_spec);
     db_drop_field($table_name, 'serial_column');
     db_drop_table($table_name);
 }
예제 #3
0
 /**
  * Asserts that a newly added field has the correct characteristics.
  */
 protected function assertFieldCharacteristics($table_name, $field_name, $field_spec)
 {
     // Check that the initial value has been registered.
     if (isset($field_spec['initial'])) {
         // There should be no row with a value different then $field_spec['initial'].
         $count = db_select($table_name)->fields($table_name, array('serial_column'))->condition($field_name, $field_spec['initial'], '<>')->countQuery()->execute()->fetchField();
         $this->assertEqual($count, 0, 'Initial values filled out.');
     }
     // Check that the default value has been registered.
     if (isset($field_spec['default'])) {
         // Try inserting a row, and check the resulting value of the new column.
         $id = db_insert($table_name)->useDefaults(array('serial_column'))->execute();
         $field_value = db_select($table_name)->fields($table_name, array($field_name))->condition('serial_column', $id)->execute()->fetchField();
         $this->assertEqual($field_value, $field_spec['default'], 'Default value registered.');
     }
     db_drop_field($table_name, $field_name);
 }