When saving preferences, check hook and authentication plugin, and actually save...
[mediawiki.git] / maintenance / convertLinks.inc
blobd0c57f784ac5b248210e6c2584d6e485aad00c8e
1 <?php
2 /**
3  * @todo document
4  * @addtogroup Maintenance
5  */
7 /** */
8 function convertLinks() {
9         global $wgDBtype;
10         if( $wgDBtype == 'postgres' ) {
11                 print "Links table already ok on Postgres.\n";
12                 return;
13         }
15         print "Converting links table to ID-ID...\n";
17         global $wgLang, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
18         global $noKeys, $logPerformance, $fh;
20         $tuplesAdded = $numBadLinks = $curRowsRead = 0; #counters etc
21         $totalTuplesInserted = 0; # total tuples INSERTed into links_temp
23         $reportCurReadProgress = true; #whether or not to give progress reports while reading IDs from cur table
24         $curReadReportInterval = 1000; #number of rows between progress reports
26         $reportLinksConvProgress = true; #whether or not to give progress reports during conversion
27         $linksConvInsertInterval = 1000; #number of rows per INSERT
29         $initialRowOffset = 0;
30         #$finalRowOffset = 0; # not used yet; highest row number from links table to process
32         # Overwrite the old links table with the new one.  If this is set to false,
33         # the new table will be left at links_temp.
34         $overwriteLinksTable = true;
36         # Don't create keys, and so allow duplicates in the new links table.
37         # This gives a huge speed improvement for very large links tables which are MyISAM. (What about InnoDB?)
38         $noKeys = false;
41         $logPerformance = false; # output performance data to a file
42         $perfLogFilename = "convLinksPerf.txt";
43         #--------------------------------------------------------------------
45         $dbw = wfGetDB( DB_MASTER );
46         list ($cur, $links, $links_temp, $links_backup) = $dbw->tableNamesN( 'cur', 'links', 'links_temp', 'links_backup' );
48         $res = $dbw->query( "SELECT l_from FROM $links LIMIT 1" );
49         if ( $dbw->fieldType( $res, 0 ) == "int" ) {
50                 print "Schema already converted\n";
51                 return;
52         }
54         $res = $dbw->query( "SELECT COUNT(*) AS count FROM $links" );
55         $row = $dbw->fetchObject($res);
56         $numRows = $row->count;
57         $dbw->freeResult( $res );
59         if ( $numRows == 0 ) {
60                 print "Updating schema (no rows to convert)...\n";
61                 createTempTable();
62         } else {
63                 if ( $logPerformance ) { $fh = fopen ( $perfLogFilename, "w" ); }
64                 $baseTime = $startTime = getMicroTime();
65                 # Create a title -> cur_id map
66                 print "Loading IDs from $cur table...\n";
67                 performanceLog ( "Reading $numRows rows from cur table...\n" );
68                 performanceLog ( "rows read vs seconds elapsed:\n" );
70                 $dbw->bufferResults( false );
71                 $res = $dbw->query( "SELECT cur_namespace,cur_title,cur_id FROM $cur" );
72                 $ids = array();
74                 while ( $row = $dbw->fetchObject( $res ) ) {
75                         $title = $row->cur_title;
76                         if ( $row->cur_namespace ) {
77                                 $title = $wgLang->getNsText( $row->cur_namespace ) . ":$title";
78                         }
79                         $ids[$title] = $row->cur_id;
80                         $curRowsRead++;
81                         if ($reportCurReadProgress) {
82                                 if (($curRowsRead % $curReadReportInterval) == 0) {
83                                         performanceLog( $curRowsRead . " " . (getMicroTime() - $baseTime) . "\n" );
84                                         print "\t$curRowsRead rows of $cur table read.\n";
85                                 }
86                         }
87                 }
88                 $dbw->freeResult( $res );
89                 $dbw->bufferResults( true );
90                 print "Finished loading IDs.\n\n";
91                 performanceLog( "Took " . (getMicroTime() - $baseTime) . " seconds to load IDs.\n\n" );
92         #--------------------------------------------------------------------
94                 # Now, step through the links table (in chunks of $linksConvInsertInterval rows),
95                 # convert, and write to the new table.
96                 createTempTable();
97                 performanceLog( "Resetting timer.\n\n" );
98                 $baseTime = getMicroTime();
99                 print "Processing $numRows rows from $links table...\n";
100                 performanceLog( "Processing $numRows rows from $links table...\n" );
101                 performanceLog( "rows inserted vs seconds elapsed:\n" );
103                 for ($rowOffset = $initialRowOffset; $rowOffset < $numRows; $rowOffset += $linksConvInsertInterval) {
104                         $sqlRead = "SELECT * FROM $links ";
105                         $sqlRead = $dbw->limitResult($sqlRead, $linksConvInsertInterval,$rowOffset);
106                         $res = $dbw->query($sqlRead);
107                         if ( $noKeys ) {
108                                 $sqlWrite = array("INSERT INTO $links_temp (l_from,l_to) VALUES ");
109                         } else {
110                                 $sqlWrite = array("INSERT IGNORE INTO $links_temp (l_from,l_to) VALUES ");
111                         }
113                         $tuplesAdded = 0; # no tuples added to INSERT yet
114                         while ( $row = $dbw->fetchObject($res) ) {
115                                 $fromTitle = $row->l_from;
116                                 if ( array_key_exists( $fromTitle, $ids ) ) { # valid title
117                                         $from = $ids[$fromTitle];
118                                         $to = $row->l_to;
119                                         if ( $tuplesAdded != 0 ) {
120                                                 $sqlWrite[] = ",";
121                                         }
122                                         $sqlWrite[] = "($from,$to)";
123                                         $tuplesAdded++;
124                                 } else { # invalid title
125                                         $numBadLinks++;
126                                 }
127                         }
128                         $dbw->freeResult($res);
129                         #print "rowOffset: $rowOffset\ttuplesAdded: $tuplesAdded\tnumBadLinks: $numBadLinks\n";
130                         if ( $tuplesAdded != 0  ) {
131                                 if ($reportLinksConvProgress) {
132                                         print "Inserting $tuplesAdded tuples into $links_temp...";
133                                 }
134                                 $dbw->query( implode("",$sqlWrite) );
135                                 $totalTuplesInserted += $tuplesAdded;
136                                 if ($reportLinksConvProgress)
137                                         print " done. Total $totalTuplesInserted tuples inserted.\n";
138                                         performanceLog( $totalTuplesInserted . " " . (getMicroTime() - $baseTime) . "\n"  );
139                         }
140                 }
141                 print "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n\n";
142                 performanceLog( "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n" );
143                 performanceLog( "Total execution time: " . (getMicroTime() - $startTime) . " seconds.\n" );
144                 if ( $logPerformance ) { fclose ( $fh ); }
145         }
146         #--------------------------------------------------------------------
148         if ( $overwriteLinksTable ) {
149                 $dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
150                 if (!($dbConn->isOpen())) {
151                         print "Opening connection to database failed.\n";
152                         return;
153                 }
154                 # Check for existing links_backup, and delete it if it exists.
155                 print "Dropping backup links table if it exists...";
156                 $dbConn->query( "DROP TABLE IF EXISTS $links_backup", DB_MASTER);
157                 print " done.\n";
159                 # Swap in the new table, and move old links table to links_backup
160                 print "Swapping tables '$links' to '$links_backup'; '$links_temp' to '$links'...";
161                 $dbConn->query( "RENAME TABLE links TO $links_backup, $links_temp TO $links", DB_MASTER );
162                 print " done.\n\n";
164                 $dbConn->close();
165                 print "Conversion complete. The old table remains at $links_backup;\n";
166                 print "delete at your leisure.\n";
167         } else {
168                 print "Conversion complete.  The converted table is at $links_temp;\n";
169                 print "the original links table is unchanged.\n";
170         }
173 #--------------------------------------------------------------------
175 function createTempTable() {
176         global $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
177         global $noKeys;
178         $dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
180         if (!($dbConn->isOpen())) {
181                 print "Opening connection to database failed.\n";
182                 return;
183         }
184         $links_temp = $dbConn->tableName( 'links_temp' );
186         print "Dropping temporary links table if it exists...";
187         $dbConn->query( "DROP TABLE IF EXISTS $links_temp");
188         print " done.\n";
190         print "Creating temporary links table...";
191         if ( $noKeys ) {
192                 $dbConn->query( "CREATE TABLE $links_temp ( " .
193                 "l_from int(8) unsigned NOT NULL default '0', " .
194                 "l_to int(8) unsigned NOT NULL default '0')");
195         } else {
196                 $dbConn->query( "CREATE TABLE $links_temp ( " .
197                 "l_from int(8) unsigned NOT NULL default '0', " .
198                 "l_to int(8) unsigned NOT NULL default '0', " .
199                 "UNIQUE KEY l_from(l_from,l_to), " .
200                 "KEY (l_to))");
201         }
202         print " done.\n\n";
205 function performanceLog( $text ) {
206         global $logPerformance, $fh;
207         if ( $logPerformance ) {
208                 fwrite( $fh, $text );
209         }
212 function getMicroTime() { # return time in seconds, with microsecond accuracy
213         list($usec, $sec) = explode(" ", microtime());
214         return ((float)$usec + (float)$sec);