diff options
author | Brion Vibber <brion@pobox.com> | 2010-10-12 17:58:26 -0700 |
---|---|---|
committer | Brion Vibber <brion@pobox.com> | 2010-10-12 17:58:26 -0700 |
commit | 621233e1ad6956cfb543042a1493a04b243e92ca (patch) | |
tree | ce3c754fe419b72f18fdad0726f4b7e1e25401b1 | |
parent | 72cba8865065f5f11c9487615c161cecb16e7db6 (diff) |
some of the ensureTable stuff partially working
-rw-r--r-- | lib/schema.php | 91 | ||||
-rw-r--r-- | scripts/dumpschema.php | 25 |
2 files changed, 87 insertions, 29 deletions
diff --git a/lib/schema.php b/lib/schema.php index f6543a21b..04bd2d1d9 100644 --- a/lib/schema.php +++ b/lib/schema.php @@ -234,7 +234,7 @@ class Schema */ function appendUniqueKeyDef(array &$sql, $name, array $def) { - $sql[] = "UNIQUE $key " . $this->buildIndexList($def); + $sql[] = "UNIQUE $name " . $this->buildIndexList($def); } /** @@ -487,59 +487,81 @@ class Schema } } - $cur = array_keys($old['fields']); - $new = array_keys($def['fields']); - - $toadd = array_diff($new, $cur); - $todrop = array_diff($cur, $new); - $same = array_intersect($new, $cur); - $tomod = array(); - - // Find which fields have actually changed definition - // in a way that we need to tweak them for this DB type. - foreach ($same as $name) { - $curCol = $old['fields'][$name]; - $newCol = $cur['fields'][$name]; - - if (!$this->columnsEqual($curCol, $newCol)) { - $tomod[] = $name; - } - } + // @fixme check if not present + $fields = $this->diffArrays($old['fields'], $def['fields'], array($this, 'columnsEqual')); + $uniques = $this->diffArrays($old['unique keys'], $def['unique keys']); + $indexes = $this->diffArrays($old['indexes'], $def['indexes']); + /* if (count($toadd) + count($todrop) + count($tomod) == 0) { // nothing to do return true; } + */ // For efficiency, we want this all in one // query, instead of using our methods. $phrase = array(); - foreach ($toadd as $columnName) { + foreach ($uniques['del'] + $uniques['mod'] as $keyName) { + $this->appendAlterDropUnique($phrase, $keyName); + } + + foreach ($fields['add'] as $columnName) { $this->appendAlterAddColumn($phrase, $columnName, $def['fields'][$columnName]); } - foreach ($todrop as $columnName) { + foreach ($fields['mod'] as $columnName) { $this->appendAlterModifyColumn($phrase, $columnName, $old['fields'][$columnName], $def['fields'][$columnName]); } - foreach ($tomod as $columnName) { + foreach ($fields['del'] as $columnName) { $this->appendAlterDropColumn($phrase, $columnName); } - $sql = 'ALTER TABLE ' . $tableName . ' ' . implode(', ', $phrase); + foreach ($uniques['mod'] + $uniques['add'] as $keyName) { + $this->appendAlterAddUnique($phrase, $keyName, $def['unique keys'][$keyName]); + } - $res = $this->conn->query($sql); + $sql = 'ALTER TABLE ' . $tableName . ' ' . implode(",\n", $phrase); - if (PEAR::isError($res)) { - throw new Exception($res->getMessage()); - } + return array($sql); + } - return true; + function diffArrays($old, $new, $compareCallback=null) + { + + $oldKeys = array_keys($old ? $old : array()); + $newKeys = array_keys($new ? $new : array()); + + $toadd = array_diff($newKeys, $oldKeys); + $todrop = array_diff($oldKeys, $newKeys); + $same = array_intersect($newKeys, $oldKeys); + $tomod = array(); + $tokeep = array(); + + // Find which fields have actually changed definition + // in a way that we need to tweak them for this DB type. + foreach ($same as $name) { + if ($compareCallback) { + $same = call_user_func($compareCallback, $old[$name], $new[$name]); + } else { + $same = ($old[$name] != $new[$name]); + } + if ($same) { + $tokeep[] = $name; + continue; + } + $tomod[] = $name; + } + return array('add' => $toadd, + 'del' => $todrop, + 'mod' => $tomod, + 'keep' => $tokeep); } /** @@ -587,6 +609,19 @@ class Schema $phrase[] = 'DROP COLUMN ' . $this->quoteIdentifier($columnName); } + function appendAlterAddUnique(array &$phrase, $keyName, array $def) + { + $sql = array(); + $sql[] = 'ADD'; + $this->appendUniqueKeyDef($sql, $keyName, $def); + $phrase[] = implode(' ', $sql);'ADD CONSTRAINT ' . $keyName; + } + + function appendAlterDropUnique(array &$phrase, $keyName) + { + $phrase[] = 'DROP CONSTRAINT ' . $keyName; + } + /** * Quote a db/table/column identifier if necessary. * diff --git a/scripts/dumpschema.php b/scripts/dumpschema.php index c0bf84f7c..3c2363638 100644 --- a/scripts/dumpschema.php +++ b/scripts/dumpschema.php @@ -23,9 +23,15 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); $helptext = <<<END_OF_CHECKSCHEMA_HELP Attempt to pull a schema definition for a given table. + --all run over all defined core tables + --diff do a raw text diff between the expected and live table defs + --update dump SQL that would be run to update or create this table + --build dump SQL that would be run to create this table fresh + + END_OF_CHECKSCHEMA_HELP; -$longoptions = array('diff', 'all', 'build'); +$longoptions = array('diff', 'all', 'build', 'update'); require_once INSTALLDIR.'/scripts/commandline.inc'; function indentOptions($indent) @@ -121,6 +127,21 @@ function dumpBuildTable($tableName) echo "\n"; } +function dumpEnsureTable($tableName) +{ + echo "-- \n"; + echo "-- $tableName\n"; + echo "-- \n"; + + $schema = Schema::get(); + $def = getCoreSchema($tableName); + $sql = $schema->buildEnsureTable($tableName, $def); + $sql[] = ''; + + echo implode(";\n", $sql); + echo "\n"; +} + function showDiff($a, $b) { $fnameA = tempnam(sys_get_temp_dir(), 'defined-diff-a'); @@ -156,6 +177,8 @@ if (count($args)) { showDiff($defined, $detected); } else if (have_option('build')) { dumpBuildTable($tableName); + } else if (have_option('update')) { + dumpEnsureTable($tableName); } else { dumpTable($tableName, true); } |