/library/Zend/Db/Adapter/Driver/Pdo/Statement.php

https://github.com/cgmartin/zf2 · PHP · 311 lines · 161 code · 42 blank · 108 comment · 19 complexity · 9fdeb8362abc778009230769f772aefb MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Db\Adapter\Driver\Pdo;
  10. use Zend\Db\Adapter\Driver\StatementInterface;
  11. use Zend\Db\Adapter\Exception;
  12. use Zend\Db\Adapter\ParameterContainer;
  13. use Zend\Db\Adapter\Profiler;
  14. class Statement implements StatementInterface, Profiler\ProfilerAwareInterface
  15. {
  16. /**
  17. * @var \PDO
  18. */
  19. protected $pdo = null;
  20. /**
  21. * @var Profiler\ProfilerInterface
  22. */
  23. protected $profiler = null;
  24. /**
  25. * @var Pdo
  26. */
  27. protected $driver = null;
  28. /**
  29. *
  30. * @var string
  31. */
  32. protected $sql = '';
  33. /**
  34. *
  35. * @var bool
  36. */
  37. protected $isQuery = null;
  38. /**
  39. *
  40. * @var ParameterContainer
  41. */
  42. protected $parameterContainer = null;
  43. /**
  44. * @var bool
  45. */
  46. protected $parametersBound = false;
  47. /**
  48. * @var \PDOStatement
  49. */
  50. protected $resource = null;
  51. /**
  52. *
  53. * @var bool
  54. */
  55. protected $isPrepared = false;
  56. /**
  57. * Set driver
  58. *
  59. * @param Pdo $driver
  60. * @return Statement
  61. */
  62. public function setDriver(Pdo $driver)
  63. {
  64. $this->driver = $driver;
  65. return $this;
  66. }
  67. /**
  68. * @param Profiler\ProfilerInterface $profiler
  69. * @return Statement
  70. */
  71. public function setProfiler(Profiler\ProfilerInterface $profiler)
  72. {
  73. $this->profiler = $profiler;
  74. return $this;
  75. }
  76. /**
  77. * @return null|Profiler\ProfilerInterface
  78. */
  79. public function getProfiler()
  80. {
  81. return $this->profiler;
  82. }
  83. /**
  84. * Initialize
  85. *
  86. * @param \PDO $connectionResource
  87. * @return Statement
  88. */
  89. public function initialize(\PDO $connectionResource)
  90. {
  91. $this->pdo = $connectionResource;
  92. return $this;
  93. }
  94. /**
  95. * Set resource
  96. *
  97. * @param \PDOStatement $pdoStatement
  98. * @return Statement
  99. */
  100. public function setResource(\PDOStatement $pdoStatement)
  101. {
  102. $this->resource = $pdoStatement;
  103. return $this;
  104. }
  105. /**
  106. * Get resource
  107. *
  108. * @return mixed
  109. */
  110. public function getResource()
  111. {
  112. return $this->resource;
  113. }
  114. /**
  115. * Set sql
  116. *
  117. * @param string $sql
  118. * @return Statement
  119. */
  120. public function setSql($sql)
  121. {
  122. $this->sql = $sql;
  123. return $this;
  124. }
  125. /**
  126. * Get sql
  127. *
  128. * @return string
  129. */
  130. public function getSql()
  131. {
  132. return $this->sql;
  133. }
  134. /**
  135. * @param ParameterContainer $parameterContainer
  136. * @return Statement
  137. */
  138. public function setParameterContainer(ParameterContainer $parameterContainer)
  139. {
  140. $this->parameterContainer = $parameterContainer;
  141. return $this;
  142. }
  143. /**
  144. * @return ParameterContainer
  145. */
  146. public function getParameterContainer()
  147. {
  148. return $this->parameterContainer;
  149. }
  150. /**
  151. * @param string $sql
  152. * @throws Exception\RuntimeException
  153. */
  154. public function prepare($sql = null)
  155. {
  156. if ($this->isPrepared) {
  157. throw new Exception\RuntimeException('This statement has been prepared already');
  158. }
  159. if ($sql == null) {
  160. $sql = $this->sql;
  161. }
  162. $this->resource = $this->pdo->prepare($sql);
  163. if ($this->resource === false) {
  164. $error = $this->pdo->errorInfo();
  165. throw new Exception\RuntimeException($error[2]);
  166. }
  167. $this->isPrepared = true;
  168. }
  169. /**
  170. * @return bool
  171. */
  172. public function isPrepared()
  173. {
  174. return $this->isPrepared;
  175. }
  176. /**
  177. * @param mixed $parameters
  178. * @throws Exception\InvalidQueryException
  179. * @return Result
  180. */
  181. public function execute($parameters = null)
  182. {
  183. if (!$this->isPrepared) {
  184. $this->prepare();
  185. }
  186. /** START Standard ParameterContainer Merging Block */
  187. if (!$this->parameterContainer instanceof ParameterContainer) {
  188. if ($parameters instanceof ParameterContainer) {
  189. $this->parameterContainer = $parameters;
  190. $parameters = null;
  191. } else {
  192. $this->parameterContainer = new ParameterContainer();
  193. }
  194. }
  195. if (is_array($parameters)) {
  196. $this->parameterContainer->setFromArray($parameters);
  197. }
  198. if ($this->parameterContainer->count() > 0) {
  199. $this->bindParametersFromContainer();
  200. }
  201. /** END Standard ParameterContainer Merging Block */
  202. if ($this->profiler) {
  203. $this->profiler->profilerStart($this);
  204. }
  205. try {
  206. $this->resource->execute();
  207. } catch (\PDOException $e) {
  208. if ($this->profiler) {
  209. $this->profiler->profilerFinish();
  210. }
  211. throw new Exception\InvalidQueryException(
  212. 'Statement could not be executed (' . implode(' - ', $this->resource->errorInfo()) . ')',
  213. null,
  214. $e
  215. );
  216. }
  217. if ($this->profiler) {
  218. $this->profiler->profilerFinish();
  219. }
  220. $result = $this->driver->createResult($this->resource, $this);
  221. return $result;
  222. }
  223. /**
  224. * Bind parameters from container
  225. */
  226. protected function bindParametersFromContainer()
  227. {
  228. if ($this->parametersBound) {
  229. return;
  230. }
  231. $parameters = $this->parameterContainer->getNamedArray();
  232. foreach ($parameters as $name => &$value) {
  233. if (is_bool($value)) {
  234. $type = \PDO::PARAM_BOOL;
  235. } else {
  236. $type = \PDO::PARAM_STR;
  237. }
  238. if ($this->parameterContainer->offsetHasErrata($name)) {
  239. switch ($this->parameterContainer->offsetGetErrata($name)) {
  240. case ParameterContainer::TYPE_INTEGER:
  241. $type = \PDO::PARAM_INT;
  242. break;
  243. case ParameterContainer::TYPE_NULL:
  244. $type = \PDO::PARAM_NULL;
  245. break;
  246. case ParameterContainer::TYPE_LOB:
  247. $type = \PDO::PARAM_LOB;
  248. break;
  249. }
  250. }
  251. // parameter is named or positional, value is reference
  252. $parameter = is_int($name) ? ($name + 1) : $name;
  253. $this->resource->bindParam($parameter, $value, $type);
  254. }
  255. }
  256. /**
  257. * Perform a deep clone
  258. * @return Statement A cloned statement
  259. */
  260. public function __clone()
  261. {
  262. $this->isPrepared = false;
  263. $this->parametersBound = false;
  264. $this->resource = null;
  265. if ($this->parameterContainer) {
  266. $this->parameterContainer = clone $this->parameterContainer;
  267. }
  268. }
  269. }