File indexing completed on 2025-01-19 05:21:02
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Db 0017 * @subpackage Statement 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Db_Statement 0025 */ 0026 // require_once 'Zend/Db/Statement.php'; 0027 0028 /** 0029 * Extends for Oracle. 0030 * 0031 * @category Zend 0032 * @package Zend_Db 0033 * @subpackage Statement 0034 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0035 * @license http://framework.zend.com/license/new-bsd New BSD License 0036 */ 0037 class Zend_Db_Statement_Oracle extends Zend_Db_Statement 0038 { 0039 0040 /** 0041 * Column names. 0042 */ 0043 protected $_keys; 0044 0045 /** 0046 * Fetched result values. 0047 */ 0048 protected $_values; 0049 0050 /** 0051 * Check if LOB field are returned as string 0052 * instead of OCI-Lob object 0053 * 0054 * @var boolean 0055 */ 0056 protected $_lobAsString = false; 0057 0058 /** 0059 * Activate/deactivate return of LOB as string 0060 * 0061 * @param string $lob_as_string 0062 * @return Zend_Db_Statement_Oracle 0063 */ 0064 public function setLobAsString($lob_as_string) 0065 { 0066 $this->_lobAsString = (bool) $lob_as_string; 0067 return $this; 0068 } 0069 0070 /** 0071 * Return whether or not LOB are returned as string 0072 * 0073 * @return boolean 0074 */ 0075 public function getLobAsString() 0076 { 0077 return $this->_lobAsString; 0078 } 0079 0080 /** 0081 * Prepares statement handle 0082 * 0083 * @param string $sql 0084 * @return void 0085 * @throws Zend_Db_Statement_Oracle_Exception 0086 */ 0087 protected function _prepare($sql) 0088 { 0089 $connection = $this->_adapter->getConnection(); 0090 $this->_stmt = @oci_parse($connection, $sql); 0091 if (!$this->_stmt) { 0092 /** 0093 * @see Zend_Db_Statement_Oracle_Exception 0094 */ 0095 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0096 throw new Zend_Db_Statement_Oracle_Exception(oci_error($connection)); 0097 } 0098 } 0099 0100 /** 0101 * Binds a parameter to the specified variable name. 0102 * 0103 * @param mixed $parameter Name the parameter, either integer or string. 0104 * @param mixed $variable Reference to PHP variable containing the value. 0105 * @param mixed $type OPTIONAL Datatype of SQL parameter. 0106 * @param mixed $length OPTIONAL Length of SQL parameter. 0107 * @param mixed $options OPTIONAL Other options. 0108 * @return bool 0109 * @throws Zend_Db_Statement_Exception 0110 */ 0111 protected function _bindParam($parameter, &$variable, $type = null, $length = null, $options = null) 0112 { 0113 // default value 0114 if ($type === NULL) { 0115 $type = SQLT_CHR; 0116 } 0117 0118 // default value 0119 if ($length === NULL) { 0120 $length = -1; 0121 } 0122 0123 $retval = @oci_bind_by_name($this->_stmt, $parameter, $variable, $length, $type); 0124 if ($retval === false) { 0125 /** 0126 * @see Zend_Db_Adapter_Oracle_Exception 0127 */ 0128 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0129 throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt)); 0130 } 0131 0132 return true; 0133 } 0134 0135 /** 0136 * Closes the cursor, allowing the statement to be executed again. 0137 * 0138 * @return bool 0139 */ 0140 public function closeCursor() 0141 { 0142 if (!$this->_stmt) { 0143 return false; 0144 } 0145 0146 oci_free_statement($this->_stmt); 0147 $this->_stmt = false; 0148 return true; 0149 } 0150 0151 /** 0152 * Returns the number of columns in the result set. 0153 * Returns null if the statement has no result set metadata. 0154 * 0155 * @return int The number of columns. 0156 */ 0157 public function columnCount() 0158 { 0159 if (!$this->_stmt) { 0160 return false; 0161 } 0162 0163 return oci_num_fields($this->_stmt); 0164 } 0165 0166 0167 /** 0168 * Retrieves the error code, if any, associated with the last operation on 0169 * the statement handle. 0170 * 0171 * @return string error code. 0172 */ 0173 public function errorCode() 0174 { 0175 if (!$this->_stmt) { 0176 return false; 0177 } 0178 0179 $error = oci_error($this->_stmt); 0180 0181 if (!$error) { 0182 return false; 0183 } 0184 0185 return $error['code']; 0186 } 0187 0188 0189 /** 0190 * Retrieves an array of error information, if any, associated with the 0191 * last operation on the statement handle. 0192 * 0193 * @return array 0194 */ 0195 public function errorInfo() 0196 { 0197 if (!$this->_stmt) { 0198 return false; 0199 } 0200 0201 $error = oci_error($this->_stmt); 0202 if (!$error) { 0203 return false; 0204 } 0205 0206 if (isset($error['sqltext'])) { 0207 return array( 0208 $error['code'], 0209 $error['message'], 0210 $error['offset'], 0211 $error['sqltext'], 0212 ); 0213 } else { 0214 return array( 0215 $error['code'], 0216 $error['message'], 0217 ); 0218 } 0219 } 0220 0221 0222 /** 0223 * Executes a prepared statement. 0224 * 0225 * @param array $params OPTIONAL Values to bind to parameter placeholders. 0226 * @return bool 0227 * @throws Zend_Db_Statement_Exception 0228 */ 0229 public function _execute(array $params = null) 0230 { 0231 $connection = $this->_adapter->getConnection(); 0232 0233 if (!$this->_stmt) { 0234 return false; 0235 } 0236 0237 if ($params !== null) { 0238 if (!is_array($params)) { 0239 $params = array($params); 0240 } 0241 $error = false; 0242 foreach (array_keys($params) as $name) { 0243 if (!$this->bindParam($name, $params[$name], null, -1)) { 0244 $error = true; 0245 break; 0246 } 0247 } 0248 if ($error) { 0249 /** 0250 * @see Zend_Db_Adapter_Oracle_Exception 0251 */ 0252 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0253 throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt)); 0254 } 0255 } 0256 0257 $retval = @oci_execute($this->_stmt, $this->_adapter->_getExecuteMode()); 0258 if ($retval === false) { 0259 /** 0260 * @see Zend_Db_Adapter_Oracle_Exception 0261 */ 0262 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0263 throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt)); 0264 } 0265 0266 $this->_keys = Array(); 0267 if ($field_num = oci_num_fields($this->_stmt)) { 0268 for ($i = 1; $i <= $field_num; $i++) { 0269 $name = oci_field_name($this->_stmt, $i); 0270 $this->_keys[] = $name; 0271 } 0272 } 0273 0274 $this->_values = Array(); 0275 if ($this->_keys) { 0276 $this->_values = array_fill(0, count($this->_keys), null); 0277 } 0278 0279 return $retval; 0280 } 0281 0282 /** 0283 * Fetches a row from the result set. 0284 * 0285 * @param int $style OPTIONAL Fetch mode for this fetch operation. 0286 * @param int $cursor OPTIONAL Absolute, relative, or other. 0287 * @param int $offset OPTIONAL Number for absolute or relative cursors. 0288 * @return mixed Array, object, or scalar depending on fetch mode. 0289 * @throws Zend_Db_Statement_Exception 0290 */ 0291 public function fetch($style = null, $cursor = null, $offset = null) 0292 { 0293 if (!$this->_stmt) { 0294 return false; 0295 } 0296 0297 if ($style === null) { 0298 $style = $this->_fetchMode; 0299 } 0300 0301 $lob_as_string = $this->getLobAsString() ? OCI_RETURN_LOBS : 0; 0302 0303 switch ($style) { 0304 case Zend_Db::FETCH_NUM: 0305 $row = oci_fetch_array($this->_stmt, OCI_NUM | OCI_RETURN_NULLS | $lob_as_string); 0306 break; 0307 case Zend_Db::FETCH_ASSOC: 0308 $row = oci_fetch_array($this->_stmt, OCI_ASSOC | OCI_RETURN_NULLS | $lob_as_string); 0309 break; 0310 case Zend_Db::FETCH_BOTH: 0311 $row = oci_fetch_array($this->_stmt, OCI_BOTH | OCI_RETURN_NULLS | $lob_as_string); 0312 break; 0313 case Zend_Db::FETCH_OBJ: 0314 $row = oci_fetch_object($this->_stmt); 0315 break; 0316 case Zend_Db::FETCH_BOUND: 0317 $row = oci_fetch_array($this->_stmt, OCI_BOTH | OCI_RETURN_NULLS | $lob_as_string); 0318 if ($row !== false) { 0319 return $this->_fetchBound($row); 0320 } 0321 break; 0322 default: 0323 /** 0324 * @see Zend_Db_Adapter_Oracle_Exception 0325 */ 0326 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0327 throw new Zend_Db_Statement_Oracle_Exception( 0328 array( 0329 'code' => 'HYC00', 0330 'message' => "Invalid fetch mode '$style' specified" 0331 ) 0332 ); 0333 break; 0334 } 0335 0336 if (! $row && $error = oci_error($this->_stmt)) { 0337 /** 0338 * @see Zend_Db_Adapter_Oracle_Exception 0339 */ 0340 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0341 throw new Zend_Db_Statement_Oracle_Exception($error); 0342 } 0343 0344 if (is_array($row) && array_key_exists('zend_db_rownum', $row)) { 0345 unset($row['zend_db_rownum']); 0346 } 0347 0348 return $row; 0349 } 0350 0351 /** 0352 * Returns an array containing all of the result set rows. 0353 * 0354 * @param int $style OPTIONAL Fetch mode. 0355 * @param int $col OPTIONAL Column number, if fetch mode is by column. 0356 * @return array Collection of rows, each in a format by the fetch mode. 0357 * @throws Zend_Db_Statement_Exception 0358 */ 0359 public function fetchAll($style = null, $col = 0) 0360 { 0361 if (!$this->_stmt) { 0362 return false; 0363 } 0364 0365 // make sure we have a fetch mode 0366 if ($style === null) { 0367 $style = $this->_fetchMode; 0368 } 0369 0370 $flags = OCI_FETCHSTATEMENT_BY_ROW; 0371 0372 switch ($style) { 0373 case Zend_Db::FETCH_BOTH: 0374 /** 0375 * @see Zend_Db_Adapter_Oracle_Exception 0376 */ 0377 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0378 throw new Zend_Db_Statement_Oracle_Exception( 0379 array( 0380 'code' => 'HYC00', 0381 'message' => "OCI8 driver does not support fetchAll(FETCH_BOTH), use fetch() in a loop instead" 0382 ) 0383 ); 0384 // notreached 0385 $flags |= OCI_NUM; 0386 $flags |= OCI_ASSOC; 0387 break; 0388 case Zend_Db::FETCH_NUM: 0389 $flags |= OCI_NUM; 0390 break; 0391 case Zend_Db::FETCH_ASSOC: 0392 $flags |= OCI_ASSOC; 0393 break; 0394 case Zend_Db::FETCH_OBJ: 0395 break; 0396 case Zend_Db::FETCH_COLUMN: 0397 $flags = $flags &~ OCI_FETCHSTATEMENT_BY_ROW; 0398 $flags |= OCI_FETCHSTATEMENT_BY_COLUMN; 0399 $flags |= OCI_NUM; 0400 break; 0401 default: 0402 /** 0403 * @see Zend_Db_Adapter_Oracle_Exception 0404 */ 0405 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0406 throw new Zend_Db_Statement_Oracle_Exception( 0407 array( 0408 'code' => 'HYC00', 0409 'message' => "Invalid fetch mode '$style' specified" 0410 ) 0411 ); 0412 break; 0413 } 0414 0415 $result = Array(); 0416 if ($flags != OCI_FETCHSTATEMENT_BY_ROW) { /* not Zend_Db::FETCH_OBJ */ 0417 if (! ($rows = oci_fetch_all($this->_stmt, $result, 0, -1, $flags) )) { 0418 if ($error = oci_error($this->_stmt)) { 0419 /** 0420 * @see Zend_Db_Adapter_Oracle_Exception 0421 */ 0422 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0423 throw new Zend_Db_Statement_Oracle_Exception($error); 0424 } 0425 if (!$rows) { 0426 return array(); 0427 } 0428 } 0429 if ($style == Zend_Db::FETCH_COLUMN) { 0430 $result = $result[$col]; 0431 } 0432 foreach ($result as &$row) { 0433 if (is_array($row) && array_key_exists('zend_db_rownum', $row)) { 0434 unset($row['zend_db_rownum']); 0435 } 0436 } 0437 } else { 0438 while (($row = oci_fetch_object($this->_stmt)) !== false) { 0439 $result [] = $row; 0440 } 0441 if ($error = oci_error($this->_stmt)) { 0442 /** 0443 * @see Zend_Db_Adapter_Oracle_Exception 0444 */ 0445 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0446 throw new Zend_Db_Statement_Oracle_Exception($error); 0447 } 0448 } 0449 0450 return $result; 0451 } 0452 0453 0454 /** 0455 * Returns a single column from the next row of a result set. 0456 * 0457 * @param int $col OPTIONAL Position of the column to fetch. 0458 * @return string 0459 * @throws Zend_Db_Statement_Exception 0460 */ 0461 public function fetchColumn($col = 0) 0462 { 0463 if (!$this->_stmt) { 0464 return false; 0465 } 0466 0467 if (!oci_fetch($this->_stmt)) { 0468 // if no error, there is simply no record 0469 if (!$error = oci_error($this->_stmt)) { 0470 return false; 0471 } 0472 /** 0473 * @see Zend_Db_Adapter_Oracle_Exception 0474 */ 0475 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0476 throw new Zend_Db_Statement_Oracle_Exception($error); 0477 } 0478 0479 $data = oci_result($this->_stmt, $col+1); //1-based 0480 if ($data === false) { 0481 /** 0482 * @see Zend_Db_Adapter_Oracle_Exception 0483 */ 0484 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0485 throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt)); 0486 } 0487 0488 if ($this->getLobAsString()) { 0489 // instanceof doesn't allow '-', we must use a temporary string 0490 $type = 'OCI-Lob'; 0491 if ($data instanceof $type) { 0492 $data = $data->read($data->size()); 0493 } 0494 } 0495 0496 return $data; 0497 } 0498 0499 /** 0500 * Fetches the next row and returns it as an object. 0501 * 0502 * @param string $class OPTIONAL Name of the class to create. 0503 * @param array $config OPTIONAL Constructor arguments for the class. 0504 * @return mixed One object instance of the specified class. 0505 * @throws Zend_Db_Statement_Exception 0506 */ 0507 public function fetchObject($class = 'stdClass', array $config = array()) 0508 { 0509 if (!$this->_stmt) { 0510 return false; 0511 } 0512 0513 $obj = oci_fetch_object($this->_stmt); 0514 0515 if ($error = oci_error($this->_stmt)) { 0516 /** 0517 * @see Zend_Db_Adapter_Oracle_Exception 0518 */ 0519 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0520 throw new Zend_Db_Statement_Oracle_Exception($error); 0521 } 0522 0523 /* @todo XXX handle parameters */ 0524 0525 return $obj; 0526 } 0527 0528 /** 0529 * Retrieves the next rowset (result set) for a SQL statement that has 0530 * multiple result sets. An example is a stored procedure that returns 0531 * the results of multiple queries. 0532 * 0533 * @return bool 0534 * @throws Zend_Db_Statement_Exception 0535 */ 0536 public function nextRowset() 0537 { 0538 /** 0539 * @see Zend_Db_Statement_Oracle_Exception 0540 */ 0541 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0542 throw new Zend_Db_Statement_Oracle_Exception( 0543 array( 0544 'code' => 'HYC00', 0545 'message' => 'Optional feature not implemented' 0546 ) 0547 ); 0548 } 0549 0550 /** 0551 * Returns the number of rows affected by the execution of the 0552 * last INSERT, DELETE, or UPDATE statement executed by this 0553 * statement object. 0554 * 0555 * @return int The number of rows affected. 0556 * @throws Zend_Db_Statement_Exception 0557 */ 0558 public function rowCount() 0559 { 0560 if (!$this->_stmt) { 0561 return false; 0562 } 0563 0564 $num_rows = oci_num_rows($this->_stmt); 0565 0566 if ($num_rows === false) { 0567 /** 0568 * @see Zend_Db_Adapter_Oracle_Exception 0569 */ 0570 // require_once 'Zend/Db/Statement/Oracle/Exception.php'; 0571 throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt)); 0572 } 0573 0574 return $num_rows; 0575 } 0576 0577 }