Test Failed
Push — master ( 3c3be4...ec7459 )
by Ricardo Jesus Ruiz
02:59
created

CI_DB_driver::version()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 4
nop 0
dl 0
loc 14
rs 9.2
c 0
b 0
f 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 - 2017, 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. (https://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
39
namespace Rioxygen\CiCoreDatabase;
40
41
use Rioxygen\CiCoreDatabase\CI_DB_result;
42
#use Rioxygen\CiCoreDatabase\CI_DB_forge;
43
#use Rioxygen\CiCoreDatabase\Mysql\CI_DB_mysqli_result;
44
/**
45
 * Database Driver Class
46
 *
47
 * This is the platform-independent base DB implementation class.
48
 * This class will not be called directly. Rather, the adapter
49
 * class for the specific database will extend and instantiate it.
50
 *
51
 * @package		CodeIgniter
52
 * @subpackage	Drivers
53
 * @category	Database
54
 * @author		EllisLab Dev Team
55
 * @link		https://codeigniter.com/user_guide/database/
56
 */
57
abstract class CI_DB_driver {
58
59
	/**
60
	 * Data Source Name / Connect string
61
	 *
62
	 * @var	string
63
	 */
64
	public $dsn;
65
66
	/**
67
	 * Username
68
	 *
69
	 * @var	string
70
	 */
71
	public $username;
72
73
	/**
74
	 * Password
75
	 *
76
	 * @var	string
77
	 */
78
	public $password;
79
80
	/**
81
	 * Hostname
82
	 *
83
	 * @var	string
84
	 */
85
	public $hostname;
86
87
	/**
88
	 * Database name
89
	 *
90
	 * @var	string
91
	 */
92
	public $database;
93
94
	/**
95
	 * Database driver
96
	 *
97
	 * @var	string
98
	 */
99
	public $dbdriver		= 'mysqli';
100
101
	/**
102
	 * Sub-driver
103
	 *
104
	 * @used-by	CI_DB_pdo_driver
105
	 * @var	string
106
	 */
107
	public $subdriver;
108
109
	/**
110
	 * Table prefix
111
	 *
112
	 * @var	string
113
	 */
114
	public $dbprefix		= '';
115
116
	/**
117
	 * Character set
118
	 *
119
	 * @var	string
120
	 */
121
	public $char_set		= 'utf8';
122
123
	/**
124
	 * Collation
125
	 *
126
	 * @var	string
127
	 */
128
	public $dbcollat		= 'utf8_general_ci';
129
130
	/**
131
	 * Encryption flag/data
132
	 *
133
	 * @var	mixed
134
	 */
135
	public $encrypt			= FALSE;
136
137
	/**
138
	 * Swap Prefix
139
	 *
140
	 * @var	string
141
	 */
142
	public $swap_pre		= '';
143
144
	/**
145
	 * Database port
146
	 *
147
	 * @var	int
148
	 */
149
	public $port			= '';
150
151
	/**
152
	 * Persistent connection flag
153
	 *
154
	 * @var	bool
155
	 */
156
	public $pconnect		= FALSE;
157
158
	/**
159
	 * Connection ID
160
	 *
161
	 * @var	object|resource
162
	 */
163
	public $conn_id			= FALSE;
164
165
	/**
166
	 * Result ID
167
	 *
168
	 * @var	object|resource
169
	 */
170
	public $result_id		= FALSE;
171
172
	/**
173
	 * Debug flag
174
	 *
175
	 * Whether to display error messages.
176
	 *
177
	 * @var	bool
178
	 */
179
	public $db_debug		= FALSE;
180
181
	/**
182
	 * Benchmark time
183
	 *
184
	 * @var	int
185
	 */
186
	public $benchmark		= 0;
187
188
	/**
189
	 * Executed queries count
190
	 *
191
	 * @var	int
192
	 */
193
	public $query_count		= 0;
194
195
	/**
196
	 * Bind marker
197
	 *
198
	 * Character used to identify values in a prepared statement.
199
	 *
200
	 * @var	string
201
	 */
202
	public $bind_marker		= '?';
203
204
	/**
205
	 * Save queries flag
206
	 *
207
	 * Whether to keep an in-memory history of queries for debugging purposes.
208
	 *
209
	 * @var	bool
210
	 */
211
	public $save_queries		= TRUE;
212
213
	/**
214
	 * Queries list
215
	 *
216
	 * @see	CI_DB_driver::$save_queries
217
	 * @var	string[]
218
	 */
219
	public $queries			= array();
220
221
	/**
222
	 * Query times
223
	 *
224
	 * A list of times that queries took to execute.
225
	 *
226
	 * @var	array
227
	 */
228
	public $query_times		= array();
229
230
	/**
231
	 * Data cache
232
	 *
233
	 * An internal generic value cache.
234
	 *
235
	 * @var	array
236
	 */
237
	public $data_cache		= array();
238
239
	/**
240
	 * Transaction enabled flag
241
	 *
242
	 * @var	bool
243
	 */
244
	public $trans_enabled		= TRUE;
245
246
	/**
247
	 * Strict transaction mode flag
248
	 *
249
	 * @var	bool
250
	 */
251
	public $trans_strict		= TRUE;
252
253
	/**
254
	 * Transaction depth level
255
	 *
256
	 * @var	int
257
	 */
258
	protected $_trans_depth		= 0;
259
260
	/**
261
	 * Transaction status flag
262
	 *
263
	 * Used with transactions to determine if a rollback should occur.
264
	 *
265
	 * @var	bool
266
	 */
267
	protected $_trans_status	= TRUE;
268
269
	/**
270
	 * Transaction failure flag
271
	 *
272
	 * Used with transactions to determine if a transaction has failed.
273
	 *
274
	 * @var	bool
275
	 */
276
	protected $_trans_failure	= FALSE;
277
278
	/**
279
	 * Cache On flag
280
	 *
281
	 * @var	bool
282
	 */
283
	public $cache_on		= FALSE;
284
285
	/**
286
	 * Cache directory path
287
	 *
288
	 * @var	bool
289
	 */
290
	public $cachedir		= '';
291
292
	/**
293
	 * Cache auto-delete flag
294
	 *
295
	 * @var	bool
296
	 */
297
	public $cache_autodel		= FALSE;
298
299
	/**
300
	 * DB Cache object
301
	 *
302
	 * @see	CI_DB_cache
303
	 * @var	object
304
	 */
305
	public $CACHE;
306
307
	/**
308
	 * Protect identifiers flag
309
	 *
310
	 * @var	bool
311
	 */
312
	protected $_protect_identifiers		= TRUE;
313
314
	/**
315
	 * List of reserved identifiers
316
	 *
317
	 * Identifiers that must NOT be escaped.
318
	 *
319
	 * @var	string[]
320
	 */
321
	protected $_reserved_identifiers	= array('*');
322
323
	/**
324
	 * Identifier escape character
325
	 *
326
	 * @var	string
327
	 */
328
	protected $_escape_char = '"';
329
330
	/**
331
	 * ESCAPE statement string
332
	 *
333
	 * @var	string
334
	 */
335
	protected $_like_escape_str = " ESCAPE '%s' ";
336
337
	/**
338
	 * ESCAPE character
339
	 *
340
	 * @var	string
341
	 */
342
	protected $_like_escape_chr = '!';
343
344
	/**
345
	 * ORDER BY random keyword
346
	 *
347
	 * @var	array
348
	 */
349
	protected $_random_keyword = array('RAND()', 'RAND(%d)');
350
351
	/**
352
	 * COUNT string
353
	 *
354
	 * @used-by	CI_DB_driver::count_all()
355
	 * @used-by	CI_DB_query_builder::count_all_results()
356
	 *
357
	 * @var	string
358
	 */
359
	protected $_count_string = 'SELECT COUNT(*) AS ';
360
361
	// --------------------------------------------------------------------
362
363
	/**
364
	 * Class constructor
365
	 *
366
	 * @param	array	$params
367
	 * @return	void
368
	 */
369
	public function __construct($params)
370
	{
371
		if (is_array($params))
372
		{
373
			foreach ($params as $key => $val)
374
			{
375
				$this->$key = $val;
376
			}
377
		}
378
	}
379
380
	// --------------------------------------------------------------------
381
382
	/**
383
	 * Initialize Database Settings
384
	 *
385
	 * @return	bool
386
	 */
387
	public function initialize()
388
	{
389
		/* If an established connection is available, then there's
390
		 * no need to connect and select the database.
391
		 *
392
		 * Depending on the database driver, conn_id can be either
393
		 * boolean TRUE, a resource or an object.
394
		 */
395
		if ($this->conn_id)
396
		{
397
			return TRUE;
398
		}
399
400
		// ----------------------------------------------------------------
401
402
		// Connect to the database and set the connection ID
403
		$this->conn_id = $this->db_connect($this->pconnect);
0 ignored issues
show
Unused Code introduced by
The call to Rioxygen\CiCoreDatabase\CI_DB_driver::db_connect() has too many arguments starting with $this->pconnect. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

403
		/** @scrutinizer ignore-call */ 
404
  $this->conn_id = $this->db_connect($this->pconnect);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
404
405
		// No connection resource? Check if there is a failover else throw an error
406
		if ( ! $this->conn_id)
407
		{
408
			// Check if there is a failover set
409
			if ( ! empty($this->failover) && is_array($this->failover))
0 ignored issues
show
Bug Best Practice introduced by
The property failover does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. Did you maybe forget to declare it?
Loading history...
410
			{
411
				// Go over all the failovers
412
				foreach ($this->failover as $failover)
413
				{
414
					// Replace the current settings with those of the failover
415
					foreach ($failover as $key => $val)
416
					{
417
						$this->$key = $val;
418
					}
419
420
					// Try to connect
421
					$this->conn_id = $this->db_connect($this->pconnect);
422
423
					// If a connection is made break the foreach loop
424
					if ($this->conn_id)
425
					{
426
						break;
427
					}
428
				}
429
			}
430
431
			// We still don't have a connection?
432
			if ( ! $this->conn_id)
433
			{
434
				log_message('error', 'Unable to connect to the database');
0 ignored issues
show
Bug introduced by
The function log_message was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

434
				/** @scrutinizer ignore-call */ 
435
    log_message('error', 'Unable to connect to the database');
Loading history...
435
436
				if ($this->db_debug)
437
				{
438
					$this->display_error('db_unable_to_connect');
439
				}
440
441
				return FALSE;
442
			}
443
		}
444
445
		// Now we set the character set and that's all
446
		return $this->db_set_charset($this->char_set);
447
	}
448
449
	// --------------------------------------------------------------------
450
451
	/**
452
	 * DB connect
453
	 *
454
	 * This is just a dummy method that all drivers will override.
455
	 *
456
	 * @return	mixed
457
	 */
458
	public function db_connect()
459
	{
460
		return TRUE;
461
	}
462
463
	// --------------------------------------------------------------------
464
465
	/**
466
	 * Persistent database connection
467
	 *
468
	 * @return	mixed
469
	 */
470
	public function db_pconnect()
471
	{
472
		return $this->db_connect(TRUE);
0 ignored issues
show
Unused Code introduced by
The call to Rioxygen\CiCoreDatabase\CI_DB_driver::db_connect() has too many arguments starting with TRUE. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

472
		return $this->/** @scrutinizer ignore-call */ db_connect(TRUE);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
473
	}
474
475
	// --------------------------------------------------------------------
476
477
	/**
478
	 * Reconnect
479
	 *
480
	 * Keep / reestablish the db connection if no queries have been
481
	 * sent for a length of time exceeding the server's idle timeout.
482
	 *
483
	 * This is just a dummy method to allow drivers without such
484
	 * functionality to not declare it, while others will override it.
485
	 *
486
	 * @return	void
487
	 */
488
	public function reconnect()
489
	{
490
	}
491
492
	// --------------------------------------------------------------------
493
494
	/**
495
	 * Select database
496
	 *
497
	 * This is just a dummy method to allow drivers without such
498
	 * functionality to not declare it, while others will override it.
499
	 *
500
	 * @return	bool
501
	 */
502
	public function db_select()
503
	{
504
		return TRUE;
505
	}
506
507
	// --------------------------------------------------------------------
508
509
	/**
510
	 * Last error
511
	 *
512
	 * @return	array
513
	 */
514
	public function error()
515
	{
516
		return array('code' => NULL, 'message' => NULL);
517
	}
518
519
	// --------------------------------------------------------------------
520
521
	/**
522
	 * Set client character set
523
	 *
524
	 * @param	string
525
	 * @return	bool
526
	 */
527
	public function db_set_charset($charset)
528
	{
529
		if (method_exists($this, '_db_set_charset') && ! $this->_db_set_charset($charset))
530
		{
531
			log_message('error', 'Unable to set database connection charset: '.$charset);
0 ignored issues
show
Bug introduced by
The function log_message was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

531
			/** @scrutinizer ignore-call */ 
532
   log_message('error', 'Unable to set database connection charset: '.$charset);
Loading history...
532
533
			if ($this->db_debug)
534
			{
535
				$this->display_error('db_unable_to_set_charset', $charset);
536
			}
537
538
			return FALSE;
539
		}
540
541
		return TRUE;
542
	}
543
544
	// --------------------------------------------------------------------
545
546
	/**
547
	 * The name of the platform in use (mysql, mssql, etc...)
548
	 *
549
	 * @return	string
550
	 */
551
	public function platform()
552
	{
553
		return $this->dbdriver;
554
	}
555
556
	// --------------------------------------------------------------------
557
558
	/**
559
	 * Database version number
560
	 *
561
	 * Returns a string containing the version of the database being used.
562
	 * Most drivers will override this method.
563
	 *
564
	 * @return	string
565
	 */
566
	public function version()
567
	{
568
		if (isset($this->data_cache['version']))
569
		{
570
			return $this->data_cache['version'];
571
		}
572
573
		if (FALSE === ($sql = $this->_version()))
574
		{
575
			return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;
576
		}
577
578
		$query = $this->query($sql)->row();
579
		return $this->data_cache['version'] = $query->ver;
580
	}
581
582
	// --------------------------------------------------------------------
583
584
	/**
585
	 * Version number query string
586
	 *
587
	 * @return	string
588
	 */
589
	protected function _version()
590
	{
591
		return 'SELECT VERSION() AS ver';
592
	}
593
594
	// --------------------------------------------------------------------
595
596
	/**
597
	 * Execute the query
598
	 *
599
	 * Accepts an SQL string as input and returns a result object upon
600
	 * successful execution of a "read" type query. Returns boolean TRUE
601
	 * upon successful execution of a "write" type query. Returns boolean
602
	 * FALSE upon failure, and if the $db_debug variable is set to TRUE
603
	 * will raise an error.
604
	 *
605
	 * @param	string	$sql
606
	 * @param	array	$binds = FALSE		An array of binding data
607
	 * @param	bool	$return_object = NULL
608
	 * @return	mixed
609
	 */
610
	public function query($sql, $binds = FALSE, $return_object = NULL)
611
	{
612
		if ($sql === '')
613
		{
614
			log_message('error', 'Invalid query: '.$sql);
0 ignored issues
show
Bug introduced by
The function log_message was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

614
			/** @scrutinizer ignore-call */ 
615
   log_message('error', 'Invalid query: '.$sql);
Loading history...
615
			return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
616
		}
617
		elseif ( ! is_bool($return_object))
618
		{
619
			$return_object = ! $this->is_write_type($sql);
620
		}
621
622
		// Verify table prefix and replace if necessary
623
		if ($this->dbprefix !== '' && $this->swap_pre !== '' && $this->dbprefix !== $this->swap_pre)
624
		{
625
			$sql = preg_replace('/(\W)'.$this->swap_pre.'(\S+?)/', '\\1'.$this->dbprefix.'\\2', $sql);
626
		}
627
628
		// Compile binds if needed
629
		if ($binds !== FALSE)
630
		{
631
			$sql = $this->compile_binds($sql, $binds);
632
		}
633
634
		// Is query caching enabled? If the query is a "read type"
635
		// we will load the caching class and return the previously
636
		// cached query if it exists
637
		if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init())
638
		{
639
			#$this->load_rdriver();
640
			if (FALSE !== ($cache = $this->CACHE->read($sql)))
641
			{
642
				return $cache;
643
			}
644
		}
645
646
		// Save the query for debugging
647
		if ($this->save_queries === TRUE)
648
		{
649
			$this->queries[] = $sql;
650
		}
651
652
		// Start the Query Timer
653
		$time_start = microtime(TRUE);
654
655
		// Run the Query
656
		if (FALSE === ($this->result_id = $this->simple_query($sql)))
657
		{
658
			if ($this->save_queries === TRUE)
659
			{
660
				$this->query_times[] = 0;
661
			}
662
663
			// This will trigger a rollback if transactions are being used
664
			if ($this->_trans_depth !== 0)
665
			{
666
				$this->_trans_status = FALSE;
667
			}
668
669
			// Grab the error now, as we might run some additional queries before displaying the error
670
			$error = $this->error();
671
672
			// Log errors
673
			log_message('error', 'Query error: '.$error['message'].' - Invalid query: '.$sql);
674
675
			if ($this->db_debug)
676
			{
677
				// We call this function in order to roll-back queries
678
				// if transactions are enabled. If we don't call this here
679
				// the error message will trigger an exit, causing the
680
				// transactions to remain in limbo.
681
				while ($this->_trans_depth !== 0)
682
				{
683
					$trans_depth = $this->_trans_depth;
684
					$this->trans_complete();
685
					if ($trans_depth === $this->_trans_depth)
686
					{
687
						log_message('error', 'Database: Failure during an automated transaction commit/rollback!');
688
						break;
689
					}
690
				}
691
692
				// Display errors
693
				return $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql));
694
			}
695
696
			return FALSE;
697
		}
698
699
		// Stop and aggregate the query time results
700
		$time_end = microtime(TRUE);
701
		$this->benchmark += $time_end - $time_start;
702
703
		if ($this->save_queries === TRUE)
704
		{
705
			$this->query_times[] = $time_end - $time_start;
706
		}
707
708
		// Increment the query counter
709
		$this->query_count++;
710
711
		// Will we have a result object instantiated? If not - we'll simply return TRUE
712
		if ($return_object !== TRUE)
713
		{
714
			// If caching is enabled we'll auto-cleanup any existing files related to this particular URI
715
			if ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init())
716
			{
717
				$this->CACHE->delete();
718
			}
719
720
			return TRUE;
721
		}
722
723
		// Load and instantiate the result driver
724
		$driver		= $this->load_rdriver();
725
		$RES		= new $driver($this);
726
727
		// Is query caching enabled? If so, we'll serialize the
728
		// result object and save it to a cache file.
729
		if ($this->cache_on === TRUE && $this->_cache_init())
730
		{
731
			// We'll create a new instance of the result object
732
			// only without the platform specific driver since
733
			// we can't use it with cached data (the query result
734
			// resource ID won't be any good once we've cached the
735
			// result object, so we'll have to compile the data
736
			// and save it)
737
			$CR = new CI_DB_result($this);
738
			$CR->result_object	= $RES->result_object();
739
			$CR->result_array	= $RES->result_array();
740
			$CR->num_rows		= $RES->num_rows();
741
742
			// Reset these since cached objects can not utilize resource IDs.
743
			$CR->conn_id		= NULL;
744
			$CR->result_id		= NULL;
745
746
			$this->CACHE->write($sql, $CR);
747
		}
748
749
		return $RES;
750
	}
751
752
	// --------------------------------------------------------------------
753
754
	/**
755
	 * Load the result drivers
756
	 *
757
	 * @return	string	the name of the result class
758
	 */
759
	public function load_rdriver()
760
	{
761
		$driver = 'Rioxygen\CiCoreDatabase\Mysql\CI_DB_'.$this->dbdriver.'_result';
762
		return $driver;
763
	}
764
765
	// --------------------------------------------------------------------
766
767
	/**
768
	 * Simple Query
769
	 * This is a simplified version of the query() function. Internally
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
770
	 * we only use it when running transaction commands since they do
771
	 * not require all the features of the main query() function.
772
	 *
773
	 * @param	string	the sql query
774
	 * @return	mixed
775
	 */
776
	public function simple_query($sql)
777
	{
778
		if ( ! $this->conn_id)
779
		{
780
			if ( ! $this->initialize())
781
			{
782
				return FALSE;
783
			}
784
		}
785
786
		return $this->_execute($sql);
0 ignored issues
show
Bug introduced by
The method _execute() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. It seems like you code against a sub-type of Rioxygen\CiCoreDatabase\CI_DB_driver such as Rioxygen\CiCoreDatabase\Mysql\CI_DB_mysqli_driver. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

786
		return $this->/** @scrutinizer ignore-call */ _execute($sql);
Loading history...
787
	}
788
789
	// --------------------------------------------------------------------
790
791
	/**
792
	 * Disable Transactions
793
	 * This permits transactions to be disabled at run-time.
794
	 *
795
	 * @return	void
796
	 */
797
	public function trans_off()
798
	{
799
		$this->trans_enabled = FALSE;
800
	}
801
802
	// --------------------------------------------------------------------
803
804
	/**
805
	 * Enable/disable Transaction Strict Mode
806
	 *
807
	 * When strict mode is enabled, if you are running multiple groups of
808
	 * transactions, if one group fails all subsequent groups will be
809
	 * rolled back.
810
	 *
811
	 * If strict mode is disabled, each group is treated autonomously,
812
	 * meaning a failure of one group will not affect any others
813
	 *
814
	 * @param	bool	$mode = TRUE
815
	 * @return	void
816
	 */
817
	public function trans_strict($mode = TRUE)
818
	{
819
		$this->trans_strict = is_bool($mode) ? $mode : TRUE;
820
	}
821
822
	// --------------------------------------------------------------------
823
824
	/**
825
	 * Start Transaction
826
	 *
827
	 * @param	bool	$test_mode = FALSE
828
	 * @return	bool
829
	 */
830
	public function trans_start($test_mode = FALSE)
831
	{
832
		if ( ! $this->trans_enabled)
833
		{
834
			return FALSE;
835
		}
836
837
		return $this->trans_begin($test_mode);
838
	}
839
840
	// --------------------------------------------------------------------
841
842
	/**
843
	 * Complete Transaction
844
	 *
845
	 * @return	bool
846
	 */
847
	public function trans_complete()
848
	{
849
		if ( ! $this->trans_enabled)
850
		{
851
			return FALSE;
852
		}
853
854
		// The query() function will set this flag to FALSE in the event that a query failed
855
		if ($this->_trans_status === FALSE OR $this->_trans_failure === TRUE)
856
		{
857
			$this->trans_rollback();
858
859
			// If we are NOT running in strict mode, we will reset
860
			// the _trans_status flag so that subsequent groups of
861
			// transactions will be permitted.
862
			if ($this->trans_strict === FALSE)
863
			{
864
				$this->_trans_status = TRUE;
865
			}
866
867
			log_message('debug', 'DB Transaction Failure');
0 ignored issues
show
Bug introduced by
The function log_message was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

867
			/** @scrutinizer ignore-call */ 
868
   log_message('debug', 'DB Transaction Failure');
Loading history...
868
			return FALSE;
869
		}
870
871
		return $this->trans_commit();
872
	}
873
874
	// --------------------------------------------------------------------
875
876
	/**
877
	 * Lets you retrieve the transaction flag to determine if it has failed
878
	 *
879
	 * @return	bool
880
	 */
881
	public function trans_status()
882
	{
883
		return $this->_trans_status;
884
	}
885
886
	// --------------------------------------------------------------------
887
888
	/**
889
	 * Begin Transaction
890
	 *
891
	 * @param	bool	$test_mode
892
	 * @return	bool
893
	 */
894
	public function trans_begin($test_mode = FALSE)
895
	{
896
		if ( ! $this->trans_enabled)
897
		{
898
			return FALSE;
899
		}
900
		// When transactions are nested we only begin/commit/rollback the outermost ones
901
		elseif ($this->_trans_depth > 0)
902
		{
903
			$this->_trans_depth++;
904
			return TRUE;
905
		}
906
907
		// Reset the transaction failure flag.
908
		// If the $test_mode flag is set to TRUE transactions will be rolled back
909
		// even if the queries produce a successful result.
910
		$this->_trans_failure = ($test_mode === TRUE);
911
912
		if ($this->_trans_begin())
0 ignored issues
show
Bug introduced by
The method _trans_begin() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. Did you maybe mean trans_begin()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

912
		if ($this->/** @scrutinizer ignore-call */ _trans_begin())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
913
		{
914
			$this->_trans_status = TRUE;
915
			$this->_trans_depth++;
916
			return TRUE;
917
		}
918
919
		return FALSE;
920
	}
921
922
	// --------------------------------------------------------------------
923
924
	/**
925
	 * Commit Transaction
926
	 *
927
	 * @return	bool
928
	 */
929 View Code Duplication
	public function trans_commit()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
930
	{
931
		if ( ! $this->trans_enabled OR $this->_trans_depth === 0)
932
		{
933
			return FALSE;
934
		}
935
		// When transactions are nested we only begin/commit/rollback the outermost ones
936
		elseif ($this->_trans_depth > 1 OR $this->_trans_commit())
0 ignored issues
show
Bug introduced by
The method _trans_commit() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. Did you maybe mean trans_commit()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

936
		elseif ($this->_trans_depth > 1 OR $this->/** @scrutinizer ignore-call */ _trans_commit())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
937
		{
938
			$this->_trans_depth--;
939
			return TRUE;
940
		}
941
942
		return FALSE;
943
	}
944
945
	// --------------------------------------------------------------------
946
947
	/**
948
	 * Rollback Transaction
949
	 *
950
	 * @return	bool
951
	 */
952 View Code Duplication
	public function trans_rollback()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
953
	{
954
		if ( ! $this->trans_enabled OR $this->_trans_depth === 0)
955
		{
956
			return FALSE;
957
		}
958
		// When transactions are nested we only begin/commit/rollback the outermost ones
959
		elseif ($this->_trans_depth > 1 OR $this->_trans_rollback())
0 ignored issues
show
Bug introduced by
The method _trans_rollback() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. Did you maybe mean trans_rollback()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

959
		elseif ($this->_trans_depth > 1 OR $this->/** @scrutinizer ignore-call */ _trans_rollback())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
960
		{
961
			$this->_trans_depth--;
962
			return TRUE;
963
		}
964
965
		return FALSE;
966
	}
967
968
	// --------------------------------------------------------------------
969
970
	/**
971
	 * Compile Bindings
972
	 *
973
	 * @param	string	the sql statement
974
	 * @param	array	an array of bind data
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\an was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
975
	 * @return	string
976
	 */
977
	public function compile_binds($sql, $binds)
978
	{
979
		if (empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)
980
		{
981
			return $sql;
982
		}
983
		elseif ( ! is_array($binds))
984
		{
985
			$binds = array($binds);
986
			$bind_count = 1;
987
		}
988
		else
989
		{
990
			// Make sure we're using numeric keys
991
			$binds = array_values($binds);
992
			$bind_count = count($binds);
993
		}
994
995
		// We'll need the marker length later
996
		$ml = strlen($this->bind_marker);
997
998
		// Make sure not to replace a chunk inside a string that happens to match the bind marker
999
		if ($c = preg_match_all("/'[^']*'|\"[^\"]*\"/i", $sql, $matches))
1000
		{
1001
			$c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i',
1002
				str_replace($matches[0],
1003
					str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),
1004
					$sql, $c),
1005
				$matches, PREG_OFFSET_CAPTURE);
1006
1007
			// Bind values' count must match the count of markers in the query
1008
			if ($bind_count !== $c)
1009
			{
1010
				return $sql;
1011
			}
1012
		}
1013
		elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
1014
		{
1015
			return $sql;
1016
		}
1017
1018
		do
1019
		{
1020
			$c--;
1021
			$escaped_value = $this->escape($binds[$c]);
1022
			if (is_array($escaped_value))
1023
			{
1024
				$escaped_value = '('.implode(',', $escaped_value).')';
1025
			}
1026
			$sql = substr_replace($sql, $escaped_value, $matches[0][$c][1], $ml);
1027
		}
1028
		while ($c !== 0);
1029
1030
		return $sql;
1031
	}
1032
1033
	// --------------------------------------------------------------------
1034
1035
	/**
1036
	 * Determines if a query is a "write" type.
1037
	 *
1038
	 * @param	string	An SQL query string
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\An was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1039
	 * @return	bool
1040
	 */
1041
	public function is_write_type($sql)
1042
	{
1043
		return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX|MERGE)\s/i', $sql);
1044
	}
1045
1046
	// --------------------------------------------------------------------
1047
1048
	/**
1049
	 * Calculate the aggregate query elapsed time
1050
	 *
1051
	 * @param	int	The number of decimal places
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1052
	 * @return	string
1053
	 */
1054
	public function elapsed_time($decimals = 6)
1055
	{
1056
		return number_format($this->benchmark, $decimals);
1057
	}
1058
1059
	// --------------------------------------------------------------------
1060
1061
	/**
1062
	 * Returns the total number of queries
1063
	 *
1064
	 * @return	int
1065
	 */
1066
	public function total_queries()
1067
	{
1068
		return $this->query_count;
1069
	}
1070
1071
	// --------------------------------------------------------------------
1072
1073
	/**
1074
	 * Returns the last query that was executed
1075
	 *
1076
	 * @return	string
1077
	 */
1078
	public function last_query()
1079
	{
1080
		return end($this->queries);
1081
	}
1082
1083
	// --------------------------------------------------------------------
1084
1085
	/**
1086
	 * "Smart" Escape String
1087
	 *
1088
	 * Escapes data based on type
1089
	 * Sets boolean and null types
1090
	 *
1091
	 * @param	string
1092
	 * @return	mixed
1093
	 */
1094
	public function escape($str)
1095
	{
1096
		if (is_array($str))
1097
		{
1098
			$str = array_map(array(&$this, 'escape'), $str);
1099
			return $str;
1100
		}
1101
		elseif (is_string($str) OR (is_object($str) && method_exists($str, '__toString')))
1102
		{
1103
			return "'".$this->escape_str($str)."'";
0 ignored issues
show
Bug introduced by
It seems like $str can also be of type object; however, parameter $str of Rioxygen\CiCoreDatabase\CI_DB_driver::escape_str() does only seem to accept string|string[], maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1103
			return "'".$this->escape_str(/** @scrutinizer ignore-type */ $str)."'";
Loading history...
1104
		}
1105
		elseif (is_bool($str))
1106
		{
1107
			return ($str === FALSE) ? 0 : 1;
1108
		}
1109
		elseif ($str === NULL)
1110
		{
1111
			return 'NULL';
1112
		}
1113
1114
		return $str;
1115
	}
1116
1117
	// --------------------------------------------------------------------
1118
1119
	/**
1120
	 * Escape String
1121
	 *
1122
	 * @param	string|string[]	$str	Input string
1123
	 * @param	bool	$like	Whether or not the string will be used in a LIKE condition
1124
	 * @return	string
1125
	 */
1126
	public function escape_str($str, $like = FALSE)
1127
	{
1128
		if (is_array($str))
1129
		{
1130
			foreach ($str as $key => $val)
1131
			{
1132
				$str[$key] = $this->escape_str($val, $like);
1133
			}
1134
1135
			return $str;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $str returns the type string[] which is incompatible with the documented return type string.
Loading history...
1136
		}
1137
1138
		$str = $this->_escape_str($str);
1139
1140
		// escape LIKE condition wildcards
1141
		if ($like === TRUE)
1142
		{
1143
			return str_replace(
1144
				array($this->_like_escape_chr, '%', '_'),
1145
				array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
1146
				$str
1147
			);
1148
		}
1149
1150
		return $str;
1151
	}
1152
1153
	// --------------------------------------------------------------------
1154
1155
	/**
1156
	 * Escape LIKE String
1157
	 *
1158
	 * Calls the individual driver for platform
1159
	 * specific escaping for LIKE conditions
1160
	 *
1161
	 * @param	string|string[]
1162
	 * @return	mixed
1163
	 */
1164
	public function escape_like_str($str)
1165
	{
1166
		return $this->escape_str($str, TRUE);
1167
	}
1168
1169
	// --------------------------------------------------------------------
1170
1171
	/**
1172
	 * Platform-dependent string escape
1173
	 *
1174
	 * @param	string
1175
	 * @return	string
1176
	 */
1177
	protected function _escape_str($str)
1178
	{
1179
		return str_replace("'", "''", remove_invisible_characters($str, FALSE));
0 ignored issues
show
Bug introduced by
The function remove_invisible_characters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1179
		return str_replace("'", "''", /** @scrutinizer ignore-call */ remove_invisible_characters($str, FALSE));
Loading history...
1180
	}
1181
1182
	// --------------------------------------------------------------------
1183
1184
	/**
1185
	 * Primary
1186
	 *
1187
	 * Retrieves the primary key. It assumes that the row in the first
1188
	 * position is the primary key
1189
	 *
1190
	 * @param	string	$table	Table name
1191
	 * @return	string
1192
	 */
1193
	public function primary($table)
1194
	{
1195
		$fields = $this->list_fields($table);
1196
		return is_array($fields) ? current($fields) : FALSE;
1197
	}
1198
1199
	// --------------------------------------------------------------------
1200
1201
	/**
1202
	 * "Count All" query
1203
	 *
1204
	 * Generates a platform-specific query string that counts all records in
1205
	 * the specified database
1206
	 *
1207
	 * @param	string
1208
	 * @return	int
1209
	 */
1210
	public function count_all($table = '')
1211
	{
1212
		if ($table === '')
1213
		{
1214
			return 0;
1215
		}
1216
1217
		$query = $this->query($this->_count_string.$this->escape_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
1218
		if ($query->num_rows() === 0)
1219
		{
1220
			return 0;
1221
		}
1222
1223
		$query = $query->row();
1224
		$this->_reset_select();
1225
		return (int) $query->numrows;
1226
	}
1227
1228
	// --------------------------------------------------------------------
1229
1230
	/**
1231
	 * Returns an array of table names
1232
	 *
1233
	 * @param	string	$constrain_by_prefix = FALSE
1234
	 * @return	array
1235
	 */
1236
	public function list_tables($constrain_by_prefix = FALSE)
1237
	{
1238
		// Is there a cached result?
1239
		if (isset($this->data_cache['table_names']))
1240
		{
1241
			return $this->data_cache['table_names'];
1242
		}
1243
1244
		if (FALSE === ($sql = $this->_list_tables($constrain_by_prefix)))
0 ignored issues
show
Bug introduced by
The method _list_tables() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. Did you maybe mean list_tables()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1244
		if (FALSE === ($sql = $this->/** @scrutinizer ignore-call */ _list_tables($constrain_by_prefix)))

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1245
		{
1246
			return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;
1247
		}
1248
1249
		$this->data_cache['table_names'] = array();
1250
		$query = $this->query($sql);
1251
1252 View Code Duplication
		foreach ($query->result_array() as $row)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1253
		{
1254
			// Do we know from which column to get the table name?
1255
			if ( ! isset($key))
1256
			{
1257
				if (isset($row['table_name']))
1258
				{
1259
					$key = 'table_name';
1260
				}
1261
				elseif (isset($row['TABLE_NAME']))
1262
				{
1263
					$key = 'TABLE_NAME';
1264
				}
1265
				else
1266
				{
1267
					/* We have no other choice but to just get the first element's key.
1268
					 * Due to array_shift() accepting its argument by reference, if
1269
					 * E_STRICT is on, this would trigger a warning. So we'll have to
1270
					 * assign it first.
1271
					 */
1272
					$key = array_keys($row);
1273
					$key = array_shift($key);
1274
				}
1275
			}
1276
1277
			$this->data_cache['table_names'][] = $row[$key];
1278
		}
1279
1280
		return $this->data_cache['table_names'];
1281
	}
1282
1283
	// --------------------------------------------------------------------
1284
1285
	/**
1286
	 * Determine if a particular table exists
1287
	 *
1288
	 * @param	string	$table_name
1289
	 * @return	bool
1290
	 */
1291
	public function table_exists($table_name)
1292
	{
1293
		return in_array($this->protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables());
1294
	}
1295
1296
	// --------------------------------------------------------------------
1297
1298
	/**
1299
	 * Fetch Field Names
1300
	 *
1301
	 * @param	string	$table	Table name
1302
	 * @return	array
1303
	 */
1304
	public function list_fields($table)
1305
	{
1306
		// Is there a cached result?
1307
		if (isset($this->data_cache['field_names'][$table]))
1308
		{
1309
			return $this->data_cache['field_names'][$table];
1310
		}
1311
1312
		if (FALSE === ($sql = $this->_list_columns($table)))
0 ignored issues
show
Bug introduced by
The method _list_columns() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. It seems like you code against a sub-type of Rioxygen\CiCoreDatabase\CI_DB_driver such as Rioxygen\CiCoreDatabase\Mysql\CI_DB_mysqli_driver. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1312
		if (FALSE === ($sql = $this->/** @scrutinizer ignore-call */ _list_columns($table)))
Loading history...
1313
		{
1314
			return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;
1315
		}
1316
1317
		$query = $this->query($sql);
1318
		$this->data_cache['field_names'][$table] = array();
1319
1320 View Code Duplication
		foreach ($query->result_array() as $row)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1321
		{
1322
			// Do we know from where to get the column's name?
1323
			if ( ! isset($key))
1324
			{
1325
				if (isset($row['column_name']))
1326
				{
1327
					$key = 'column_name';
1328
				}
1329
				elseif (isset($row['COLUMN_NAME']))
1330
				{
1331
					$key = 'COLUMN_NAME';
1332
				}
1333
				else
1334
				{
1335
					// We have no other choice but to just get the first element's key.
1336
					$key = key($row);
1337
				}
1338
			}
1339
1340
			$this->data_cache['field_names'][$table][] = $row[$key];
1341
		}
1342
1343
		return $this->data_cache['field_names'][$table];
1344
	}
1345
1346
	// --------------------------------------------------------------------
1347
1348
	/**
1349
	 * Determine if a particular field exists
1350
	 *
1351
	 * @param	string
1352
	 * @param	string
1353
	 * @return	bool
1354
	 */
1355
	public function field_exists($field_name, $table_name)
1356
	{
1357
		return in_array($field_name, $this->list_fields($table_name));
1358
	}
1359
1360
	// --------------------------------------------------------------------
1361
1362
	/**
1363
	 * Returns an object with field data
1364
	 *
1365
	 * @param	string	$table	the table name
1366
	 * @return	array
1367
	 */
1368
	public function field_data($table)
1369
	{
1370
		$query = $this->query($this->_field_data($this->protect_identifiers($table, TRUE, NULL, FALSE)));
0 ignored issues
show
Bug introduced by
The method _field_data() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. Did you maybe mean field_data()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1370
		$query = $this->query($this->/** @scrutinizer ignore-call */ _field_data($this->protect_identifiers($table, TRUE, NULL, FALSE)));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1371
		return ($query) ? $query->field_data() : FALSE;
1372
	}
1373
1374
	// --------------------------------------------------------------------
1375
1376
	/**
1377
	 * Escape the SQL Identifiers
1378
	 *
1379
	 * This function escapes column and table names
1380
	 *
1381
	 * @param	mixed
1382
	 * @return	mixed
1383
	 */
1384
	public function escape_identifiers($item)
1385
	{
1386
		if ($this->_escape_char === '' OR empty($item) OR in_array($item, $this->_reserved_identifiers))
1387
		{
1388
			return $item;
1389
		}
1390
		elseif (is_array($item))
1391
		{
1392
			foreach ($item as $key => $value)
1393
			{
1394
				$item[$key] = $this->escape_identifiers($value);
1395
			}
1396
1397
			return $item;
1398
		}
1399
		// Avoid breaking functions and literal values inside queries
1400
		elseif (ctype_digit($item) OR $item[0] === "'" OR ($this->_escape_char !== '"' && $item[0] === '"') OR strpos($item, '(') !== FALSE)
1401
		{
1402
			return $item;
1403
		}
1404
1405
		static $preg_ec = array();
1406
1407
		if (empty($preg_ec))
1408
		{
1409
			if (is_array($this->_escape_char))
1410
			{
1411
				$preg_ec = array(
1412
					preg_quote($this->_escape_char[0], '/'),
1413
					preg_quote($this->_escape_char[1], '/'),
1414
					$this->_escape_char[0],
1415
					$this->_escape_char[1]
1416
				);
1417
			}
1418
			else
1419
			{
1420
				$preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/');
1421
				$preg_ec[2] = $preg_ec[3] = $this->_escape_char;
1422
			}
1423
		}
1424
1425
		foreach ($this->_reserved_identifiers as $id)
1426
		{
1427
			if (strpos($item, '.'.$id) !== FALSE)
1428
			{
1429
				return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);
1430
			}
1431
		}
1432
1433
		return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);
1434
	}
1435
1436
	// --------------------------------------------------------------------
1437
1438
	/**
1439
	 * Generate an insert string
1440
	 *
1441
	 * @param	string	the table upon which the query will be performed
1442
	 * @param	array	an associative array data of key/values
1443
	 * @return	string
1444
	 */
1445
	public function insert_string($table, $data)
1446
	{
1447
		$fields = $values = array();
1448
1449
		foreach ($data as $key => $val)
1450
		{
1451
			$fields[] = $this->escape_identifiers($key);
1452
			$values[] = $this->escape($val);
1453
		}
1454
1455
		return $this->_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values);
1456
	}
1457
1458
	// --------------------------------------------------------------------
1459
1460
	/**
1461
	 * Insert statement
1462
	 *
1463
	 * Generates a platform-specific insert string from the supplied data
1464
	 *
1465
	 * @param	string	the table name
1466
	 * @param	array	the insert keys
1467
	 * @param	array	the insert values
1468
	 * @return	string
1469
	 */
1470
	protected function _insert($table, $keys, $values)
1471
	{
1472
		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
1473
	}
1474
1475
	// --------------------------------------------------------------------
1476
1477
	/**
1478
	 * Generate an update string
1479
	 *
1480
	 * @param	string	the table upon which the query will be performed
1481
	 * @param	array	an associative array data of key/values
1482
	 * @param	mixed	the "where" statement
1483
	 * @return	string
1484
	 */
1485
	public function update_string($table, $data, $where)
1486
	{
1487
		if (empty($where))
1488
		{
1489
			return FALSE;
1490
		}
1491
1492
		$this->where($where);
0 ignored issues
show
Bug introduced by
The method where() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. It seems like you code against a sub-type of Rioxygen\CiCoreDatabase\CI_DB_driver such as Rioxygen\CiCoreDatabase\CI_DB_query_builder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1492
		$this->/** @scrutinizer ignore-call */ 
1493
         where($where);
Loading history...
1493
1494
		$fields = array();
1495
		foreach ($data as $key => $val)
1496
		{
1497
			$fields[$this->protect_identifiers($key)] = $this->escape($val);
1498
		}
1499
1500
		$sql = $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);
1501
		$this->_reset_write();
0 ignored issues
show
Bug introduced by
The method _reset_write() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. It seems like you code against a sub-type of Rioxygen\CiCoreDatabase\CI_DB_driver such as Rioxygen\CiCoreDatabase\CI_DB_query_builder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1501
		$this->/** @scrutinizer ignore-call */ 
1502
         _reset_write();
Loading history...
1502
		return $sql;
1503
	}
1504
1505
	// --------------------------------------------------------------------
1506
1507
	/**
1508
	 * Update statement
1509
	 *
1510
	 * Generates a platform-specific update string from the supplied data
1511
	 *
1512
	 * @param	string	the table name
1513
	 * @param	array	the update data
1514
	 * @return	string
1515
	 */
1516
	protected function _update($table, $values)
1517
	{
1518
		foreach ($values as $key => $val)
1519
		{
1520
			$valstr[] = $key.' = '.$val;
1521
		}
1522
1523
		return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $valstr seems to be defined by a foreach iteration on line 1518. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1524
			.$this->_compile_wh('qb_where')
0 ignored issues
show
Bug introduced by
The method _compile_wh() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. It seems like you code against a sub-type of Rioxygen\CiCoreDatabase\CI_DB_driver such as Rioxygen\CiCoreDatabase\CI_DB_query_builder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1524
			.$this->/** @scrutinizer ignore-call */ _compile_wh('qb_where')
Loading history...
1525
			.$this->_compile_order_by()
0 ignored issues
show
Bug introduced by
The method _compile_order_by() does not exist on Rioxygen\CiCoreDatabase\CI_DB_driver. It seems like you code against a sub-type of Rioxygen\CiCoreDatabase\CI_DB_driver such as Rioxygen\CiCoreDatabase\CI_DB_query_builder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1525
			.$this->/** @scrutinizer ignore-call */ _compile_order_by()
Loading history...
1526
			.($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');
1527
	}
1528
1529
	// --------------------------------------------------------------------
1530
1531
	/**
1532
	 * Tests whether the string has an SQL operator
1533
	 *
1534
	 * @param	string
1535
	 * @return	bool
1536
	 */
1537
	protected function _has_operator($str)
1538
	{
1539
		return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sEXISTS|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
1540
	}
1541
1542
	// --------------------------------------------------------------------
1543
1544
	/**
1545
	 * Returns the SQL string operator
1546
	 *
1547
	 * @param	string
1548
	 * @return	string
1549
	 */
1550
	protected function _get_operator($str)
1551
	{
1552
		static $_operators;
1553
1554
		if (empty($_operators))
1555
		{
1556
			$_les = ($this->_like_escape_str !== '')
1557
				? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/')
1558
				: '';
1559
			$_operators = array(
1560
				'\s*(?:<|>|!)?=\s*',             // =, <=, >=, !=
1561
				'\s*<>?\s*',                     // <, <>
1562
				'\s*>\s*',                       // >
1563
				'\s+IS NULL',                    // IS NULL
1564
				'\s+IS NOT NULL',                // IS NOT NULL
1565
				'\s+EXISTS\s*\(.*\)',        // EXISTS(sql)
1566
				'\s+NOT EXISTS\s*\(.*\)',    // NOT EXISTS(sql)
1567
				'\s+BETWEEN\s+',                 // BETWEEN value AND value
1568
				'\s+IN\s*\(.*\)',            // IN(list)
1569
				'\s+NOT IN\s*\(.*\)',        // NOT IN (list)
1570
				'\s+LIKE\s+\S.*('.$_les.')?',    // LIKE 'expr'[ ESCAPE '%s']
1571
				'\s+NOT LIKE\s+\S.*('.$_les.')?' // NOT LIKE 'expr'[ ESCAPE '%s']
1572
			);
1573
1574
		}
1575
1576
		return preg_match('/'.implode('|', $_operators).'/i', $str, $match)
1577
			? $match[0] : FALSE;
1578
	}
1579
1580
	// --------------------------------------------------------------------
1581
1582
	/**
1583
	 * Enables a native PHP function to be run, using a platform agnostic wrapper.
1584
	 *
1585
	 * @param	string	$function	Function name
1586
	 * @return	mixed
1587
	 */
1588
	public function call_function($function)
1589
	{
1590
		$driver = ($this->dbdriver === 'postgre') ? 'pg_' : $this->dbdriver.'_';
1591
1592
		if (FALSE === strpos($driver, $function))
1593
		{
1594
			$function = $driver.$function;
1595
		}
1596
1597
		if ( ! function_exists($function))
1598
		{
1599
			return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;
1600
		}
1601
1602
		return (func_num_args() > 1)
1603
			? call_user_func_array($function, array_slice(func_get_args(), 1))
1604
			: call_user_func($function);
1605
	}
1606
1607
	// --------------------------------------------------------------------
1608
1609
	/**
1610
	 * Set Cache Directory Path
1611
	 *
1612
	 * @param	string	the path to the cache directory
1613
	 * @return	void
1614
	 */
1615
	public function cache_set_path($path = '')
1616
	{
1617
		$this->cachedir = $path;
1618
	}
1619
1620
	// --------------------------------------------------------------------
1621
1622
	/**
1623
	 * Enable Query Caching
1624
	 *
1625
	 * @return	bool	cache_on value
1626
	 */
1627
	public function cache_on()
1628
	{
1629
		return $this->cache_on = TRUE;
1630
	}
1631
1632
	// --------------------------------------------------------------------
1633
1634
	/**
1635
	 * Disable Query Caching
1636
	 *
1637
	 * @return	bool	cache_on value
1638
	 */
1639
	public function cache_off()
1640
	{
1641
		return $this->cache_on = FALSE;
1642
	}
1643
1644
	// --------------------------------------------------------------------
1645
1646
	/**
1647
	 * Delete the cache files associated with a particular URI
1648
	 *
1649
	 * @param	string	$segment_one = ''
1650
	 * @param	string	$segment_two = ''
1651
	 * @return	bool
1652
	 */
1653
	public function cache_delete($segment_one = '', $segment_two = '')
1654
	{
1655
		return $this->_cache_init()
1656
			? $this->CACHE->delete($segment_one, $segment_two)
1657
			: FALSE;
1658
	}
1659
1660
	// --------------------------------------------------------------------
1661
1662
	/**
1663
	 * Delete All cache files
1664
	 *
1665
	 * @return	bool
1666
	 */
1667
	public function cache_delete_all()
1668
	{
1669
		return $this->_cache_init()
1670
			? $this->CACHE->delete_all()
1671
			: FALSE;
1672
	}
1673
1674
	// --------------------------------------------------------------------
1675
1676
	/**
1677
	 * Initialize the Cache Class
1678
	 *
1679
	 * @return	bool
1680
	 */
1681
	protected function _cache_init()
1682
	{
1683
		if ( ! class_exists('CI_DB_Cache', FALSE))
1684
		{
1685
			require_once(BASEPATH.'database/DB_cache.php');
0 ignored issues
show
Bug introduced by
The constant Rioxygen\CiCoreDatabase\BASEPATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1686
		}
1687
		elseif (is_object($this->CACHE))
1688
		{
1689
			return TRUE;
1690
		}
1691
1692
		$this->CACHE = new CI_DB_Cache($this); // pass db object to support multiple db connections and returned db objects
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\CI_DB_Cache was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1693
		return TRUE;
1694
	}
1695
1696
	// --------------------------------------------------------------------
1697
1698
	/**
1699
	 * Close DB Connection
1700
	 *
1701
	 * @return	void
1702
	 */
1703
	public function close()
1704
	{
1705
		if ($this->conn_id)
1706
		{
1707
			$this->_close();
1708
			$this->conn_id = FALSE;
1709
		}
1710
	}
1711
1712
	// --------------------------------------------------------------------
1713
1714
	/**
1715
	 * Close DB Connection
1716
	 *
1717
	 * This method would be overridden by most of the drivers.
1718
	 *
1719
	 * @return	void
1720
	 */
1721
	protected function _close()
1722
	{
1723
		$this->conn_id = FALSE;
1724
	}
1725
1726
	// --------------------------------------------------------------------
1727
1728
	/**
1729
	 * Display an error message
1730
	 *
1731
	 * @param	string	the error message
1732
	 * @param	string	any "swap" values
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\any was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1733
	 * @param	bool	whether to localize the message
0 ignored issues
show
Bug introduced by
The type Rioxygen\CiCoreDatabase\whether was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1734
	 * @return	string	sends the application/views/errors/error_db.php template
1735
	 */
1736
	public function display_error($error = '', $swap = '', $native = FALSE)
1737
	{
1738
		$LANG =& load_class('Lang', 'core');
0 ignored issues
show
Bug introduced by
The function load_class was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1738
		$LANG =& /** @scrutinizer ignore-call */ load_class('Lang', 'core');
Loading history...
1739
		$LANG->load('db');
1740
1741
		$heading = $LANG->line('db_error_heading');
1742
1743
		if ($native === TRUE)
1744
		{
1745
			$message = (array) $error;
1746
		}
1747
		else
1748
		{
1749
			$message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error)));
1750
		}
1751
1752
		// Find the most likely culprit of the error by going through
1753
		// the backtrace until the source file is no longer in the
1754
		// database folder.
1755
		$trace = debug_backtrace();
1756
		foreach ($trace as $call)
1757
		{
1758
			if (isset($call['file'], $call['class']))
1759
			{
1760
				// We'll need this on Windows, as APPPATH and BASEPATH will always use forward slashes
1761
				if (DIRECTORY_SEPARATOR !== '/')
1762
				{
1763
					$call['file'] = str_replace('\\', '/', $call['file']);
1764
				}
1765
1766
				if (strpos($call['file'], BASEPATH.'database') === FALSE && strpos($call['class'], 'Loader') === FALSE)
0 ignored issues
show
Bug introduced by
The constant Rioxygen\CiCoreDatabase\BASEPATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1767
				{
1768
					// Found it - use a relative path for safety
1769
					$message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']);
0 ignored issues
show
Bug introduced by
The constant Rioxygen\CiCoreDatabase\APPPATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1770
					$message[] = 'Line Number: '.$call['line'];
1771
					break;
1772
				}
1773
			}
1774
		}
1775
1776
		$error =& load_class('Exceptions', 'core');
1777
		echo $error->show_error($heading, $message, 'error_db');
1778
		exit(8); // EXIT_DATABASE
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1779
	}
1780
1781
	// --------------------------------------------------------------------
1782
1783
	/**
1784
	 * Protect Identifiers
1785
	 *
1786
	 * This function is used extensively by the Query Builder class, and by
1787
	 * a couple functions in this class.
1788
	 * It takes a column or table name (optionally with an alias) and inserts
1789
	 * the table prefix onto it. Some logic is necessary in order to deal with
1790
	 * column names that include the path. Consider a query like this:
1791
	 *
1792
	 * SELECT hostname.database.table.column AS c FROM hostname.database.table
1793
	 *
1794
	 * Or a query with aliasing:
1795
	 *
1796
	 * SELECT m.member_id, m.member_name FROM members AS m
1797
	 *
1798
	 * Since the column name can include up to four segments (host, DB, table, column)
1799
	 * or also have an alias prefix, we need to do a bit of work to figure this out and
1800
	 * insert the table prefix (if it exists) in the proper position, and escape only
1801
	 * the correct identifiers.
1802
	 *
1803
	 * @param	string
1804
	 * @param	bool
1805
	 * @param	mixed
1806
	 * @param	bool
1807
	 * @return	string
1808
	 */
1809
	public function protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE)
1810
	{
1811
		if ( ! is_bool($protect_identifiers))
1812
		{
1813
			$protect_identifiers = $this->_protect_identifiers;
1814
		}
1815
1816
		if (is_array($item))
1817
		{
1818
			$escaped_array = array();
1819
			foreach ($item as $k => $v)
1820
			{
1821
				$escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v, $prefix_single, $protect_identifiers, $field_exists);
1822
			}
1823
1824
			return $escaped_array;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $escaped_array returns the type array|string[] which is incompatible with the documented return type string.
Loading history...
1825
		}
1826
1827
		// This is basically a bug fix for queries that use MAX, MIN, etc.
1828
		// If a parenthesis is found we know that we do not need to
1829
		// escape the data or add a prefix. There's probably a more graceful
1830
		// way to deal with this, but I'm not thinking of it -- Rick
1831
		//
1832
		// Added exception for single quotes as well, we don't want to alter
1833
		// literal strings. -- Narf
1834
		if (strcspn($item, "()'") !== strlen($item))
1835
		{
1836
			return $item;
1837
		}
1838
1839
		// Convert tabs or multiple spaces into single spaces
1840
		$item = preg_replace('/\s+/', ' ', trim($item));
1841
1842
		// If the item has an alias declaration we remove it and set it aside.
1843
		// Note: strripos() is used in order to support spaces in table names
1844
		if ($offset = strripos($item, ' AS '))
1845
		{
1846
			$alias = ($protect_identifiers)
1847
				? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4))
0 ignored issues
show
Bug introduced by
Are you sure substr($item, $offset, 4) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1847
				? /** @scrutinizer ignore-type */ substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4))
Loading history...
1848
				: substr($item, $offset);
1849
			$item = substr($item, 0, $offset);
1850
		}
1851
		elseif ($offset = strrpos($item, ' '))
1852
		{
1853
			$alias = ($protect_identifiers)
1854
				? ' '.$this->escape_identifiers(substr($item, $offset + 1))
0 ignored issues
show
Bug introduced by
Are you sure $this->escape_identifier...tr($item, $offset + 1)) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1854
				? ' './** @scrutinizer ignore-type */ $this->escape_identifiers(substr($item, $offset + 1))
Loading history...
1855
				: substr($item, $offset);
1856
			$item = substr($item, 0, $offset);
1857
		}
1858
		else
1859
		{
1860
			$alias = '';
1861
		}
1862
1863
		// Break the string apart if it contains periods, then insert the table prefix
1864
		// in the correct location, assuming the period doesn't indicate that we're dealing
1865
		// with an alias. While we're at it, we will escape the components
1866
		if (strpos($item, '.') !== FALSE)
0 ignored issues
show
Bug introduced by
It seems like $item can also be of type false; however, parameter $haystack of strpos() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1866
		if (strpos(/** @scrutinizer ignore-type */ $item, '.') !== FALSE)
Loading history...
1867
		{
1868
			$parts = explode('.', $item);
0 ignored issues
show
Bug introduced by
It seems like $item can also be of type false; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1868
			$parts = explode('.', /** @scrutinizer ignore-type */ $item);
Loading history...
1869
1870
			// Does the first segment of the exploded item match
1871
			// one of the aliases previously identified? If so,
1872
			// we have nothing more to do other than escape the item
1873
			//
1874
			// NOTE: The ! empty() condition prevents this method
1875
			//       from breaking when QB isn't enabled.
1876
			if ( ! empty($this->qb_aliased_tables) && in_array($parts[0], $this->qb_aliased_tables))
1877
			{
1878
				if ($protect_identifiers === TRUE)
1879
				{
1880
					foreach ($parts as $key => $val)
1881
					{
1882
						if ( ! in_array($val, $this->_reserved_identifiers))
1883
						{
1884
							$parts[$key] = $this->escape_identifiers($val);
1885
						}
1886
					}
1887
1888
					$item = implode('.', $parts);
1889
				}
1890
1891
				return $item.$alias;
0 ignored issues
show
Bug introduced by
Are you sure $item of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1891
				return /** @scrutinizer ignore-type */ $item.$alias;
Loading history...
1892
			}
1893
1894
			// Is there a table prefix defined in the config file? If not, no need to do anything
1895
			if ($this->dbprefix !== '')
1896
			{
1897
				// We now add the table prefix based on some logic.
1898
				// Do we have 4 segments (hostname.database.table.column)?
1899
				// If so, we add the table prefix to the column name in the 3rd segment.
1900
				if (isset($parts[3]))
1901
				{
1902
					$i = 2;
1903
				}
1904
				// Do we have 3 segments (database.table.column)?
1905
				// If so, we add the table prefix to the column name in 2nd position
1906
				elseif (isset($parts[2]))
1907
				{
1908
					$i = 1;
1909
				}
1910
				// Do we have 2 segments (table.column)?
1911
				// If so, we add the table prefix to the column name in 1st segment
1912
				else
1913
				{
1914
					$i = 0;
1915
				}
1916
1917
				// This flag is set when the supplied $item does not contain a field name.
1918
				// This can happen when this function is being called from a JOIN.
1919
				if ($field_exists === FALSE)
1920
				{
1921
					$i++;
1922
				}
1923
1924
				// Verify table prefix and replace if necessary
1925
				if ($this->swap_pre !== '' && strpos($parts[$i], $this->swap_pre) === 0)
1926
				{
1927
					$parts[$i] = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $parts[$i]);
1928
				}
1929
				// We only add the table prefix if it does not already exist
1930
				elseif (strpos($parts[$i], $this->dbprefix) !== 0)
1931
				{
1932
					$parts[$i] = $this->dbprefix.$parts[$i];
1933
				}
1934
1935
				// Put the parts back together
1936
				$item = implode('.', $parts);
1937
			}
1938
1939
			if ($protect_identifiers === TRUE)
1940
			{
1941
				$item = $this->escape_identifiers($item);
1942
			}
1943
1944
			return $item.$alias;
1945
		}
1946
1947
		// Is there a table prefix? If not, no need to insert it
1948
		if ($this->dbprefix !== '')
1949
		{
1950
			// Verify table prefix and replace if necessary
1951
			if ($this->swap_pre !== '' && strpos($item, $this->swap_pre) === 0)
1952
			{
1953
				$item = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $item);
1954
			}
1955
			// Do we prefix an item with no segments?
1956
			elseif ($prefix_single === TRUE && strpos($item, $this->dbprefix) !== 0)
1957
			{
1958
				$item = $this->dbprefix.$item;
1959
			}
1960
		}
1961
1962
		if ($protect_identifiers === TRUE && ! in_array($item, $this->_reserved_identifiers))
1963
		{
1964
			$item = $this->escape_identifiers($item);
1965
		}
1966
1967
		return $item.$alias;
1968
	}
1969
1970
	// --------------------------------------------------------------------
1971
1972
	/**
1973
	 * Dummy method that allows Query Builder class to be disabled
1974
	 * and keep count_all() working.
1975
	 *
1976
	 * @return	void
1977
	 */
1978
	protected function _reset_select()
1979
	{
1980
	}
1981
1982
}
1983