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