PageRenderTime 75ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/fuel/category_tool/fuel/core/classes/database/pdo/connection.php

https://github.com/connvoi/dev
PHP | 314 lines | 220 code | 47 blank | 47 comment | 15 complexity | b4b6963346209633b1e1d6d94cc486c8 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. <?php
  2. /**
  3. * PDO database connection.
  4. *
  5. * @package Fuel/Database
  6. * @category Drivers
  7. * @author Kohana Team
  8. * @copyright (c) 2008-2009 Kohana Team
  9. * @license http://kohanaphp.com/license
  10. */
  11. namespace Fuel\Core;
  12. class Database_PDO_Connection extends \Database_Connection
  13. {
  14. /**
  15. * @var \PDO Raw server connection
  16. */
  17. protected $_connection;
  18. /**
  19. * @var string PDO uses no quoting by default for identifiers
  20. */
  21. protected $_identifier = '';
  22. /**
  23. * @var bool Allows transactions
  24. */
  25. protected $_in_transaction = false;
  26. /**
  27. * @var string Which kind of DB is used
  28. */
  29. public $_db_type = '';
  30. protected function __construct($name, array $config)
  31. {
  32. parent::__construct($name, $config);
  33. if (isset($this->_config['identifier']))
  34. {
  35. // Allow the identifier to be overloaded per-connection
  36. $this->_identifier = (string) $this->_config['identifier'];
  37. }
  38. }
  39. public function connect()
  40. {
  41. if ($this->_connection)
  42. {
  43. return;
  44. }
  45. // Extract the connection parameters, adding required variabels
  46. extract($this->_config['connection'] + array(
  47. 'dsn' => '',
  48. 'username' => null,
  49. 'password' => null,
  50. 'persistent' => false,
  51. ));
  52. // Clear the connection parameters for security
  53. $this->_config['connection'] = array();
  54. // determine db type
  55. $_dsn_find_collon = strpos($dsn, ':');
  56. $this->_db_type = $_dsn_find_collon ? substr($dsn, 0, $_dsn_find_collon) : null;
  57. // Force PDO to use exceptions for all errors
  58. $attrs = array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION);
  59. if ( ! empty($persistent))
  60. {
  61. // Make the connection persistent
  62. $attrs[\PDO::ATTR_PERSISTENT] = true;
  63. }
  64. try
  65. {
  66. // Create a new PDO connection
  67. $this->_connection = new \PDO($dsn, $username, $password, $attrs);
  68. }
  69. catch (\PDOException $e)
  70. {
  71. throw new \Database_Exception($e->getMessage(), $e->getCode(), $e);
  72. }
  73. if ( ! empty($this->_config['charset']))
  74. {
  75. // Set the character set
  76. $this->set_charset($this->_config['charset']);
  77. }
  78. }
  79. public function disconnect()
  80. {
  81. // Destroy the PDO object
  82. $this->_connection = null;
  83. return true;
  84. }
  85. public function set_charset($charset)
  86. {
  87. // Make sure the database is connected
  88. $this->_connection or $this->connect();
  89. // Execute a raw SET NAMES query
  90. $this->_connection->exec('SET NAMES '.$this->quote($charset));
  91. }
  92. public function query($type, $sql, $as_object)
  93. {
  94. // Make sure the database is connected
  95. $this->_connection or $this->connect();
  96. if ( ! empty($this->_config['profiling']))
  97. {
  98. // Benchmark this query for the current instance
  99. $benchmark = \Profiler::start("Database ({$this->_instance})", $sql);
  100. }
  101. try
  102. {
  103. try
  104. {
  105. $result = $this->_connection->query($sql);
  106. }
  107. catch (\Exception $e)
  108. {
  109. // do a reconnect first and try again, before giving up
  110. $this->connect();
  111. $result = $this->_connection->query($sql);
  112. }
  113. }
  114. catch (\Exception $e)
  115. {
  116. if (isset($benchmark))
  117. {
  118. // This benchmark is worthless
  119. \Profiler::delete($benchmark);
  120. }
  121. // Convert the exception in a database exception
  122. throw new \Database_Exception($e->getMessage().' with query: "'.$sql.'"');
  123. }
  124. if (isset($benchmark))
  125. {
  126. \Profiler::stop($benchmark);
  127. }
  128. // Set the last query
  129. $this->last_query = $sql;
  130. if ($type === \DB::SELECT)
  131. {
  132. // Convert the result into an array, as PDOStatement::rowCount is not reliable
  133. if ($as_object === false)
  134. {
  135. $result->setFetchMode(\PDO::FETCH_ASSOC);
  136. }
  137. elseif (is_string($as_object))
  138. {
  139. $result->setFetchMode(\PDO::FETCH_CLASS, $as_object);
  140. }
  141. else
  142. {
  143. $result->setFetchMode(\PDO::FETCH_CLASS, 'stdClass');
  144. }
  145. $result = $result->fetchAll();
  146. // Return an iterator of results
  147. return new \Database_Result_Cached($result, $sql, $as_object);
  148. }
  149. elseif ($type === \DB::INSERT)
  150. {
  151. // Return a list of insert id and rows created
  152. return array(
  153. $this->_connection->lastInsertId(),
  154. $result->rowCount(),
  155. );
  156. }
  157. else
  158. {
  159. // Return the number of rows affected
  160. return $result->errorCode() === '00000' ? $result->rowCount() : -1;
  161. }
  162. }
  163. public function list_tables($like = null)
  164. {
  165. throw new \FuelException('Database method '.__METHOD__.' is not supported by '.__CLASS__);
  166. }
  167. public function list_columns($table, $like = null)
  168. {
  169. $this->_connection or $this->connect();
  170. $q = $this->_connection->prepare("DESCRIBE ".$table);
  171. $q->execute();
  172. $result = $q->fetchAll();
  173. $count = 0;
  174. $columns = array();
  175. ! is_null($like) and $like = str_replace('%', '.*', $like);
  176. foreach ($result as $row)
  177. {
  178. if ( ! is_null($like) and preg_match($like, $row['Field'])) continue;
  179. list($type, $length) = $this->_parse_type($row['Type']);
  180. $column = $this->datatype($type);
  181. $column['name'] = $row['Field'];
  182. $column['default'] = $row['Default'];
  183. $column['data_type'] = $type;
  184. $column['null'] = ($row['Null'] == 'YES');
  185. $column['ordinal_position'] = ++$count;
  186. switch ($column['type'])
  187. {
  188. case 'float':
  189. if (isset($length))
  190. {
  191. list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
  192. }
  193. break;
  194. case 'int':
  195. if (isset($length))
  196. {
  197. // MySQL attribute
  198. $column['display'] = $length;
  199. }
  200. break;
  201. case 'string':
  202. switch ($column['data_type'])
  203. {
  204. case 'binary':
  205. case 'varbinary':
  206. $column['character_maximum_length'] = $length;
  207. break;
  208. case 'char':
  209. case 'varchar':
  210. $column['character_maximum_length'] = $length;
  211. case 'text':
  212. case 'tinytext':
  213. case 'mediumtext':
  214. case 'longtext':
  215. $column['collation_name'] = isset($row['Collation']) ? $row['Collation'] : null;
  216. break;
  217. case 'enum':
  218. case 'set':
  219. $column['collation_name'] = isset($row['Collation']) ? $row['Collation'] : null;
  220. $column['options'] = explode('\',\'', substr($length, 1, - 1));
  221. break;
  222. }
  223. break;
  224. }
  225. // MySQL attributes
  226. $column['comment'] = isset($row['Comment']) ? $row['Comment'] : null;
  227. $column['extra'] = $row['Extra'];
  228. $column['key'] = $row['Key'];
  229. $column['privileges'] = isset($row['Privileges']) ? $row['Privileges'] : null;
  230. $columns[$row['Field']] = $column;
  231. }
  232. return $columns;
  233. }
  234. public function datatype($type)
  235. {
  236. // try to determine the datatype
  237. $datatype = parent::datatype($type);
  238. // if not an ANSI database, assume it's string
  239. return empty($datatype) ? array('type' => 'string') : $datatype;
  240. }
  241. public function escape($value)
  242. {
  243. // Make sure the database is connected
  244. $this->_connection or $this->connect();
  245. return $this->_connection->quote($value);
  246. }
  247. public function in_transaction()
  248. {
  249. return $this->_in_transaction;
  250. }
  251. public function start_transaction()
  252. {
  253. $this->_connection or $this->connect();
  254. $this->_in_transaction = true;
  255. return $this->_connection->beginTransaction();
  256. }
  257. public function commit_transaction()
  258. {
  259. $this->_in_transaction = false;
  260. return $this->_connection->commit();
  261. }
  262. public function rollback_transaction()
  263. {
  264. $this->_in_transaction = false;
  265. return $this->_connection->rollBack();
  266. }
  267. }