blob: 3f0109249fbbf9d55ae75c6345e7af3a575973a0 [file] [log] [blame]
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -07001<?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 *
7 * @package CodeIgniter
8 * @author Esen Sagynov
9 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
10 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 2.0.2
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * CUBRID 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
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070028 * @author Esen Sagynov
Esen Sagynov2e087942011-08-09 23:35:01 -070029 * @link http://codeigniter.com/user_guide/database/
30 */
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070031class CI_DB_cubrid_driver extends CI_DB {
32
33 // Default CUBRID Broker port. Will be used unless user
34 // explicitly specifies another one.
35 const DEFAULT_PORT = 33000;
36
Esen Sagynov2e087942011-08-09 23:35:01 -070037 var $dbdriver = 'cubrid';
38
39 // The character used for escaping - no need in CUBRID
40 var $_escape_char = '';
41
42 // clause and character used for LIKE escape sequences - not used in CUBRID
43 var $_like_escape_str = '';
44 var $_like_escape_chr = '';
45
46 /**
47 * The syntax to count rows is slightly different across different
48 * database engines, so this string appears in each driver and is
49 * used for the count_all() and count_all_results() functions.
50 */
51 var $_count_string = 'SELECT COUNT(*) AS ';
52 var $_random_keyword = ' RAND()'; // database specific random keyword
53
54 /**
55 * Non-persistent database connection
56 *
57 * @access private called by the base class
58 * @return resource
59 */
60 function db_connect()
61 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070062 // If no port is defined by the user, use the default value
Esen Sagynov2e087942011-08-09 23:35:01 -070063 if ($this->port == '')
64 {
65 $this->port = self::DEFAULT_PORT;
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070066 }
Esen Sagynov2e087942011-08-09 23:35:01 -070067
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070068 $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password);
Esen Sagynov2e087942011-08-09 23:35:01 -070069
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -070070 if ($conn)
71 {
72 // Check if a user wants to run queries in dry, i.e. run the
73 // queries but not commit them.
74 if (isset($this->auto_commit) && ! $this->auto_commit)
75 {
76 cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE);
77 }
78 else
79 {
80 cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE);
81 $this->auto_commit = TRUE;
82 }
83 }
84
85 return $conn;
Esen Sagynov2e087942011-08-09 23:35:01 -070086 }
87
88 // --------------------------------------------------------------------
89
90 /**
91 * Persistent database connection
92 * In CUBRID persistent DB connection is supported natively in CUBRID
93 * engine which can be configured in the CUBRID Broker configuration
94 * file by setting the CCI_PCONNECT parameter to ON. In that case, all
95 * connections established between the client application and the
96 * server will become persistent. This is calling the same
97 * @cubrid_connect function will establish persisten connection
98 * considering that the CCI_PCONNECT is ON.
99 *
100 * @access private called by the base class
101 * @return resource
102 */
103 function db_pconnect()
104 {
105 return $this->db_connect();
106 }
107
108 // --------------------------------------------------------------------
109
110 /**
111 * Reconnect
112 *
113 * Keep / reestablish the db connection if no queries have been
114 * sent for a length of time exceeding the server's idle timeout
115 *
116 * @access public
117 * @return void
118 */
119 function reconnect()
120 {
121 if (cubrid_ping($this->conn_id) === FALSE)
122 {
123 $this->conn_id = FALSE;
124 }
125 }
126
127 // --------------------------------------------------------------------
128
129 /**
130 * Select the database
131 *
132 * @access private called by the base class
133 * @return resource
134 */
135 function db_select()
136 {
137 // In CUBRID there is no need to select a database as the database
138 // is chosen at the connection time.
139 // So, to determine if the database is "selected", all we have to
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700140 // do is ping the server and return that value.
Esen Sagynov2e087942011-08-09 23:35:01 -0700141 return cubrid_ping($this->conn_id);
142 }
143
144 // --------------------------------------------------------------------
145
146 /**
147 * Set client character set
148 *
149 * @access public
150 * @param string
151 * @param string
152 * @return resource
153 */
154 function db_set_charset($charset, $collation)
155 {
156 // In CUBRID, there is no need to set charset or collation.
157 // This is why returning true will allow the application continue
158 // its normal process.
159 return TRUE;
160 }
161
162 // --------------------------------------------------------------------
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700163
Esen Sagynov2e087942011-08-09 23:35:01 -0700164 /**
165 * Version number query string
166 *
167 * @access public
168 * @return string
169 */
170 function _version()
171 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700172 // To obtain the CUBRID Server version, no need to run the SQL query.
173 // CUBRID PHP API provides a function to determin this value.
174 // This is why we also need to add 'cubrid' value to the list of
175 // $driver_version_exceptions array in DB_driver class in
176 // version() function.
Esen Sagynov2e087942011-08-09 23:35:01 -0700177 return cubrid_get_server_info($this->conn_id);
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 resource
188 */
189 function _execute($sql)
190 {
191 $sql = $this->_prep_query($sql);
192 return @cubrid_query($sql, $this->conn_id);
193 }
194
195 // --------------------------------------------------------------------
196
197 /**
198 * Prep the query
199 *
200 * If needed, each database adapter can prep the query string
201 *
202 * @access private called by execute()
203 * @param string an SQL query
204 * @return string
205 */
206 function _prep_query($sql)
207 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700208 // No need to prepare
Esen Sagynov2e087942011-08-09 23:35:01 -0700209 return $sql;
210 }
211
212 // --------------------------------------------------------------------
213
214 /**
215 * Begin Transaction
216 *
217 * @access public
218 * @return bool
219 */
220 function trans_begin($test_mode = FALSE)
221 {
222 if ( ! $this->trans_enabled)
223 {
224 return TRUE;
225 }
226
227 // When transactions are nested we only begin/commit/rollback the outermost ones
228 if ($this->_trans_depth > 0)
229 {
230 return TRUE;
231 }
232
233 // Reset the transaction failure flag.
234 // If the $test_mode flag is set to TRUE transactions will be rolled back
235 // even if the queries produce a successful result.
236 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
237
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700238 if (cubrid_get_autocommit($this->conn_id))
239 {
240 cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
241 }
Esen Sagynov2e087942011-08-09 23:35:01 -0700242
243 return TRUE;
244 }
245
246 // --------------------------------------------------------------------
247
248 /**
249 * Commit Transaction
250 *
251 * @access public
252 * @return bool
253 */
254 function trans_commit()
255 {
256 if ( ! $this->trans_enabled)
257 {
258 return TRUE;
259 }
260
261 // When transactions are nested we only begin/commit/rollback the outermost ones
262 if ($this->_trans_depth > 0)
263 {
264 return TRUE;
265 }
266
267 cubrid_commit($this->conn_id);
268
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700269 if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
270 {
271 cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
272 }
273
Esen Sagynov2e087942011-08-09 23:35:01 -0700274 return TRUE;
275 }
276
277 // --------------------------------------------------------------------
278
279 /**
280 * Rollback Transaction
281 *
282 * @access public
283 * @return bool
284 */
285 function trans_rollback()
286 {
287 if ( ! $this->trans_enabled)
288 {
289 return TRUE;
290 }
291
292 // When transactions are nested we only begin/commit/rollback the outermost ones
293 if ($this->_trans_depth > 0)
294 {
295 return TRUE;
296 }
297
298 cubrid_rollback($this->conn_id);
299
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700300 if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
301 {
302 cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
303 }
304
Esen Sagynov2e087942011-08-09 23:35:01 -0700305 return TRUE;
306 }
307
308 // --------------------------------------------------------------------
309
310 /**
311 * Escape String
312 *
313 * @access public
314 * @param string
315 * @param bool whether or not the string will be used in a LIKE condition
316 * @return string
317 */
318 function escape_str($str, $like = FALSE)
319 {
320 if (is_array($str))
321 {
322 foreach ($str as $key => $val)
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700323 {
Esen Sagynov2e087942011-08-09 23:35:01 -0700324 $str[$key] = $this->escape_str($val, $like);
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700325 }
Esen Sagynov2e087942011-08-09 23:35:01 -0700326
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700327 return $str;
328 }
Esen Sagynov2e087942011-08-09 23:35:01 -0700329
330 if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id))
331 {
332 $str = cubrid_real_escape_string($str, $this->conn_id);
333 }
334 else
335 {
336 $str = addslashes($str);
337 }
338
339 // escape LIKE condition wildcards
340 if ($like === TRUE)
341 {
Esen Sagynov2e087942011-08-09 23:35:01 -0700342 $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
343 }
344
345 return $str;
346 }
347
348 // --------------------------------------------------------------------
349
350 /**
351 * Affected Rows
352 *
353 * @access public
354 * @return integer
355 */
356 function affected_rows()
357 {
358 return @cubrid_affected_rows($this->conn_id);
359 }
360
361 // --------------------------------------------------------------------
362
363 /**
364 * Insert ID
365 *
366 * @access public
367 * @return integer
368 */
369 function insert_id()
370 {
371 return @cubrid_insert_id($this->conn_id);
372 }
373
374 // --------------------------------------------------------------------
375
376 /**
377 * "Count All" query
378 *
379 * Generates a platform-specific query string that counts all records in
380 * the specified table
381 *
382 * @access public
383 * @param string
384 * @return string
385 */
386 function count_all($table = '')
387 {
388 if ($table == '')
389 {
390 return 0;
391 }
392
393 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
394
395 if ($query->num_rows() == 0)
396 {
397 return 0;
398 }
399
400 $row = $query->row();
401 return (int) $row->numrows;
402 }
403
404 // --------------------------------------------------------------------
405
406 /**
407 * List table query
408 *
409 * Generates a platform-specific query string so that the table names can be fetched
410 *
411 * @access private
412 * @param boolean
413 * @return string
414 */
415 function _list_tables($prefix_limit = FALSE)
416 {
417 $sql = "SHOW TABLES";
418
419 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
420 {
421 $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
422 }
423
424 return $sql;
425 }
426
427 // --------------------------------------------------------------------
428
429 /**
430 * Show column query
431 *
432 * Generates a platform-specific query string so that the column names can be fetched
433 *
434 * @access public
435 * @param string the table name
436 * @return string
437 */
438 function _list_columns($table = '')
439 {
440 return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
441 }
442
443 // --------------------------------------------------------------------
444
445 /**
446 * Field data query
447 *
448 * Generates a platform-specific query so that the column data can be retrieved
449 *
450 * @access public
451 * @param string the table name
452 * @return object
453 */
454 function _field_data($table)
455 {
456 return "SELECT * FROM ".$table." LIMIT 1";
457 }
458
459 // --------------------------------------------------------------------
460
461 /**
462 * The error message string
463 *
464 * @access private
465 * @return string
466 */
467 function _error_message()
468 {
469 return cubrid_error($this->conn_id);
470 }
471
472 // --------------------------------------------------------------------
473
474 /**
475 * The error message number
476 *
477 * @access private
478 * @return integer
479 */
480 function _error_number()
481 {
482 return cubrid_errno($this->conn_id);
483 }
484
485 // --------------------------------------------------------------------
486
487 /**
488 * Escape the SQL Identifiers
489 *
490 * This function escapes column and table names
491 *
492 * @access private
493 * @param string
494 * @return string
495 */
496 function _escape_identifiers($item)
497 {
498 if ($this->_escape_char == '')
499 {
500 return $item;
501 }
502
503 foreach ($this->_reserved_identifiers as $id)
504 {
505 if (strpos($item, '.'.$id) !== FALSE)
506 {
507 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
508
509 // remove duplicates if the user already included the escape
510 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
511 }
512 }
513
514 if (strpos($item, '.') !== FALSE)
515 {
516 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
517 }
518 else
519 {
520 $str = $this->_escape_char.$item.$this->_escape_char;
521 }
522
523 // remove duplicates if the user already included the escape
524 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
525 }
526
527 // --------------------------------------------------------------------
528
529 /**
530 * From Tables
531 *
532 * This function implicitly groups FROM tables so there is no confusion
533 * about operator precedence in harmony with SQL standards
534 *
535 * @access public
536 * @param type
537 * @return type
538 */
539 function _from_tables($tables)
540 {
541 if ( ! is_array($tables))
542 {
543 $tables = array($tables);
544 }
545
546 return '('.implode(', ', $tables).')';
547 }
548
549 // --------------------------------------------------------------------
550
551 /**
552 * Insert statement
553 *
554 * Generates a platform-specific insert 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 _insert($table, $keys, $values)
563 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700564 return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
Esen Sagynov2e087942011-08-09 23:35:01 -0700565 }
566
567 // --------------------------------------------------------------------
568
569
570 /**
571 * Replace statement
572 *
573 * Generates a platform-specific replace string from the supplied data
574 *
575 * @access public
576 * @param string the table name
577 * @param array the insert keys
578 * @param array the insert values
579 * @return string
580 */
581 function _replace($table, $keys, $values)
582 {
Esen Sagynovee3e5942011-08-10 03:22:58 -0700583 return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
Esen Sagynov2e087942011-08-09 23:35:01 -0700584 }
585
586 // --------------------------------------------------------------------
587
588 /**
589 * Insert_batch statement
590 *
591 * Generates a platform-specific insert string from the supplied data
592 *
593 * @access public
594 * @param string the table name
595 * @param array the insert keys
596 * @param array the insert values
597 * @return string
598 */
599 function _insert_batch($table, $keys, $values)
600 {
Esen Sagynovee3e5942011-08-10 03:22:58 -0700601 return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values);
Esen Sagynov2e087942011-08-09 23:35:01 -0700602 }
603
604 // --------------------------------------------------------------------
605
606
607 /**
608 * Update statement
609 *
610 * Generates a platform-specific update string from the supplied data
611 *
612 * @access public
613 * @param string the table name
614 * @param array the update data
615 * @param array the where clause
616 * @param array the orderby clause
617 * @param array the limit clause
618 * @return string
619 */
620 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
621 {
622 foreach ($values as $key => $val)
623 {
Esen Sagynovee3e5942011-08-10 03:22:58 -0700624 $valstr[] = sprintf('"%s" = %s', $key, $val);
Esen Sagynov2e087942011-08-09 23:35:01 -0700625 }
626
627 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
628
629 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
630
631 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
632
633 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
634
635 $sql .= $orderby.$limit;
636
637 return $sql;
638 }
639
640 // --------------------------------------------------------------------
641
642
643 /**
644 * Update_Batch statement
645 *
646 * Generates a platform-specific batch update string from the supplied data
647 *
648 * @access public
649 * @param string the table name
650 * @param array the update data
651 * @param array the where clause
652 * @return string
653 */
654 function _update_batch($table, $values, $index, $where = NULL)
655 {
656 $ids = array();
657 $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
658
659 foreach ($values as $key => $val)
660 {
661 $ids[] = $val[$index];
662
663 foreach (array_keys($val) as $field)
664 {
665 if ($field != $index)
666 {
Esen Sagynov2ab2b1e2011-08-11 00:41:16 -0700667 $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
Esen Sagynov2e087942011-08-09 23:35:01 -0700668 }
669 }
670 }
671
672 $sql = "UPDATE ".$table." SET ";
673 $cases = '';
674
675 foreach ($final as $k => $v)
676 {
677 $cases .= $k.' = CASE '."\n";
678 foreach ($v as $row)
679 {
680 $cases .= $row."\n";
681 }
682
683 $cases .= 'ELSE '.$k.' END, ';
684 }
685
686 $sql .= substr($cases, 0, -2);
687
688 $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
689
690 return $sql;
691 }
692
693 // --------------------------------------------------------------------
694
695
696 /**
697 * Truncate statement
698 *
699 * Generates a platform-specific truncate string from the supplied data
700 * If the database does not support the truncate() command
701 * This function maps to "DELETE FROM table"
702 *
703 * @access public
704 * @param string the table name
705 * @return string
706 */
707 function _truncate($table)
708 {
709 return "TRUNCATE ".$table;
710 }
711
712 // --------------------------------------------------------------------
713
714 /**
715 * Delete statement
716 *
717 * Generates a platform-specific delete string from the supplied data
718 *
719 * @access public
720 * @param string the table name
721 * @param array the where clause
722 * @param string the limit clause
723 * @return string
724 */
725 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
726 {
727 $conditions = '';
728
729 if (count($where) > 0 OR count($like) > 0)
730 {
731 $conditions = "\nWHERE ";
732 $conditions .= implode("\n", $this->ar_where);
733
734 if (count($where) > 0 && count($like) > 0)
735 {
736 $conditions .= " AND ";
737 }
738 $conditions .= implode("\n", $like);
739 }
740
741 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
742
743 return "DELETE FROM ".$table.$conditions.$limit;
744 }
745
746 // --------------------------------------------------------------------
747
748 /**
749 * Limit string
750 *
751 * Generates a platform-specific LIMIT clause
752 *
753 * @access public
754 * @param string the sql query string
755 * @param integer the number of rows to limit the query to
756 * @param integer the offset value
757 * @return string
758 */
759 function _limit($sql, $limit, $offset)
760 {
761 if ($offset == 0)
762 {
763 $offset = '';
764 }
765 else
766 {
767 $offset .= ", ";
768 }
769
770 return $sql."LIMIT ".$offset.$limit;
771 }
772
773 // --------------------------------------------------------------------
774
775 /**
776 * Close DB Connection
777 *
778 * @access public
779 * @param resource
780 * @return void
781 */
782 function _close($conn_id)
783 {
784 @cubrid_close($conn_id);
785 }
786
787}
788
789
790/* End of file cubrid_driver.php */
791/* Location: ./system/database/drivers/cubrid/cubrid_driver.php */