diff options
Diffstat (limited to 'system/database/drivers/sqlsrv')
-rw-r--r-- | system/database/drivers/sqlsrv/sqlsrv_driver.php | 198 | ||||
-rw-r--r-- | system/database/drivers/sqlsrv/sqlsrv_forge.php | 149 | ||||
-rw-r--r-- | system/database/drivers/sqlsrv/sqlsrv_result.php | 24 | ||||
-rw-r--r-- | system/database/drivers/sqlsrv/sqlsrv_utility.php | 49 |
4 files changed, 103 insertions, 317 deletions
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index 9f2f88699..655a9e90b 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -29,7 +29,7 @@ * SQLSRV 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_sqlsrv_driver extends CI_DB { public $dbdriver = 'sqlsrv'; // 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' "; @@ -55,7 +55,10 @@ class CI_DB_sqlsrv_driver extends CI_DB { * used for the count_all() and count_all_results() functions. */ protected $_count_string = 'SELECT COUNT(*) AS '; - protected $_random_keyword = ' ASC'; // not currently supported + protected $_random_keyword = ' NEWID()'; + + // SQLSRV-specific properties + protected $_quoted_identifier = TRUE; /** * Non-persistent database connection @@ -68,12 +71,12 @@ class CI_DB_sqlsrv_driver extends CI_DB { $character_set = (0 === strcasecmp('utf8', $this->char_set)) ? 'UTF-8' : $this->char_set; $connection = array( - 'UID' => empty($this->username) ? '' : $this->username, - 'PWD' => empty($this->password) ? '' : $this->password, - 'Database' => $this->database, - 'ConnectionPooling' => $pooling ? 1 : 0, + 'UID' => empty($this->username) ? '' : $this->username, + 'PWD' => empty($this->password) ? '' : $this->password, + 'Database' => $this->database, + 'ConnectionPooling' => $pooling ? 1 : 0, 'CharacterSet' => $character_set, - 'ReturnDatesAsStrings' => 1 + 'ReturnDatesAsStrings' => 1 ); // If the username and password are both empty, assume this is a @@ -83,7 +86,15 @@ class CI_DB_sqlsrv_driver extends CI_DB { unset($connection['UID'], $connection['PWD']); } - return sqlsrv_connect($this->hostname, $connection); + $conn_id = sqlsrv_connect($this->hostname, $connection); + + // 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; } // -------------------------------------------------------------------- @@ -132,11 +143,9 @@ class CI_DB_sqlsrv_driver extends CI_DB { */ protected function _execute($sql) { - return sqlsrv_query($this->conn_id, - $sql, - NULL, - array('Scrollable'=> SQLSRV_CURSOR_STATIC, 'SendStreamParamsAtExec' => TRUE) - ); + return (is_write_type($sql) && stripos($sql, 'INSERT') === FALSE) + ? sqlsrv_query($this->conn_id, $sql) + : sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => SQLSRV_CURSOR_STATIC)); } // -------------------------------------------------------------------- @@ -148,13 +157,8 @@ class CI_DB_sqlsrv_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; } @@ -162,7 +166,7 @@ class CI_DB_sqlsrv_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); return sqlsrv_begin_transaction($this->conn_id); } @@ -176,13 +180,8 @@ class CI_DB_sqlsrv_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; } @@ -199,13 +198,8 @@ class CI_DB_sqlsrv_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; } @@ -237,7 +231,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { */ public function affected_rows() { - return @sqlrv_rows_affected($this->conn_id); + return sqlrv_rows_affected($this->result_id); } // -------------------------------------------------------------------- @@ -259,23 +253,6 @@ class CI_DB_sqlsrv_driver extends CI_DB { // -------------------------------------------------------------------- /** - * 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. - } - - // -------------------------------------------------------------------- - - /** * Database version number * * @return string @@ -298,35 +275,6 @@ class CI_DB_sqlsrv_driver extends CI_DB { // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @param string - * @return int - */ - public function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query("SELECT COUNT(*) AS numrows FROM " . $this->dbprefix . $table); - 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 @@ -410,21 +358,6 @@ class CI_DB_sqlsrv_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @param string - * @return string - */ - public function _escape_identifiers($item) - { - return $item; - } - - // -------------------------------------------------------------------- - - /** * From Tables * * This function implicitly groups FROM tables so there is no confusion @@ -435,29 +368,7 @@ class CI_DB_sqlsrv_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; } // -------------------------------------------------------------------- @@ -470,18 +381,26 @@ class CI_DB_sqlsrv_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) + 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; + } + + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); + + if ( ! empty($like)) { - $valstr[] = $key." = ".$val; + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); } - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.implode(' ', $where); + return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; } // -------------------------------------------------------------------- @@ -490,15 +409,16 @@ class CI_DB_sqlsrv_driver extends CI_DB { * 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; } // -------------------------------------------------------------------- @@ -510,12 +430,22 @@ class CI_DB_sqlsrv_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) + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) { - return 'DELETE FROM '.$table.' WHERE '.implode(' ', $where); + $conditions = array(); + + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); + + $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + + return ($limit) + ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' + : 'DELETE FROM '.$table.$conditions; } // -------------------------------------------------------------------- @@ -532,7 +462,10 @@ class CI_DB_sqlsrv_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); + // As of SQL Server 2012 (11.0.*) OFFSET is supported + return version_compare($this->version(), '11', '>=') + ? $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY' + : preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); } // -------------------------------------------------------------------- @@ -540,12 +473,11 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Close DB Connection * - * @param resource * @return void */ - protected function _close($conn_id) + protected function _close() { - @sqlsrv_close($conn_id); + @sqlsrv_close($this->conn_id); } } diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php index 0dc7b5242..e6f7e1ac1 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_forge.php +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -34,43 +34,7 @@ */ class CI_DB_sqlsrv_forge extends CI_DB_forge { - /** - * Create database - * - * @param string the database name - * @return string - */ - public function _create_database($name) - { - return "CREATE DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string the database name - * @return bool - */ - public function _drop_database($name) - { - return "DROP DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @return bool - */ - public function _drop_table($table) - { - return "DROP TABLE ".$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- + protected $_drop_table = 'DROP TABLE %s'; /** * Create Table @@ -80,20 +44,17 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge { * @param mixed primary key(s) * @param mixed key(s) * @param bool should 'IF NOT EXISTS' be added to the SQL - * @return bool + * @return string */ - public function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + 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 @@ -101,41 +62,33 @@ class CI_DB_sqlsrv_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 .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - $sql .= ' '.$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']) && $attribues['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'; } @@ -150,30 +103,22 @@ class CI_DB_sqlsrv_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->escape_identifiers($key)); - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -193,56 +138,20 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge { * @param string the field after which we should add the new field * @return string */ - public function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + 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; - - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @param string the old table name - * @param string the new table name - * @return string - */ - public function _rename_table($table_name, $new_table_name) - { - // I think this syntax will work, but can find little documentation on renaming tables in MSSQL - return 'ALTER TABLE '.$this->db->protect_identifiers($table_name).' RENAME TO '.$this->db->protect_identifiers($new_table_name); + 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/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php index 10d790e4b..f802383d2 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_result.php +++ b/system/database/drivers/sqlsrv/sqlsrv_result.php @@ -92,12 +92,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result { $retval = array(); foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field) { - $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['Size']; $F->primary_key = 0; - $F->default = ''; + $F->default = ''; $retval[] = $F; } @@ -124,22 +124,6 @@ class CI_DB_sqlsrv_result extends CI_DB_result { // -------------------------------------------------------------------- /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero - * - * @return void - */ - protected function _data_seek($n = 0) - { - // Not implemented - } - - // -------------------------------------------------------------------- - - /** * Result - associative array * * Returns the result set as an array diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php index 5830c62de..5a71b1628 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_utility.php +++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php @@ -34,55 +34,16 @@ */ class CI_DB_sqlsrv_utility extends CI_DB_utility { - /** - * List databases - * - * @return string - */ - public function _list_databases() - { - return "EXEC sp_helpdb"; // Can also be: EXEC sp_databases - } - - // -------------------------------------------------------------------- + protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases + protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE'; /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @param string the table name - * @return bool - */ - public function _optimize_table($table) - { - return FALSE; // Is this supported in MS SQL? - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @param string the table name - * @return bool - */ - public function _repair_table($table) - { - return FALSE; // Is this supported in MS SQL? - } - - // -------------------------------------------------------------------- - - /** - * MSSQL Export + * SQLSRV Export * * @param array Preferences - * @return mixed + * @return bool */ - public function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); |