Passed
Push — master ( 8cab1d...e18f97 )
by Julius
40:17 queued 25:44
created

DbalException::isRetryable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright 2021 Christoph Wurst <[email protected]>
7
 *
8
 * @author Christoph Wurst <[email protected]>
9
 * @author Daniel Kesselberg <[email protected]>
10
 *
11
 * @license GNU AGPL version 3 or any later version
12
 *
13
 * This program is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License as
15
 * published by the Free Software Foundation, either version 3 of the
16
 * License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License
24
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 */
27
namespace OC\DB\Exceptions;
28
29
use Doctrine\DBAL\ConnectionException;
30
use Doctrine\DBAL\Exception\ConstraintViolationException;
31
use Doctrine\DBAL\Exception\DatabaseObjectExistsException;
32
use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException;
33
use Doctrine\DBAL\Exception\DeadlockException;
34
use Doctrine\DBAL\Exception\DriverException;
35
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
36
use Doctrine\DBAL\Exception\InvalidArgumentException;
37
use Doctrine\DBAL\Exception\InvalidFieldNameException;
38
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
39
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
40
use Doctrine\DBAL\Exception\RetryableException;
41
use Doctrine\DBAL\Exception\ServerException;
42
use Doctrine\DBAL\Exception\SyntaxErrorException;
43
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
44
use OCP\DB\Exception;
45
46
/**
47
 * Wrapper around the raw dbal exception, so we can pass it to apps that catch
48
 * our OCP db exception
49
 *
50
 * @psalm-immutable
51
 */
52
class DbalException extends Exception {
53
	/** @var \Doctrine\DBAL\Exception */
54
	private $original;
55
56
	/**
57
	 * @param \Doctrine\DBAL\Exception $original
58
	 * @param int $code
59
	 * @param string $message
60
	 */
61
	private function __construct(\Doctrine\DBAL\Exception $original, int $code, string $message) {
62
		parent::__construct(
63
			$message,
64
			$code,
65
			$original
66
		);
67
		$this->original = $original;
68
	}
69
70
	public static function wrap(\Doctrine\DBAL\Exception $original, string $message = ''): self {
71
		return new self(
72
			$original,
73
			is_int($original->getCode()) ? $original->getCode() : 0,
74
			empty($message) ? $original->getMessage() : $message
75
		);
76
	}
77
78
	public function isRetryable(): bool {
79
		return $this->original instanceof RetryableException;
80
	}
81
82
	public function getReason(): ?int {
83
		/**
84
		 * Constraint errors
85
		 */
86
		if ($this->original instanceof ForeignKeyConstraintViolationException) {
87
			return parent::REASON_FOREIGN_KEY_VIOLATION;
88
		}
89
		if ($this->original instanceof NotNullConstraintViolationException) {
90
			return parent::REASON_NOT_NULL_CONSTRAINT_VIOLATION;
91
		}
92
		if ($this->original instanceof UniqueConstraintViolationException) {
93
			return parent::REASON_UNIQUE_CONSTRAINT_VIOLATION;
94
		}
95
		// The base exception comes last
96
		if ($this->original instanceof ConstraintViolationException) {
97
			return parent::REASON_CONSTRAINT_VIOLATION;
98
		}
99
100
		/**
101
		 * Other server errors
102
		 */
103
		if ($this->original instanceof DatabaseObjectExistsException) {
104
			return parent::REASON_DATABASE_OBJECT_EXISTS;
105
		}
106
		if ($this->original instanceof DatabaseObjectNotFoundException) {
107
			return parent::REASON_DATABASE_OBJECT_NOT_FOUND;
108
		}
109
		if ($this->original instanceof DeadlockException) {
110
			return parent::REASON_DEADLOCK;
111
		}
112
		if ($this->original instanceof InvalidFieldNameException) {
113
			return parent::REASON_INVALID_FIELD_NAME;
114
		}
115
		if ($this->original instanceof NonUniqueFieldNameException) {
116
			return parent::REASON_NON_UNIQUE_FIELD_NAME;
117
		}
118
		if ($this->original instanceof SyntaxErrorException) {
119
			return parent::REASON_SYNTAX_ERROR;
120
		}
121
		// The base server exception class comes last
122
		if ($this->original instanceof ServerException) {
123
			return parent::REASON_SERVER;
124
		}
125
126
		/**
127
		 * Generic errors
128
		 */
129
		if ($this->original instanceof ConnectionException) {
130
			return parent::REASON_CONNECTION_LOST;
131
		}
132
		if ($this->original instanceof InvalidArgumentException) {
133
			return parent::REASON_INVALID_ARGUMENT;
134
		}
135
		if ($this->original instanceof DriverException) {
136
			return parent::REASON_DRIVER;
137
		}
138
139
		return null;
140
	}
141
}
142