7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
17 * @subpackage Statement
18 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
23 * @see Zend_Db_Statement
25 require_once 'Zend/Db/Statement.php';
28 * Extends for Microsoft SQL Server Driver for PHP
32 * @subpackage Statement
33 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
34 * @license http://framework.zend.com/license/new-bsd New BSD License
36 class Zend_Db_Statement_Sqlsrv
extends Zend_Db_Statement
39 * The connection_stmt object.
44 * The connection_stmt object original string.
46 protected $_originalSQL;
56 protected $_executed = false;
59 * Prepares statement handle
63 * @throws Zend_Db_Statement_Sqlsrv_Exception
65 protected function _prepare($sql)
67 $connection = $this->_adapter
->getConnection();
69 $this->_stmt
= sqlsrv_prepare($connection, $sql);
72 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
73 throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
76 $this->_originalSQL
= $sql;
80 * Binds a parameter to the specified variable name.
82 * @param mixed $parameter Name the parameter, either integer or string.
83 * @param mixed $variable Reference to PHP variable containing the value.
84 * @param mixed $type OPTIONAL Datatype of SQL parameter.
85 * @param mixed $length OPTIONAL Length of SQL parameter.
86 * @param mixed $options OPTIONAL Other options.
88 * @throws Zend_Db_Statement_Exception
90 protected function _bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
92 //Sql server doesn't support bind by name
97 * Closes the cursor, allowing the statement to be executed again.
101 public function closeCursor()
107 sqlsrv_free_stmt($this->_stmt
);
108 $this->_stmt
= false;
113 * Returns the number of columns in the result set.
114 * Returns null if the statement has no result set metadata.
116 * @return int The number of columns.
118 public function columnCount()
120 if ($this->_stmt
&& $this->_executed
) {
121 return sqlsrv_num_fields($this->_stmt
);
129 * Retrieves the error code, if any, associated with the last operation on
130 * the statement handle.
132 * @return string error code.
134 public function errorCode()
140 $error = sqlsrv_errors();
145 return $error[0]['code'];
150 * Retrieves an array of error information, if any, associated with the
151 * last operation on the statement handle.
155 public function errorInfo()
161 $error = sqlsrv_errors();
168 $error[0]['message'],
174 * Executes a prepared statement.
176 * @param array $params OPTIONAL Values to bind to parameter placeholders.
178 * @throws Zend_Db_Statement_Exception
180 public function _execute(array $params = null)
182 $connection = $this->_adapter
->getConnection();
187 if ($params !== null) {
188 if (!is_array($params)) {
189 $params = array($params);
193 // make all params passed by reference
197 foreach ($params as $param) {
199 $params_[] = &$temp[$i];
205 $this->_stmt
= sqlsrv_query($connection, $this->_originalSQL
, $params);
208 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
209 throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
212 $this->_executed
= true;
214 return (!$this->_stmt
);
218 * Fetches a row from the result set.
220 * @param int $style OPTIONAL Fetch mode for this fetch operation.
221 * @param int $cursor OPTIONAL Absolute, relative, or other.
222 * @param int $offset OPTIONAL Number for absolute or relative cursors.
223 * @return mixed Array, object, or scalar depending on fetch mode.
224 * @throws Zend_Db_Statement_Exception
226 public function fetch($style = null, $cursor = null, $offset = null)
232 if (null === $style) {
233 $style = $this->_fetchMode
;
236 $values = sqlsrv_fetch_array($this->_stmt
, SQLSRV_FETCH_ASSOC
);
238 if (!$values && (null !== $error = sqlsrv_errors())) {
239 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
240 throw new Zend_Db_Statement_Sqlsrv_Exception($error);
243 if (null === $values) {
248 foreach ($values as $key => $value) {
249 $this->_keys
[] = $this->_adapter
->foldCase($key);
253 $values = array_values($values);
257 case Zend_Db
::FETCH_NUM
:
260 case Zend_Db
::FETCH_ASSOC
:
261 $row = array_combine($this->_keys
, $values);
263 case Zend_Db
::FETCH_BOTH
:
264 $assoc = array_combine($this->_keys
, $values);
265 $row = array_merge($values, $assoc);
267 case Zend_Db
::FETCH_OBJ
:
268 $row = (object) array_combine($this->_keys
, $values);
270 case Zend_Db
::FETCH_BOUND
:
271 $assoc = array_combine($this->_keys
, $values);
272 $row = array_merge($values, $assoc);
273 $row = $this->_fetchBound($row);
276 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
277 throw new Zend_Db_Statement_Sqlsrv_Exception("Invalid fetch mode '$style' specified");
285 * Returns a single column from the next row of a result set.
287 * @param int $col OPTIONAL Position of the column to fetch.
289 * @throws Zend_Db_Statement_Exception
291 public function fetchColumn($col = 0)
297 if (!sqlsrv_fetch($this->_stmt
)) {
298 if (null !== $error = sqlsrv_errors()) {
299 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
300 throw new Zend_Db_Statement_Sqlsrv_Exception($error);
303 // If no error, there is simply no record
307 $data = sqlsrv_get_field($this->_stmt
, $col); //0-based
308 if ($data === false) {
309 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
310 throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
317 * Fetches the next row and returns it as an object.
319 * @param string $class OPTIONAL Name of the class to create.
320 * @param array $config OPTIONAL Constructor arguments for the class.
321 * @return mixed One object instance of the specified class.
322 * @throws Zend_Db_Statement_Exception
324 public function fetchObject($class = 'stdClass', array $config = array())
330 $obj = sqlsrv_fetch_object($this->_stmt
);
332 if ($error = sqlsrv_errors()) {
333 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
334 throw new Zend_Db_Statement_Sqlsrv_Exception($error);
337 /* @todo XXX handle parameters */
347 * Returns metadata for a column in a result set.
351 * @throws Zend_Db_Statement_Sqlsrv_Exception
353 public function getColumnMeta($column)
355 $fields = sqlsrv_field_metadata($this->_stmt
);
358 throw new Zend_Db_Statement_Sqlsrv_Exception('Column metadata can not be fetched');
361 if (!isset($fields[$column])) {
362 throw new Zend_Db_Statement_Sqlsrv_Exception('Column index does not exist in statement');
365 return $fields[$column];
369 * Retrieves the next rowset (result set) for a SQL statement that has
370 * multiple result sets. An example is a stored procedure that returns
371 * the results of multiple queries.
374 * @throws Zend_Db_Statement_Exception
376 public function nextRowset()
378 if (sqlsrv_next_result($this->_stmt
) === false) {
379 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
380 throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
383 //else - moved to next (or there are no more rows)
387 * Returns the number of rows affected by the execution of the
388 * last INSERT, DELETE, or UPDATE statement executed by this
391 * @return int The number of rows affected.
392 * @throws Zend_Db_Statement_Exception
394 public function rowCount()
400 if (!$this->_executed
) {
404 $num_rows = sqlsrv_rows_affected($this->_stmt
);
406 // Strict check is necessary; 0 is a valid return value
407 if ($num_rows === false) {
408 require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
409 throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());