diff options
Diffstat (limited to 'modules/field')
-rw-r--r-- | modules/field/modules/field_sql_storage/field_sql_storage.module | 36 | ||||
-rw-r--r-- | modules/field/modules/field_sql_storage/field_sql_storage.test | 25 |
2 files changed, 55 insertions, 6 deletions
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module index 695561624..2ed783507 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.module +++ b/modules/field/modules/field_sql_storage/field_sql_storage.module @@ -236,13 +236,37 @@ function field_sql_storage_field_update_forbid($field, $prior_field, $has_data) function field_sql_storage_field_storage_update_field($field, $prior_field, $has_data) { if (! $has_data) { // There is no data. Re-create the tables completely. - $prior_schema = _field_sql_storage_schema($prior_field); - foreach ($prior_schema as $name => $table) { - db_drop_table($name, $table); + + if (Database::getConnection()->supportsTransactionalDDL()) { + // If the database supports transactional DDL, we can go ahead and rely + // on it. If not, we will have to rollback manually if something fails. + $transaction = db_transaction(); + } + + try { + $prior_schema = _field_sql_storage_schema($prior_field); + foreach ($prior_schema as $name => $table) { + db_drop_table($name, $table); + } + $schema = _field_sql_storage_schema($field); + foreach ($schema as $name => $table) { + db_create_table($name, $table); + } } - $schema = _field_sql_storage_schema($field); - foreach ($schema as $name => $table) { - db_create_table($name, $table); + catch (Exception $e) { + if (Database::getConnection()->supportsTransactionalDDL()) { + $transaction->rollback(); + } + else { + // Recreate tables. + $prior_schema = _field_sql_storage_schema($prior_field); + foreach ($prior_schema as $name => $table) { + if (!db_table_exists($name)) { + db_create_table($name, $table); + } + } + } + throw $e; } } else { diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.test b/modules/field/modules/field_sql_storage/field_sql_storage.test index f94344fa2..773de3d07 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.test +++ b/modules/field/modules/field_sql_storage/field_sql_storage.test @@ -306,6 +306,31 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase { } /** + * Test that failure to create fields is handled gracefully. + */ + function testFieldUpdateFailure() { + // Create a text field. + $field = array('field_name' => 'test_text', 'type' => 'text', 'settings' => array('max_length' => 255)); + $field = field_create_field($field); + + // Attempt to update the field in a way that would break the storage. + $prior_field = $field; + $field['settings']['max_length'] = -1; + try { + field_update_field($field); + $this->fail(t('Update succeeded.')); + } + catch (Exception $e) { + $this->pass(t('Update properly failed.')); + } + + // Ensure that the field tables are still there. + foreach (_field_sql_storage_schema($prior_field) as $table_name => $table_info) { + $this->assertTrue(db_table_exists($table_name), t('Table %table exists.', array('%table' => $table_name))); + } + } + + /** * Test adding and removing indexes while data is present. */ function testFieldUpdateIndexesWithData() { |