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