blob: bb605acd69284a46667de6b9511def779aa366e8 [file] [log] [blame]
Andrey Andreev24abcb92012-01-05 20:40:15 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreev24abcb92012-01-05 20:40:15 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreev24abcb92012-01-05 20:40:15 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
Andrey Andreev342a4662012-01-24 15:24:00 +020012 * bundled with this package in the files license.txt / license.rst. It is
Derek Jonesf4a4bd82011-10-20 12:18:42 -050013 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Barry Mienydd671972010-10-04 16:33:58 +020019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
Barry Mienydd671972010-10-04 16:33:58 +020024 * @since Version 1.0
Derek Allard2067d1a2008-11-13 22:59:24 +000025 * @filesource
26 */
27
Derek Allard2067d1a2008-11-13 22:59:24 +000028/**
29 * oci8 Database Adapter Class
30 *
31 * Note: _DB is an extender class that the app controller
32 * creates dynamically based on whether the active record
33 * class is being used or not.
34 *
Barry Mienydd671972010-10-04 16:33:58 +020035 * @package CodeIgniter
Derek Jones4b9c6292011-07-01 17:40:48 -050036 * @subpackage Drivers
Derek Allard2067d1a2008-11-13 22:59:24 +000037 * @category Database
Derek Jonesf4a4bd82011-10-20 12:18:42 -050038 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000039 * @link http://codeigniter.com/user_guide/database/
40 */
41
42/**
43 * oci8 Database Adapter Class
44 *
45 * This is a modification of the DB_driver class to
46 * permit access to oracle databases
47 *
Derek Jones4b9c6292011-07-01 17:40:48 -050048 * @author Kelly McArdle
Derek Allard2067d1a2008-11-13 22:59:24 +000049 */
Derek Allard2067d1a2008-11-13 22:59:24 +000050class CI_DB_oci8_driver extends CI_DB {
51
Andrey Andreev24abcb92012-01-05 20:40:15 +020052 public $dbdriver = 'oci8';
Barry Mienydd671972010-10-04 16:33:58 +020053
Derek Allard2067d1a2008-11-13 22:59:24 +000054 // The character used for excaping
Andrey Andreev24abcb92012-01-05 20:40:15 +020055 protected $_escape_char = '"';
Barry Mienydd671972010-10-04 16:33:58 +020056
Derek Jonese4ed5832009-02-20 21:44:59 +000057 // clause and character used for LIKE escape sequences
Andrey Andreevda123732012-03-20 22:27:40 +020058 protected $_like_escape_str = " ESCAPE '%s' ";
Andrey Andreev24abcb92012-01-05 20:40:15 +020059 protected $_like_escape_chr = '!';
Barry Mienydd671972010-10-04 16:33:58 +020060
Derek Allard2067d1a2008-11-13 22:59:24 +000061 /**
62 * The syntax to count rows is slightly different across different
63 * database engines, so this string appears in each driver and is
64 * used for the count_all() and count_all_results() functions.
65 */
Andrey Andreev24abcb92012-01-05 20:40:15 +020066 protected $_count_string = 'SELECT COUNT(1) AS ';
67 protected $_random_keyword = ' ASC'; // not currently supported
Derek Allard2067d1a2008-11-13 22:59:24 +000068
69 // Set "auto commit" by default
Andrey Andreev99013ed2012-03-05 16:17:32 +020070 public $commit_mode = OCI_COMMIT_ON_SUCCESS;
Derek Allard2067d1a2008-11-13 22:59:24 +000071
72 // need to track statement id and cursor id
Andrey Andreev24abcb92012-01-05 20:40:15 +020073 public $stmt_id;
74 public $curs_id;
Derek Allard2067d1a2008-11-13 22:59:24 +000075
76 // if we use a limit, we will add a field that will
77 // throw off num_fields later
Andrey Andreev24abcb92012-01-05 20:40:15 +020078 public $limit_used;
Derek Allard2067d1a2008-11-13 22:59:24 +000079
Andrey Andreevdad61c22012-02-13 01:08:06 +020080 public function __construct($params)
81 {
82 parent::__construct($params);
83
84 $valid_dsns = array(
Andrey Andreevdad61c22012-02-13 01:08:06 +020085 'tns' => '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS
Andrey Andreevfcd1f472012-02-13 09:30:16 +020086 // Easy Connect string (Oracle 10g+)
87 'ec' => '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i',
Andrey Andreevdad61c22012-02-13 01:08:06 +020088 'in' => '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora)
89 );
90
91 /* Space characters don't have any effect when actually
92 * connecting, but can be a hassle while validating the DSN.
93 */
94 $this->dsn = str_replace(array("\n", "\r", "\t", ' '), '', $this->dsn);
95
96 if ($this->dsn !== '')
97 {
98 foreach ($valid_dsns as $regexp)
99 {
100 if (preg_match($regexp, $this->dsn))
101 {
102 return;
103 }
104 }
105 }
106
107 // Legacy support for TNS in the hostname configuration field
108 $this->hostname = str_replace(array("\n", "\r", "\t", ' '), '', $this->hostname);
109 if (preg_match($valid_dsns['tns'], $this->hostname))
110 {
111 $this->dsn = $this->hostname;
112 return;
113 }
114 elseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE
115 && (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== ''))
116 {
117 /* If the hostname field isn't empty, doesn't contain
118 * ':' and/or '/' and if port and/or database aren't
119 * empty, then the hostname field is most likely indeed
120 * just a hostname. Therefore we'll try and build an
121 * Easy Connect string from these 3 settings, assuming
122 * that the database field is a service name.
123 */
124 $this->dsn = $this->hostname
125 .(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '')
126 .($this->database !== '' ? '/'.ltrim($this->database, '/') : '');
127
128 if (preg_match($valid_dsns['ec'], $this->dsn))
129 {
130 return;
131 }
132 }
133
134 /* At this point, we can only try and validate the hostname and
135 * database fields separately as DSNs.
136 */
137 if (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname))
138 {
139 $this->dsn = $this->hostname;
140 return;
141 }
142
143 $this->database = str_replace(array("\n", "\r", "\t", ' '), '', $this->database);
144 foreach ($valid_dsns as $regexp)
145 {
146 if (preg_match($regexp, $this->database))
147 {
148 return;
149 }
150 }
151
152 /* Well - OK, an empty string should work as well.
153 * PHP will try to use environment variables to
154 * determine which Oracle instance to connect to.
155 */
156 $this->dsn = '';
157 }
158
Derek Allard2067d1a2008-11-13 22:59:24 +0000159 /**
160 * Non-persistent database connection
161 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200162 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300164 public function db_connect()
Derek Allard2067d1a2008-11-13 22:59:24 +0000165 {
Andrey Andreevdad61c22012-02-13 01:08:06 +0200166 return ( ! empty($this->char_set))
167 ? @oci_connect($this->username, $this->password, $this->dsn, $this->char_set)
168 : @oci_connect($this->username, $this->password, $this->dsn);
Derek Allard2067d1a2008-11-13 22:59:24 +0000169 }
170
171 // --------------------------------------------------------------------
172
173 /**
174 * Persistent database connection
175 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200176 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000177 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300178 public function db_pconnect()
Derek Allard2067d1a2008-11-13 22:59:24 +0000179 {
Andrey Andreevdad61c22012-02-13 01:08:06 +0200180 return ( ! empty($this->char_set))
181 ? @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set)
182 : @oci_pconnect($this->username, $this->password, $this->dsn);
Derek Allard2067d1a2008-11-13 22:59:24 +0000183 }
184
185 // --------------------------------------------------------------------
186
187 /**
Derek Jones87cbafc2009-02-27 16:29:59 +0000188 * Reconnect
189 *
190 * Keep / reestablish the db connection if no queries have been
191 * sent for a length of time exceeding the server's idle timeout
192 *
Derek Jones87cbafc2009-02-27 16:29:59 +0000193 * @return void
194 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300195 public function reconnect()
Derek Jones87cbafc2009-02-27 16:29:59 +0000196 {
197 // not implemented in oracle
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300198 return;
Derek Jones87cbafc2009-02-27 16:29:59 +0000199 }
200
201 // --------------------------------------------------------------------
202
203 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000204 * Select the database
205 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200206 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000207 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300208 public function db_select()
Derek Allard2067d1a2008-11-13 22:59:24 +0000209 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300210 // Not in Oracle - schemas are actually usernames
Derek Allard2067d1a2008-11-13 22:59:24 +0000211 return TRUE;
212 }
213
214 // --------------------------------------------------------------------
215
216 /**
Andrey Andreev08856b82012-03-03 03:19:28 +0200217 * Database version number
Derek Allard2067d1a2008-11-13 22:59:24 +0000218 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200219 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000220 */
Andrey Andreev08856b82012-03-03 03:19:28 +0200221 public function version()
Derek Allard2067d1a2008-11-13 22:59:24 +0000222 {
Andrey Andreev08856b82012-03-03 03:19:28 +0200223 return isset($this->data_cache['version'])
224 ? $this->data_cache['version']
225 : $this->data_cache['version'] = oci_server_version($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000226 }
227
228 // --------------------------------------------------------------------
229
230 /**
231 * Execute the query
232 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200233 * @param string an SQL query
234 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000235 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300236 protected function _execute($sql)
Derek Allard2067d1a2008-11-13 22:59:24 +0000237 {
Andrey Andreev24abcb92012-01-05 20:40:15 +0200238 /* Oracle must parse the query before it is run. All of the actions with
239 * the query are based on the statement id returned by oci_parse().
240 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000241 $this->stmt_id = FALSE;
242 $this->_set_stmt_id($sql);
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300243 oci_set_prefetch($this->stmt_id, 1000);
Andrey Andreev99013ed2012-03-05 16:17:32 +0200244 return @oci_execute($this->stmt_id, $this->commit_mode);
Derek Allard2067d1a2008-11-13 22:59:24 +0000245 }
246
247 /**
248 * Generate a statement ID
249 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200250 * @param string an SQL query
251 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000252 */
Andrey Andreevda123732012-03-20 22:27:40 +0200253 protected function _set_stmt_id($sql)
Derek Allard2067d1a2008-11-13 22:59:24 +0000254 {
255 if ( ! is_resource($this->stmt_id))
256 {
Timothy Warrend2ff0bc2012-03-19 16:52:10 -0400257 $this->stmt_id = oci_parse($this->conn_id, $sql);
Derek Allard2067d1a2008-11-13 22:59:24 +0000258 }
259 }
260
261 // --------------------------------------------------------------------
262
263 /**
Andrey Andreevda123732012-03-20 22:27:40 +0200264 * Get cursor. Returns a cursor from the database
Derek Allard2067d1a2008-11-13 22:59:24 +0000265 *
Andrey Andreevda123732012-03-20 22:27:40 +0200266 * @return cursor id
Derek Allard2067d1a2008-11-13 22:59:24 +0000267 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300268 public function get_cursor()
Derek Allard2067d1a2008-11-13 22:59:24 +0000269 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200270 return $this->curs_id = oci_new_cursor($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000271 }
272
273 // --------------------------------------------------------------------
274
275 /**
Derek Jones4b9c6292011-07-01 17:40:48 -0500276 * Stored Procedure. Executes a stored procedure
Derek Allard2067d1a2008-11-13 22:59:24 +0000277 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200278 * @param string package name in which the stored procedure is in
279 * @param string stored procedure name to execute
280 * @param array parameters
281 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000282 *
283 * params array keys
284 *
Derek Jones4b9c6292011-07-01 17:40:48 -0500285 * KEY OPTIONAL NOTES
Andrey Andreevaa786c92012-01-16 12:14:45 +0200286 * name no the name of the parameter should be in :<param_name> format
287 * value no the value of the parameter. If this is an OUT or IN OUT parameter,
288 * this should be a reference to a variable
289 * type yes the type of the parameter
290 * length yes the max size of the parameter
Derek Allard2067d1a2008-11-13 22:59:24 +0000291 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300292 public function stored_procedure($package, $procedure, $params)
Derek Allard2067d1a2008-11-13 22:59:24 +0000293 {
294 if ($package == '' OR $procedure == '' OR ! is_array($params))
295 {
296 if ($this->db_debug)
297 {
298 log_message('error', 'Invalid query: '.$package.'.'.$procedure);
Derek Allardfac8fbc2010-02-05 16:14:49 +0000299 return $this->display_error('db_invalid_query');
Derek Allard2067d1a2008-11-13 22:59:24 +0000300 }
301 return FALSE;
302 }
Barry Mienydd671972010-10-04 16:33:58 +0200303
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 // build the query string
Andrey Andreeve35d7782012-01-19 15:56:20 +0200305 $sql = 'BEGIN '.$package.'.'.$procedure.'(';
Derek Allard2067d1a2008-11-13 22:59:24 +0000306
307 $have_cursor = FALSE;
Pascal Krietec3a4a8d2011-02-14 13:40:08 -0500308 foreach ($params as $param)
Derek Allard2067d1a2008-11-13 22:59:24 +0000309 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200310 $sql .= $param['name'].',';
Barry Mienydd671972010-10-04 16:33:58 +0200311
Andrey Andreev85facfa2012-01-26 14:12:14 +0200312 if (isset($param['type']) && $param['type'] === OCI_B_CURSOR)
Derek Allard2067d1a2008-11-13 22:59:24 +0000313 {
314 $have_cursor = TRUE;
315 }
316 }
Andrey Andreevaa786c92012-01-16 12:14:45 +0200317 $sql = trim($sql, ',') . '); END;';
Barry Mienydd671972010-10-04 16:33:58 +0200318
Derek Allard2067d1a2008-11-13 22:59:24 +0000319 $this->stmt_id = FALSE;
320 $this->_set_stmt_id($sql);
321 $this->_bind_params($params);
Andrey Andreevaa786c92012-01-16 12:14:45 +0200322 return $this->query($sql, FALSE, $have_cursor);
Derek Allard2067d1a2008-11-13 22:59:24 +0000323 }
Barry Mienydd671972010-10-04 16:33:58 +0200324
Derek Allard2067d1a2008-11-13 22:59:24 +0000325 // --------------------------------------------------------------------
326
327 /**
328 * Bind parameters
329 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200330 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000331 */
Andrey Andreev1b5a8562012-03-13 13:13:43 +0200332 protected function _bind_params($params)
Derek Allard2067d1a2008-11-13 22:59:24 +0000333 {
334 if ( ! is_array($params) OR ! is_resource($this->stmt_id))
335 {
336 return;
337 }
Barry Mienydd671972010-10-04 16:33:58 +0200338
Derek Allard2067d1a2008-11-13 22:59:24 +0000339 foreach ($params as $param)
340 {
Barry Mienydd671972010-10-04 16:33:58 +0200341 foreach (array('name', 'value', 'type', 'length') as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000342 {
343 if ( ! isset($param[$val]))
344 {
345 $param[$val] = '';
346 }
347 }
348
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300349 oci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000350 }
351 }
352
353 // --------------------------------------------------------------------
354
355 /**
356 * Begin Transaction
357 *
Barry Mienydd671972010-10-04 16:33:58 +0200358 * @return bool
359 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300360 public function trans_begin($test_mode = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000361 {
362 if ( ! $this->trans_enabled)
363 {
364 return TRUE;
365 }
Barry Mienydd671972010-10-04 16:33:58 +0200366
Derek Allard2067d1a2008-11-13 22:59:24 +0000367 // When transactions are nested we only begin/commit/rollback the outermost ones
368 if ($this->_trans_depth > 0)
369 {
370 return TRUE;
371 }
Barry Mienydd671972010-10-04 16:33:58 +0200372
Derek Allard2067d1a2008-11-13 22:59:24 +0000373 // Reset the transaction failure flag.
374 // If the $test_mode flag is set to TRUE transactions will be rolled back
375 // even if the queries produce a successful result.
376 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
Barry Mienydd671972010-10-04 16:33:58 +0200377
Andrey Andreev99013ed2012-03-05 16:17:32 +0200378 $this->commit_mode = (is_php('5.3.2')) ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT;
Derek Allard2067d1a2008-11-13 22:59:24 +0000379 return TRUE;
380 }
381
382 // --------------------------------------------------------------------
383
384 /**
385 * Commit Transaction
386 *
Barry Mienydd671972010-10-04 16:33:58 +0200387 * @return bool
388 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300389 public function trans_commit()
Derek Allard2067d1a2008-11-13 22:59:24 +0000390 {
391 if ( ! $this->trans_enabled)
392 {
393 return TRUE;
394 }
395
396 // When transactions are nested we only begin/commit/rollback the outermost ones
397 if ($this->_trans_depth > 0)
398 {
399 return TRUE;
400 }
401
Andrey Andreev99013ed2012-03-05 16:17:32 +0200402 $this->commit_mode = OCI_COMMIT_ON_SUCCESS;
Andrey Andreev24abcb92012-01-05 20:40:15 +0200403 return oci_commit($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000404 }
405
406 // --------------------------------------------------------------------
407
408 /**
409 * Rollback Transaction
410 *
Barry Mienydd671972010-10-04 16:33:58 +0200411 * @return bool
412 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300413 public function trans_rollback()
Derek Allard2067d1a2008-11-13 22:59:24 +0000414 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000415 // When transactions are nested we only begin/commit/rollback the outermost ones
Andrey Andreeve35d7782012-01-19 15:56:20 +0200416 if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000417 {
418 return TRUE;
419 }
420
Andrey Andreev99013ed2012-03-05 16:17:32 +0200421 $this->commit_mode = OCI_COMMIT_ON_SUCCESS;
Andrey Andreev24abcb92012-01-05 20:40:15 +0200422 return oci_rollback($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000423 }
424
425 // --------------------------------------------------------------------
426
427 /**
428 * Escape String
429 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200430 * @param string
Derek Jonese4ed5832009-02-20 21:44:59 +0000431 * @param bool whether or not the string will be used in a LIKE condition
Andrey Andreevaa786c92012-01-16 12:14:45 +0200432 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000433 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300434 public function escape_str($str, $like = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000435 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000436 if (is_array($str))
437 {
Pascal Krietec3a4a8d2011-02-14 13:40:08 -0500438 foreach ($str as $key => $val)
Barry Mienydd671972010-10-04 16:33:58 +0200439 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000440 $str[$key] = $this->escape_str($val, $like);
Barry Mienydd671972010-10-04 16:33:58 +0200441 }
442
443 return $str;
444 }
Derek Jonese4ed5832009-02-20 21:44:59 +0000445
Andrey Andreevaa786c92012-01-16 12:14:45 +0200446 $str = str_replace("'", "''", remove_invisible_characters($str));
Barry Mienydd671972010-10-04 16:33:58 +0200447
Derek Jonese4ed5832009-02-20 21:44:59 +0000448 // escape LIKE condition wildcards
449 if ($like === TRUE)
450 {
Andrey Andreevc2905f52012-03-01 14:39:26 +0200451 return str_replace(array($this->_like_escape_chr, '%', '_'),
Andrey Andreev08c7c622012-02-28 13:23:38 +0200452 array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
Andrey Andreevaa786c92012-01-16 12:14:45 +0200453 $str);
Derek Jonese4ed5832009-02-20 21:44:59 +0000454 }
Barry Mienydd671972010-10-04 16:33:58 +0200455
Derek Jonese4ed5832009-02-20 21:44:59 +0000456 return $str;
Derek Allard2067d1a2008-11-13 22:59:24 +0000457 }
458
459 // --------------------------------------------------------------------
460
461 /**
462 * Affected Rows
463 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200464 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000465 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300466 public function affected_rows()
Derek Allard2067d1a2008-11-13 22:59:24 +0000467 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300468 return @oci_num_rows($this->stmt_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000469 }
470
471 // --------------------------------------------------------------------
472
473 /**
474 * Insert ID
475 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200476 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000477 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300478 public function insert_id()
Derek Allard2067d1a2008-11-13 22:59:24 +0000479 {
480 // not supported in oracle
Derek Allardfac8fbc2010-02-05 16:14:49 +0000481 return $this->display_error('db_unsupported_function');
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 }
483
484 // --------------------------------------------------------------------
485
486 /**
487 * "Count All" query
488 *
489 * Generates a platform-specific query string that counts all records in
490 * the specified database
491 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200492 * @param string
493 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000494 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300495 public function count_all($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000496 {
497 if ($table == '')
Derek Allarde37ab382009-02-03 16:13:57 +0000498 {
499 return 0;
500 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000501
Andrey Andreev032e7ea2012-03-06 19:48:35 +0200502 $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
Derek Allard2067d1a2008-11-13 22:59:24 +0000503 if ($query == FALSE)
Derek Allarde37ab382009-02-03 16:13:57 +0000504 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000505 return 0;
Derek Allarde37ab382009-02-03 16:13:57 +0000506 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000507
508 $row = $query->row();
Greg Aker90248ab2011-08-20 14:23:14 -0500509 $this->_reset_select();
Derek Allarde37ab382009-02-03 16:13:57 +0000510 return (int) $row->numrows;
Derek Allard2067d1a2008-11-13 22:59:24 +0000511 }
512
513 // --------------------------------------------------------------------
514
515 /**
516 * Show table query
517 *
518 * Generates a platform-specific query string so that the table names can be fetched
519 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200520 * @param bool
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300521 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000522 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300523 protected function _list_tables($prefix_limit = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000524 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200525 $sql = 'SELECT TABLE_NAME FROM ALL_TABLES';
Derek Allard2067d1a2008-11-13 22:59:24 +0000526
Andrey Andreev1ab62ae2012-01-20 13:04:10 +0200527 if ($prefix_limit !== FALSE && $this->dbprefix != '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000528 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200529 return $sql." WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
Derek Allard2067d1a2008-11-13 22:59:24 +0000530 }
Barry Mienydd671972010-10-04 16:33:58 +0200531
Derek Allard2067d1a2008-11-13 22:59:24 +0000532 return $sql;
533 }
534
535 // --------------------------------------------------------------------
536
537 /**
538 * Show column query
539 *
540 * Generates a platform-specific query string so that the column names can be fetched
541 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200542 * @param string the table name
543 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000544 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300545 protected function _list_columns($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000546 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200547 return 'SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = \''.$table.'\'';
Derek Allard2067d1a2008-11-13 22:59:24 +0000548 }
549
550 // --------------------------------------------------------------------
551
552 /**
553 * Field data query
554 *
555 * Generates a platform-specific query so that the column data can be retrieved
556 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200557 * @param string the table name
558 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000559 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300560 protected function _field_data($table)
Derek Allard2067d1a2008-11-13 22:59:24 +0000561 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200562 return 'SELECT * FROM '.$table.' WHERE rownum = 1';
Derek Allard2067d1a2008-11-13 22:59:24 +0000563 }
564
565 // --------------------------------------------------------------------
566
567 /**
Andrey Andreev4be5de12012-03-02 15:45:41 +0200568 * Error
Derek Allard2067d1a2008-11-13 22:59:24 +0000569 *
Andrey Andreev4be5de12012-03-02 15:45:41 +0200570 * Returns an array containing code and message of the last
571 * database error that has occured.
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200572 *
573 * @return array
574 */
Andrey Andreev4be5de12012-03-02 15:45:41 +0200575 public function error()
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200576 {
Andrey Andreev4be5de12012-03-02 15:45:41 +0200577 /* oci_error() returns an array that already contains the
578 * 'code' and 'message' keys, so we can just return it.
579 */
Andrey Andreev601f8b22012-03-01 20:11:15 +0200580 if (is_resource($this->curs_id))
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200581 {
Andrey Andreev601f8b22012-03-01 20:11:15 +0200582 return oci_error($this->curs_id);
583 }
584 elseif (is_resource($this->stmt_id))
585 {
586 return oci_error($this->stmt_id);
587 }
588 elseif (is_resource($this->conn_id))
589 {
590 return oci_error($this->conn_id);
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200591 }
592
Andrey Andreev601f8b22012-03-01 20:11:15 +0200593 return oci_error();
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200594 }
595
596 // --------------------------------------------------------------------
597
Derek Allard2067d1a2008-11-13 22:59:24 +0000598 /**
599 * Escape the SQL Identifiers
600 *
601 * This function escapes column and table names
602 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000603 * @param string
604 * @return string
605 */
Andrey Andreev4a315682012-01-26 02:03:10 +0200606 public function _escape_identifiers($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000607 {
608 if ($this->_escape_char == '')
609 {
610 return $item;
611 }
612
613 foreach ($this->_reserved_identifiers as $id)
614 {
615 if (strpos($item, '.'.$id) !== FALSE)
616 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200617 $item = str_replace('.', $this->_escape_char.'.', $item);
Barry Mienydd671972010-10-04 16:33:58 +0200618
Derek Allard2067d1a2008-11-13 22:59:24 +0000619 // remove duplicates if the user already included the escape
Andrey Andreevaa786c92012-01-16 12:14:45 +0200620 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
Barry Mienydd671972010-10-04 16:33:58 +0200621 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000622 }
Barry Mienydd671972010-10-04 16:33:58 +0200623
Derek Allard2067d1a2008-11-13 22:59:24 +0000624 if (strpos($item, '.') !== FALSE)
625 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200626 $item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
Derek Allard2067d1a2008-11-13 22:59:24 +0000627 }
Barry Mienydd671972010-10-04 16:33:58 +0200628
Derek Allard2067d1a2008-11-13 22:59:24 +0000629 // remove duplicates if the user already included the escape
Andrey Andreevaa786c92012-01-16 12:14:45 +0200630 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
Derek Allard2067d1a2008-11-13 22:59:24 +0000631 }
Barry Mienydd671972010-10-04 16:33:58 +0200632
Derek Allard2067d1a2008-11-13 22:59:24 +0000633 // --------------------------------------------------------------------
634
635 /**
636 * From Tables
637 *
638 * This function implicitly groups FROM tables so there is no confusion
639 * about operator precedence in harmony with SQL standards
640 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200641 * @param array
642 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000643 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300644 protected function _from_tables($tables)
Derek Allard2067d1a2008-11-13 22:59:24 +0000645 {
Andrey Andreeve35d7782012-01-19 15:56:20 +0200646 return is_array($tables) ? implode(', ', $tables) : $tables;
Derek Allard2067d1a2008-11-13 22:59:24 +0000647 }
648
649 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200650
Derek Allard2067d1a2008-11-13 22:59:24 +0000651 /**
652 * Insert statement
653 *
654 * Generates a platform-specific insert string from the supplied data
655 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200656 * @param string the table name
657 * @param array the insert keys
658 * @param array the insert values
659 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300661 protected function _insert($table, $keys, $values)
Derek Allard2067d1a2008-11-13 22:59:24 +0000662 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200663 return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
Derek Allard2067d1a2008-11-13 22:59:24 +0000664 }
665
666 // --------------------------------------------------------------------
667
668 /**
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300669 * Insert_batch statement
670 *
671 * Generates a platform-specific insert string from the supplied data
672 *
Andrey Andreevda123732012-03-20 22:27:40 +0200673 * @param string the table name
674 * @param array the insert keys
675 * @param array the insert values
676 * @return string
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300677 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300678 protected function _insert_batch($table, $keys, $values)
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300679 {
680 $keys = implode(', ', $keys);
681 $sql = "INSERT ALL\n";
682
683 for ($i = 0, $c = count($values); $i < $c; $i++)
Andrey Andreevb83c4082011-09-23 03:32:45 +0300684 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200685 $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i].'\n';
Andrey Andreevb83c4082011-09-23 03:32:45 +0300686 }
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300687
Andrey Andreevaa786c92012-01-16 12:14:45 +0200688 return $sql.'SELECT * FROM dual';
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300689 }
690
691 // --------------------------------------------------------------------
692
693 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000694 * Update statement
695 *
696 * Generates a platform-specific update string from the supplied data
697 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 * @param string the table name
699 * @param array the update data
700 * @param array the where clause
701 * @param array the orderby clause
702 * @param array the limit clause
703 * @return string
704 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300705 protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000706 {
Pascal Krietec3a4a8d2011-02-14 13:40:08 -0500707 foreach ($values as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000708 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200709 $valstr[] = $key.' = '.$val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000710 }
Barry Mienydd671972010-10-04 16:33:58 +0200711
Andrey Andreevaa786c92012-01-16 12:14:45 +0200712 return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
713 .(($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : '')
714 .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
715 .( ! $limit ? '' : ' LIMIT '.$limit);
Derek Allard2067d1a2008-11-13 22:59:24 +0000716 }
717
718 // --------------------------------------------------------------------
719
720 /**
721 * Truncate statement
722 *
723 * Generates a platform-specific truncate string from the supplied data
724 * If the database does not support the truncate() command
725 * This function maps to "DELETE FROM table"
726 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000727 * @param string the table name
728 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200729 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300730 protected function _truncate($table)
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200732 return 'TRUNCATE TABLE '.$table;
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 }
Barry Mienydd671972010-10-04 16:33:58 +0200734
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 // --------------------------------------------------------------------
736
737 /**
738 * Delete statement
739 *
740 * Generates a platform-specific delete string from the supplied data
741 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000742 * @param string the table name
743 * @param array the where clause
744 * @param string the limit clause
745 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200746 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300747 protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000748 {
749 $conditions = '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000750 if (count($where) > 0 OR count($like) > 0)
751 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200752 $conditions = "\nWHERE ".implode("\n", $this->ar_where);
Derek Allard2067d1a2008-11-13 22:59:24 +0000753
754 if (count($where) > 0 && count($like) > 0)
755 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200756 $conditions .= ' AND ';
Derek Allard2067d1a2008-11-13 22:59:24 +0000757 }
758 $conditions .= implode("\n", $like);
759 }
760
Andrey Andreevaa786c92012-01-16 12:14:45 +0200761 return 'DELETE FROM '.$table.$conditions.( ! $limit ? '' : ' LIMIT '.$limit);
Derek Allard2067d1a2008-11-13 22:59:24 +0000762 }
763
764 // --------------------------------------------------------------------
765
766 /**
767 * Limit string
768 *
769 * Generates a platform-specific LIMIT clause
770 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200771 * @param string the sql query string
772 * @param int the number of rows to limit the query to
773 * @param int the offset value
774 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000775 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300776 protected function _limit($sql, $limit, $offset)
Derek Allard2067d1a2008-11-13 22:59:24 +0000777 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000778 $this->limit_used = TRUE;
Andrey Andreevaa786c92012-01-16 12:14:45 +0200779 return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')'
780 .($offset != 0 ? ' WHERE rnum >= '.$offset : '');
Barry Mienydd671972010-10-04 16:33:58 +0200781 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000782
783 // --------------------------------------------------------------------
784
785 /**
786 * Close DB Connection
787 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200788 * @param resource
789 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000790 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300791 protected function _close($conn_id)
Derek Allard2067d1a2008-11-13 22:59:24 +0000792 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300793 @oci_close($conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000794 }
795
Derek Allard2067d1a2008-11-13 22:59:24 +0000796}
797
Derek Allard2067d1a2008-11-13 22:59:24 +0000798/* End of file oci8_driver.php */
Timothy Warren215890b2012-03-20 09:38:16 -0400799/* Location: ./system/database/drivers/oci8/oci8_driver.php */