Created
October 14, 2010 22:49
-
-
Save lxbarth/627239 to your computer and use it in GitHub Desktop.
Updated patch for http://drupal.org/node/937442, requires patch from http://drupal.org/node/937554
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
? .git | |
? .gitignore | |
? 937442-25_maintain_field_schema.patch | |
? 937442-2_maintain_field_schema.patch | |
? 937554-1_cleanup_field_data.patch | |
? sites/default/files | |
? sites/default/settings.php | |
Index: modules/field/field.crud.inc | |
=================================================================== | |
RCS file: /cvs/drupal/drupal/modules/field/field.crud.inc,v | |
retrieving revision 1.71 | |
diff -u -p -r1.71 field.crud.inc | |
--- modules/field/field.crud.inc 29 Sep 2010 01:37:02 -0000 1.71 | |
+++ modules/field/field.crud.inc 14 Oct 2010 22:47:52 -0000 | |
@@ -289,8 +289,8 @@ function field_create_field($field) { | |
$field += array( | |
'entity_types' => array(), | |
'cardinality' => 1, | |
- 'translatable' => FALSE, | |
- 'locked' => FALSE, | |
+ 'translatable' => 0, | |
+ 'locked' => 0, | |
'settings' => array(), | |
'storage' => array(), | |
'deleted' => 0, | |
Index: modules/field/field.install | |
=================================================================== | |
RCS file: /cvs/drupal/drupal/modules/field/field.install,v | |
retrieving revision 1.22 | |
diff -u -p -r1.22 field.install | |
--- modules/field/field.install 29 Sep 2010 19:46:40 -0000 1.22 | |
+++ modules/field/field.install 14 Oct 2010 22:47:52 -0000 | |
@@ -334,6 +334,76 @@ function _update_7000_field_read_fields( | |
} | |
/** | |
+ * Utility function: Update a field. | |
+ * | |
+ * @param $prior_field | |
+ * A field structure containing the previous field schema definition. | |
+ * @param $field | |
+ * A field structure containing the new field schema definition. | |
+ * | |
+ * @return | |
+ * Throws a FieldException if the update cannot be performed. | |
+ * | |
+ * @see field_update_field() | |
+ */ | |
+function _update_7000_field_update_field($prior_field, $field) { | |
+ // Some updates are always disallowed. | |
+ if ($field['storage']['type'] != $prior_field['storage']['type']) { | |
+ throw new FieldException("Cannot change an existing field's storage type."); | |
+ } | |
+ | |
+ $has_data = field_has_data($field); | |
+ | |
+ // Tell the storage engine to update the field. Do this before | |
+ // saving the new definition since it still might fail. | |
+ $storage_type = field_info_storage_types($field['storage']['type']); | |
+ module_invoke($storage_type['module'], 'field_storage_update_field', $field, $prior_field, $has_data); | |
+ | |
+ // Save the new field definition. | |
+ // The serialized 'data' column contains everything from $field that does not | |
+ // have its own column and is not automatically populated when the field is | |
+ // read. | |
+ $keys = array( | |
+ // Ignore {field_config} keys. | |
+ 'id', 'field_name', 'type', 'module', 'active', 'locked', 'cardinality', | |
+ 'translatable', 'deleted', | |
+ // Ignore all possible storage engine keys. | |
+ 'storage', 'storage_type', 'storage_module', 'storage_active', | |
+ // Ignore the data key itself. | |
+ 'data', | |
+ // Ignore field schema keys. | |
+ // @todo Right now, this is the only way to make this function work like it | |
+ // is supposed to work. I.e., without copying field schema information | |
+ // into the serialized 'data' column, subsequent invocations of | |
+ // field_update_field() are failing, since field_read_fields() retrieves | |
+ // the current hook_field_schema(), so there is *nothing* to update. | |
+ //'columns', 'primary key', 'unique keys', 'indexes', 'foreign keys', | |
+ // Ignore field_info_field() properties. | |
+ 'bundles', | |
+ ); | |
+ $data = array_diff_key($field, array_flip($keys)); | |
+ $field['data'] = $data; | |
+ | |
+ // Store the field and create the id. | |
+ db_update('field_config') | |
+ ->fields(array( | |
+ 'field_name' => $field['field_name'], | |
+ 'type' => $field['type'], | |
+ 'module' => $field['module'], | |
+ 'active' => $field['active'], | |
+ 'storage_type' => $field['storage']['type'], | |
+ 'storage_module' => $field['storage']['module'], | |
+ 'storage_active' => $field['storage']['active'], | |
+ 'locked' => $field['locked'], | |
+ 'cardinality' => $field['cardinality'], | |
+ 'translatable' => $field['translatable'], | |
+ 'data' => serialize($field['data']), | |
+ )) | |
+ ->condition('id', $field['id']) | |
+ ->execute(); | |
+} | |
+ | |
+/** | |
* Utility function: write a field instance directly to the database. | |
* | |
* This function can be used for databases whose schema is at field module | |
Index: modules/field/modules/field_sql_storage/field_sql_storage.module | |
=================================================================== | |
RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v | |
retrieving revision 1.56 | |
diff -u -p -r1.56 field_sql_storage.module | |
--- modules/field/modules/field_sql_storage/field_sql_storage.module 6 Oct 2010 13:57:47 -0000 1.56 | |
+++ modules/field/modules/field_sql_storage/field_sql_storage.module 14 Oct 2010 22:47:52 -0000 | |
@@ -267,29 +267,61 @@ function field_sql_storage_field_storage | |
} | |
} | |
else { | |
- // There is data, so there are no column changes. Drop all the | |
- // prior indexes and create all the new ones, except for all the | |
- // priors that exist unchanged. | |
- $table = _field_sql_storage_tablename($prior_field); | |
- $revision_table = _field_sql_storage_revision_tablename($prior_field); | |
- foreach ($prior_field['indexes'] as $name => $columns) { | |
- if (!isset($field['indexes'][$name]) || $columns != $field['indexes'][$name]) { | |
- $real_name = _field_sql_storage_indexname($field['field_name'], $name); | |
- db_drop_index($table, $real_name); | |
- db_drop_index($revision_table, $real_name); | |
- } | |
- } | |
+ // There is data. | |
$table = _field_sql_storage_tablename($field); | |
$revision_table = _field_sql_storage_revision_tablename($field); | |
- foreach ($field['indexes'] as $name => $columns) { | |
- if (!isset($prior_field['indexes'][$name]) || $columns != $prior_field['indexes'][$name]) { | |
- $real_name = _field_sql_storage_indexname($field['field_name'], $name); | |
- $real_columns = array(); | |
- foreach ($columns as $column_name) { | |
- $real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name); | |
+ | |
+ // Drop prior indexes, except for all unchanged. | |
+ if (isset($prior_field['indexes'])) { | |
+ foreach ($prior_field['indexes'] as $name => $columns) { | |
+ if (!isset($field['indexes'][$name]) || $columns != $field['indexes'][$name]) { | |
+ $real_name = _field_sql_storage_indexname($field['field_name'], $name); | |
+ db_drop_index($table, $real_name); | |
+ db_drop_index($revision_table, $real_name); | |
+ } | |
+ } | |
+ } | |
+ | |
+ // Perform field schema column updates, if any. | |
+ if (isset($prior_field['columns'])) { | |
+ foreach ($prior_field['columns'] as $name => $spec) { | |
+ // Remove a field column. | |
+ if (!isset($field['columns'][$name])) { | |
+ $real_name = _field_sql_storage_columnname($field['field_name'], $name); | |
+ db_drop_field($table, $real_name); | |
+ db_drop_field($revision_table, $real_name); | |
+ } | |
+ } | |
+ } | |
+ if (isset($field['columns'])) { | |
+ foreach ($field['columns'] as $name => $spec) { | |
+ // Add a field column. | |
+ if (!isset($prior_field['columns'][$name])) { | |
+ $real_name = _field_sql_storage_columnname($field['field_name'], $name); | |
+ db_add_field($table, $real_name, $spec); | |
+ db_add_field($revision_table, $real_name, $spec); | |
+ } | |
+ // Change a field column. | |
+ if ($prior_field['columns'][$name] != $spec) { | |
+ $real_name = _field_sql_storage_columnname($field['field_name'], $name); | |
+ db_change_field($table, $real_name, $real_name, $spec); | |
+ db_change_field($revision_table, $real_name, $real_name, $spec); | |
+ } | |
+ } | |
+ } | |
+ | |
+ // Create new indexes, except for all unchanged. | |
+ if (isset($field['indexes'])) { | |
+ foreach ($field['indexes'] as $name => $columns) { | |
+ if (!isset($prior_field['indexes'][$name]) || $columns != $prior_field['indexes'][$name]) { | |
+ $real_name = _field_sql_storage_indexname($field['field_name'], $name); | |
+ $real_columns = array(); | |
+ foreach ($columns as $column_name) { | |
+ $real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name); | |
+ } | |
+ db_add_index($table, $real_name, $real_columns); | |
+ db_add_index($revision_table, $real_name, $real_columns); | |
} | |
- db_add_index($table, $real_name, $real_columns); | |
- db_add_index($revision_table, $real_name, $real_columns); | |
} | |
} | |
} | |
Index: modules/field/modules/field_sql_storage/field_sql_storage.test | |
=================================================================== | |
RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.test,v | |
retrieving revision 1.22 | |
diff -u -p -r1.22 field_sql_storage.test | |
--- modules/field/modules/field_sql_storage/field_sql_storage.test 29 Sep 2010 01:37:02 -0000 1.22 | |
+++ modules/field/modules/field_sql_storage/field_sql_storage.test 14 Oct 2010 22:47:52 -0000 | |
@@ -13,6 +13,8 @@ | |
* Tests field storage. | |
*/ | |
class FieldSqlStorageTestCase extends DrupalWebTestCase { | |
+ protected $profile = 'testing'; | |
+ | |
public static function getInfo() { | |
return array( | |
'name' => 'Field SQL storage tests', | |
@@ -301,16 +303,34 @@ class FieldSqlStorageTestCase extends Dr | |
*/ | |
function testUpdateFieldSchemaWithData() { | |
// Create a decimal 5.2 field and add some data. | |
- $field = array('field_name' => 'decimal52', 'type' => 'number_decimal', 'settings' => array('precision' => 5, 'scale' => 2)); | |
+ $field_name = 'decimal52'; | |
+ $field = array( | |
+ 'field_name' => $field_name, | |
+ 'type' => 'number_decimal', | |
+ 'settings' => array( | |
+ 'precision' => 5, | |
+ 'scale' => 2, | |
+ )); | |
$field = field_create_field($field); | |
$instance = array('field_name' => 'decimal52', 'entity_type' => 'test_entity', 'bundle' => 'test_bundle'); | |
$instance = field_create_instance($instance); | |
$entity = field_test_create_stub_entity(0, 0, $instance['bundle']); | |
- $entity->decimal52[LANGUAGE_NONE][0]['value'] = '1.235'; | |
- field_attach_insert('test_entity', $entity); | |
+ $entity->decimal52[LANGUAGE_NONE][0]['value'] = '1.12345'; | |
+ field_test_entity_save($entity); | |
- // Attempt to update the field in a way that would work without data. | |
- $field['settings']['scale'] = 3; | |
+ $entity = field_test_entity_test_load($entity->ftid); | |
+ $this->assertEqual($entity->{$field_name}[LANGUAGE_NONE][0]['value'], '1.12'); | |
+ | |
+ // Modify the field schema. | |
+ $prior_field = $field; | |
+ $field['settings']['precision'] = 2; | |
+ $field['settings']['scale'] = 1; | |
+ | |
+ // Attempt to update the field: | |
+ // - The CRUD API function field_update_field() must fail as field instances | |
+ // contain data. | |
+ // - The schema maintenance helper _update_7000_field_update_field() must | |
+ // not fail for a simple schema modification like the one at hand. | |
try { | |
field_update_field($field); | |
$this->fail(t('Cannot update field schema with data.')); | |
@@ -318,6 +338,11 @@ class FieldSqlStorageTestCase extends Dr | |
catch (FieldException $e) { | |
$this->pass(t('Cannot update field schema with data.')); | |
} | |
+ | |
+ _update_7000_field_update_field($prior_field, $field); | |
+ field_cache_clear(); | |
+ $entity = field_test_entity_test_load($entity->ftid); | |
+ $this->assertEqual($entity->{$field_name}[LANGUAGE_NONE][0]['value'], '1.1'); | |
} | |
/** |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment