db = $db; $this->tablesToClone = $tablesToClone; $this->newTablePrefix = $newTablePrefix; $this->oldTablePrefix = $oldTablePrefix !== null ? $oldTablePrefix : $this->db->tablePrefix(); $this->dropCurrentTables = $dropCurrentTables; } /** * Set whether to use temporary tables or not * @param bool $u Use temporary tables when cloning the structure */ public function useTemporaryTables( $u = true ) { $this->useTemporaryTables = $u; } /** * Clone the table structure */ public function cloneTableStructure() { global $wgSharedTables, $wgSharedDB; foreach ( $this->tablesToClone as $tbl ) { if ( $wgSharedDB && in_array( $tbl, $wgSharedTables, true ) ) { // Shared tables don't work properly when cloning due to // how prefixes are handled (T67654) throw new RuntimeException( "Cannot clone shared table $tbl." ); } # Clean up from previous aborted run. So that table escaping # works correctly across DB engines, we need to change the pre- # fix back and forth so tableName() works right. self::changePrefix( $this->oldTablePrefix ); $oldTableName = $this->db->tableName( $tbl, 'raw' ); self::changePrefix( $this->newTablePrefix ); $newTableName = $this->db->tableName( $tbl, 'raw' ); // Postgres: Temp tables are automatically deleted upon end of session // Same Temp table name hides existing table for current session if ( $this->dropCurrentTables && !in_array( $this->db->getType(), [ 'oracle' ] ) ) { if ( $oldTableName === $newTableName ) { // Last ditch check to avoid data loss throw new LogicException( "Not dropping new table, as '$newTableName'" . " is name of both the old and the new table." ); } $this->db->dropTable( $tbl, __METHOD__ ); wfDebug( __METHOD__ . " dropping {$newTableName}\n" ); // Dropping the oldTable because the prefix was changed } # Create new table wfDebug( __METHOD__ . " duplicating $oldTableName to $newTableName\n" ); $this->db->duplicateTableStructure( $oldTableName, $newTableName, $this->useTemporaryTables ); } } /** * Change the prefix back to the original. * @param bool $dropTables Optionally drop the tables we created */ public function destroy( $dropTables = false ) { if ( $dropTables ) { self::changePrefix( $this->newTablePrefix ); foreach ( $this->tablesToClone as $tbl ) { $this->db->dropTable( $tbl ); } } self::changePrefix( $this->oldTablePrefix ); } /** * Change the table prefix on all open DB connections/ * * @param string $prefix * @return void */ public static function changePrefix( $prefix ) { global $wgDBprefix; $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); $lbFactory->setDomainPrefix( $prefix ); $wgDBprefix = $prefix; } }