blob: a8b410947c54f1d3a770714ec4f2c3bcf477dfc8 [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 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 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 */
50
51class CI_DB_oci8_driver extends CI_DB {
52
Andrey Andreev24abcb92012-01-05 20:40:15 +020053 public $dbdriver = 'oci8';
Barry Mienydd671972010-10-04 16:33:58 +020054
Derek Allard2067d1a2008-11-13 22:59:24 +000055 // The character used for excaping
Andrey Andreev24abcb92012-01-05 20:40:15 +020056 protected $_escape_char = '"';
Barry Mienydd671972010-10-04 16:33:58 +020057
Derek Jonese4ed5832009-02-20 21:44:59 +000058 // clause and character used for LIKE escape sequences
Andrey Andreev24abcb92012-01-05 20:40:15 +020059 protected $_like_escape_str = " escape '%s' ";
60 protected $_like_escape_chr = '!';
Barry Mienydd671972010-10-04 16:33:58 +020061
Derek Allard2067d1a2008-11-13 22:59:24 +000062 /**
63 * The syntax to count rows is slightly different across different
64 * database engines, so this string appears in each driver and is
65 * used for the count_all() and count_all_results() functions.
66 */
Andrey Andreev24abcb92012-01-05 20:40:15 +020067 protected $_count_string = 'SELECT COUNT(1) AS ';
68 protected $_random_keyword = ' ASC'; // not currently supported
Derek Allard2067d1a2008-11-13 22:59:24 +000069
70 // Set "auto commit" by default
Andrey Andreev24abcb92012-01-05 20:40:15 +020071 protected $_commit = OCI_COMMIT_ON_SUCCESS;
Derek Allard2067d1a2008-11-13 22:59:24 +000072
73 // need to track statement id and cursor id
Andrey Andreev24abcb92012-01-05 20:40:15 +020074 public $stmt_id;
75 public $curs_id;
Derek Allard2067d1a2008-11-13 22:59:24 +000076
77 // if we use a limit, we will add a field that will
78 // throw off num_fields later
Andrey Andreev24abcb92012-01-05 20:40:15 +020079 public $limit_used;
Derek Allard2067d1a2008-11-13 22:59:24 +000080
Andrey Andreevdad61c22012-02-13 01:08:06 +020081 public function __construct($params)
82 {
83 parent::__construct($params);
84
85 $valid_dsns = array(
Andrey Andreevdad61c22012-02-13 01:08:06 +020086 'tns' => '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS
Andrey Andreevfcd1f472012-02-13 09:30:16 +020087 // Easy Connect string (Oracle 10g+)
88 'ec' => '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i',
Andrey Andreevdad61c22012-02-13 01:08:06 +020089 'in' => '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora)
90 );
91
92 /* Space characters don't have any effect when actually
93 * connecting, but can be a hassle while validating the DSN.
94 */
95 $this->dsn = str_replace(array("\n", "\r", "\t", ' '), '', $this->dsn);
96
97 if ($this->dsn !== '')
98 {
99 foreach ($valid_dsns as $regexp)
100 {
101 if (preg_match($regexp, $this->dsn))
102 {
103 return;
104 }
105 }
106 }
107
108 // Legacy support for TNS in the hostname configuration field
109 $this->hostname = str_replace(array("\n", "\r", "\t", ' '), '', $this->hostname);
110 if (preg_match($valid_dsns['tns'], $this->hostname))
111 {
112 $this->dsn = $this->hostname;
113 return;
114 }
115 elseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE
116 && (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== ''))
117 {
118 /* If the hostname field isn't empty, doesn't contain
119 * ':' and/or '/' and if port and/or database aren't
120 * empty, then the hostname field is most likely indeed
121 * just a hostname. Therefore we'll try and build an
122 * Easy Connect string from these 3 settings, assuming
123 * that the database field is a service name.
124 */
125 $this->dsn = $this->hostname
126 .(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '')
127 .($this->database !== '' ? '/'.ltrim($this->database, '/') : '');
128
129 if (preg_match($valid_dsns['ec'], $this->dsn))
130 {
131 return;
132 }
133 }
134
135 /* At this point, we can only try and validate the hostname and
136 * database fields separately as DSNs.
137 */
138 if (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname))
139 {
140 $this->dsn = $this->hostname;
141 return;
142 }
143
144 $this->database = str_replace(array("\n", "\r", "\t", ' '), '', $this->database);
145 foreach ($valid_dsns as $regexp)
146 {
147 if (preg_match($regexp, $this->database))
148 {
149 return;
150 }
151 }
152
153 /* Well - OK, an empty string should work as well.
154 * PHP will try to use environment variables to
155 * determine which Oracle instance to connect to.
156 */
157 $this->dsn = '';
158 }
159
Derek Allard2067d1a2008-11-13 22:59:24 +0000160 /**
161 * Non-persistent database connection
162 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200163 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000164 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300165 public function db_connect()
Derek Allard2067d1a2008-11-13 22:59:24 +0000166 {
Andrey Andreevdad61c22012-02-13 01:08:06 +0200167 return ( ! empty($this->char_set))
168 ? @oci_connect($this->username, $this->password, $this->dsn, $this->char_set)
169 : @oci_connect($this->username, $this->password, $this->dsn);
Derek Allard2067d1a2008-11-13 22:59:24 +0000170 }
171
172 // --------------------------------------------------------------------
173
174 /**
175 * Persistent database connection
176 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200177 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000178 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300179 public function db_pconnect()
Derek Allard2067d1a2008-11-13 22:59:24 +0000180 {
Andrey Andreevdad61c22012-02-13 01:08:06 +0200181 return ( ! empty($this->char_set))
182 ? @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set)
183 : @oci_pconnect($this->username, $this->password, $this->dsn);
Derek Allard2067d1a2008-11-13 22:59:24 +0000184 }
185
186 // --------------------------------------------------------------------
187
188 /**
Derek Jones87cbafc2009-02-27 16:29:59 +0000189 * Reconnect
190 *
191 * Keep / reestablish the db connection if no queries have been
192 * sent for a length of time exceeding the server's idle timeout
193 *
Derek Jones87cbafc2009-02-27 16:29:59 +0000194 * @return void
195 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300196 public function reconnect()
Derek Jones87cbafc2009-02-27 16:29:59 +0000197 {
198 // not implemented in oracle
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300199 return;
Derek Jones87cbafc2009-02-27 16:29:59 +0000200 }
201
202 // --------------------------------------------------------------------
203
204 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 * Select the database
206 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200207 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000208 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300209 public function db_select()
Derek Allard2067d1a2008-11-13 22:59:24 +0000210 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300211 // Not in Oracle - schemas are actually usernames
Derek Allard2067d1a2008-11-13 22:59:24 +0000212 return TRUE;
213 }
214
215 // --------------------------------------------------------------------
216
217 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000218 * Version number query string
219 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200220 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000221 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300222 protected function _version()
Derek Allard2067d1a2008-11-13 22:59:24 +0000223 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300224 return oci_server_version($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000225 }
226
227 // --------------------------------------------------------------------
228
229 /**
230 * Execute the query
231 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200232 * @param string an SQL query
233 * @return resource
Derek Allard2067d1a2008-11-13 22:59:24 +0000234 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300235 protected function _execute($sql)
Derek Allard2067d1a2008-11-13 22:59:24 +0000236 {
Andrey Andreev24abcb92012-01-05 20:40:15 +0200237 /* Oracle must parse the query before it is run. All of the actions with
238 * the query are based on the statement id returned by oci_parse().
239 */
Derek Allard2067d1a2008-11-13 22:59:24 +0000240 $this->stmt_id = FALSE;
241 $this->_set_stmt_id($sql);
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300242 oci_set_prefetch($this->stmt_id, 1000);
243 return @oci_execute($this->stmt_id, $this->_commit);
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 }
245
246 /**
247 * Generate a statement ID
248 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200249 * @param string an SQL query
250 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000251 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300252 private function _set_stmt_id($sql)
Derek Allard2067d1a2008-11-13 22:59:24 +0000253 {
254 if ( ! is_resource($this->stmt_id))
255 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300256 $this->stmt_id = oci_parse($this->conn_id, $this->_prep_query($sql));
Derek Allard2067d1a2008-11-13 22:59:24 +0000257 }
258 }
259
260 // --------------------------------------------------------------------
261
262 /**
263 * Prep the query
264 *
265 * If needed, each database adapter can prep the query string
266 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200267 * @param string an SQL query
268 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000269 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300270 private function _prep_query($sql)
Derek Allard2067d1a2008-11-13 22:59:24 +0000271 {
272 return $sql;
273 }
274
275 // --------------------------------------------------------------------
276
277 /**
Andrey Andreevaa786c92012-01-16 12:14:45 +0200278 * getCursor. Returns a cursor from the database
Derek Allard2067d1a2008-11-13 22:59:24 +0000279 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200280 * @return resource cursor id
Derek Allard2067d1a2008-11-13 22:59:24 +0000281 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300282 public function get_cursor()
Derek Allard2067d1a2008-11-13 22:59:24 +0000283 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200284 return $this->curs_id = oci_new_cursor($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000285 }
286
287 // --------------------------------------------------------------------
288
289 /**
Derek Jones4b9c6292011-07-01 17:40:48 -0500290 * Stored Procedure. Executes a stored procedure
Derek Allard2067d1a2008-11-13 22:59:24 +0000291 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200292 * @param string package name in which the stored procedure is in
293 * @param string stored procedure name to execute
294 * @param array parameters
295 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000296 *
297 * params array keys
298 *
Derek Jones4b9c6292011-07-01 17:40:48 -0500299 * KEY OPTIONAL NOTES
Andrey Andreevaa786c92012-01-16 12:14:45 +0200300 * name no the name of the parameter should be in :<param_name> format
301 * value no the value of the parameter. If this is an OUT or IN OUT parameter,
302 * this should be a reference to a variable
303 * type yes the type of the parameter
304 * length yes the max size of the parameter
Derek Allard2067d1a2008-11-13 22:59:24 +0000305 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300306 public function stored_procedure($package, $procedure, $params)
Derek Allard2067d1a2008-11-13 22:59:24 +0000307 {
308 if ($package == '' OR $procedure == '' OR ! is_array($params))
309 {
310 if ($this->db_debug)
311 {
312 log_message('error', 'Invalid query: '.$package.'.'.$procedure);
Derek Allardfac8fbc2010-02-05 16:14:49 +0000313 return $this->display_error('db_invalid_query');
Derek Allard2067d1a2008-11-13 22:59:24 +0000314 }
315 return FALSE;
316 }
Barry Mienydd671972010-10-04 16:33:58 +0200317
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 // build the query string
Andrey Andreeve35d7782012-01-19 15:56:20 +0200319 $sql = 'BEGIN '.$package.'.'.$procedure.'(';
Derek Allard2067d1a2008-11-13 22:59:24 +0000320
321 $have_cursor = FALSE;
Pascal Krietec3a4a8d2011-02-14 13:40:08 -0500322 foreach ($params as $param)
Derek Allard2067d1a2008-11-13 22:59:24 +0000323 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200324 $sql .= $param['name'].',';
Barry Mienydd671972010-10-04 16:33:58 +0200325
Andrey Andreev85facfa2012-01-26 14:12:14 +0200326 if (isset($param['type']) && $param['type'] === OCI_B_CURSOR)
Derek Allard2067d1a2008-11-13 22:59:24 +0000327 {
328 $have_cursor = TRUE;
329 }
330 }
Andrey Andreevaa786c92012-01-16 12:14:45 +0200331 $sql = trim($sql, ',') . '); END;';
Barry Mienydd671972010-10-04 16:33:58 +0200332
Derek Allard2067d1a2008-11-13 22:59:24 +0000333 $this->stmt_id = FALSE;
334 $this->_set_stmt_id($sql);
335 $this->_bind_params($params);
Andrey Andreevaa786c92012-01-16 12:14:45 +0200336 return $this->query($sql, FALSE, $have_cursor);
Derek Allard2067d1a2008-11-13 22:59:24 +0000337 }
Barry Mienydd671972010-10-04 16:33:58 +0200338
Derek Allard2067d1a2008-11-13 22:59:24 +0000339 // --------------------------------------------------------------------
340
341 /**
342 * Bind parameters
343 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200344 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000345 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300346 private function _bind_params($params)
Derek Allard2067d1a2008-11-13 22:59:24 +0000347 {
348 if ( ! is_array($params) OR ! is_resource($this->stmt_id))
349 {
350 return;
351 }
Barry Mienydd671972010-10-04 16:33:58 +0200352
Derek Allard2067d1a2008-11-13 22:59:24 +0000353 foreach ($params as $param)
354 {
Barry Mienydd671972010-10-04 16:33:58 +0200355 foreach (array('name', 'value', 'type', 'length') as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000356 {
357 if ( ! isset($param[$val]))
358 {
359 $param[$val] = '';
360 }
361 }
362
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300363 oci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000364 }
365 }
366
367 // --------------------------------------------------------------------
368
369 /**
370 * Begin Transaction
371 *
Barry Mienydd671972010-10-04 16:33:58 +0200372 * @return bool
373 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300374 public function trans_begin($test_mode = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000375 {
376 if ( ! $this->trans_enabled)
377 {
378 return TRUE;
379 }
Barry Mienydd671972010-10-04 16:33:58 +0200380
Derek Allard2067d1a2008-11-13 22:59:24 +0000381 // When transactions are nested we only begin/commit/rollback the outermost ones
382 if ($this->_trans_depth > 0)
383 {
384 return TRUE;
385 }
Barry Mienydd671972010-10-04 16:33:58 +0200386
Derek Allard2067d1a2008-11-13 22:59:24 +0000387 // Reset the transaction failure flag.
388 // If the $test_mode flag is set to TRUE transactions will be rolled back
389 // even if the queries produce a successful result.
390 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
Barry Mienydd671972010-10-04 16:33:58 +0200391
Andrey Andreev24abcb92012-01-05 20:40:15 +0200392 $this->_commit = (is_php('5.3.2')) ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT;
Derek Allard2067d1a2008-11-13 22:59:24 +0000393 return TRUE;
394 }
395
396 // --------------------------------------------------------------------
397
398 /**
399 * Commit Transaction
400 *
Barry Mienydd671972010-10-04 16:33:58 +0200401 * @return bool
402 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300403 public function trans_commit()
Derek Allard2067d1a2008-11-13 22:59:24 +0000404 {
405 if ( ! $this->trans_enabled)
406 {
407 return TRUE;
408 }
409
410 // When transactions are nested we only begin/commit/rollback the outermost ones
411 if ($this->_trans_depth > 0)
412 {
413 return TRUE;
414 }
415
Derek Allard2067d1a2008-11-13 22:59:24 +0000416 $this->_commit = OCI_COMMIT_ON_SUCCESS;
Andrey Andreev24abcb92012-01-05 20:40:15 +0200417 return oci_commit($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000418 }
419
420 // --------------------------------------------------------------------
421
422 /**
423 * Rollback Transaction
424 *
Barry Mienydd671972010-10-04 16:33:58 +0200425 * @return bool
426 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300427 public function trans_rollback()
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000429 // When transactions are nested we only begin/commit/rollback the outermost ones
Andrey Andreeve35d7782012-01-19 15:56:20 +0200430 if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000431 {
432 return TRUE;
433 }
434
Derek Allard2067d1a2008-11-13 22:59:24 +0000435 $this->_commit = OCI_COMMIT_ON_SUCCESS;
Andrey Andreev24abcb92012-01-05 20:40:15 +0200436 return oci_rollback($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000437 }
438
439 // --------------------------------------------------------------------
440
441 /**
442 * Escape String
443 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200444 * @param string
Derek Jonese4ed5832009-02-20 21:44:59 +0000445 * @param bool whether or not the string will be used in a LIKE condition
Andrey Andreevaa786c92012-01-16 12:14:45 +0200446 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000447 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300448 public function escape_str($str, $like = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000449 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000450 if (is_array($str))
451 {
Pascal Krietec3a4a8d2011-02-14 13:40:08 -0500452 foreach ($str as $key => $val)
Barry Mienydd671972010-10-04 16:33:58 +0200453 {
Derek Jonese4ed5832009-02-20 21:44:59 +0000454 $str[$key] = $this->escape_str($val, $like);
Barry Mienydd671972010-10-04 16:33:58 +0200455 }
456
457 return $str;
458 }
Derek Jonese4ed5832009-02-20 21:44:59 +0000459
Andrey Andreevaa786c92012-01-16 12:14:45 +0200460 $str = str_replace("'", "''", remove_invisible_characters($str));
Barry Mienydd671972010-10-04 16:33:58 +0200461
Derek Jonese4ed5832009-02-20 21:44:59 +0000462 // escape LIKE condition wildcards
463 if ($like === TRUE)
464 {
Andrey Andreevc2905f52012-03-01 14:39:26 +0200465 return str_replace(array($this->_like_escape_chr, '%', '_'),
Andrey Andreev08c7c622012-02-28 13:23:38 +0200466 array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
Andrey Andreevaa786c92012-01-16 12:14:45 +0200467 $str);
Derek Jonese4ed5832009-02-20 21:44:59 +0000468 }
Barry Mienydd671972010-10-04 16:33:58 +0200469
Derek Jonese4ed5832009-02-20 21:44:59 +0000470 return $str;
Derek Allard2067d1a2008-11-13 22:59:24 +0000471 }
472
473 // --------------------------------------------------------------------
474
475 /**
476 * Affected Rows
477 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200478 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000479 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300480 public function affected_rows()
Derek Allard2067d1a2008-11-13 22:59:24 +0000481 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300482 return @oci_num_rows($this->stmt_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000483 }
484
485 // --------------------------------------------------------------------
486
487 /**
488 * Insert ID
489 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200490 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000491 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300492 public function insert_id()
Derek Allard2067d1a2008-11-13 22:59:24 +0000493 {
494 // not supported in oracle
Derek Allardfac8fbc2010-02-05 16:14:49 +0000495 return $this->display_error('db_unsupported_function');
Derek Allard2067d1a2008-11-13 22:59:24 +0000496 }
497
498 // --------------------------------------------------------------------
499
500 /**
501 * "Count All" query
502 *
503 * Generates a platform-specific query string that counts all records in
504 * the specified database
505 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200506 * @param string
507 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000508 */
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300509 public function count_all($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000510 {
511 if ($table == '')
Derek Allarde37ab382009-02-03 16:13:57 +0000512 {
513 return 0;
514 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000515
Andrey Andreevaa786c92012-01-16 12:14:45 +0200516 $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 +0000517
518 if ($query == FALSE)
Derek Allarde37ab382009-02-03 16:13:57 +0000519 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000520 return 0;
Derek Allarde37ab382009-02-03 16:13:57 +0000521 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000522
523 $row = $query->row();
Greg Aker90248ab2011-08-20 14:23:14 -0500524 $this->_reset_select();
Derek Allarde37ab382009-02-03 16:13:57 +0000525 return (int) $row->numrows;
Derek Allard2067d1a2008-11-13 22:59:24 +0000526 }
527
528 // --------------------------------------------------------------------
529
530 /**
531 * Show table query
532 *
533 * Generates a platform-specific query string so that the table names can be fetched
534 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200535 * @param bool
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300536 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000537 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300538 protected function _list_tables($prefix_limit = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000539 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200540 $sql = 'SELECT TABLE_NAME FROM ALL_TABLES';
Derek Allard2067d1a2008-11-13 22:59:24 +0000541
Andrey Andreev1ab62ae2012-01-20 13:04:10 +0200542 if ($prefix_limit !== FALSE && $this->dbprefix != '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000543 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200544 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 +0000545 }
Barry Mienydd671972010-10-04 16:33:58 +0200546
Derek Allard2067d1a2008-11-13 22:59:24 +0000547 return $sql;
548 }
549
550 // --------------------------------------------------------------------
551
552 /**
553 * Show column query
554 *
555 * Generates a platform-specific query string so that the column names can be fetched
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 _list_columns($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000561 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200562 return 'SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = \''.$table.'\'';
Derek Allard2067d1a2008-11-13 22:59:24 +0000563 }
564
565 // --------------------------------------------------------------------
566
567 /**
568 * Field data query
569 *
570 * Generates a platform-specific query so that the column data can be retrieved
571 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200572 * @param string the table name
573 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000574 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300575 protected function _field_data($table)
Derek Allard2067d1a2008-11-13 22:59:24 +0000576 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200577 return 'SELECT * FROM '.$table.' WHERE rownum = 1';
Derek Allard2067d1a2008-11-13 22:59:24 +0000578 }
579
580 // --------------------------------------------------------------------
581
582 /**
583 * The error message string
584 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200585 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000586 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300587 protected function _error_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000588 {
Andrey Andreev601f8b22012-03-01 20:11:15 +0200589 $error = $this->_oci8_error_data();
Derek Allard2067d1a2008-11-13 22:59:24 +0000590 return $error['message'];
591 }
592
593 // --------------------------------------------------------------------
594
595 /**
596 * The error message number
597 *
Andrey Andreev601f8b22012-03-01 20:11:15 +0200598 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000599 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300600 protected function _error_number()
Derek Allard2067d1a2008-11-13 22:59:24 +0000601 {
Andrey Andreev601f8b22012-03-01 20:11:15 +0200602 $error = $this->_oci8_error_data();
Derek Allard2067d1a2008-11-13 22:59:24 +0000603 return $error['code'];
604 }
Barry Mienydd671972010-10-04 16:33:58 +0200605
Derek Allard2067d1a2008-11-13 22:59:24 +0000606 // --------------------------------------------------------------------
607
608 /**
Andrey Andreev601f8b22012-03-01 20:11:15 +0200609 * OCI8-specific method to get errors.
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200610 *
Andrey Andreev601f8b22012-03-01 20:11:15 +0200611 * Used by _error_message() and _error_code().
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200612 *
613 * @return array
614 */
Andrey Andreev601f8b22012-03-01 20:11:15 +0200615 protected function _oci8_error_data()
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200616 {
Andrey Andreev601f8b22012-03-01 20:11:15 +0200617 if (is_resource($this->curs_id))
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200618 {
Andrey Andreev601f8b22012-03-01 20:11:15 +0200619 return oci_error($this->curs_id);
620 }
621 elseif (is_resource($this->stmt_id))
622 {
623 return oci_error($this->stmt_id);
624 }
625 elseif (is_resource($this->conn_id))
626 {
627 return oci_error($this->conn_id);
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200628 }
629
Andrey Andreev601f8b22012-03-01 20:11:15 +0200630 return oci_error();
Andrey Andreev6ea08e62012-01-05 21:43:17 +0200631 }
632
633 // --------------------------------------------------------------------
634
Derek Allard2067d1a2008-11-13 22:59:24 +0000635 /**
636 * Escape the SQL Identifiers
637 *
638 * This function escapes column and table names
639 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000640 * @param string
641 * @return string
642 */
Andrey Andreev4a315682012-01-26 02:03:10 +0200643 public function _escape_identifiers($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000644 {
645 if ($this->_escape_char == '')
646 {
647 return $item;
648 }
649
650 foreach ($this->_reserved_identifiers as $id)
651 {
652 if (strpos($item, '.'.$id) !== FALSE)
653 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200654 $item = str_replace('.', $this->_escape_char.'.', $item);
Barry Mienydd671972010-10-04 16:33:58 +0200655
Derek Allard2067d1a2008-11-13 22:59:24 +0000656 // remove duplicates if the user already included the escape
Andrey Andreevaa786c92012-01-16 12:14:45 +0200657 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
Barry Mienydd671972010-10-04 16:33:58 +0200658 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000659 }
Barry Mienydd671972010-10-04 16:33:58 +0200660
Derek Allard2067d1a2008-11-13 22:59:24 +0000661 if (strpos($item, '.') !== FALSE)
662 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200663 $item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
Derek Allard2067d1a2008-11-13 22:59:24 +0000664 }
Barry Mienydd671972010-10-04 16:33:58 +0200665
Derek Allard2067d1a2008-11-13 22:59:24 +0000666 // remove duplicates if the user already included the escape
Andrey Andreevaa786c92012-01-16 12:14:45 +0200667 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
Derek Allard2067d1a2008-11-13 22:59:24 +0000668 }
Barry Mienydd671972010-10-04 16:33:58 +0200669
Derek Allard2067d1a2008-11-13 22:59:24 +0000670 // --------------------------------------------------------------------
671
672 /**
673 * From Tables
674 *
675 * This function implicitly groups FROM tables so there is no confusion
676 * about operator precedence in harmony with SQL standards
677 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200678 * @param array
679 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000680 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300681 protected function _from_tables($tables)
Derek Allard2067d1a2008-11-13 22:59:24 +0000682 {
Andrey Andreeve35d7782012-01-19 15:56:20 +0200683 return is_array($tables) ? implode(', ', $tables) : $tables;
Derek Allard2067d1a2008-11-13 22:59:24 +0000684 }
685
686 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200687
Derek Allard2067d1a2008-11-13 22:59:24 +0000688 /**
689 * Insert statement
690 *
691 * Generates a platform-specific insert string from the supplied data
692 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200693 * @param string the table name
694 * @param array the insert keys
695 * @param array the insert values
696 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000697 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300698 protected function _insert($table, $keys, $values)
Derek Allard2067d1a2008-11-13 22:59:24 +0000699 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200700 return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
Derek Allard2067d1a2008-11-13 22:59:24 +0000701 }
702
703 // --------------------------------------------------------------------
704
705 /**
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300706 * Insert_batch statement
707 *
708 * Generates a platform-specific insert string from the supplied data
709 *
Greg Aker03abee32011-12-25 00:31:29 -0600710 * @param string the table name
711 * @param array the insert keys
712 * @param array the insert values
713 * @return string
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300714 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300715 protected function _insert_batch($table, $keys, $values)
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300716 {
717 $keys = implode(', ', $keys);
718 $sql = "INSERT ALL\n";
719
720 for ($i = 0, $c = count($values); $i < $c; $i++)
Andrey Andreevb83c4082011-09-23 03:32:45 +0300721 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200722 $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i].'\n';
Andrey Andreevb83c4082011-09-23 03:32:45 +0300723 }
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300724
Andrey Andreevaa786c92012-01-16 12:14:45 +0200725 return $sql.'SELECT * FROM dual';
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300726 }
727
728 // --------------------------------------------------------------------
729
730 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 * Update statement
732 *
733 * Generates a platform-specific update string from the supplied data
734 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 * @param string the table name
736 * @param array the update data
737 * @param array the where clause
738 * @param array the orderby clause
739 * @param array the limit clause
740 * @return string
741 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300742 protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000743 {
Pascal Krietec3a4a8d2011-02-14 13:40:08 -0500744 foreach ($values as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000745 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200746 $valstr[] = $key.' = '.$val;
Derek Allard2067d1a2008-11-13 22:59:24 +0000747 }
Barry Mienydd671972010-10-04 16:33:58 +0200748
Andrey Andreevaa786c92012-01-16 12:14:45 +0200749 return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
750 .(($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : '')
751 .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
752 .( ! $limit ? '' : ' LIMIT '.$limit);
Derek Allard2067d1a2008-11-13 22:59:24 +0000753 }
754
755 // --------------------------------------------------------------------
756
757 /**
758 * Truncate statement
759 *
760 * Generates a platform-specific truncate string from the supplied data
761 * If the database does not support the truncate() command
762 * This function maps to "DELETE FROM table"
763 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000764 * @param string the table name
765 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200766 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300767 protected function _truncate($table)
Derek Allard2067d1a2008-11-13 22:59:24 +0000768 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200769 return 'TRUNCATE TABLE '.$table;
Derek Allard2067d1a2008-11-13 22:59:24 +0000770 }
Barry Mienydd671972010-10-04 16:33:58 +0200771
Derek Allard2067d1a2008-11-13 22:59:24 +0000772 // --------------------------------------------------------------------
773
774 /**
775 * Delete statement
776 *
777 * Generates a platform-specific delete string from the supplied data
778 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000779 * @param string the table name
780 * @param array the where clause
781 * @param string the limit clause
782 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200783 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300784 protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000785 {
786 $conditions = '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000787 if (count($where) > 0 OR count($like) > 0)
788 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200789 $conditions = "\nWHERE ".implode("\n", $this->ar_where);
Derek Allard2067d1a2008-11-13 22:59:24 +0000790
791 if (count($where) > 0 && count($like) > 0)
792 {
Andrey Andreevaa786c92012-01-16 12:14:45 +0200793 $conditions .= ' AND ';
Derek Allard2067d1a2008-11-13 22:59:24 +0000794 }
795 $conditions .= implode("\n", $like);
796 }
797
Andrey Andreevaa786c92012-01-16 12:14:45 +0200798 return 'DELETE FROM '.$table.$conditions.( ! $limit ? '' : ' LIMIT '.$limit);
Derek Allard2067d1a2008-11-13 22:59:24 +0000799 }
800
801 // --------------------------------------------------------------------
802
803 /**
804 * Limit string
805 *
806 * Generates a platform-specific LIMIT clause
807 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200808 * @param string the sql query string
809 * @param int the number of rows to limit the query to
810 * @param int the offset value
811 * @return string
Derek Allard2067d1a2008-11-13 22:59:24 +0000812 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300813 protected function _limit($sql, $limit, $offset)
Derek Allard2067d1a2008-11-13 22:59:24 +0000814 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000815 $this->limit_used = TRUE;
Andrey Andreevaa786c92012-01-16 12:14:45 +0200816 return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')'
817 .($offset != 0 ? ' WHERE rnum >= '.$offset : '');
Barry Mienydd671972010-10-04 16:33:58 +0200818 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000819
820 // --------------------------------------------------------------------
821
822 /**
823 * Close DB Connection
824 *
Andrey Andreevaa786c92012-01-16 12:14:45 +0200825 * @param resource
826 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000827 */
Andrey Andreevbc95e472011-10-20 09:44:48 +0300828 protected function _close($conn_id)
Derek Allard2067d1a2008-11-13 22:59:24 +0000829 {
Andrey Andreev5c3a2022011-10-07 21:04:58 +0300830 @oci_close($conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000831 }
832
Derek Allard2067d1a2008-11-13 22:59:24 +0000833}
834
Derek Allard2067d1a2008-11-13 22:59:24 +0000835/* End of file oci8_driver.php */
Andrey Andreev99c6dd42011-09-23 03:07:01 +0300836/* Location: ./system/database/drivers/oci8/oci8_driver.php */