You are here

function schema_compare_table in Schema 5

Same name and namespace in other branches
  1. 8 schema.module \schema_compare_table()
  2. 6 schema.module \schema_compare_table()
  3. 7 schema.module \schema_compare_table()
1 call to schema_compare_table()
schema_compare_schemas in ./schema.module

File

./schema.module, line 269

Code

function schema_compare_table($ref, $inspect = NULL) {
  global $db_type;
  $_db_type = $db_type;
  if ($_db_type == 'mysqli') {
    $_db_type = 'mysql';
  }
  if (!isset($inspect)) {
    $inspect = schema_invoke('inspect', $ref['name']);
    $inspect = $inspect[$ref['name']];
  }
  if (!isset($inspect)) {
    return array(
      'status' => 'missing',
    );
  }
  $reasons = $notes = array();
  $col_keys = array_flip(array(
    'type',
    'size',
    'not null',
    'length',
    'unsigned',
    'default',
  ));
  foreach ($ref['fields'] as $colname => $col) {

    // Many Schema types can map to the same engine type (e.g. in
    // PostgresSQL, text:{small,medium,big} are all just text).  When
    // we inspect the database, we see the common type, but the
    // reference we are comparing against can have a specific type.
    // We therefore run the reference's specific type through the
    // type conversion cycle to get its common type for comparison.
    //
    // Sadly, we need a special-case hack for 'serial'.
    $serial = $col['type'] == 'serial' ? TRUE : FALSE;
    $dbtype = schema_engine_type($col, $ref['name'], $colname);
    list($col['type'], $col['size']) = schema_schema_type($dbtype, $ref['name'], $colname);
    if ($serial) {
      $col['type'] = 'serial';
    }

    // If an engine-specific type is specified, use it.  XXX $inspect
    // will contain the schema type for the engine type, if one
    // exists, whereas dbtype_type contains the engine type.
    if (isset($col[$_db_type . '_type'])) {
      $col['type'] = $col[$_db_type . '_type'];
    }
    $col = array_intersect_key($col, $col_keys);
    if (!isset($inspect['fields'][$colname])) {
      $reasons[] = "{$colname}: not in database";
      continue;
    }

    // XXX These should be unified so one reason contains all
    // mismatches between the columns.
    $colcmp1 = array_diff_assoc($col, $inspect['fields'][$colname]);
    if (count($colcmp1) != 0) {
      foreach ($colcmp1 as $key => $val) {
        $reasons[] = "column {$colname}:<br/>declared: " . schema_phpprint_column($col) . '<br/>actual: ' . schema_phpprint_column($inspect['fields'][$colname]);
      }
    }
    $colcmp2 = array_diff_assoc($inspect['fields'][$colname], $col);
    if (count($colcmp2) != 0) {
      foreach ($colcmp2 as $key => $val) {
        if (isset($col_keys[$key]) && !isset($colcmp1[$key])) {
          if (!isset($col['key']) && isset($inspect['fields'][$colname]) && $inspect['fields'][$colname][$key] === FALSE) {
            $notes[] = "column {$colname}: key '{$key}' not set, ignoring inspected default value";
          }
          else {
            $reasons[] = "column {$colname}:<br/>declared: " . schema_phpprint_column($col) . '<br/>actual: ' . schema_phpprint_column($inspect['fields'][$colname]);
          }
        }
      }
    }
    unset($inspect['fields'][$colname]);
  }
  foreach ($inspect['fields'] as $colname => $col) {
    $reasons[] = "{$colname}: unexpected column in database";
  }
  if (isset($ref['primary key'])) {
    if (!isset($inspect['primary key'])) {
      $reasons[] = "primary key: missing in database";
    }
    else {
      if ($ref['primary key'] !== $inspect['primary key']) {
        $reasons[] = "primary key:<br />declared: " . schema_phpprint_key($ref['primary key']) . '<br />actual: ' . schema_phpprint_key($inspect['primary key']);
      }
    }
  }
  else {
    if (isset($inspect['primary key'])) {
      $reasons[] = "primary key: missing in schema";
    }
  }
  foreach (array(
    'unique keys',
    'indexes',
  ) as $type) {
    if (isset($ref[$type])) {
      foreach ($ref[$type] as $keyname => $key) {
        if (!isset($inspect[$type][$keyname])) {
          $reasons[] = "{$type} {$keyname}: missing in database";
          continue;
        }

        // $key is column list
        if ($key !== $inspect[$type][$keyname]) {
          $reasons[] = "{$type} {$keyname}:<br />declared: " . schema_phpprint_key($key) . '<br />actual: ' . schema_phpprint_key($inspect[$type][$keyname]);
        }
        unset($inspect[$type][$keyname]);
      }
    }
    if (isset($inspect[$type])) {
      foreach ($inspect[$type] as $keyname => $col) {

        // this is not an error, the dba might have added it on purpose
        $notes[] = "{$type} {$keyname}: unexpected (not an error)";
      }
    }
  }
  $status = count($reasons) ? 'different' : 'same';
  return array(
    'status' => $status,
    'reasons' => $reasons,
    'notes' => $notes,
  );
}