function schema_compare_table in Schema 7
Same name and namespace in other branches
- 8 schema.module \schema_compare_table()
- 5 schema.module \schema_compare_table()
- 6 schema.module \schema_compare_table()
Compares a reference specification (such as one returned by a module's hook_schema) to an inspected specification from the database.
Parameters
$inspect if not provided, the database is inspected.:
2 calls to schema_compare_table()
- SchemaRegressionTest::testInspectionConflict518210 in tests/
schema_regression.test - Test API for adding tables
- schema_compare_schemas in ./
schema.module - Compares two complete schemas.
File
- ./
schema.module, line 493 - The Schema module provides functionality built on the Schema API.
Code
function schema_compare_table($ref, $inspect = NULL) {
$_db_type = db_driver();
if (!isset($inspect)) {
// TODO: Handle prefixing the D7 way
// $ref_name = db_prefix_tables('{' . $ref['name'] . '}');
$ref_name = $ref['name'];
$inspect = schema_dbobject()
->inspect(NULL, $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',
'scale',
'precision',
));
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;
$name = isset($ref['name']) ? $ref['name'] : '';
$dbtype = schema_engine_type($col, $name, $colname);
list($col['type'], $col['size']) = schema_schema_type($dbtype, $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;
}
// Account for schemas that contain unnecessary 'default' => NULL
if (!isset($col['default']) || is_null($col['default']) && !isset($inspect['fields'][$colname]['default'])) {
unset($col['default']);
}
$kdiffs = array();
foreach ($col_keys as $key => $val) {
if (!(isset($col[$key]) && !is_null($col[$key]) && $col[$key] !== FALSE && isset($inspect['fields'][$colname][$key]) && $inspect['fields'][$colname][$key] !== FALSE && $col[$key] == $inspect['fields'][$colname][$key] || (!isset($col[$key]) || is_null($col[$key]) || $col[$key] === FALSE) && (!isset($inspect['fields'][$colname][$key]) || $inspect['fields'][$colname][$key] === FALSE))) {
// One way or another, difference between the two so note it to explicitly identify it later.
$kdiffs[] = $key;
}
}
if (count($kdiffs) != 0) {
$reasons[] = "column {$colname} - difference" . (count($kdiffs) > 1 ? 's' : '') . " on: " . implode(', ', $kdiffs) . "<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";
}
elseif ($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']);
}
}
elseif (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,
);
}