mdb2schemamanager.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace OC\DB;
  9. class MDB2SchemaManager {
  10. /**
  11. * @var \OC\DB\Connection $conn
  12. */
  13. protected $conn;
  14. /**
  15. * @param \OC\DB\Connection $conn
  16. */
  17. public function __construct($conn) {
  18. $this->conn = $conn;
  19. $this->conn->close();
  20. $this->conn->connect();
  21. }
  22. /**
  23. * @brief saves database scheme to xml file
  24. * @param string $file name of file
  25. * @param int|string $mode
  26. * @return bool
  27. *
  28. * TODO: write more documentation
  29. */
  30. public function getDbStructure( $file, $mode = MDB2_SCHEMA_DUMP_STRUCTURE) {
  31. $sm = $this->conn->getSchemaManager();
  32. return \OC_DB_MDB2SchemaWriter::saveSchemaToFile($file, $sm);
  33. }
  34. /**
  35. * @brief Creates tables from XML file
  36. * @param string $file file to read structure from
  37. * @return bool
  38. *
  39. * TODO: write more documentation
  40. */
  41. public function createDbFromStructure( $file ) {
  42. $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform());
  43. $toSchema = $schemaReader->loadSchemaFromFile($file);
  44. return $this->executeSchemaChange($toSchema);
  45. }
  46. /**
  47. * @brief update the database scheme
  48. * @param string $file file to read structure from
  49. * @return bool
  50. */
  51. public function updateDbFromStructure($file, $generateSql = false) {
  52. $sm = $this->conn->getSchemaManager();
  53. $fromSchema = $sm->createSchema();
  54. $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform());
  55. $toSchema = $schemaReader->loadSchemaFromFile($file);
  56. // remove tables we don't know about
  57. /** @var $table \Doctrine\DBAL\Schema\Table */
  58. foreach($fromSchema->getTables() as $table) {
  59. if (!$toSchema->hasTable($table->getName())) {
  60. $fromSchema->dropTable($table->getName());
  61. }
  62. }
  63. // remove sequences we don't know about
  64. foreach($fromSchema->getSequences() as $table) {
  65. if (!$toSchema->hasSequence($table->getName())) {
  66. $fromSchema->dropSequence($table->getName());
  67. }
  68. }
  69. $comparator = new \Doctrine\DBAL\Schema\Comparator();
  70. $schemaDiff = $comparator->compare($fromSchema, $toSchema);
  71. $platform = $this->conn->getDatabasePlatform();
  72. foreach($schemaDiff->changedTables as $tableDiff) {
  73. $tableDiff->name = $platform->quoteIdentifier($tableDiff->name);
  74. }
  75. if ($generateSql) {
  76. return $this->generateChangeScript($schemaDiff);
  77. }
  78. return $this->executeSchemaChange($schemaDiff);
  79. }
  80. /**
  81. * @brief drop a table
  82. * @param string $tableName the table to drop
  83. */
  84. public function dropTable($tableName) {
  85. $sm = $this->conn->getSchemaManager();
  86. $fromSchema = $sm->createSchema();
  87. $toSchema = clone $fromSchema;
  88. $toSchema->dropTable($tableName);
  89. $sql = $fromSchema->getMigrateToSql($toSchema, $this->conn->getDatabasePlatform());
  90. $this->conn->executeQuery($sql);
  91. }
  92. /**
  93. * remove all tables defined in a database structure xml file
  94. * @param string $file the xml file describing the tables
  95. */
  96. public function removeDBStructure($file) {
  97. $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform());
  98. $fromSchema = $schemaReader->loadSchemaFromFile($file);
  99. $toSchema = clone $fromSchema;
  100. /** @var $table \Doctrine\DBAL\Schema\Table */
  101. foreach($toSchema->getTables() as $table) {
  102. $toSchema->dropTable($table->getName());
  103. }
  104. $comparator = new \Doctrine\DBAL\Schema\Comparator();
  105. $schemaDiff = $comparator->compare($fromSchema, $toSchema);
  106. $this->executeSchemaChange($schemaDiff);
  107. }
  108. /**
  109. * @brief replaces the ownCloud tables with a new set
  110. * @param $file string path to the MDB2 xml db export file
  111. */
  112. public function replaceDB( $file ) {
  113. $apps = \OC_App::getAllApps();
  114. $this->conn->beginTransaction();
  115. // Delete the old tables
  116. $this->removeDBStructure( \OC::$SERVERROOT . '/db_structure.xml' );
  117. foreach($apps as $app) {
  118. $path = \OC_App::getAppPath($app).'/appinfo/database.xml';
  119. if(file_exists($path)) {
  120. $this->removeDBStructure( $path );
  121. }
  122. }
  123. // Create new tables
  124. $this->conn->commit();
  125. }
  126. /**
  127. * @param \Doctrine\DBAL\Schema\Schema $schema
  128. * @return bool
  129. */
  130. private function executeSchemaChange($schema) {
  131. $this->conn->beginTransaction();
  132. foreach($schema->toSql($this->conn->getDatabasePlatform()) as $sql) {
  133. $this->conn->query($sql);
  134. }
  135. $this->conn->commit();
  136. return true;
  137. }
  138. /**
  139. * @param \Doctrine\DBAL\Schema\Schema $schema
  140. * @return string
  141. */
  142. public function generateChangeScript($schema) {
  143. $script = '';
  144. $sqls = $schema->toSql($this->conn->getDatabasePlatform());
  145. foreach($sqls as $sql) {
  146. $script .= $sql . ';';
  147. $script .= PHP_EOL;
  148. }
  149. return $script;
  150. }
  151. }