MediaWiki  REL1_24
sql.php
Go to the documentation of this file.
00001 <?php
00025 require_once __DIR__ . '/Maintenance.php';
00026 
00032 class MwSql extends Maintenance {
00033     public function __construct() {
00034         parent::__construct();
00035         $this->mDescription = "Send SQL queries to a MediaWiki database";
00036         $this->addOption( 'cluster', 'Use an external cluster by name', false, true );
00037         $this->addOption( 'wikidb', 'The database wiki ID to use if not the current one', false, true );
00038         $this->addOption( 'slave', 'Use a slave server (either "any" or by name)', false, true );
00039     }
00040 
00041     public function execute() {
00042         $wiki = $this->getOption( 'wikidb' ) ?: false;
00043         // Get the appropriate load balancer (for this wiki)
00044         if ( $this->hasOption( 'cluster' ) ) {
00045             $lb = wfGetLBFactory()->getExternalLB( $this->getOption( 'cluster' ), $wiki );
00046         } else {
00047             $lb = wfGetLB( $wiki );
00048         }
00049         // Figure out which server to use
00050         if ( $this->hasOption( 'slave' ) ) {
00051             $server = $this->getOption( 'slave' );
00052             if ( $server === 'any' ) {
00053                 $index = DB_SLAVE;
00054             } else {
00055                 $index = null;
00056                 $serverCount = $lb->getServerCount();
00057                 for ( $i = 0; $i < $serverCount; ++$i ) {
00058                     if ( $lb->getServerName( $i ) === $server ) {
00059                         $index = $i;
00060                         break;
00061                     }
00062                 }
00063                 if ( $index === null ) {
00064                     $this->error( "No slave server configured with the name '$server'.", 1 );
00065                 }
00066             }
00067         } else {
00068             $index = DB_MASTER;
00069         }
00070         // Get a DB handle (with this wiki's DB selected) from the appropriate load balancer
00071         $db = $lb->getConnection( $index, array(), $wiki );
00072         if ( $this->hasOption( 'slave' ) && $db->getLBInfo( 'master' ) !== null ) {
00073             $this->error( "The server selected ({$db->getServer()}) is not a slave.", 1 );
00074         }
00075 
00076         if ( $this->hasArg( 0 ) ) {
00077             $file = fopen( $this->getArg( 0 ), 'r' );
00078             if ( !$file ) {
00079                 $this->error( "Unable to open input file", true );
00080             }
00081 
00082             $error = $db->sourceStream( $file, false, array( $this, 'sqlPrintResult' ) );
00083             if ( $error !== true ) {
00084                 $this->error( $error, true );
00085             } else {
00086                 exit( 0 );
00087             }
00088         }
00089 
00090         $useReadline = function_exists( 'readline_add_history' )
00091             && Maintenance::posix_isatty( 0 /*STDIN*/ );
00092 
00093         if ( $useReadline ) {
00094             global $IP;
00095             $historyFile = isset( $_ENV['HOME'] ) ?
00096                 "{$_ENV['HOME']}/.mwsql_history" : "$IP/maintenance/.mwsql_history";
00097             readline_read_history( $historyFile );
00098         }
00099 
00100         $wholeLine = '';
00101         $newPrompt = '> ';
00102         $prompt = $newPrompt;
00103         while ( ( $line = Maintenance::readconsole( $prompt ) ) !== false ) {
00104             if ( !$line ) {
00105                 # User simply pressed return key
00106                 continue;
00107             }
00108             $done = $db->streamStatementEnd( $wholeLine, $line );
00109 
00110             $wholeLine .= $line;
00111 
00112             if ( !$done ) {
00113                 $wholeLine .= ' ';
00114                 $prompt = '    -> ';
00115                 continue;
00116             }
00117             if ( $useReadline ) {
00118                 # Delimiter is eated by streamStatementEnd, we add it
00119                 # up in the history (bug 37020)
00120                 readline_add_history( $wholeLine . $db->getDelimiter() );
00121                 readline_write_history( $historyFile );
00122             }
00123             try {
00124                 $res = $db->query( $wholeLine );
00125                 $this->sqlPrintResult( $res, $db );
00126                 $prompt = $newPrompt;
00127                 $wholeLine = '';
00128             } catch ( DBQueryError $e ) {
00129                 $doDie = !Maintenance::posix_isatty( 0 );
00130                 $this->error( $e, $doDie );
00131             }
00132         }
00133         wfWaitForSlaves();
00134     }
00135 
00141     public function sqlPrintResult( $res, $db ) {
00142         if ( !$res ) {
00143             // Do nothing
00144             return;
00145         } elseif ( is_object( $res ) && $res->numRows() ) {
00146             foreach ( $res as $row ) {
00147                 $this->output( print_r( $row, true ) );
00148             }
00149         } else {
00150             $affected = $db->affectedRows();
00151             $this->output( "Query OK, $affected row(s) affected\n" );
00152         }
00153     }
00154 
00158     public function getDbType() {
00159         return Maintenance::DB_ADMIN;
00160     }
00161 }
00162 
00163 $maintClass = "MwSql";
00164 require_once RUN_MAINTENANCE_IF_MAIN;