postgre_driver.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2006, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * Postgre Database Adapter Class
00020  *
00021  * Note: _DB is an extender class that the app controller
00022  * creates dynamically based on whether the active record
00023  * class is being used or not.
00024  *
00025  * @package             CodeIgniter
00026  * @subpackage  Drivers
00027  * @category    Database
00028  * @author              ExpressionEngine Dev Team
00029  * @link                http://codeigniter.com/user_guide/database/
00030  */
00031 class CI_DB_postgre_driver extends CI_DB {
00032 
00033         /**
00034          * The syntax to count rows is slightly different across different
00035          * database engines, so this string appears in each driver and is
00036          * used for the count_all() and count_all_results() functions.
00037          */
00038         var $_count_string = "SELECT COUNT(*) AS ";
00039         var $_random_keyword = ' RANDOM()'; // database specific random keyword
00040 
00041         /**
00042          * Non-persistent database connection
00043          *
00044          * @access      private called by the base class
00045          * @return      resource
00046          */     
00047         function db_connect()
00048         {
00049                 $port = ($this->port == '') ? '' : " port=".$this->port;
00050                 
00051                 return @pg_connect("host=".$this->hostname.$port." dbname=".$this->database." user=".$this->username." password=".$this->password);
00052         }
00053 
00054         // --------------------------------------------------------------------
00055 
00056         /**
00057          * Persistent database connection
00058          *
00059          * @access      private called by the base class
00060          * @return      resource
00061          */     
00062         function db_pconnect()
00063         {
00064                 $port = ($this->port == '') ? '' : " port=".$this->port;
00065 
00066                 return @pg_pconnect("host=".$this->hostname.$port." dbname=".$this->database." user=".$this->username." password=".$this->password);
00067         }
00068         
00069         // --------------------------------------------------------------------
00070 
00071         /**
00072          * Select the database
00073          *
00074          * @access      private called by the base class
00075          * @return      resource
00076          */     
00077         function db_select()
00078         {
00079                 // Not needed for Postgre so we'll return TRUE
00080                 return TRUE;
00081         }
00082 
00083         // --------------------------------------------------------------------
00084 
00085         /**
00086          * Set client character set
00087          *
00088          * @access      public
00089          * @param       string
00090          * @param       string
00091          * @return      resource
00092          */
00093         function db_set_charset($charset, $collation)
00094         {
00095                 // TODO - add support if needed
00096                 return TRUE;
00097         }
00098 
00099         // --------------------------------------------------------------------
00100         
00101         /**
00102          * Version number query string
00103          *
00104          * @access      public
00105          * @return      string
00106          */
00107         function _version()
00108         {
00109                 return "SELECT version() AS ver";
00110         }
00111 
00112         // --------------------------------------------------------------------
00113 
00114         /**
00115          * Execute the query
00116          *
00117          * @access      private called by the base class
00118          * @param       string  an SQL query
00119          * @return      resource
00120          */     
00121         function _execute($sql)
00122         {
00123                 $sql = $this->_prep_query($sql);
00124                 return @pg_query($this->conn_id, $sql);
00125         }
00126         
00127         // --------------------------------------------------------------------
00128 
00129         /**
00130          * Prep the query
00131          *
00132          * If needed, each database adapter can prep the query string
00133          *
00134          * @access      private called by execute()
00135          * @param       string  an SQL query
00136          * @return      string
00137          */     
00138         function _prep_query($sql)
00139         {
00140                 return $sql;
00141         }
00142 
00143         // --------------------------------------------------------------------
00144 
00145         /**
00146          * Begin Transaction
00147          *
00148          * @access      public
00149          * @return      bool            
00150          */     
00151         function trans_begin($test_mode = FALSE)
00152         {
00153                 if ( ! $this->trans_enabled)
00154                 {
00155                         return TRUE;
00156                 }
00157                 
00158                 // When transactions are nested we only begin/commit/rollback the outermost ones
00159                 if ($this->_trans_depth > 0)
00160                 {
00161                         return TRUE;
00162                 }
00163 
00164                 // Reset the transaction failure flag.
00165                 // If the $test_mode flag is set to TRUE transactions will be rolled back
00166                 // even if the queries produce a successful result.
00167                 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
00168 
00169                 return @pg_exec($this->conn_id, "begin");
00170         }
00171 
00172         // --------------------------------------------------------------------
00173 
00174         /**
00175          * Commit Transaction
00176          *
00177          * @access      public
00178          * @return      bool            
00179          */     
00180         function trans_commit()
00181         {
00182                 if ( ! $this->trans_enabled)
00183                 {
00184                         return TRUE;
00185                 }
00186 
00187                 // When transactions are nested we only begin/commit/rollback the outermost ones
00188                 if ($this->_trans_depth > 0)
00189                 {
00190                         return TRUE;
00191                 }
00192 
00193                 return @pg_exec($this->conn_id, "commit");
00194         }
00195 
00196         // --------------------------------------------------------------------
00197 
00198         /**
00199          * Rollback Transaction
00200          *
00201          * @access      public
00202          * @return      bool            
00203          */     
00204         function trans_rollback()
00205         {
00206                 if ( ! $this->trans_enabled)
00207                 {
00208                         return TRUE;
00209                 }
00210 
00211                 // When transactions are nested we only begin/commit/rollback the outermost ones
00212                 if ($this->_trans_depth > 0)
00213                 {
00214                         return TRUE;
00215                 }
00216 
00217                 return @pg_exec($this->conn_id, "rollback");
00218         }
00219 
00220         // --------------------------------------------------------------------
00221 
00222         /**
00223          * Escape String
00224          *
00225          * @access      public
00226          * @param       string
00227          * @return      string
00228          */
00229         function escape_str($str)       
00230         {       
00231                 return pg_escape_string($str);
00232         }
00233                 
00234         // --------------------------------------------------------------------
00235 
00236         /**
00237          * Affected Rows
00238          *
00239          * @access      public
00240          * @return      integer
00241          */
00242         function affected_rows()
00243         {
00244                 return @pg_affected_rows($this->result_id);
00245         }
00246         
00247         // --------------------------------------------------------------------
00248 
00249         /**
00250          * Insert ID
00251          *
00252          * @access      public
00253          * @return      integer
00254          */
00255         function insert_id()
00256         {
00257                 $v = $this->_version();
00258                 $v = $v['server'];
00259                 
00260                 $table  = func_num_args() > 0 ? func_get_arg(0) : null;
00261                 $column = func_num_args() > 1 ? func_get_arg(1) : null;
00262                 
00263                 if ($table == null && $v >= '8.1')
00264                 {
00265                         $sql='SELECT LASTVAL() as ins_id';
00266                 }
00267                 elseif ($table != null && $column != null && $v >= '8.0')
00268                 {
00269                         $sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
00270                         $query = $this->query($sql);
00271                         $row = $query->row();
00272                         $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq);
00273                 }
00274                 elseif ($table != null)
00275                 {
00276                         // seq_name passed in table parameter
00277                         $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
00278                 }
00279                 else
00280                 {
00281                         return pg_last_oid($this->result_id);
00282                 }
00283                 $query = $this->query($sql);
00284                 $row = $query->row();
00285                 return $row->ins_id;
00286         }
00287 
00288         // --------------------------------------------------------------------
00289 
00290         /**
00291          * "Count All" query
00292          *
00293          * Generates a platform-specific query string that counts all records in
00294          * the specified database
00295          *
00296          * @access      public
00297          * @param       string
00298          * @return      string
00299          */
00300         function count_all($table = '')
00301         {
00302                 if ($table == '')
00303                         return '0';
00304 
00305                 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows'). " FROM " . $this->_protect_identifiers($this->dbprefix.$table));
00306                                 
00307                 if ($query->num_rows() == 0)
00308                         return '0';
00309 
00310                 $row = $query->row();
00311                 return $row->numrows;
00312         }
00313 
00314         // --------------------------------------------------------------------
00315 
00316         /**
00317          * Show table query
00318          *
00319          * Generates a platform-specific query string so that the table names can be fetched
00320          *
00321          * @access      private
00322          * @param       boolean
00323          * @return      string
00324          */
00325         function _list_tables($prefix_limit = FALSE)
00326         {       
00327                 $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";        
00328                 
00329                 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
00330                 {
00331                         $sql .= " AND table_name LIKE '".$this->dbprefix."%'";
00332                 }
00333                 
00334                 return $sql;
00335         }
00336         
00337         // --------------------------------------------------------------------
00338 
00339         /**
00340          * Show column query
00341          *
00342          * Generates a platform-specific query string so that the column names can be fetched
00343          *
00344          * @access      public
00345          * @param       string  the table name
00346          * @return      string
00347          */
00348         function _list_columns($table = '')
00349         {
00350                 return "SELECT column_name FROM information_schema.columns WHERE table_name ='".$this->_escape_table($table)."'";
00351         }
00352 
00353         // --------------------------------------------------------------------
00354 
00355         /**
00356          * Field data query
00357          *
00358          * Generates a platform-specific query so that the column data can be retrieved
00359          *
00360          * @access      public
00361          * @param       string  the table name
00362          * @return      object
00363          */
00364         function _field_data($table)
00365         {
00366                 return "SELECT * FROM ".$this->_escape_table($table)." LIMIT 1";
00367         }
00368 
00369         // --------------------------------------------------------------------
00370 
00371         /**
00372          * The error message string
00373          *
00374          * @access      private
00375          * @return      string
00376          */
00377         function _error_message()
00378         {
00379                 return pg_last_error($this->conn_id);
00380         }
00381         
00382         // --------------------------------------------------------------------
00383 
00384         /**
00385          * The error message number
00386          *
00387          * @access      private
00388          * @return      integer
00389          */
00390         function _error_number()
00391         {
00392                 return '';
00393         }
00394         
00395         // --------------------------------------------------------------------
00396 
00397         /**
00398          * Escape Table Name
00399          *
00400          * This function adds backticks if the table name has a period
00401          * in it. Some DBs will get cranky unless periods are escaped.
00402          *
00403          * @access      private
00404          * @param       string  the table name
00405          * @return      string
00406          */
00407         function _escape_table($table)
00408         {
00409                 if (strpos($table, '.') !== FALSE)
00410                 {
00411                         $table = '"' . str_replace('.', '"."', $table) . '"';
00412                 }
00413                 
00414                 return $table;
00415         }
00416         
00417         // --------------------------------------------------------------------
00418 
00419         /**
00420          * Protect Identifiers
00421          *
00422          * This function adds backticks if appropriate based on db type
00423          *
00424          * @access      private
00425          * @param       mixed   the item to escape
00426          * @param       boolean only affect the first word
00427          * @return      mixed   the item with backticks
00428          */
00429         function _protect_identifiers($item, $first_word_only = FALSE)
00430         {
00431                 if (is_array($item))
00432                 {
00433                         $escaped_array = array();
00434 
00435                         foreach($item as $k=>$v)
00436                         {
00437                                 $escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v, $first_word_only);
00438                         }
00439 
00440                         return $escaped_array;
00441                 }       
00442 
00443                 // This function may get "item1 item2" as a string, and so
00444                 // we may need ""item1" "item2"" and not ""item1 item2""
00445                 if (ctype_alnum($item) === FALSE)
00446                 {
00447                         if (strpos($item, '.') !== FALSE)
00448                         {
00449                                 $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
00450                                 $table_name =  substr($item, 0, strpos($item, '.')+1);
00451                                 $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
00452                         }
00453 
00454                         // This function may get "field >= 1", and need it to return ""field" >= 1"
00455                         $lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
00456 
00457                         $item = preg_replace('/(^'.$lbound.')([\w\d\-\_]+?)(\s|\)|$)/iS', '$1"$2"$3', $item);
00458                 }
00459                 else
00460                 {
00461                         return "\"{$item}\"";
00462                 }
00463 
00464                 $exceptions = array('AS', '/', '-', '%', '+', '*', 'OR', 'IS');
00465                 
00466                 foreach ($exceptions as $exception)
00467                 {
00468                 
00469                         if (stristr($item, " \"{$exception}\" ") !== FALSE)
00470                         {
00471                                 $item = preg_replace('/ "('.preg_quote($exception).')" /i', ' $1 ', $item);
00472                         }
00473                 }
00474                 return $item;
00475         }
00476                         
00477         // --------------------------------------------------------------------
00478 
00479         /**
00480          * From Tables
00481          *
00482          * This function implicitly groups FROM tables so there is no confusion
00483          * about operator precedence in harmony with SQL standards
00484          *
00485          * @access      public
00486          * @param       type
00487          * @return      type
00488          */
00489         function _from_tables($tables)
00490         {
00491                 if ( ! is_array($tables))
00492                 {
00493                         $tables = array($tables);
00494                 }
00495                 
00496                 return implode(', ', $tables);
00497         }
00498 
00499         // --------------------------------------------------------------------
00500         
00501         /**
00502          * Insert statement
00503          *
00504          * Generates a platform-specific insert string from the supplied data
00505          *
00506          * @access      public
00507          * @param       string  the table name
00508          * @param       array   the insert keys
00509          * @param       array   the insert values
00510          * @return      string
00511          */
00512         function _insert($table, $keys, $values)
00513         {       
00514                 return "INSERT INTO ".$this->_escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
00515         }
00516         
00517         // --------------------------------------------------------------------
00518 
00519         /**
00520          * Update statement
00521          *
00522          * Generates a platform-specific update string from the supplied data
00523          *
00524          * @access      public
00525          * @param       string  the table name
00526          * @param       array   the update data
00527          * @param       array   the where clause
00528          * @param       array   the orderby clause
00529          * @param       array   the limit clause
00530          * @return      string
00531          */
00532         function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
00533         {
00534                 foreach($values as $key => $val)
00535                 {
00536                         $valstr[] = $key." = ".$val;
00537                 }
00538                 
00539                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
00540                 
00541                 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
00542         
00543                 $sql = "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr);
00544                 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
00545                 $sql .= $orderby.$limit;
00546                 
00547                 return $sql;
00548         }
00549 
00550         
00551         // --------------------------------------------------------------------
00552 
00553         /**
00554          * Truncate statement
00555          *
00556          * Generates a platform-specific truncate string from the supplied data
00557          * If the database does not support the truncate() command
00558          * This function maps to "DELETE FROM table"
00559          *
00560          * @access      public
00561          * @param       string  the table name
00562          * @return      string
00563          */     
00564         function _truncate($table)
00565         {
00566                 return "TRUNCATE ".$this->_escape_table($table);
00567         }
00568         
00569         // --------------------------------------------------------------------
00570 
00571         /**
00572          * Delete statement
00573          *
00574          * Generates a platform-specific delete string from the supplied data
00575          *
00576          * @access      public
00577          * @param       string  the table name
00578          * @param       array   the where clause
00579          * @param       string  the limit clause
00580          * @return      string
00581          */     
00582         function _delete($table, $where = array(), $like = array(), $limit = FALSE)
00583         {
00584                 $conditions = '';
00585 
00586                 if (count($where) > 0 OR count($like) > 0)
00587                 {
00588                         $conditions = "\nWHERE ";
00589                         $conditions .= implode("\n", $this->ar_where);
00590 
00591                         if (count($where) > 0 && count($like) > 0)
00592                         {
00593                                 $conditions .= " AND ";
00594                         }
00595                         $conditions .= implode("\n", $like);
00596                 }
00597 
00598                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
00599         
00600                 return "DELETE FROM ".$table.$conditions.$limit;
00601         }
00602 
00603         // --------------------------------------------------------------------
00604         /**
00605          * Limit string
00606          *
00607          * Generates a platform-specific LIMIT clause
00608          *
00609          * @access      public
00610          * @param       string  the sql query string
00611          * @param       integer the number of rows to limit the query to
00612          * @param       integer the offset value
00613          * @return      string
00614          */
00615         function _limit($sql, $limit, $offset)
00616         {       
00617                 $sql .= "LIMIT ".$limit;
00618         
00619                 if ($offset > 0)
00620                 {
00621                         $sql .= " OFFSET ".$offset;
00622                 }
00623                 
00624                 return $sql;
00625         }
00626 
00627         // --------------------------------------------------------------------
00628 
00629         /**
00630          * Close DB Connection
00631          *
00632          * @access      public
00633          * @param       resource
00634          * @return      void
00635          */
00636         function _close($conn_id)
00637         {
00638                 @pg_close($conn_id);
00639         }
00640 
00641 
00642 }
00643 
00644 
00645 /* End of file postgre_driver.php */
00646 /* Location: ./system/database/drivers/postgre/postgre_driver.php */