1
|
|
|
<?php if ( ! defined('BASEPATH')) { |
2
|
|
|
exit('No direct script access allowed'); |
3
|
|
|
} |
4
|
|
|
/** |
5
|
|
|
* CodeIgniter |
6
|
|
|
* |
7
|
|
|
* An open source application development framework for PHP 5.1.6 or newer |
8
|
|
|
* |
9
|
|
|
* @package CodeIgniter |
10
|
|
|
* @author ExpressionEngine Dev Team |
11
|
|
|
* @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. |
12
|
|
|
* @license http://codeigniter.com/user_guide/license.html |
13
|
|
|
* @link http://codeigniter.com |
14
|
|
|
* @since Version 1.0 |
15
|
|
|
* @filesource |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
// ------------------------------------------------------------------------ |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* oci8 Database Adapter Class |
22
|
|
|
* |
23
|
|
|
* Note: _DB is an extender class that the app controller |
24
|
|
|
* creates dynamically based on whether the active record |
25
|
|
|
* class is being used or not. |
26
|
|
|
* |
27
|
|
|
* @package CodeIgniter |
28
|
|
|
* @subpackage Drivers |
29
|
|
|
* @category Database |
30
|
|
|
* @author ExpressionEngine Dev Team |
31
|
|
|
* @link http://codeigniter.com/user_guide/database/ |
32
|
|
|
*/ |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* oci8 Database Adapter Class |
36
|
|
|
* |
37
|
|
|
* This is a modification of the DB_driver class to |
38
|
|
|
* permit access to oracle databases |
39
|
|
|
* |
40
|
|
|
* @author Kelly McArdle |
41
|
|
|
* |
42
|
|
|
*/ |
43
|
|
|
|
44
|
|
|
class CI_DB_oci8_driver extends CI_DB { |
45
|
|
|
|
46
|
|
|
var $dbdriver = 'oci8'; |
47
|
|
|
|
48
|
|
|
// The character used for excaping |
49
|
|
|
var $_escape_char = '"'; |
50
|
|
|
|
51
|
|
|
// clause and character used for LIKE escape sequences |
52
|
|
|
var $_like_escape_str = " escape '%s' "; |
53
|
|
|
var $_like_escape_chr = '!'; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* The syntax to count rows is slightly different across different |
57
|
|
|
* database engines, so this string appears in each driver and is |
58
|
|
|
* used for the count_all() and count_all_results() functions. |
59
|
|
|
*/ |
60
|
|
|
var $_count_string = "SELECT COUNT(1) AS "; |
61
|
|
|
var $_random_keyword = ' ASC'; // not currently supported |
62
|
|
|
|
63
|
|
|
// Set "auto commit" by default |
64
|
|
|
var $_commit = OCI_COMMIT_ON_SUCCESS; |
65
|
|
|
|
66
|
|
|
// need to track statement id and cursor id |
67
|
|
|
var $stmt_id; |
68
|
|
|
var $curs_id; |
69
|
|
|
|
70
|
|
|
// if we use a limit, we will add a field that will |
71
|
|
|
// throw off num_fields later |
72
|
|
|
var $limit_used; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Non-persistent database connection |
76
|
|
|
* |
77
|
|
|
* @access private called by the base class |
78
|
|
|
* @return resource |
79
|
|
|
*/ |
80
|
|
|
public function db_connect() |
81
|
|
|
{ |
82
|
|
|
return @oci_connect($this->username, $this->password, $this->hostname, $this->char_set); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// -------------------------------------------------------------------- |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Persistent database connection |
89
|
|
|
* |
90
|
|
|
* @access private called by the base class |
91
|
|
|
* @return resource |
92
|
|
|
*/ |
93
|
|
|
public function db_pconnect() |
94
|
|
|
{ |
95
|
|
|
return @oci_pconnect($this->username, $this->password, $this->hostname, $this->char_set); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
// -------------------------------------------------------------------- |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Reconnect |
102
|
|
|
* |
103
|
|
|
* Keep / reestablish the db connection if no queries have been |
104
|
|
|
* sent for a length of time exceeding the server's idle timeout |
105
|
|
|
* |
106
|
|
|
* @access public |
107
|
|
|
* @return void |
108
|
|
|
*/ |
109
|
|
|
public function reconnect() |
110
|
|
|
{ |
111
|
|
|
// not implemented in oracle |
112
|
|
|
return; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
// -------------------------------------------------------------------- |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Select the database |
119
|
|
|
* |
120
|
|
|
* @access private called by the base class |
121
|
|
|
* @return boolean |
122
|
|
|
*/ |
123
|
|
|
public function db_select() |
124
|
|
|
{ |
125
|
|
|
// Not in Oracle - schemas are actually usernames |
126
|
|
|
return TRUE; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
// -------------------------------------------------------------------- |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Set client character set |
133
|
|
|
* |
134
|
|
|
* @access public |
135
|
|
|
* @param string |
136
|
|
|
* @param string |
137
|
|
|
* @return boolean |
138
|
|
|
*/ |
139
|
|
|
public function db_set_charset($charset, $collation) |
140
|
|
|
{ |
141
|
|
|
// @todo - add support if needed |
142
|
|
|
return TRUE; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
// -------------------------------------------------------------------- |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Version number query string |
149
|
|
|
* |
150
|
|
|
* @access protected |
151
|
|
|
* @return string |
152
|
|
|
*/ |
153
|
|
|
protected function _version() |
154
|
|
|
{ |
155
|
|
|
return oci_server_version($this->conn_id); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
// -------------------------------------------------------------------- |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Execute the query |
162
|
|
|
* |
163
|
|
|
* @access protected called by the base class |
164
|
|
|
* @param string an SQL query |
165
|
|
|
* @return resource |
166
|
|
|
*/ |
167
|
|
|
protected function _execute($sql) |
168
|
|
|
{ |
169
|
|
|
// oracle must parse the query before it is run. All of the actions with |
170
|
|
|
// the query are based on the statement id returned by ociparse |
171
|
|
|
$this->stmt_id = FALSE; |
172
|
|
|
$this->_set_stmt_id($sql); |
173
|
|
|
oci_set_prefetch($this->stmt_id, 1000); |
174
|
|
|
return @oci_execute($this->stmt_id, $this->_commit); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Generate a statement ID |
179
|
|
|
* |
180
|
|
|
* @access private |
181
|
|
|
* @param string an SQL query |
182
|
|
|
* @return none |
183
|
|
|
*/ |
184
|
|
|
private function _set_stmt_id($sql) |
185
|
|
|
{ |
186
|
|
|
if ( ! is_resource($this->stmt_id)) |
187
|
|
|
{ |
188
|
|
|
$this->stmt_id = oci_parse($this->conn_id, $this->_prep_query($sql)); |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
// -------------------------------------------------------------------- |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Prep the query |
196
|
|
|
* |
197
|
|
|
* If needed, each database adapter can prep the query string |
198
|
|
|
* |
199
|
|
|
* @access private called by execute() |
200
|
|
|
* @param string an SQL query |
201
|
|
|
* @return string |
202
|
|
|
*/ |
203
|
|
|
private function _prep_query($sql) |
204
|
|
|
{ |
205
|
|
|
return $sql; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
// -------------------------------------------------------------------- |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* getCursor. Returns a cursor from the datbase |
212
|
|
|
* |
213
|
|
|
* @access public |
214
|
|
|
* @return resource id |
215
|
|
|
*/ |
216
|
|
|
public function get_cursor() |
217
|
|
|
{ |
218
|
|
|
$this->curs_id = oci_new_cursor($this->conn_id); |
219
|
|
|
return $this->curs_id; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
// -------------------------------------------------------------------- |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Stored Procedure. Executes a stored procedure |
226
|
|
|
* |
227
|
|
|
* @access public |
228
|
|
|
* @param package package stored procedure is in |
229
|
|
|
* @param procedure stored procedure to execute |
230
|
|
|
* @param params array of parameters |
231
|
|
|
* @return array |
232
|
|
|
* |
233
|
|
|
* params array keys |
234
|
|
|
* |
235
|
|
|
* KEY OPTIONAL NOTES |
236
|
|
|
* name no the name of the parameter should be in :<param_name> format |
237
|
|
|
* value no the value of the parameter. If this is an OUT or IN OUT parameter, |
238
|
|
|
* this should be a reference to a variable |
239
|
|
|
* type yes the type of the parameter |
240
|
|
|
* length yes the max size of the parameter |
241
|
|
|
*/ |
242
|
|
|
public function stored_procedure($package, $procedure, $params) |
243
|
|
|
{ |
244
|
|
|
if ($package == '' OR $procedure == '' OR ! is_array($params)) |
245
|
|
|
{ |
246
|
|
View Code Duplication |
if ($this->db_debug) |
247
|
|
|
{ |
248
|
|
|
log_message('error', 'Invalid query: '.$package.'.'.$procedure); |
249
|
|
|
return $this->display_error('db_invalid_query'); |
250
|
|
|
} |
251
|
|
|
return FALSE; |
|
|
|
|
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
// build the query string |
255
|
|
|
$sql = "begin $package.$procedure("; |
256
|
|
|
|
257
|
|
|
$have_cursor = FALSE; |
258
|
|
|
foreach ($params as $param) |
259
|
|
|
{ |
260
|
|
|
$sql .= $param['name'].","; |
261
|
|
|
|
262
|
|
|
if (array_key_exists('type', $param) && ($param['type'] === OCI_B_CURSOR)) |
263
|
|
|
{ |
264
|
|
|
$have_cursor = TRUE; |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
$sql = trim($sql, ",")."); end;"; |
268
|
|
|
|
269
|
|
|
$this->stmt_id = FALSE; |
270
|
|
|
$this->_set_stmt_id($sql); |
271
|
|
|
$this->_bind_params($params); |
272
|
|
|
$this->query($sql, FALSE, $have_cursor); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
// -------------------------------------------------------------------- |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Bind parameters |
279
|
|
|
* |
280
|
|
|
* @access private |
281
|
|
|
* @return none |
282
|
|
|
*/ |
283
|
|
|
private function _bind_params($params) |
284
|
|
|
{ |
285
|
|
|
if ( ! is_array($params) OR ! is_resource($this->stmt_id)) |
286
|
|
|
{ |
287
|
|
|
return; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
foreach ($params as $param) |
291
|
|
|
{ |
292
|
|
|
foreach (array('name', 'value', 'type', 'length') as $val) |
293
|
|
|
{ |
294
|
|
|
if ( ! isset($param[$val])) |
295
|
|
|
{ |
296
|
|
|
$param[$val] = ''; |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
oci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']); |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
// -------------------------------------------------------------------- |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Begin Transaction |
308
|
|
|
* |
309
|
|
|
* @access public |
310
|
|
|
* @return bool |
311
|
|
|
*/ |
312
|
|
View Code Duplication |
public function trans_begin($test_mode = FALSE) |
313
|
|
|
{ |
314
|
|
|
if ( ! $this->trans_enabled) |
315
|
|
|
{ |
316
|
|
|
return TRUE; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
// When transactions are nested we only begin/commit/rollback the outermost ones |
320
|
|
|
if ($this->_trans_depth > 0) |
321
|
|
|
{ |
322
|
|
|
return TRUE; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
// Reset the transaction failure flag. |
326
|
|
|
// If the $test_mode flag is set to TRUE transactions will be rolled back |
327
|
|
|
// even if the queries produce a successful result. |
328
|
|
|
$this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; |
329
|
|
|
|
330
|
|
|
$this->_commit = OCI_DEFAULT; |
331
|
|
|
return TRUE; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
// -------------------------------------------------------------------- |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Commit Transaction |
338
|
|
|
* |
339
|
|
|
* @access public |
340
|
|
|
* @return bool |
341
|
|
|
*/ |
342
|
|
View Code Duplication |
public function trans_commit() |
343
|
|
|
{ |
344
|
|
|
if ( ! $this->trans_enabled) |
345
|
|
|
{ |
346
|
|
|
return TRUE; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
// When transactions are nested we only begin/commit/rollback the outermost ones |
350
|
|
|
if ($this->_trans_depth > 0) |
351
|
|
|
{ |
352
|
|
|
return TRUE; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
$ret = oci_commit($this->conn_id); |
356
|
|
|
$this->_commit = OCI_COMMIT_ON_SUCCESS; |
357
|
|
|
return $ret; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
// -------------------------------------------------------------------- |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* Rollback Transaction |
364
|
|
|
* |
365
|
|
|
* @access public |
366
|
|
|
* @return bool |
367
|
|
|
*/ |
368
|
|
View Code Duplication |
public function trans_rollback() |
369
|
|
|
{ |
370
|
|
|
if ( ! $this->trans_enabled) |
371
|
|
|
{ |
372
|
|
|
return TRUE; |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
// When transactions are nested we only begin/commit/rollback the outermost ones |
376
|
|
|
if ($this->_trans_depth > 0) |
377
|
|
|
{ |
378
|
|
|
return TRUE; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
$ret = oci_rollback($this->conn_id); |
382
|
|
|
$this->_commit = OCI_COMMIT_ON_SUCCESS; |
383
|
|
|
return $ret; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
// -------------------------------------------------------------------- |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* Escape String |
390
|
|
|
* |
391
|
|
|
* @access public |
392
|
|
|
* @param string |
393
|
|
|
* @param bool whether or not the string will be used in a LIKE condition |
394
|
|
|
* @return string |
395
|
|
|
*/ |
396
|
|
View Code Duplication |
public function escape_str($str, $like = FALSE) |
397
|
|
|
{ |
398
|
|
|
if (is_array($str)) |
399
|
|
|
{ |
400
|
|
|
foreach ($str as $key => $val) |
401
|
|
|
{ |
402
|
|
|
$str[$key] = $this->escape_str($val, $like); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
return $str; |
|
|
|
|
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
$str = remove_invisible_characters($str); |
409
|
|
|
|
410
|
|
|
// escape LIKE condition wildcards |
411
|
|
|
if ($like === TRUE) |
412
|
|
|
{ |
413
|
|
|
$str = str_replace(array('%', '_', $this->_like_escape_chr), |
414
|
|
|
array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), |
415
|
|
|
$str); |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
return $str; |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
// -------------------------------------------------------------------- |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Affected Rows |
425
|
|
|
* |
426
|
|
|
* @access public |
427
|
|
|
* @return integer |
428
|
|
|
*/ |
429
|
|
|
public function affected_rows() |
430
|
|
|
{ |
431
|
|
|
return @oci_num_rows($this->stmt_id); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
// -------------------------------------------------------------------- |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Insert ID |
438
|
|
|
* |
439
|
|
|
* @access public |
440
|
|
|
* @return integer |
441
|
|
|
*/ |
442
|
|
|
public function insert_id() |
443
|
|
|
{ |
444
|
|
|
// not supported in oracle |
445
|
|
|
return $this->display_error('db_unsupported_function'); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
// -------------------------------------------------------------------- |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* "Count All" query |
452
|
|
|
* |
453
|
|
|
* Generates a platform-specific query string that counts all records in |
454
|
|
|
* the specified database |
455
|
|
|
* |
456
|
|
|
* @access public |
457
|
|
|
* @param string |
458
|
|
|
* @return integer |
459
|
|
|
*/ |
460
|
|
View Code Duplication |
public function count_all($table = '') |
461
|
|
|
{ |
462
|
|
|
if ($table == '') |
463
|
|
|
{ |
464
|
|
|
return 0; |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
$query = $this->query($this->_count_string.$this->_protect_identifiers('numrows')." FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE)); |
468
|
|
|
|
469
|
|
|
if ($query == FALSE) |
470
|
|
|
{ |
471
|
|
|
return 0; |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
$row = $query->row(); |
475
|
|
|
$this->_reset_select(); |
476
|
|
|
return (int)$row->numrows; |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
// -------------------------------------------------------------------- |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* Show table query |
483
|
|
|
* |
484
|
|
|
* Generates a platform-specific query string so that the table names can be fetched |
485
|
|
|
* |
486
|
|
|
* @access protected |
487
|
|
|
* @param boolean |
488
|
|
|
* @return string |
489
|
|
|
*/ |
490
|
|
View Code Duplication |
protected function _list_tables($prefix_limit = FALSE) |
491
|
|
|
{ |
492
|
|
|
$sql = "SELECT TABLE_NAME FROM ALL_TABLES"; |
493
|
|
|
|
494
|
|
|
if ($prefix_limit !== FALSE AND $this->dbprefix != '') |
495
|
|
|
{ |
496
|
|
|
$sql .= " WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
return $sql; |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
// -------------------------------------------------------------------- |
503
|
|
|
|
504
|
|
|
/** |
505
|
|
|
* Show column query |
506
|
|
|
* |
507
|
|
|
* Generates a platform-specific query string so that the column names can be fetched |
508
|
|
|
* |
509
|
|
|
* @access protected |
510
|
|
|
* @param string the table name |
511
|
|
|
* @return string |
512
|
|
|
*/ |
513
|
|
|
protected function _list_columns($table = '') |
514
|
|
|
{ |
515
|
|
|
return "SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = '$table'"; |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
// -------------------------------------------------------------------- |
519
|
|
|
|
520
|
|
|
/** |
521
|
|
|
* Field data query |
522
|
|
|
* |
523
|
|
|
* Generates a platform-specific query so that the column data can be retrieved |
524
|
|
|
* |
525
|
|
|
* @access public |
526
|
|
|
* @param string the table name |
527
|
|
|
* @return string |
528
|
|
|
*/ |
529
|
|
|
protected function _field_data($table) |
530
|
|
|
{ |
531
|
|
|
return "SELECT * FROM ".$table." where rownum = 1"; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
// -------------------------------------------------------------------- |
535
|
|
|
|
536
|
|
|
/** |
537
|
|
|
* The error message string |
538
|
|
|
* |
539
|
|
|
* @access protected |
540
|
|
|
* @return string |
541
|
|
|
*/ |
542
|
|
|
protected function _error_message() |
543
|
|
|
{ |
544
|
|
|
// If the error was during connection, no conn_id should be passed |
545
|
|
|
$error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error(); |
546
|
|
|
return $error['message']; |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
// -------------------------------------------------------------------- |
550
|
|
|
|
551
|
|
|
/** |
552
|
|
|
* The error message number |
553
|
|
|
* |
554
|
|
|
* @access protected |
555
|
|
|
* @return integer |
556
|
|
|
*/ |
557
|
|
|
protected function _error_number() |
558
|
|
|
{ |
559
|
|
|
// Same as _error_message() |
|
|
|
|
560
|
|
|
$error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error(); |
561
|
|
|
return $error['code']; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
// -------------------------------------------------------------------- |
565
|
|
|
|
566
|
|
|
/** |
567
|
|
|
* Escape the SQL Identifiers |
568
|
|
|
* |
569
|
|
|
* This function escapes column and table names |
570
|
|
|
* |
571
|
|
|
* @access protected |
572
|
|
|
* @param string |
573
|
|
|
* @return string |
574
|
|
|
*/ |
575
|
|
View Code Duplication |
protected function _escape_identifiers($item) |
576
|
|
|
{ |
577
|
|
|
if ($this->_escape_char == '') |
578
|
|
|
{ |
579
|
|
|
return $item; |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
foreach ($this->_reserved_identifiers as $id) |
583
|
|
|
{ |
584
|
|
|
if (strpos($item, '.'.$id) !== FALSE) |
585
|
|
|
{ |
586
|
|
|
$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.', $item); |
587
|
|
|
|
588
|
|
|
// remove duplicates if the user already included the escape |
589
|
|
|
return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); |
590
|
|
|
} |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
if (strpos($item, '.') !== FALSE) |
594
|
|
|
{ |
595
|
|
|
$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; |
596
|
|
|
} else |
597
|
|
|
{ |
598
|
|
|
$str = $this->_escape_char.$item.$this->_escape_char; |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
// remove duplicates if the user already included the escape |
602
|
|
|
return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
// -------------------------------------------------------------------- |
606
|
|
|
|
607
|
|
|
/** |
608
|
|
|
* From Tables |
609
|
|
|
* |
610
|
|
|
* This function implicitly groups FROM tables so there is no confusion |
611
|
|
|
* about operator precedence in harmony with SQL standards |
612
|
|
|
* |
613
|
|
|
* @access protected |
614
|
|
|
* @param type |
615
|
|
|
* @return string |
616
|
|
|
*/ |
617
|
|
|
protected function _from_tables($tables) |
618
|
|
|
{ |
619
|
|
|
if ( ! is_array($tables)) |
620
|
|
|
{ |
621
|
|
|
$tables = array($tables); |
622
|
|
|
} |
623
|
|
|
|
624
|
|
|
return implode(', ', $tables); |
625
|
|
|
} |
626
|
|
|
|
627
|
|
|
// -------------------------------------------------------------------- |
628
|
|
|
|
629
|
|
|
/** |
630
|
|
|
* Insert statement |
631
|
|
|
* |
632
|
|
|
* Generates a platform-specific insert string from the supplied data |
633
|
|
|
* |
634
|
|
|
* @access public |
635
|
|
|
* @param string the table name |
636
|
|
|
* @param array the insert keys |
637
|
|
|
* @param array the insert values |
638
|
|
|
* @return string |
639
|
|
|
*/ |
640
|
|
|
protected function _insert($table, $keys, $values) |
641
|
|
|
{ |
642
|
|
|
return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
// -------------------------------------------------------------------- |
646
|
|
|
|
647
|
|
|
/** |
648
|
|
|
* Insert_batch statement |
649
|
|
|
* |
650
|
|
|
* Generates a platform-specific insert string from the supplied data |
651
|
|
|
* |
652
|
|
|
* @access protected |
653
|
|
|
* @param string the table name |
654
|
|
|
* @param array the insert keys |
655
|
|
|
* @param array the insert values |
656
|
|
|
* @return string |
657
|
|
|
*/ |
658
|
|
|
protected function _insert_batch($table, $keys, $values) |
659
|
|
|
{ |
660
|
|
|
$keys = implode(', ', $keys); |
661
|
|
|
$sql = "INSERT ALL\n"; |
662
|
|
|
|
663
|
|
|
for ($i = 0, $c = count($values); $i < $c; $i++) |
664
|
|
|
{ |
665
|
|
|
$sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n"; |
666
|
|
|
} |
667
|
|
|
|
668
|
|
|
$sql .= 'SELECT * FROM dual'; |
669
|
|
|
|
670
|
|
|
return $sql; |
671
|
|
|
} |
672
|
|
|
|
673
|
|
|
// -------------------------------------------------------------------- |
674
|
|
|
|
675
|
|
|
/** |
676
|
|
|
* Update statement |
677
|
|
|
* |
678
|
|
|
* Generates a platform-specific update string from the supplied data |
679
|
|
|
* |
680
|
|
|
* @access protected |
681
|
|
|
* @param string the table name |
682
|
|
|
* @param array the update data |
683
|
|
|
* @param array the where clause |
684
|
|
|
* @param array the orderby clause |
685
|
|
|
* @param array the limit clause |
686
|
|
|
* @return string |
687
|
|
|
*/ |
688
|
|
View Code Duplication |
protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE) |
689
|
|
|
{ |
690
|
|
|
foreach ($values as $key => $val) |
691
|
|
|
{ |
692
|
|
|
$valstr[] = $key." = ".$val; |
|
|
|
|
693
|
|
|
} |
694
|
|
|
|
695
|
|
|
$limit = ( ! $limit) ? '' : ' LIMIT '.$limit; |
696
|
|
|
|
697
|
|
|
$orderby = (count($orderby) >= 1) ? ' ORDER BY '.implode(", ", $orderby) : ''; |
698
|
|
|
|
699
|
|
|
$sql = "UPDATE ".$table." SET ".implode(', ', $valstr); |
|
|
|
|
700
|
|
|
|
701
|
|
|
$sql .= ($where != '' AND count($where) >= 1) ? " WHERE ".implode(" ", $where) : ''; |
702
|
|
|
|
703
|
|
|
$sql .= $orderby.$limit; |
704
|
|
|
|
705
|
|
|
return $sql; |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
// -------------------------------------------------------------------- |
709
|
|
|
|
710
|
|
|
/** |
711
|
|
|
* Truncate statement |
712
|
|
|
* |
713
|
|
|
* Generates a platform-specific truncate string from the supplied data |
714
|
|
|
* If the database does not support the truncate() command |
715
|
|
|
* This function maps to "DELETE FROM table" |
716
|
|
|
* |
717
|
|
|
* @access protected |
718
|
|
|
* @param string the table name |
719
|
|
|
* @return string |
720
|
|
|
*/ |
721
|
|
|
protected function _truncate($table) |
722
|
|
|
{ |
723
|
|
|
return "TRUNCATE TABLE ".$table; |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
// -------------------------------------------------------------------- |
727
|
|
|
|
728
|
|
|
/** |
729
|
|
|
* Delete statement |
730
|
|
|
* |
731
|
|
|
* Generates a platform-specific delete string from the supplied data |
732
|
|
|
* |
733
|
|
|
* @access protected |
734
|
|
|
* @param string the table name |
735
|
|
|
* @param array the where clause |
736
|
|
|
* @param string the limit clause |
737
|
|
|
* @return string |
738
|
|
|
*/ |
739
|
|
View Code Duplication |
protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) |
740
|
|
|
{ |
741
|
|
|
$conditions = ''; |
742
|
|
|
|
743
|
|
|
if (count($where) > 0 OR count($like) > 0) |
744
|
|
|
{ |
745
|
|
|
$conditions = "\nWHERE "; |
746
|
|
|
$conditions .= implode("\n", $this->ar_where); |
747
|
|
|
|
748
|
|
|
if (count($where) > 0 && count($like) > 0) |
749
|
|
|
{ |
750
|
|
|
$conditions .= " AND "; |
751
|
|
|
} |
752
|
|
|
$conditions .= implode("\n", $like); |
753
|
|
|
} |
754
|
|
|
|
755
|
|
|
$limit = ( ! $limit) ? '' : ' LIMIT '.$limit; |
756
|
|
|
|
757
|
|
|
return "DELETE FROM ".$table.$conditions.$limit; |
758
|
|
|
} |
759
|
|
|
|
760
|
|
|
// -------------------------------------------------------------------- |
761
|
|
|
|
762
|
|
|
/** |
763
|
|
|
* Limit string |
764
|
|
|
* |
765
|
|
|
* Generates a platform-specific LIMIT clause |
766
|
|
|
* |
767
|
|
|
* @access protected |
768
|
|
|
* @param string the sql query string |
769
|
|
|
* @param integer the number of rows to limit the query to |
770
|
|
|
* @param integer the offset value |
771
|
|
|
* @return string |
772
|
|
|
*/ |
773
|
|
|
protected function _limit($sql, $limit, $offset) |
774
|
|
|
{ |
775
|
|
|
$limit = $offset + $limit; |
776
|
|
|
$newsql = "SELECT * FROM (select inner_query.*, rownum rnum FROM ($sql) inner_query WHERE rownum < $limit)"; |
777
|
|
|
|
778
|
|
|
if ($offset != 0) |
779
|
|
|
{ |
780
|
|
|
$newsql .= " WHERE rnum >= $offset"; |
781
|
|
|
} |
782
|
|
|
|
783
|
|
|
// remember that we used limits |
784
|
|
|
$this->limit_used = TRUE; |
785
|
|
|
|
786
|
|
|
return $newsql; |
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
// -------------------------------------------------------------------- |
790
|
|
|
|
791
|
|
|
/** |
792
|
|
|
* Close DB Connection |
793
|
|
|
* |
794
|
|
|
* @access protected |
795
|
|
|
* @param resource |
796
|
|
|
* @return void |
797
|
|
|
*/ |
798
|
|
|
protected function _close($conn_id) |
799
|
|
|
{ |
800
|
|
|
@oci_close($conn_id); |
|
|
|
|
801
|
|
|
} |
802
|
|
|
|
803
|
|
|
|
804
|
|
|
} |
805
|
|
|
|
806
|
|
|
|
807
|
|
|
|
808
|
|
|
/* End of file oci8_driver.php */ |
809
|
|
|
/* Location: ./system/database/drivers/oci8/oci8_driver.php */ |
810
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.