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