MediaWiki  REL1_23
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                 for ( $i = 0; $i < $lb->getServerCount(); ++$i ) {
00057                     if ( $lb->getServerName( $i ) === $server ) {
00058                         $index = $i;
00059                         break;
00060                     }
00061                 }
00062                 if ( $index === null ) {
00063                     $this->error( "No slave server configured with the name '$server'.", 1 );
00064                 }
00065             }
00066         } else {
00067             $index = DB_MASTER;
00068         }
00069         // Get a DB handle (with this wiki's DB selected) from the appropriate load balancer
00070         $db = $lb->getConnection( $index, array(), $wiki );
00071         if ( $this->hasOption( 'slave' ) && $db->getLBInfo( 'master' ) !== null ) {
00072             $this->error( "The server selected ({$db->getServer()}) is not a slave.", 1 );
00073         }
00074 
00075         if ( $this->hasArg( 0 ) ) {
00076             $file = fopen( $this->getArg( 0 ), 'r' );
00077             if ( !$file ) {
00078                 $this->error( "Unable to open input file", true );
00079             }
00080 
00081             $error = $db->sourceStream( $file, false, array( $this, 'sqlPrintResult' ) );
00082             if ( $error !== true ) {
00083                 $this->error( $error, true );
00084             } else {
00085                 exit( 0 );
00086             }
00087         }
00088 
00089         $useReadline = function_exists( 'readline_add_history' )
00090                 && Maintenance::posix_isatty( 0 /*STDIN*/ );
00091 
00092         if ( $useReadline ) {
00093             global $IP;
00094             $historyFile = isset( $_ENV['HOME'] ) ?
00095                     "{$_ENV['HOME']}/.mwsql_history" : "$IP/maintenance/.mwsql_history";
00096             readline_read_history( $historyFile );
00097         }
00098 
00099         $wholeLine = '';
00100         $newPrompt = '> ';
00101         $prompt = $newPrompt;
00102         while ( ( $line = Maintenance::readconsole( $prompt ) ) !== false ) {
00103             if ( !$line ) {
00104                 # User simply pressed return key
00105                 continue;
00106             }
00107             $done = $db->streamStatementEnd( $wholeLine, $line );
00108 
00109             $wholeLine .= $line;
00110 
00111             if ( !$done ) {
00112                 $wholeLine .= ' ';
00113                 $prompt = '    -> ';
00114                 continue;
00115             }
00116             if ( $useReadline ) {
00117                 # Delimiter is eated by streamStatementEnd, we add it
00118                 # up in the history (bug 37020)
00119                 readline_add_history( $wholeLine . $db->getDelimiter() );
00120                 readline_write_history( $historyFile );
00121             }
00122             try {
00123                 $res = $db->query( $wholeLine );
00124                 $this->sqlPrintResult( $res, $db );
00125                 $prompt = $newPrompt;
00126                 $wholeLine = '';
00127             } catch ( DBQueryError $e ) {
00128                 $doDie = ! Maintenance::posix_isatty( 0 );
00129                 $this->error( $e, $doDie );
00130             }
00131         }
00132         wfWaitForSlaves();
00133     }
00134 
00140     public function sqlPrintResult( $res, $db ) {
00141         if ( !$res ) {
00142             // Do nothing
00143             return;
00144         } elseif ( is_object( $res ) && $res->numRows() ) {
00145             foreach ( $res as $row ) {
00146                 $this->output( print_r( $row, true ) );
00147             }
00148         } else {
00149             $affected = $db->affectedRows();
00150             $this->output( "Query OK, $affected row(s) affected\n" );
00151         }
00152     }
00153 
00157     public function getDbType() {
00158         return Maintenance::DB_ADMIN;
00159     }
00160 }
00161 
00162 $maintClass = "MwSql";
00163 require_once RUN_MAINTENANCE_IF_MAIN;