Passed
Push — master ( 713899...8e0d19 )
by Dāvis
04:05
created

Oci8::commit()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 13
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 0
dl 13
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Sludio\HelperBundle\Doctrine\DBAL\Driver\OCI8;
4
5
use PDO;
6
7
class Oci8 extends PDO
8
{
9
    // New param type for clob and blob support.
10
    const PARAM_BLOB = OCI_B_BLOB;
11
    const PARAM_CLOB = OCI_B_CLOB;
12
    const LOB_SQL = 0;
13
    const LOB_PL_SQL = 1;
14
15
    /**
16
     * @var resource Database handler
17
     */
18
    public $dbh;
19
20
    /**
21
     * @var array Driver options
22
     */
23
    private $options;
24
25
    /**
26
     * @var bool Whether currently in a transaction
27
     */
28
    private $inTransaction = false;
29
30
    /**
31
     * Creates a PDO instance representing a connection to a database
32
     *
33
     * @param        $dsn
34
     * @param        $username [optional]
35
     * @param        $password [optional]
36
     * @param null   $host
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $dbName is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $port is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $host is correct as it would always require null to be passed?
Loading history...
37
     * @param null   $dbName
38
     * @param null   $port
39
     * @param string $charset
40
     * @param array  $options  [optional]
41
     */
42
    public function __construct($dsn = null, $username = null, $password = null, $host = null, $dbName = null, $port = null, $charset = 'AL32UTF8', $options = [])
43
    {
44
        $this->connect($username, $password, $host, $dbName, $port, $charset, $options ?: []);
45
        $this->options = $options;
46
    }
47
48
    /**
49
     * Prepares a statement for execution and returns a statement object
50
     *
51
     * @param string $statement This must be a valid SQL statement for the
52
     *                          target database server.
53
     * @param array  $options   [optional] This array holds one or more key=>value
54
     *                          pairs to set attribute values for the PDOStatement object that this
55
     *                          method returns.
56
     *
57
     * @throws Oci8Exception
58
     * @return Oci8Statement
59
     */
60
    public function prepare($statement, array $options = [])
61
    {
62
        $sth = @oci_parse($this->dbh, $statement);
63
64
        if (!$sth) {
65
            $e = oci_error($this->dbh);
66
            throw new Oci8Exception($e['message']);
0 ignored issues
show
Bug introduced by
The call to Sludio\HelperBundle\Doct...xception::__construct() has too few arguments starting with code. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

66
            throw /** @scrutinizer ignore-call */ new Oci8Exception($e['message']);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
67
        }
68
69
        if ($options === null) {
70
            $options = $this->options;
71
        }
72
73
        if (!is_array($options)) {
74
            $options = [];
75
        }
76
77
        return new Oci8Statement($sth, $this, $options);
78
    }
79
80
    /**
81
     * Initiates a transaction
82
     *
83
     * @throws Oci8Exception
84
     * @return bool TRUE on success or FALSE on failure
85
     */
86
    public function beginTransaction()
87
    {
88
        if ($this->inTransaction()) {
89
            throw new Oci8Exception('There is already an active transaction');
0 ignored issues
show
Bug introduced by
The call to Sludio\HelperBundle\Doct...xception::__construct() has too few arguments starting with code. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
            throw /** @scrutinizer ignore-call */ new Oci8Exception('There is already an active transaction');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
90
        }
91
92
        $this->inTransaction = true;
93
94
        return true;
95
    }
96
97
    /**
98
     * Checks if inside a transaction
99
     *
100
     * @return bool TRUE if a transaction is currently active, and FALSE if not.
101
     */
102
    public function inTransaction()
103
    {
104
        return $this->inTransaction;
105
    }
106
107
    /**
108
     * Commits a transaction
109
     *
110
     * @throws Oci8Exception
111
     * @return bool TRUE on success or FALSE on failure.
112
     */
113 View Code Duplication
    public function commit()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
    {
115
        if (!$this->inTransaction()) {
116
            throw new Oci8Exception('There is no active transaction');
0 ignored issues
show
Bug introduced by
The call to Sludio\HelperBundle\Doct...xception::__construct() has too few arguments starting with code. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

116
            throw /** @scrutinizer ignore-call */ new Oci8Exception('There is no active transaction');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
117
        }
118
119
        if (oci_commit($this->dbh)) {
120
            $this->inTransaction = false;
121
122
            return true;
123
        }
124
125
        return false;
126
    }
127
128
    /**
129
     * Rolls back a transaction
130
     *
131
     * @throws Oci8Exception
132
     * @return bool TRUE on success or FALSE on failure.
133
     */
134 View Code Duplication
    public function rollBack()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
135
    {
136
        if (!$this->inTransaction()) {
137
            throw new Oci8Exception('There is no active transaction');
0 ignored issues
show
Bug introduced by
The call to Sludio\HelperBundle\Doct...xception::__construct() has too few arguments starting with code. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
            throw /** @scrutinizer ignore-call */ new Oci8Exception('There is no active transaction');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
138
        }
139
140
        if (oci_rollback($this->dbh)) {
141
            $this->inTransaction = false;
142
143
            return true;
144
        }
145
146
        return false;
147
    }
148
149
    /**
150
     * Sets an attribute on the database handle
151
     *
152
     * @param int   $attribute
153
     * @param mixed $value
154
     *
155
     * @return bool TRUE on success or FALSE on failure.
156
     */
157
    public function setAttribute($attribute, $value)
158
    {
159
        $this->options[$attribute] = $value;
160
161
        return true;
162
    }
163
164
    /**
165
     * Executes an SQL statement and returns the number of affected rows
166
     *
167
     * @param string $statement The SQL statement to prepare and execute.
168
     *
169
     * @return int The number of rows that were modified or deleted by the SQL
170
     *   statement you issued.
171
     * @throws \Sludio\HelperBundle\Doctrine\DBAL\Driver\OCI8\Oci8Exception
172
     */
173
    public function exec($statement)
174
    {
175
        $stmt = $this->query($statement);
176
177
        return $stmt->rowCount();
178
    }
179
180
    /**
181
     * Executes an SQL statement, returning the results as a
182
     * Oci8Statement object
183
     *
184
     * @param string     $statement The SQL statement to prepare and execute.
185
     * @param int|null   $fetchMode The fetch mode must be one of the
186
     *                              PDO::FETCH_* constants.
187
     * @param mixed|null $modeArg   Column number, class name or object.
188
     * @param array|null $ctorArgs  Constructor arguments.
189
     *
190
     * @return Oci8Statement
191
     * @throws \Sludio\HelperBundle\Doctrine\DBAL\Driver\OCI8\Oci8Exception
192
     */
193
    public function query($statement, $fetchMode = null, $modeArg = null, array $ctorArgs = [])
194
    {
195
        $stmt = $this->query($statement);
196
        if ($fetchMode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fetchMode of type null|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
197
            $stmt->setFetchMode($fetchMode, $modeArg, $ctorArgs);
198
        }
199
200
        return $stmt;
201
    }
202
203
    /**
204
     * Method not implemented
205
     *
206
     * @param string $name Sequence name; no use in this context
207
     *
208
     * @return mixed Last sequence number or 0 if sequence does not exist
209
     * @throws \Sludio\HelperBundle\Doctrine\DBAL\Driver\OCI8\Oci8Exception
210
     */
211
    public function lastInsertId($name = null)
212
    {
213
        throw new Oci8Exception('Method not implemented');
0 ignored issues
show
Bug introduced by
The call to Sludio\HelperBundle\Doct...xception::__construct() has too few arguments starting with code. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

213
        throw /** @scrutinizer ignore-call */ new Oci8Exception('Method not implemented');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
214
    }
215
216
    /**
217
     * Fetch the SQLSTATE associated with the last operation on the database
218
     * handle
219
     * While this returns an error code, it merely emulates the action. If
220
     * there are no errors, it returns the success SQLSTATE code (00000).
221
     * If there are errors, it returns HY000. See errorInfo() to retrieve
222
     * the actual Oracle error code and message.
223
     *
224
     * @return string
225
     */
226
    public function errorCode()
227
    {
228
        $error = $this->errorInfo();
229
230
        return $error[0];
231
    }
232
233
    /**
234
     * Returns extended error information for the last operation on the database
235
     * handle
236
     * The array consists of the following fields:
237
     *   0  SQLSTATE error code (a five characters alphanumeric identifier
238
     *      defined in the ANSI SQL standard).
239
     *   1  Driver-specific error code.
240
     *   2  Driver-specific error message.
241
     *
242
     * @return array Error information
243
     */
244 View Code Duplication
    public function errorInfo()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
    {
246
        $e = oci_error($this->dbh);
247
248
        if (is_array($e)) {
249
            return [
250
                'HY000',
251
                $e['code'],
252
                $e['message'],
253
            ];
254
        }
255
256
        return [
257
            '00000',
258
            null,
259
            null,
260
        ];
261
    }
262
263
    /**
264
     * Retrieve a database connection attribute
265
     *
266
     * @param int $attribute
267
     *
268
     * @return mixed A successful call returns the value of the requested PDO
269
     *   attribute. An unsuccessful call returns null.
270
     */
271
    public function getAttribute($attribute)
272
    {
273
        if ($attribute === PDO::ATTR_DRIVER_NAME) {
274
            return 'oci8';
275
        }
276
277
        if (isset($this->options[$attribute])) {
278
            return $this->options[$attribute];
279
        }
280
281
        return null;
282
    }
283
284
    /**
285
     * Special non PDO function used to start cursors in the database
286
     * Remember to call oci_free_statement() on your cursor
287
     *
288
     * @access public
289
     * @return mixed New statement handle, or FALSE on error.
290
     */
291
    public function getNewCursor()
292
    {
293
        return oci_new_cursor($this->dbh);
294
    }
295
296
    /**
297
     * Special non PDO function used to start descriptor in the database
298
     * Remember to call oci_free_statement() on your cursor
299
     *
300
     * @access public
301
     *
302
     * @param int $type One of OCI_DTYPE_FILE, OCI_DTYPE_LOB or OCI_DTYPE_ROWID.
303
     *
304
     * @return mixed New LOB or FILE descriptor on success, FALSE on error.
305
     */
306
    public function getNewDescriptor($type = OCI_D_LOB)
307
    {
308
        return oci_new_descriptor($this->dbh, $type);
309
    }
310
311
    /**
312
     * Special non PDO function used to close an open cursor in the database
313
     *
314
     * @access public
315
     *
316
     * @param mixed $cursor A valid OCI statement identifier.
317
     *
318
     * @return mixed Returns TRUE on success or FALSE on failure.
319
     */
320
    public function closeCursor($cursor)
321
    {
322
        return oci_free_statement($cursor);
323
    }
324
325
    /**
326
     * Special non PDO function
327
     * Allocates new collection object
328
     *
329
     * @param string $typeName Should be a valid named type (uppercase).
330
     * @param string $schema   Should point to the scheme, where the named type was created.
331
     *                         The name of the current user is the default value.
332
     *
333
     * @return \OCI_Collection
334
     */
335
    public function getNewCollection($typeName, $schema)
336
    {
337
        return oci_new_collection($this->dbh, $typeName, $schema);
338
    }
339
340
    /**
341
     * Places quotes around the input string
342
     *  If you are using this function to build SQL statements, you are strongly
343
     * recommended to use prepare() to prepare SQL statements with bound
344
     * parameters instead of using quote() to interpolate user input into an SQL
345
     * statement. Prepared statements with bound parameters are not only more
346
     * portable, more convenient, immune to SQL injection, but are often much
347
     * faster to execute than interpolated queries, as both the server and
348
     * client side can cache a compiled form of the query.
349
     *
350
     * @param string $string    The string to be quoted.
351
     * @param int    $paramType Provides a data type hint for drivers that have
352
     *                          alternate quoting styles
353
     *
354
     * @return string Returns a quoted string that is theoretically safe to pass
355
     *   into an SQL statement.
356
     * @todo Implement support for $paramType.
357
     */
358
    public function quote($string, $paramType = PDO::PARAM_STR)
359
    {
360
        return "'".str_replace("'", "''", $string)."'";
361
    }
362
363
    /**
364
     * Special non PDO function to check if sequence exists
365
     *
366
     * @param  string $name
367
     *
368
     * @return boolean
369
     * @throws \Sludio\HelperBundle\Doctrine\DBAL\Driver\OCI8\Oci8Exception
370
     */
371
    public function checkSequence($name)
372
    {
373
        if (!$name) {
374
            return false;
375
        }
376
377
        $stmt = $this->query("select count(*)
378
            from all_sequences
379
            where
380
                sequence_name=upper('{$name}')
381
                and sequence_owner=upper(user)
382
            ", PDO::FETCH_COLUMN);
383
384
        return $stmt->fetch();
385
    }
386
387
    /**
388
     * Parse DSN string and get $param value.
389
     *
390
     * @param string $dsn
391
     * @param string $param
392
     * @param mixed  $default
393
     *
394
     * @return string|null
395
     */
396
    protected function parseDsn($dsn, $param, $default = null)
397
    {
398
        if (preg_match('/'.$param.'=(?<param>[^;]+)/', $dsn, $mathes)) {
399
            return $mathes['param'];
400
        }
401
402
        return $default;
403
    }
404
405
    /**
406
     * Connect to database
407
     *
408
     * @param string $username
409
     * @param string $password
410
     * @param        $host
411
     * @param string $dbName
412
     * @param        $port
413
     * @param string $charset
414
     * @param array  $options
415
     *
416
     * @throws \Sludio\HelperBundle\Doctrine\DBAL\Driver\OCI8\Oci8Exception
417
     */
418
    public function connect($username, $password, $host, $dbName, $port, $charset, array $options = [])
419
    {
420
        $dbName = '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(Host = '.$host.') (Port = '.$port.')) (CONNECT_DATA = (SID = '.$dbName.')))';
421
422
        if (array_key_exists(PDO::ATTR_PERSISTENT, $options) && $options[PDO::ATTR_PERSISTENT]) {
423
            $this->dbh = @oci_pconnect($username, $password, $dbName, $charset);
424
        } else {
425
            $this->dbh = @oci_connect($username, $password, $dbName, $charset);
426
        }
427
428
        if (!$this->dbh) {
429
            $e = oci_error();
430
            throw new Oci8Exception($e['message']);
0 ignored issues
show
Bug introduced by
The call to Sludio\HelperBundle\Doct...xception::__construct() has too few arguments starting with code. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

430
            throw /** @scrutinizer ignore-call */ new Oci8Exception($e['message']);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
431
        }
432
    }
433
}
434