summaryrefslogtreecommitdiff
path: root/scripts/dumpschema.php
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dumpschema.php')
-rw-r--r--scripts/dumpschema.php249
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