Statement.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. namespace Doctrine\DBAL\Portability;
  3. use Doctrine\DBAL\Driver\Statement as DriverStatement;
  4. use Doctrine\DBAL\Driver\StatementIterator;
  5. use Doctrine\DBAL\FetchMode;
  6. use Doctrine\DBAL\ParameterType;
  7. use IteratorAggregate;
  8. use PDO;
  9. use function array_change_key_case;
  10. use function is_string;
  11. use function rtrim;
  12. /**
  13. * Portability wrapper for a Statement.
  14. */
  15. class Statement implements IteratorAggregate, DriverStatement
  16. {
  17. /** @var int */
  18. private $portability;
  19. /** @var DriverStatement */
  20. private $stmt;
  21. /** @var int */
  22. private $case;
  23. /** @var int */
  24. private $defaultFetchMode = FetchMode::MIXED;
  25. /**
  26. * Wraps <tt>Statement</tt> and applies portability measures.
  27. *
  28. * @param DriverStatement $stmt
  29. */
  30. public function __construct($stmt, Connection $conn)
  31. {
  32. $this->stmt = $stmt;
  33. $this->portability = $conn->getPortability();
  34. $this->case = $conn->getFetchCase();
  35. }
  36. /**
  37. * {@inheritdoc}
  38. */
  39. public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null)
  40. {
  41. return $this->stmt->bindParam($column, $variable, $type, $length);
  42. }
  43. /**
  44. * {@inheritdoc}
  45. */
  46. public function bindValue($param, $value, $type = ParameterType::STRING)
  47. {
  48. return $this->stmt->bindValue($param, $value, $type);
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. public function closeCursor()
  54. {
  55. return $this->stmt->closeCursor();
  56. }
  57. /**
  58. * {@inheritdoc}
  59. */
  60. public function columnCount()
  61. {
  62. return $this->stmt->columnCount();
  63. }
  64. /**
  65. * {@inheritdoc}
  66. */
  67. public function errorCode()
  68. {
  69. return $this->stmt->errorCode();
  70. }
  71. /**
  72. * {@inheritdoc}
  73. */
  74. public function errorInfo()
  75. {
  76. return $this->stmt->errorInfo();
  77. }
  78. /**
  79. * {@inheritdoc}
  80. */
  81. public function execute($params = null)
  82. {
  83. return $this->stmt->execute($params);
  84. }
  85. /**
  86. * {@inheritdoc}
  87. */
  88. public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null)
  89. {
  90. $this->defaultFetchMode = $fetchMode;
  91. return $this->stmt->setFetchMode($fetchMode, $arg1, $arg2);
  92. }
  93. /**
  94. * {@inheritdoc}
  95. */
  96. public function getIterator()
  97. {
  98. return new StatementIterator($this);
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
  104. {
  105. $fetchMode = $fetchMode ?: $this->defaultFetchMode;
  106. $row = $this->stmt->fetch($fetchMode);
  107. $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM);
  108. $fixCase = $this->case !== null
  109. && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
  110. && ($this->portability & Connection::PORTABILITY_FIX_CASE);
  111. $row = $this->fixRow($row, $iterateRow, $fixCase);
  112. return $row;
  113. }
  114. /**
  115. * {@inheritdoc}
  116. */
  117. public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
  118. {
  119. $fetchMode = $fetchMode ?: $this->defaultFetchMode;
  120. if ($fetchArgument) {
  121. $rows = $this->stmt->fetchAll($fetchMode, $fetchArgument);
  122. } else {
  123. $rows = $this->stmt->fetchAll($fetchMode);
  124. }
  125. $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM);
  126. $fixCase = $this->case !== null
  127. && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
  128. && ($this->portability & Connection::PORTABILITY_FIX_CASE);
  129. if (! $iterateRow && ! $fixCase) {
  130. return $rows;
  131. }
  132. if ($fetchMode === FetchMode::COLUMN) {
  133. foreach ($rows as $num => $row) {
  134. $rows[$num] = [$row];
  135. }
  136. }
  137. foreach ($rows as $num => $row) {
  138. $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase);
  139. }
  140. if ($fetchMode === FetchMode::COLUMN) {
  141. foreach ($rows as $num => $row) {
  142. $rows[$num] = $row[0];
  143. }
  144. }
  145. return $rows;
  146. }
  147. /**
  148. * @param mixed $row
  149. * @param int $iterateRow
  150. * @param bool $fixCase
  151. *
  152. * @return mixed
  153. */
  154. protected function fixRow($row, $iterateRow, $fixCase)
  155. {
  156. if (! $row) {
  157. return $row;
  158. }
  159. if ($fixCase) {
  160. $row = array_change_key_case($row, $this->case);
  161. }
  162. if ($iterateRow) {
  163. foreach ($row as $k => $v) {
  164. if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') {
  165. $row[$k] = null;
  166. } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) {
  167. $row[$k] = rtrim($v);
  168. }
  169. }
  170. }
  171. return $row;
  172. }
  173. /**
  174. * {@inheritdoc}
  175. */
  176. public function fetchColumn($columnIndex = 0)
  177. {
  178. $value = $this->stmt->fetchColumn($columnIndex);
  179. if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) {
  180. if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') {
  181. $value = null;
  182. } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) {
  183. $value = rtrim($value);
  184. }
  185. }
  186. return $value;
  187. }
  188. /**
  189. * {@inheritdoc}
  190. */
  191. public function rowCount()
  192. {
  193. return $this->stmt->rowCount();
  194. }
  195. }