blob: cb33919a450b487862a9c28232a194aecc72cfb0 [file] [log] [blame]
Derek Jonesf4a4bd82011-10-20 12:18:42 -05001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Esen Sagynov2e087942011-08-09 23:35:01 -07002/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 5.1.6 or newer
6 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * 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 *
Esen Sagynov2e087942011-08-09 23:35:01 -070019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Esen Sagynov2e087942011-08-09 23:35:01 -070023 * @link http://codeigniter.com
24 * @since Version 2.0.2
25 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * CUBRID Database Adapter Class
32 *
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
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070040 * @author Esen Sagynov
Esen Sagynov2e087942011-08-09 23:35:01 -070041 * @link http://codeigniter.com/user_guide/database/
42 */
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070043class CI_DB_cubrid_driver extends CI_DB {
44
45 // Default CUBRID Broker port. Will be used unless user
46 // explicitly specifies another one.
47 const DEFAULT_PORT = 33000;
48
Esen Sagynov2e087942011-08-09 23:35:01 -070049 var $dbdriver = 'cubrid';
50
51 // The character used for escaping - no need in CUBRID
52 var $_escape_char = '';
53
54 // clause and character used for LIKE escape sequences - not used in CUBRID
55 var $_like_escape_str = '';
56 var $_like_escape_chr = '';
57
58 /**
59 * The syntax to count rows is slightly different across different
60 * database engines, so this string appears in each driver and is
61 * used for the count_all() and count_all_results() functions.
62 */
63 var $_count_string = 'SELECT COUNT(*) AS ';
64 var $_random_keyword = ' RAND()'; // database specific random keyword
65
66 /**
67 * Non-persistent database connection
68 *
69 * @access private called by the base class
70 * @return resource
71 */
72 function db_connect()
73 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070074 // If no port is defined by the user, use the default value
Esen Sagynov2e087942011-08-09 23:35:01 -070075 if ($this->port == '')
76 {
77 $this->port = self::DEFAULT_PORT;
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070078 }
Esen Sagynov2e087942011-08-09 23:35:01 -070079
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070080 $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password);
Esen Sagynov2e087942011-08-09 23:35:01 -070081
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070082 if ($conn)
83 {
84 // Check if a user wants to run queries in dry, i.e. run the
85 // queries but not commit them.
86 if (isset($this->auto_commit) && ! $this->auto_commit)
87 {
88 cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE);
89 }
90 else
91 {
92 cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE);
93 $this->auto_commit = TRUE;
94 }
95 }
96
97 return $conn;
Esen Sagynov2e087942011-08-09 23:35:01 -070098 }
99
100 // --------------------------------------------------------------------
101
102 /**
103 * Persistent database connection
104 * In CUBRID persistent DB connection is supported natively in CUBRID
105 * engine which can be configured in the CUBRID Broker configuration
106 * file by setting the CCI_PCONNECT parameter to ON. In that case, all
107 * connections established between the client application and the
108 * server will become persistent. This is calling the same
109 * @cubrid_connect function will establish persisten connection
110 * considering that the CCI_PCONNECT is ON.
111 *
112 * @access private called by the base class
113 * @return resource
114 */
115 function db_pconnect()
116 {
117 return $this->db_connect();
118 }
119
120 // --------------------------------------------------------------------
121
122 /**
123 * Reconnect
124 *
125 * Keep / reestablish the db connection if no queries have been
126 * sent for a length of time exceeding the server's idle timeout
127 *
128 * @access public
129 * @return void
130 */
131 function reconnect()
132 {
133 if (cubrid_ping($this->conn_id) === FALSE)
134 {
135 $this->conn_id = FALSE;
136 }
137 }
138
139 // --------------------------------------------------------------------
140
141 /**
142 * Select the database
143 *
144 * @access private called by the base class
145 * @return resource
146 */
147 function db_select()
148 {
149 // In CUBRID there is no need to select a database as the database
150 // is chosen at the connection time.
151 // So, to determine if the database is "selected", all we have to
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700152 // do is ping the server and return that value.
Esen Sagynov2e087942011-08-09 23:35:01 -0700153 return cubrid_ping($this->conn_id);
154 }
155
156 // --------------------------------------------------------------------
157
158 /**
Esen Sagynov2e087942011-08-09 23:35:01 -0700159 * Version number query string
160 *
161 * @access public
162 * @return string
163 */
164 function _version()
165 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700166 // To obtain the CUBRID Server version, no need to run the SQL query.
167 // CUBRID PHP API provides a function to determin this value.
168 // This is why we also need to add 'cubrid' value to the list of
169 // $driver_version_exceptions array in DB_driver class in
170 // version() function.
Esen Sagynov2e087942011-08-09 23:35:01 -0700171 return cubrid_get_server_info($this->conn_id);
172 }
173
174 // --------------------------------------------------------------------
175
176 /**
177 * Execute the query
178 *
179 * @access private called by the base class
180 * @param string an SQL query
181 * @return resource
182 */
183 function _execute($sql)
184 {
185 $sql = $this->_prep_query($sql);
186 return @cubrid_query($sql, $this->conn_id);
187 }
188
189 // --------------------------------------------------------------------
190
191 /**
192 * Prep the query
193 *
194 * If needed, each database adapter can prep the query string
195 *
196 * @access private called by execute()
197 * @param string an SQL query
198 * @return string
199 */
200 function _prep_query($sql)
201 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700202 // No need to prepare
Esen Sagynov2e087942011-08-09 23:35:01 -0700203 return $sql;
204 }
205
206 // --------------------------------------------------------------------
207
208 /**
209 * Begin Transaction
210 *
211 * @access public
212 * @return bool
213 */
214 function trans_begin($test_mode = FALSE)
215 {
216 if ( ! $this->trans_enabled)
217 {
218 return TRUE;
219 }
220
221 // When transactions are nested we only begin/commit/rollback the outermost ones
222 if ($this->_trans_depth > 0)
223 {
224 return TRUE;
225 }
226
227 // Reset the transaction failure flag.
228 // If the $test_mode flag is set to TRUE transactions will be rolled back
229 // even if the queries produce a successful result.
230 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
231
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700232 if (cubrid_get_autocommit($this->conn_id))
233 {
234 cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
235 }
Esen Sagynov2e087942011-08-09 23:35:01 -0700236
237 return TRUE;
238 }
239
240 // --------------------------------------------------------------------
241
242 /**
243 * Commit Transaction
244 *
245 * @access public
246 * @return bool
247 */
248 function trans_commit()
249 {
250 if ( ! $this->trans_enabled)
251 {
252 return TRUE;
253 }
254
255 // When transactions are nested we only begin/commit/rollback the outermost ones
256 if ($this->_trans_depth > 0)
257 {
258 return TRUE;
259 }
260
261 cubrid_commit($this->conn_id);
262
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700263 if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
264 {
265 cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
266 }
267
Esen Sagynov2e087942011-08-09 23:35:01 -0700268 return TRUE;
269 }
270
271 // --------------------------------------------------------------------
272
273 /**
274 * Rollback Transaction
275 *
276 * @access public
277 * @return bool
278 */
279 function trans_rollback()
280 {
281 if ( ! $this->trans_enabled)
282 {
283 return TRUE;
284 }
285
286 // When transactions are nested we only begin/commit/rollback the outermost ones
287 if ($this->_trans_depth > 0)
288 {
289 return TRUE;
290 }
291
292 cubrid_rollback($this->conn_id);
293
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700294 if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
295 {
296 cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
297 }
298
Esen Sagynov2e087942011-08-09 23:35:01 -0700299 return TRUE;
300 }
301
302 // --------------------------------------------------------------------
303
304 /**
305 * Escape String
306 *
307 * @access public
308 * @param string
309 * @param bool whether or not the string will be used in a LIKE condition
310 * @return string
311 */
312 function escape_str($str, $like = FALSE)
313 {
314 if (is_array($str))
315 {
316 foreach ($str as $key => $val)
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700317 {
Esen Sagynov2e087942011-08-09 23:35:01 -0700318 $str[$key] = $this->escape_str($val, $like);
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700319 }
Esen Sagynov2e087942011-08-09 23:35:01 -0700320
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700321 return $str;
322 }
Esen Sagynov2e087942011-08-09 23:35:01 -0700323
324 if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id))
325 {
326 $str = cubrid_real_escape_string($str, $this->conn_id);
327 }
328 else
329 {
330 $str = addslashes($str);
331 }
332
333 // escape LIKE condition wildcards
334 if ($like === TRUE)
335 {
Esen Sagynov2e087942011-08-09 23:35:01 -0700336 $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
337 }
338
339 return $str;
340 }
341
342 // --------------------------------------------------------------------
343
344 /**
345 * Affected Rows
346 *
Andrey Andreevea3eec92012-03-01 19:16:23 +0200347 * @return int
Esen Sagynov2e087942011-08-09 23:35:01 -0700348 */
Andrey Andreevea3eec92012-03-01 19:16:23 +0200349 public function affected_rows()
Esen Sagynov2e087942011-08-09 23:35:01 -0700350 {
Andrey Andreevea3eec92012-03-01 19:16:23 +0200351 return @cubrid_affected_rows();
Esen Sagynov2e087942011-08-09 23:35:01 -0700352 }
353
354 // --------------------------------------------------------------------
355
356 /**
357 * Insert ID
358 *
359 * @access public
360 * @return integer
361 */
362 function insert_id()
363 {
364 return @cubrid_insert_id($this->conn_id);
365 }
366
367 // --------------------------------------------------------------------
368
369 /**
370 * "Count All" query
371 *
372 * Generates a platform-specific query string that counts all records in
373 * the specified table
374 *
375 * @access public
376 * @param string
377 * @return string
378 */
379 function count_all($table = '')
380 {
381 if ($table == '')
382 {
383 return 0;
384 }
385
386 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
387
388 if ($query->num_rows() == 0)
389 {
390 return 0;
391 }
392
393 $row = $query->row();
Greg Aker90248ab2011-08-20 14:23:14 -0500394 $this->_reset_select();
Esen Sagynov2e087942011-08-09 23:35:01 -0700395 return (int) $row->numrows;
396 }
397
398 // --------------------------------------------------------------------
399
400 /**
401 * List table query
402 *
403 * Generates a platform-specific query string so that the table names can be fetched
404 *
405 * @access private
406 * @param boolean
407 * @return string
408 */
409 function _list_tables($prefix_limit = FALSE)
410 {
411 $sql = "SHOW TABLES";
412
413 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
414 {
415 $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
416 }
417
418 return $sql;
419 }
420
421 // --------------------------------------------------------------------
422
423 /**
424 * Show column query
425 *
426 * Generates a platform-specific query string so that the column names can be fetched
427 *
428 * @access public
429 * @param string the table name
430 * @return string
431 */
432 function _list_columns($table = '')
433 {
434 return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
435 }
436
437 // --------------------------------------------------------------------
438
439 /**
440 * Field data query
441 *
442 * Generates a platform-specific query so that the column data can be retrieved
443 *
444 * @access public
445 * @param string the table name
446 * @return object
447 */
448 function _field_data($table)
449 {
450 return "SELECT * FROM ".$table." LIMIT 1";
451 }
452
453 // --------------------------------------------------------------------
454
455 /**
Andrey Andreev4be5de12012-03-02 15:45:41 +0200456 * Error
Esen Sagynov2e087942011-08-09 23:35:01 -0700457 *
Andrey Andreev4be5de12012-03-02 15:45:41 +0200458 * Returns an array containing code and message of the last
459 * database error that has occured.
Esen Sagynov2e087942011-08-09 23:35:01 -0700460 *
Andrey Andreev4be5de12012-03-02 15:45:41 +0200461 * @return array
Esen Sagynov2e087942011-08-09 23:35:01 -0700462 */
Andrey Andreev4be5de12012-03-02 15:45:41 +0200463 public function error()
Esen Sagynov2e087942011-08-09 23:35:01 -0700464 {
Andrey Andreev4be5de12012-03-02 15:45:41 +0200465 return array('code' => cubrid_errno($this->conn_id), 'message' => cubrid_error($this->conn_id));
Esen Sagynov2e087942011-08-09 23:35:01 -0700466 }
467
Esen Sagynov2e087942011-08-09 23:35:01 -0700468 /**
469 * Escape the SQL Identifiers
470 *
471 * This function escapes column and table names
472 *
473 * @access private
474 * @param string
475 * @return string
476 */
477 function _escape_identifiers($item)
478 {
479 if ($this->_escape_char == '')
480 {
481 return $item;
482 }
483
484 foreach ($this->_reserved_identifiers as $id)
485 {
486 if (strpos($item, '.'.$id) !== FALSE)
487 {
488 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
489
490 // remove duplicates if the user already included the escape
491 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
492 }
493 }
494
495 if (strpos($item, '.') !== FALSE)
496 {
497 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
498 }
499 else
500 {
501 $str = $this->_escape_char.$item.$this->_escape_char;
502 }
503
504 // remove duplicates if the user already included the escape
505 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
506 }
507
508 // --------------------------------------------------------------------
509
510 /**
511 * From Tables
512 *
513 * This function implicitly groups FROM tables so there is no confusion
514 * about operator precedence in harmony with SQL standards
515 *
516 * @access public
517 * @param type
518 * @return type
519 */
520 function _from_tables($tables)
521 {
522 if ( ! is_array($tables))
523 {
524 $tables = array($tables);
525 }
526
527 return '('.implode(', ', $tables).')';
528 }
529
530 // --------------------------------------------------------------------
531
532 /**
533 * Insert statement
534 *
535 * Generates a platform-specific insert string from the supplied data
536 *
537 * @access public
538 * @param string the table name
539 * @param array the insert keys
540 * @param array the insert values
541 * @return string
542 */
543 function _insert($table, $keys, $values)
544 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700545 return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
Esen Sagynov2e087942011-08-09 23:35:01 -0700546 }
547
548 // --------------------------------------------------------------------
549
550
551 /**
552 * Replace statement
553 *
554 * Generates a platform-specific replace string from the supplied data
555 *
556 * @access public
557 * @param string the table name
558 * @param array the insert keys
559 * @param array the insert values
560 * @return string
561 */
562 function _replace($table, $keys, $values)
563 {
Esen Sagynovee3e5942011-08-10 03:22:58 -0700564 return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
Esen Sagynov2e087942011-08-09 23:35:01 -0700565 }
566
567 // --------------------------------------------------------------------
568
569 /**
570 * Insert_batch statement
571 *
572 * Generates a platform-specific insert string from the supplied data
573 *
574 * @access public
575 * @param string the table name
576 * @param array the insert keys
577 * @param array the insert values
578 * @return string
579 */
580 function _insert_batch($table, $keys, $values)
581 {
Esen Sagynovee3e5942011-08-10 03:22:58 -0700582 return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values);
Esen Sagynov2e087942011-08-09 23:35:01 -0700583 }
584
585 // --------------------------------------------------------------------
586
587
588 /**
589 * Update statement
590 *
591 * Generates a platform-specific update string from the supplied data
592 *
593 * @access public
594 * @param string the table name
595 * @param array the update data
596 * @param array the where clause
597 * @param array the orderby clause
598 * @param array the limit clause
599 * @return string
600 */
601 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
602 {
603 foreach ($values as $key => $val)
604 {
Esen Sagynovee3e5942011-08-10 03:22:58 -0700605 $valstr[] = sprintf('"%s" = %s', $key, $val);
Esen Sagynov2e087942011-08-09 23:35:01 -0700606 }
607
608 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
609
610 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
611
612 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
613
614 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
615
616 $sql .= $orderby.$limit;
617
618 return $sql;
619 }
620
621 // --------------------------------------------------------------------
622
623
624 /**
625 * Update_Batch statement
626 *
627 * Generates a platform-specific batch update string from the supplied data
628 *
629 * @access public
630 * @param string the table name
631 * @param array the update data
632 * @param array the where clause
633 * @return string
634 */
635 function _update_batch($table, $values, $index, $where = NULL)
636 {
637 $ids = array();
638 $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
639
640 foreach ($values as $key => $val)
641 {
642 $ids[] = $val[$index];
643
644 foreach (array_keys($val) as $field)
645 {
646 if ($field != $index)
647 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700648 $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
Esen Sagynov2e087942011-08-09 23:35:01 -0700649 }
650 }
651 }
652
653 $sql = "UPDATE ".$table." SET ";
654 $cases = '';
655
656 foreach ($final as $k => $v)
657 {
658 $cases .= $k.' = CASE '."\n";
659 foreach ($v as $row)
660 {
661 $cases .= $row."\n";
662 }
663
664 $cases .= 'ELSE '.$k.' END, ';
665 }
666
667 $sql .= substr($cases, 0, -2);
668
669 $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
670
671 return $sql;
672 }
673
674 // --------------------------------------------------------------------
675
676
677 /**
678 * Truncate statement
679 *
680 * Generates a platform-specific truncate string from the supplied data
681 * If the database does not support the truncate() command
682 * This function maps to "DELETE FROM table"
683 *
684 * @access public
685 * @param string the table name
686 * @return string
687 */
688 function _truncate($table)
689 {
690 return "TRUNCATE ".$table;
691 }
692
693 // --------------------------------------------------------------------
694
695 /**
696 * Delete statement
697 *
698 * Generates a platform-specific delete string from the supplied data
699 *
700 * @access public
701 * @param string the table name
702 * @param array the where clause
703 * @param string the limit clause
704 * @return string
705 */
706 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
707 {
708 $conditions = '';
709
710 if (count($where) > 0 OR count($like) > 0)
711 {
712 $conditions = "\nWHERE ";
713 $conditions .= implode("\n", $this->ar_where);
714
715 if (count($where) > 0 && count($like) > 0)
716 {
717 $conditions .= " AND ";
718 }
719 $conditions .= implode("\n", $like);
720 }
721
722 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
723
724 return "DELETE FROM ".$table.$conditions.$limit;
725 }
726
727 // --------------------------------------------------------------------
728
729 /**
730 * Limit string
731 *
732 * Generates a platform-specific LIMIT clause
733 *
734 * @access public
735 * @param string the sql query string
736 * @param integer the number of rows to limit the query to
737 * @param integer the offset value
738 * @return string
739 */
740 function _limit($sql, $limit, $offset)
741 {
742 if ($offset == 0)
743 {
744 $offset = '';
745 }
746 else
747 {
748 $offset .= ", ";
749 }
750
751 return $sql."LIMIT ".$offset.$limit;
752 }
753
754 // --------------------------------------------------------------------
755
756 /**
757 * Close DB Connection
758 *
759 * @access public
760 * @param resource
761 * @return void
762 */
763 function _close($conn_id)
764 {
765 @cubrid_close($conn_id);
766 }
767
768}
769
770
771/* End of file cubrid_driver.php */
Andrey Andreev063f5962012-02-27 12:20:52 +0200772/* Location: ./system/database/drivers/cubrid/cubrid_driver.php */