PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/core/Tracker/Db/Pdo/Mysql.php

https://github.com/CodeYellowBV/piwik
PHP | 290 lines | 160 code | 29 blank | 101 comment | 32 complexity | 10c096683e1c58ae09047629649c4bcf MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik\Tracker\Db\Pdo;
  10. use Exception;
  11. use PDO;
  12. use PDOException;
  13. use PDOStatement;
  14. use Piwik\Tracker\Db;
  15. use Piwik\Tracker\Db\DbException;
  16. /**
  17. * PDO MySQL wrapper
  18. *
  19. */
  20. class Mysql extends Db
  21. {
  22. /**
  23. * @var PDO
  24. */
  25. protected $connection = null;
  26. protected $dsn;
  27. protected $username;
  28. protected $password;
  29. protected $charset;
  30. protected $activeTransaction = false;
  31. /**
  32. * Builds the DB object
  33. *
  34. * @param array $dbInfo
  35. * @param string $driverName
  36. */
  37. public function __construct($dbInfo, $driverName = 'mysql')
  38. {
  39. if (isset($dbInfo['unix_socket']) && $dbInfo['unix_socket'][0] == '/') {
  40. $this->dsn = $driverName . ':dbname=' . $dbInfo['dbname'] . ';unix_socket=' . $dbInfo['unix_socket'];
  41. } else if (!empty($dbInfo['port']) && $dbInfo['port'][0] == '/') {
  42. $this->dsn = $driverName . ':dbname=' . $dbInfo['dbname'] . ';unix_socket=' . $dbInfo['port'];
  43. } else {
  44. $this->dsn = $driverName . ':dbname=' . $dbInfo['dbname'] . ';host=' . $dbInfo['host'] . ';port=' . $dbInfo['port'];
  45. }
  46. $this->username = $dbInfo['username'];
  47. $this->password = $dbInfo['password'];
  48. $this->charset = isset($dbInfo['charset']) ? $dbInfo['charset'] : null;
  49. }
  50. public function __destruct()
  51. {
  52. $this->connection = null;
  53. }
  54. /**
  55. * Connects to the DB
  56. *
  57. * @throws Exception if there was an error connecting the DB
  58. */
  59. public function connect()
  60. {
  61. if (self::$profiling) {
  62. $timer = $this->initProfiler();
  63. }
  64. $this->connection = @new PDO($this->dsn, $this->username, $this->password, $config = array());
  65. $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  66. // we may want to setAttribute(PDO::ATTR_TIMEOUT ) to a few seconds (default is 60) in case the DB is locked
  67. // the piwik.php would stay waiting for the database... bad!
  68. // we delete the password from this object "just in case" it could be printed
  69. $this->password = '';
  70. /*
  71. * Lazy initialization via MYSQL_ATTR_INIT_COMMAND depends
  72. * on mysqlnd support, PHP version, and OS.
  73. * see ZF-7428 and http://bugs.php.net/bug.php?id=47224
  74. */
  75. if (!empty($this->charset)) {
  76. $sql = "SET NAMES '" . $this->charset . "'";
  77. $this->connection->exec($sql);
  78. }
  79. if (self::$profiling && isset($timer)) {
  80. $this->recordQueryProfile('connect', $timer);
  81. }
  82. }
  83. /**
  84. * Disconnects from the server
  85. */
  86. public function disconnect()
  87. {
  88. $this->connection = null;
  89. }
  90. /**
  91. * Returns an array containing all the rows of a query result, using optional bound parameters.
  92. *
  93. * @param string $query Query
  94. * @param array $parameters Parameters to bind
  95. * @return array|bool
  96. * @see query()
  97. * @throws Exception|DbException if an exception occurred
  98. */
  99. public function fetchAll($query, $parameters = array())
  100. {
  101. try {
  102. $sth = $this->query($query, $parameters);
  103. if ($sth === false) {
  104. return false;
  105. }
  106. return $sth->fetchAll(PDO::FETCH_ASSOC);
  107. } catch (PDOException $e) {
  108. throw new DbException("Error query: " . $e->getMessage());
  109. }
  110. }
  111. /**
  112. * Fetches the first column of all SQL result rows as an array.
  113. *
  114. * @param string $sql An SQL SELECT statement.
  115. * @param mixed $bind Data to bind into SELECT placeholders.
  116. * @throws \Piwik\Tracker\Db\DbException
  117. * @return string
  118. */
  119. public function fetchCol($sql, $bind = array())
  120. {
  121. try {
  122. $sth = $this->query($sql, $bind);
  123. if ($sth === false) {
  124. return false;
  125. }
  126. $result = $sth->fetchAll(PDO::FETCH_COLUMN, 0);
  127. return $result;
  128. } catch (PDOException $e) {
  129. throw new DbException("Error query: " . $e->getMessage());
  130. }
  131. }
  132. /**
  133. * Returns the first row of a query result, using optional bound parameters.
  134. *
  135. * @param string $query Query
  136. * @param array $parameters Parameters to bind
  137. * @return bool|mixed
  138. * @see query()
  139. * @throws Exception|DbException if an exception occurred
  140. */
  141. public function fetch($query, $parameters = array())
  142. {
  143. try {
  144. $sth = $this->query($query, $parameters);
  145. if ($sth === false) {
  146. return false;
  147. }
  148. return $sth->fetch(PDO::FETCH_ASSOC);
  149. } catch (PDOException $e) {
  150. throw new DbException("Error query: " . $e->getMessage());
  151. }
  152. }
  153. /**
  154. * Executes a query, using optional bound parameters.
  155. *
  156. * @param string $query Query
  157. * @param array|string $parameters Parameters to bind array('idsite'=> 1)
  158. * @return PDOStatement|bool PDOStatement or false if failed
  159. * @throws DbException if an exception occured
  160. */
  161. public function query($query, $parameters = array())
  162. {
  163. if (is_null($this->connection)) {
  164. return false;
  165. }
  166. try {
  167. if (self::$profiling) {
  168. $timer = $this->initProfiler();
  169. }
  170. if (!is_array($parameters)) {
  171. $parameters = array($parameters);
  172. }
  173. $sth = $this->connection->prepare($query);
  174. $sth->execute($parameters);
  175. if (self::$profiling && isset($timer)) {
  176. $this->recordQueryProfile($query, $timer);
  177. }
  178. return $sth;
  179. } catch (PDOException $e) {
  180. throw new DbException("Error query: " . $e->getMessage() . "
  181. In query: $query
  182. Parameters: " . var_export($parameters, true));
  183. }
  184. }
  185. /**
  186. * Returns the last inserted ID in the DB
  187. * Wrapper of PDO::lastInsertId()
  188. *
  189. * @return int
  190. */
  191. public function lastInsertId()
  192. {
  193. return $this->connection->lastInsertId();
  194. }
  195. /**
  196. * Test error number
  197. *
  198. * @param Exception $e
  199. * @param string $errno
  200. * @return bool
  201. */
  202. public function isErrNo($e, $errno)
  203. {
  204. if (preg_match('/([0-9]{4})/', $e->getMessage(), $match)) {
  205. return $match[1] == $errno;
  206. }
  207. return false;
  208. }
  209. /**
  210. * Return number of affected rows in last query
  211. *
  212. * @param mixed $queryResult Result from query()
  213. * @return int
  214. */
  215. public function rowCount($queryResult)
  216. {
  217. return $queryResult->rowCount();
  218. }
  219. /**
  220. * Start Transaction
  221. * @return string TransactionID
  222. */
  223. public function beginTransaction()
  224. {
  225. if(!$this->activeTransaction === false ) {
  226. return;
  227. }
  228. if( $this->connection->beginTransaction() ) {
  229. $this->activeTransaction = uniqid();
  230. return $this->activeTransaction;
  231. }
  232. }
  233. /**
  234. * Commit Transaction
  235. * @param string TransactionID from beginTransaction
  236. */
  237. public function commit($xid)
  238. {
  239. if($this->activeTransaction != $xid || $this->activeTransaction === false ) {
  240. return;
  241. }
  242. $this->activeTransaction = false;
  243. if(!$this->connection->commit() ) {
  244. throw new DbException("Commit failed");
  245. }
  246. }
  247. /**
  248. * Rollback Transaction
  249. * @param string TransactionID from beginTransaction
  250. */
  251. public function rollBack($xid)
  252. {
  253. if($this->activeTransaction != $xid || $this->activeTransaction === false ) {
  254. return;
  255. }
  256. $this->activeTransaction = false;
  257. if(!$this->connection->rollBack() ) {
  258. throw new DbException("Rollback failed");
  259. }
  260. }
  261. }