PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/libraries/joomla/database/driver/sqlite.php

https://bitbucket.org/ke2083/transfans.co.uk-website
PHP | 559 lines | 234 code | 77 blank | 248 comment | 20 complexity | 7f4b1138cce13e079553135c2f80d959 MD5 | raw file
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Database
  5. *
  6. * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * SQLite database driver
  12. *
  13. * @link https://secure.php.net/pdo
  14. * @since 3.0.0
  15. */
  16. class JDatabaseDriverSqlite extends JDatabaseDriverPdo
  17. {
  18. /**
  19. * The name of the database driver.
  20. *
  21. * @var string
  22. * @since 3.0.0
  23. */
  24. public $name = 'sqlite';
  25. /**
  26. * The type of the database server family supported by this driver.
  27. *
  28. * @var string
  29. * @since CMS 3.5.0
  30. */
  31. public $serverType = 'sqlite';
  32. /**
  33. * The character(s) used to quote SQL statement names such as table names or field names,
  34. * etc. The child classes should define this as necessary. If a single character string the
  35. * same character is used for both sides of the quoted name, else the first character will be
  36. * used for the opening quote and the second for the closing quote.
  37. *
  38. * @var string
  39. * @since 3.0.0
  40. */
  41. protected $nameQuote = '`';
  42. /**
  43. * Connects to the database if needed.
  44. *
  45. * @return void Returns void if the database connected successfully.
  46. *
  47. * @since 3.0.0
  48. * @throws RuntimeException
  49. */
  50. public function connect()
  51. {
  52. if ($this->connection)
  53. {
  54. return;
  55. }
  56. parent::connect();
  57. $this->connection->sqliteCreateFunction(
  58. 'ROW_NUMBER',
  59. function($init = null)
  60. {
  61. static $rownum, $partition;
  62. if ($init !== null)
  63. {
  64. $rownum = $init;
  65. $partition = null;
  66. return $rownum;
  67. }
  68. $args = func_get_args();
  69. array_shift($args);
  70. $partitionBy = $args ? implode(',', $args) : null;
  71. if ($partitionBy === null || $partitionBy === $partition)
  72. {
  73. $rownum++;
  74. }
  75. else
  76. {
  77. $rownum = 1;
  78. $partition = $partitionBy;
  79. }
  80. return $rownum;
  81. }
  82. );
  83. }
  84. /**
  85. * Disconnects the database.
  86. *
  87. * @return void
  88. *
  89. * @since 3.0.0
  90. */
  91. public function disconnect()
  92. {
  93. $this->freeResult();
  94. $this->connection = null;
  95. }
  96. /**
  97. * Drops a table from the database.
  98. *
  99. * @param string $tableName The name of the database table to drop.
  100. * @param boolean $ifExists Optionally specify that the table must exist before it is dropped.
  101. *
  102. * @return JDatabaseDriverSqlite Returns this object to support chaining.
  103. *
  104. * @since 3.0.0
  105. */
  106. public function dropTable($tableName, $ifExists = true)
  107. {
  108. $this->connect();
  109. $query = $this->getQuery(true);
  110. $this->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $query->quoteName($tableName));
  111. $this->execute();
  112. return $this;
  113. }
  114. /**
  115. * Method to escape a string for usage in an SQLite statement.
  116. *
  117. * Note: Using query objects with bound variables is
  118. * preferable to the below.
  119. *
  120. * @param string $text The string to be escaped.
  121. * @param boolean $extra Unused optional parameter to provide extra escaping.
  122. *
  123. * @return string The escaped string.
  124. *
  125. * @since 3.0.0
  126. */
  127. public function escape($text, $extra = false)
  128. {
  129. if (is_int($text))
  130. {
  131. return $text;
  132. }
  133. if (is_float($text))
  134. {
  135. // Force the dot as a decimal point.
  136. return str_replace(',', '.', $text);
  137. }
  138. return SQLite3::escapeString($text);
  139. }
  140. /**
  141. * Method to get the database collation in use by sampling a text field of a table in the database.
  142. *
  143. * @return mixed The collation in use by the database or boolean false if not supported.
  144. *
  145. * @since 3.0.0
  146. */
  147. public function getCollation()
  148. {
  149. return $this->charset;
  150. }
  151. /**
  152. * Method to get the database connection collation, as reported by the driver. If the connector doesn't support
  153. * reporting this value please return an empty string.
  154. *
  155. * @return string
  156. */
  157. public function getConnectionCollation()
  158. {
  159. return $this->charset;
  160. }
  161. /**
  162. * Shows the table CREATE statement that creates the given tables.
  163. *
  164. * Note: Doesn't appear to have support in SQLite
  165. *
  166. * @param mixed $tables A table name or a list of table names.
  167. *
  168. * @return array A list of the create SQL for the tables.
  169. *
  170. * @since 3.0.0
  171. * @throws RuntimeException
  172. */
  173. public function getTableCreate($tables)
  174. {
  175. $this->connect();
  176. // Sanitize input to an array and iterate over the list.
  177. settype($tables, 'array');
  178. return $tables;
  179. }
  180. /**
  181. * Retrieves field information about a given table.
  182. *
  183. * @param string $table The name of the database table.
  184. * @param boolean $typeOnly True to only return field types.
  185. *
  186. * @return array An array of fields for the database table.
  187. *
  188. * @since 3.0.0
  189. * @throws RuntimeException
  190. */
  191. public function getTableColumns($table, $typeOnly = true)
  192. {
  193. $this->connect();
  194. $columns = array();
  195. $query = $this->getQuery(true);
  196. $fieldCasing = $this->getOption(PDO::ATTR_CASE);
  197. $this->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);
  198. $table = strtoupper($table);
  199. $query->setQuery('pragma table_info(' . $table . ')');
  200. $this->setQuery($query);
  201. $fields = $this->loadObjectList();
  202. if ($typeOnly)
  203. {
  204. foreach ($fields as $field)
  205. {
  206. $columns[$field->NAME] = $field->TYPE;
  207. }
  208. }
  209. else
  210. {
  211. foreach ($fields as $field)
  212. {
  213. // Do some dirty translation to MySQL output.
  214. // TODO: Come up with and implement a standard across databases.
  215. $columns[$field->NAME] = (object) array(
  216. 'Field' => $field->NAME,
  217. 'Type' => $field->TYPE,
  218. 'Null' => ($field->NOTNULL == '1' ? 'NO' : 'YES'),
  219. 'Default' => $field->DFLT_VALUE,
  220. 'Key' => ($field->PK != '0' ? 'PRI' : ''),
  221. );
  222. }
  223. }
  224. $this->setOption(PDO::ATTR_CASE, $fieldCasing);
  225. return $columns;
  226. }
  227. /**
  228. * Get the details list of keys for a table.
  229. *
  230. * @param string $table The name of the table.
  231. *
  232. * @return array An array of the column specification for the table.
  233. *
  234. * @since 3.0.0
  235. * @throws RuntimeException
  236. */
  237. public function getTableKeys($table)
  238. {
  239. $this->connect();
  240. $keys = array();
  241. $query = $this->getQuery(true);
  242. $fieldCasing = $this->getOption(PDO::ATTR_CASE);
  243. $this->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);
  244. $table = strtoupper($table);
  245. $query->setQuery('pragma table_info( ' . $table . ')');
  246. // $query->bind(':tableName', $table);
  247. $this->setQuery($query);
  248. $rows = $this->loadObjectList();
  249. foreach ($rows as $column)
  250. {
  251. if ($column->PK == 1)
  252. {
  253. $keys[$column->NAME] = $column;
  254. }
  255. }
  256. $this->setOption(PDO::ATTR_CASE, $fieldCasing);
  257. return $keys;
  258. }
  259. /**
  260. * Method to get an array of all tables in the database (schema).
  261. *
  262. * @return array An array of all the tables in the database.
  263. *
  264. * @since 3.0.0
  265. * @throws RuntimeException
  266. */
  267. public function getTableList()
  268. {
  269. $this->connect();
  270. $type = 'table';
  271. $query = $this->getQuery(true)
  272. ->select('name')
  273. ->from('sqlite_master')
  274. ->where('type = :type')
  275. ->bind(':type', $type)
  276. ->order('name');
  277. $this->setQuery($query);
  278. $tables = $this->loadColumn();
  279. return $tables;
  280. }
  281. /**
  282. * Get the version of the database connector.
  283. *
  284. * @return string The database connector version.
  285. *
  286. * @since 3.0.0
  287. */
  288. public function getVersion()
  289. {
  290. $this->connect();
  291. $this->setQuery('SELECT sqlite_version()');
  292. return $this->loadResult();
  293. }
  294. /**
  295. * Select a database for use.
  296. *
  297. * @param string $database The name of the database to select for use.
  298. *
  299. * @return boolean True if the database was successfully selected.
  300. *
  301. * @since 3.0.0
  302. * @throws RuntimeException
  303. */
  304. public function select($database)
  305. {
  306. $this->connect();
  307. return true;
  308. }
  309. /**
  310. * Set the connection to use UTF-8 character encoding.
  311. *
  312. * Returns false automatically for the Oracle driver since
  313. * you can only set the character set when the connection
  314. * is created.
  315. *
  316. * @return boolean True on success.
  317. *
  318. * @since 3.0.0
  319. */
  320. public function setUtf()
  321. {
  322. $this->connect();
  323. return false;
  324. }
  325. /**
  326. * Locks a table in the database.
  327. *
  328. * @param string $table The name of the table to unlock.
  329. *
  330. * @return JDatabaseDriverSqlite Returns this object to support chaining.
  331. *
  332. * @since 3.0.0
  333. * @throws RuntimeException
  334. */
  335. public function lockTable($table)
  336. {
  337. return $this;
  338. }
  339. /**
  340. * Renames a table in the database.
  341. *
  342. * @param string $oldTable The name of the table to be renamed
  343. * @param string $newTable The new name for the table.
  344. * @param string $backup Not used by Sqlite.
  345. * @param string $prefix Not used by Sqlite.
  346. *
  347. * @return JDatabaseDriverSqlite Returns this object to support chaining.
  348. *
  349. * @since 3.0.0
  350. * @throws RuntimeException
  351. */
  352. public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
  353. {
  354. $this->setQuery('ALTER TABLE ' . $oldTable . ' RENAME TO ' . $newTable)->execute();
  355. return $this;
  356. }
  357. /**
  358. * Unlocks tables in the database.
  359. *
  360. * @return JDatabaseDriverSqlite Returns this object to support chaining.
  361. *
  362. * @since 3.0.0
  363. * @throws RuntimeException
  364. */
  365. public function unlockTables()
  366. {
  367. return $this;
  368. }
  369. /**
  370. * Test to see if the PDO ODBC connector is available.
  371. *
  372. * @return boolean True on success, false otherwise.
  373. *
  374. * @since 3.0.0
  375. */
  376. public static function isSupported()
  377. {
  378. return class_exists('PDO') && in_array('sqlite', PDO::getAvailableDrivers());
  379. }
  380. /**
  381. * Method to commit a transaction.
  382. *
  383. * @param boolean $toSavepoint If true, commit to the last savepoint.
  384. *
  385. * @return void
  386. *
  387. * @since 3.1.4
  388. * @throws RuntimeException
  389. */
  390. public function transactionCommit($toSavepoint = false)
  391. {
  392. $this->connect();
  393. if (!$toSavepoint || $this->transactionDepth <= 1)
  394. {
  395. parent::transactionCommit($toSavepoint);
  396. }
  397. else
  398. {
  399. $this->transactionDepth--;
  400. }
  401. }
  402. /**
  403. * Method to roll back a transaction.
  404. *
  405. * @param boolean $toSavepoint If true, rollback to the last savepoint.
  406. *
  407. * @return void
  408. *
  409. * @since 3.1.4
  410. * @throws RuntimeException
  411. */
  412. public function transactionRollback($toSavepoint = false)
  413. {
  414. $this->connect();
  415. if (!$toSavepoint || $this->transactionDepth <= 1)
  416. {
  417. parent::transactionRollback($toSavepoint);
  418. }
  419. else
  420. {
  421. $savepoint = 'SP_' . ($this->transactionDepth - 1);
  422. $this->setQuery('ROLLBACK TO ' . $this->quoteName($savepoint));
  423. if ($this->execute())
  424. {
  425. $this->transactionDepth--;
  426. }
  427. }
  428. }
  429. /**
  430. * Method to initialize a transaction.
  431. *
  432. * @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
  433. *
  434. * @return void
  435. *
  436. * @since 3.1.4
  437. * @throws RuntimeException
  438. */
  439. public function transactionStart($asSavepoint = false)
  440. {
  441. $this->connect();
  442. if (!$asSavepoint || !$this->transactionDepth)
  443. {
  444. parent::transactionStart($asSavepoint);
  445. }
  446. $savepoint = 'SP_' . $this->transactionDepth;
  447. $this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint));
  448. if ($this->execute())
  449. {
  450. $this->transactionDepth++;
  451. }
  452. }
  453. /**
  454. * Get the query strings to alter the character set and collation of a table.
  455. *
  456. * @param string $tableName The name of the table
  457. *
  458. * @return string[] The queries required to alter the table's character set and collation
  459. *
  460. * @since CMS 3.5.0
  461. */
  462. public function getAlterTableCharacterSet($tableName)
  463. {
  464. return array();
  465. }
  466. /**
  467. * Return the query string to create new Database.
  468. * Each database driver, other than MySQL, need to override this member to return correct string.
  469. *
  470. * @param stdClass $options Object used to pass user and database name to database driver.
  471. * This object must have "db_name" and "db_user" set.
  472. * @param boolean $utf True if the database supports the UTF-8 character set.
  473. *
  474. * @return string The query that creates database
  475. *
  476. * @since 3.0.1
  477. */
  478. protected function getCreateDatabaseQuery($options, $utf)
  479. {
  480. return 'CREATE DATABASE ' . $this->quoteName($options->db_name);
  481. }
  482. }