diff options
Diffstat (limited to 'system/database/drivers/mssql')
-rw-r--r-- | system/database/drivers/mssql/mssql_driver.php | 207 | ||||
-rw-r--r-- | system/database/drivers/mssql/mssql_forge.php | 88 | ||||
-rw-r--r-- | system/database/drivers/mssql/mssql_result.php | 33 | ||||
-rw-r--r-- | system/database/drivers/mssql/mssql_utility.php | 2 |
4 files changed, 141 insertions, 189 deletions
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index f60ec8168..b4a1af7ba 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -43,33 +43,57 @@ 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' "; - protected $_like_escape_chr = '!'; + protected $_random_keyword = ' NEWID()'; - /** - * 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. + // MSSQL-specific properties + protected $_quoted_identifier = TRUE; + + /* + * Constructor + * + * Appends the port number to the hostname, if needed. + * + * @param array + * @return void */ - protected $_count_string = 'SELECT COUNT(*) AS '; - protected $_random_keyword = ' NEWID()'; + public function __construct($params) + { + parent::__construct($params); + + if ( ! empty($this->port)) + { + $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port; + } + } + + // -------------------------------------------------------------------- /** * Non-persistent database connection * + * @param bool * @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 +105,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); } // -------------------------------------------------------------------- @@ -106,7 +125,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 +140,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 +156,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 +165,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 +179,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 +197,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 +233,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 +266,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 = version_compare($this->version(), '8', '>=') + ? 'SELECT SCOPE_IDENTITY() AS last_id' + : 'SELECT @@IDENTITY AS last_id'; - // -------------------------------------------------------------------- - - /** - * Parse major version - * - * Grabs the major version number from the - * database server version string passed in. - * - * @param string $version - * @return int major version number - */ - protected function _parse_major_version($version) - { - 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. + $query = $this->query($query); + $query = $query->row(); + return $query->last_id; } // -------------------------------------------------------------------- @@ -304,35 +290,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 @@ -342,16 +299,17 @@ class CI_DB_mssql_driver extends CI_DB { */ 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'); } // -------------------------------------------------------------------- @@ -381,7 +339,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 '.$this->protect_identifiers($table); } // -------------------------------------------------------------------- @@ -414,12 +372,7 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _from_tables($tables) { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return implode(', ', $tables); + return is_array($tables) ? implode(', ', $tables) : $tables; } // -------------------------------------------------------------------- @@ -513,9 +466,30 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - $i = $limit + $offset; + // As of SQL Server 2012 (11.0.*) OFFSET is supported + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $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', '>=') && $offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- @@ -523,15 +497,14 @@ 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); } } /* End of file mssql_driver.php */ -/* Location: ./system/database/drivers/mssql/mssql_driver.php */ +/* Location: ./system/database/drivers/mssql/mssql_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php index 8f8e7c5b9..3a3528f7b 100644 --- a/system/database/drivers/mssql/mssql_forge.php +++ b/system/database/drivers/mssql/mssql_forge.php @@ -48,16 +48,13 @@ class CI_DB_mssql_forge extends CI_DB_forge { */ protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { - $sql = 'CREATE TABLE '; + $sql = ($if_not_exists === TRUE) + ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n" + : ''; - if ($if_not_exists === TRUE) - { - $sql .= 'IF NOT EXISTS '; - } + $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' ('; - $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 @@ -65,41 +62,33 @@ class CI_DB_mssql_forge extends CI_DB_forge { // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->protect_identifiers($field); - - $sql .= ' '.$attributes['TYPE']; + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - if (array_key_exists('CONSTRAINT', $attributes)) + if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT'])) { $sql .= '('.$attributes['CONSTRAINT'].')'; } - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } @@ -114,30 +103,22 @@ class CI_DB_mssql_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->protect_identifiers($key); - } - else - { - $key = array($this->db->protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -159,37 +140,18 @@ class CI_DB_mssql_forge extends CI_DB_forge { */ protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name); + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name); // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { return $sql; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } - - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - return $sql.' AFTER '.$this->db->protect_identifiers($after_field); - } - - return $sql; - + return $sql.' '.$column_definition + .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } } diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php index 4cc87f4cf..aeede3f4b 100644 --- a/system/database/drivers/mssql/mssql_result.php +++ b/system/database/drivers/mssql/mssql_result.php @@ -26,13 +26,14 @@ */ /** - * 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 +44,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); } // -------------------------------------------------------------------- @@ -92,12 +95,12 @@ class CI_DB_mssql_result extends CI_DB_result { $retval = array(); while ($field = mssql_fetch_field($this->result_id)) { - $F = new stdClass(); - $F->name = $field->name; - $F->type = $field->type; + $F = new stdClass(); + $F->name = $field->name; + $F->type = $field->type; $F->max_length = $field->max_length; $F->primary_key = 0; - $F->default = ''; + $F->default = ''; $retval[] = $F; } @@ -158,11 +161,25 @@ class CI_DB_mssql_result extends CI_DB_result { * * Returns the result set as an object * + * @param string * @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..69fcec5f6 100644 --- a/system/database/drivers/mssql/mssql_utility.php +++ b/system/database/drivers/mssql/mssql_utility.php @@ -41,7 +41,7 @@ class CI_DB_mssql_utility extends CI_DB_utility { * MSSQL Export * * @param array Preferences - * @return mixed + * @return bool */ protected function _backup($params = array()) { |