Failed Conditions
Pull Request — develop (#3367)
by Benjamin
61:25
created

OCI8Connection::exceptionFromErrorInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Doctrine\DBAL\Driver\OCI8;
4
5
use Doctrine\DBAL\Driver\Connection;
6
use Doctrine\DBAL\Driver\DriverException;
7
use Doctrine\DBAL\Driver\ResultStatement;
8
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
9
use Doctrine\DBAL\Driver\Statement as DriverStatement;
10
use UnexpectedValueException;
11
use const OCI_COMMIT_ON_SUCCESS;
12
use const OCI_DEFAULT;
13
use const OCI_NO_AUTO_COMMIT;
14
use function addcslashes;
15
use function define;
16
use function defined;
17
use function oci_commit;
18
use function oci_connect;
19
use function oci_error;
20
use function oci_pconnect;
21
use function oci_rollback;
22
use function oci_server_version;
23
use function preg_match;
24
use function sprintf;
25
use function str_replace;
26
27
/**
28
 * OCI8 implementation of the Connection interface.
29
 */
30
class OCI8Connection implements Connection, ServerInfoAwareConnection
31
{
32
    /** @var resource */
33
    protected $dbh;
34
35
    /** @var int */
36
    protected $executeMode = OCI_COMMIT_ON_SUCCESS;
37
38
    /**
39
     * Creates a Connection to an Oracle Database using oci8 extension.
40
     *
41
     * @param string      $username
42
     * @param string      $password
43
     * @param string      $db
44
     * @param string|null $charset
45
     * @param int         $sessionMode
46
     * @param bool        $persistent
47
     *
48
     * @throws DriverException
49
     */
50
    public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT, $persistent = false)
51
    {
52 79
        if (! defined('OCI_NO_AUTO_COMMIT')) {
53
            define('OCI_NO_AUTO_COMMIT', 0);
54 79
        }
55
56
        $this->dbh = $persistent
57
            ? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
58 79
            : @oci_connect($username, $password, $db, $charset, $sessionMode);
59
60 79
        if (! $this->dbh) {
61
            throw self::exceptionFromErrorInfo(oci_error());
62 79
        }
63 3
    }
64
65 76
    /**
66
     * {@inheritdoc}
67
     *
68
     * @throws UnexpectedValueException If the version string returned by the database server
69
     *                                  does not contain a parsable version number.
70
     */
71
    public function getServerVersion()
72
    {
73
        if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', oci_server_version($this->dbh), $version)) {
74
            throw new UnexpectedValueException(
75
                sprintf(
76
                    'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' .
77
                    'Please report this database version string to the Doctrine team.',
78
                    oci_server_version($this->dbh)
79
                )
80
            );
81
        }
82
83
        return $version[1];
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function requiresQueryForServerVersion()
90
    {
91 1
        return false;
92
    }
93 1
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function prepare(string $sql) : DriverStatement
98
    {
99 261
        return new OCI8Statement($this->dbh, $sql, $this);
100
    }
101 261
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function query(string $sql) : ResultStatement
106
    {
107 171
        $stmt = $this->prepare($sql);
108
        $stmt->execute();
109 171
110 171
        return $stmt;
111
    }
112 168
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function quote(string $value) : string
117
    {
118 4
        $value = str_replace("'", "''", $value);
119
120 4
        return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
121 2
    }
122
123 3
    /**
124
     * {@inheritdoc}
125 3
     */
126
    public function exec(string $statement) : int
127
    {
128
        $stmt = $this->prepare($statement);
129
        $stmt->execute();
130
131 172
        return $stmt->rowCount();
132
    }
133 172
134 172
    /**
135
     * {@inheritdoc}
136 158
     */
137
    public function lastInsertId(?string $name = null) : string
138
    {
139
        if ($name === null) {
140
            throw new DriverException('A sequence name must be provided.');
141
        }
142 4
143
        $sql    = 'SELECT ' . $name . '.CURRVAL FROM DUAL';
144 4
        $stmt   = $this->query($sql);
145 1
        $result = $stmt->fetchColumn();
146
147
        if ($result === false) {
148 3
            throw new DriverException('lastInsertId failed: Query was executed but no result was returned.');
149 3
        }
150 3
151
        return $result;
152 3
    }
153
154
    /**
155
     * Returns the current execution mode.
156 3
     *
157
     * @return int
158
     */
159
    public function getExecuteMode()
160
    {
161
        return $this->executeMode;
162
    }
163
164 256
    /**
165
     * {@inheritdoc}
166 256
     */
167
    public function beginTransaction() : void
168
    {
169
        $this->executeMode = OCI_NO_AUTO_COMMIT;
170
    }
171
172 15
    /**
173
     * {@inheritdoc}
174 15
     */
175
    public function commit() : void
176 15
    {
177
        if (! oci_commit($this->dbh)) {
178
            throw self::exceptionFromErrorInfo($this->errorInfo());
179
        }
180
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
181
    }
182 7
183
    /**
184 7
     * {@inheritdoc}
185
     */
186
    public function rollBack() : void
187 7
    {
188
        if (! oci_rollback($this->dbh)) {
189 7
            throw self::exceptionFromErrorInfo($this->errorInfo());
190
        }
191
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
192
    }
193
194
    /**
195 9
     * {@inheritdoc}
196
     */
197 9
    public function errorCode()
198
    {
199
        $error = oci_error($this->dbh);
200 9
        if ($error !== false) {
201
            $error = $error['code'];
202 9
        }
203
204
        return $error;
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    public function errorInfo()
211
    {
212
        return oci_error($this->dbh);
213
    }
214
215
    /**
216
     * @param mixed[] $error The return value of an oci_error() call.
217
     */
218
    public static function exceptionFromErrorInfo(array $error) : DriverException
219
    {
220
        return new DriverException($error['message'], null, $error['code']);
221
    }
222
}
223