From dc272e6e209e9cc9a555df7ee103e48f8d088dc6 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 22 Jul 2013 16:24:46 +0200 Subject: db: cast default values for boolean fields to booleans --- lib/db/mdb2schemareader.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php index 0ead9528c93..b88e0f60419 100644 --- a/lib/db/mdb2schemareader.php +++ b/lib/db/mdb2schemareader.php @@ -167,6 +167,9 @@ class OC_DB_MDB2SchemaReader { $type = 'bigint'; } } + if ($type == 'boolean' && isset($options['default'])){ + $options['default'] = self::asBool($options['default']); + } if (!empty($options['autoincrement']) && !empty($options['notnull'])) { $options['primary'] = true; -- cgit v1.2.3 From b073a34e77d127488b414fedc5b24c31b11bc12e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 22 Jul 2013 16:25:07 +0200 Subject: add support for the element within field definitions --- lib/db/mdb2schemareader.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php index b88e0f60419..e9561a7ef1d 100644 --- a/lib/db/mdb2schemareader.php +++ b/lib/db/mdb2schemareader.php @@ -138,6 +138,10 @@ class OC_DB_MDB2SchemaReader { $comment = (string)$child; $options['comment'] = $comment; break; + case 'primary': + $primary = self::asBool($child); + $options['primary'] = $primary; + break; default: throw new DomainException('Unknown element: '.$child->getName()); -- cgit v1.2.3 From 499a01f179d511135828c10edf64348547d31794 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 22 Jul 2013 17:41:33 +0200 Subject: use === --- lib/db/mdb2schemareader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php index e9561a7ef1d..ad4b2fe0e03 100644 --- a/lib/db/mdb2schemareader.php +++ b/lib/db/mdb2schemareader.php @@ -171,7 +171,7 @@ class OC_DB_MDB2SchemaReader { $type = 'bigint'; } } - if ($type == 'boolean' && isset($options['default'])){ + if ($type === 'boolean' && isset($options['default'])){ $options['default'] = self::asBool($options['default']); } if (!empty($options['autoincrement']) -- cgit v1.2.3 From fbbe0ebe7735222b7e9502585c622ea3f98648c2 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 29 Jul 2013 16:32:37 +0200 Subject: add function to get config object from OC_Config --- lib/legacy/config.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/legacy/config.php b/lib/legacy/config.php index 5294a48ea44..7e498013737 100644 --- a/lib/legacy/config.php +++ b/lib/legacy/config.php @@ -46,6 +46,10 @@ class OC_Config { */ public static $object; + public static function getObject() { + return self::$object; + } + /** * @brief Lists all available config keys * @return array with key names -- cgit v1.2.3 From d6c56b584ac4fdb9169ed2747072d8f90cc00612 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 29 Jul 2013 16:33:00 +0200 Subject: make MDB2Schema reader non static --- lib/db/mdb2schemareader.php | 195 ++++++++++++++++++++++++++++---------------- lib/db/schema.php | 20 ++++- 2 files changed, 143 insertions(+), 72 deletions(-) diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php index ad4b2fe0e03..b7128a2f176 100644 --- a/lib/db/mdb2schemareader.php +++ b/lib/db/mdb2schemareader.php @@ -6,35 +6,57 @@ * See the COPYING-README file. */ -class OC_DB_MDB2SchemaReader { - static protected $DBNAME; - static protected $DBTABLEPREFIX; - static protected $platform; +namespace OC\DB; +class MDB2SchemaReader { /** - * @param $file - * @param $platform + * @var string $DBNAME + */ + protected $DBNAME; + + /** + * @var string $DBTABLEPREFIX + */ + protected $DBTABLEPREFIX; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + protected $platform; + + /** + * @param \OC\Config $config + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct($config, $platform) { + $this->platform = $platform; + $this->DBNAME = $config->getValue('dbname', 'owncloud'); + $this->DBTABLEPREFIX = $config->getValue('dbtableprefix', 'oc_'); + } + + /** + * @param string $file * @return \Doctrine\DBAL\Schema\Schema - * @throws DomainException + * @throws \DomainException */ - public static function loadSchemaFromFile($file, $platform) { - self::$DBNAME = OC_Config::getValue( "dbname", "owncloud" ); - self::$DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" ); - self::$platform = $platform; + public function loadSchemaFromFile($file) { $schema = new \Doctrine\DBAL\Schema\Schema(); $xml = simplexml_load_file($file); - foreach($xml->children() as $child) { - switch($child->getName()) { + foreach ($xml->children() as $child) { + /** + * @var \SimpleXMLElement $child + */ + switch ($child->getName()) { case 'name': case 'create': case 'overwrite': case 'charset': break; case 'table': - self::loadTable($schema, $child); + $this->loadTable($schema, $child); break; default: - throw new DomainException('Unknown element: '.$child->getName()); + throw new \DomainException('Unknown element: ' . $child->getName()); } } @@ -43,16 +65,20 @@ class OC_DB_MDB2SchemaReader { /** * @param\Doctrine\DBAL\Schema\Schema $schema - * @param $xml - * @throws DomainException + * @param \SimpleXMLElement $xml + * @throws \DomainException */ - private static function loadTable($schema, $xml) { - foreach($xml->children() as $child) { - switch($child->getName()) { + private function loadTable($schema, $xml) { + $table = null; + foreach ($xml->children() as $child) { + /** + * @var \SimpleXMLElement $child + */ + switch ($child->getName()) { case 'name': $name = (string)$child; - $name = str_replace( '*dbprefix*', self::$DBTABLEPREFIX, $name ); - $name = self::$platform->quoteIdentifier($name); + $name = str_replace('*dbprefix*', $this->DBTABLEPREFIX, $name); + $name = $this->platform->quoteIdentifier($name); $table = $schema->createTable($name); break; case 'create': @@ -60,10 +86,13 @@ class OC_DB_MDB2SchemaReader { case 'charset': break; case 'declaration': - self::loadDeclaration($table, $child); + if (is_null($table)) { + throw new \DomainException('Table declaration before table name'); + } + $this->loadDeclaration($table, $child); break; default: - throw new DomainException('Unknown element: '.$child->getName()); + throw new \DomainException('Unknown element: ' . $child->getName()); } } @@ -71,36 +100,47 @@ class OC_DB_MDB2SchemaReader { /** * @param \Doctrine\DBAL\Schema\Table $table - * @param $xml - * @throws DomainException + * @param \SimpleXMLElement $xml + * @throws \DomainException */ - private static function loadDeclaration($table, $xml) { - foreach($xml->children() as $child) { - switch($child->getName()) { + private function loadDeclaration($table, $xml) { + foreach ($xml->children() as $child) { + /** + * @var \SimpleXMLElement $child + */ + switch ($child->getName()) { case 'field': - self::loadField($table, $child); + $this->loadField($table, $child); break; case 'index': - self::loadIndex($table, $child); + $this->loadIndex($table, $child); break; default: - throw new DomainException('Unknown element: '.$child->getName()); + throw new \DomainException('Unknown element: ' . $child->getName()); } } } - private static function loadField($table, $xml) { + /** + * @param \Doctrine\DBAL\Schema\Table $table + * @param \SimpleXMLElement $xml + * @throws \DomainException + */ + private function loadField($table, $xml) { $options = array(); - foreach($xml->children() as $child) { - switch($child->getName()) { + foreach ($xml->children() as $child) { + /** + * @var \SimpleXMLElement $child + */ + switch ($child->getName()) { case 'name': $name = (string)$child; - $name = self::$platform->quoteIdentifier($name); + $name = $this->platform->quoteIdentifier($name); break; case 'type': $type = (string)$child; - switch($type) { + switch ($type) { case 'text': $type = 'string'; break; @@ -110,8 +150,6 @@ class OC_DB_MDB2SchemaReader { case 'timestamp': $type = 'datetime'; break; - // TODO - return; } break; case 'length': @@ -119,15 +157,15 @@ class OC_DB_MDB2SchemaReader { $options['length'] = $length; break; case 'unsigned': - $unsigned = self::asBool($child); + $unsigned = $this->asBool($child); $options['unsigned'] = $unsigned; break; case 'notnull': - $notnull = self::asBool($child); + $notnull = $this->asBool($child); $options['notnull'] = $notnull; break; case 'autoincrement': - $autoincrement = self::asBool($child); + $autoincrement = $this->asBool($child); $options['autoincrement'] = $autoincrement; break; case 'default': @@ -139,11 +177,11 @@ class OC_DB_MDB2SchemaReader { $options['comment'] = $comment; break; case 'primary': - $primary = self::asBool($child); + $primary = $this->asBool($child); $options['primary'] = $primary; break; default: - throw new DomainException('Unknown element: '.$child->getName()); + throw new \DomainException('Unknown element: ' . $child->getName()); } } @@ -157,25 +195,30 @@ class OC_DB_MDB2SchemaReader { } if ($type == 'integer') { $options['default'] = 0; + } elseif ($type == 'boolean') { + $options['default'] = false; } if (!empty($options['autoincrement']) && $options['autoincrement']) { unset($options['default']); } } - if ($type == 'integer' && isset($options['length'])) { + if ($type === 'integer' && isset($options['default'])) { + $options['default'] = (int)$options['default']; + } + if ($type === 'integer' && isset($options['length'])) { $length = $options['length']; if ($length < 4) { $type = 'smallint'; - } - else if ($length > 4) { + } else if ($length > 4) { $type = 'bigint'; } } - if ($type === 'boolean' && isset($options['default'])){ - $options['default'] = self::asBool($options['default']); + if ($type === 'boolean' && isset($options['default'])) { + $options['default'] = $this->asBool($options['default']); } if (!empty($options['autoincrement']) - && !empty($options['notnull'])) { + && !empty($options['notnull']) + ) { $options['primary'] = true; } $table->addColumn($name, $type, $options); @@ -185,38 +228,49 @@ class OC_DB_MDB2SchemaReader { } } - private static function loadIndex($table, $xml) { + /** + * @param \Doctrine\DBAL\Schema\Table $table + * @param \SimpleXMLElement $xml + * @throws \DomainException + */ + private function loadIndex($table, $xml) { $name = null; $fields = array(); - foreach($xml->children() as $child) { - switch($child->getName()) { + foreach ($xml->children() as $child) { + /** + * @var \SimpleXMLElement $child + */ + switch ($child->getName()) { case 'name': $name = (string)$child; break; case 'primary': - $primary = self::asBool($child); + $primary = $this->asBool($child); break; case 'unique': - $unique = self::asBool($child); + $unique = $this->asBool($child); break; case 'field': - foreach($child->children() as $field) { - switch($field->getName()) { + foreach ($child->children() as $field) { + /** + * @var \SimpleXMLElement $field + */ + switch ($field->getName()) { case 'name': $field_name = (string)$field; - $field_name = self::$platform->quoteIdentifier($field_name); + $field_name = $this->platform->quoteIdentifier($field_name); $fields[] = $field_name; break; case 'sorting': break; default: - throw new DomainException('Unknown element: '.$field->getName()); + throw new \DomainException('Unknown element: ' . $field->getName()); } } break; default: - throw new DomainException('Unknown element: '.$child->getName()); + throw new \DomainException('Unknown element: ' . $child->getName()); } } @@ -224,22 +278,25 @@ class OC_DB_MDB2SchemaReader { if (isset($primary) && $primary) { $table->setPrimaryKey($fields, $name); } else - if (isset($unique) && $unique) { - $table->addUniqueIndex($fields, $name); - } else { - $table->addIndex($fields, $name); - } + if (isset($unique) && $unique) { + $table->addUniqueIndex($fields, $name); + } else { + $table->addIndex($fields, $name); + } } else { - throw new DomainException('Empty index definition: '.$name.' options:'. print_r($fields, true)); + throw new \DomainException('Empty index definition: ' . $name . ' options:' . print_r($fields, true)); } } - private static function asBool($xml) { + /** + * @param \SimpleXMLElement | string $xml + * @return bool + */ + private function asBool($xml) { $result = (string)$xml; if ($result == 'true') { $result = true; - } else - if ($result == 'false') { + } elseif ($result == 'false') { $result = false; } return (bool)$result; diff --git a/lib/db/schema.php b/lib/db/schema.php index fa053c64ef0..bc82249609d 100644 --- a/lib/db/schema.php +++ b/lib/db/schema.php @@ -24,18 +24,21 @@ class OC_DB_Schema { /** * @brief Creates tables from XML file + * @param \Doctrine\DBAL\Connection $conn * @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, $conn->getDatabasePlatform()); + $schemaReader = new \OC\DB\MDB2SchemaReader(\OC_Config::getObject(), $conn->getDatabasePlatform()); + $toSchema = $schemaReader->loadSchemaFromFile($file); return self::executeSchemaChange($conn, $toSchema); } /** * @brief update the database scheme + * @param \Doctrine\DBAL\Connection $conn * @param string $file file to read structure from * @return bool */ @@ -43,7 +46,8 @@ class OC_DB_Schema { $sm = $conn->getSchemaManager(); $fromSchema = $sm->createSchema(); - $toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform()); + $schemaReader = new \OC\DB\MDB2SchemaReader(\OC_Config::getObject(), $conn->getDatabasePlatform()); + $toSchema = $schemaReader->loadSchemaFromFile($file); // remove tables we don't know about foreach($fromSchema->getTables() as $table) { @@ -79,6 +83,7 @@ class OC_DB_Schema { /** * @brief drop a table + * @param \Doctrine\DBAL\Connection $conn * @param string $tableName the table to drop */ public static function dropTable($conn, $tableName) { @@ -92,10 +97,12 @@ class OC_DB_Schema { /** * remove all tables defined in a database structure xml file + * @param \Doctrine\DBAL\Connection $conn * @param string $file the xml file describing the tables */ public static function removeDBStructure($conn, $file) { - $fromSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform()); + $schemaReader = new \OC\DB\MDB2SchemaReader(\OC_Config::getObject(), $conn->getDatabasePlatform()); + $fromSchema = $schemaReader->loadSchemaFromFile($file); $toSchema = clone $fromSchema; foreach($toSchema->getTables() as $table) { $toSchema->dropTable($table->getName()); @@ -107,6 +114,7 @@ class OC_DB_Schema { /** * @brief replaces the ownCloud tables with a new set + * @param \Doctrine\DBAL\Connection $conn * @param $file string path to the MDB2 xml db export file */ public static function replaceDB( $conn, $file ) { @@ -126,11 +134,17 @@ class OC_DB_Schema { self::commit(); } + /** + * @param \Doctrine\DBAL\Connection $conn + * @param \Doctrine\DBAL\Schema\Schema $schema + * @return bool + */ private static function executeSchemaChange($conn, $schema) { $conn->beginTransaction(); foreach($schema->toSql($conn->getDatabasePlatform()) as $sql) { $conn->query($sql); } $conn->commit(); + return true; } } -- cgit v1.2.3 From a4df982dc3b2f88078d0ef4a4dbe0fdc1d37105a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 29 Jul 2013 16:33:27 +0200 Subject: add tests for MDB2SchemaReader --- tests/lib/db/mdb2schemareader.php | 80 +++++++++++++++++++++++++++++++++++++++ tests/lib/db/testschema.xml | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 tests/lib/db/mdb2schemareader.php create mode 100644 tests/lib/db/testschema.xml diff --git a/tests/lib/db/mdb2schemareader.php b/tests/lib/db/mdb2schemareader.php new file mode 100644 index 00000000000..b9b241194fd --- /dev/null +++ b/tests/lib/db/mdb2schemareader.php @@ -0,0 +1,80 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\DB; + +use Doctrine\DBAL\Platforms\MySqlPlatform; + +class MDB2SchemaReader extends \PHPUnit_Framework_TestCase { + /** + * @var \OC\DB\MDB2SchemaReader $reader + */ + protected $reader; + + /** + * @return \OC\Config + */ + protected function getConfig() { + $config = $this->getMockBuilder('\OC\Config') + ->disableOriginalConstructor() + ->getMock(); + $config->expects($this->any()) + ->method('getValue') + ->will($this->returnValueMap(array( + array('dbname', 'owncloud', 'testDB'), + array('dbtableprefix', 'oc_', 'test_') + ))); + return $config; + } + + public function testRead() { + $reader = new \OC\DB\MDB2SchemaReader($this->getConfig(), new MySqlPlatform()); + $schema = $reader->loadSchemaFromFile(__DIR__ . '/testschema.xml'); + $this->assertCount(1, $schema->getTables()); + + $table = $schema->getTable('test_table'); + $this->assertCount(7, $table->getColumns()); + + $this->assertEquals(4, $table->getColumn('integerfield')->getLength()); + $this->assertTrue($table->getColumn('integerfield')->getAutoincrement()); + $this->assertNull($table->getColumn('integerfield')->getDefault()); + $this->assertTrue($table->getColumn('integerfield')->getNotnull()); + $this->assertInstanceOf('Doctrine\DBAL\Types\IntegerType', $table->getColumn('integerfield')->getType()); + + $this->assertSame(10, $table->getColumn('integerfield_default')->getDefault()); + + $this->assertEquals(32, $table->getColumn('textfield')->getLength()); + $this->assertFalse($table->getColumn('textfield')->getAutoincrement()); + $this->assertSame('foo', $table->getColumn('textfield')->getDefault()); + $this->assertTrue($table->getColumn('textfield')->getNotnull()); + $this->assertInstanceOf('Doctrine\DBAL\Types\StringType', $table->getColumn('textfield')->getType()); + + $this->assertNull($table->getColumn('clobfield')->getLength()); + $this->assertFalse($table->getColumn('clobfield')->getAutoincrement()); + $this->assertSame('', $table->getColumn('clobfield')->getDefault()); + $this->assertTrue($table->getColumn('clobfield')->getNotnull()); + $this->assertInstanceOf('Doctrine\DBAL\Types\TextType', $table->getColumn('clobfield')->getType()); + + $this->assertNull($table->getColumn('booleanfield')->getLength()); + $this->assertFalse($table->getColumn('booleanfield')->getAutoincrement()); + $this->assertFalse($table->getColumn('booleanfield')->getDefault()); + $this->assertInstanceOf('Doctrine\DBAL\Types\BooleanType', $table->getColumn('booleanfield')->getType()); + + $this->assertTrue($table->getColumn('booleanfield_true')->getDefault()); + $this->assertFalse($table->getColumn('booleanfield_false')->getDefault()); + + $this->assertCount(2, $table->getIndexes()); + $this->assertEquals(array('integerfield'), $table->getIndex('primary')->getUnquotedColumns()); + $this->assertTrue($table->getIndex('primary')->isPrimary()); + $this->assertTrue($table->getIndex('primary')->isUnique()); + $this->assertEquals(array('booleanfield'), $table->getIndex('index_boolean')->getUnquotedColumns()); + $this->assertFalse($table->getIndex('index_boolean')->isPrimary()); + $this->assertFalse($table->getIndex('index_boolean')->isUnique()); + } +} diff --git a/tests/lib/db/testschema.xml b/tests/lib/db/testschema.xml new file mode 100644 index 00000000000..509b55ee81f --- /dev/null +++ b/tests/lib/db/testschema.xml @@ -0,0 +1,77 @@ + + + + *dbname* + true + false + + utf8 + + + + *dbprefix*table + + + + integerfield + integer + 0 + true + 1 + 4 + + + integerfield_default + integer + 10 + true + 4 + + + textfield + text + foo + true + 32 + + + clobfield + clob + true + + + booleanfield + boolean + + + booleanfield_true + boolean + true + + + booleanfield_false + boolean + false + + + + index_primary + true + true + + integerfield + ascending + + + + + index_boolean + false + + booleanfield + ascending + + + +
+
-- cgit v1.2.3