MediaWiki
REL1_24
|
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;