PageRenderTime 57ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/concrete/libraries/3rdparty/Zend/Db/Adapter/Mysqli.php

https://bitbucket.org/selfeky/xclusivescardwebsite
PHP | 549 lines | 283 code | 41 blank | 225 comment | 43 complexity | 52affed08328ee926c11fb4b6c07fc34 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 Adapter
  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: Mysqli.php 24593 2012-01-05 20:35:02Z matthew $
  21. */
  22. /**
  23. * @see Zend_Db_Adapter_Abstract
  24. */
  25. require_once 'Zend/Db/Adapter/Abstract.php';
  26. /**
  27. * @see Zend_Db_Profiler
  28. */
  29. require_once 'Zend/Db/Profiler.php';
  30. /**
  31. * @see Zend_Db_Select
  32. */
  33. require_once 'Zend/Db/Select.php';
  34. /**
  35. * @see Zend_Db_Statement_Mysqli
  36. */
  37. require_once 'Zend/Db/Statement/Mysqli.php';
  38. /**
  39. * @category Zend
  40. * @package Zend_Db
  41. * @subpackage Adapter
  42. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  43. * @license http://framework.zend.com/license/new-bsd New BSD License
  44. */
  45. class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
  46. {
  47. /**
  48. * Keys are UPPERCASE SQL datatypes or the constants
  49. * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
  50. *
  51. * Values are:
  52. * 0 = 32-bit integer
  53. * 1 = 64-bit integer
  54. * 2 = float or decimal
  55. *
  56. * @var array Associative array of datatypes to values 0, 1, or 2.
  57. */
  58. protected $_numericDataTypes = array(
  59. Zend_Db::INT_TYPE => Zend_Db::INT_TYPE,
  60. Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE,
  61. Zend_Db::FLOAT_TYPE => Zend_Db::FLOAT_TYPE,
  62. 'INT' => Zend_Db::INT_TYPE,
  63. 'INTEGER' => Zend_Db::INT_TYPE,
  64. 'MEDIUMINT' => Zend_Db::INT_TYPE,
  65. 'SMALLINT' => Zend_Db::INT_TYPE,
  66. 'TINYINT' => Zend_Db::INT_TYPE,
  67. 'BIGINT' => Zend_Db::BIGINT_TYPE,
  68. 'SERIAL' => Zend_Db::BIGINT_TYPE,
  69. 'DEC' => Zend_Db::FLOAT_TYPE,
  70. 'DECIMAL' => Zend_Db::FLOAT_TYPE,
  71. 'DOUBLE' => Zend_Db::FLOAT_TYPE,
  72. 'DOUBLE PRECISION' => Zend_Db::FLOAT_TYPE,
  73. 'FIXED' => Zend_Db::FLOAT_TYPE,
  74. 'FLOAT' => Zend_Db::FLOAT_TYPE
  75. );
  76. /**
  77. * @var Zend_Db_Statement_Mysqli
  78. */
  79. protected $_stmt = null;
  80. /**
  81. * Default class name for a DB statement.
  82. *
  83. * @var string
  84. */
  85. protected $_defaultStmtClass = 'Zend_Db_Statement_Mysqli';
  86. /**
  87. * Quote a raw string.
  88. *
  89. * @param mixed $value Raw string
  90. *
  91. * @return string Quoted string
  92. */
  93. protected function _quote($value)
  94. {
  95. if (is_int($value) || is_float($value)) {
  96. return $value;
  97. }
  98. $this->_connect();
  99. return "'" . $this->_connection->real_escape_string($value) . "'";
  100. }
  101. /**
  102. * Returns the symbol the adapter uses for delimiting identifiers.
  103. *
  104. * @return string
  105. */
  106. public function getQuoteIdentifierSymbol()
  107. {
  108. return "`";
  109. }
  110. /**
  111. * Returns a list of the tables in the database.
  112. *
  113. * @return array
  114. */
  115. public function listTables()
  116. {
  117. $result = array();
  118. // Use mysqli extension API, because SHOW doesn't work
  119. // well as a prepared statement on MySQL 4.1.
  120. $sql = 'SHOW TABLES';
  121. if ($queryResult = $this->getConnection()->query($sql)) {
  122. while ($row = $queryResult->fetch_row()) {
  123. $result[] = $row[0];
  124. }
  125. $queryResult->close();
  126. } else {
  127. /**
  128. * @see Zend_Db_Adapter_Mysqli_Exception
  129. */
  130. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  131. throw new Zend_Db_Adapter_Mysqli_Exception($this->getConnection()->error);
  132. }
  133. return $result;
  134. }
  135. /**
  136. * Returns the column descriptions for a table.
  137. *
  138. * The return value is an associative array keyed by the column name,
  139. * as returned by the RDBMS.
  140. *
  141. * The value of each array element is an associative array
  142. * with the following keys:
  143. *
  144. * SCHEMA_NAME => string; name of database or schema
  145. * TABLE_NAME => string;
  146. * COLUMN_NAME => string; column name
  147. * COLUMN_POSITION => number; ordinal position of column in table
  148. * DATA_TYPE => string; SQL datatype name of column
  149. * DEFAULT => string; default expression of column, null if none
  150. * NULLABLE => boolean; true if column can have nulls
  151. * LENGTH => number; length of CHAR/VARCHAR
  152. * SCALE => number; scale of NUMERIC/DECIMAL
  153. * PRECISION => number; precision of NUMERIC/DECIMAL
  154. * UNSIGNED => boolean; unsigned property of an integer type
  155. * PRIMARY => boolean; true if column is part of the primary key
  156. * PRIMARY_POSITION => integer; position of column in primary key
  157. * IDENTITY => integer; true if column is auto-generated with unique values
  158. *
  159. * @param string $tableName
  160. * @param string $schemaName OPTIONAL
  161. * @return array
  162. */
  163. public function describeTable($tableName, $schemaName = null)
  164. {
  165. /**
  166. * @todo use INFORMATION_SCHEMA someday when
  167. * MySQL's implementation isn't too slow.
  168. */
  169. if ($schemaName) {
  170. $sql = 'DESCRIBE ' . $this->quoteIdentifier("$schemaName.$tableName", true);
  171. } else {
  172. $sql = 'DESCRIBE ' . $this->quoteIdentifier($tableName, true);
  173. }
  174. /**
  175. * Use mysqli extension API, because DESCRIBE doesn't work
  176. * well as a prepared statement on MySQL 4.1.
  177. */
  178. if ($queryResult = $this->getConnection()->query($sql)) {
  179. while ($row = $queryResult->fetch_assoc()) {
  180. $result[] = $row;
  181. }
  182. $queryResult->close();
  183. } else {
  184. /**
  185. * @see Zend_Db_Adapter_Mysqli_Exception
  186. */
  187. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  188. throw new Zend_Db_Adapter_Mysqli_Exception($this->getConnection()->error);
  189. }
  190. $desc = array();
  191. $row_defaults = array(
  192. 'Length' => null,
  193. 'Scale' => null,
  194. 'Precision' => null,
  195. 'Unsigned' => null,
  196. 'Primary' => false,
  197. 'PrimaryPosition' => null,
  198. 'Identity' => false
  199. );
  200. $i = 1;
  201. $p = 1;
  202. foreach ($result as $key => $row) {
  203. $row = array_merge($row_defaults, $row);
  204. if (preg_match('/unsigned/', $row['Type'])) {
  205. $row['Unsigned'] = true;
  206. }
  207. if (preg_match('/^((?:var)?char)\((\d+)\)/', $row['Type'], $matches)) {
  208. $row['Type'] = $matches[1];
  209. $row['Length'] = $matches[2];
  210. } else if (preg_match('/^decimal\((\d+),(\d+)\)/', $row['Type'], $matches)) {
  211. $row['Type'] = 'decimal';
  212. $row['Precision'] = $matches[1];
  213. $row['Scale'] = $matches[2];
  214. } else if (preg_match('/^float\((\d+),(\d+)\)/', $row['Type'], $matches)) {
  215. $row['Type'] = 'float';
  216. $row['Precision'] = $matches[1];
  217. $row['Scale'] = $matches[2];
  218. } else if (preg_match('/^((?:big|medium|small|tiny)?int)\((\d+)\)/', $row['Type'], $matches)) {
  219. $row['Type'] = $matches[1];
  220. /**
  221. * The optional argument of a MySQL int type is not precision
  222. * or length; it is only a hint for display width.
  223. */
  224. }
  225. if (strtoupper($row['Key']) == 'PRI') {
  226. $row['Primary'] = true;
  227. $row['PrimaryPosition'] = $p;
  228. if ($row['Extra'] == 'auto_increment') {
  229. $row['Identity'] = true;
  230. } else {
  231. $row['Identity'] = false;
  232. }
  233. ++$p;
  234. }
  235. $desc[$this->foldCase($row['Field'])] = array(
  236. 'SCHEMA_NAME' => null, // @todo
  237. 'TABLE_NAME' => $this->foldCase($tableName),
  238. 'COLUMN_NAME' => $this->foldCase($row['Field']),
  239. 'COLUMN_POSITION' => $i,
  240. 'DATA_TYPE' => $row['Type'],
  241. 'DEFAULT' => $row['Default'],
  242. 'NULLABLE' => (bool) ($row['Null'] == 'YES'),
  243. 'LENGTH' => $row['Length'],
  244. 'SCALE' => $row['Scale'],
  245. 'PRECISION' => $row['Precision'],
  246. 'UNSIGNED' => $row['Unsigned'],
  247. 'PRIMARY' => $row['Primary'],
  248. 'PRIMARY_POSITION' => $row['PrimaryPosition'],
  249. 'IDENTITY' => $row['Identity']
  250. );
  251. ++$i;
  252. }
  253. return $desc;
  254. }
  255. /**
  256. * Creates a connection to the database.
  257. *
  258. * @return void
  259. * @throws Zend_Db_Adapter_Mysqli_Exception
  260. */
  261. protected function _connect()
  262. {
  263. if ($this->_connection) {
  264. return;
  265. }
  266. if (!extension_loaded('mysqli')) {
  267. /**
  268. * @see Zend_Db_Adapter_Mysqli_Exception
  269. */
  270. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  271. throw new Zend_Db_Adapter_Mysqli_Exception('The Mysqli extension is required for this adapter but the extension is not loaded');
  272. }
  273. if (isset($this->_config['port'])) {
  274. $port = (integer) $this->_config['port'];
  275. } else {
  276. $port = null;
  277. }
  278. $this->_connection = mysqli_init();
  279. if(!empty($this->_config['driver_options'])) {
  280. foreach($this->_config['driver_options'] as $option=>$value) {
  281. if(is_string($option)) {
  282. // Suppress warnings here
  283. // Ignore it if it's not a valid constant
  284. $option = @constant(strtoupper($option));
  285. if($option === null)
  286. continue;
  287. }
  288. mysqli_options($this->_connection, $option, $value);
  289. }
  290. }
  291. // Suppress connection warnings here.
  292. // Throw an exception instead.
  293. $_isConnected = @mysqli_real_connect(
  294. $this->_connection,
  295. $this->_config['host'],
  296. $this->_config['username'],
  297. $this->_config['password'],
  298. $this->_config['dbname'],
  299. $port
  300. );
  301. if ($_isConnected === false || mysqli_connect_errno()) {
  302. $this->closeConnection();
  303. /**
  304. * @see Zend_Db_Adapter_Mysqli_Exception
  305. */
  306. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  307. throw new Zend_Db_Adapter_Mysqli_Exception(mysqli_connect_error());
  308. }
  309. if (!empty($this->_config['charset'])) {
  310. mysqli_set_charset($this->_connection, $this->_config['charset']);
  311. }
  312. }
  313. /**
  314. * Test if a connection is active
  315. *
  316. * @return boolean
  317. */
  318. public function isConnected()
  319. {
  320. return ((bool) ($this->_connection instanceof mysqli));
  321. }
  322. /**
  323. * Force the connection to close.
  324. *
  325. * @return void
  326. */
  327. public function closeConnection()
  328. {
  329. if ($this->isConnected()) {
  330. $this->_connection->close();
  331. }
  332. $this->_connection = null;
  333. }
  334. /**
  335. * Prepare a statement and return a PDOStatement-like object.
  336. *
  337. * @param string $sql SQL query
  338. * @return Zend_Db_Statement_Mysqli
  339. */
  340. public function prepare($sql)
  341. {
  342. $this->_connect();
  343. if ($this->_stmt) {
  344. $this->_stmt->close();
  345. }
  346. $stmtClass = $this->_defaultStmtClass;
  347. if (!class_exists($stmtClass)) {
  348. require_once 'Zend/Loader.php';
  349. Zend_Loader::loadClass($stmtClass);
  350. }
  351. $stmt = new $stmtClass($this, $sql);
  352. if ($stmt === false) {
  353. return false;
  354. }
  355. $stmt->setFetchMode($this->_fetchMode);
  356. $this->_stmt = $stmt;
  357. return $stmt;
  358. }
  359. /**
  360. * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
  361. *
  362. * As a convention, on RDBMS brands that support sequences
  363. * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
  364. * from the arguments and returns the last id generated by that sequence.
  365. * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
  366. * returns the last value generated for such a column, and the table name
  367. * argument is disregarded.
  368. *
  369. * MySQL does not support sequences, so $tableName and $primaryKey are ignored.
  370. *
  371. * @param string $tableName OPTIONAL Name of table.
  372. * @param string $primaryKey OPTIONAL Name of primary key column.
  373. * @return string
  374. * @todo Return value should be int?
  375. */
  376. public function lastInsertId($tableName = null, $primaryKey = null)
  377. {
  378. $mysqli = $this->_connection;
  379. return (string) $mysqli->insert_id;
  380. }
  381. /**
  382. * Begin a transaction.
  383. *
  384. * @return void
  385. */
  386. protected function _beginTransaction()
  387. {
  388. $this->_connect();
  389. $this->_connection->autocommit(false);
  390. }
  391. /**
  392. * Commit a transaction.
  393. *
  394. * @return void
  395. */
  396. protected function _commit()
  397. {
  398. $this->_connect();
  399. $this->_connection->commit();
  400. $this->_connection->autocommit(true);
  401. }
  402. /**
  403. * Roll-back a transaction.
  404. *
  405. * @return void
  406. */
  407. protected function _rollBack()
  408. {
  409. $this->_connect();
  410. $this->_connection->rollback();
  411. $this->_connection->autocommit(true);
  412. }
  413. /**
  414. * Set the fetch mode.
  415. *
  416. * @param int $mode
  417. * @return void
  418. * @throws Zend_Db_Adapter_Mysqli_Exception
  419. */
  420. public function setFetchMode($mode)
  421. {
  422. switch ($mode) {
  423. case Zend_Db::FETCH_LAZY:
  424. case Zend_Db::FETCH_ASSOC:
  425. case Zend_Db::FETCH_NUM:
  426. case Zend_Db::FETCH_BOTH:
  427. case Zend_Db::FETCH_NAMED:
  428. case Zend_Db::FETCH_OBJ:
  429. $this->_fetchMode = $mode;
  430. break;
  431. case Zend_Db::FETCH_BOUND: // bound to PHP variable
  432. /**
  433. * @see Zend_Db_Adapter_Mysqli_Exception
  434. */
  435. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  436. throw new Zend_Db_Adapter_Mysqli_Exception('FETCH_BOUND is not supported yet');
  437. break;
  438. default:
  439. /**
  440. * @see Zend_Db_Adapter_Mysqli_Exception
  441. */
  442. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  443. throw new Zend_Db_Adapter_Mysqli_Exception("Invalid fetch mode '$mode' specified");
  444. }
  445. }
  446. /**
  447. * Adds an adapter-specific LIMIT clause to the SELECT statement.
  448. *
  449. * @param string $sql
  450. * @param int $count
  451. * @param int $offset OPTIONAL
  452. * @return string
  453. */
  454. public function limit($sql, $count, $offset = 0)
  455. {
  456. $count = intval($count);
  457. if ($count <= 0) {
  458. /**
  459. * @see Zend_Db_Adapter_Mysqli_Exception
  460. */
  461. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  462. throw new Zend_Db_Adapter_Mysqli_Exception("LIMIT argument count=$count is not valid");
  463. }
  464. $offset = intval($offset);
  465. if ($offset < 0) {
  466. /**
  467. * @see Zend_Db_Adapter_Mysqli_Exception
  468. */
  469. require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
  470. throw new Zend_Db_Adapter_Mysqli_Exception("LIMIT argument offset=$offset is not valid");
  471. }
  472. $sql .= " LIMIT $count";
  473. if ($offset > 0) {
  474. $sql .= " OFFSET $offset";
  475. }
  476. return $sql;
  477. }
  478. /**
  479. * Check if the adapter supports real SQL parameters.
  480. *
  481. * @param string $type 'positional' or 'named'
  482. * @return bool
  483. */
  484. public function supportsParameters($type)
  485. {
  486. switch ($type) {
  487. case 'positional':
  488. return true;
  489. case 'named':
  490. default:
  491. return false;
  492. }
  493. }
  494. /**
  495. * Retrieve server version in PHP style
  496. *
  497. *@return string
  498. */
  499. public function getServerVersion()
  500. {
  501. $this->_connect();
  502. $version = $this->_connection->server_version;
  503. $major = (int) ($version / 10000);
  504. $minor = (int) ($version % 10000 / 100);
  505. $revision = (int) ($version % 100);
  506. return $major . '.' . $minor . '.' . $revision;
  507. }
  508. }