]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - scripts/dumpschema.php
Make attachment fit better in notice: drop text and link
[quix0rs-gnu-social.git] / scripts / dumpschema.php
1 #!/usr/bin/env php
2 <?php
3 /*
4  * StatusNet - a distributed open-source microblogging tool
5  * Copyright (C) 2008, 2009, StatusNet, Inc.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 define('INSTALLDIR', dirname(__DIR__));
22 define('PUBLICDIR', INSTALLDIR . DIRECTORY_SEPARATOR . 'public');
23
24 $helptext = <<<END_OF_CHECKSCHEMA_HELP
25 Attempt to pull a schema definition for a given table.
26
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
33
34
35 END_OF_CHECKSCHEMA_HELP;
36
37 $longoptions = array('diff', 'all', 'create', 'update', 'raw', 'checksum');
38 require_once INSTALLDIR.'/scripts/commandline.inc';
39
40 function indentOptions($indent)
41 {
42     $cutoff = 3;
43     if ($indent < $cutoff) {
44         $space = $indent ? str_repeat(' ', $indent * 4) : '';
45         $sep = ",";
46         $lf = "\n";
47         $endspace = "$lf" . ($indent ? str_repeat(' ', ($indent - 1) * 4) : '');
48     } else {
49         $space = '';
50         $sep = ", ";
51         $lf = '';
52         $endspace = '';
53     }
54     if ($indent - 1 < $cutoff) {
55     }
56     return array($space, $sep, $lf, $endspace);
57 }
58
59 function prettyDumpArray($arr, $key=null, $indent=0)
60 {
61     // hack
62     if ($key == 'primary key') {
63         $subIndent = $indent + 2;
64     } else {
65         $subIndent = $indent + 1;
66     }
67
68     list($space, $sep, $lf, $endspace) = indentOptions($indent);
69     list($inspace, $insep, $inlf, $inendspace) = indentOptions($subIndent);
70
71     print "{$space}";
72     if (!is_numeric($key)) {
73         print "'$key' => ";
74     }
75     if (is_array($arr)) {
76         print "array({$inlf}";
77         $n = 0;
78         foreach ($arr as $key => $row) {
79             $n++;
80             prettyDumpArray($row, $key, $subIndent);
81             if ($n < count($arr)) {
82                 print "$insep$inlf";
83             }
84         }
85         // hack!
86         print "{$inendspace})";
87     } else {
88         print var_export($arr, true);
89     }
90 }
91
92 function getCoreSchema($tableName)
93 {
94     $schema = array();
95     include INSTALLDIR . '/db/core.php';
96     return $schema[$tableName];
97 }
98
99 function getCoreTables()
100 {
101     $schema = array();
102     include INSTALLDIR . '/db/core.php';
103     return array_keys($schema);
104 }
105
106 function dumpTable($tableName, $live)
107 {
108     if ($live) {
109         $schema = Schema::get();
110         $def = $schema->getTableDef($tableName);
111     } else {
112         // hack
113         $def = getCoreSchema($tableName);
114     }
115     prettyDumpArray($def, $tableName);
116     print "\n";
117 }
118
119 function dumpBuildTable($tableName)
120 {
121     echo "-- \n";
122     echo "-- $tableName\n";
123     echo "-- \n";
124
125     $schema = Schema::get();
126     $def = getCoreSchema($tableName);
127     $sql = $schema->buildCreateTable($tableName, $def);
128     $sql[] = '';
129
130     echo implode(";\n", $sql);
131     echo "\n";
132 }
133
134 function dumpEnsureTable($tableName)
135 {
136     $schema = Schema::get();
137     $def = getCoreSchema($tableName);
138     $sql = $schema->buildEnsureTable($tableName, $def);
139
140     if ($sql) {
141         echo "-- \n";
142         echo "-- $tableName\n";
143         echo "-- \n";
144
145         $sql[] = '';
146         echo implode(";\n", $sql);
147         echo "\n";
148     }
149 }
150
151 function dumpDiff($tableName, $filter)
152 {
153     $schema = Schema::get();
154     $def = getCoreSchema($tableName);
155     try {
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);
161         } else {
162             throw $e;
163         }
164     }
165
166     if ($filter) {
167         //$old = $schema->filterDef($old);
168         $def = $schema->filterDef($def);
169     }
170
171     // @hack
172     $old = tweakPrimaryKey($old);
173     $def = tweakPrimaryKey($def);
174
175     $sections = array_unique(array_merge(array_keys($old), array_keys($def)));
176     $final = array();
177     foreach ($sections as $section) {
178         if ($section == 'fields') {
179             // this shouldn't be needed maybe... wait what?
180         }
181         $diff = $schema->diffArrays($old, $def, $section);
182         $chunks = array('del', 'mod', 'add');
183         foreach ($chunks as $chunk) {
184             if ($diff[$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];
193                     }
194                 }
195             }
196         }
197     }
198
199     prettyDumpArray($final, $tableName);
200     print "\n";
201 }
202
203 function tweakPrimaryKey($def)
204 {
205     if (isset($def['primary key'])) {
206         $def['primary keys'] = array('primary key' => $def['primary key']);
207         unset($def['primary key']);
208     }
209     if (isset($def['description'])) {
210         $def['descriptions'] = array('description' => $def['description']);
211         unset($def['description']);
212     }
213     return $def;
214 }
215
216 function dumpChecksum($tableName)
217 {
218     $schema = Schema::get();
219     $def = getCoreSchema($tableName);
220
221     $updater = new SchemaUpdater($schema);
222     $checksum = $updater->checksum($def);
223     $old = @$updater->checksums[$tableName];
224
225     if ($old == $checksum) {
226         echo "OK  $checksum $tableName\n";
227     } else if (!$old) {
228         echo "NEW $checksum $tableName\n";
229     } else {
230         echo "MOD $checksum $tableName (was $old)\n";
231     }
232 }
233
234 if (have_option('all')) {
235     $args = getCoreTables();
236 }
237
238 if (count($args)) {
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);
248         } else {
249             dumpTable($tableName, true);
250         }
251     }
252 } else {
253     show_help($helptext);
254 }