1<?php 2/** 3 * Zend Framework 4 * 5 * LICENSE 6 * 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. 14 * 15 * @category Zend 16 * @package Zend_Db 17 * @subpackage Statement 18 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 19 * @license http://framework.zend.com/license/new-bsd New BSD License 20 * @version $Id: Db2.php 23775 2011-03-01 17:25:24Z ralph $ 21 */ 22 23/** 24 * @see Zend_Db_Statement 25 */ 26// require_once 'Zend/Db/Statement.php'; 27 28/** 29 * Extends for DB2 native adapter. 30 * 31 * @package Zend_Db 32 * @subpackage Statement 33 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 34 * @license http://framework.zend.com/license/new-bsd New BSD License 35 */ 36class Zend_Db_Statement_Db2 extends Zend_Db_Statement 37{ 38 39 /** 40 * Column names. 41 */ 42 protected $_keys; 43 44 /** 45 * Fetched result values. 46 */ 47 protected $_values; 48 49 /** 50 * Prepare a statement handle. 51 * 52 * @param string $sql 53 * @return void 54 * @throws Zend_Db_Statement_Db2_Exception 55 */ 56 public function _prepare($sql) 57 { 58 $connection = $this->_adapter->getConnection(); 59 60 // db2_prepare on i5 emits errors, these need to be 61 // suppressed so that proper exceptions can be thrown 62 $this->_stmt = @db2_prepare($connection, $sql); 63 64 if (!$this->_stmt) { 65 /** 66 * @see Zend_Db_Statement_Db2_Exception 67 */ 68 // require_once 'Zend/Db/Statement/Db2/Exception.php'; 69 throw new Zend_Db_Statement_Db2_Exception( 70 db2_stmt_errormsg(), 71 db2_stmt_error() 72 ); 73 } 74 } 75 76 /** 77 * Binds a parameter to the specified variable name. 78 * 79 * @param mixed $parameter Name the parameter, either integer or string. 80 * @param mixed $variable Reference to PHP variable containing the value. 81 * @param mixed $type OPTIONAL Datatype of SQL parameter. 82 * @param mixed $length OPTIONAL Length of SQL parameter. 83 * @param mixed $options OPTIONAL Other options. 84 * @return bool 85 * @throws Zend_Db_Statement_Db2_Exception 86 */ 87 public function _bindParam($parameter, &$variable, $type = null, $length = null, $options = null) 88 { 89 if ($type === null) { 90 $type = DB2_PARAM_IN; 91 } 92 93 if (isset($options['data-type'])) { 94 $datatype = $options['data-type']; 95 } else { 96 $datatype = DB2_CHAR; 97 } 98 99 if (!db2_bind_param($this->_stmt, $position, "variable", $type, $datatype)) { 100 /** 101 * @see Zend_Db_Statement_Db2_Exception 102 */ 103 // require_once 'Zend/Db/Statement/Db2/Exception.php'; 104 throw new Zend_Db_Statement_Db2_Exception( 105 db2_stmt_errormsg(), 106 db2_stmt_error() 107 ); 108 } 109 110 return true; 111 } 112 113 /** 114 * Closes the cursor, allowing the statement to be executed again. 115 * 116 * @return bool 117 */ 118 public function closeCursor() 119 { 120 if (!$this->_stmt) { 121 return false; 122 } 123 db2_free_stmt($this->_stmt); 124 $this->_stmt = false; 125 return true; 126 } 127 128 129 /** 130 * Returns the number of columns in the result set. 131 * Returns null if the statement has no result set metadata. 132 * 133 * @return int The number of columns. 134 */ 135 public function columnCount() 136 { 137 if (!$this->_stmt) { 138 return false; 139 } 140 return db2_num_fields($this->_stmt); 141 } 142 143 /** 144 * Retrieves the error code, if any, associated with the last operation on 145 * the statement handle. 146 * 147 * @return string error code. 148 */ 149 public function errorCode() 150 { 151 if (!$this->_stmt) { 152 return false; 153 } 154 155 $error = db2_stmt_error(); 156 if ($error === '') { 157 return false; 158 } 159 160 return $error; 161 } 162 163 /** 164 * Retrieves an array of error information, if any, associated with the 165 * last operation on the statement handle. 166 * 167 * @return array 168 */ 169 public function errorInfo() 170 { 171 $error = $this->errorCode(); 172 if ($error === false){ 173 return false; 174 } 175 176 /* 177 * Return three-valued array like PDO. But DB2 does not distinguish 178 * between SQLCODE and native RDBMS error code, so repeat the SQLCODE. 179 */ 180 return array( 181 $error, 182 $error, 183 db2_stmt_errormsg() 184 ); 185 } 186 187 /** 188 * Executes a prepared statement. 189 * 190 * @param array $params OPTIONAL Values to bind to parameter placeholders. 191 * @return bool 192 * @throws Zend_Db_Statement_Db2_Exception 193 */ 194 public function _execute(array $params = null) 195 { 196 if (!$this->_stmt) { 197 return false; 198 } 199 200 $retval = true; 201 if ($params !== null) { 202 $retval = @db2_execute($this->_stmt, $params); 203 } else { 204 $retval = @db2_execute($this->_stmt); 205 } 206 207 if ($retval === false) { 208 /** 209 * @see Zend_Db_Statement_Db2_Exception 210 */ 211 // require_once 'Zend/Db/Statement/Db2/Exception.php'; 212 throw new Zend_Db_Statement_Db2_Exception( 213 db2_stmt_errormsg(), 214 db2_stmt_error()); 215 } 216 217 $this->_keys = array(); 218 if ($field_num = $this->columnCount()) { 219 for ($i = 0; $i < $field_num; $i++) { 220 $name = db2_field_name($this->_stmt, $i); 221 $this->_keys[] = $name; 222 } 223 } 224 225 $this->_values = array(); 226 if ($this->_keys) { 227 $this->_values = array_fill(0, count($this->_keys), null); 228 } 229 230 return $retval; 231 } 232 233 /** 234 * Fetches a row from the result set. 235 * 236 * @param int $style OPTIONAL Fetch mode for this fetch operation. 237 * @param int $cursor OPTIONAL Absolute, relative, or other. 238 * @param int $offset OPTIONAL Number for absolute or relative cursors. 239 * @return mixed Array, object, or scalar depending on fetch mode. 240 * @throws Zend_Db_Statement_Db2_Exception 241 */ 242 public function fetch($style = null, $cursor = null, $offset = null) 243 { 244 if (!$this->_stmt) { 245 return false; 246 } 247 248 if ($style === null) { 249 $style = $this->_fetchMode; 250 } 251 252 switch ($style) { 253 case Zend_Db::FETCH_NUM : 254 $row = db2_fetch_array($this->_stmt); 255 break; 256 case Zend_Db::FETCH_ASSOC : 257 $row = db2_fetch_assoc($this->_stmt); 258 break; 259 case Zend_Db::FETCH_BOTH : 260 $row = db2_fetch_both($this->_stmt); 261 break; 262 case Zend_Db::FETCH_OBJ : 263 $row = db2_fetch_object($this->_stmt); 264 break; 265 case Zend_Db::FETCH_BOUND: 266 $row = db2_fetch_both($this->_stmt); 267 if ($row !== false) { 268 return $this->_fetchBound($row); 269 } 270 break; 271 default: 272 /** 273 * @see Zend_Db_Statement_Db2_Exception 274 */ 275 // require_once 'Zend/Db/Statement/Db2/Exception.php'; 276 throw new Zend_Db_Statement_Db2_Exception("Invalid fetch mode '$style' specified"); 277 break; 278 } 279 280 return $row; 281 } 282 283 /** 284 * Fetches the next row and returns it as an object. 285 * 286 * @param string $class OPTIONAL Name of the class to create. 287 * @param array $config OPTIONAL Constructor arguments for the class. 288 * @return mixed One object instance of the specified class. 289 */ 290 public function fetchObject($class = 'stdClass', array $config = array()) 291 { 292 $obj = $this->fetch(Zend_Db::FETCH_OBJ); 293 return $obj; 294 } 295 296 /** 297 * Retrieves the next rowset (result set) for a SQL statement that has 298 * multiple result sets. An example is a stored procedure that returns 299 * the results of multiple queries. 300 * 301 * @return bool 302 * @throws Zend_Db_Statement_Db2_Exception 303 */ 304 public function nextRowset() 305 { 306 /** 307 * @see Zend_Db_Statement_Db2_Exception 308 */ 309 // require_once 'Zend/Db/Statement/Db2/Exception.php'; 310 throw new Zend_Db_Statement_Db2_Exception(__FUNCTION__ . '() is not implemented'); 311 } 312 313 /** 314 * Returns the number of rows affected by the execution of the 315 * last INSERT, DELETE, or UPDATE statement executed by this 316 * statement object. 317 * 318 * @return int The number of rows affected. 319 */ 320 public function rowCount() 321 { 322 if (!$this->_stmt) { 323 return false; 324 } 325 326 $num = @db2_num_rows($this->_stmt); 327 328 if ($num === false) { 329 return 0; 330 } 331 332 return $num; 333 } 334 335 /** 336 * Returns an array containing all of the result set rows. 337 * 338 * @param int $style OPTIONAL Fetch mode. 339 * @param int $col OPTIONAL Column number, if fetch mode is by column. 340 * @return array Collection of rows, each in a format by the fetch mode. 341 * 342 * Behaves like parent, but if limit() 343 * is used, the final result removes the extra column 344 * 'zend_db_rownum' 345 */ 346 public function fetchAll($style = null, $col = null) 347 { 348 $data = parent::fetchAll($style, $col); 349 $results = array(); 350 $remove = $this->_adapter->foldCase('ZEND_DB_ROWNUM'); 351 352 foreach ($data as $row) { 353 if (is_array($row) && array_key_exists($remove, $row)) { 354 unset($row[$remove]); 355 } 356 $results[] = $row; 357 } 358 return $results; 359 } 360} 361