blob: 5e5c01ef9a64db12545280ea02eb33dac7718c86 [file] [log] [blame]
Timothy Warren80ab8162011-08-22 18:26:12 -04001<?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 *
Timothy Warrend1a5ba22011-10-21 04:45:28 -04007 * NOTICE OF LICENSE
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Timothy Warren80ab8162011-08-22 18:26:12 -040019 * @package CodeIgniter
Timothy Warrend1a5ba22011-10-21 04:45:28 -040020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Timothy Warrend1a5ba22011-10-21 04:45:28 -040022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Timothy Warren80ab8162011-08-22 18:26:12 -040023 * @link http://codeigniter.com
Timothy Warren018af7a2011-09-07 12:07:35 -040024 * @since Version 2.1.0
Timothy Warren80ab8162011-08-22 18:26:12 -040025 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
Timothy Warren02615962011-08-24 08:21:36 -040031 * PDO Database Adapter Class
Timothy Warren80ab8162011-08-22 18:26:12 -040032 *
33 * Note: _DB is an extender class that the app controller
34 * creates dynamically based on whether the active record
35 * class is being used or not.
36 *
37 * @package CodeIgniter
38 * @subpackage Drivers
39 * @category Database
Timothy Warrend1a5ba22011-10-21 04:45:28 -040040 * @author EllisLab Dev Team
Timothy Warren80ab8162011-08-22 18:26:12 -040041 * @link http://codeigniter.com/user_guide/database/
42 */
43class CI_DB_pdo_driver extends CI_DB {
44
45 var $dbdriver = 'pdo';
46
47 // the character used to excape - not necessary for PDO
48 var $_escape_char = '';
Taufan Aditya18209332012-02-09 16:07:27 +070049
50 // clause and character used for LIKE escape sequences
Timothy Warrenc7ba6642011-09-14 12:25:14 -040051 var $_like_escape_str;
52 var $_like_escape_chr;
Timothy Warren80ab8162011-08-22 18:26:12 -040053
54 /**
55 * The syntax to count rows is slightly different across different
56 * database engines, so this string appears in each driver and is
57 * used for the count_all() and count_all_results() functions.
58 */
59 var $_count_string = "SELECT COUNT(*) AS ";
60 var $_random_keyword;
Taufan Aditya18209332012-02-09 16:07:27 +070061
62 // need to track the pdo DSN, driver and options
63 var $dsn;
64 var $pdodriver;
Timothy Warren7aae3682011-10-25 10:37:31 -040065 var $options = array();
Timothy Warren80ab8162011-08-22 18:26:12 -040066
Timothy Warren51b0e642011-09-13 13:30:27 -040067 function __construct($params)
Timothy Warren80ab8162011-08-22 18:26:12 -040068 {
Timothy Warrenb5a43b02011-10-04 17:26:04 -040069 parent::__construct($params);
Taufan Aditya18209332012-02-09 16:07:27 +070070
71 if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) == 2)
72 {
73 // If there is a minimum valid dsn string pattern found, we're done
Taufan Adityafdd6ad02012-02-10 13:10:27 +070074 // This is for general PDO users, who tend to have a full DSN string.
Taufan Aditya18209332012-02-09 16:07:27 +070075 $this->pdodriver = end($match);
76 }
77 else
78 {
79 // Try to build a complete DSN string from params
80 $this->_connect_string($params);
81 }
82
Timothy Warrenc7ba6642011-09-14 12:25:14 -040083 // clause and character used for LIKE escape sequences
Taufan Aditya18209332012-02-09 16:07:27 +070084 // this one depends on the driver being used
85 if ($this->pdodriver == 'mysql')
Timothy Warrenc7ba6642011-09-14 12:25:14 -040086 {
87 $this->_like_escape_str = '';
88 $this->_like_escape_chr = '';
89 }
Taufan Aditya18209332012-02-09 16:07:27 +070090 elseif ($this->pdodriver == 'odbc')
Timothy Warrenc7ba6642011-09-14 12:25:14 -040091 {
92 $this->_like_escape_str = " {escape '%s'} ";
93 $this->_like_escape_chr = '!';
94 }
95 else
96 {
97 $this->_like_escape_str = " ESCAPE '%s' ";
98 $this->_like_escape_chr = '!';
99 }
100
Taufan Aditya18209332012-02-09 16:07:27 +0700101 $this->trans_enabled = FALSE;
Timothy Warren80ab8162011-08-22 18:26:12 -0400102 $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
103 }
104
105 /**
Taufan Aditya18209332012-02-09 16:07:27 +0700106 * Connection String
107 *
108 * @access private
109 * @param array
110 * @return void
111 */
112 function _connect_string($params)
113 {
114 if (strpos($this->hostname, ':'))
115 {
116 // hostname generally would have this prototype
117 // $db['hostname'] = 'pdodriver:host(/Server(/DSN))=hostname(/DSN);';
118 // We need to get the prefix (pdodriver used by PDO).
119 $this->dsn = $this->hostname;
Timothy Warren1c175c82012-02-10 08:37:45 -0500120 $split_dsn = explode(":", $this->hostname);
121 $this->pdodriver = $split_dsn[0];
122
123 // End this part of the dsn with a semicolon
124 $this->dsn .= rtrim(';', $this->dsn) . ';';
Taufan Aditya18209332012-02-09 16:07:27 +0700125 }
126 else
127 {
128 // Invalid DSN, display an error
129 if ( ! array_key_exists('pdodriver', $params))
130 {
131 show_error('Invalid DB Connection String for PDO');
132 }
133
134 // Assuming that the following DSN string format is used:
135 // $dsn = 'pdo://username:password@hostname:port/database?pdodriver=pgsql';
136 $this->dsn = $this->pdodriver.':';
137
138 // Add hostname to the DSN for databases that need it
139 if ( ! empty($this->hostname) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'sybase', 'mssql', 'dblib', 'cubrid')))
140 {
141 $this->dsn .= 'host='.$this->hostname.';';
142 }
143
144 // Add a port to the DSN for databases that can use it
145 if ( ! empty($this->port) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'ibm', 'cubrid')))
146 {
147 $this->dsn .= 'port='.$this->port.';';
148 }
149 }
150
151 // Add the database name to the DSN, if needed
152 if (stripos($this->dsn, 'dbname') === FALSE
153 && in_array($this->pdodriver, array('4D', 'pgsql', 'mysql', 'firebird', 'sybase', 'mssql', 'dblib', 'cubrid')))
154 {
155 $this->dsn .= 'dbname='.$this->database.';';
156 }
157 elseif (stripos($this->dsn, 'database') === FALSE && in_array($this->pdodriver, array('ibm', 'sqlsrv')))
158 {
159 if (stripos($this->dsn, 'dsn') === FALSE)
160 {
161 $this->dsn .= 'database='.$this->database.';';
162 }
163 }
164 elseif ($this->pdodriver === 'sqlite' && $this->dsn === 'sqlite:')
165 {
166 if ($this->database !== ':memory')
167 {
168 if ( ! file_exists($this->database))
169 {
170 show_error('Invalid DB Connection string for PDO SQLite');
171 }
172
173 $this->dsn .= (strpos($this->database, DIRECTORY_SEPARATOR) !== 0) ? DIRECTORY_SEPARATOR : '';
174 }
175
176 $this->dsn .= $this->database;
177 }
178
179 // Add charset to the DSN, if needed
180 if ( ! empty($this->char_set) && in_array($this->pdodriver, array('4D', 'mysql', 'sybase', 'mssql', 'dblib', 'oci')))
181 {
182 $this->dsn .= 'charset='.$this->char_set.';';
183 }
184 }
185
186 /**
Timothy Warren80ab8162011-08-22 18:26:12 -0400187 * Non-persistent database connection
188 *
189 * @access private called by the base class
190 * @return resource
191 */
192 function db_connect()
193 {
Taufan Aditya18209332012-02-09 16:07:27 +0700194 $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
195
196 return $this->pdo_connect();
Timothy Warren80ab8162011-08-22 18:26:12 -0400197 }
198
199 // --------------------------------------------------------------------
200
201 /**
202 * Persistent database connection
203 *
204 * @access private called by the base class
205 * @return resource
206 */
207 function db_pconnect()
208 {
Taufan Aditya18209332012-02-09 16:07:27 +0700209 $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
210 $this->options[PDO::ATTR_PERSISTENT] = TRUE;
Timothy Warrend93393f2011-10-26 11:31:49 -0400211
Taufan Aditya18209332012-02-09 16:07:27 +0700212 return $this->pdo_connect();
213 }
214
215 // --------------------------------------------------------------------
216
217 /**
218 * PDO connection
219 *
220 * @access private called by the PDO driver class
221 * @return resource
222 */
223 function pdo_connect()
224 {
Taufan Aditya62b8cae2012-02-09 16:40:39 +0700225 // Refer : http://php.net/manual/en/ref.pdo-mysql.connection.php
Taufan Aditya18209332012-02-09 16:07:27 +0700226 if ($this->pdodriver == 'mysql' && is_php('5.3.6'))
227 {
Taufan Aditya55bb97e2012-02-09 16:43:26 +0700228 $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES $this->char_set COLLATE '$this->dbcollat'";
Taufan Aditya18209332012-02-09 16:07:27 +0700229 }
230
231 // Connecting...
232 try
233 {
234 $db = new PDO($this->dsn, $this->username, $this->password, $this->options);
235 }
236 catch (PDOException $e)
237 {
238 if ($this->db_debug && empty($this->failover))
239 {
240 $this->display_error($e->getMessage(), '', TRUE);
241 }
242
243 return FALSE;
244 }
245
246 return $db;
Timothy Warren80ab8162011-08-22 18:26:12 -0400247 }
248
249 // --------------------------------------------------------------------
250
251 /**
252 * Reconnect
253 *
254 * Keep / reestablish the db connection if no queries have been
255 * sent for a length of time exceeding the server's idle timeout
256 *
257 * @access public
258 * @return void
259 */
260 function reconnect()
261 {
Timothy Warren02615962011-08-24 08:21:36 -0400262 if ($this->db->db_debug)
263 {
264 return $this->db->display_error('db_unsuported_feature');
265 }
Taufan Aditya18209332012-02-09 16:07:27 +0700266
Timothy Warren02615962011-08-24 08:21:36 -0400267 return FALSE;
Timothy Warren80ab8162011-08-22 18:26:12 -0400268 }
269
270 // --------------------------------------------------------------------
271
272 /**
273 * Select the database
274 *
275 * @access private called by the base class
276 * @return resource
277 */
278 function db_select()
279 {
280 // Not needed for PDO
281 return TRUE;
282 }
283
284 // --------------------------------------------------------------------
285
286 /**
287 * Set client character set
288 *
289 * @access public
290 * @param string
291 * @param string
292 * @return resource
293 */
294 function db_set_charset($charset, $collation)
295 {
Timothy Warren80ab8162011-08-22 18:26:12 -0400296 return TRUE;
297 }
298
299 // --------------------------------------------------------------------
300
301 /**
302 * Version number query string
303 *
304 * @access public
305 * @return string
306 */
307 function _version()
308 {
Timothy Warren36fb8de2011-08-24 08:29:05 -0400309 return $this->conn_id->getAttribute(PDO::ATTR_CLIENT_VERSION);
Timothy Warren80ab8162011-08-22 18:26:12 -0400310 }
311
312 // --------------------------------------------------------------------
313
314 /**
315 * Execute the query
316 *
317 * @access private called by the base class
318 * @param string an SQL query
Timothy Warren51a48882011-09-14 13:47:06 -0400319 * @return object
Timothy Warren80ab8162011-08-22 18:26:12 -0400320 */
321 function _execute($sql)
322 {
323 $sql = $this->_prep_query($sql);
Taufan Aditya18209332012-02-09 16:07:27 +0700324
Timothy Warren51a48882011-09-14 13:47:06 -0400325 $result_id = $this->conn_id->query($sql);
326
Timothy Warrend6691532011-10-07 10:03:01 -0400327 if (is_object($result_id))
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400328 {
329 $this->affect_rows = $result_id->rowCount();
330 }
331 else
332 {
333 $this->affect_rows = 0;
334 }
Timothy Warren51a48882011-09-14 13:47:06 -0400335
336 return $result_id;
Timothy Warren80ab8162011-08-22 18:26:12 -0400337 }
338
339 // --------------------------------------------------------------------
340
341 /**
342 * Prep the query
343 *
344 * If needed, each database adapter can prep the query string
345 *
346 * @access private called by execute()
347 * @param string an SQL query
348 * @return string
349 */
350 function _prep_query($sql)
351 {
Taufan Aditya18209332012-02-09 16:07:27 +0700352 if ($this->pdodriver === 'pgsql')
353 {
354 // Change the backtick(s) for Postgre
355 $sql = str_replace('`', '"', $sql);
356 }
357 elseif ($this->pdodriver === 'sqlite')
358 {
359 // Change the backtick(s) for SQLite
360 $sql = str_replace('`', '', $sql);
361 }
362
Timothy Warren80ab8162011-08-22 18:26:12 -0400363 return $sql;
364 }
365
366 // --------------------------------------------------------------------
367
368 /**
369 * Begin Transaction
370 *
371 * @access public
372 * @return bool
373 */
374 function trans_begin($test_mode = FALSE)
375 {
376 if ( ! $this->trans_enabled)
377 {
378 return TRUE;
379 }
380
381 // When transactions are nested we only begin/commit/rollback the outermost ones
382 if ($this->_trans_depth > 0)
383 {
384 return TRUE;
385 }
386
387 // Reset the transaction failure flag.
388 // If the $test_mode flag is set to TRUE transactions will be rolled back
389 // even if the queries produce a successful result.
Timothy Warrend019fd62011-10-26 11:26:17 -0400390 $this->_trans_failure = (bool) ($test_mode === TRUE);
Timothy Warren80ab8162011-08-22 18:26:12 -0400391
Timothy Warrenab347582011-08-23 12:29:29 -0400392 return $this->conn_id->beginTransaction();
Timothy Warren80ab8162011-08-22 18:26:12 -0400393 }
394
395 // --------------------------------------------------------------------
396
397 /**
398 * Commit Transaction
399 *
400 * @access public
401 * @return bool
402 */
403 function trans_commit()
404 {
405 if ( ! $this->trans_enabled)
406 {
407 return TRUE;
408 }
409
410 // When transactions are nested we only begin/commit/rollback the outermost ones
411 if ($this->_trans_depth > 0)
412 {
413 return TRUE;
414 }
415
Timothy Warrenab347582011-08-23 12:29:29 -0400416 $ret = $this->conn->commit();
Taufan Aditya18209332012-02-09 16:07:27 +0700417
Timothy Warren80ab8162011-08-22 18:26:12 -0400418 return $ret;
419 }
420
421 // --------------------------------------------------------------------
422
423 /**
424 * Rollback Transaction
425 *
426 * @access public
427 * @return bool
428 */
429 function trans_rollback()
430 {
431 if ( ! $this->trans_enabled)
432 {
433 return TRUE;
434 }
435
436 // When transactions are nested we only begin/commit/rollback the outermost ones
437 if ($this->_trans_depth > 0)
438 {
439 return TRUE;
440 }
441
Timothy Warrenab347582011-08-23 12:29:29 -0400442 $ret = $this->conn_id->rollBack();
Taufan Aditya18209332012-02-09 16:07:27 +0700443
Timothy Warren80ab8162011-08-22 18:26:12 -0400444 return $ret;
445 }
446
447 // --------------------------------------------------------------------
448
449 /**
450 * Escape String
451 *
452 * @access public
453 * @param string
454 * @param bool whether or not the string will be used in a LIKE condition
455 * @return string
456 */
457 function escape_str($str, $like = FALSE)
458 {
459 if (is_array($str))
460 {
461 foreach ($str as $key => $val)
462 {
463 $str[$key] = $this->escape_str($val, $like);
464 }
465
466 return $str;
467 }
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400468
Timothy Warren47663972011-10-05 16:44:50 -0400469 //Escape the string
470 $str = $this->conn_id->quote($str);
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400471
Timothy Warren47663972011-10-05 16:44:50 -0400472 //If there are duplicated quotes, trim them away
Timothy Warrend6691532011-10-07 10:03:01 -0400473 if (strpos($str, "'") === 0)
Timothy Warrenec193322011-10-07 09:53:35 -0400474 {
475 $str = substr($str, 1, -1);
476 }
477
Timothy Warren80ab8162011-08-22 18:26:12 -0400478 // escape LIKE condition wildcards
479 if ($like === TRUE)
480 {
481 $str = str_replace( array('%', '_', $this->_like_escape_chr),
Taufan Aditya18209332012-02-09 16:07:27 +0700482 array($this->_like_escape_chr.'%',
483 $this->_like_escape_chr.'_',
484 $this->_like_escape_chr.$this->_like_escape_chr),
Timothy Warren80ab8162011-08-22 18:26:12 -0400485 $str);
486 }
487
488 return $str;
489 }
490
491 // --------------------------------------------------------------------
492
493 /**
494 * Affected Rows
495 *
496 * @access public
497 * @return integer
498 */
499 function affected_rows()
500 {
Timothy Warren51a48882011-09-14 13:47:06 -0400501 return $this->affect_rows;
Timothy Warren80ab8162011-08-22 18:26:12 -0400502 }
503
504 // --------------------------------------------------------------------
505
506 /**
507 * Insert ID
Timothy Warren57cea512011-09-14 14:26:28 -0400508 *
Timothy Warren80ab8162011-08-22 18:26:12 -0400509 * @access public
510 * @return integer
511 */
Timothy Warren51a48882011-09-14 13:47:06 -0400512 function insert_id($name=NULL)
Timothy Warren80ab8162011-08-22 18:26:12 -0400513 {
Taufan Aditya18209332012-02-09 16:07:27 +0700514 if ($this->pdodriver == 'pgsql')
Timothy Warren33512752011-10-07 09:51:49 -0400515 {
Taufan Aditya18209332012-02-09 16:07:27 +0700516 //Convenience method for postgres insertid
Timothy Warren33512752011-10-07 09:51:49 -0400517 $v = $this->_version();
518
519 $table = func_num_args() > 0 ? func_get_arg(0) : NULL;
520
521 if ($table == NULL && $v >= '8.1')
522 {
523 $sql='SELECT LASTVAL() as ins_id';
524 }
Taufan Aditya18209332012-02-09 16:07:27 +0700525
Timothy Warren33512752011-10-07 09:51:49 -0400526 $query = $this->query($sql);
Taufan Aditya18209332012-02-09 16:07:27 +0700527 $row = $query->row();
528
Timothy Warren33512752011-10-07 09:51:49 -0400529 return $row->ins_id;
530 }
531 else
532 {
533 return $this->conn_id->lastInsertId($name);
534 }
Timothy Warren80ab8162011-08-22 18:26:12 -0400535 }
536
537 // --------------------------------------------------------------------
538
539 /**
540 * "Count All" query
541 *
542 * Generates a platform-specific query string that counts all records in
543 * the specified database
544 *
545 * @access public
546 * @param string
547 * @return string
548 */
549 function count_all($table = '')
550 {
551 if ($table == '')
552 {
553 return 0;
554 }
555
Taufan Aditya18209332012-02-09 16:07:27 +0700556 $sql = $this->_count_string.$this->_protect_identifiers('numrows').' FROM ';
557 $sql .= $this->_protect_identifiers($table, TRUE, NULL, FALSE);
558 $query = $this->query($sql);
Timothy Warren80ab8162011-08-22 18:26:12 -0400559
560 if ($query->num_rows() == 0)
561 {
562 return 0;
563 }
564
565 $row = $query->row();
566 $this->_reset_select();
Taufan Aditya18209332012-02-09 16:07:27 +0700567
Timothy Warren80ab8162011-08-22 18:26:12 -0400568 return (int) $row->numrows;
569 }
570
571 // --------------------------------------------------------------------
572
573 /**
574 * Show table query
575 *
576 * Generates a platform-specific query string so that the table names can be fetched
577 *
578 * @access private
579 * @param boolean
580 * @return string
581 */
582 function _list_tables($prefix_limit = FALSE)
583 {
Taufan Aditya18209332012-02-09 16:07:27 +0700584 if ($this->pdodriver == 'pgsql')
585 {
586 // Analog function to show all tables in postgre
587 $sql = "SELECT * FROM information_schema.tables WHERE table_schema = 'public'";
588 }
589 else
590 {
591 $sql = "SHOW TABLES FROM `".$this->database."`";
592 }
Timothy Warren80ab8162011-08-22 18:26:12 -0400593
594 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
595 {
Taufan Aditya18209332012-02-09 16:07:27 +0700596 return FALSE;
Timothy Warren80ab8162011-08-22 18:26:12 -0400597 }
598
599 return $sql;
600 }
601
602 // --------------------------------------------------------------------
603
604 /**
605 * Show column query
606 *
607 * Generates a platform-specific query string so that the column names can be fetched
608 *
609 * @access public
610 * @param string the table name
611 * @return string
612 */
613 function _list_columns($table = '')
614 {
Taufan Aditya18209332012-02-09 16:07:27 +0700615 return 'SHOW COLUMNS FROM '.$this->_from_tables($table);
Timothy Warren80ab8162011-08-22 18:26:12 -0400616 }
617
618 // --------------------------------------------------------------------
619
620 /**
621 * Field data query
622 *
623 * Generates a platform-specific query so that the column data can be retrieved
624 *
625 * @access public
626 * @param string the table name
627 * @return object
628 */
629 function _field_data($table)
630 {
Taufan Aditya18209332012-02-09 16:07:27 +0700631 return 'SELECT TOP 1 FROM '.$this->_from_tables($table);
Timothy Warren80ab8162011-08-22 18:26:12 -0400632 }
633
634 // --------------------------------------------------------------------
635
636 /**
637 * The error message string
638 *
639 * @access private
640 * @return string
641 */
642 function _error_message()
643 {
Timothy Warrenab347582011-08-23 12:29:29 -0400644 $error_array = $this->conn_id->errorInfo();
Taufan Aditya18209332012-02-09 16:07:27 +0700645
Timothy Warrenab347582011-08-23 12:29:29 -0400646 return $error_array[2];
Timothy Warren80ab8162011-08-22 18:26:12 -0400647 }
648
649 // --------------------------------------------------------------------
650
651 /**
652 * The error message number
653 *
654 * @access private
655 * @return integer
656 */
657 function _error_number()
658 {
Timothy Warrenab347582011-08-23 12:29:29 -0400659 return $this->conn_id->errorCode();
Timothy Warren80ab8162011-08-22 18:26:12 -0400660 }
661
662 // --------------------------------------------------------------------
663
664 /**
665 * Escape the SQL Identifiers
666 *
667 * This function escapes column and table names
668 *
669 * @access private
670 * @param string
671 * @return string
672 */
673 function _escape_identifiers($item)
674 {
675 if ($this->_escape_char == '')
676 {
677 return $item;
678 }
679
680 foreach ($this->_reserved_identifiers as $id)
681 {
682 if (strpos($item, '.'.$id) !== FALSE)
683 {
684 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
685
686 // remove duplicates if the user already included the escape
687 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
688 }
689 }
690
691 if (strpos($item, '.') !== FALSE)
692 {
Taufan Aditya18209332012-02-09 16:07:27 +0700693 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
694 $str .= $this->_escape_char;
Timothy Warren80ab8162011-08-22 18:26:12 -0400695 }
696 else
697 {
698 $str = $this->_escape_char.$item.$this->_escape_char;
699 }
700
701 // remove duplicates if the user already included the escape
702 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
703 }
704
705 // --------------------------------------------------------------------
706
707 /**
708 * From Tables
709 *
710 * This function implicitly groups FROM tables so there is no confusion
711 * about operator precedence in harmony with SQL standards
712 *
713 * @access public
714 * @param type
715 * @return type
716 */
717 function _from_tables($tables)
718 {
719 if ( ! is_array($tables))
720 {
721 $tables = array($tables);
722 }
723
Taufan Aditya18209332012-02-09 16:07:27 +0700724 return (count($tables) == 1) ? '`'.$tables[0].'`' : '('.implode(', ', $tables).')';
Timothy Warren80ab8162011-08-22 18:26:12 -0400725 }
726
727 // --------------------------------------------------------------------
728
729 /**
730 * Insert statement
731 *
732 * Generates a platform-specific insert string from the supplied data
733 *
734 * @access public
735 * @param string the table name
736 * @param array the insert keys
737 * @param array the insert values
738 * @return string
739 */
740 function _insert($table, $keys, $values)
741 {
Taufan Aditya18209332012-02-09 16:07:27 +0700742 return 'INSERT INTO '.$this->_from_tables($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
Timothy Warren80ab8162011-08-22 18:26:12 -0400743 }
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400744
745 // --------------------------------------------------------------------
746
747 /**
748 * Insert_batch statement
749 *
750 * Generates a platform-specific insert string from the supplied data
751 *
752 * @access public
753 * @param string the table name
754 * @param array the insert keys
755 * @param array the insert values
756 * @return string
757 */
758 function _insert_batch($table, $keys, $values)
759 {
Taufan Aditya18209332012-02-09 16:07:27 +0700760 return 'INSERT INTO '.$this->_from_tables($table).' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400761 }
Timothy Warren80ab8162011-08-22 18:26:12 -0400762
763 // --------------------------------------------------------------------
764
765 /**
766 * Update statement
767 *
768 * Generates a platform-specific update string from the supplied data
769 *
770 * @access public
771 * @param string the table name
772 * @param array the update data
773 * @param array the where clause
774 * @param array the orderby clause
775 * @param array the limit clause
776 * @return string
777 */
778 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
779 {
780 foreach ($values as $key => $val)
781 {
782 $valstr[] = $key." = ".$val;
783 }
784
Taufan Aditya18209332012-02-09 16:07:27 +0700785 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
786 $orderby = (count($orderby) >= 1) ? ' ORDER BY '.implode(', ', $orderby) : '';
Timothy Warren80ab8162011-08-22 18:26:12 -0400787
Taufan Aditya18209332012-02-09 16:07:27 +0700788 $sql = 'UPDATE '.$this->_from_tables($table).' SET '.implode(', ', $valstr);
789 $sql .= ($where != '' && count($where) >= 1) ? ' WHERE '.implode(' ', $where) : '';
Timothy Warren80ab8162011-08-22 18:26:12 -0400790 $sql .= $orderby.$limit;
791
792 return $sql;
793 }
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400794
795 // --------------------------------------------------------------------
796
797 /**
798 * Update_Batch statement
799 *
800 * Generates a platform-specific batch update string from the supplied data
801 *
802 * @access public
803 * @param string the table name
804 * @param array the update data
805 * @param array the where clause
806 * @return string
807 */
808 function _update_batch($table, $values, $index, $where = NULL)
809 {
Taufan Aditya18209332012-02-09 16:07:27 +0700810 $ids = array();
811 $where = ($where != '' && count($where) >=1) ? implode(" ", $where).' AND ' : '';
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400812
813 foreach ($values as $key => $val)
814 {
815 $ids[] = $val[$index];
816
817 foreach (array_keys($val) as $field)
818 {
819 if ($field != $index)
820 {
821 $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
822 }
823 }
824 }
825
Taufan Aditya18209332012-02-09 16:07:27 +0700826 $sql = 'UPDATE '.$this->_from_tables($table).' SET ';
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400827 $cases = '';
828
829 foreach ($final as $k => $v)
830 {
831 $cases .= $k.' = CASE '."\n";
Taufan Aditya18209332012-02-09 16:07:27 +0700832
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400833 foreach ($v as $row)
834 {
835 $cases .= $row."\n";
836 }
837
838 $cases .= 'ELSE '.$k.' END, ';
839 }
840
841 $sql .= substr($cases, 0, -2);
Timothy Warrenb5a43b02011-10-04 17:26:04 -0400842 $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
843
844 return $sql;
845 }
Timothy Warren80ab8162011-08-22 18:26:12 -0400846
847
848 // --------------------------------------------------------------------
849
850 /**
851 * Truncate statement
852 *
853 * Generates a platform-specific truncate string from the supplied data
854 * If the database does not support the truncate() command
855 * This function maps to "DELETE FROM table"
856 *
857 * @access public
858 * @param string the table name
859 * @return string
860 */
861 function _truncate($table)
862 {
863 return $this->_delete($table);
864 }
865
866 // --------------------------------------------------------------------
867
868 /**
869 * Delete statement
870 *
871 * Generates a platform-specific delete string from the supplied data
872 *
873 * @access public
874 * @param string the table name
875 * @param array the where clause
876 * @param string the limit clause
877 * @return string
878 */
879 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
880 {
881 $conditions = '';
882
883 if (count($where) > 0 OR count($like) > 0)
884 {
Taufan Aditya18209332012-02-09 16:07:27 +0700885 $conditions = "\nWHERE ";
Timothy Warren80ab8162011-08-22 18:26:12 -0400886 $conditions .= implode("\n", $this->ar_where);
887
888 if (count($where) > 0 && count($like) > 0)
889 {
890 $conditions .= " AND ";
891 }
Taufan Aditya18209332012-02-09 16:07:27 +0700892
Timothy Warren80ab8162011-08-22 18:26:12 -0400893 $conditions .= implode("\n", $like);
894 }
895
896 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
897
Taufan Aditya18209332012-02-09 16:07:27 +0700898 return 'DELETE FROM '.$this->_from_tables($table).$conditions.$limit;
Timothy Warren80ab8162011-08-22 18:26:12 -0400899 }
900
901 // --------------------------------------------------------------------
902
903 /**
904 * Limit string
905 *
906 * Generates a platform-specific LIMIT clause
907 *
908 * @access public
909 * @param string the sql query string
910 * @param integer the number of rows to limit the query to
911 * @param integer the offset value
912 * @return string
913 */
914 function _limit($sql, $limit, $offset)
915 {
Taufan Aditya18209332012-02-09 16:07:27 +0700916 if ($this->pdodriver == 'cubrid' OR $this->pdodriver == 'sqlite')
Timothy Warren0a43ad82011-09-15 20:15:19 -0400917 {
Taufan Aditya18209332012-02-09 16:07:27 +0700918 $offset = ($offset == 0) ? '' : $offset.', ';
Timothy Warren0a43ad82011-09-15 20:15:19 -0400919
Taufan Aditya18209332012-02-09 16:07:27 +0700920 return $sql.'LIMIT '.$offset.$limit;
Timothy Warren0a43ad82011-09-15 20:15:19 -0400921 }
922 else
923 {
Taufan Aditya18209332012-02-09 16:07:27 +0700924 $sql .= 'LIMIT '.$limit;
925 $sql .= ($offset > 0) ? ' OFFSET '.$offset : '';
Timothy Warren0a43ad82011-09-15 20:15:19 -0400926
927 return $sql;
928 }
Timothy Warren80ab8162011-08-22 18:26:12 -0400929 }
930
931 // --------------------------------------------------------------------
932
933 /**
934 * Close DB Connection
935 *
936 * @access public
937 * @param resource
938 * @return void
939 */
940 function _close($conn_id)
941 {
Timothy Warren6a450cf2011-08-23 12:46:11 -0400942 $this->conn_id = null;
Timothy Warren80ab8162011-08-22 18:26:12 -0400943 }
944
Timothy Warren80ab8162011-08-22 18:26:12 -0400945}
946
Timothy Warren80ab8162011-08-22 18:26:12 -0400947/* End of file pdo_driver.php */
948/* Location: ./system/database/drivers/pdo/pdo_driver.php */