Пример #1
0
 /**
  * Usually aborts on failure
  * If errors are explicitly ignored, returns success
  */
 function query($sql, $fname = '', $tempIgnore = false)
 {
     global $wgProfiling;
     if ($wgProfiling) {
         # generalizeSQL will probably cut down the query to reasonable
         # logging size most of the time. The substr is really just a sanity check.
         # Who's been wasting my precious column space? -- TS
         #$profName = 'query: ' . $fname . ' ' . substr( Database::generalizeSQL( $sql ), 0, 255 );
         if (is_null($this->getLBInfo('master'))) {
             $queryProf = 'query: ' . substr(Database::generalizeSQL($sql), 0, 255);
             $totalProf = 'Database::query';
         } else {
             $queryProf = 'query-m: ' . substr(Database::generalizeSQL($sql), 0, 255);
             $totalProf = 'Database::query-master';
         }
         wfProfileIn($totalProf);
         wfProfileIn($queryProf);
     }
     $this->mLastQuery = $sql;
     # Add a comment for easy SHOW PROCESSLIST interpretation
     if ($fname) {
         $commentedSql = preg_replace("/\\s/", " /* {$fname} */ ", $sql, 1);
     } else {
         $commentedSql = $sql;
     }
     # If DBO_TRX is set, start a transaction
     if ($this->mFlags & DBO_TRX && !$this->trxLevel() && $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK') {
         $this->begin();
     }
     if ($this->debug()) {
         $sqlx = substr($commentedSql, 0, 500);
         $sqlx = strtr($sqlx, "\t\n", '  ');
         wfDebug("SQL: {$sqlx}\n");
     }
     # Do the query and handle errors
     $ret = $this->doQuery($commentedSql);
     # Try reconnecting if the connection was lost
     if (false === $ret && ($this->lastErrno() == 2013 || $this->lastErrno() == 2006)) {
         # Transaction is gone, like it or not
         $this->mTrxLevel = 0;
         wfDebug("Connection lost, reconnecting...\n");
         if ($this->ping()) {
             wfDebug("Reconnected\n");
             $ret = $this->doQuery($commentedSql);
         } else {
             wfDebug("Failed\n");
         }
     }
     if (false === $ret) {
         $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore);
     }
     if ($wgProfiling) {
         wfProfileOut($queryProf);
         wfProfileOut($totalProf);
     }
     return $ret;
 }
Пример #2
0
 /**
  * Usually aborts on failure.  If errors are explicitly ignored, returns success.
  *
  * @param  $sql        String: SQL query
  * @param  $fname      String: Name of the calling function, for profiling/SHOW PROCESSLIST 
  *     comment (you can use __METHOD__ or add some extra info)
  * @param  $tempIgnore Bool:   Whether to avoid throwing an exception on errors... 
  *     maybe best to catch the exception instead?
  * @return true for a successful write query, ResultWrapper object for a successful read query, 
  *     or false on failure if $tempIgnore set
  * @throws DBQueryError Thrown when the database returns an error of any kind
  */
 public function query($sql, $fname = '', $tempIgnore = false)
 {
     global $wgProfiling;
     // XXADDED by Reuben to log slower queries
     global $wgCommandLineMode;
     $LOG_SLOW = 30;
     $startTime = microtime(true);
     if ($wgProfiling) {
         # generalizeSQL will probably cut down the query to reasonable
         # logging size most of the time. The substr is really just a sanity check.
         # Who's been wasting my precious column space? -- TS
         #$profName = 'query: ' . $fname . ' ' . substr( Database::generalizeSQL( $sql ), 0, 255 );
         if (is_null($this->getLBInfo('master'))) {
             $queryProf = 'query: ' . substr(Database::generalizeSQL($sql), 0, 255);
             $totalProf = 'Database::query';
         } else {
             $queryProf = 'query-m: ' . substr(Database::generalizeSQL($sql), 0, 255);
             $totalProf = 'Database::query-master';
         }
         wfProfileIn($totalProf);
         wfProfileIn($queryProf);
     }
     $this->mLastQuery = $sql;
     # Add a comment for easy SHOW PROCESSLIST interpretation
     #if ( $fname ) {
     global $wgUser;
     if (is_object($wgUser) && !$wgUser instanceof StubObject) {
         $userName = $wgUser->getName();
         if (mb_strlen($userName) > 15) {
             $userName = mb_substr($userName, 0, 15) . '...';
         }
         $userName = str_replace('/', '', $userName);
     } else {
         $userName = '';
     }
     $commentedSql = preg_replace('/\\s/', " /* {$fname} {$userName} */ ", $sql, 1);
     #} else {
     #	$commentedSql = $sql;
     #}
     # If DBO_TRX is set, start a transaction
     if ($this->mFlags & DBO_TRX && !$this->trxLevel() && $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK') {
         // avoid establishing transactions for SHOW and SET statements too -
         // that would delay transaction initializations to once connection
         // is really used by application
         $sqlstart = substr($sql, 0, 10);
         // very much worth it, benchmark certified(tm)
         if (strpos($sqlstart, "SHOW ") !== 0 and strpos($sqlstart, "SET ") !== 0) {
             $this->begin();
         }
     }
     if ($this->debug()) {
         $sqlx = substr($commentedSql, 0, 500);
         $sqlx = strtr($sqlx, "\t\n", '  ');
         wfDebug("SQL: {$sqlx}\n");
     }
     # Do the query and handle errors
     $ret = $this->doQuery($commentedSql);
     # Try reconnecting if the connection was lost
     if (false === $ret && ($this->lastErrno() == 2013 || $this->lastErrno() == 2006)) {
         # Transaction is gone, like it or not
         $this->mTrxLevel = 0;
         wfDebug("Connection lost, reconnecting...\n");
         if ($this->ping()) {
             wfDebug("Reconnected\n");
             $sqlx = substr($commentedSql, 0, 500);
             $sqlx = strtr($sqlx, "\t\n", '  ');
             global $wgRequestTime;
             $elapsed = round(microtime(true) - $wgRequestTime, 3);
             wfLogDBError("Connection lost and reconnected after {$elapsed}s, query: {$sqlx}\n");
             $ret = $this->doQuery($commentedSql);
         } else {
             wfDebug("Failed\n");
         }
         // XXCHANGED -- Reuben hack: we've found that our database drivers timeout
         // after 10 minutes of inactivity in a long-running script. We've found that
         // the mysql_ping() that's called right now doesn't work to reconnect, but
         // that closing and re-opening the connection usually works.
         if (false === $ret && $this->lastErrno() == 2006) {
             error_log('Encountered Reuben MySQL error 2006 DB hack. Re-connecting to server ' . $this->mServer);
             @$this->close();
             $this->mConn = null;
             $this->open($this->mServer, $this->mUser, $this->mPassword, $this->mDBname);
             $this->ping();
             $ret = $this->doQuery($commentedSql);
         }
     }
     if (false === $ret) {
         $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore);
     }
     if (!defined('IS_PROD_EN_SITE')) {
         define('IS_PROD_EN_SITE', true);
     }
     if (!$wgCommandLineMode && IS_PROD_EN_SITE && $LOG_SLOW > 0) {
         $total = microtime(true) - $startTime;
         if ($total >= $LOG_SLOW) {
             $prof = substr($sql, 0, 1000);
             $totalStr = sprintf('%.2f', $total) . 's';
             $backtrace = wfBacktrace();
             $hostname = gethostname();
             if (strpos($hostname, 'spare') === false) {
                 $msg = "This query took {$totalStr}:<br>\n<br>\n{$prof}<br>\n<br>\n{$backtrace}<br>\nGenerated on {$hostname}<br>\n";
                 $headers = 'MIME-Version: 1.0' . "\r\n";
                 $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
                 mail('reuben@wikihow.com,jordan@wikihow.com', 'Slow query: ' . $totalStr, $msg, $headers);
             }
         }
     }
     if ($wgProfiling) {
         wfProfileOut($queryProf);
         wfProfileOut($totalProf);
     }
     return $this->resultObject($ret);
 }
Пример #3
0
 /**
  * Usually aborts on failure
  * If errors are explicitly ignored, returns success
  */
 function query($sql, $fname = '', $tempIgnore = false)
 {
     global $wgProfiling, $wgCommandLineMode;
     if ($wgProfiling) {
         # generalizeSQL will probably cut down the query to reasonable
         # logging size most of the time. The substr is really just a sanity check.
         $profName = 'query: ' . $fname . ' ' . substr(Database::generalizeSQL($sql), 0, 255);
         wfProfileIn('Database::query');
         wfProfileIn($profName);
     }
     $this->mLastQuery = $sql;
     # Add a comment for easy SHOW PROCESSLIST interpretation
     if ($fname) {
         $commentedSql = "/* {$fname} */ {$sql}";
     } else {
         $commentedSql = $sql;
     }
     # If DBO_TRX is set, start a transaction
     if ($this->mFlags & DBO_TRX && !$this->trxLevel() && $sql != 'BEGIN') {
         $this->begin();
     }
     if ($this->debug()) {
         $sqlx = substr($commentedSql, 0, 500);
         $sqlx = strtr($sqlx, "\t\n", '  ');
         wfDebug("SQL: {$sqlx}\n");
     }
     # Do the query and handle errors
     $ret = $this->doQuery($commentedSql);
     # Try reconnecting if the connection was lost
     if (false === $ret && ($this->lastErrno() == 2013 || $this->lastErrno() == 2006)) {
         # Transaction is gone, like it or not
         $this->mTrxLevel = 0;
         wfDebug("Connection lost, reconnecting...\n");
         if ($this->ping()) {
             wfDebug("Reconnected\n");
             $ret = $this->doQuery($commentedSql);
         } else {
             wfDebug("Failed\n");
         }
     }
     if (false === $ret) {
         $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore);
     }
     if ($wgProfiling) {
         wfProfileOut($profName);
         wfProfileOut('Database::query');
     }
     return $ret;
 }
Пример #4
0
 /**
  * Usually aborts on failure.  If errors are explicitly ignored, returns success.
  *
  * @param  $sql        String: SQL query
  * @param  $fname      String: Name of the calling function, for profiling/SHOW PROCESSLIST 
  *     comment (you can use __METHOD__ or add some extra info)
  * @param  $tempIgnore Bool:   Whether to avoid throwing an exception on errors... 
  *     maybe best to catch the exception instead?
  * @return true for a successful write query, ResultWrapper object for a successful read query, 
  *     or false on failure if $tempIgnore set
  * @throws DBQueryError Thrown when the database returns an error of any kind
  */
 public function query($sql, $fname = '', $tempIgnore = false)
 {
     global $wgProfiling;
     if ($wgProfiling) {
         # generalizeSQL will probably cut down the query to reasonable
         # logging size most of the time. The substr is really just a sanity check.
         # Who's been wasting my precious column space? -- TS
         #$profName = 'query: ' . $fname . ' ' . substr( Database::generalizeSQL( $sql ), 0, 255 );
         if (is_null($this->getLBInfo('master'))) {
             $queryProf = 'query: ' . substr(Database::generalizeSQL($sql), 0, 255);
             $totalProf = 'Database::query';
         } else {
             $queryProf = 'query-m: ' . substr(Database::generalizeSQL($sql), 0, 255);
             $totalProf = 'Database::query-master';
         }
         wfProfileIn($totalProf);
         wfProfileIn($queryProf);
     }
     $this->mLastQuery = $sql;
     # Add a comment for easy SHOW PROCESSLIST interpretation
     #if ( $fname ) {
     global $wgUser;
     if (is_object($wgUser) && !$wgUser instanceof StubObject) {
         $userName = $wgUser->getName();
         if (mb_strlen($userName) > 15) {
             $userName = mb_substr($userName, 0, 15) . '...';
         }
         $userName = str_replace('/', '', $userName);
     } else {
         $userName = '';
     }
     $commentedSql = preg_replace('/\\s/', " /* {$fname} {$userName} */ ", $sql, 1);
     #} else {
     #	$commentedSql = $sql;
     #}
     # If DBO_TRX is set, start a transaction
     if ($this->mFlags & DBO_TRX && !$this->trxLevel() && $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK') {
         // avoid establishing transactions for SHOW and SET statements too -
         // that would delay transaction initializations to once connection
         // is really used by application
         $sqlstart = substr($sql, 0, 10);
         // very much worth it, benchmark certified(tm)
         if (strpos($sqlstart, "SHOW ") !== 0 and strpos($sqlstart, "SET ") !== 0) {
             $this->begin();
         }
     }
     if ($this->debug()) {
         $sqlx = substr($commentedSql, 0, 500);
         $sqlx = strtr($sqlx, "\t\n", '  ');
         wfDebug("SQL: {$sqlx}\n");
     }
     # Do the query and handle errors
     $ret = $this->doQuery($commentedSql);
     # Try reconnecting if the connection was lost
     if (false === $ret && ($this->lastErrno() == 2013 || $this->lastErrno() == 2006)) {
         # Transaction is gone, like it or not
         $this->mTrxLevel = 0;
         wfDebug("Connection lost, reconnecting...\n");
         if ($this->ping()) {
             wfDebug("Reconnected\n");
             $sqlx = substr($commentedSql, 0, 500);
             $sqlx = strtr($sqlx, "\t\n", '  ');
             global $wgRequestTime;
             $elapsed = round(microtime(true) - $wgRequestTime, 3);
             wfLogDBError("Connection lost and reconnected after {$elapsed}s, query: {$sqlx}\n");
             $ret = $this->doQuery($commentedSql);
         } else {
             wfDebug("Failed\n");
         }
     }
     if (false === $ret) {
         $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore);
     }
     if ($wgProfiling) {
         wfProfileOut($queryProf);
         wfProfileOut($totalProf);
     }
     return $this->resultObject($ret);
 }
Пример #5
0
 /**
  * Usually aborts on failure
  * If errors are explicitly ignored, returns success
  */
 function query($sql, $fname = '', $tempIgnore = false)
 {
     global $wgProfiling, $wgCommandLineMode;
     if (wfReadOnly()) {
         # This is a quick check for the most common kinds of write query used
         # in MediaWiki, to provide extra safety in addition to UI-level checks.
         # It is not intended to prevent every conceivable write query, or even
         # to handle such queries gracefully.
         if (preg_match('/^(update|insert|replace|delete)/i', $sql)) {
             wfDebug("Write query from {$fname} blocked\n");
             return false;
         }
     }
     if ($wgProfiling) {
         # generalizeSQL will probably cut down the query to reasonable
         # logging size most of the time. The substr is really just a sanity check.
         $profName = 'query: ' . $fname . ' ' . substr(Database::generalizeSQL($sql), 0, 255);
         wfProfileIn('Database::query');
         wfProfileIn($profName);
     }
     $this->mLastQuery = $sql;
     # Add a comment for easy SHOW PROCESSLIST interpretation
     if ($fname) {
         $commentedSql = "/* {$fname} */ {$sql}";
     } else {
         $commentedSql = $sql;
     }
     # If DBO_TRX is set, start a transaction
     if ($this->mFlags & DBO_TRX && !$this->trxLevel() && $sql != 'BEGIN') {
         $this->begin();
     }
     if ($this->debug()) {
         $sqlx = substr($commentedSql, 0, 500);
         $sqlx = strtr($sqlx, "\t\n", '  ');
         wfDebug("SQL: {$sqlx}\n");
     }
     # Do the query and handle errors
     $ret = $this->doQuery($commentedSql);
     # Try reconnecting if the connection was lost
     if (false === $ret && ($this->lastErrno() == 2013 || $this->lastErrno() == 2006)) {
         # Transaction is gone, like it or not
         $this->mTrxLevel = 0;
         wfDebug("Connection lost, reconnecting...\n");
         if ($this->ping()) {
             wfDebug("Reconnected\n");
             $ret = $this->doQuery($commentedSql);
         } else {
             wfDebug("Failed\n");
         }
     }
     if (false === $ret) {
         $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore);
     }
     if ($wgProfiling) {
         wfProfileOut($profName);
         wfProfileOut('Database::query');
     }
     return $ret;
 }