/** @var int[] Prior flags member variable values */
private $priorFlags = [];
- /** @var mixed Class name or object With profileIn/profileOut methods */
+ /** @var callable|null */
protected $profiler;
/** @var TransactionProfiler */
protected $trxProfiler;
$this->srvCache = $params['srvCache'] ?? new HashBagOStuff();
- $this->profiler = $params['profiler'];
+ $this->profiler = is_callable( $params['profiler'] ) ? $params['profiler'] : null;
$this->trxProfiler = $params['trxProfiler'];
$this->connLogger = $params['connLogger'];
$this->queryLogger = $params['queryLogger'];
* used to adjust lock timeouts or encoding modes and the like.
* - connLogger: Optional PSR-3 logger interface instance.
* - queryLogger: Optional PSR-3 logger interface instance.
- * - profiler: Optional class name or object with profileIn()/profileOut() methods.
- * These will be called in query(), using a simplified version of the SQL that also
- * includes the agent as a SQL comment.
+ * - profiler : Optional callback that takes a section name argument and returns
+ * a ScopedCallback instance that ends the profile section in its destructor.
+ * These will be called in query(), using a simplified version of the SQL that
+ * also includes the agent as a SQL comment.
* - trxProfiler: Optional TransactionProfiler instance.
* - errorLogger: Optional callback that takes an Exception and logs it.
* - deprecationLogger: Optional callback that takes a string and logs it.
# option is ROLLBACK, since the snapshots would have been released.
$this->trxStatus = self::STATUS_TRX_ERROR;
$this->trxStatusCause =
- $this->makeQueryException( $lastError, $lastErrno, $sql, $fname );
+ $this->getQueryExceptionAndLog( $lastError, $lastErrno, $sql, $fname );
$tempIgnore = false; // cannot recover
$this->trxStatusIgnoredCause = null;
}
$queryProf .= $this->trxShortId ? " [TRX#{$this->trxShortId}]" : "";
$startTime = microtime( true );
- if ( $this->profiler ) {
- $this->profiler->profileIn( $queryProf );
- }
+ $ps = $this->profiler ? ( $this->profiler )( $queryProf ) : null;
$this->affectedRowCount = null;
$ret = $this->doQuery( $commentedSql );
$this->affectedRowCount = $this->affectedRows();
- if ( $this->profiler ) {
- $this->profiler->profileOut( $queryProf );
- }
+ unset( $ps ); // profile out (if set)
$queryRuntime = max( microtime( true ) - $startTime, 0.0 );
- unset( $queryProfSection ); // profile out (if set)
-
if ( $ret !== false ) {
$this->lastPing = $startTime;
if ( $isWrite && $this->trxLevel ) {
if ( $tempIgnore ) {
$this->queryLogger->debug( "SQL ERROR (ignored): $error\n" );
} else {
- $exception = $this->makeQueryException( $error, $errno, $sql, $fname );
+ $exception = $this->getQueryExceptionAndLog( $error, $errno, $sql, $fname );
throw $exception;
}
* @param string $fname
* @return DBError
*/
- private function makeQueryException( $error, $errno, $sql, $fname ) {
+ private function getQueryExceptionAndLog( $error, $errno, $sql, $fname ) {
$sql1line = mb_substr( str_replace( "\n", "\\n", $sql ), 0, 5 * 1024 );
$this->queryLogger->error(
"{fname}\t{db_server}\t{errno}\t{error}\t{sql1line}",
'error' => $error,
'sql1line' => $sql1line,
'fname' => $fname,
+ 'trace' => ( new RuntimeException() )->getTraceAsString()
] )
);
$this->queryLogger->debug( "SQL ERROR: " . $error . "\n" );
return;
}
+ $uniqueIndexes = (array)$uniqueIndexes;
// Single row case
if ( !is_array( reset( $rows ) ) ) {
$rows = [ $rows ];
$this->query( $sql, $fname );
}
- public function upsert( $table, array $rows, array $uniqueIndexes, array $set,
+ public function upsert( $table, array $rows, $uniqueIndexes, array $set,
$fname = __METHOD__
) {
if ( $rows === [] ) {
return true; // nothing to do
}
+ $uniqueIndexes = (array)$uniqueIndexes;
if ( !is_array( reset( $rows ) ) ) {
$rows = [ $rows ];
}