PageRenderTime 60ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/core/xpdo/om/sqlite/xpdomanager.class.php

https://github.com/gbds/revolution
PHP | 308 lines | 249 code | 16 blank | 43 comment | 74 complexity | 169c42e1c5f2532c05c3cc52d216b40e MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright 2006-2010 by Jason Coward <xpdo@opengeek.com>
  4. *
  5. * This file is part of xPDO.
  6. *
  7. * xPDO is free software; you can redistribute it and/or modify it under the
  8. * terms of the GNU General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option) any later
  10. * version.
  11. *
  12. * xPDO is distributed in the hope that it will be useful, but WITHOUT ANY
  13. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  14. * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * xPDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  18. * Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. /**
  21. * The SQLite implementation of the xPDOManager class.
  22. *
  23. * @package xpdo
  24. * @subpackage om.sqlite
  25. */
  26. /**
  27. * Include the parent {@link xPDOManager} class.
  28. */
  29. require_once (dirname(dirname(__FILE__)) . '/xpdomanager.class.php');
  30. /**
  31. * Provides SQLite data source management for an xPDO instance.
  32. *
  33. * These are utility functions that only need to be loaded under special
  34. * circumstances, such as creating tables, adding indexes, altering table
  35. * structures, etc. xPDOManager class implementations are specific to a
  36. * database driver and this instance is implemented for SQLite.
  37. *
  38. * @package xpdo
  39. * @subpackage om.sqlite
  40. */
  41. class xPDOManager_sqlite extends xPDOManager {
  42. public function createSourceContainer($dsnArray = null, $username= null, $password= null, $containerOptions= array ()) {
  43. $created = false;
  44. $this->xpdo->log(xPDO::LOG_LEVEL_WARN, 'SQLite does not support source container creation');
  45. if ($dsnArray === null) $dsnArray = xPDO::parseDSN($this->xpdo->getOption('dsn'));
  46. if (is_array($dsnArray)) {
  47. try {
  48. $dbfile = $dsnArray['dbname'];
  49. $created = !file_exists($dbfile);
  50. } catch (Exception $e) {
  51. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error creating source container: " . $e->getMessage());
  52. }
  53. }
  54. return $created;
  55. }
  56. public function removeSourceContainer($dsnArray = null, $username= null, $password= null) {
  57. $removed= false;
  58. if ($dsnArray === null) $dsnArray = xPDO::parseDSN($this->xpdo->getOption('dsn'));
  59. if (is_array($dsnArray)) {
  60. try {
  61. $dbfile = $dsnArray['dbname'];
  62. if (file_exists($dbfile)) {
  63. $removed = unlink($dbfile);
  64. if (!$removed) {
  65. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not remove source container");
  66. }
  67. } else {
  68. $removed= true;
  69. }
  70. } catch (Exception $e) {
  71. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not remove source container: " . $e->getMessage());
  72. }
  73. }
  74. return $removed;
  75. }
  76. public function removeObjectContainer($className) {
  77. $removed= false;
  78. $instance= $this->xpdo->newObject($className);
  79. if ($instance) {
  80. $sql= 'DROP TABLE ' . $this->xpdo->getTableName($className);
  81. $removed= $this->xpdo->exec($sql);
  82. if ($removed === false && $this->xpdo->errorCode() !== '' && $this->xpdo->errorCode() !== PDO::ERR_NONE) {
  83. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not drop table ' . $className . "\nSQL: {$sql}\nERROR: " . print_r($this->xpdo->pdo->errorInfo(), true));
  84. } else {
  85. $removed= true;
  86. $this->xpdo->log(xPDO::LOG_LEVEL_INFO, 'Dropped table' . $className . "\nSQL: {$sql}\n");
  87. }
  88. }
  89. return $removed;
  90. }
  91. public function createObjectContainer($className) {
  92. $created= false;
  93. $instance= $this->xpdo->newObject($className);
  94. if ($instance) {
  95. $tableName= $this->xpdo->getTableName($className);
  96. $existsStmt = $this->xpdo->query("SELECT COUNT(*) FROM {$tableName}");
  97. if ($existsStmt && $existsStmt->fetchAll()) {
  98. return true;
  99. }
  100. $tableMeta= $this->xpdo->getTableMeta($className);
  101. $sql= 'CREATE TABLE ' . $tableName . ' (';
  102. $fieldMeta = $this->xpdo->getFieldMeta($className);
  103. $nativeGen = false;
  104. $columns = array();
  105. while (list($key, $meta)= each($fieldMeta)) {
  106. $columns[] = $this->getColumnDef($className, $key, $meta);
  107. if (array_key_exists('generated', $meta) && $meta['generated'] == 'native') $nativeGen = true;
  108. }
  109. $sql .= implode(', ', $columns);
  110. $indexes = $this->xpdo->getIndexMeta($className);
  111. $createIndices = array();
  112. $tableConstraints = array();
  113. if (!empty ($indexes)) {
  114. foreach ($indexes as $indexkey => $indexdef) {
  115. $indexType = ($indexdef['primary'] ? 'PRIMARY KEY' : ($indexdef['unique'] ? 'UNIQUE' : 'INDEX'));
  116. $index = $indexdef['columns'];
  117. if (is_array($index)) {
  118. $indexset= array ();
  119. foreach ($index as $indexmember => $indexmemberdetails) {
  120. $indexMemberDetails = $this->xpdo->escape($indexmember);
  121. $indexset[]= $indexMemberDetails;
  122. }
  123. $indexset= implode(',', $indexset);
  124. if (!empty($indexset)) {
  125. switch ($indexType) {
  126. case 'UNIQUE':
  127. $createIndices[$indexkey] = "CREATE UNIQUE INDEX {$this->xpdo->escape($indexkey)} ON {$tableName} ({$indexset})";
  128. break;
  129. case 'INDEX':
  130. $createIndices[$indexkey] = "CREATE INDEX {$this->xpdo->escape($indexkey)} ON {$tableName} ({$indexset})";
  131. break;
  132. case 'PRIMARY KEY':
  133. if ($nativeGen) break;
  134. $tableConstraints[]= "{$indexType} ({$indexset})";
  135. break;
  136. default:
  137. $tableConstraints[]= "CONSTRAINT {$this->xpdo->escape($indexkey)} {$indexType} ({$indexset})";
  138. break;
  139. }
  140. }
  141. }
  142. }
  143. }
  144. if (!empty($tableConstraints)) {
  145. $sql .= ', ' . implode(', ', $tableConstraints);
  146. }
  147. $sql .= ")";
  148. $created= $this->xpdo->exec($sql);
  149. if ($created === false && $this->xpdo->errorCode() !== '' && $this->xpdo->errorCode() !== PDO::ERR_NONE) {
  150. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not create table ' . $tableName . "\nSQL: {$sql}\nERROR: " . print_r($this->xpdo->errorInfo(), true));
  151. } else {
  152. $created= true;
  153. $this->xpdo->log(xPDO::LOG_LEVEL_INFO, 'Created table ' . $tableName . "\nSQL: {$sql}\n");
  154. }
  155. if ($created === true && !empty($createIndices)) {
  156. foreach ($createIndices as $createIndexKey => $createIndex) {
  157. $indexCreated = $this->xpdo->exec($createIndex);
  158. if ($indexCreated === false && $this->xpdo->errorCode() !== '' && $this->xpdo->errorCode() !== PDO::ERR_NONE) {
  159. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not create index {$createIndexKey}: {$createIndex} " . print_r($this->xpdo->errorInfo(), true));
  160. } else {
  161. $this->xpdo->log(xPDO::LOG_LEVEL_INFO, "Created index {$createIndexKey} on {$tableName}: {$createIndex}");
  162. }
  163. }
  164. }
  165. }
  166. return $created;
  167. }
  168. public function alterObjectContainer($className, array $options = array()) {
  169. // TODO: Implement alterObjectContainer() method.
  170. }
  171. public function addConstraint($class, $name, array $options = array()) {
  172. // TODO: Implement addConstraint() method.
  173. }
  174. public function addField($class, $name, array $options = array()) {
  175. $result = false;
  176. $className = $this->xpdo->loadClass($class);
  177. if ($className) {
  178. $meta = $this->xpdo->getFieldMeta($className);
  179. if (is_array($meta) && array_key_exists($name, $meta)) {
  180. $colDef = $this->getColumnDef($className, $name, $meta[$name]);
  181. if (!empty($colDef)) {
  182. $sql = "ALTER TABLE {$this->xpdo->getTableName($className)} ADD COLUMN {$colDef}";
  183. if ($this->xpdo->exec($sql)) {
  184. $result = true;
  185. } else {
  186. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error adding field {$class}->{$name}: " . print_r($this->xpdo->errorInfo(), true), '', __METHOD__, __FILE__, __LINE__);
  187. }
  188. }
  189. }
  190. }
  191. return $result;
  192. }
  193. public function addIndex($class, $name, array $options = array()) {
  194. $result = false;
  195. $className = $this->xpdo->loadClass($class);
  196. if ($className) {
  197. $meta = $this->xpdo->getIndexMeta($className);
  198. if (is_array($meta) && array_key_exists($name, $meta)) {
  199. $indexType = ($meta[$name]['unique'] ? 'UNIQUE INDEX' : 'INDEX');
  200. $idxDef = $this->getIndexDef($className, $name, $meta[$name]);
  201. if (!empty($idxDef)) {
  202. $sql = "CREATE {$indexType} ON {$this->xpdo->getTableName($className)} ({$idxDef})";
  203. if ($this->xpdo->exec($sql)) {
  204. $result = true;
  205. } else {
  206. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error adding index {$name} to {$class}: " . print_r($this->xpdo->errorInfo(), true), '', __METHOD__, __FILE__, __LINE__);
  207. }
  208. }
  209. }
  210. }
  211. return $result;
  212. }
  213. public function alterField($class, $name, array $options = array()) {
  214. $result = false;
  215. // TODO: Implement alterField() method somehow, no support in sqlite for altering existing columns
  216. return $result;
  217. }
  218. public function removeConstraint($class, $name, array $options = array()) {
  219. $result = false;
  220. // TODO: Implement removeConstraint() method.
  221. return $result;
  222. }
  223. public function removeField($class, $name, array $options = array()) {
  224. $result = false;
  225. // TODO: Implement removeField() method somehow, no support in sqlite for dropping existing columns
  226. return $result;
  227. }
  228. public function removeIndex($class, $name, array $options = array()) {
  229. $result = false;
  230. $className = $this->xpdo->loadClass($class);
  231. if ($className) {
  232. $sql = "DROP INDEX {$this->xpdo->escape($name)}";
  233. if ($this->xpdo->exec($sql)) {
  234. $result = true;
  235. } else {
  236. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error removing index {$name} from {$class}: " . print_r($this->xpdo->errorInfo(), true), '', __METHOD__, __FILE__, __LINE__);
  237. }
  238. }
  239. return $result;
  240. }
  241. protected function getColumnDef($class, $name, $meta, array $options = array()) {
  242. $pk = $this->xpdo->getPK($class);
  243. $pktype = $this->xpdo->getPKType($class);
  244. $dbtype= strtoupper($meta['dbtype']);
  245. $precision= isset ($meta['precision']) && !preg_match('/ENUM/i', $dbtype) ? '(' . $meta['precision'] . ')' : '';
  246. if (preg_match('/ENUM/i', $dbtype)) {
  247. $dbtype= 'CHAR';
  248. }
  249. $notNull= !isset ($meta['null'])
  250. ? false
  251. : ($meta['null'] === 'false' || empty($meta['null']));
  252. $null= $notNull ? ' NOT NULL' : ' NULL';
  253. $extra = '';
  254. if (isset ($meta['index']) && $meta['index'] == 'pk' && !is_array($pk) && $pktype == 'integer' && isset ($meta['generated']) && $meta['generated'] == 'native') {
  255. $extra= ' PRIMARY KEY AUTOINCREMENT';
  256. $options['nativeGen'] = true;
  257. $null= '';
  258. }
  259. if (empty ($extra) && isset ($meta['extra'])) {
  260. $extra= ' ' . $meta['extra'];
  261. }
  262. $default= '';
  263. if (array_key_exists('default', $meta)) {
  264. $defaultVal= $meta['default'];
  265. if ($defaultVal === null || strtoupper($defaultVal) === 'NULL' || in_array($this->xpdo->driver->getPhpType($dbtype), array('integer', 'float')) || (in_array($meta['phptype'], array('datetime', 'date', 'timestamp', 'time')) && in_array($defaultVal, array_merge($this->xpdo->driver->_currentTimestamps, $this->xpdo->driver->_currentDates, $this->xpdo->driver->_currentTimes)))) {
  266. $default= ' DEFAULT ' . $defaultVal;
  267. } else {
  268. $default= ' DEFAULT \'' . $defaultVal . '\'';
  269. }
  270. }
  271. $attributes= (isset ($meta['attributes'])) ? ' ' . $meta['attributes'] : '';
  272. if (strpos(strtolower($attributes), 'unsigned') !== false) {
  273. $result = $this->xpdo->escape($name) . ' ' . $dbtype . $precision . $attributes . $null . $default . $extra;
  274. } else {
  275. $result = $this->xpdo->escape($name) . ' ' . $dbtype . $precision . $null . $default . $attributes . $extra;
  276. }
  277. return $result;
  278. }
  279. protected function getIndexDef($class, $name, $meta, array $options = array()) {
  280. $result = '';
  281. $index = isset($meta['columns']) ? $meta['columns'] : null;
  282. if (is_array($index)) {
  283. $indexset= array ();
  284. foreach ($index as $indexmember => $indexmemberdetails) {
  285. $indexMemberDetails = $this->xpdo->escape($indexmember);
  286. $indexset[]= $indexMemberDetails;
  287. }
  288. $result= implode(',', $indexset);
  289. }
  290. return $result;
  291. }
  292. }