Passed
Push — master ( 910238...2d3e1b )
by Darío
02:38
created

Oracle::connect()   B

Complexity

Conditions 7
Paths 33

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 33
nop 0
dl 0
loc 23
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace Drone\Db\Driver;
12
13
/**
14
 * Oracle class
15
 *
16
 * This is a database driver class to connect to Oracle
17
 */
18
class Oracle extends AbstractDriver implements DriverInterface
19
{
20
    /**
21
     * {@inheritDoc}
22
     *
23
     * @var resource
24
     */
25
    protected $dbconn;
26
27
    /**
28
     * {@inheritDoc}
29
     *
30
     * @param array $options
31
     */
32
    public function __construct($options)
33
    {
34
        if (!array_key_exists("dbchar", $options))
35
            $options["dbchar"] = "AL32UTF8";
36
37
        parent::__construct($options);
38
39
        $auto_connect = array_key_exists('auto_connect', $options) ? $options["auto_connect"] : true;
40
41
        if ($auto_connect)
42
            $this->connect();
43
    }
44
45
    /**
46
     * Connects to database
47
     *
48
     * @throws RuntimeException
49
     * @throws Exception\ConnectionException
50
     *
51
     * @return resource
52
     */
53
    public function connect()
54
    {
55
        if (!extension_loaded('oci8'))
56
            throw new \RuntimeException("The Oci8 extension is not loaded");
57
58
        $connection_string = (is_null($this->dbhost) || empty($this->dbhost))
59
            ? $this->dbname
60
            :
61
                (!is_null($this->dbport) && !empty($this->dbport))
62
                    ? $this->dbhost .":". $this->dbport ."/". $this->dbname
63
                    : $this->dbhost ."/". $this->dbname;
64
65
        $conn = @oci_connect($this->dbuser,  $this->dbpass, $connection_string, $this->dbchar);
66
67
        if ($conn === false)
68
        {
69
            $error = oci_error();
70
            throw new Exception\ConnectionException($error["message"], $error["code"]);
71
        }
72
73
        $this->dbconn = $conn;
74
75
        return $this->dbconn;
76
    }
77
78
    /**
79
     * Excecutes a statement
80
     *
81
     * @param string $sql
82
     * @param array $params
83
     *
84
     * @throws Exception\InvalidQueryException
85
     *
86
     * @return resource
87
     */
88
    public function execute($sql, Array $params = [])
89
    {
90
        $this->numRows = 0;
91
        $this->numFields = 0;
92
        $this->rowsAffected = 0;
93
94
        $this->arrayResult = null;
95
96
        $this->result = $stid = @oci_parse($this->dbconn, $sql);
97
98
        if (!$stid)
0 ignored issues
show
introduced by
$stid is of type resource, thus it always evaluated to false.
Loading history...
99
        {
100
            $error = $stid ? oci_error($stid) : oci_error();
0 ignored issues
show
introduced by
$stid is of type resource, thus it always evaluated to false.
Loading history...
101
102
            if (!empty($error))
103
            {
104
                $error = [
105
                    "message" => "Could not prepare statement!"
106
                ];
107
108
                $this->error($error["message"]);
109
            }
110
            else
111
                $this->error($error["code"], $error["message"]);
112
113
            if (array_key_exists("code", $error))
114
                throw new Exception\InvalidQueryException($error["message"], $error["code"]);
115
            else
116
                throw new Exception\InvalidQueryException($error["message"]);
117
        }
118
119
        # Bound variables
120
        if (count($params))
121
        {
122
            $param_keys   = array_keys($params);
123
            $param_values = array_values($params);
124
125
            for ($i = 0; $i < count($params); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
126
            {
127
                oci_bind_by_name($stid, $param_keys[$i], $param_values[$i], -1);
128
            }
129
        }
130
131
        $prev_error_handler = set_error_handler(['\Drone\Error\ErrorHandler', 'errorControlOperator'], E_ALL);
132
133
        // may be throw a Fatal error (Ex: Maximum execution time)
134
        $r = ($this->transac_mode) ? oci_execute($stid, OCI_NO_AUTO_COMMIT) : oci_execute($stid,  OCI_COMMIT_ON_SUCCESS);
135
136
        set_error_handler($prev_error_handler);
137
138
        if (!$r)
139
        {
140
            $error = oci_error($stid);
141
            $this->error($error["code"], $error["message"]);
142
143
            throw new Exception\InvalidQueryException($error["message"], $error["code"]);
144
        }
145
146
        # This should be before of getArrayResult() because oci_fetch() is incremental.
147
        $this->rowsAffected = oci_num_rows($stid);
148
149
        $rows = $this->getArrayResult();
150
151
        $this->numRows = count($rows);
152
        $this->numFields = oci_num_fields($stid);
153
154
        if ($this->transac_mode)
155
            $this->transac_result = is_null($this->transac_result) ? $stid: $this->transac_result && $stid;
156
157
        $this->result = $stid;
158
159
        return $this->result;
160
    }
161
162
    /**
163
     * {@inheritDoc}
164
     */
165
    public function commit()
166
    {
167
        return oci_commit($this->dbconn);
168
    }
169
170
    /**
171
     * {@inheritDoc}
172
     */
173
    public function rollback()
174
    {
175
        return oci_rollback($this->dbconn);
176
    }
177
178
    /**
179
     * {@inheritDoc}
180
     */
181
    public function disconnect()
182
    {
183
        parent::disconnect();
184
        return oci_close($this->dbconn);
185
    }
186
187
    /**
188
     * Returns an array with the rows fetched
189
     *
190
     * @throws LogicException
191
     *
192
     * @return array
193
     */
194
    protected function toArray()
195
    {
196
        $data = [];
197
198
        if ($this->result)
199
        {
200
            while ( ($row = @oci_fetch_array($this->result, OCI_BOTH + OCI_RETURN_NULLS)) !== false )
201
            {
202
                $data[] = $row;
203
            }
204
        }
205
        else
206
            /*
207
             * "This kind of exception should lead directly to a fix in your code"
208
             * So much production tests tell us this error is throwed because developers
209
             * execute toArray() before execute().
210
             *
211
             * Ref: http://php.net/manual/en/class.logicexception.php
212
             */
213
            throw new \LogicException('There are not data in the buffer!');
214
215
        $this->arrayResult = $data;
216
217
        return $data;
218
    }
219
220
    /**
221
     * By default __destruct() disconnects to database
222
     *
223
     * @return null
224
     */
225
    public function __destruct()
226
    {
227
        if ($this->dbconn)
228
            oci_close($this->dbconn);
229
    }
230
}