diff options
Diffstat (limited to 'system/database/drivers/mssql')
-rw-r--r-- | system/database/drivers/mssql/mssql_driver.php | 388 | ||||
-rw-r--r-- | system/database/drivers/mssql/mssql_forge.php | 196 | ||||
-rw-r--r-- | system/database/drivers/mssql/mssql_result.php | 49 | ||||
-rw-r--r-- | system/database/drivers/mssql/mssql_utility.php | 22 |
4 files changed, 325 insertions, 330 deletions
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 90609a84d..d3e439d69 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,12 +24,13 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * 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 @@ -40,36 +41,78 @@ */ class CI_DB_mssql_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'mssql'; - // The character used for escaping - protected $_escape_char = ''; + // -------------------------------------------------------------------- - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + /** + * ORDER BY random keyword + * + * @var array + */ + protected $_random_keyword = array('NEWID()', 'RAND(%d)'); /** - * 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() methods. + * Quoted identifier flag + * + * Whether to use SQL-92 standard quoted identifier + * (double quotes) or brackets for identifier escaping. + * + * @var bool */ - protected $_count_string = 'SELECT COUNT(*) AS '; - protected $_random_keyword = ' NEWID()'; + protected $_quoted_identifier = TRUE; + + // -------------------------------------------------------------------- + + /** + * Class constructor + * + * Appends the port number to the hostname, if needed. + * + * @param array $params + * @return void + */ + public function __construct($params) + { + parent::__construct($params); + + if ( ! empty($this->port)) + { + $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port; + } + } + + // -------------------------------------------------------------------- /** * Non-persistent database connection * + * @param bool $persistent * @return resource */ - public function db_connect() + public function db_connect($persistent = FALSE) { - if ($this->port != '') + $this->conn_id = ($persistent) + ? @mssql_pconnect($this->hostname, $this->username, $this->password) + : @mssql_connect($this->hostname, $this->username, $this->password); + + if ( ! $this->conn_id) { - $this->hostname .= ','.$this->port; + return FALSE; } - return @mssql_connect($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 $this->conn_id; } // -------------------------------------------------------------------- @@ -81,12 +124,7 @@ class CI_DB_mssql_driver extends CI_DB { */ public function db_pconnect() { - if ($this->port != '') - { - $this->hostname .= ','.$this->port; - } - - return @mssql_pconnect($this->hostname, $this->username, $this->password); + return $this->db_connect(TRUE); } // -------------------------------------------------------------------- @@ -94,7 +132,7 @@ class CI_DB_mssql_driver extends CI_DB { /** * Select the database * - * @param string database name + * @param string $database * @return bool */ public function db_select($database = '') @@ -106,7 +144,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; @@ -120,8 +158,8 @@ class CI_DB_mssql_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query - * @return resource + * @param string $sql an SQL query + * @return mixed resource if rows are returned, bool otherwise */ protected function _execute($sql) { @@ -133,17 +171,13 @@ class CI_DB_mssql_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ 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 +185,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 +199,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 +217,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'); } // -------------------------------------------------------------------- @@ -210,8 +231,8 @@ class CI_DB_mssql_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -232,7 +253,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,28 +286,26 @@ 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 = version_compare($this->version(), '8', '>=') + ? 'SELECT SCOPE_IDENTITY() AS last_id' + : 'SELECT @@IDENTITY AS last_id'; + + $query = $this->query($query); + $query = $query->row(); + return $query->last_id; } // -------------------------------------------------------------------- /** - * Parse major version - * - * Grabs the major version number from the - * database server version string passed in. + * Set client character set * - * @param string $version - * @return int major version number + * @param string $charset + * @return bool */ - protected function _parse_major_version($version) + protected function _db_set_charset($charset) { - preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); - return $ver_info[1]; // return the major version b/c that's all we're interested in. + return (@ini_set('mssql.charset', $charset) !== FALSE); } // -------------------------------------------------------------------- @@ -304,54 +323,26 @@ 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 * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) { - $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; + $sql = 'SELECT '.$this->escape_identifiers('name') + .' FROM '.$this->escape_identifiers('sysobjects') + .' WHERE '.$this->escape_identifiers('type')." = 'U'"; - // 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 + $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_like_escape_str, $this->_like_escape_chr); } - return $sql; + return $sql.' ORDER BY '.$this->escape_identifiers('name'); } // -------------------------------------------------------------------- @@ -361,27 +352,52 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') { - return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'"; + return 'SELECT COLUMN_NAME + FROM INFORMATION_SCHEMA.Columns + WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); } // -------------------------------------------------------------------- /** - * Field data query - * - * Generates a platform-specific query so that the column data can be retrieved + * Returns an object with field data * - * @param string the table name - * @return string + * @param string $table + * @return array */ - protected function _field_data($table) + public function field_data($table = '') { - return "SELECT TOP 1 * FROM ".$table; + if ($table === '') + { + return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE; + } + + $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT + FROM INFORMATION_SCHEMA.Columns + WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); + + if (($query = $this->query($sql)) === FALSE) + { + return FALSE; + } + $query = $query->result_object(); + + $retval = array(); + for ($i = 0, $c = count($query); $i < $c; $i++) + { + $retval[$i] = new stdClass(); + $retval[$i]->name = $query[$i]->COLUMN_NAME; + $retval[$i]->type = $query[$i]->DATA_TYPE; + $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION; + $retval[$i]->default = $query[$i]->COLUMN_DEFAULT; + } + + return $retval; } // -------------------------------------------------------------------- @@ -404,54 +420,19 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return implode(', ', $tables); - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -461,10 +442,10 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -479,43 +460,91 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + if ($this->qb_limit) + { + return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; + } - return ($limit) - ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' - : 'DELETE FROM '.$table.$conditions; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) + { + $limit = $this->qb_offset + $this->qb_limit; + + // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, + // however an ORDER BY clause is required for it to work + if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby)) + { + $orderby = $this->_compile_order_by(); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); + + // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results + if (count($this->qb_select) === 0) + { + $select = '*'; // Inevitable + } + else + { + // Use only field names and their aliases, everything else is out of our scope. + $select = array(); + $field_regexp = ($this->_quoted_identifier) + ? '("[^\"]+")' : '(\[[^\]]+\])'; + for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) + { + $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) + ? $m[1] : $this->qb_select[$i]; + } + $select = implode(', ', $select); + } + + return 'SELECT '.$select." FROM (\n\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); + } + + // -------------------------------------------------------------------- + + /** + * Insert batch statement + * + * Generates a platform-specific insert string from the supplied data. + * + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values + * @return string|bool + */ + protected function _insert_batch($table, $keys, $values) { - $i = $limit + $offset; + // Multiple-value inserts are only supported as of SQL Server 2008 + if (version_compare($this->version(), '10', '>=')) + { + return parent::_insert_batch($table, $keys, $values); + } - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; } // -------------------------------------------------------------------- @@ -523,12 +552,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); } } diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php index 8f8e7c5b9..5eebedbf7 100644 --- a/system/database/drivers/mssql/mssql_forge.php +++ b/system/database/drivers/mssql/mssql_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MS SQL Forge Class @@ -34,162 +35,99 @@ */ class CI_DB_mssql_forge extends CI_DB_forge { - protected $_drop_table = 'DROP TABLE %s'; - /** - * Create Table + * CREATE TABLE IF statement * - * @param string the table name - * @param array the fields - * @param mixed primary key(s) - * @param mixed key(s) - * @param bool should 'IF NOT EXISTS' be added to the SQL - * @return string + * @var string */ - protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) - { - $sql = 'CREATE TABLE '; - - if ($if_not_exists === TRUE) - { - $sql .= 'IF NOT EXISTS '; - } - - $sql .= $this->db->escape_identifiers($table).' ('; - $current_field_count = 0; - - foreach ($fields as $field => $attributes) - { - // Numeric field names aren't allowed in databases, so if the key is - // numeric, we know it was assigned by PHP and the developer manually - // entered the field information, so we'll simply add it to the list - if (is_numeric($field)) - { - $sql .= "\n\t$attributes"; - } - else - { - $attributes = array_change_key_case($attributes, CASE_UPPER); - - $sql .= "\n\t".$this->db->protect_identifiers($field); - - $sql .= ' '.$attributes['TYPE']; - - if (array_key_exists('CONSTRAINT', $attributes)) - { - $sql .= '('.$attributes['CONSTRAINT'].')'; - } + protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE"; - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) - { - $sql .= ' UNSIGNED'; - } - - if (array_key_exists('DEFAULT', $attributes)) - { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; - } - - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + /** + * DROP TABLE IF statement + * + * @var string + */ + protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE"; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) - { - $sql .= ' AUTO_INCREMENT'; - } - } + /** + * UNSIGNED support + * + * @var array + */ + protected $_unsigned = array( + 'TINYINT' => 'SMALLINT', + 'SMALLINT' => 'INT', + 'INT' => 'BIGINT', + 'REAL' => 'FLOAT' + ); - // don't add a comma on the end of the last field - if (++$current_field_count < count($fields)) - { - $sql .= ','; - } - } + // -------------------------------------------------------------------- - if (count($primary_keys) > 0) + /** + * ALTER TABLE + * + * @param string $alter_type ALTER type + * @param string $table Table name + * @param mixed $field Column definition + * @return string|string[] + */ + protected function _alter_table($alter_type, $table, $field) + { + if (in_array($alter_type, array('ADD', 'DROP'), TRUE)) { - $primary_keys = $this->db->protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + return parent::_alter_table($alter_type, $table, $field); } - if (is_array($keys) && count($keys) > 0) + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN '; + $sqls = array(); + for ($i = 0, $c = count($field); $i < $c; $i++) { - foreach ($keys as $key) - { - if (is_array($key)) - { - $key = $this->db->protect_identifiers($key); - } - else - { - $key = array($this->db->protect_identifiers($key)); - } - - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; - } + $sqls[] = $sql.$this->_process_column($field[$i]); } - $sql .= "\n)"; - - return $sql; + return $sqls; } // -------------------------------------------------------------------- /** - * Alter table query + * Field attribute TYPE * - * Generates a platform-specific query so that a table can be altered - * Called by add_column(), drop_column(), and column_alter(), + * Performs a data type mapping between different databases. * - * @param string the ALTER type (ADD, DROP, CHANGE) - * @param string the column name - * @param string the table name - * @param string the column definition - * @param string the default value - * @param bool should 'NOT NULL' be added - * @param string the field after which we should add the new field - * @return string + * @param array &$attributes + * @return void */ - protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _attr_type(&$attributes) { - $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name); - - // DROP has everything it needs now. - if ($alter_type == 'DROP') + switch (strtoupper($attributes['TYPE'])) { - return $sql; - } - - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; + case 'MEDIUMINT': + $attributes['TYPE'] = 'INTEGER'; + $attributes['UNSIGNED'] = FALSE; + return; + case 'INTEGER': + $attributes['TYPE'] = 'INT'; + return; + default: return; } + } - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + // -------------------------------------------------------------------- - if ($after_field != '') + /** + * Field attribute AUTO_INCREMENT + * + * @param array &$attributes + * @param array &$field + * @return void + */ + protected function _attr_auto_increment(&$attributes, &$field) + { + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) { - return $sql.' AFTER '.$this->db->protect_identifiers($after_field); + $field['auto_increment'] = ' IDENTITY(1,1)'; } - - return $sql; - } } diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php index 4cc87f4cf..ca222aed4 100644 --- a/system/database/drivers/mssql/mssql_result.php +++ b/system/database/drivers/mssql/mssql_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,15 +24,17 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** - * MS SQL Result Class + * MSSQL Result Class * * This class extends the parent result class: CI_DB_result * * @category Database * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ + * @since 1.3 */ class CI_DB_mssql_result extends CI_DB_result { @@ -43,7 +45,9 @@ class CI_DB_mssql_result extends CI_DB_result { */ public function num_rows() { - return @mssql_num_rows($this->result_id); + return is_int($this->num_rows) + ? $this->num_rows + : $this->num_rows = @mssql_num_rows($this->result_id); } // -------------------------------------------------------------------- @@ -90,16 +94,14 @@ class CI_DB_mssql_result extends CI_DB_result { public function field_data() { $retval = array(); - while ($field = mssql_fetch_field($this->result_id)) + for ($i = 0, $c = $this->num_field(); $i < $c; $i++) { - $F = new stdClass(); - $F->name = $field->name; - $F->type = $field->type; - $F->max_length = $field->max_length; - $F->primary_key = 0; - $F->default = ''; - - $retval[] = $F; + $field = mssql_fetch_field($this->result_id, $i); + + $retval[$i] = new stdClass(); + $retval[$i]->name = $field->name; + $retval[$i]->type = $field->type; + $retval[$i]->max_length = $field->max_length; } return $retval; @@ -128,11 +130,12 @@ class CI_DB_mssql_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ - protected function _data_seek($n = 0) + public function data_seek($n = 0) { return mssql_data_seek($this->result_id, $n); } @@ -158,11 +161,25 @@ class CI_DB_mssql_result extends CI_DB_result { * * Returns the result set as an object * + * @param string $class_name * @return object */ - protected function _fetch_object() + protected function _fetch_object($class_name = 'stdClass') { - return mssql_fetch_object($this->result_id); + $row = @mssql_fetch_object($this->result_id); + + if ($class_name === 'stdClass' OR ! $row) + { + return $row; + } + + $class_name = new $class_name(); + foreach ($row as $key => $value) + { + $class_name->$key = $value; + } + + return $class_name; } } diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php index 6d47618ce..76c7cb9c2 100644 --- a/system/database/drivers/mssql/mssql_utility.php +++ b/system/database/drivers/mssql/mssql_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MS SQL Utility Class @@ -34,19 +35,30 @@ */ class CI_DB_mssql_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE'; /** - * MSSQL Export + * Export * - * @param array Preferences - * @return mixed + * @param array $params Preferences + * @return bool */ protected function _backup($params = array()) { // Currently unsupported - return $this->db->display_error('db_unsuported_feature'); + return $this->db->display_error('db_unsupported_feature'); } } |