blob: be321ff112d9f66ec4f507681f137afc3e229b41 [file] [log] [blame]
Andrey Andreev0e8968a2012-01-26 02:04:37 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Alex Bilbie84445d02011-03-10 16:43:39 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Alex Bilbie84445d02011-03-10 16:43:39 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreev0e8968a2012-01-26 02:04:37 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreev0e8968a2012-01-26 02:04:37 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Alex Bilbie84445d02011-03-10 16:43:39 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Alex Bilbie84445d02011-03-10 16:43:39 +000023 * @link http://codeigniter.com
Andrey Andreevbf940582012-06-10 07:05:05 +030024 * @since Version 2.0.3
Alex Bilbie84445d02011-03-10 16:43:39 +000025 * @filesource
26 */
27
Alex Bilbie84445d02011-03-10 16:43:39 +000028/**
Alex Bilbie01ab0042011-03-18 19:24:30 +000029 * SQLSRV Database Adapter Class
Alex Bilbie84445d02011-03-10 16:43:39 +000030 *
31 * Note: _DB is an extender class that the app controller
Jamie Rumbelow7efad202012-02-19 12:37:00 +000032 * creates dynamically based on whether the query builder
Alex Bilbie84445d02011-03-10 16:43:39 +000033 * class is being used or not.
34 *
35 * @package CodeIgniter
36 * @subpackage Drivers
37 * @category Database
Derek Jonesf4a4bd82011-10-20 12:18:42 -050038 * @author EllisLab Dev Team
Alex Bilbie84445d02011-03-10 16:43:39 +000039 * @link http://codeigniter.com/user_guide/database/
40 */
Alex Bilbie01ab0042011-03-18 19:24:30 +000041class CI_DB_sqlsrv_driver extends CI_DB {
Alex Bilbie84445d02011-03-10 16:43:39 +000042
Andrey Andreev0e8968a2012-01-26 02:04:37 +020043 public $dbdriver = 'sqlsrv';
Alex Bilbie84445d02011-03-10 16:43:39 +000044
45 // The character used for escaping
Andrey Andreev082ee2b2012-06-08 15:26:34 +030046 protected $_escape_char = '"';
Alex Bilbie84445d02011-03-10 16:43:39 +000047
Andrey Andreev0e8968a2012-01-26 02:04:37 +020048 protected $_random_keyword = ' NEWID()';
Alex Bilbie84445d02011-03-10 16:43:39 +000049
Andrey Andreev082ee2b2012-06-08 15:26:34 +030050 // SQLSRV-specific properties
51 protected $_quoted_identifier = TRUE;
52
Alex Bilbie84445d02011-03-10 16:43:39 +000053 /**
54 * Non-persistent database connection
55 *
Alex Bilbie84445d02011-03-10 16:43:39 +000056 * @return resource
57 */
Andrey Andreeve6297342012-03-20 16:25:07 +020058 public function db_connect($pooling = FALSE)
Alex Bilbie84445d02011-03-10 16:43:39 +000059 {
Andrey Andreev2f8bf9b2012-10-12 20:37:52 +030060 $charset = in_array(strtolower($this->char_set), array('utf-8', 'utf8'), TRUE)
61 ? 'UTF-8' : SQLSRV_ENC_CHAR;
Alex Bilbie3a43c7a2011-03-18 19:48:04 +000062
63 $connection = array(
Andrey Andreev0e8968a2012-01-26 02:04:37 +020064 'UID' => empty($this->username) ? '' : $this->username,
65 'PWD' => empty($this->password) ? '' : $this->password,
66 'Database' => $this->database,
Andrey Andreev2f8bf9b2012-10-12 20:37:52 +030067 'ConnectionPooling' => ($pooling === TRUE) ? 1 : 0,
68 'CharacterSet' => $charset,
69 'Encrypt' => ($this->encrypt === TRUE) ? 1 : 0,
Andrey Andreev0e8968a2012-01-26 02:04:37 +020070 'ReturnDatesAsStrings' => 1
Alex Bilbie3a43c7a2011-03-18 19:48:04 +000071 );
Andrey Andreev0e8968a2012-01-26 02:04:37 +020072
73 // If the username and password are both empty, assume this is a
Alex Bilbie3a43c7a2011-03-18 19:48:04 +000074 // 'Windows Authentication Mode' connection.
Andrey Andreev0e8968a2012-01-26 02:04:37 +020075 if (empty($connection['UID']) && empty($connection['PWD']))
76 {
Alex Bilbie3a43c7a2011-03-18 19:48:04 +000077 unset($connection['UID'], $connection['PWD']);
Alex Bilbie84445d02011-03-10 16:43:39 +000078 }
79
Andrey Andreevfac37612012-07-02 14:56:20 +030080 $this->conn_id = sqlsrv_connect($this->hostname, $connection);
Andrey Andreev082ee2b2012-06-08 15:26:34 +030081
82 // Determine how identifiers are escaped
83 $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
84 $query = $query->row_array();
Andrey Andreev70c72c92012-06-25 00:04:51 +030085 $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
Andrey Andreev082ee2b2012-06-08 15:26:34 +030086 $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
87
Andrey Andreevfac37612012-07-02 14:56:20 +030088 return $this->conn_id;
Alex Bilbie84445d02011-03-10 16:43:39 +000089 }
90
91 // --------------------------------------------------------------------
92
93 /**
94 * Persistent database connection
95 *
Alex Bilbie84445d02011-03-10 16:43:39 +000096 * @return resource
97 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +020098 public function db_pconnect()
Alex Bilbie84445d02011-03-10 16:43:39 +000099 {
Kyle Farris37e351f2011-09-07 11:14:46 -0300100 return $this->db_connect(TRUE);
Alex Bilbie84445d02011-03-10 16:43:39 +0000101 }
102
103 // --------------------------------------------------------------------
104
105 /**
Alex Bilbie84445d02011-03-10 16:43:39 +0000106 * Select the database
107 *
Andrey Andreev11454e02012-02-22 16:05:47 +0200108 * @param string database name
109 * @return bool
Alex Bilbie84445d02011-03-10 16:43:39 +0000110 */
Andrey Andreev11454e02012-02-22 16:05:47 +0200111 public function db_select($database = '')
Alex Bilbie84445d02011-03-10 16:43:39 +0000112 {
Andrey Andreev024ba2d2012-02-24 11:40:36 +0200113 if ($database === '')
114 {
115 $database = $this->database;
116 }
117
118 if ($this->_execute('USE '.$database))
119 {
120 $this->database = $database;
121 return TRUE;
122 }
123
124 return FALSE;
Alex Bilbie84445d02011-03-10 16:43:39 +0000125 }
126
127 // --------------------------------------------------------------------
128
129 /**
Alex Bilbie84445d02011-03-10 16:43:39 +0000130 * Execute the query
131 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000132 * @param string an SQL query
133 * @return resource
134 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200135 protected function _execute($sql)
Alex Bilbie84445d02011-03-10 16:43:39 +0000136 {
Andrey Andreevb2f60332012-07-03 14:45:00 +0300137 return ($this->is_write_type($sql) && stripos($sql, 'INSERT') === FALSE)
Andrey Andreev846acc72012-05-24 23:27:46 +0300138 ? sqlsrv_query($this->conn_id, $sql)
139 : sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => SQLSRV_CURSOR_STATIC));
Alex Bilbie84445d02011-03-10 16:43:39 +0000140 }
141
142 // --------------------------------------------------------------------
143
144 /**
145 * Begin Transaction
146 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000147 * @return bool
148 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200149 public function trans_begin($test_mode = FALSE)
Alex Bilbie84445d02011-03-10 16:43:39 +0000150 {
Alex Bilbie84445d02011-03-10 16:43:39 +0000151 // When transactions are nested we only begin/commit/rollback the outermost ones
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200152 if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
Alex Bilbie84445d02011-03-10 16:43:39 +0000153 {
154 return TRUE;
155 }
156
157 // Reset the transaction failure flag.
158 // If the $test_mode flag is set to TRUE transactions will be rolled back
159 // even if the queries produce a successful result.
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200160 $this->_trans_failure = ($test_mode === TRUE);
Alex Bilbie84445d02011-03-10 16:43:39 +0000161
Alex Bilbie3a43c7a2011-03-18 19:48:04 +0000162 return sqlsrv_begin_transaction($this->conn_id);
Alex Bilbie84445d02011-03-10 16:43:39 +0000163 }
164
165 // --------------------------------------------------------------------
166
167 /**
168 * Commit Transaction
169 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000170 * @return bool
171 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200172 public function trans_commit()
Alex Bilbie84445d02011-03-10 16:43:39 +0000173 {
Alex Bilbie84445d02011-03-10 16:43:39 +0000174 // When transactions are nested we only begin/commit/rollback the outermost ones
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200175 if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
Alex Bilbie84445d02011-03-10 16:43:39 +0000176 {
177 return TRUE;
178 }
179
Alex Bilbie3a43c7a2011-03-18 19:48:04 +0000180 return sqlsrv_commit($this->conn_id);
Alex Bilbie84445d02011-03-10 16:43:39 +0000181 }
182
183 // --------------------------------------------------------------------
184
185 /**
186 * Rollback Transaction
187 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000188 * @return bool
189 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200190 public function trans_rollback()
Alex Bilbie84445d02011-03-10 16:43:39 +0000191 {
Alex Bilbie84445d02011-03-10 16:43:39 +0000192 // When transactions are nested we only begin/commit/rollback the outermost ones
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200193 if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
Alex Bilbie84445d02011-03-10 16:43:39 +0000194 {
195 return TRUE;
196 }
197
Alex Bilbie3a43c7a2011-03-18 19:48:04 +0000198 return sqlsrv_rollback($this->conn_id);
Alex Bilbie84445d02011-03-10 16:43:39 +0000199 }
200
201 // --------------------------------------------------------------------
202
203 /**
204 * Escape String
205 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000206 * @param string
207 * @param bool whether or not the string will be used in a LIKE condition
208 * @return string
209 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200210 public function escape_str($str, $like = FALSE)
Alex Bilbie84445d02011-03-10 16:43:39 +0000211 {
Alex Bilbie84445d02011-03-10 16:43:39 +0000212 // Escape single quotes
Alex Bilbie3a43c7a2011-03-18 19:48:04 +0000213 return str_replace("'", "''", $str);
Alex Bilbie84445d02011-03-10 16:43:39 +0000214 }
215
216 // --------------------------------------------------------------------
217
218 /**
219 * Affected Rows
220 *
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200221 * @return int
Alex Bilbie84445d02011-03-10 16:43:39 +0000222 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200223 public function affected_rows()
Alex Bilbie84445d02011-03-10 16:43:39 +0000224 {
Andrey Andreevede49ba2012-07-23 16:06:36 +0300225 return sqlsrv_rows_affected($this->result_id);
Alex Bilbie84445d02011-03-10 16:43:39 +0000226 }
227
228 // --------------------------------------------------------------------
229
230 /**
Andrey Andreeve6297342012-03-20 16:25:07 +0200231 * Insert ID
232 *
233 * Returns the last id created in the Identity column.
234 *
235 * @return string
236 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200237 public function insert_id()
Alex Bilbie84445d02011-03-10 16:43:39 +0000238 {
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200239 $query = $this->query('SELECT @@IDENTITY AS insert_id');
240 $query = $query->row();
241 return $query->insert_id;
Alex Bilbie84445d02011-03-10 16:43:39 +0000242 }
243
244 // --------------------------------------------------------------------
245
246 /**
Andrey Andreev08856b82012-03-03 03:19:28 +0200247 * Database version number
248 *
249 * @return string
250 */
251 public function version()
Alex Bilbie84445d02011-03-10 16:43:39 +0000252 {
Andrey Andreev08856b82012-03-03 03:19:28 +0200253 if (isset($this->data_cache['version']))
254 {
255 return $this->data_cache['version'];
256 }
257
258 if (($info = sqlsrv_server_info($this->conn_id)) === FALSE)
259 {
260 return FALSE;
261 }
262
263 return $this->data_cache['version'] = $info['SQLServerVersion'];
Alex Bilbie84445d02011-03-10 16:43:39 +0000264 }
265
266 // --------------------------------------------------------------------
267
268 /**
Alex Bilbie84445d02011-03-10 16:43:39 +0000269 * List table query
270 *
271 * Generates a platform-specific query string so that the table names can be fetched
272 *
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200273 * @param bool
Alex Bilbie84445d02011-03-10 16:43:39 +0000274 * @return string
275 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200276 protected function _list_tables($prefix_limit = FALSE)
Alex Bilbie84445d02011-03-10 16:43:39 +0000277 {
Andrey Andreev70c72c92012-06-25 00:04:51 +0300278 $sql = 'SELECT '.$this->escape_identifiers('name')
279 .' FROM '.$this->escape_identifiers('sysobjects')
280 .' WHERE '.$this->escape_identifiers('type')." = 'U'";
281
282 if ($prefix_limit === TRUE && $this->dbprefix !== '')
283 {
284 $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
285 .sprintf($this->_escape_like_str, $this->_escape_like_chr);
286 }
287
288 return $sql.' ORDER BY '.$this->escape_identifiers('name');
Alex Bilbie84445d02011-03-10 16:43:39 +0000289 }
290
291 // --------------------------------------------------------------------
292
293 /**
294 * List column query
295 *
296 * Generates a platform-specific query string so that the column names can be fetched
297 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000298 * @param string the table name
299 * @return string
300 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200301 protected function _list_columns($table = '')
Alex Bilbie84445d02011-03-10 16:43:39 +0000302 {
Andrey Andreeve6297342012-03-20 16:25:07 +0200303 return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";
Alex Bilbie84445d02011-03-10 16:43:39 +0000304 }
305
306 // --------------------------------------------------------------------
307
308 /**
309 * Field data query
310 *
311 * Generates a platform-specific query so that the column data can be retrieved
312 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000313 * @param string the table name
Andrey Andreeve6297342012-03-20 16:25:07 +0200314 * @return string
Alex Bilbie84445d02011-03-10 16:43:39 +0000315 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200316 protected function _field_data($table)
Alex Bilbie84445d02011-03-10 16:43:39 +0000317 {
Andrey Andreev70c72c92012-06-25 00:04:51 +0300318 return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
Alex Bilbie84445d02011-03-10 16:43:39 +0000319 }
320
321 // --------------------------------------------------------------------
322
323 /**
Andrey Andreev4be5de12012-03-02 15:45:41 +0200324 * Error
Alex Bilbie84445d02011-03-10 16:43:39 +0000325 *
Andrey Andreev4be5de12012-03-02 15:45:41 +0200326 * Returns an array containing code and message of the last
327 * database error that has occured.
Alex Bilbie84445d02011-03-10 16:43:39 +0000328 *
Andrey Andreev4be5de12012-03-02 15:45:41 +0200329 * @return array
Alex Bilbie84445d02011-03-10 16:43:39 +0000330 */
Andrey Andreev4be5de12012-03-02 15:45:41 +0200331 public function error()
Alex Bilbie84445d02011-03-10 16:43:39 +0000332 {
Andrey Andreev4be5de12012-03-02 15:45:41 +0200333 $error = array('code' => '00000', 'message' => '');
334 $sqlsrv_errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
335
336 if ( ! is_array($sqlsrv_errors))
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200337 {
Andrey Andreev4be5de12012-03-02 15:45:41 +0200338 return $error;
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200339 }
340
Andrey Andreev4be5de12012-03-02 15:45:41 +0200341 $sqlsrv_error = array_shift($sqlsrv_errors);
342 if (isset($sqlsrv_error['SQLSTATE']))
343 {
344 $error['code'] = isset($sqlsrv_error['code']) ? $sqlsrv_error['SQLSTATE'].'/'.$sqlsrv_error['code'] : $sqlsrv_error['SQLSTATE'];
345 }
346 elseif (isset($sqlsrv_error['code']))
347 {
348 $error['code'] = $sqlsrv_error['code'];
349 }
350
351 if (isset($sqlsrv_error['message']))
352 {
353 $error['message'] = $sqlsrv_error['message'];
354 }
355
356 return $error;
Alex Bilbie84445d02011-03-10 16:43:39 +0000357 }
358
359 // --------------------------------------------------------------------
360
361 /**
Alex Bilbie84445d02011-03-10 16:43:39 +0000362 * Update statement
363 *
364 * Generates a platform-specific update string from the supplied data
365 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000366 * @param string the table name
367 * @param array the update data
368 * @param array the where clause
Andrey Andreev00541ae2012-04-09 11:43:10 +0300369 * @param array the orderby clause (ignored)
370 * @param array the limit clause (ignored)
371 * @param array the like clause
Alex Bilbie84445d02011-03-10 16:43:39 +0000372 * @return string
373 */
Andrey Andreev00541ae2012-04-09 11:43:10 +0300374 protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
Alex Bilbie84445d02011-03-10 16:43:39 +0000375 {
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200376 foreach ($values as $key => $val)
Alex Bilbie84445d02011-03-10 16:43:39 +0000377 {
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200378 $valstr[] = $key.' = '.$val;
Alex Bilbie84445d02011-03-10 16:43:39 +0000379 }
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200380
Andrey Andreev00541ae2012-04-09 11:43:10 +0300381 $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
382
383 if ( ! empty($like))
384 {
385 $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
386 }
387
st24b47e982012-04-24 17:45:44 +0800388 return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where;
Alex Bilbie84445d02011-03-10 16:43:39 +0000389 }
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200390
Alex Bilbie84445d02011-03-10 16:43:39 +0000391 // --------------------------------------------------------------------
392
393 /**
394 * Truncate statement
395 *
396 * Generates a platform-specific truncate string from the supplied data
Andrey Andreev6d83cde2012-04-05 16:20:50 +0300397 *
398 * If the database does not support the truncate() command,
399 * then this method maps to 'DELETE FROM table'
Alex Bilbie84445d02011-03-10 16:43:39 +0000400 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000401 * @param string the table name
402 * @return string
403 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200404 protected function _truncate($table)
Alex Bilbie84445d02011-03-10 16:43:39 +0000405 {
Andrey Andreev6d83cde2012-04-05 16:20:50 +0300406 return 'TRUNCATE TABLE '.$table;
Alex Bilbie84445d02011-03-10 16:43:39 +0000407 }
408
409 // --------------------------------------------------------------------
410
411 /**
412 * Delete statement
413 *
414 * Generates a platform-specific delete string from the supplied data
415 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000416 * @param string the table name
417 * @param array the where clause
Andrey Andreev5c0e9fe2012-04-09 12:28:11 +0300418 * @param array the like clause
Alex Bilbie84445d02011-03-10 16:43:39 +0000419 * @param string the limit clause
420 * @return string
421 */
Andrey Andreev5c0e9fe2012-04-09 12:28:11 +0300422 protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
Alex Bilbie84445d02011-03-10 16:43:39 +0000423 {
Andrey Andreev5c0e9fe2012-04-09 12:28:11 +0300424 $conditions = array();
425
426 empty($where) OR $conditions[] = implode(' ', $where);
427 empty($like) OR $conditions[] = implode(' ', $like);
428
429 $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
430
431 return ($limit)
432 ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
433 : 'DELETE FROM '.$table.$conditions;
Alex Bilbie84445d02011-03-10 16:43:39 +0000434 }
435
436 // --------------------------------------------------------------------
437
438 /**
439 * Limit string
440 *
441 * Generates a platform-specific LIMIT clause
442 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000443 * @param string the sql query string
Andrey Andreeve6297342012-03-20 16:25:07 +0200444 * @param int the number of rows to limit the query to
445 * @param int the offset value
Alex Bilbie84445d02011-03-10 16:43:39 +0000446 * @return string
447 */
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200448 protected function _limit($sql, $limit, $offset)
Alex Bilbie84445d02011-03-10 16:43:39 +0000449 {
Andrey Andreevd25c5892012-06-08 16:23:01 +0300450 // As of SQL Server 2012 (11.0.*) OFFSET is supported
Andrey Andreev71379ca2012-06-11 16:12:43 +0300451 if (version_compare($this->version(), '11', '>='))
452 {
453 return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY';
454 }
455
456 $limit = $offset + $limit;
457
458 // An ORDER BY clause is required for ROW_NUMBER() to work
459 if ($offset && ! empty($this->qb_orderby))
460 {
461 $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
462
463 // We have to strip the ORDER BY clause
Andrey Andreev97386682012-10-11 10:24:51 +0300464 $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
Andrey Andreev71379ca2012-06-11 16:12:43 +0300465
466 return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n"
467 .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
468 ."\n) ".$this->escape_identifiers('CI_subquery')
469 ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit;
470 }
471
472 return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
Alex Bilbie84445d02011-03-10 16:43:39 +0000473 }
474
475 // --------------------------------------------------------------------
476
477 /**
478 * Close DB Connection
479 *
Alex Bilbie84445d02011-03-10 16:43:39 +0000480 * @return void
481 */
Andrey Andreev79922c02012-05-23 12:27:17 +0300482 protected function _close()
Alex Bilbie84445d02011-03-10 16:43:39 +0000483 {
Andrey Andreev79922c02012-05-23 12:27:17 +0300484 @sqlsrv_close($this->conn_id);
Alex Bilbie84445d02011-03-10 16:43:39 +0000485 }
486
487}
488
Andrey Andreev0e8968a2012-01-26 02:04:37 +0200489/* End of file sqlsrv_driver.php */
Andrey Andreev79922c02012-05-23 12:27:17 +0300490/* Location: ./system/database/drivers/sqlsrv/sqlsrv_driver.php */