Result.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <?php
  2. namespace Doctrine\DBAL\ForwardCompatibility;
  3. use Doctrine\DBAL\Driver;
  4. use Doctrine\DBAL\Exception;
  5. use Doctrine\DBAL\Exception\NoKeyValue;
  6. use Doctrine\DBAL\ParameterType;
  7. use Doctrine\Deprecations\Deprecation;
  8. use IteratorAggregate;
  9. use PDO;
  10. use Traversable;
  11. use function array_shift;
  12. use function method_exists;
  13. /**
  14. * A wrapper around a Doctrine\DBAL\Driver\ResultStatement that adds 3.0 features
  15. * defined in Result interface
  16. */
  17. class Result implements IteratorAggregate, DriverStatement, DriverResultStatement
  18. {
  19. /** @var Driver\ResultStatement */
  20. private $stmt;
  21. public static function ensure(Driver\ResultStatement $stmt): Result
  22. {
  23. if ($stmt instanceof Result) {
  24. return $stmt;
  25. }
  26. return new Result($stmt);
  27. }
  28. public function __construct(Driver\ResultStatement $stmt)
  29. {
  30. $this->stmt = $stmt;
  31. }
  32. /**
  33. * @return Driver\ResultStatement
  34. */
  35. public function getIterator()
  36. {
  37. return $this->stmt;
  38. }
  39. /**
  40. * {@inheritDoc}
  41. *
  42. * @deprecated Use Result::free() instead.
  43. */
  44. public function closeCursor()
  45. {
  46. return $this->stmt->closeCursor();
  47. }
  48. /**
  49. * {@inheritDoc}
  50. */
  51. public function columnCount()
  52. {
  53. return $this->stmt->columnCount();
  54. }
  55. /**
  56. * {@inheritDoc}
  57. *
  58. * @deprecated Use one of the fetch- or iterate-related methods.
  59. */
  60. public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
  61. {
  62. return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3);
  63. }
  64. /**
  65. * {@inheritDoc}
  66. *
  67. * @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
  68. */
  69. public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
  70. {
  71. Deprecation::triggerIfCalledFromOutside(
  72. 'doctrine/dbal',
  73. 'https://github.com/doctrine/dbal/pull/4019',
  74. 'Result::fetch() is deprecated, use Result::fetchNumeric(), fetchAssociative() or fetchOne() instead.'
  75. );
  76. return $this->stmt->fetch($fetchMode, $cursorOrientation, $cursorOffset);
  77. }
  78. /**
  79. * {@inheritDoc}
  80. *
  81. * @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
  82. */
  83. public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
  84. {
  85. Deprecation::triggerIfCalledFromOutside(
  86. 'doctrine/dbal',
  87. 'https://github.com/doctrine/dbal/pull/4019',
  88. 'Result::fetchAll() is deprecated, use Result::fetchAllNumeric(), fetchAllAssociative() or ' .
  89. 'fetchFirstColumn() instead.'
  90. );
  91. return $this->stmt->fetchAll($fetchMode, $fetchArgument, $ctorArgs);
  92. }
  93. /**
  94. * {@inheritDoc}
  95. *
  96. * @deprecated Use fetchOne() instead.
  97. */
  98. public function fetchColumn($columnIndex = 0)
  99. {
  100. Deprecation::triggerIfCalledFromOutside(
  101. 'doctrine/dbal',
  102. 'https://github.com/doctrine/dbal/pull/4019',
  103. 'Result::fetchColumn() is deprecated, use Result::fetchOne() instead.'
  104. );
  105. return $this->stmt->fetchColumn($columnIndex);
  106. }
  107. /**
  108. * {@inheritDoc}
  109. */
  110. public function fetchNumeric()
  111. {
  112. return $this->stmt->fetch(PDO::FETCH_NUM);
  113. }
  114. /**
  115. * {@inheritDoc}
  116. */
  117. public function fetchAssociative()
  118. {
  119. return $this->stmt->fetch(PDO::FETCH_ASSOC);
  120. }
  121. /**
  122. * {@inheritDoc}
  123. */
  124. public function fetchOne()
  125. {
  126. $row = $this->fetchNumeric();
  127. if ($row === false) {
  128. return false;
  129. }
  130. return $row[0];
  131. }
  132. /**
  133. * {@inheritDoc}
  134. */
  135. public function fetchAllNumeric(): array
  136. {
  137. $rows = [];
  138. while (($row = $this->fetchNumeric()) !== false) {
  139. $rows[] = $row;
  140. }
  141. return $rows;
  142. }
  143. /**
  144. * {@inheritDoc}
  145. */
  146. public function fetchAllAssociative(): array
  147. {
  148. $rows = [];
  149. while (($row = $this->fetchAssociative()) !== false) {
  150. $rows[] = $row;
  151. }
  152. return $rows;
  153. }
  154. /**
  155. * {@inheritDoc}
  156. */
  157. public function fetchAllKeyValue(): array
  158. {
  159. $this->ensureHasKeyValue();
  160. $data = [];
  161. foreach ($this->fetchAllNumeric() as [$key, $value]) {
  162. $data[$key] = $value;
  163. }
  164. return $data;
  165. }
  166. /**
  167. * {@inheritDoc}
  168. */
  169. public function fetchAllAssociativeIndexed(): array
  170. {
  171. $data = [];
  172. foreach ($this->fetchAllAssociative() as $row) {
  173. $data[array_shift($row)] = $row;
  174. }
  175. return $data;
  176. }
  177. /**
  178. * {@inheritDoc}
  179. */
  180. public function fetchFirstColumn(): array
  181. {
  182. $rows = [];
  183. while (($row = $this->fetchOne()) !== false) {
  184. $rows[] = $row;
  185. }
  186. return $rows;
  187. }
  188. /**
  189. * {@inheritdoc}
  190. *
  191. * @return Traversable<int,array<int,mixed>>
  192. */
  193. public function iterateNumeric(): Traversable
  194. {
  195. while (($row = $this->fetchNumeric()) !== false) {
  196. yield $row;
  197. }
  198. }
  199. /**
  200. * {@inheritDoc}
  201. *
  202. * @return Traversable<int,array<string,mixed>>
  203. */
  204. public function iterateAssociative(): Traversable
  205. {
  206. while (($row = $this->fetchAssociative()) !== false) {
  207. yield $row;
  208. }
  209. }
  210. /**
  211. * {@inheritDoc}
  212. *
  213. * @return Traversable<mixed,mixed>
  214. */
  215. public function iterateKeyValue(): Traversable
  216. {
  217. $this->ensureHasKeyValue();
  218. foreach ($this->iterateNumeric() as [$key, $value]) {
  219. yield $key => $value;
  220. }
  221. }
  222. /**
  223. * {@inheritDoc}
  224. *
  225. * @return Traversable<mixed,array<string,mixed>>
  226. */
  227. public function iterateAssociativeIndexed(): Traversable
  228. {
  229. foreach ($this->iterateAssociative() as $row) {
  230. yield array_shift($row) => $row;
  231. }
  232. }
  233. /**
  234. * {@inheritDoc}
  235. *
  236. * @return Traversable<int,mixed>
  237. */
  238. public function iterateColumn(): Traversable
  239. {
  240. while (($value = $this->fetchOne()) !== false) {
  241. yield $value;
  242. }
  243. }
  244. /**
  245. * {@inheritDoc}
  246. */
  247. public function rowCount()
  248. {
  249. if (method_exists($this->stmt, 'rowCount')) {
  250. return $this->stmt->rowCount();
  251. }
  252. throw Exception::notSupported('rowCount');
  253. }
  254. public function free(): void
  255. {
  256. $this->closeCursor();
  257. }
  258. private function ensureHasKeyValue(): void
  259. {
  260. $columnCount = $this->columnCount();
  261. if ($columnCount < 2) {
  262. throw NoKeyValue::fromColumnCount($columnCount);
  263. }
  264. }
  265. /**
  266. * {@inheritDoc}
  267. *
  268. * @deprecated This feature will no longer be available on Result object in 3.0.x version.
  269. */
  270. public function bindValue($param, $value, $type = ParameterType::STRING)
  271. {
  272. Deprecation::triggerIfCalledFromOutside(
  273. 'doctrine/dbal',
  274. 'https://github.com/doctrine/dbal/pull/4019',
  275. 'Result::bindValue() is deprecated, no replacement.'
  276. );
  277. if ($this->stmt instanceof Driver\Statement) {
  278. return $this->stmt->bindValue($param, $value, $type);
  279. }
  280. throw Exception::notSupported('bindValue');
  281. }
  282. /**
  283. * {@inheritDoc}
  284. *
  285. * @deprecated This feature will no longer be available on Result object in 3.0.x version.
  286. */
  287. public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null)
  288. {
  289. Deprecation::triggerIfCalledFromOutside(
  290. 'doctrine/dbal',
  291. 'https://github.com/doctrine/dbal/pull/4019',
  292. 'Result::bindParam() is deprecated, no replacement.'
  293. );
  294. if ($this->stmt instanceof Driver\Statement) {
  295. return $this->stmt->bindParam($param, $variable, $type, $length);
  296. }
  297. throw Exception::notSupported('bindParam');
  298. }
  299. /**
  300. * {@inheritDoc}
  301. *
  302. * @deprecated The error information is available via exceptions.
  303. */
  304. public function errorCode()
  305. {
  306. Deprecation::triggerIfCalledFromOutside(
  307. 'doctrine/dbal',
  308. 'https://github.com/doctrine/dbal/pull/4019',
  309. 'Result::errorCode() is deprecated, the error information is available via exceptions.'
  310. );
  311. if ($this->stmt instanceof Driver\Statement) {
  312. return $this->stmt->errorCode();
  313. }
  314. throw Exception::notSupported('errorCode');
  315. }
  316. /**
  317. * {@inheritDoc}
  318. *
  319. * @deprecated The error information is available via exceptions.
  320. */
  321. public function errorInfo()
  322. {
  323. Deprecation::triggerIfCalledFromOutside(
  324. 'doctrine/dbal',
  325. 'https://github.com/doctrine/dbal/pull/4019',
  326. 'Result::errorInfo() is deprecated, the error information is available via exceptions.'
  327. );
  328. if ($this->stmt instanceof Driver\Statement) {
  329. return $this->stmt->errorInfo();
  330. }
  331. throw Exception::notSupported('errorInfo');
  332. }
  333. /**
  334. * {@inheritDoc}
  335. *
  336. * @deprecated This feature will no longer be available on Result object in 3.0.x version.
  337. */
  338. public function execute($params = null)
  339. {
  340. Deprecation::triggerIfCalledFromOutside(
  341. 'doctrine/dbal',
  342. 'https://github.com/doctrine/dbal/pull/4019',
  343. 'Result::execute() is deprecated, no replacement.'
  344. );
  345. if ($this->stmt instanceof Driver\Statement) {
  346. return $this->stmt->execute($params);
  347. }
  348. throw Exception::notSupported('execute');
  349. }
  350. }