Statement.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <?php
  2. namespace Doctrine\DBAL;
  3. use Doctrine\DBAL\Driver\Statement as DriverStatement;
  4. use Doctrine\DBAL\Platforms\AbstractPlatform;
  5. use Doctrine\DBAL\Types\Type;
  6. use IteratorAggregate;
  7. use PDO;
  8. use Throwable;
  9. use function is_array;
  10. use function is_string;
  11. /**
  12. * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
  13. * for logging, DBAL mapping types, etc.
  14. */
  15. class Statement implements IteratorAggregate, DriverStatement
  16. {
  17. /**
  18. * The SQL statement.
  19. *
  20. * @var string
  21. */
  22. protected $sql;
  23. /**
  24. * The bound parameters.
  25. *
  26. * @var mixed[]
  27. */
  28. protected $params = [];
  29. /**
  30. * The parameter types.
  31. *
  32. * @var int[]|string[]
  33. */
  34. protected $types = [];
  35. /**
  36. * The underlying driver statement.
  37. *
  38. * @var \Doctrine\DBAL\Driver\Statement
  39. */
  40. protected $stmt;
  41. /**
  42. * The underlying database platform.
  43. *
  44. * @var AbstractPlatform
  45. */
  46. protected $platform;
  47. /**
  48. * The connection this statement is bound to and executed on.
  49. *
  50. * @var Connection
  51. */
  52. protected $conn;
  53. /**
  54. * Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>.
  55. *
  56. * @param string $sql The SQL of the statement.
  57. * @param Connection $conn The connection on which the statement should be executed.
  58. */
  59. public function __construct($sql, Connection $conn)
  60. {
  61. $this->sql = $sql;
  62. $this->stmt = $conn->getWrappedConnection()->prepare($sql);
  63. $this->conn = $conn;
  64. $this->platform = $conn->getDatabasePlatform();
  65. }
  66. /**
  67. * Binds a parameter value to the statement.
  68. *
  69. * The value can optionally be bound with a PDO binding type or a DBAL mapping type.
  70. * If bound with a DBAL mapping type, the binding type is derived from the mapping
  71. * type and the value undergoes the conversion routines of the mapping type before
  72. * being bound.
  73. *
  74. * @param string|int $name The name or position of the parameter.
  75. * @param mixed $value The value of the parameter.
  76. * @param mixed $type Either a PDO binding type or a DBAL mapping type name or instance.
  77. *
  78. * @return bool TRUE on success, FALSE on failure.
  79. */
  80. public function bindValue($name, $value, $type = ParameterType::STRING)
  81. {
  82. $this->params[$name] = $value;
  83. $this->types[$name] = $type;
  84. if ($type !== null) {
  85. if (is_string($type)) {
  86. $type = Type::getType($type);
  87. }
  88. if ($type instanceof Type) {
  89. $value = $type->convertToDatabaseValue($value, $this->platform);
  90. $bindingType = $type->getBindingType();
  91. } else {
  92. $bindingType = $type;
  93. }
  94. return $this->stmt->bindValue($name, $value, $bindingType);
  95. }
  96. return $this->stmt->bindValue($name, $value);
  97. }
  98. /**
  99. * Binds a parameter to a value by reference.
  100. *
  101. * Binding a parameter by reference does not support DBAL mapping types.
  102. *
  103. * @param string|int $name The name or position of the parameter.
  104. * @param mixed $var The reference to the variable to bind.
  105. * @param int $type The PDO binding type.
  106. * @param int|null $length Must be specified when using an OUT bind
  107. * so that PHP allocates enough memory to hold the returned value.
  108. *
  109. * @return bool TRUE on success, FALSE on failure.
  110. */
  111. public function bindParam($name, &$var, $type = ParameterType::STRING, $length = null)
  112. {
  113. $this->params[$name] = $var;
  114. $this->types[$name] = $type;
  115. return $this->stmt->bindParam($name, $var, $type, $length);
  116. }
  117. /**
  118. * Executes the statement with the currently bound parameters.
  119. *
  120. * @param mixed[]|null $params
  121. *
  122. * @return bool TRUE on success, FALSE on failure.
  123. *
  124. * @throws DBALException
  125. */
  126. public function execute($params = null)
  127. {
  128. if (is_array($params)) {
  129. $this->params = $params;
  130. }
  131. $logger = $this->conn->getConfiguration()->getSQLLogger();
  132. if ($logger) {
  133. $logger->startQuery($this->sql, $this->params, $this->types);
  134. }
  135. try {
  136. $stmt = $this->stmt->execute($params);
  137. } catch (Throwable $ex) {
  138. if ($logger) {
  139. $logger->stopQuery();
  140. }
  141. throw DBALException::driverExceptionDuringQuery(
  142. $this->conn->getDriver(),
  143. $ex,
  144. $this->sql,
  145. $this->conn->resolveParams($this->params, $this->types)
  146. );
  147. }
  148. if ($logger) {
  149. $logger->stopQuery();
  150. }
  151. $this->params = [];
  152. $this->types = [];
  153. return $stmt;
  154. }
  155. /**
  156. * Closes the cursor, freeing the database resources used by this statement.
  157. *
  158. * @return bool TRUE on success, FALSE on failure.
  159. */
  160. public function closeCursor()
  161. {
  162. return $this->stmt->closeCursor();
  163. }
  164. /**
  165. * Returns the number of columns in the result set.
  166. *
  167. * @return int
  168. */
  169. public function columnCount()
  170. {
  171. return $this->stmt->columnCount();
  172. }
  173. /**
  174. * Fetches the SQLSTATE associated with the last operation on the statement.
  175. *
  176. * @return string|int|bool
  177. */
  178. public function errorCode()
  179. {
  180. return $this->stmt->errorCode();
  181. }
  182. /**
  183. * {@inheritDoc}
  184. */
  185. public function errorInfo()
  186. {
  187. return $this->stmt->errorInfo();
  188. }
  189. /**
  190. * {@inheritdoc}
  191. */
  192. public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
  193. {
  194. if ($arg2 === null) {
  195. return $this->stmt->setFetchMode($fetchMode);
  196. } elseif ($arg3 === null) {
  197. return $this->stmt->setFetchMode($fetchMode, $arg2);
  198. }
  199. return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3);
  200. }
  201. /**
  202. * Required by interface IteratorAggregate.
  203. *
  204. * {@inheritdoc}
  205. */
  206. public function getIterator()
  207. {
  208. return $this->stmt;
  209. }
  210. /**
  211. * {@inheritdoc}
  212. */
  213. public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
  214. {
  215. return $this->stmt->fetch($fetchMode);
  216. }
  217. /**
  218. * {@inheritdoc}
  219. */
  220. public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
  221. {
  222. if ($fetchArgument) {
  223. return $this->stmt->fetchAll($fetchMode, $fetchArgument);
  224. }
  225. return $this->stmt->fetchAll($fetchMode);
  226. }
  227. /**
  228. * {@inheritDoc}
  229. */
  230. public function fetchColumn($columnIndex = 0)
  231. {
  232. return $this->stmt->fetchColumn($columnIndex);
  233. }
  234. /**
  235. * Returns the number of rows affected by the last execution of this statement.
  236. *
  237. * @return int The number of affected rows.
  238. */
  239. public function rowCount()
  240. {
  241. return $this->stmt->rowCount();
  242. }
  243. /**
  244. * Gets the wrapped driver statement.
  245. *
  246. * @return \Doctrine\DBAL\Driver\Statement
  247. */
  248. public function getWrappedStatement()
  249. {
  250. return $this->stmt;
  251. }
  252. }