PDOStatement.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. namespace Doctrine\DBAL\Driver;
  3. use Doctrine\DBAL\FetchMode;
  4. use Doctrine\DBAL\ParameterType;
  5. use PDO;
  6. use const E_USER_DEPRECATED;
  7. use function sprintf;
  8. use function trigger_error;
  9. /**
  10. * The PDO implementation of the Statement interface.
  11. * Used by all PDO-based drivers.
  12. */
  13. class PDOStatement extends \PDOStatement implements Statement
  14. {
  15. private const PARAM_TYPE_MAP = [
  16. ParameterType::NULL => PDO::PARAM_NULL,
  17. ParameterType::INTEGER => PDO::PARAM_INT,
  18. ParameterType::STRING => PDO::PARAM_STR,
  19. ParameterType::BINARY => PDO::PARAM_LOB,
  20. ParameterType::LARGE_OBJECT => PDO::PARAM_LOB,
  21. ParameterType::BOOLEAN => PDO::PARAM_BOOL,
  22. ];
  23. private const FETCH_MODE_MAP = [
  24. FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC,
  25. FetchMode::NUMERIC => PDO::FETCH_NUM,
  26. FetchMode::MIXED => PDO::FETCH_BOTH,
  27. FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ,
  28. FetchMode::COLUMN => PDO::FETCH_COLUMN,
  29. FetchMode::CUSTOM_OBJECT => PDO::FETCH_CLASS,
  30. ];
  31. /**
  32. * Protected constructor.
  33. */
  34. protected function __construct()
  35. {
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
  41. {
  42. $fetchMode = $this->convertFetchMode($fetchMode);
  43. // This thin wrapper is necessary to shield against the weird signature
  44. // of PDOStatement::setFetchMode(): even if the second and third
  45. // parameters are optional, PHP will not let us remove it from this
  46. // declaration.
  47. try {
  48. if ($arg2 === null && $arg3 === null) {
  49. return parent::setFetchMode($fetchMode);
  50. }
  51. if ($arg3 === null) {
  52. return parent::setFetchMode($fetchMode, $arg2);
  53. }
  54. return parent::setFetchMode($fetchMode, $arg2, $arg3);
  55. } catch (\PDOException $exception) {
  56. throw new PDOException($exception);
  57. }
  58. }
  59. /**
  60. * {@inheritdoc}
  61. */
  62. public function bindValue($param, $value, $type = ParameterType::STRING)
  63. {
  64. $type = $this->convertParamType($type);
  65. try {
  66. return parent::bindValue($param, $value, $type);
  67. } catch (\PDOException $exception) {
  68. throw new PDOException($exception);
  69. }
  70. }
  71. /**
  72. * {@inheritdoc}
  73. */
  74. public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null)
  75. {
  76. $type = $this->convertParamType($type);
  77. try {
  78. return parent::bindParam($column, $variable, $type, $length, $driverOptions);
  79. } catch (\PDOException $exception) {
  80. throw new PDOException($exception);
  81. }
  82. }
  83. /**
  84. * {@inheritdoc}
  85. */
  86. public function closeCursor()
  87. {
  88. try {
  89. return parent::closeCursor();
  90. } catch (\PDOException $exception) {
  91. // Exceptions not allowed by the interface.
  92. // In case driver implementations do not adhere to the interface, silence exceptions here.
  93. return true;
  94. }
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. public function execute($params = null)
  100. {
  101. try {
  102. return parent::execute($params);
  103. } catch (\PDOException $exception) {
  104. throw new PDOException($exception);
  105. }
  106. }
  107. /**
  108. * {@inheritdoc}
  109. */
  110. public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
  111. {
  112. $fetchMode = $this->convertFetchMode($fetchMode);
  113. try {
  114. if ($fetchMode === null && $cursorOrientation === PDO::FETCH_ORI_NEXT && $cursorOffset === 0) {
  115. return parent::fetch();
  116. }
  117. if ($cursorOrientation === PDO::FETCH_ORI_NEXT && $cursorOffset === 0) {
  118. return parent::fetch($fetchMode);
  119. }
  120. if ($cursorOffset === 0) {
  121. return parent::fetch($fetchMode, $cursorOrientation);
  122. }
  123. return parent::fetch($fetchMode, $cursorOrientation, $cursorOffset);
  124. } catch (\PDOException $exception) {
  125. throw new PDOException($exception);
  126. }
  127. }
  128. /**
  129. * {@inheritdoc}
  130. */
  131. public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
  132. {
  133. $fetchMode = $this->convertFetchMode($fetchMode);
  134. try {
  135. if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) {
  136. return parent::fetchAll();
  137. }
  138. if ($fetchArgument === null && $ctorArgs === null) {
  139. return parent::fetchAll($fetchMode);
  140. }
  141. if ($ctorArgs === null) {
  142. return parent::fetchAll($fetchMode, $fetchArgument);
  143. }
  144. return parent::fetchAll($fetchMode, $fetchArgument, $ctorArgs);
  145. } catch (\PDOException $exception) {
  146. throw new PDOException($exception);
  147. }
  148. }
  149. /**
  150. * {@inheritdoc}
  151. */
  152. public function fetchColumn($columnIndex = 0)
  153. {
  154. try {
  155. return parent::fetchColumn($columnIndex);
  156. } catch (\PDOException $exception) {
  157. throw new PDOException($exception);
  158. }
  159. }
  160. /**
  161. * Converts DBAL parameter type to PDO parameter type
  162. *
  163. * @param int $type Parameter type
  164. */
  165. private function convertParamType(int $type) : int
  166. {
  167. if (! isset(self::PARAM_TYPE_MAP[$type])) {
  168. // TODO: next major: throw an exception
  169. @trigger_error(sprintf(
  170. 'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0',
  171. $type
  172. ), E_USER_DEPRECATED);
  173. return $type;
  174. }
  175. return self::PARAM_TYPE_MAP[$type];
  176. }
  177. /**
  178. * Converts DBAL fetch mode to PDO fetch mode
  179. *
  180. * @param int|null $fetchMode Fetch mode
  181. */
  182. private function convertFetchMode(?int $fetchMode) : ?int
  183. {
  184. if ($fetchMode === null) {
  185. return null;
  186. }
  187. if (! isset(self::FETCH_MODE_MAP[$fetchMode])) {
  188. // TODO: next major: throw an exception
  189. @trigger_error(sprintf(
  190. 'Using a PDO fetch mode or their combination (%d given)' .
  191. ' is deprecated and will cause an error in Doctrine 3.0',
  192. $fetchMode
  193. ), E_USER_DEPRECATED);
  194. return $fetchMode;
  195. }
  196. return self::FETCH_MODE_MAP[$fetchMode];
  197. }
  198. }