Skip to content

Instantly share code, notes, and snippets.

@bangpound
Created August 17, 2010 03:54
Show Gist options
  • Save bangpound/528371 to your computer and use it in GitHub Desktop.
Save bangpound/528371 to your computer and use it in GitHub Desktop.
/**
* Migrate {taxonomy_term_node} table to field storage.
*/
function taxonomy_update_7005(&$sandbox) {
// This is a multi-pass update. On the first call we need to initialize some
// variables.
if (!isset($sandbox['total'])) {
$sandbox['last'] = 0;
$sandbox['count'] = 0;
$query = db_select('taxonomy_term_node', 't');
$sandbox['total'] = $query->countQuery()->execute()->fetchField();
// Use an inline version of Drupal 6 taxonomy_get_vocabularies() here since
// we can no longer rely on $vocabulary->nodes from the API function.
$result = db_query('SELECT v.vid, v.machine_name, n.type FROM {taxonomy_vocabulary} v INNER JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid');
$vocabularies = array();
foreach ($result as $record) {
// If no node types are associated with a vocabulary, the LEFT JOIN will
// return a NULL value for type.
if (isset($record->type)) {
$vocabularies[$record->vid][$record->type] = 'taxonomy_'. $record->machine_name;
}
}
if (!empty($vocabularies)) {
$sandbox['vocabularies'] = $vocabularies;
}
}
else {
$field_info = field_info_fields();
$etid = _field_sql_storage_etid('node');
// We do each pass in batches of 1000.
$batch = 1000;
// Query selects all revisions at once and processes them in revision and
// term weight order.
$query = 'SELECT td.vid AS vocab_id, td.tid, tn.nid, tn.vid, n.type, n2.created, n2.sticky, n2.nid AS is_current FROM {taxonomy_term_data} td LEFT JOIN {taxonomy_term_node} tn ON td.tid = tn.tid LEFT JOIN {node} n ON tn.nid = n.nid LEFT JOIN {node} n2 ON tn.vid = n2.vid ORDER BY tn.vid, td.weight ASC';
$result = db_query_range($query, $sandbox['last'], $batch);
if (isset($sandbox['cursor'])) {
$values = $sandbox['cursor']['values'];
$deltas = $sandbox['cursor']['deltas'];
}
else {
$deltas = array();
}
foreach ($result as $record) {
$sandbox['count'] += 1;
// Use the valid field for this vocabulary and node type or use the
// overflow vocabulary if there is no valid field.
$field_name = isset($sandbox['vocabularies'][$record->vocab_id][$record->type]) ? $sandbox['vocabularies'][$record->vocab_id][$record->type] : 'taxonomyextra_upgrade';
$field = $field_info[$field_name];
// Start deltas from 0, and increment by one for each term attached to a
// node.
if (!isset($deltas[$field_name])) {
$deltas[$field_name] = 0;
}
if (isset($values)) {
// If the last inserted revision_id is the same as the current record,
// use the previous deltas to calculate the next delta.
if ($record->vid == $values[2]) {
// see field_default_validate().
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ($deltas[$field_name] + 1) >= $field['cardinality']) {
// For excess values for a single value field, switch over to the
// overflow field.
$field_name = 'taxonomyextra_upgrade';
$field = $field_info[$field_name];
}
}
else {
// When the record is a new revision, empty the deltas array.
$deltas = array($field_name => 0);
}
}
// Table and column found in the field's storage details. During upgrades,
// it's always SQL.
$table = key($field['storage']['details']['sql'][FIELD_LOAD_REVISION]);
$value_column = $field['storage']['details']['sql'][FIELD_LOAD_REVISION][$table]['tid'];
// Column names and values in field storage are the same for current and
// revision.
$columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'language', 'delta', $value_column);
$values = array($etid, $record->nid, $record->vid, $record->type, LANGUAGE_NONE, $deltas[$field_name]++, $record->tid);
// Insert rows into the revision table.
db_insert($table)->fields($columns)->values($values)->execute();
// is_current column is a node ID if this revision is also current.
if ($record->is_current) {
$table = key($field['storage']['details']['sql'][FIELD_LOAD_CURRENT]);
db_insert($table)->fields($columns)->values($values)->execute();
// Update the {taxonomy_index} table.
db_insert('taxonomy_index')
->fields(array('nid', 'tid', 'sticky', 'created',))
->values(array($record->nid, $record->tid, $record->sticky, $record->created))
->execute();
}
}
// Store the set of inserted values and the current revision's deltas in the
// sandbox.
$sandbox['cursor'] = array(
'values' => $values,
'deltas' => $deltas,
);
$sandbox['last'] += $batch;
}
if ($sandbox['count'] < $sandbox['total']) {
$sandbox['#finished'] = FALSE;
}
else {
db_drop_table('taxonomy_vocabulary_node_type');
db_drop_table('taxonomy_term_node');
// If there are no vocabs, we're done.
$sandbox['#finished'] = TRUE;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment