MediaWiki  REL1_24
CloneDatabase.php
Go to the documentation of this file.
00001 <?php
00027 class CloneDatabase {
00029     private $newTablePrefix = '';
00030 
00032     private $oldTablePrefix = '';
00033 
00035     private $tablesToClone = array();
00036 
00038     private $dropCurrentTables = true;
00039 
00041     private $useTemporaryTables = true;
00042 
00052     public function __construct( DatabaseBase $db, array $tablesToClone,
00053         $newTablePrefix, $oldTablePrefix = '', $dropCurrentTables = true
00054     ) {
00055         $this->db = $db;
00056         $this->tablesToClone = $tablesToClone;
00057         $this->newTablePrefix = $newTablePrefix;
00058         $this->oldTablePrefix = $oldTablePrefix ? $oldTablePrefix : $this->db->tablePrefix();
00059         $this->dropCurrentTables = $dropCurrentTables;
00060     }
00061 
00066     public function useTemporaryTables( $u = true ) {
00067         $this->useTemporaryTables = $u;
00068     }
00069 
00073     public function cloneTableStructure() {
00074         global $wgSharedTables, $wgSharedDB;
00075         foreach ( $this->tablesToClone as $tbl ) {
00076             if ( $wgSharedDB && in_array( $tbl, $wgSharedTables, true ) ) {
00077                 // Shared tables don't work properly when cloning due to
00078                 // how prefixes are handled (bug 65654)
00079                 throw new MWException( "Cannot clone shared table $tbl." );
00080             }
00081             # Clean up from previous aborted run.  So that table escaping
00082             # works correctly across DB engines, we need to change the pre-
00083             # fix back and forth so tableName() works right.
00084 
00085             self::changePrefix( $this->oldTablePrefix );
00086             $oldTableName = $this->db->tableName( $tbl, 'raw' );
00087 
00088             self::changePrefix( $this->newTablePrefix );
00089             $newTableName = $this->db->tableName( $tbl, 'raw' );
00090 
00091             if ( $this->dropCurrentTables
00092                 && !in_array( $this->db->getType(), array( 'postgres', 'oracle' ) )
00093             ) {
00094                 if ( $oldTableName === $newTableName ) {
00095                     // Last ditch check to avoid data loss
00096                     throw new MWException( "Not dropping new table, as '$newTableName'"
00097                         . " is name of both the old and the new table." );
00098                 }
00099                 $this->db->dropTable( $tbl, __METHOD__ );
00100                 wfDebug( __METHOD__ . " dropping {$newTableName}\n" );
00101                 //Dropping the oldTable because the prefix was changed
00102             }
00103 
00104             # Create new table
00105             wfDebug( __METHOD__ . " duplicating $oldTableName to $newTableName\n" );
00106             $this->db->duplicateTableStructure( $oldTableName, $newTableName, $this->useTemporaryTables );
00107         }
00108     }
00109 
00114     public function destroy( $dropTables = false ) {
00115         if ( $dropTables ) {
00116             self::changePrefix( $this->newTablePrefix );
00117             foreach ( $this->tablesToClone as $tbl ) {
00118                 $this->db->dropTable( $tbl );
00119             }
00120         }
00121         self::changePrefix( $this->oldTablePrefix );
00122     }
00123 
00130     public static function changePrefix( $prefix ) {
00131         global $wgDBprefix;
00132         wfGetLBFactory()->forEachLB( array( 'CloneDatabase', 'changeLBPrefix' ), array( $prefix ) );
00133         $wgDBprefix = $prefix;
00134     }
00135 
00141     public static function changeLBPrefix( $lb, $prefix ) {
00142         $lb->forEachOpenConnection( array( 'CloneDatabase', 'changeDBPrefix' ), array( $prefix ) );
00143     }
00144 
00150     public static function changeDBPrefix( $db, $prefix ) {
00151         $db->tablePrefix( $prefix );
00152     }
00153 }