diff options
author | Bart Visscher <bartv@thisnet.nl> | 2012-10-10 20:49:47 +0200 |
---|---|---|
committer | Bart Visscher <bartv@thisnet.nl> | 2012-10-13 15:17:21 +0200 |
commit | 5686183e4345d798ded448b016a2f73ad5f37984 (patch) | |
tree | fd591b25002d11e3c1a9bc41d3eda7d7bff4e8e5 /lib/db | |
parent | 24b10be7625fab71ddf54f5cab59d445dac611fc (diff) | |
download | nextcloud-server-5686183e4345d798ded448b016a2f73ad5f37984.tar.gz nextcloud-server-5686183e4345d798ded448b016a2f73ad5f37984.zip |
Use Doctrine for schema changes
Diffstat (limited to 'lib/db')
-rw-r--r-- | lib/db/mdb2schemareader.php | 220 | ||||
-rw-r--r-- | lib/db/schema.php | 128 |
2 files changed, 348 insertions, 0 deletions
diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php new file mode 100644 index 00000000000..3f6cadd3dc4 --- /dev/null +++ b/lib/db/mdb2schemareader.php @@ -0,0 +1,220 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_DB_MDB2SchemaReader { + static protected $DBNAME; + static protected $DBTABLEPREFIX; + + public static function loadSchemaFromFile($file) { + self::$DBNAME = OC_Config::getValue( "dbname", "owncloud" ); + self::$DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" ); + $schema = new \Doctrine\DBAL\Schema\Schema(); + $xml = simplexml_load_file($file); + foreach($xml->children() as $child) { + switch($child->getName()) { + case 'name': + $name = (string)$child; + $name = str_replace( '*dbname*', self::$DBNAME, $name ); + break; + case 'create': + case 'overwrite': + case 'charset': + break; + case 'table': + self::loadTable($schema, $child); + break; + default: + var_dump($child->getName()); + + } + } + return $schema; + } + + private static function loadTable($schema, $xml) { + foreach($xml->children() as $child) { + switch($child->getName()) { + case 'name': + $name = (string)$child; + $name = str_replace( '*dbprefix*', self::$DBTABLEPREFIX, $name ); + $table = $schema->createTable($name); + break; + case 'create': + case 'overwrite': + case 'charset': + break; + case 'declaration': + self::loadDeclaration($table, $child); + break; + default: + var_dump($child->getName()); + + } + } + } + + private static function loadDeclaration($table, $xml) { + foreach($xml->children() as $child) { + switch($child->getName()) { + case 'field': + self::loadField($table, $child); + break; + case 'index': + self::loadIndex($table, $child); + break; + default: + var_dump($child->getName()); + + } + } + } + + private static function loadField($table, $xml) { + $options = array(); + foreach($xml->children() as $child) { + switch($child->getName()) { + case 'name': + $name = (string)$child; + break; + case 'type': + $type = (string)$child; + switch($type) { + case 'text': + $type = 'string'; + break; + case 'clob': + $type = 'text'; + break; + case 'timestamp': + $type = 'datetime'; + break; + // TODO + return; + } + break; + case 'length': + $length = (string)$child; + $options['length'] = $length; + break; + case 'unsigned': + $unsigned = self::asBool($child); + $options['unsigned'] = $unsigned; + break; + case 'notnull': + $notnull = self::asBool($child); + $options['notnull'] = $notnull; + break; + case 'autoincrement': + $autoincrement = self::asBool($child); + $options['autoincrement'] = $autoincrement; + break; + case 'default': + $default = (string)$child; + $options['default'] = $default; + break; + default: + var_dump($child->getName()); + + } + } + if (isset($name) && isset($type)) { + if ($name == 'x') { + var_dump($name, $type, $options); + echo '<pre>'; + debug_print_backtrace(); + } + if (empty($options['default'])) { + if ($type == 'integer') { + if (empty($options['default'])) { + $options['default'] = 0; + } + } + if (!empty($options['autoincrement'])) { + unset($options['default']); + } + } + if ($type == 'integer') { + $length = $options['length']; + if ($length == 1) { + $type = 'boolean'; + } + else if ($length < 4) { + $type = 'smallint'; + } + else if ($length > 4) { + $type = 'bigint'; + } + } + $table->addColumn($name, $type, $options); + if (!empty($options['autoincrement']) + && !empty($options['notnull'])) { + $table->setPrimaryKey(array($name)); + } + } + } + + private static function loadIndex($table, $xml) { + $name = null; + $fields = array(); + foreach($xml->children() as $child) { + switch($child->getName()) { + case 'name': + $name = (string)$child; + break; + case 'primary': + $primary = self::asBool($child); + break; + case 'unique': + $unique = self::asBool($child); + break; + case 'field': + foreach($child->children() as $field) { + switch($field->getName()) { + case 'name': + $field_name = (string)$field; + $fields[] = $field_name; + break; + case 'sorting': + break; + default: + var_dump($field->getName()); + + } + } + break; + default: + var_dump($child->getName()); + + } + } + if (!empty($fields)) { + if (isset($primary) && $primary) { + $table->setPrimaryKey($fields, $name); + } else + if (isset($unique) && $unique) { + $table->addUniqueIndex($fields, $name); + } else { + $table->addIndex($fields, $name); + } + } else { + var_dump($name, $fields); + } + } + + private static function asBool($xml) { + $result = (string)$xml; + if ($result == 'true') { + $result = true; + } else + if ($result == 'false') { + $result = false; + } + return (bool)$result; + } + +} diff --git a/lib/db/schema.php b/lib/db/schema.php new file mode 100644 index 00000000000..ca90e300e0d --- /dev/null +++ b/lib/db/schema.php @@ -0,0 +1,128 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_DB_Schema { + private static $DBNAME; + private static $DBTABLEPREFIX; + + /** + * @brief saves database scheme to xml file + * @param string $file name of file + * @param int $mode + * @return bool + * + * TODO: write more documentation + */ + public static function getDbStructure( $conn, $file ,$mode=MDB2_SCHEMA_DUMP_STRUCTURE) { + $sm = $conn->getSchemaManager(); + $fromSchema = $sm->createSchema(); + + return OC_DB_MDB2SchemaWriter::saveSchemaToFile($file); + } + + /** + * @brief Creates tables from XML file + * @param string $file file to read structure from + * @return bool + * + * TODO: write more documentation + */ + public static function createDbFromStructure( $conn, $file ) { + $toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file); + return self::executeSchemaChange($conn, $toSchema); + } + + /** + * @brief update the database scheme + * @param string $file file to read structure from + * @return bool + */ + public static function updateDbFromStructure($conn, $file) { + $sm = $conn->getSchemaManager(); + $fromSchema = $sm->createSchema(); + + $toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file); + + // remove tables we don't know about + foreach($fromSchema->getTables() as $table) { + if (!$toSchema->hasTable($table->getName())) { + $fromSchema->dropTable($table->getName()); + } + } + + $comparator = new \Doctrine\DBAL\Schema\Comparator(); + $schemaDiff = $comparator->compare($fromSchema, $toSchema); + + //$from = $fromSchema->toSql($conn->getDatabasePlatform()); + //$to = $toSchema->toSql($conn->getDatabasePlatform()); + //echo($from[9]); + //echo '<br>'; + //echo($to[9]); + //var_dump($from, $to); + return self::executeSchemaChange($conn, $schemaDiff); + } + + /** + * @brief drop a table + * @param string $tableName the table to drop + */ + public static function dropTable($conn, $tableName) { + $sm = $conn->getSchemaManager(); + $fromSchema = $sm->createSchema(); + $toSchema = clone $fromSchema; + $toSchema->dropTable('user'); + $sql = $fromSchema->getMigrateToSql($toSchema, $conn->getDatabasePlatform()); + var_dump($sql); + die; + $conn->execute($sql); + } + + /** + * remove all tables defined in a database structure xml file + * @param string $file the xml file describing the tables + */ + public static function removeDBStructure($conn, $file) { + $fromSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file); + $toSchema = clone $fromSchema; + foreach($toSchema->getTables() as $table) { + $toSchema->dropTable($table->getName()); + } + $comparator = new \Doctrine\DBAL\Schema\Comparator(); + $schemaDiff = $comparator->compare($fromSchema, $toSchema); + self::executeSchemaChange($conn, $schemaDiff); + } + + /** + * @brief replaces the owncloud tables with a new set + * @param $file string path to the MDB2 xml db export file + */ + public static function replaceDB( $conn, $file ) { + $apps = OC_App::getAllApps(); + self::beginTransaction(); + // Delete the old tables + self::removeDBStructure( OC::$SERVERROOT . '/db_structure.xml' ); + + foreach($apps as $app) { + $path = OC_App::getAppPath($app).'/appinfo/database.xml'; + if(file_exists($path)) { + self::removeDBStructure( $path ); + } + } + + // Create new tables + self::commit(); + } + + private static function executeSchemaChange($conn, $schema) { + $conn->beginTransaction(); + foreach($schema->toSql($conn->getDatabasePlatform()) as $sql) { + $conn->query($sql); + } + $conn->commit(); + } +} |