@@ -79,6 +79,9 @@ class Connection extends \Doctrine\DBAL\Connection {
7979 /** @var DbDataCollector|null */
8080 protected $ dbDataCollector = null ;
8181
82+ protected bool $ logDbException = false ;
83+ private ?array $ transactionBacktrace = null ;
84+
8285 protected bool $ logRequestId ;
8386 protected string $ requestId ;
8487
@@ -110,6 +113,7 @@ public function __construct(
110113 $ this ->logger = \OC ::$ server ->get (LoggerInterface::class);
111114
112115 $ this ->logRequestId = $ this ->systemConfig ->getValue ('db.log_request_id ' , false );
116+ $ this ->logDbException = $ this ->systemConfig ->getValue ('db.log_exceptions ' , false );
113117 $ this ->requestId = Server::get (IRequestId::class)->getId ();
114118
115119 /** @var \OCP\Profiler\IProfiler */
@@ -263,7 +267,12 @@ public function executeQuery(string $sql, array $params = [], $types = [], Query
263267 $ sql = $ this ->finishQuery ($ sql );
264268 $ this ->queriesExecuted ++;
265269 $ this ->logQueryToFile ($ sql );
266- return parent ::executeQuery ($ sql , $ params , $ types , $ qcp );
270+ try {
271+ return parent ::executeQuery ($ sql , $ params , $ types , $ qcp );
272+ } catch (\Exception $ e ) {
273+ $ this ->logDatabaseException ($ e );
274+ throw $ e ;
275+ }
267276 }
268277
269278 /**
@@ -294,7 +303,12 @@ public function executeStatement($sql, array $params = [], array $types = []): i
294303 $ sql = $ this ->finishQuery ($ sql );
295304 $ this ->queriesExecuted ++;
296305 $ this ->logQueryToFile ($ sql );
297- return (int )parent ::executeStatement ($ sql , $ params , $ types );
306+ try {
307+ return (int )parent ::executeStatement ($ sql , $ params , $ types );
308+ } catch (\Exception $ e ) {
309+ $ this ->logDatabaseException ($ e );
310+ throw $ e ;
311+ }
298312 }
299313
300314 protected function logQueryToFile (string $ sql ): void {
@@ -356,11 +370,21 @@ public function realLastInsertId($seqName = null) {
356370 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
357371 */
358372 public function insertIfNotExist ($ table , $ input , array $ compare = null ) {
359- return $ this ->adapter ->insertIfNotExist ($ table , $ input , $ compare );
373+ try {
374+ return $ this ->adapter ->insertIfNotExist ($ table , $ input , $ compare );
375+ } catch (\Exception $ e ) {
376+ $ this ->logDatabaseException ($ e );
377+ throw $ e ;
378+ }
360379 }
361380
362381 public function insertIgnoreConflict (string $ table , array $ values ) : int {
363- return $ this ->adapter ->insertIgnoreConflict ($ table , $ values );
382+ try {
383+ return $ this ->adapter ->insertIgnoreConflict ($ table , $ values );
384+ } catch (\Exception $ e ) {
385+ $ this ->logDatabaseException ($ e );
386+ throw $ e ;
387+ }
364388 }
365389
366390 private function getType ($ value ) {
@@ -616,4 +640,43 @@ private function getMigrator() {
616640 return new Migrator ($ this , $ config , $ dispatcher );
617641 }
618642 }
643+
644+ public function beginTransaction () {
645+ if (!$ this ->inTransaction ()) {
646+ $ this ->transactionBacktrace = debug_backtrace (DEBUG_BACKTRACE_IGNORE_ARGS );
647+ }
648+ return parent ::beginTransaction ();
649+ }
650+
651+ public function commit () {
652+ $ result = parent ::commit ();
653+ if ($ this ->getTransactionNestingLevel () === 0 ) {
654+ $ this ->transactionBacktrace = null ;
655+ }
656+ return $ result ;
657+ }
658+
659+ public function rollBack () {
660+ $ result = parent ::rollBack ();
661+ if ($ this ->getTransactionNestingLevel () === 0 ) {
662+ $ this ->transactionBacktrace = null ;
663+ }
664+ return $ result ;
665+ }
666+
667+ /**
668+ * Log a database exception if enabled
669+ *
670+ * @param \Exception $exception
671+ * @return void
672+ */
673+ public function logDatabaseException (\Exception $ exception ): void {
674+ if ($ this ->logDbException ) {
675+ if ($ exception instanceof Exception \UniqueConstraintViolationException) {
676+ $ this ->logger ->info ($ exception ->getMessage (), ['exception ' => $ exception , 'transaction ' => $ this ->transactionBacktrace ]);
677+ } else {
678+ $ this ->logger ->error ($ exception ->getMessage (), ['exception ' => $ exception , 'transaction ' => $ this ->transactionBacktrace ]);
679+ }
680+ }
681+ }
619682}
0 commit comments