function content_alter_db_field in Content Construction Kit (CCK) 5
Perform adds, alters, and drops as needed to synchronize the database with new field definitions.
13 calls to content_alter_db_field()
- content_field_instance_delete in ./
content_crud.inc - Delete an existing field instance.
- content_update_10 in ./
content.install - Fix corrupted db due to a bug in 1.3 release (http://drupal.org/node/115332)
- content_update_1004 in ./
content.install - Fix corrupted db due to a bug in 1.3 release (http://drupal.org/node/115332)
- content_update_5 in ./
content.install - Move data from per-field storage to per-content-type storage where possible.
- nodereference_update_3 in ./
nodereference.install - Data is now stored in per-field tables.
File
- ./
content_admin.inc, line 1081 - Administrative interface for content type creation.
Code
function content_alter_db_field($previous_field, $previous_columns, $new_field, $new_columns) {
// When adding and removing columns, we need to know what content type has an instance of the field.
if (count($previous_columns)) {
if (!isset($previous_field['type_name'])) {
$previous_field['type_name'] = db_result(db_query("SELECT type_name FROM {node_field_instance} WHERE field_name = '%s'", $previous_field['field_name']));
}
$previous_db_info = content_database_info($previous_field);
}
if (count($new_columns)) {
$new_field['type_name'] = db_result(db_query("SELECT type_name FROM {node_field_instance} WHERE field_name = '%s'", $new_field['field_name']));
$new_db_info = content_database_info($new_field);
}
if (!count($new_columns)) {
if (count($previous_columns)) {
if ($previous_field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) {
db_query('DROP TABLE {' . $previous_db_info['table'] . '}');
}
else {
foreach ($previous_db_info['columns'] as $column => $attributes) {
db_query('ALTER TABLE {' . $previous_db_info['table'] . '} DROP ' . $attributes['column']);
}
}
}
return;
}
if ($new_field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) {
if (!count($previous_columns) || $previous_field['db_storage'] == CONTENT_DB_STORAGE_PER_CONTENT_TYPE) {
// New columns with per-field storage; need to add a table.
if ($new_field['multiple']) {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int unsigned NOT NULL default '0',\n delta int unsigned NOT NULL default '0',\n nid int unsigned NOT NULL default '0',\n PRIMARY KEY (vid,delta),\n KEY nid (nid)\n ) /*!40100 DEFAULT CHARACTER SET utf8 */");
break;
case 'pgsql':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int_unsigned NOT NULL default '0',\n delta int_unsigned NOT NULL default '0',\n nid int_unsigned NOT NULL default '0',\n PRIMARY KEY (vid,delta)\n )");
db_query("CREATE INDEX {" . $new_db_info['table'] . "}_nid_idx ON {" . $new_db_info['table'] . "}(nid)");
break;
}
}
else {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int unsigned NOT NULL default '0',\n nid int unsigned NOT NULL default '0',\n PRIMARY KEY (vid),\n KEY nid (nid)\n ) /*!40100 DEFAULT CHARACTER SET utf8 */");
break;
case 'pgsql':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int_unsigned NOT NULL default '0',\n nid int_unsigned NOT NULL default '0',\n PRIMARY KEY (vid)\n )");
db_query("CREATE INDEX {" . $new_db_info['table'] . "}_nid_idx ON {" . $new_db_info['table'] . "}(nid)");
break;
}
}
}
if (count($previous_columns) && $previous_field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) {
// Already using per-field storage; change multiplicity if needed.
if ($previous_field['multiple'] && !$new_field['multiple']) {
db_query('DELETE FROM {' . $new_db_info['table'] . '} WHERE delta != 0');
db_query('ALTER TABLE {' . $new_db_info['table'] . '} DROP delta');
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query('ALTER TABLE {' . $new_db_info['table'] . '} DROP PRIMARY KEY');
db_query('ALTER TABLE {' . $new_db_info['table'] . '} ADD PRIMARY KEY (vid)');
break;
case 'pgsql':
db_query('ALTER TABLE {' . $new_db_info['table'] . '} DROP CONSTRAINT {' . $new_db_info['table'] . '}_pkey');
db_query('ALTER TABLE {' . $new_db_info['table'] . '} ADD PRIMARY KEY (vid)');
break;
}
}
else {
if (!$previous_field['multiple'] && $new_field['multiple']) {
content_db_add_column($new_db_info['table'], 'delta', 'int', array(
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
));
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query('ALTER TABLE {' . $new_db_info['table'] . '} DROP PRIMARY KEY');
db_query('ALTER TABLE {' . $new_db_info['table'] . '} ADD PRIMARY KEY (vid,delta)');
break;
case 'pgsql':
db_query('ALTER TABLE {' . $new_db_info['table'] . '} DROP CONSTRAINT {' . $new_db_info['table'] . '}_pkey');
db_query('ALTER TABLE {' . $new_db_info['table'] . '} ADD PRIMARY KEY (vid,delta)');
break;
}
}
}
}
}
// Add new columns and change modified columns.
foreach ($new_columns as $column => $attributes) {
$column_name = $new_field['field_name'] . '_' . $column;
if (!isset($previous_columns[$column]) || $previous_field['db_storage'] != $new_field['db_storage']) {
if (!db_table_exists($new_db_info['table'])) {
if ($new_field['db_storage'] == CONTENT_DB_STORAGE_PER_CONTENT_TYPE) {
if ($new_field['multiple']) {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int unsigned NOT NULL default '0',\n delta int unsigned NOT NULL default '0',\n nid int unsigned NOT NULL default '0',\n PRIMARY KEY (vid,delta),\n KEY nid (nid)\n ) /*!40100 DEFAULT CHARACTER SET utf8 */");
break;
case 'pgsql':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int_unsigned NOT NULL default '0',\n delta int_unsigned NOT NULL default '0',\n nid int_unsigned NOT NULL default '0',\n PRIMARY KEY (vid,delta)\n )");
db_query("CREATE INDEX {" . $new_db_info['table'] . "}_nid_idx ON {" . $new_db_info['table'] . "}(nid)");
break;
}
}
else {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int unsigned NOT NULL default '0',\n nid int unsigned NOT NULL default '0',\n PRIMARY KEY (vid),\n KEY nid (nid)\n ) /*!40100 DEFAULT CHARACTER SET utf8 */");
break;
case 'pgsql':
db_query("CREATE TABLE {" . $new_db_info['table'] . "} (\n vid int_unsigned NOT NULL default '0',\n nid int_unsigned NOT NULL default '0',\n PRIMARY KEY (vid)\n )");
db_query("CREATE INDEX {" . $new_db_info['table'] . "}_nid_idx ON {" . $new_db_info['table'] . "}(nid)");
break;
}
}
// end: if ($new_field['multiple'])
}
// end: if ($new_field['db_storage'] == CONTENT_DB_STORAGE_PER_CONTENT_TYPE)
}
content_db_add_column($new_db_info['table'], $column_name, $attributes['type'], $attributes);
}
else {
if ($attributes != $previous_columns[$column]) {
content_db_change_column($new_db_info['table'], $column_name, $column_name, $attributes['type'], $attributes);
}
}
}
if (count($previous_columns) && count($new_columns)) {
// Remove obsolete columns.
foreach ($previous_columns as $column => $attributes) {
$column_name = $previous_field['field_name'] . '_' . $column;
if (!isset($new_columns[$column])) {
db_query('ALTER TABLE {' . $new_db_info['table'] . '} DROP ' . $column_name);
}
}
// Migrate data from one storage type to another
// We check if the previous table still exists (avoid problems during upgrades from older db schemes)
if (db_table_exists($previous_db_info['table'])) {
// Migrate data from per-content-type storage.
if ($previous_field['db_storage'] == CONTENT_DB_STORAGE_PER_CONTENT_TYPE && $new_field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) {
$columns = array();
foreach ($previous_db_info['columns'] as $column => $attributes) {
$columns[] = $attributes['column'];
}
if ($new_field['multiple']) {
db_query('INSERT INTO {' . $new_db_info['table'] . '} (vid, nid, delta, ' . implode(', ', $columns) . ') SELECT vid, nid, 0, ' . implode(', ', $columns) . ' FROM {' . $previous_db_info['table'] . '}');
}
else {
db_query('INSERT INTO {' . $new_db_info['table'] . '} (vid, nid, ' . implode(', ', $columns) . ') SELECT vid, nid, ' . implode(', ', $columns) . ' FROM {' . $previous_db_info['table'] . '}');
}
foreach ($columns as $column_name) {
db_query('ALTER TABLE {' . $previous_db_info['table'] . '} DROP ' . $column_name);
}
}
// Migrate data from per-field storage.
if ($previous_field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD && $new_field['db_storage'] == CONTENT_DB_STORAGE_PER_CONTENT_TYPE) {
$column_names = array();
$column_placeholders_default = array();
$column_assignments_default = array();
foreach ($new_db_info['columns'] as $column => $attributes) {
$column_names[] = $attributes['column'];
if (in_array($attributes['type'], array(
'int',
'mediumint',
'tinyint',
'bigint',
'float',
))) {
$column_placeholders_default[] = '%d';
$column_assignments_default[] = $attributes['column'] . ' = %d';
}
else {
$column_placeholders_default[] = "'%s'";
$column_assignments_default[] = $attributes['column'] . " = '%s'";
}
}
if ($previous_field['multiple']) {
$result = db_query("SELECT " . implode(', ', $column_names) . ", c.vid, c.nid FROM {" . $previous_db_info['table'] . "} c JOIN {node} n ON c.nid = n.nid WHERE delta = 0 AND n.type = '%s'", $new_field['type_name']);
}
else {
$result = db_query("SELECT " . implode(', ', $column_names) . ", c.vid, c.nid FROM {" . $previous_db_info['table'] . "} c JOIN {node} n ON c.nid = n.nid WHERE n.type = '%s'", $new_field['type_name']);
}
while ($data = db_fetch_array($result)) {
$column_assignments = $column_assignments_default;
$column_placeholders = $column_placeholders_default;
// search for NULL values and replace assignments and placeholders accordingly
foreach ($data as $key => $value) {
if (is_null($value)) {
$pos = array_search($key, $column_names);
$column_assignments[$pos] = $key . "= %s";
$column_placeholders[$pos] = "%s";
$data[$key] = 'NULL';
}
}
if (db_result(db_query('SELECT COUNT(*) FROM {' . $new_db_info['table'] . '} WHERE vid = %d AND nid = %d', $data['vid'], $data['nid']))) {
db_query('UPDATE {' . $new_db_info['table'] . '} SET ' . implode(', ', $column_assignments) . ' WHERE vid = %d AND nid = %d', $data);
}
else {
db_query('INSERT INTO {' . $new_db_info['table'] . '} (' . implode(', ', $column_names) . ', vid, nid) VALUES (' . implode(', ', $column_placeholders) . ', %d, %d)', $data);
}
}
db_query('DROP TABLE {' . $previous_db_info['table'] . '}');
}
}
}
}