CDbDataReader.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. /**
  3. * CDbDataReader class file
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CDbDataReader represents a forward-only stream of rows from a query result set.
  12. *
  13. * To read the current row of data, call {@link read}. The method {@link readAll}
  14. * returns all the rows in a single array.
  15. *
  16. * One can also retrieve the rows of data in CDbDataReader by using foreach:
  17. * <pre>
  18. * foreach($reader as $row)
  19. * // $row represents a row of data
  20. * </pre>
  21. * Since CDbDataReader is a forward-only stream, you can only traverse it once.
  22. *
  23. * It is possible to use a specific mode of data fetching by setting
  24. * {@link setFetchMode FetchMode}. See {@link http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php}
  25. * for more details.
  26. *
  27. * @property boolean $isClosed Whether the reader is closed or not.
  28. * @property integer $rowCount Number of rows contained in the result.
  29. * @property integer $columnCount The number of columns in the result set.
  30. * @property mixed $fetchMode Fetch mode.
  31. *
  32. * @author Qiang Xue <qiang.xue@gmail.com>
  33. * @package system.db
  34. * @since 1.0
  35. */
  36. class CDbDataReader extends CComponent implements Iterator, Countable
  37. {
  38. private $_statement;
  39. private $_closed=false;
  40. private $_row;
  41. private $_index=-1;
  42. public $queryString;
  43. /**
  44. * Constructor.
  45. * @param CDbCommand $command the command generating the query result
  46. */
  47. public function __construct(CDbCommand $command)
  48. {
  49. $this->_statement =$command->getPdoStatement();
  50. $this->_statement->setFetchMode(PDO::FETCH_ASSOC);
  51. $this->queryString = $this->_statement->queryString;
  52. }
  53. /**
  54. * Binds a column to a PHP variable.
  55. * When rows of data are being fetched, the corresponding column value
  56. * will be set in the variable. Note, the fetch mode must include PDO::FETCH_BOUND.
  57. * @param mixed $column Number of the column (1-indexed) or name of the column
  58. * in the result set. If using the column name, be aware that the name
  59. * should match the case of the column, as returned by the driver.
  60. * @param mixed $value Name of the PHP variable to which the column will be bound.
  61. * @param integer $dataType Data type of the parameter
  62. * @see http://www.php.net/manual/en/function.PDOStatement-bindColumn.php
  63. */
  64. public function bindColumn($column, &$value, $dataType=null)
  65. {
  66. if($dataType===null)
  67. $this->_statement->bindColumn($column,$value);
  68. else
  69. $this->_statement->bindColumn($column,$value,$dataType);
  70. }
  71. /**
  72. * Set the default fetch mode for this statement
  73. * @param mixed $mode fetch mode
  74. * @see http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php
  75. */
  76. public function setFetchMode($mode)
  77. {
  78. $params=func_get_args();
  79. call_user_func_array(array($this->_statement,'setFetchMode'),$params);
  80. }
  81. /**
  82. * Advances the reader to the next row in a result set.
  83. * @return array|false the current row, false if no more row available
  84. */
  85. public function read()
  86. {
  87. return $this->_statement->fetch();
  88. }
  89. /**
  90. * Returns a single column from the next row of a result set.
  91. * @param integer $columnIndex zero-based column index
  92. * @return mixed|false the column of the current row, false if no more row available
  93. */
  94. public function readColumn($columnIndex)
  95. {
  96. return $this->_statement->fetchColumn($columnIndex);
  97. }
  98. /**
  99. * Returns an object populated with the next row of data.
  100. * @param string $className class name of the object to be created and populated
  101. * @param array $fields Elements of this array are passed to the constructor
  102. * @return mixed|false the populated object, false if no more row of data available
  103. */
  104. public function readObject($className,$fields)
  105. {
  106. return $this->_statement->fetchObject($className,$fields);
  107. }
  108. /**
  109. * Reads the whole result set into an array.
  110. * @return array the result set (each array element represents a row of data).
  111. * An empty array will be returned if the result contains no row.
  112. */
  113. public function readAll()
  114. {
  115. return $this->_statement->fetchAll();
  116. }
  117. /**
  118. * Advances the reader to the next result when reading the results of a batch of statements.
  119. * This method is only useful when there are multiple result sets
  120. * returned by the query. Not all DBMS support this feature.
  121. * @return boolean Returns true on success or false on failure.
  122. */
  123. public function nextResult()
  124. {
  125. if(($result=$this->_statement->nextRowset())!==false)
  126. $this->_index=-1;
  127. return $result;
  128. }
  129. /**
  130. * Closes the reader.
  131. * This frees up the resources allocated for executing this SQL statement.
  132. * Read attempts after this method call are unpredictable.
  133. */
  134. public function close()
  135. {
  136. $this->_statement->closeCursor();
  137. $this->_closed=true;
  138. }
  139. /**
  140. * whether the reader is closed or not.
  141. * @return boolean whether the reader is closed or not.
  142. */
  143. public function getIsClosed()
  144. {
  145. return $this->_closed;
  146. }
  147. /**
  148. * Returns the number of rows in the result set.
  149. * Note, most DBMS may not give a meaningful count.
  150. * In this case, use "SELECT COUNT(*) FROM tableName" to obtain the number of rows.
  151. * @return integer number of rows contained in the result.
  152. */
  153. public function getRowCount()
  154. {
  155. return $this->_statement->rowCount();
  156. }
  157. /**
  158. * Returns the number of rows in the result set.
  159. * This method is required by the Countable interface.
  160. * Note, most DBMS may not give a meaningful count.
  161. * In this case, use "SELECT COUNT(*) FROM tableName" to obtain the number of rows.
  162. * @return integer number of rows contained in the result.
  163. */
  164. public function count()
  165. {
  166. return $this->getRowCount();
  167. }
  168. /**
  169. * Returns the number of columns in the result set.
  170. * Note, even there's no row in the reader, this still gives correct column number.
  171. * @return integer the number of columns in the result set.
  172. */
  173. public function getColumnCount()
  174. {
  175. return $this->_statement->columnCount();
  176. }
  177. /**
  178. * Resets the iterator to the initial state.
  179. * This method is required by the interface Iterator.
  180. * @throws CException if this method is invoked twice
  181. */
  182. public function rewind()
  183. {
  184. if($this->_index<0)
  185. {
  186. $this->_row=$this->_statement->fetch();
  187. $this->_index=0;
  188. }
  189. else
  190. throw new CDbException(Yii::t('yii','CDbDataReader cannot rewind. It is a forward-only reader.'));
  191. }
  192. /**
  193. * Returns the index of the current row.
  194. * This method is required by the interface Iterator.
  195. * @return integer the index of the current row.
  196. */
  197. public function key()
  198. {
  199. return $this->_index;
  200. }
  201. /**
  202. * Returns the current row.
  203. * This method is required by the interface Iterator.
  204. * @return mixed the current row.
  205. */
  206. public function current()
  207. {
  208. return $this->_row;
  209. }
  210. /**
  211. * Moves the internal pointer to the next row.
  212. * This method is required by the interface Iterator.
  213. */
  214. public function next()
  215. {
  216. $this->_row=$this->_statement->fetch();
  217. $this->_index++;
  218. }
  219. /**
  220. * Returns whether there is a row of data at current position.
  221. * This method is required by the interface Iterator.
  222. * @return boolean whether there is a row of data at current position.
  223. */
  224. public function valid()
  225. {
  226. return $this->_row!==false;
  227. }
  228. }