Passed
Pull Request — develop (#3453)
by Evgeniy
19:01
created

OCI8Connection::requiresQueryForServerVersion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.037

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 3
cp 0.6667
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 1.037
1
<?php
2
3
namespace Doctrine\DBAL\Driver\OCI8;
4
5
use Doctrine\DBAL\Driver\Connection;
6
use Doctrine\DBAL\Driver\ResultStatement;
7
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
8
use Doctrine\DBAL\Driver\Statement as DriverStatement;
9
use Doctrine\DBAL\ParameterType;
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 is_float;
16
use function is_int;
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 $charset
45
     * @param int    $sessionMode
46
     * @param bool   $persistent
47
     *
48
     * @throws OCI8Exception
49
     */
50 30
    public function __construct(
51
        $username,
52
        $password,
53
        $db,
54
        $charset = '',
55
        $sessionMode = OCI_DEFAULT,
56
        $persistent = false
57
    ) {
58 30
        $dbh = $persistent
59
            ? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
60 30
            : @oci_connect($username, $password, $db, $charset, $sessionMode);
61
62 30
        if ($dbh === false) {
0 ignored issues
show
introduced by
The condition $dbh === false is always false.
Loading history...
63 3
            throw OCI8Exception::fromErrorInfo(oci_error());
64
        }
65
66 27
        $this->dbh = $dbh;
67 27
    }
68
69
    /**
70
     * {@inheritdoc}
71
     *
72
     * @throws UnexpectedValueException If the version string returned by the database server
73
     *                                  does not contain a parsable version number.
74
     */
75
    public function getServerVersion()
76
    {
77
        $version = oci_server_version($this->dbh);
78
79
        if ($version === false) {
80
            throw OCI8Exception::fromErrorInfo(oci_error($this->dbh));
81
        }
82
83
        if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches)) {
84
            throw new UnexpectedValueException(
85
                sprintf(
86
                    'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' .
87
                    'Please report this database version string to the Doctrine team.',
88
                    $version
89
                )
90
            );
91
        }
92
93
        return $matches[1];
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 1
    public function requiresQueryForServerVersion()
100
    {
101 1
        return false;
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107 265
    public function prepare(string $sql) : DriverStatement
108
    {
109 265
        return new OCI8Statement($this->dbh, $sql, $this);
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115 174
    public function query(string $sql) : ResultStatement
116
    {
117 174
        $stmt = $this->prepare($sql);
118 174
        $stmt->execute();
119
120 171
        return $stmt;
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126 4
    public function quote($value, $type = ParameterType::STRING)
127
    {
128 4
        if (is_int($value) || is_float($value)) {
129 2
            return $value;
130
        }
131 3
        $value = str_replace("'", "''", $value);
132
133 3
        return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 177
    public function exec(string $statement) : int
140
    {
141 177
        $stmt = $this->prepare($statement);
142 177
        $stmt->execute();
143
144 171
        return $stmt->rowCount();
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 4
    public function lastInsertId($name = null)
151
    {
152 4
        if ($name === null) {
153 1
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by Doctrine\DBAL\Driver\Connection::lastInsertId() of string.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
154
        }
155
156 3
        $sql    = 'SELECT ' . $name . '.CURRVAL FROM DUAL';
157 3
        $stmt   = $this->query($sql);
158 3
        $result = $stmt->fetchColumn();
159
160 3
        if ($result === false) {
161
            throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.');
162
        }
163
164 3
        return (int) $result;
165
    }
166
167
    /**
168
     * Returns the current execution mode.
169
     *
170
     * @return int
171
     */
172 260
    public function getExecuteMode()
173
    {
174 260
        return $this->executeMode;
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 15
    public function beginTransaction()
181
    {
182 15
        $this->executeMode = OCI_NO_AUTO_COMMIT;
183
184 15
        return true;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190 7
    public function commit()
191
    {
192 7
        if (! oci_commit($this->dbh)) {
193
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
194
        }
195 7
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
196
197 7
        return true;
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203 9
    public function rollBack()
204
    {
205 9
        if (! oci_rollback($this->dbh)) {
206
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
207
        }
208 9
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
209
210 9
        return true;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function errorCode()
217
    {
218
        $error = oci_error($this->dbh);
219
        if ($error !== false) {
220
            $error = $error['code'];
221
        }
222
223
        return $error;
224
    }
225
226
    /**
227
     * {@inheritdoc}
228
     */
229
    public function errorInfo()
230
    {
231
        $error = oci_error($this->dbh);
232
233
        if ($error === false) {
234
            return [];
235
        }
236
237
        return $error;
238
    }
239
}
240