4 * StatusNet - a distributed open-source microblogging tool
5 * Copyright (C) 2008, 2009, StatusNet, Inc.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 define('INSTALLDIR', dirname(__DIR__));
22 define('PUBLICDIR', INSTALLDIR . DIRECTORY_SEPARATOR . 'public');
24 $helptext = <<<END_OF_CHECKSCHEMA_HELP
25 Attempt to pull a schema definition for a given table.
27 --all run over all defined core tables
28 --diff show differences between the expected and live table defs
29 --raw skip compatibility filtering for diffs
30 --create dump SQL that would be run to update or create this table
31 --build dump SQL that would be run to create this table fresh
32 --checksum just output checksums from the source schema defs
35 END_OF_CHECKSCHEMA_HELP;
37 $longoptions = array('diff', 'all', 'create', 'update', 'raw', 'checksum');
38 require_once INSTALLDIR.'/scripts/commandline.inc';
40 function indentOptions($indent)
43 if ($indent < $cutoff) {
44 $space = $indent ? str_repeat(' ', $indent * 4) : '';
47 $endspace = "$lf" . ($indent ? str_repeat(' ', ($indent - 1) * 4) : '');
54 if ($indent - 1 < $cutoff) {
56 return array($space, $sep, $lf, $endspace);
59 function prettyDumpArray($arr, $key=null, $indent=0)
62 if ($key == 'primary key') {
63 $subIndent = $indent + 2;
65 $subIndent = $indent + 1;
68 list($space, $sep, $lf, $endspace) = indentOptions($indent);
69 list($inspace, $insep, $inlf, $inendspace) = indentOptions($subIndent);
72 if (!is_numeric($key)) {
76 print "array({$inlf}";
78 foreach ($arr as $key => $row) {
80 prettyDumpArray($row, $key, $subIndent);
81 if ($n < count($arr)) {
86 print "{$inendspace})";
88 print var_export($arr, true);
92 function getCoreSchema($tableName)
95 include INSTALLDIR . '/db/core.php';
96 return $schema[$tableName];
99 function getCoreTables()
102 include INSTALLDIR . '/db/core.php';
103 return array_keys($schema);
106 function dumpTable($tableName, $live)
109 $schema = Schema::get();
110 $def = $schema->getTableDef($tableName);
113 $def = getCoreSchema($tableName);
115 prettyDumpArray($def, $tableName);
119 function dumpBuildTable($tableName)
122 echo "-- $tableName\n";
125 $schema = Schema::get();
126 $def = getCoreSchema($tableName);
127 $sql = $schema->buildCreateTable($tableName, $def);
130 echo implode(";\n", $sql);
134 function dumpEnsureTable($tableName)
136 $schema = Schema::get();
137 $def = getCoreSchema($tableName);
138 $sql = $schema->buildEnsureTable($tableName, $def);
142 echo "-- $tableName\n";
146 echo implode(";\n", $sql);
151 function dumpDiff($tableName, $filter)
153 $schema = Schema::get();
154 $def = getCoreSchema($tableName);
156 $old = $schema->getTableDef($tableName);
157 } catch (Exception $e) {
158 // @fixme this is a terrible check :D
159 if (preg_match('/no such table/i', $e->getMessage())) {
160 return dumpTable($tableName, false);
167 //$old = $schema->filterDef($old);
168 $def = $schema->filterDef($def);
172 $old = tweakPrimaryKey($old);
173 $def = tweakPrimaryKey($def);
175 $sections = array_unique(array_merge(array_keys($old), array_keys($def)));
177 foreach ($sections as $section) {
178 if ($section == 'fields') {
179 // this shouldn't be needed maybe... wait what?
181 $diff = $schema->diffArrays($old, $def, $section);
182 $chunks = array('del', 'mod', 'add');
183 foreach ($chunks as $chunk) {
185 foreach ($diff[$chunk] as $key) {
186 if ($chunk == 'del') {
187 $final[$section]["DEL $key"] = $old[$section][$key];
188 } else if ($chunk == 'add') {
189 $final[$section]["ADD $key"] = $def[$section][$key];
190 } else if ($chunk == 'mod') {
191 $final[$section]["OLD $key"] = $old[$section][$key];
192 $final[$section]["NEW $key"] = $def[$section][$key];
199 prettyDumpArray($final, $tableName);
203 function tweakPrimaryKey($def)
205 if (isset($def['primary key'])) {
206 $def['primary keys'] = array('primary key' => $def['primary key']);
207 unset($def['primary key']);
209 if (isset($def['description'])) {
210 $def['descriptions'] = array('description' => $def['description']);
211 unset($def['description']);
216 function dumpChecksum($tableName)
218 $schema = Schema::get();
219 $def = getCoreSchema($tableName);
221 $updater = new SchemaUpdater($schema);
222 $checksum = $updater->checksum($def);
223 $old = @$updater->checksums[$tableName];
225 if ($old == $checksum) {
226 echo "OK $checksum $tableName\n";
228 echo "NEW $checksum $tableName\n";
230 echo "MOD $checksum $tableName (was $old)\n";
234 if (have_option('all')) {
235 $args = getCoreTables();
239 foreach ($args as $tableName) {
240 if (have_option('diff')) {
241 dumpDiff($tableName, !have_option('raw'));
242 } else if (have_option('create')) {
243 dumpBuildTable($tableName);
244 } else if (have_option('update')) {
245 dumpEnsureTable($tableName);
246 } else if (have_option('checksum')) {
247 dumpChecksum($tableName);
249 dumpTable($tableName, true);
253 show_help($helptext);