X-Git-Url: https://git.cyclocoop.org/%7B%24admin_url%7Dmembres/modifier.php?a=blobdiff_plain;f=includes%2Fdb%2FDatabase.php;h=0a2e22199343e56a24877e318844a8985dde39e7;hb=3c16633c4f60d43711b575f4a904d5b0dbf6aa67;hp=e95f134c01685f81e87b5a73da454849c62a732b;hpb=ff05579d1c7fcf9d449bdd474b48338dd58b1c5d;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/db/Database.php b/includes/db/Database.php index e95f134c01..0a2e221993 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -814,6 +814,10 @@ abstract class DatabaseBase implements IDatabase { if ( $user ) { $this->open( $server, $user, $password, $dbName ); } + + $isMaster = !is_null( $this->getLBInfo( 'master' ) ); + $trxProf = Profiler::instance()->getTransactionProfiler(); + $trxProf->recordConnection( $this->mServer, $this->mDBname, $isMaster ); } /** @@ -1079,8 +1083,11 @@ abstract class DatabaseBase implements IDatabase { $isWriteQuery = $this->isWriteQuery( $sql ); if ( $isWriteQuery ) { + if ( !$this->mDoneWrites ) { + wfDebug( __METHOD__ . ': Writes done: ' . + DatabaseBase::generalizeSQL( $sql ) . "\n" ); + } # Set a flag indicating that writes have been done - wfDebug( __METHOD__ . ': Writes done: ' . DatabaseBase::generalizeSQL( $sql ) . "\n" ); $this->mDoneWrites = microtime( true ); } @@ -1114,24 +1121,21 @@ abstract class DatabaseBase implements IDatabase { $this->mServer, $this->mDBname, $this->mTrxShortId ); } - $queryProf = ''; - $totalProf = ''; $isMaster = !is_null( $this->getLBInfo( 'master' ) ); + # generalizeSQL will probably cut down the query to reasonable + # logging size most of the time. The substr is really just a sanity check. + if ( $isMaster ) { + $queryProf = 'query-m: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 ); + $totalProf = 'DatabaseBase::query-master'; + } else { + $queryProf = 'query: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 ); + $totalProf = 'DatabaseBase::query'; + } + # Include query transaction state + $queryProf .= $this->mTrxShortId ? " [TRX#{$this->mTrxShortId}]" : ""; $profiler = Profiler::instance(); if ( !$profiler instanceof ProfilerStub ) { - # generalizeSQL will probably cut down the query to reasonable - # logging size most of the time. The substr is really just a sanity check. - if ( $isMaster ) { - $queryProf = 'query-m: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 ); - $totalProf = 'DatabaseBase::query-master'; - } else { - $queryProf = 'query: ' . substr( DatabaseBase::generalizeSQL( $sql ), 0, 255 ); - $totalProf = 'DatabaseBase::query'; - } - # Include query transaction state - $queryProf .= $this->mTrxShortId ? " [TRX#{$this->mTrxShortId}]" : ""; - $totalProfSection = $profiler->scopedProfileIn( $totalProf ); $queryProfSection = $profiler->scopedProfileIn( $queryProf ); } @@ -1155,21 +1159,12 @@ abstract class DatabaseBase implements IDatabase { throw new DBUnexpectedError( $this, "DB connection was already closed." ); } - # Log the query time and feed it into the DB trx profiler - if ( $queryProf != '' ) { - $that = $this; - $queryStartTime = microtime( true ); - $queryProfile = new ScopedCallback( - function () use ( $that, $queryStartTime, $queryProf, $isMaster ) { - $n = $that->affectedRows(); - $trxProf = Profiler::instance()->getTransactionProfiler(); - $trxProf->recordQueryCompletion( $queryProf, $queryStartTime, $isMaster, $n ); - } - ); - } - # Do the query and handle errors + $startTime = microtime( true ); $ret = $this->doQuery( $commentedSql ); + # Log the query time and feed it into the DB trx profiler + $profiler->getTransactionProfiler()->recordQueryCompletion( + $queryProf, $startTime, $isWriteQuery, $this->affectedRows() ); MWDebug::queryTime( $queryId ); @@ -1196,7 +1191,11 @@ abstract class DatabaseBase implements IDatabase { $this->reportQueryError( $lastError, $lastErrno, $sql, $fname, $tempIgnore ); } else { # Should be safe to silently retry (no trx and thus no callbacks) + $startTime = microtime( true ); $ret = $this->doQuery( $commentedSql ); + # Log the query time and feed it into the DB trx profiler + $profiler->getTransactionProfiler()->recordQueryCompletion( + $queryProf, $startTime, $isWriteQuery, $this->affectedRows() ); } } else { wfDebug( "Failed\n" ); @@ -1204,7 +1203,8 @@ abstract class DatabaseBase implements IDatabase { } if ( false === $ret ) { - $this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore ); + $this->reportQueryError( + $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore ); } $res = $this->resultObject( $ret ); @@ -1383,9 +1383,13 @@ abstract class DatabaseBase implements IDatabase { * * @return bool|mixed The value from the field, or false on failure. */ - public function selectField( $table, $var, $cond = '', $fname = __METHOD__, - $options = array() + public function selectField( + $table, $var, $cond = '', $fname = __METHOD__, $options = array() ) { + if ( $var === '*' ) { // sanity + throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" ); + } + if ( !is_array( $options ) ) { $options = array( $options ); } @@ -1393,7 +1397,6 @@ abstract class DatabaseBase implements IDatabase { $options['LIMIT'] = 1; $res = $this->select( $table, $var, $cond, $fname, $options ); - if ( $res === false || !$this->numRows( $res ) ) { return false; } @@ -1407,6 +1410,48 @@ abstract class DatabaseBase implements IDatabase { } } + /** + * A SELECT wrapper which returns a list of single field values from result rows. + * + * Usually throws a DBQueryError on failure. If errors are explicitly + * ignored, returns false on failure. + * + * If no result rows are returned from the query, false is returned. + * + * @param string|array $table Table name. See DatabaseBase::select() for details. + * @param string $var The field name to select. This must be a valid SQL + * fragment: do not use unvalidated user input. + * @param string|array $cond The condition array. See DatabaseBase::select() for details. + * @param string $fname The function name of the caller. + * @param string|array $options The query options. See DatabaseBase::select() for details. + * + * @return bool|array The values from the field, or false on failure + * @since 1.25 + */ + public function selectFieldValues( + $table, $var, $cond = '', $fname = __METHOD__, $options = array() + ) { + if ( $var === '*' ) { // sanity + throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" ); + } + + if ( !is_array( $options ) ) { + $options = array( $options ); + } + + $res = $this->select( $table, $var, $cond, $fname, $options ); + if ( $res === false ) { + return false; + } + + $values = array(); + foreach ( $res as $row ) { + $values[] = $row->$var; + } + + return $values; + } + /** * Returns an optional USE INDEX clause to go after the table, and a * string to go at the end of the query. @@ -1593,9 +1638,10 @@ abstract class DatabaseBase implements IDatabase { * - If the value of such an array element is a scalar (such as a * string), it will be treated as data and thus quoted appropriately. * If it is null, an IS NULL clause will be added. - * - If the value is an array, an IN(...) clause will be constructed, - * such that the field name may match any of the elements in the - * array. The elements of the array will be quoted. + * - If the value is an array, an IN (...) clause will be constructed + * from its non-null elements, and an IS NULL clause will be added + * if null is present, such that the field may match any of the + * elements in the array. The non-null elements will be quoted. * * Note that expressions are often DBMS-dependent in their syntax. * DBMS-independent wrappers are provided for constructing several types of