diff options
Diffstat (limited to 'system/database/drivers/mssql/mssql_driver.php')
-rw-r--r-- | system/database/drivers/mssql/mssql_driver.php | 280 |
1 files changed, 101 insertions, 179 deletions
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 912808631..87094e76e 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -29,7 +29,7 @@ * MS SQL Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -43,7 +43,7 @@ class CI_DB_mssql_driver extends CI_DB { public $dbdriver = 'mssql'; // The character used for escaping - protected $_escape_char = ''; + protected $_escape_char = '"'; // clause and character used for LIKE escape sequences protected $_like_escape_str = " ESCAPE '%s' "; @@ -52,10 +52,33 @@ class CI_DB_mssql_driver extends CI_DB { /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * used for the count_all() and count_all_results() methods. */ protected $_count_string = 'SELECT COUNT(*) AS '; - protected $_random_keyword = ' ASC'; // not currently supported + protected $_random_keyword = ' NEWID()'; + + // MSSQL-specific properties + protected $_quoted_identifier = TRUE; + + /* + * Constructor + * + * Appends the port number to the hostname, if needed. + * + * @param array + * @return void + */ + public function __construct($params) + { + parent::__construct($params); + + if ( ! empty($this->port)) + { + $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port; + } + } + + // -------------------------------------------------------------------- /** * Non-persistent database connection @@ -64,12 +87,7 @@ class CI_DB_mssql_driver extends CI_DB { */ public function db_connect() { - if ($this->port != '') - { - $this->hostname .= ','.$this->port; - } - - return @mssql_connect($this->hostname, $this->username, $this->password); + return $this->_mssql_connect(); } // -------------------------------------------------------------------- @@ -81,12 +99,35 @@ class CI_DB_mssql_driver extends CI_DB { */ public function db_pconnect() { - if ($this->port != '') + return $this->_mssql_connect(TRUE); + } + + // -------------------------------------------------------------------- + + /* + * MSSQL Connect + * + * @param bool + * @return resource + */ + protected function _mssql_connect($persistent = FALSE) + { + $conn_id = ($persistent) + ? @mssql_pconnect($this->hostname, $this->username, $this->password) + : @mssql_connect($this->hostname, $this->username, $this->password); + + if ( ! $conn_id) { - $this->hostname .= ','.$this->port; + return FALSE; } - return @mssql_pconnect($this->hostname, $this->username, $this->password); + // Determine how identifiers are escaped + $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); + $query = $query->row_array(); + $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query->qi; + $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); + + return $conn_id; } // -------------------------------------------------------------------- @@ -106,7 +147,7 @@ class CI_DB_mssql_driver extends CI_DB { // Note: The brackets are required in the event that the DB name // contains reserved characters - if (@mssql_select_db('['.$database.']', $this->conn_id)) + if (@mssql_select_db($this->escape_identifiers($database), $this->conn_id)) { $this->database = $database; return TRUE; @@ -121,7 +162,7 @@ class CI_DB_mssql_driver extends CI_DB { * Execute the query * * @param string an SQL query - * @return resource + * @return mixed resource if rows are returned, bool otherwise */ protected function _execute($sql) { @@ -137,13 +178,8 @@ class CI_DB_mssql_driver extends CI_DB { */ public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -151,10 +187,9 @@ class CI_DB_mssql_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); - $this->simple_query('BEGIN TRAN'); - return TRUE; + return $this->simple_query('BEGIN TRAN'); } // -------------------------------------------------------------------- @@ -166,19 +201,13 @@ class CI_DB_mssql_driver extends CI_DB { */ public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $this->simple_query('COMMIT TRAN'); - return TRUE; + return $this->simple_query('COMMIT TRAN'); } // -------------------------------------------------------------------- @@ -190,19 +219,13 @@ class CI_DB_mssql_driver extends CI_DB { */ public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $this->simple_query('ROLLBACK TRAN'); - return TRUE; + return $this->simple_query('ROLLBACK TRAN'); } // -------------------------------------------------------------------- @@ -232,7 +255,7 @@ class CI_DB_mssql_driver extends CI_DB { // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( + return str_replace( array($this->_like_escape_chr, '%', '_'), array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), $str @@ -265,11 +288,13 @@ class CI_DB_mssql_driver extends CI_DB { */ public function insert_id() { - $ver = self::_parse_major_version($this->version()); - $sql = ($ver >= 8 ? "SELECT SCOPE_IDENTITY() AS last_id" : "SELECT @@IDENTITY AS last_id"); - $query = $this->query($sql); - $row = $query->row(); - return $row->last_id; + $query = (self::_parse_major_version($this->version()) > 7) + ? 'SELECT SCOPE_IDENTITY() AS last_id' + : 'SELECT @@IDENTITY AS last_id'; + + $query = $this->query($query); + $query = $query->row(); + return $query->last_id; } // -------------------------------------------------------------------- @@ -304,35 +329,6 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @param string - * @return string - */ - public function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE)); - if ($query->num_rows() == 0) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; - } - - // -------------------------------------------------------------------- - - /** * List table query * * Generates a platform-specific query string so that the table names can be fetched @@ -345,7 +341,7 @@ class CI_DB_mssql_driver extends CI_DB { $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; // for future compatibility - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE AND $this->dbprefix !== '') { //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); return FALSE; // not currently supported @@ -381,7 +377,7 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _field_data($table) { - return "SELECT TOP 1 * FROM ".$table; + return 'SELECT TOP 1 * FROM '.$table; } // -------------------------------------------------------------------- @@ -404,47 +400,6 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @param string - * @return string - */ - public function _escape_identifiers($item) - { - if ($this->_escape_char == '') - { - return $item; - } - - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - } - - if (strpos($item, '.') !== FALSE) - { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - } - else - { - $str = $this->_escape_char.$item.$this->_escape_char; - } - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - - // -------------------------------------------------------------------- - - /** * From Tables * * This function implicitly groups FROM tables so there is no confusion @@ -455,29 +410,7 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _from_tables($tables) { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return implode(', ', $tables); - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + return is_array($tables) ? implode(', ', $tables) : $tables; } // -------------------------------------------------------------------- @@ -490,46 +423,44 @@ class CI_DB_mssql_driver extends CI_DB { * @param string the table name * @param array the update data * @param array the where clause - * @param array the orderby clause - * @param array the limit clause + * @param array the orderby clause (ignored) + * @param array the limit clause (ignored) + * @param array the like clause * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) { - foreach ($values as $key => $val) + foreach($values as $key => $val) { - $valstr[] = $key." = ".$val; + $valstr[] = $key.' = '.$val; } - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); - - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; + if ( ! empty($like)) + { + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); + } - return $sql; + return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where; } - // -------------------------------------------------------------------- /** * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" + * + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' * * @param string the table name * @return string */ protected function _truncate($table) { - return "TRUNCATE ".$table; + return 'TRUNCATE TABLE '.$table; } // -------------------------------------------------------------------- @@ -541,28 +472,22 @@ class CI_DB_mssql_driver extends CI_DB { * * @param string the table name * @param array the where clause + * @param array the like clause * @param string the limit clause * @return string */ protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) { - $conditions = ''; + $conditions = array(); - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; - return "DELETE FROM ".$table.$conditions.$limit; + return ($limit) + ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' + : 'DELETE FROM '.$table.$conditions; } // -------------------------------------------------------------------- @@ -579,9 +504,7 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - $i = $limit + $offset; - - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); } // -------------------------------------------------------------------- @@ -589,12 +512,11 @@ class CI_DB_mssql_driver extends CI_DB { /** * Close DB Connection * - * @param resource * @return void */ - protected function _close($conn_id) + protected function _close() { - @mssql_close($conn_id); + @mssql_close($this->conn_id); } } |