mssql_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) 2008, 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  * MS SQL 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_mssql_driver extends CI_DB {
00032 
00033         var $dbdriver = 'mssql';
00034         
00035         // The character used for escaping
00036         var $_escape_char = '';
00037         /**
00038          * The syntax to count rows is slightly different across different
00039          * database engines, so this string appears in each driver and is
00040          * used for the count_all() and count_all_results() functions.
00041          */
00042         var $_count_string = "SELECT COUNT(*) AS ";
00043         var $_random_keyword = ' ASC'; // not currently supported
00044 
00045         /**
00046          * Non-persistent database connection
00047          *
00048          * @access      private called by the base class
00049          * @return      resource
00050          */     
00051         function db_connect()
00052         {
00053                 if ($this->port != '')
00054                 {
00055                         $this->hostname .= ','.$this->port;
00056                 }
00057 
00058                 return @mssql_connect($this->hostname, $this->username, $this->password);
00059         }
00060         
00061         // --------------------------------------------------------------------
00062 
00063         /**
00064          * Persistent database connection
00065          *
00066          * @access      private called by the base class
00067          * @return      resource
00068          */     
00069         function db_pconnect()
00070         {
00071                 if ($this->port != '')
00072                 {
00073                         $this->hostname .= ','.$this->port;
00074                 }
00075 
00076                 return @mssql_pconnect($this->hostname, $this->username, $this->password);
00077         }
00078         
00079         // --------------------------------------------------------------------
00080 
00081         /**
00082          * Select the database
00083          *
00084          * @access      private called by the base class
00085          * @return      resource
00086          */     
00087         function db_select()
00088         {
00089                 // Note: The brackets are required in the event that the DB name
00090                 // contains reserved characters
00091                 return @mssql_select_db('['.$this->database.']', $this->conn_id);
00092         }
00093 
00094         // --------------------------------------------------------------------
00095         
00096         /**
00097          * Set client character set
00098          *
00099          * @access      public
00100          * @param       string
00101          * @param       string
00102          * @return      resource
00103          */
00104         function db_set_charset($charset, $collation)
00105         {
00106                 // @todo - add support if needed
00107                 return TRUE;
00108         }
00109 
00110         // --------------------------------------------------------------------
00111         
00112         /**
00113          * Execute the query
00114          *
00115          * @access      private called by the base class
00116          * @param       string  an SQL query
00117          * @return      resource
00118          */     
00119         function _execute($sql)
00120         {
00121                 $sql = $this->_prep_query($sql);
00122                 return @mssql_query($sql, $this->conn_id);
00123         }
00124         
00125         // --------------------------------------------------------------------
00126 
00127         /**
00128          * Prep the query
00129          *
00130          * If needed, each database adapter can prep the query string
00131          *
00132          * @access      private called by execute()
00133          * @param       string  an SQL query
00134          * @return      string
00135          */     
00136         function _prep_query($sql)
00137         {
00138                 return $sql;
00139         }
00140 
00141         // --------------------------------------------------------------------
00142 
00143         /**
00144          * Begin Transaction
00145          *
00146          * @access      public
00147          * @return      bool            
00148          */     
00149         function trans_begin($test_mode = FALSE)
00150         {
00151                 if ( ! $this->trans_enabled)
00152                 {
00153                         return TRUE;
00154                 }
00155                 
00156                 // When transactions are nested we only begin/commit/rollback the outermost ones
00157                 if ($this->_trans_depth > 0)
00158                 {
00159                         return TRUE;
00160                 }
00161 
00162                 // Reset the transaction failure flag.
00163                 // If the $test_mode flag is set to TRUE transactions will be rolled back
00164                 // even if the queries produce a successful result.
00165                 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
00166 
00167                 $this->simple_query('BEGIN TRAN');
00168                 return TRUE;
00169         }
00170 
00171         // --------------------------------------------------------------------
00172 
00173         /**
00174          * Commit Transaction
00175          *
00176          * @access      public
00177          * @return      bool            
00178          */     
00179         function trans_commit()
00180         {
00181                 if ( ! $this->trans_enabled)
00182                 {
00183                         return TRUE;
00184                 }
00185 
00186                 // When transactions are nested we only begin/commit/rollback the outermost ones
00187                 if ($this->_trans_depth > 0)
00188                 {
00189                         return TRUE;
00190                 }
00191 
00192                 $this->simple_query('COMMIT TRAN');
00193                 return TRUE;
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                 $this->simple_query('ROLLBACK TRAN');
00218                 return TRUE;
00219         }
00220         
00221         // --------------------------------------------------------------------
00222 
00223         /**
00224          * Escape String
00225          *
00226          * @access      public
00227          * @param       string
00228          * @return      string
00229          */
00230         function escape_str($str)       
00231         {
00232                 // Access the CI object
00233                 $CI =& get_instance();
00234                 
00235                 // Escape single quotes
00236                 return str_replace("'", "''", $CI->input->_remove_invisible_characters($str));
00237         }
00238         
00239         // --------------------------------------------------------------------
00240 
00241         /**
00242          * Affected Rows
00243          *
00244          * @access      public
00245          * @return      integer
00246          */
00247         function affected_rows()
00248         {
00249                 return @mssql_rows_affected($this->conn_id);
00250         }
00251         
00252         // --------------------------------------------------------------------
00253 
00254         /**
00255         * Insert ID
00256         *
00257         * Returns the last id created in the Identity column.
00258         *
00259         * @access public
00260         * @return integer
00261         */
00262         function insert_id()
00263         {
00264                 $ver = self::_parse_major_version($this->version());
00265                 $sql = ($ver >= 8 ? "SELECT SCOPE_IDENTITY() AS last_id" : "SELECT @@IDENTITY AS last_id");
00266                 $query = $this->query($sql);
00267                 $row = $query->row();
00268                 return $row->last_id;
00269         }
00270 
00271         // --------------------------------------------------------------------
00272 
00273         /**
00274         * Parse major version
00275         *
00276         * Grabs the major version number from the 
00277         * database server version string passed in.
00278         *
00279         * @access private
00280         * @param string $version
00281         * @return int16 major version number
00282         */
00283         function _parse_major_version($version)
00284         {
00285                 preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info);
00286                 return $ver_info[1]; // return the major version b/c that's all we're interested in.
00287         }
00288 
00289         // --------------------------------------------------------------------
00290 
00291         /**
00292         * Version number query string
00293         *
00294         * @access public
00295         * @return string
00296         */
00297         function _version()
00298         {
00299                 return "SELECT @@VERSION AS ver";
00300         }
00301 
00302         // --------------------------------------------------------------------
00303 
00304         /**
00305          * "Count All" query
00306          *
00307          * Generates a platform-specific query string that counts all records in
00308          * the specified database
00309          *
00310          * @access      public
00311          * @param       string
00312          * @return      string
00313          */
00314         function count_all($table = '')
00315         {
00316                 if ($table == '')
00317                         return '0';
00318         
00319                 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows'). " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
00320 
00321                 if ($query->num_rows() == 0)
00322                         return '0';
00323 
00324                 $row = $query->row();
00325                 return $row->numrows;
00326         }
00327 
00328         // --------------------------------------------------------------------
00329 
00330         /**
00331          * List table query
00332          *
00333          * Generates a platform-specific query string so that the table names can be fetched
00334          *
00335          * @access      private
00336          * @param       boolean
00337          * @return      string
00338          */
00339         function _list_tables($prefix_limit = FALSE)
00340         {
00341                 $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
00342                 
00343                 // for future compatibility
00344                 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
00345                 {
00346                         //$sql .= " LIKE '".$this->dbprefix."%'";
00347                         return FALSE; // not currently supported
00348                 }
00349                 
00350                 return $sql;
00351         }
00352 
00353         // --------------------------------------------------------------------
00354 
00355         /**
00356          * List column query
00357          *
00358          * Generates a platform-specific query string so that the column names can be fetched
00359          *
00360          * @access      private
00361          * @param       string  the table name
00362          * @return      string
00363          */
00364         function _list_columns($table = '')
00365         {
00366                 return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";      
00367         }
00368 
00369         // --------------------------------------------------------------------
00370 
00371         /**
00372          * Field data query
00373          *
00374          * Generates a platform-specific query so that the column data can be retrieved
00375          *
00376          * @access      public
00377          * @param       string  the table name
00378          * @return      object
00379          */
00380         function _field_data($table)
00381         {
00382                 return "SELECT TOP 1 * FROM ".$table;   
00383         }
00384 
00385         // --------------------------------------------------------------------
00386 
00387         /**
00388          * The error message string
00389          *
00390          * @access      private
00391          * @return      string
00392          */
00393         function _error_message()
00394         {
00395                 // Are errros even supported in MS SQL?
00396                 return '';
00397         }
00398         
00399         // --------------------------------------------------------------------
00400 
00401         /**
00402          * The error message number
00403          *
00404          * @access      private
00405          * @return      integer
00406          */
00407         function _error_number()
00408         {
00409                 // Are error numbers supported?
00410                 return '';
00411         }
00412 
00413         // --------------------------------------------------------------------
00414 
00415         /**
00416          * Escape the SQL Identifiers
00417          *
00418          * This function escapes column and table names
00419          *
00420          * @access      private
00421          * @param       string
00422          * @return      string
00423          */
00424         function _escape_identifiers($item)
00425         {
00426                 if ($this->_escape_char == '')
00427                 {
00428                         return $item;
00429                 }
00430         
00431                 if (strpos($item, '.') !== FALSE)
00432                 {
00433                         $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;                    
00434                 }
00435                 else
00436                 {
00437                         $str = $this->_escape_char.$item.$this->_escape_char;
00438                 }
00439                 
00440                 // remove duplicates if the user already included the escape
00441                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
00442         }
00443         
00444         // --------------------------------------------------------------------
00445 
00446         /**
00447          * From Tables
00448          *
00449          * This function implicitly groups FROM tables so there is no confusion
00450          * about operator precedence in harmony with SQL standards
00451          *
00452          * @access      public
00453          * @param       type
00454          * @return      type
00455          */
00456         function _from_tables($tables)
00457         {
00458                 if ( ! is_array($tables))
00459                 {
00460                         $tables = array($tables);
00461                 }
00462                 
00463                 return implode(', ', $tables);
00464         }
00465 
00466         // --------------------------------------------------------------------
00467         
00468         /**
00469          * Insert statement
00470          *
00471          * Generates a platform-specific insert string from the supplied data
00472          *
00473          * @access      public
00474          * @param       string  the table name
00475          * @param       array   the insert keys
00476          * @param       array   the insert values
00477          * @return      string
00478          */
00479         function _insert($table, $keys, $values)
00480         {       
00481                 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
00482         }
00483         
00484         // --------------------------------------------------------------------
00485 
00486         /**
00487          * Update statement
00488          *
00489          * Generates a platform-specific update string from the supplied data
00490          *
00491          * @access      public
00492          * @param       string  the table name
00493          * @param       array   the update data
00494          * @param       array   the where clause
00495          * @param       array   the orderby clause
00496          * @param       array   the limit clause
00497          * @return      string
00498          */
00499         function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
00500         {
00501                 foreach($values as $key => $val)
00502                 {
00503                         $valstr[] = $key." = ".$val;
00504                 }
00505                 
00506                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
00507                 
00508                 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
00509         
00510                 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
00511 
00512                 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
00513 
00514                 $sql .= $orderby.$limit;
00515                 
00516                 return $sql;
00517         }
00518 
00519         
00520         // --------------------------------------------------------------------
00521 
00522         /**
00523          * Truncate statement
00524          *
00525          * Generates a platform-specific truncate string from the supplied data
00526          * If the database does not support the truncate() command
00527          * This function maps to "DELETE FROM table"
00528          *
00529          * @access      public
00530          * @param       string  the table name
00531          * @return      string
00532          */     
00533         function _truncate($table)
00534         {
00535                 return "TRUNCATE ".$table;
00536         }
00537         
00538         // --------------------------------------------------------------------
00539 
00540         /**
00541          * Delete statement
00542          *
00543          * Generates a platform-specific delete string from the supplied data
00544          *
00545          * @access      public
00546          * @param       string  the table name
00547          * @param       array   the where clause
00548          * @param       string  the limit clause
00549          * @return      string
00550          */     
00551         function _delete($table, $where = array(), $like = array(), $limit = FALSE)
00552         {
00553                 $conditions = '';
00554 
00555                 if (count($where) > 0 OR count($like) > 0)
00556                 {
00557                         $conditions = "\nWHERE ";
00558                         $conditions .= implode("\n", $this->ar_where);
00559 
00560                         if (count($where) > 0 && count($like) > 0)
00561                         {
00562                                 $conditions .= " AND ";
00563                         }
00564                         $conditions .= implode("\n", $like);
00565                 }
00566 
00567                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
00568         
00569                 return "DELETE FROM ".$table.$conditions.$limit;
00570         }
00571 
00572         // --------------------------------------------------------------------
00573 
00574         /**
00575          * Limit string
00576          *
00577          * Generates a platform-specific LIMIT clause
00578          *
00579          * @access      public
00580          * @param       string  the sql query string
00581          * @param       integer the number of rows to limit the query to
00582          * @param       integer the offset value
00583          * @return      string
00584          */
00585         function _limit($sql, $limit, $offset)
00586         {
00587                 $i = $limit + $offset;
00588         
00589                 return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);               
00590         }
00591 
00592         // --------------------------------------------------------------------
00593 
00594         /**
00595          * Close DB Connection
00596          *
00597          * @access      public
00598          * @param       resource
00599          * @return      void
00600          */
00601         function _close($conn_id)
00602         {
00603                 @mssql_close($conn_id);
00604         }       
00605 
00606 }
00607 
00608 
00609 
00610 /* End of file mssql_driver.php */
00611 /* Location: ./system/database/drivers/mssql/mssql_driver.php */