GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 7d455c...f6fa23 )
by Lonnie
07:56
created

CI_DB_oci8_driver::version()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 18
rs 8.8571
cc 5
eloc 8
nc 4
nop 0
1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	http://codeigniter.com
35
 * @since	Version 1.4.1
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
40
/**
41
 * oci8 Database Adapter Class
42
 *
43
 * Note: _DB is an extender class that the app controller
44
 * creates dynamically based on whether the query builder
45
 * class is being used or not.
46
 *
47
 * @package		CodeIgniter
48
 * @subpackage  Drivers
49
 * @category	Database
50
 * @author		EllisLab Dev Team
51
 * @link		http://codeigniter.com/user_guide/database/
52
 */
53
54
/**
55
 * oci8 Database Adapter Class
56
 *
57
 * This is a modification of the DB_driver class to
58
 * permit access to oracle databases
59
 *
60
 * @author	  Kelly McArdle
61
 */
62
class CI_DB_oci8_driver extends CI_DB {
63
64
	/**
65
	 * Database driver
66
	 *
67
	 * @var	string
68
	 */
69
	public $dbdriver = 'oci8';
70
71
	/**
72
	 * Statement ID
73
	 *
74
	 * @var	resource
75
	 */
76
	public $stmt_id;
77
78
	/**
79
	 * Cursor ID
80
	 *
81
	 * @var	resource
82
	 */
83
	public $curs_id;
84
85
	/**
86
	 * Commit mode flag
87
	 *
88
	 * @var	int
89
	 */
90
	public $commit_mode = OCI_COMMIT_ON_SUCCESS;
91
92
	/**
93
	 * Limit used flag
94
	 *
95
	 * If we use LIMIT, we'll add a field that will
96
	 * throw off num_fields later.
97
	 *
98
	 * @var	bool
99
	 */
100
	public $limit_used;
101
102
	// --------------------------------------------------------------------
103
104
	/**
105
	 * Reset $stmt_id flag
106
	 *
107
	 * Used by stored_procedure() to prevent _execute() from
108
	 * re-setting the statement ID.
109
	 */
110
	protected $_reset_stmt_id = TRUE;
111
112
	/**
113
	 * List of reserved identifiers
114
	 *
115
	 * Identifiers that must NOT be escaped.
116
	 *
117
	 * @var	string[]
118
	 */
119
	protected $_reserved_identifiers = array('*', 'rownum');
120
121
	/**
122
	 * ORDER BY random keyword
123
	 *
124
	 * @var	array
125
	 */
126
	protected $_random_keyword = array('ASC', 'ASC'); // not currently supported
127
128
	/**
129
	 * COUNT string
130
	 *
131
	 * @used-by	CI_DB_driver::count_all()
132
	 * @used-by	CI_DB_query_builder::count_all_results()
133
	 *
134
	 * @var	string
135
	 */
136
	protected $_count_string = 'SELECT COUNT(1) AS ';
137
138
	// --------------------------------------------------------------------
139
140
	/**
141
	 * Class constructor
142
	 *
143
	 * @param	array	$params
144
	 * @return	void
145
	 */
146
	public function __construct($params)
147
	{
148
		parent::__construct($params);
149
150
		$valid_dsns = array(
151
			'tns'	=> '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS
152
			// Easy Connect string (Oracle 10g+)
153
			'ec'	=> '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i',
154
			'in'	=> '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora)
155
		);
156
157
		/* Space characters don't have any effect when actually
158
		 * connecting, but can be a hassle while validating the DSN.
159
		 */
160
		$this->dsn = str_replace(array("\n", "\r", "\t", ' '), '', $this->dsn);
161
162
		if ($this->dsn !== '')
163
		{
164
			foreach ($valid_dsns as $regexp)
165
			{
166
				if (preg_match($regexp, $this->dsn))
167
				{
168
					return;
169
				}
170
			}
171
		}
172
173
		// Legacy support for TNS in the hostname configuration field
174
		$this->hostname = str_replace(array("\n", "\r", "\t", ' '), '', $this->hostname);
175
		if (preg_match($valid_dsns['tns'], $this->hostname))
176
		{
177
			$this->dsn = $this->hostname;
178
			return;
179
		}
180
		elseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE
181
			&& (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== ''))
182
		{
183
			/* If the hostname field isn't empty, doesn't contain
184
			 * ':' and/or '/' and if port and/or database aren't
185
			 * empty, then the hostname field is most likely indeed
186
			 * just a hostname. Therefore we'll try and build an
187
			 * Easy Connect string from these 3 settings, assuming
188
			 * that the database field is a service name.
189
			 */
190
			$this->dsn = $this->hostname
191
				.(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '')
192
				.($this->database !== '' ? '/'.ltrim($this->database, '/') : '');
193
194
			if (preg_match($valid_dsns['ec'], $this->dsn))
195
			{
196
				return;
197
			}
198
		}
199
200
		/* At this point, we can only try and validate the hostname and
201
		 * database fields separately as DSNs.
202
		 */
203
		if (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname))
204
		{
205
			$this->dsn = $this->hostname;
206
			return;
207
		}
208
209
		$this->database = str_replace(array("\n", "\r", "\t", ' '), '', $this->database);
210
		foreach ($valid_dsns as $regexp)
211
		{
212
			if (preg_match($regexp, $this->database))
213
			{
214
				return;
215
			}
216
		}
217
218
		/* Well - OK, an empty string should work as well.
219
		 * PHP will try to use environment variables to
220
		 * determine which Oracle instance to connect to.
221
		 */
222
		$this->dsn = '';
223
	}
224
225
	// --------------------------------------------------------------------
226
227
	/**
228
	 * Non-persistent database connection
229
	 *
230
	 * @param	bool	$persistent
231
	 * @return	resource
232
	 */
233
	public function db_connect($persistent = FALSE)
234
	{
235
		$func = ($persistent === TRUE) ? 'oci_pconnect' : 'oci_connect';
236
		return empty($this->char_set)
237
			? $func($this->username, $this->password, $this->dsn)
238
			: $func($this->username, $this->password, $this->dsn, $this->char_set);
239
	}
240
241
	// --------------------------------------------------------------------
242
243
	/**
244
	 * Database version number
245
	 *
246
	 * @return	string
247
	 */
248
	public function version()
249
	{
250
		if (isset($this->data_cache['version']))
251
		{
252
			return $this->data_cache['version'];
253
		}
254
255
		if ( ! $this->conn_id OR ($version_string = oci_server_version($this->conn_id)) === FALSE)
256
		{
257
			return FALSE;
258
		}
259
		elseif (preg_match('#Release\s(\d+(?:\.\d+)+)#', $version_string, $match))
260
		{
261
			return $this->data_cache['version'] = $match[1];
262
		}
263
264
		return FALSE;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return FALSE; (false) is incompatible with the return type documented by CI_DB_oci8_driver::version of type string.

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:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
265
	}
266
267
	// --------------------------------------------------------------------
268
269
	/**
270
	 * Execute the query
271
	 *
272
	 * @param	string	$sql	an SQL query
273
	 * @return	resource
274
	 */
275
	protected function _execute($sql)
276
	{
277
		/* Oracle must parse the query before it is run. All of the actions with
278
		 * the query are based on the statement id returned by oci_parse().
279
		 */
280
		if ($this->_reset_stmt_id === TRUE)
281
		{
282
			$this->stmt_id = oci_parse($this->conn_id, $sql);
283
		}
284
285
		oci_set_prefetch($this->stmt_id, 1000);
286
		return oci_execute($this->stmt_id, $this->commit_mode);
287
	}
288
289
	// --------------------------------------------------------------------
290
291
	/**
292
	 * Get cursor. Returns a cursor from the database
293
	 *
294
	 * @return	resource
295
	 */
296
	public function get_cursor()
297
	{
298
		return $this->curs_id = oci_new_cursor($this->conn_id);
299
	}
300
301
	// --------------------------------------------------------------------
302
303
	/**
304
	 * Stored Procedure.  Executes a stored procedure
305
	 *
306
	 * @param	string	package name in which the stored procedure is in
307
	 * @param	string	stored procedure name to execute
308
	 * @param	array	parameters
309
	 * @return	mixed
310
	 *
311
	 * params array keys
312
	 *
313
	 * KEY      OPTIONAL  NOTES
314
	 * name     no        the name of the parameter should be in :<param_name> format
315
	 * value    no        the value of the parameter.  If this is an OUT or IN OUT parameter,
316
	 *                    this should be a reference to a variable
317
	 * type     yes       the type of the parameter
318
	 * length   yes       the max size of the parameter
319
	 */
320
	public function stored_procedure($package, $procedure, array $params)
321
	{
322
		if ($package === '' OR $procedure === '')
323
		{
324
			log_message('error', 'Invalid query: '.$package.'.'.$procedure);
325
			return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
326
		}
327
328
		// Build the query string
329
		$sql = 'BEGIN '.$package.'.'.$procedure.'(';
330
331
		$have_cursor = FALSE;
332
		foreach ($params as $param)
333
		{
334
			$sql .= $param['name'].',';
335
336
			if (isset($param['type']) && $param['type'] === OCI_B_CURSOR)
337
			{
338
				$have_cursor = TRUE;
339
			}
340
		}
341
		$sql = trim($sql, ',').'); END;';
342
343
		$this->_reset_stmt_id = FALSE;
344
		$this->stmt_id = oci_parse($this->conn_id, $sql);
345
		$this->_bind_params($params);
346
		$result = $this->query($sql, FALSE, $have_cursor);
347
		$this->_reset_stmt_id = TRUE;
348
		return $result;
349
	}
350
351
	// --------------------------------------------------------------------
352
353
	/**
354
	 * Bind parameters
355
	 *
356
	 * @param	array	$params
357
	 * @return	void
358
	 */
359
	protected function _bind_params($params)
360
	{
361
		if ( ! is_array($params) OR ! is_resource($this->stmt_id))
362
		{
363
			return;
364
		}
365
366
		foreach ($params as $param)
367
		{
368
			foreach (array('name', 'value', 'type', 'length') as $val)
369
			{
370
				if ( ! isset($param[$val]))
371
				{
372
					$param[$val] = '';
373
				}
374
			}
375
376
			oci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']);
377
		}
378
	}
379
380
	// --------------------------------------------------------------------
381
382
	/**
383
	 * Begin Transaction
384
	 *
385
	 * @return	bool
386
	 */
387
	protected function _trans_begin()
388
	{
389
		$this->commit_mode = is_php('5.3.2') ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT;
390
		return TRUE;
391
	}
392
393
	// --------------------------------------------------------------------
394
395
	/**
396
	 * Commit Transaction
397
	 *
398
	 * @return	bool
399
	 */
400
	protected function _trans_commit()
401
	{
402
		$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
403
404
		return oci_commit($this->conn_id);
405
	}
406
407
	// --------------------------------------------------------------------
408
409
	/**
410
	 * Rollback Transaction
411
	 *
412
	 * @return	bool
413
	 */
414
	protected function _trans_rollback()
415
	{
416
		$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
417
		return oci_rollback($this->conn_id);
418
	}
419
420
	// --------------------------------------------------------------------
421
422
	/**
423
	 * Affected Rows
424
	 *
425
	 * @return	int
426
	 */
427
	public function affected_rows()
428
	{
429
		return oci_num_rows($this->stmt_id);
430
	}
431
432
	// --------------------------------------------------------------------
433
434
	/**
435
	 * Insert ID
436
	 *
437
	 * @return	int
438
	 */
439
	public function insert_id()
440
	{
441
		// not supported in oracle
442
		return $this->display_error('db_unsupported_function');
443
	}
444
445
	// --------------------------------------------------------------------
446
447
	/**
448
	 * Show table query
449
	 *
450
	 * Generates a platform-specific query string so that the table names can be fetched
451
	 *
452
	 * @param	bool	$prefix_limit
453
	 * @return	string
454
	 */
455 View Code Duplication
	protected function _list_tables($prefix_limit = FALSE)
456
	{
457
		$sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
458
459
		if ($prefix_limit !== FALSE && $this->dbprefix !== '')
460
		{
461
			return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
462
				.sprintf($this->_like_escape_str, $this->_like_escape_chr);
463
		}
464
465
		return $sql;
466
	}
467
468
	// --------------------------------------------------------------------
469
470
	/**
471
	 * Show column query
472
	 *
473
	 * Generates a platform-specific query string so that the column names can be fetched
474
	 *
475
	 * @param	string	$table
476
	 * @return	string
477
	 */
478 View Code Duplication
	protected function _list_columns($table = '')
479
	{
480
		if (strpos($table, '.') !== FALSE)
481
		{
482
			sscanf($table, '%[^.].%s', $owner, $table);
483
		}
484
		else
485
		{
486
			$owner = $this->username;
487
		}
488
489
		return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
490
			WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
491
				AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
492
	}
493
494
	// --------------------------------------------------------------------
495
496
	/**
497
	 * Returns an object with field data
498
	 *
499
	 * @param	string	$table
500
	 * @return	array
501
	 */
502 View Code Duplication
	public function field_data($table)
503
	{
504
		if (strpos($table, '.') !== FALSE)
505
		{
506
			sscanf($table, '%[^.].%s', $owner, $table);
507
		}
508
		else
509
		{
510
			$owner = $this->username;
511
		}
512
513
		$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE
514
			FROM ALL_TAB_COLUMNS
515
			WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
516
				AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
517
518
		if (($query = $this->query($sql)) === FALSE)
519
		{
520
			return FALSE;
521
		}
522
		$query = $query->result_object();
523
524
		$retval = array();
525
		for ($i = 0, $c = count($query); $i < $c; $i++)
526
		{
527
			$retval[$i]			= new stdClass();
528
			$retval[$i]->name		= $query[$i]->COLUMN_NAME;
529
			$retval[$i]->type		= $query[$i]->DATA_TYPE;
530
531
			$length = ($query[$i]->CHAR_LENGTH > 0)
532
				? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;
533
			if ($length === NULL)
534
			{
535
				$length = $query[$i]->DATA_LENGTH;
536
			}
537
			$retval[$i]->max_length		= $length;
538
539
			$default = $query[$i]->DATA_DEFAULT;
540
			if ($default === NULL && $query[$i]->NULLABLE === 'N')
541
			{
542
				$default = '';
543
			}
544
			$retval[$i]->default = $default;
545
		}
546
547
		return $retval;
548
	}
549
550
	// --------------------------------------------------------------------
551
552
	/**
553
	 * Error
554
	 *
555
	 * Returns an array containing code and message of the last
556
	 * database error that has occured.
557
	 *
558
	 * @return	array
559
	 */
560
	public function error()
561
	{
562
		/* oci_error() returns an array that already contains the
563
		 * 'code' and 'message' keys, so we can just return it.
564
		 */
565
		if (is_resource($this->curs_id))
566
		{
567
			return oci_error($this->curs_id);
568
		}
569
		elseif (is_resource($this->stmt_id))
570
		{
571
			return oci_error($this->stmt_id);
572
		}
573
		elseif (is_resource($this->conn_id))
574
		{
575
			return oci_error($this->conn_id);
576
		}
577
578
		return oci_error();
579
	}
580
581
	// --------------------------------------------------------------------
582
583
	/**
584
	 * Insert batch statement
585
	 *
586
	 * Generates a platform-specific insert string from the supplied data
587
	 *
588
	 * @param	string	$table	Table name
589
	 * @param	array	$keys	INSERT keys
590
	 * @param 	array	$values	INSERT values
591
	 * @return	string
592
	 */
593 View Code Duplication
	protected function _insert_batch($table, $keys, $values)
594
	{
595
		$keys = implode(', ', $keys);
596
		$sql = "INSERT ALL\n";
597
598
		for ($i = 0, $c = count($values); $i < $c; $i++)
599
		{
600
			$sql .= '	INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
601
		}
602
603
		return $sql.'SELECT * FROM dual';
604
	}
605
606
	// --------------------------------------------------------------------
607
608
	/**
609
	 * Truncate statement
610
	 *
611
	 * Generates a platform-specific truncate string from the supplied data
612
	 *
613
	 * If the database does not support the TRUNCATE statement,
614
	 * then this method maps to 'DELETE FROM table'
615
	 *
616
	 * @param	string	$table
617
	 * @return	string
618
	 */
619
	protected function _truncate($table)
620
	{
621
		return 'TRUNCATE TABLE '.$table;
622
	}
623
624
	// --------------------------------------------------------------------
625
626
	/**
627
	 * Delete statement
628
	 *
629
	 * Generates a platform-specific delete string from the supplied data
630
	 *
631
	 * @param	string	$table
632
	 * @return	string
633
	 */
634 View Code Duplication
	protected function _delete($table)
635
	{
636
		if ($this->qb_limit)
637
		{
638
			$this->where('rownum <= ',$this->qb_limit, FALSE);
639
			$this->qb_limit = FALSE;
640
		}
641
642
		return parent::_delete($table);
643
	}
644
645
	// --------------------------------------------------------------------
646
647
	/**
648
	 * LIMIT
649
	 *
650
	 * Generates a platform-specific LIMIT clause
651
	 *
652
	 * @param	string	$sql	SQL Query
653
	 * @return	string
654
	 */
655
	protected function _limit($sql)
656
	{
657
		$this->limit_used = TRUE;
658
		return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
659
			.($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1) : '');
660
	}
661
662
	// --------------------------------------------------------------------
663
664
	/**
665
	 * Close DB Connection
666
	 *
667
	 * @return	void
668
	 */
669
	protected function _close()
670
	{
671
		oci_close($this->conn_id);
672
	}
673
674
}
675