Passed
Push — 2.9 ( d389f3...7345cd )
by Sergei
31:44 queued 28:51
created

OCI8Connection   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 195
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 25
eloc 54
dl 0
loc 195
ccs 0
cts 104
cp 0
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A errorInfo() 0 3 1
A getServerVersion() 0 13 2
A errorCode() 0 8 2
A quote() 0 8 3
A beginTransaction() 0 5 1
A commit() 0 8 2
A rollBack() 0 8 2
A lastInsertId() 0 15 3
A requiresQueryForServerVersion() 0 3 1
A getExecuteMode() 0 3 1
A query() 0 9 1
A __construct() 0 12 4
A exec() 0 6 1
A prepare() 0 3 1
1
<?php
2
3
namespace Doctrine\DBAL\Driver\OCI8;
4
5
use Doctrine\DBAL\Driver\Connection;
6
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
7
use Doctrine\DBAL\ParameterType;
8
use UnexpectedValueException;
9
use const OCI_COMMIT_ON_SUCCESS;
10
use const OCI_DEFAULT;
11
use const OCI_NO_AUTO_COMMIT;
12
use function addcslashes;
13
use function define;
14
use function defined;
15
use function func_get_args;
16
use function is_float;
17
use function is_int;
18
use function oci_commit;
19
use function oci_connect;
20
use function oci_error;
21
use function oci_pconnect;
22
use function oci_rollback;
23
use function oci_server_version;
24
use function preg_match;
25
use function sprintf;
26
use function str_replace;
27
28
/**
29
 * OCI8 implementation of the Connection interface.
30
 */
31
class OCI8Connection implements Connection, ServerInfoAwareConnection
32
{
33
    /** @var resource */
34
    protected $dbh;
35
36
    /** @var int */
37
    protected $executeMode = OCI_COMMIT_ON_SUCCESS;
38
39
    /**
40
     * Creates a Connection to an Oracle Database using oci8 extension.
41
     *
42
     * @param string      $username
43
     * @param string      $password
44
     * @param string      $db
45
     * @param string|null $charset
46
     * @param int         $sessionMode
47
     * @param bool        $persistent
48
     *
49
     * @throws OCI8Exception
50
     */
51
    public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT, $persistent = false)
52
    {
53
        if (! defined('OCI_NO_AUTO_COMMIT')) {
54
            define('OCI_NO_AUTO_COMMIT', 0);
55
        }
56
57
        $this->dbh = $persistent
0 ignored issues
show
Documentation Bug introduced by
It seems like $persistent ? @oci_pconn...$charset, $sessionMode) can also be of type false. However, the property $dbh is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
58
            ? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
59
            : @oci_connect($username, $password, $db, $charset, $sessionMode);
60
61
        if (! $this->dbh) {
62
            throw OCI8Exception::fromErrorInfo(oci_error());
63
        }
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     *
69
     * @throws UnexpectedValueException If the version string returned by the database server
70
     *                                  does not contain a parsable version number.
71
     */
72
    public function getServerVersion()
73
    {
74
        if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', oci_server_version($this->dbh), $version)) {
75
            throw new UnexpectedValueException(
76
                sprintf(
77
                    'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' .
78
                    'Please report this database version string to the Doctrine team.',
79
                    oci_server_version($this->dbh)
80
                )
81
            );
82
        }
83
84
        return $version[1];
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function requiresQueryForServerVersion()
91
    {
92
        return false;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function prepare($prepareString)
99
    {
100
        return new OCI8Statement($this->dbh, $prepareString, $this);
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function query()
107
    {
108
        $args = func_get_args();
109
        $sql  = $args[0];
110
        //$fetchMode = $args[1];
111
        $stmt = $this->prepare($sql);
112
        $stmt->execute();
113
114
        return $stmt;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function quote($value, $type = ParameterType::STRING)
121
    {
122
        if (is_int($value) || is_float($value)) {
123
            return $value;
124
        }
125
        $value = str_replace("'", "''", $value);
126
127
        return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function exec($statement)
134
    {
135
        $stmt = $this->prepare($statement);
136
        $stmt->execute();
137
138
        return $stmt->rowCount();
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function lastInsertId($name = null)
145
    {
146
        if ($name === null) {
147
            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...
148
        }
149
150
        $sql    = 'SELECT ' . $name . '.CURRVAL FROM DUAL';
151
        $stmt   = $this->query($sql);
152
        $result = $stmt->fetchColumn();
153
154
        if ($result === false) {
155
            throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.');
156
        }
157
158
        return (int) $result;
159
    }
160
161
    /**
162
     * Returns the current execution mode.
163
     *
164
     * @return int
165
     */
166
    public function getExecuteMode()
167
    {
168
        return $this->executeMode;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function beginTransaction()
175
    {
176
        $this->executeMode = OCI_NO_AUTO_COMMIT;
177
178
        return true;
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184
    public function commit()
185
    {
186
        if (! oci_commit($this->dbh)) {
187
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
188
        }
189
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
190
191
        return true;
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function rollBack()
198
    {
199
        if (! oci_rollback($this->dbh)) {
200
            throw OCI8Exception::fromErrorInfo($this->errorInfo());
201
        }
202
        $this->executeMode = OCI_COMMIT_ON_SUCCESS;
203
204
        return true;
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    public function errorCode()
211
    {
212
        $error = oci_error($this->dbh);
213
        if ($error !== false) {
214
            $error = $error['code'];
215
        }
216
217
        return $error;
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223
    public function errorInfo()
224
    {
225
        return oci_error($this->dbh);
0 ignored issues
show
Bug Best Practice introduced by
The expression return oci_error($this->dbh) also could return the type false which is incompatible with the return type mandated by Doctrine\DBAL\Driver\Connection::errorInfo() of array<mixed,mixed>.
Loading history...
226
    }
227
}
228