diff options
Diffstat (limited to 'scripts/dumpschema.php')
-rw-r--r-- | scripts/dumpschema.php | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/scripts/dumpschema.php b/scripts/dumpschema.php new file mode 100644 index 000000000..2b238f006 --- /dev/null +++ b/scripts/dumpschema.php @@ -0,0 +1,249 @@ +#!/usr/bin/env php +<?php +/* + * StatusNet - a distributed open-source microblogging tool + * Copyright (C) 2008, 2009, StatusNet, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +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 show differences between the expected and live table defs + --raw skip compatibility filtering for diffs + --create dump SQL that would be run to update or create this table + --build dump SQL that would be run to create this table fresh + --checksum just output checksums from the source schema defs + + +END_OF_CHECKSCHEMA_HELP; + +$longoptions = array('diff', 'all', 'create', 'update', 'raw', 'checksum'); +require_once INSTALLDIR.'/scripts/commandline.inc'; + +function indentOptions($indent) +{ + $cutoff = 3; + if ($indent < $cutoff) { + $space = $indent ? str_repeat(' ', $indent * 4) : ''; + $sep = ","; + $lf = "\n"; + $endspace = "$lf" . ($indent ? str_repeat(' ', ($indent - 1) * 4) : ''); + } else { + $space = ''; + $sep = ", "; + $lf = ''; + $endspace = ''; + } + if ($indent - 1 < $cutoff) { + } + return array($space, $sep, $lf, $endspace); +} + +function prettyDumpArray($arr, $key=null, $indent=0) +{ + // hack + if ($key == 'primary key') { + $subIndent = $indent + 2; + } else { + $subIndent = $indent + 1; + } + + list($space, $sep, $lf, $endspace) = indentOptions($indent); + list($inspace, $insep, $inlf, $inendspace) = indentOptions($subIndent); + + print "{$space}"; + if (!is_numeric($key)) { + print "'$key' => "; + } + if (is_array($arr)) { + print "array({$inlf}"; + $n = 0; + foreach ($arr as $key => $row) { + $n++; + prettyDumpArray($row, $key, $subIndent); + if ($n < count($arr)) { + print "$insep$inlf"; + } + } + // hack! + print "{$inendspace})"; + } else { + print var_export($arr, true); + } +} + +function getCoreSchema($tableName) +{ + $schema = array(); + include INSTALLDIR . '/db/core.php'; + return $schema[$tableName]; +} + +function getCoreTables() +{ + $schema = array(); + include INSTALLDIR . '/db/core.php'; + return array_keys($schema); +} + +function dumpTable($tableName, $live) +{ + if ($live) { + $schema = Schema::get(); + $def = $schema->getTableDef($tableName); + } else { + // hack + $def = getCoreSchema($tableName); + } + prettyDumpArray($def, $tableName); + print "\n"; +} + +function dumpBuildTable($tableName) +{ + echo "-- \n"; + echo "-- $tableName\n"; + echo "-- \n"; + + $schema = Schema::get(); + $def = getCoreSchema($tableName); + $sql = $schema->buildCreateTable($tableName, $def); + $sql[] = ''; + + echo implode(";\n", $sql); + echo "\n"; +} + +function dumpEnsureTable($tableName) +{ + $schema = Schema::get(); + $def = getCoreSchema($tableName); + $sql = $schema->buildEnsureTable($tableName, $def); + + if ($sql) { + echo "-- \n"; + echo "-- $tableName\n"; + echo "-- \n"; + + $sql[] = ''; + echo implode(";\n", $sql); + echo "\n"; + } +} + +function dumpDiff($tableName, $filter) +{ + $schema = Schema::get(); + $def = getCoreSchema($tableName); + try { + $old = $schema->getTableDef($tableName); + } catch (Exception $e) { + // @fixme this is a terrible check :D + if (preg_match('/no such table/i', $e->getMessage())) { + return dumpTable($tableName, false); + } else { + throw $e; + } + } + + if ($filter) { + //$old = $schema->filterDef($old); + $def = $schema->filterDef($def); + } + + // @hack + $old = tweakPrimaryKey($old); + $def = tweakPrimaryKey($def); + + $sections = array_unique(array_merge(array_keys($old), array_keys($def))); + $final = array(); + foreach ($sections as $section) { + if ($section == 'fields') { + // this shouldn't be needed maybe... wait what? + } + $diff = $schema->diffArrays($old, $def, $section, $compare); + $chunks = array('del', 'mod', 'add'); + foreach ($chunks as $chunk) { + if ($diff[$chunk]) { + foreach ($diff[$chunk] as $key) { + if ($chunk == 'del') { + $final[$section]["DEL $key"] = $old[$section][$key]; + } else if ($chunk == 'add') { + $final[$section]["ADD $key"] = $def[$section][$key]; + } else if ($chunk == 'mod') { + $final[$section]["OLD $key"] = $old[$section][$key]; + $final[$section]["NEW $key"] = $def[$section][$key]; + } + } + } + } + } + + prettyDumpArray($final, $tableName); + print "\n"; +} + +function tweakPrimaryKey($def) +{ + if (isset($def['primary key'])) { + $def['primary keys'] = array('primary key' => $def['primary key']); + unset($def['primary key']); + } + return $def; +} + +function dumpChecksum($tableName) +{ + $schema = Schema::get(); + $def = getCoreSchema($tableName); + + $updater = new SchemaUpdater($schema); + $checksum = $updater->checksum($def); + $old = @$updater->checksums[$tableName]; + + if ($old == $checksum) { + echo "OK $checksum $tableName\n"; + } else if (!$old) { + echo "NEW $checksum $tableName\n"; + } else { + echo "MOD $checksum $tableName (was $old)\n"; + } +} + +if (have_option('all')) { + $args = getCoreTables(); +} + +if (count($args)) { + foreach ($args as $tableName) { + if (have_option('diff')) { + dumpDiff($tableName, !have_option('raw')); + } else if (have_option('create')) { + dumpBuildTable($tableName); + } else if (have_option('update')) { + dumpEnsureTable($tableName); + } else if (have_option('checksum')) { + dumpChecksum($tableName); + } else { + dumpTable($tableName, true); + } + } +} else { + show_help($helptext); +}
\ No newline at end of file |