CDbDataReader.php 7.0 KB

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