Driver.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Database;
  16. use InvalidArgumentException;
  17. use PDO;
  18. /**
  19. * Represents a database driver containing all specificities for
  20. * a database engine including its SQL dialect.
  21. *
  22. * @property \PDO|null $_connection
  23. */
  24. abstract class Driver
  25. {
  26. /**
  27. * Configuration data.
  28. *
  29. * @var array
  30. */
  31. protected $_config;
  32. /**
  33. * Base configuration that is merged into the user
  34. * supplied configuration data.
  35. *
  36. * @var array
  37. */
  38. protected $_baseConfig = [];
  39. /**
  40. * Indicates whether or not the driver is doing automatic identifier quoting
  41. * for all queries
  42. *
  43. * @var bool
  44. */
  45. protected $_autoQuoting = false;
  46. /**
  47. * Constructor
  48. *
  49. * @param array $config The configuration for the driver.
  50. * @throws \InvalidArgumentException
  51. */
  52. public function __construct($config = [])
  53. {
  54. if (empty($config['username']) && !empty($config['login'])) {
  55. throw new InvalidArgumentException(
  56. 'Please pass "username" instead of "login" for connecting to the database'
  57. );
  58. }
  59. $config += $this->_baseConfig;
  60. $this->_config = $config;
  61. if (!empty($config['quoteIdentifiers'])) {
  62. $this->enableAutoQuoting();
  63. }
  64. }
  65. /**
  66. * Establishes a connection to the database server
  67. *
  68. * @return bool true on success
  69. */
  70. abstract public function connect();
  71. /**
  72. * Disconnects from database server
  73. *
  74. * @return void
  75. */
  76. abstract public function disconnect();
  77. /**
  78. * Returns correct connection resource or object that is internally used
  79. * If first argument is passed,
  80. *
  81. * @param null|\PDO $connection The connection object
  82. * @return \PDO
  83. */
  84. abstract public function connection($connection = null);
  85. /**
  86. * Returns whether php is able to use this driver for connecting to database
  87. *
  88. * @return bool true if it is valid to use this driver
  89. */
  90. abstract public function enabled();
  91. /**
  92. * Prepares a sql statement to be executed
  93. *
  94. * @param string|\Cake\Database\Query $query The query to convert into a statement.
  95. * @return \Cake\Database\StatementInterface
  96. */
  97. abstract public function prepare($query);
  98. /**
  99. * Starts a transaction
  100. *
  101. * @return bool true on success, false otherwise
  102. */
  103. abstract public function beginTransaction();
  104. /**
  105. * Commits a transaction
  106. *
  107. * @return bool true on success, false otherwise
  108. */
  109. abstract public function commitTransaction();
  110. /**
  111. * Rollsback a transaction
  112. *
  113. * @return bool true on success, false otherwise
  114. */
  115. abstract public function rollbackTransaction();
  116. /**
  117. * Get the SQL for releasing a save point.
  118. *
  119. * @param string $name The table name
  120. * @return string
  121. */
  122. abstract public function releaseSavePointSQL($name);
  123. /**
  124. * Get the SQL for creating a save point.
  125. *
  126. * @param string $name The table name
  127. * @return string
  128. */
  129. abstract public function savePointSQL($name);
  130. /**
  131. * Get the SQL for rollingback a save point.
  132. *
  133. * @param string $name The table name
  134. * @return string
  135. */
  136. abstract public function rollbackSavePointSQL($name);
  137. /**
  138. * Get the SQL for disabling foreign keys
  139. *
  140. * @return string
  141. */
  142. abstract public function disableForeignKeySQL();
  143. /**
  144. * Get the SQL for enabling foreign keys
  145. *
  146. * @return string
  147. */
  148. abstract public function enableForeignKeySQL();
  149. /**
  150. * Returns whether the driver supports adding or dropping constraints
  151. * to already created tables.
  152. *
  153. * @return bool true if driver supports dynamic constraints
  154. */
  155. abstract public function supportsDynamicConstraints();
  156. /**
  157. * Returns whether this driver supports save points for nested transactions
  158. *
  159. * @return bool true if save points are supported, false otherwise
  160. */
  161. public function supportsSavePoints()
  162. {
  163. return true;
  164. }
  165. /**
  166. * Returns a value in a safe representation to be used in a query string
  167. *
  168. * @param mixed $value The value to quote.
  169. * @param string $type Type to be used for determining kind of quoting to perform
  170. * @return string
  171. */
  172. abstract public function quote($value, $type);
  173. /**
  174. * Checks if the driver supports quoting
  175. *
  176. * @return bool
  177. */
  178. public function supportsQuoting()
  179. {
  180. return true;
  181. }
  182. /**
  183. * Returns a callable function that will be used to transform a passed Query object.
  184. * This function, in turn, will return an instance of a Query object that has been
  185. * transformed to accommodate any specificities of the SQL dialect in use.
  186. *
  187. * @param string $type the type of query to be transformed
  188. * (select, insert, update, delete)
  189. * @return callable
  190. */
  191. abstract public function queryTranslator($type);
  192. /**
  193. * Get the schema dialect.
  194. *
  195. * Used by Cake\Database\Schema package to reflect schema and
  196. * generate schema.
  197. *
  198. * If all the tables that use this Driver specify their
  199. * own schemas, then this may return null.
  200. *
  201. * @return \Cake\Database\Schema\BaseSchema
  202. */
  203. abstract public function schemaDialect();
  204. /**
  205. * Quotes a database identifier (a column name, table name, etc..) to
  206. * be used safely in queries without the risk of using reserved words
  207. *
  208. * @param string $identifier The identifier expression to quote.
  209. * @return string
  210. */
  211. abstract public function quoteIdentifier($identifier);
  212. /**
  213. * Escapes values for use in schema definitions.
  214. *
  215. * @param mixed $value The value to escape.
  216. * @return string String for use in schema definitions.
  217. */
  218. public function schemaValue($value)
  219. {
  220. if ($value === null) {
  221. return 'NULL';
  222. }
  223. if ($value === false) {
  224. return 'FALSE';
  225. }
  226. if ($value === true) {
  227. return 'TRUE';
  228. }
  229. if (is_float($value)) {
  230. return str_replace(',', '.', (string)$value);
  231. }
  232. if ((is_int($value) || $value === '0') || (
  233. is_numeric($value) && strpos($value, ',') === false &&
  234. $value[0] !== '0' && strpos($value, 'e') === false)
  235. ) {
  236. return (string)$value;
  237. }
  238. return $this->_connection->quote($value, PDO::PARAM_STR);
  239. }
  240. /**
  241. * Returns the schema name that's being used
  242. *
  243. * @return string
  244. */
  245. public function schema()
  246. {
  247. return $this->_config['schema'];
  248. }
  249. /**
  250. * Returns last id generated for a table or sequence in database
  251. *
  252. * @param string|null $table table name or sequence to get last insert value from
  253. * @param string|null $column the name of the column representing the primary key
  254. * @return string|int
  255. */
  256. public function lastInsertId($table = null, $column = null)
  257. {
  258. return $this->_connection->lastInsertId($table, $column);
  259. }
  260. /**
  261. * Check whether or not the driver is connected.
  262. *
  263. * @return bool
  264. */
  265. public function isConnected()
  266. {
  267. return $this->_connection !== null;
  268. }
  269. /**
  270. * Sets whether or not this driver should automatically quote identifiers
  271. * in queries.
  272. *
  273. * @param bool $enable Whether to enable auto quoting
  274. * @return $this
  275. */
  276. public function enableAutoQuoting($enable = true)
  277. {
  278. $this->_autoQuoting = (bool)$enable;
  279. return $this;
  280. }
  281. /**
  282. * Returns whether or not this driver should automatically quote identifiers
  283. * in queries
  284. *
  285. * @return bool
  286. */
  287. public function isAutoQuotingEnabled()
  288. {
  289. return $this->_autoQuoting;
  290. }
  291. /**
  292. * Returns whether or not this driver should automatically quote identifiers
  293. * in queries
  294. *
  295. * If called with a boolean argument, it will toggle the auto quoting setting
  296. * to the passed value
  297. *
  298. * @deprecated 3.4.0 use enableAutoQuoting()/isAutoQuotingEnabled() instead.
  299. * @param bool|null $enable Whether to enable auto quoting
  300. * @return bool
  301. */
  302. public function autoQuoting($enable = null)
  303. {
  304. if ($enable !== null) {
  305. $this->enableAutoQuoting($enable);
  306. }
  307. return $this->isAutoQuotingEnabled();
  308. }
  309. /**
  310. * Transforms the passed query to this Driver's dialect and returns an instance
  311. * of the transformed query and the full compiled SQL string
  312. *
  313. * @param \Cake\Database\Query $query The query to compile.
  314. * @param \Cake\Database\ValueBinder $generator The value binder to use.
  315. * @return array containing 2 entries. The first entity is the transformed query
  316. * and the second one the compiled SQL
  317. */
  318. public function compileQuery(Query $query, ValueBinder $generator)
  319. {
  320. $processor = $this->newCompiler();
  321. $translator = $this->queryTranslator($query->type());
  322. $query = $translator($query);
  323. return [$query, $processor->compile($query, $generator)];
  324. }
  325. /**
  326. * Returns an instance of a QueryCompiler
  327. *
  328. * @return \Cake\Database\QueryCompiler
  329. */
  330. public function newCompiler()
  331. {
  332. return new QueryCompiler();
  333. }
  334. /**
  335. * Destructor
  336. */
  337. public function __destruct()
  338. {
  339. $this->_connection = null;
  340. }
  341. /**
  342. * Returns an array that can be used to describe the internal state of this
  343. * object.
  344. *
  345. * @return array
  346. */
  347. public function __debugInfo()
  348. {
  349. return [
  350. 'connected' => $this->_connection !== null
  351. ];
  352. }
  353. }