PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/concrete/libraries/3rdparty/Zend/Db/Statement.php

https://bitbucket.org/selfeky/xclusivescardwebsite
PHP | 488 lines | 219 code | 42 blank | 227 comment | 37 complexity | cd789eefed21b6b2b71f5ed9a5b6e194 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Db
  17. * @subpackage Statement
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Statement.php 24790 2012-05-10 12:28:51Z mcleod@spaceweb.nl $
  21. */
  22. /**
  23. * @see Zend_Db
  24. */
  25. require_once 'Zend/Db.php';
  26. /**
  27. * @see Zend_Db_Statement_Interface
  28. */
  29. require_once 'Zend/Db/Statement/Interface.php';
  30. /**
  31. * Abstract class to emulate a PDOStatement for native database adapters.
  32. *
  33. * @category Zend
  34. * @package Zend_Db
  35. * @subpackage Statement
  36. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  37. * @license http://framework.zend.com/license/new-bsd New BSD License
  38. */
  39. abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
  40. {
  41. /**
  42. * @var resource|object The driver level statement object/resource
  43. */
  44. protected $_stmt = null;
  45. /**
  46. * @var Zend_Db_Adapter_Abstract
  47. */
  48. protected $_adapter = null;
  49. /**
  50. * The current fetch mode.
  51. *
  52. * @var integer
  53. */
  54. protected $_fetchMode = Zend_Db::FETCH_ASSOC;
  55. /**
  56. * Attributes.
  57. *
  58. * @var array
  59. */
  60. protected $_attribute = array();
  61. /**
  62. * Column result bindings.
  63. *
  64. * @var array
  65. */
  66. protected $_bindColumn = array();
  67. /**
  68. * Query parameter bindings; covers bindParam() and bindValue().
  69. *
  70. * @var array
  71. */
  72. protected $_bindParam = array();
  73. /**
  74. * SQL string split into an array at placeholders.
  75. *
  76. * @var array
  77. */
  78. protected $_sqlSplit = array();
  79. /**
  80. * Parameter placeholders in the SQL string by position in the split array.
  81. *
  82. * @var array
  83. */
  84. protected $_sqlParam = array();
  85. /**
  86. * @var Zend_Db_Profiler_Query
  87. */
  88. protected $_queryId = null;
  89. /**
  90. * Constructor for a statement.
  91. *
  92. * @param Zend_Db_Adapter_Abstract $adapter
  93. * @param mixed $sql Either a string or Zend_Db_Select.
  94. */
  95. public function __construct($adapter, $sql)
  96. {
  97. $this->_adapter = $adapter;
  98. if ($sql instanceof Zend_Db_Select) {
  99. $sql = $sql->assemble();
  100. }
  101. $this->_parseParameters($sql);
  102. $this->_prepare($sql);
  103. $this->_queryId = $this->_adapter->getProfiler()->queryStart($sql);
  104. }
  105. /**
  106. * Internal method called by abstract statment constructor to setup
  107. * the driver level statement
  108. *
  109. * @return void
  110. */
  111. protected function _prepare($sql)
  112. {
  113. return;
  114. }
  115. /**
  116. * @param string $sql
  117. * @return void
  118. */
  119. protected function _parseParameters($sql)
  120. {
  121. $sql = $this->_stripQuoted($sql);
  122. // split into text and params
  123. $this->_sqlSplit = preg_split('/(\?|\:[a-zA-Z0-9_]+)/',
  124. $sql, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
  125. // map params
  126. $this->_sqlParam = array();
  127. foreach ($this->_sqlSplit as $key => $val) {
  128. if ($val == '?') {
  129. if ($this->_adapter->supportsParameters('positional') === false) {
  130. /**
  131. * @see Zend_Db_Statement_Exception
  132. */
  133. require_once 'Zend/Db/Statement/Exception.php';
  134. throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$val'");
  135. }
  136. } else if ($val[0] == ':') {
  137. if ($this->_adapter->supportsParameters('named') === false) {
  138. /**
  139. * @see Zend_Db_Statement_Exception
  140. */
  141. require_once 'Zend/Db/Statement/Exception.php';
  142. throw new Zend_Db_Statement_Exception("Invalid bind-variable name '$val'");
  143. }
  144. }
  145. $this->_sqlParam[] = $val;
  146. }
  147. // set up for binding
  148. $this->_bindParam = array();
  149. }
  150. /**
  151. * Remove parts of a SQL string that contain quoted strings
  152. * of values or identifiers.
  153. *
  154. * @param string $sql
  155. * @return string
  156. */
  157. protected function _stripQuoted($sql)
  158. {
  159. // get the character for value quoting
  160. // this should be '
  161. $q = $this->_adapter->quote('a');
  162. $q = $q[0];
  163. // get the value used as an escaped quote,
  164. // e.g. \' or ''
  165. $qe = $this->_adapter->quote($q);
  166. $qe = substr($qe, 1, 2);
  167. $qe = preg_quote($qe);
  168. $escapeChar = substr($qe,0,1);
  169. // remove 'foo\'bar'
  170. if (!empty($q)) {
  171. $escapeChar = preg_quote($escapeChar);
  172. // this segfaults only after 65,000 characters instead of 9,000
  173. $sql = preg_replace("/$q([^$q{$escapeChar}]*|($qe)*)*$q/s", '', $sql);
  174. }
  175. // get a version of the SQL statement with all quoted
  176. // values and delimited identifiers stripped out
  177. // remove "foo\"bar"
  178. $sql = preg_replace("/\"(\\\\\"|[^\"])*\"/Us", '', $sql);
  179. // get the character for delimited id quotes,
  180. // this is usually " but in MySQL is `
  181. $d = $this->_adapter->quoteIdentifier('a');
  182. $d = $d[0];
  183. // get the value used as an escaped delimited id quote,
  184. // e.g. \" or "" or \`
  185. $de = $this->_adapter->quoteIdentifier($d);
  186. $de = substr($de, 1, 2);
  187. $de = preg_quote($de);
  188. // Note: $de and $d where never used..., now they are:
  189. $sql = preg_replace("/$d($de|\\\\{2}|[^$d])*$d/Us", '', $sql);
  190. return $sql;
  191. }
  192. /**
  193. * Bind a column of the statement result set to a PHP variable.
  194. *
  195. * @param string $column Name the column in the result set, either by
  196. * position or by name.
  197. * @param mixed $param Reference to the PHP variable containing the value.
  198. * @param mixed $type OPTIONAL
  199. * @return bool
  200. */
  201. public function bindColumn($column, &$param, $type = null)
  202. {
  203. $this->_bindColumn[$column] =& $param;
  204. return true;
  205. }
  206. /**
  207. * Binds a parameter to the specified variable name.
  208. *
  209. * @param mixed $parameter Name the parameter, either integer or string.
  210. * @param mixed $variable Reference to PHP variable containing the value.
  211. * @param mixed $type OPTIONAL Datatype of SQL parameter.
  212. * @param mixed $length OPTIONAL Length of SQL parameter.
  213. * @param mixed $options OPTIONAL Other options.
  214. * @return bool
  215. */
  216. public function bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
  217. {
  218. if (!is_int($parameter) && !is_string($parameter)) {
  219. /**
  220. * @see Zend_Db_Statement_Exception
  221. */
  222. require_once 'Zend/Db/Statement/Exception.php';
  223. throw new Zend_Db_Statement_Exception('Invalid bind-variable position');
  224. }
  225. $position = null;
  226. if (($intval = (int) $parameter) > 0 && $this->_adapter->supportsParameters('positional')) {
  227. if ($intval >= 1 || $intval <= count($this->_sqlParam)) {
  228. $position = $intval;
  229. }
  230. } else if ($this->_adapter->supportsParameters('named')) {
  231. if ($parameter[0] != ':') {
  232. $parameter = ':' . $parameter;
  233. }
  234. if (in_array($parameter, $this->_sqlParam) !== false) {
  235. $position = $parameter;
  236. }
  237. }
  238. if ($position === null) {
  239. /**
  240. * @see Zend_Db_Statement_Exception
  241. */
  242. require_once 'Zend/Db/Statement/Exception.php';
  243. throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$parameter'");
  244. }
  245. // Finally we are assured that $position is valid
  246. $this->_bindParam[$position] =& $variable;
  247. return $this->_bindParam($position, $variable, $type, $length, $options);
  248. }
  249. /**
  250. * Binds a value to a parameter.
  251. *
  252. * @param mixed $parameter Name the parameter, either integer or string.
  253. * @param mixed $value Scalar value to bind to the parameter.
  254. * @param mixed $type OPTIONAL Datatype of the parameter.
  255. * @return bool
  256. */
  257. public function bindValue($parameter, $value, $type = null)
  258. {
  259. return $this->bindParam($parameter, $value, $type);
  260. }
  261. /**
  262. * Executes a prepared statement.
  263. *
  264. * @param array $params OPTIONAL Values to bind to parameter placeholders.
  265. * @return bool
  266. */
  267. public function execute(array $params = null)
  268. {
  269. /*
  270. * Simple case - no query profiler to manage.
  271. */
  272. if ($this->_queryId === null) {
  273. return $this->_execute($params);
  274. }
  275. /*
  276. * Do the same thing, but with query profiler
  277. * management before and after the execute.
  278. */
  279. $prof = $this->_adapter->getProfiler();
  280. $qp = $prof->getQueryProfile($this->_queryId);
  281. if ($qp->hasEnded()) {
  282. $this->_queryId = $prof->queryClone($qp);
  283. $qp = $prof->getQueryProfile($this->_queryId);
  284. }
  285. if ($params !== null) {
  286. $qp->bindParams($params);
  287. } else {
  288. $qp->bindParams($this->_bindParam);
  289. }
  290. $qp->start($this->_queryId);
  291. $retval = $this->_execute($params);
  292. $prof->queryEnd($this->_queryId);
  293. return $retval;
  294. }
  295. /**
  296. * Returns an array containing all of the result set rows.
  297. *
  298. * @param int $style OPTIONAL Fetch mode.
  299. * @param int $col OPTIONAL Column number, if fetch mode is by column.
  300. * @return array Collection of rows, each in a format by the fetch mode.
  301. */
  302. public function fetchAll($style = null, $col = null)
  303. {
  304. $data = array();
  305. if ($style === Zend_Db::FETCH_COLUMN && $col === null) {
  306. $col = 0;
  307. }
  308. if ($col === null) {
  309. while ($row = $this->fetch($style)) {
  310. $data[] = $row;
  311. }
  312. } else {
  313. while (false !== ($val = $this->fetchColumn($col))) {
  314. $data[] = $val;
  315. }
  316. }
  317. return $data;
  318. }
  319. /**
  320. * Returns a single column from the next row of a result set.
  321. *
  322. * @param int $col OPTIONAL Position of the column to fetch.
  323. * @return string One value from the next row of result set, or false.
  324. */
  325. public function fetchColumn($col = 0)
  326. {
  327. $data = array();
  328. $col = (int) $col;
  329. $row = $this->fetch(Zend_Db::FETCH_NUM);
  330. if (!is_array($row)) {
  331. return false;
  332. }
  333. return $row[$col];
  334. }
  335. /**
  336. * Fetches the next row and returns it as an object.
  337. *
  338. * @param string $class OPTIONAL Name of the class to create.
  339. * @param array $config OPTIONAL Constructor arguments for the class.
  340. * @return mixed One object instance of the specified class, or false.
  341. */
  342. public function fetchObject($class = 'stdClass', array $config = array())
  343. {
  344. $obj = new $class($config);
  345. $row = $this->fetch(Zend_Db::FETCH_ASSOC);
  346. if (!is_array($row)) {
  347. return false;
  348. }
  349. foreach ($row as $key => $val) {
  350. $obj->$key = $val;
  351. }
  352. return $obj;
  353. }
  354. /**
  355. * Retrieve a statement attribute.
  356. *
  357. * @param string $key Attribute name.
  358. * @return mixed Attribute value.
  359. */
  360. public function getAttribute($key)
  361. {
  362. if (array_key_exists($key, $this->_attribute)) {
  363. return $this->_attribute[$key];
  364. }
  365. }
  366. /**
  367. * Set a statement attribute.
  368. *
  369. * @param string $key Attribute name.
  370. * @param mixed $val Attribute value.
  371. * @return bool
  372. */
  373. public function setAttribute($key, $val)
  374. {
  375. $this->_attribute[$key] = $val;
  376. }
  377. /**
  378. * Set the default fetch mode for this statement.
  379. *
  380. * @param int $mode The fetch mode.
  381. * @return bool
  382. * @throws Zend_Db_Statement_Exception
  383. */
  384. public function setFetchMode($mode)
  385. {
  386. switch ($mode) {
  387. case Zend_Db::FETCH_NUM:
  388. case Zend_Db::FETCH_ASSOC:
  389. case Zend_Db::FETCH_BOTH:
  390. case Zend_Db::FETCH_OBJ:
  391. $this->_fetchMode = $mode;
  392. break;
  393. case Zend_Db::FETCH_BOUND:
  394. default:
  395. $this->closeCursor();
  396. /**
  397. * @see Zend_Db_Statement_Exception
  398. */
  399. require_once 'Zend/Db/Statement/Exception.php';
  400. throw new Zend_Db_Statement_Exception('invalid fetch mode');
  401. break;
  402. }
  403. }
  404. /**
  405. * Helper function to map retrieved row
  406. * to bound column variables
  407. *
  408. * @param array $row
  409. * @return bool True
  410. */
  411. public function _fetchBound($row)
  412. {
  413. foreach ($row as $key => $value) {
  414. // bindColumn() takes 1-based integer positions
  415. // but fetch() returns 0-based integer indexes
  416. if (is_int($key)) {
  417. $key++;
  418. }
  419. // set results only to variables that were bound previously
  420. if (isset($this->_bindColumn[$key])) {
  421. $this->_bindColumn[$key] = $value;
  422. }
  423. }
  424. return true;
  425. }
  426. /**
  427. * Gets the Zend_Db_Adapter_Abstract for this
  428. * particular Zend_Db_Statement object.
  429. *
  430. * @return Zend_Db_Adapter_Abstract
  431. */
  432. public function getAdapter()
  433. {
  434. return $this->_adapter;
  435. }
  436. /**
  437. * Gets the resource or object setup by the
  438. * _parse
  439. * @return unknown_type
  440. */
  441. public function getDriverStatement()
  442. {
  443. return $this->_stmt;
  444. }
  445. }