Passed
Push — master ( 800486...f6d51e )
by Darío
02:49
created

Oracle   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 207
rs 9.92
c 0
b 0
f 0
wmc 31
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)
99
        {
100
            $error = oci_error($stid) : oci_error();
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected ':' on line 100 at column 38
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++)
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
}