/lenasys/trunk

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