diff options
Diffstat (limited to 'lib/db')
-rw-r--r-- | lib/db/adapter.php | 72 | ||||
-rw-r--r-- | lib/db/adapteroci8.php | 28 | ||||
-rw-r--r-- | lib/db/adapterpgsql.php | 23 | ||||
-rw-r--r-- | lib/db/adaptersqlite.php | 60 | ||||
-rw-r--r-- | lib/db/adaptersqlsrv.php | 28 | ||||
-rw-r--r-- | lib/db/connection.php | 197 | ||||
-rw-r--r-- | lib/db/mdb2schemamanager.php (renamed from lib/db/schema.php) | 92 | ||||
-rw-r--r-- | lib/db/mdb2schemareader.php | 196 | ||||
-rw-r--r-- | lib/db/statementwrapper.php | 4 |
9 files changed, 593 insertions, 107 deletions
diff --git a/lib/db/adapter.php b/lib/db/adapter.php new file mode 100644 index 00000000000..6b31f37dd98 --- /dev/null +++ b/lib/db/adapter.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\DB; + +/** + * This handles the way we use to write queries, into something that can be + * handled by the database abstraction layer. + */ +class Adapter { + + /** + * @var \OC\DB\Connection $conn + */ + protected $conn; + + public function __construct($conn) { + $this->conn = $conn; + } + + /** + * @param string $table name + * @return int id of last insert statement + */ + public function lastInsertId($table) { + return $this->conn->realLastInsertId($table); + } + + /** + * @param string $statement that needs to be changed so the db can handle it + * @return string changed statement + */ + public function fixupStatement($statement) { + return $statement; + } + + /** + * @brief insert the @input values when they do not exist yet + * @param string $table name + * @param array $input key->value pairs + * @return int count of inserted rows + */ + public function insertIfNotExist($table, $input) { + $query = 'INSERT INTO `' .$table . '` (`' + . implode('`,`', array_keys($input)) . '`) SELECT ' + . str_repeat('?,', count($input)-1).'? ' // Is there a prettier alternative? + . 'FROM `' . $table . '` WHERE '; + + foreach($input as $key => $value) { + $query .= '`' . $key . '` = ? AND '; + } + $query = substr($query, 0, strlen($query) - 5); + $query .= ' HAVING COUNT(*) = 0'; + $inserts = array_values($input); + $inserts = array_merge($inserts, $inserts); + + try { + return $this->conn->executeUpdate($query, $inserts); + } catch(\Doctrine\DBAL\DBALException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; + $entry .= 'Offending command was: ' . $query.'<br />'; + \OC_Log::write('core', $entry, \OC_Log::FATAL); + error_log('DB error: ' . $entry); + \OC_Template::printErrorPage( $entry ); + } + } +} diff --git a/lib/db/adapteroci8.php b/lib/db/adapteroci8.php new file mode 100644 index 00000000000..bc226e979ec --- /dev/null +++ b/lib/db/adapteroci8.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +namespace OC\DB; + +class AdapterOCI8 extends Adapter { + public function lastInsertId($table) { + if($table !== null) { + $suffix = '_SEQ'; + $table = '"'.$table.$suffix.'"'; + } + return $this->conn->realLastInsertId($table); + } + + const UNIX_TIMESTAMP_REPLACEMENT = "(cast(sys_extract_utc(systimestamp) as date) - date'1970-01-01') * 86400"; + public function fixupStatement($statement) { + $statement = str_replace( '`', '"', $statement ); + $statement = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement ); + return $statement; + } +} diff --git a/lib/db/adapterpgsql.php b/lib/db/adapterpgsql.php new file mode 100644 index 00000000000..990d71c9f29 --- /dev/null +++ b/lib/db/adapterpgsql.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +namespace OC\DB; + +class AdapterPgSql extends Adapter { + public function lastInsertId($table) { + return $this->conn->fetchColumn('SELECT lastval()'); + } + + const UNIX_TIMESTAMP_REPLACEMENT = 'cast(extract(epoch from current_timestamp) as integer)'; + public function fixupStatement($statement) { + $statement = str_replace( '`', '"', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement ); + return $statement; + } +} diff --git a/lib/db/adaptersqlite.php b/lib/db/adaptersqlite.php new file mode 100644 index 00000000000..fa6d308ae32 --- /dev/null +++ b/lib/db/adaptersqlite.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +namespace OC\DB; + +class AdapterSqlite extends Adapter { + public function fixupStatement($statement) { + $statement = str_replace( '`', '"', $statement ); + $statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement ); + return $statement; + } + + public function insertIfNotExist($table, $input) { + // NOTE: For SQLite we have to use this clumsy approach + // otherwise all fieldnames used must have a unique key. + $query = 'SELECT COUNT(*) FROM `' . $table . '` WHERE '; + foreach($input as $key => $value) { + $query .= '`' . $key . '` = ? AND '; + } + $query = substr($query, 0, strlen($query) - 5); + try { + $stmt = $this->conn->prepare($query); + $result = $stmt->execute(array_values($input)); + } catch(\Doctrine\DBAL\DBALException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; + $entry .= 'Offending command was: ' . $query . '<br />'; + \OC_Log::write('core', $entry, \OC_Log::FATAL); + error_log('DB error: '.$entry); + \OC_Template::printErrorPage( $entry ); + } + + if ($stmt->fetchColumn() === '0') { + $query = 'INSERT INTO `' . $table . '` (`' + . implode('`,`', array_keys($input)) . '`) VALUES(' + . str_repeat('?,', count($input)-1).'? ' . ')'; + } else { + return 0; //no rows updated + } + + try { + $statement = $this->conn->prepare($query); + $result = $statement->execute(array_values($input)); + } catch(\Doctrine\DBAL\DBALException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; + $entry .= 'Offending command was: ' . $query.'<br />'; + \OC_Log::write('core', $entry, \OC_Log::FATAL); + error_log('DB error: ' . $entry); + \OC_Template::printErrorPage( $entry ); + } + + return $result; + } +} diff --git a/lib/db/adaptersqlsrv.php b/lib/db/adaptersqlsrv.php new file mode 100644 index 00000000000..d0a67af28a7 --- /dev/null +++ b/lib/db/adaptersqlsrv.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +namespace OC\DB; + +class AdapterSQLSrv extends Adapter { + public function lastInsertId($table) { + if($table !== null) { + $table = $this->conn->replaceTablePrefix( $table ); + } + return $this->conn->lastInsertId($table); + } + + public function fixupStatement($statement) { + $statement = preg_replace( "/\`(.*?)`/", "[$1]", $statement ); + $statement = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $statement ); + $statement = str_replace( 'LENGTH(', 'LEN(', $statement ); + $statement = str_replace( 'SUBSTR(', 'SUBSTRING(', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', 'DATEDIFF(second,{d \'1970-01-01\'},GETDATE())', $statement ); + return $statement; + } +} diff --git a/lib/db/connection.php b/lib/db/connection.php new file mode 100644 index 00000000000..2581969dbd0 --- /dev/null +++ b/lib/db/connection.php @@ -0,0 +1,197 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\DB; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Configuration; +use Doctrine\DBAL\Cache\QueryCacheProfile; +use Doctrine\Common\EventManager; + +class Connection extends \Doctrine\DBAL\Connection { + /** + * @var string $tablePrefix + */ + protected $tablePrefix; + + /** + * @var \OC\DB\Adapter $adapter + */ + protected $adapter; + + /** + * @var \Doctrine\DBAL\Driver\Statement[] $preparedQueries + */ + protected $preparedQueries = array(); + + protected $cachingQueryStatementEnabled = true; + + /** + * Initializes a new instance of the Connection class. + * + * @param array $params The connection parameters. + * @param \Doctrine\DBAL\Driver $driver + * @param \Doctrine\DBAL\Configuration $config + * @param \Doctrine\Common\EventManager $eventManager + * @throws \Exception + */ + public function __construct(array $params, Driver $driver, Configuration $config = null, + EventManager $eventManager = null) + { + if (!isset($params['adapter'])) { + throw new \Exception('adapter not set'); + } + if (!isset($params['tablePrefix'])) { + throw new \Exception('tablePrefix not set'); + } + parent::__construct($params, $driver, $config, $eventManager); + $this->adapter = new $params['adapter']($this); + $this->tablePrefix = $params['tablePrefix']; + } + + /** + * Prepares an SQL statement. + * + * @param string $statement The SQL statement to prepare. + * @param int $limit + * @param int $offset + * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + */ + public function prepare( $statement, $limit=null, $offset=null ) { + if ($limit === -1) { + $limit = null; + } + if (!is_null($limit)) { + $platform = $this->getDatabasePlatform(); + $statement = $platform->modifyLimitQuery($statement, $limit, $offset); + } else { + if (isset($this->preparedQueries[$statement]) && $this->cachingQueryStatementEnabled) { + return $this->preparedQueries[$statement]; + } + $origStatement = $statement; + } + $statement = $this->replaceTablePrefix($statement); + $statement = $this->adapter->fixupStatement($statement); + + if(\OC_Config::getValue( 'log_query', false)) { + \OC_Log::write('core', 'DB prepare : '.$statement, \OC_Log::DEBUG); + } + $result = parent::prepare($statement); + if (is_null($limit) && $this->cachingQueryStatementEnabled) { + $this->preparedQueries[$origStatement] = $result; + } + return $result; + } + + /** + * Executes an, optionally parameterized, SQL query. + * + * If the query is parameterized, a prepared statement is used. + * If an SQLLogger is configured, the execution is logged. + * + * @param string $query The SQL query to execute. + * @param array $params The parameters to bind to the query, if any. + * @param array $types The types the previous parameters are in. + * @param QueryCacheProfile $qcp + * @return \Doctrine\DBAL\Driver\Statement The executed statement. + * @internal PERF: Directly prepares a driver statement, not a wrapper. + */ + public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) + { + $query = $this->replaceTablePrefix($query); + $query = $this->adapter->fixupStatement($query); + return parent::executeQuery($query, $params, $types, $qcp); + } + + /** + * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters + * and returns the number of affected rows. + * + * This method supports PDO binding types as well as DBAL mapping types. + * + * @param string $query The SQL query. + * @param array $params The query parameters. + * @param array $types The parameter types. + * @return integer The number of affected rows. + * @internal PERF: Directly prepares a driver statement, not a wrapper. + */ + public function executeUpdate($query, array $params = array(), array $types = array()) + { + $query = $this->replaceTablePrefix($query); + $query = $this->adapter->fixupStatement($query); + return parent::executeUpdate($query, $params, $types); + } + + /** + * Returns the ID of the last inserted row, or the last value from a sequence object, + * depending on the underlying driver. + * + * Note: This method may not return a meaningful or consistent result across different drivers, + * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY + * columns or sequences. + * + * @param string $seqName Name of the sequence object from which the ID should be returned. + * @return string A string representation of the last inserted ID. + */ + public function lastInsertId($seqName = null) + { + if ($seqName) { + $seqName = $this->replaceTablePrefix($seqName); + } + return $this->adapter->lastInsertId($seqName); + } + + // internal use + public function realLastInsertId($seqName = null) + { + return parent::lastInsertId($seqName); + } + + /** + * @brief Insert a row if a matching row doesn't exists. + * @param string $table. The table to insert into in the form '*PREFIX*tableName' + * @param array $input. An array of fieldname/value pairs + * @return bool The return value from execute() + */ + public function insertIfNotExist($table, $input) { + return $this->adapter->insertIfNotExist($table, $input); + } + + /** + * returns the error code and message as a string for logging + * works with DoctrineException + * @return string + */ + public function getError() { + $msg = $this->errorCode() . ': '; + $errorInfo = $this->errorInfo(); + if (is_array($errorInfo)) { + $msg .= 'SQLSTATE = '.$errorInfo[0] . ', '; + $msg .= 'Driver Code = '.$errorInfo[1] . ', '; + $msg .= 'Driver Message = '.$errorInfo[2]; + } + return $msg; + } + + // internal use + /** + * @param string $statement + * @return string + */ + protected function replaceTablePrefix($statement) { + return str_replace( '*PREFIX*', $this->tablePrefix, $statement ); + } + + public function enableQueryStatementCaching() { + $this->cachingQueryStatementEnabled = true; + } + + public function disableQueryStatementCaching() { + $this->cachingQueryStatementEnabled = false; + $this->preparedQueries = array(); + } +} diff --git a/lib/db/schema.php b/lib/db/mdb2schemamanager.php index fa053c64ef0..8e76f46c78f 100644 --- a/lib/db/schema.php +++ b/lib/db/mdb2schemamanager.php @@ -6,20 +6,33 @@ * See the COPYING-README file. */ -class OC_DB_Schema { +namespace OC\DB; + +class MDB2SchemaManager { + /** + * @var \OC\DB\Connection $conn + */ + protected $conn; + + /** + * @param \OC\DB\Connection $conn + */ + public function __construct($conn) { + $this->conn = $conn; + } + /** * @brief saves database scheme to xml file - * @param \Doctrine\DBAL\Connection $conn * @param string $file name of file * @param int|string $mode * @return bool * * TODO: write more documentation */ - public static function getDbStructure( $conn, $file, $mode=MDB2_SCHEMA_DUMP_STRUCTURE) { - $sm = $conn->getSchemaManager(); + public function getDbStructure( $file, $mode = MDB2_SCHEMA_DUMP_STRUCTURE) { + $sm = $this->conn->getSchemaManager(); - return OC_DB_MDB2SchemaWriter::saveSchemaToFile($file, $sm); + return \OC_DB_MDB2SchemaWriter::saveSchemaToFile($file, $sm); } /** @@ -29,9 +42,10 @@ class OC_DB_Schema { * * TODO: write more documentation */ - public static function createDbFromStructure( $conn, $file ) { - $toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform()); - return self::executeSchemaChange($conn, $toSchema); + public function createDbFromStructure( $file ) { + $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform()); + $toSchema = $schemaReader->loadSchemaFromFile($file); + return $this->executeSchemaChange($toSchema); } /** @@ -39,11 +53,12 @@ class OC_DB_Schema { * @param string $file file to read structure from * @return bool */ - public static function updateDbFromStructure($conn, $file) { - $sm = $conn->getSchemaManager(); + public function updateDbFromStructure($file) { + $sm = $this->conn->getSchemaManager(); $fromSchema = $sm->createSchema(); - $toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform()); + $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform()); + $toSchema = $schemaReader->loadSchemaFromFile($file); // remove tables we don't know about foreach($fromSchema->getTables() as $table) { @@ -61,76 +76,75 @@ class OC_DB_Schema { $comparator = new \Doctrine\DBAL\Schema\Comparator(); $schemaDiff = $comparator->compare($fromSchema, $toSchema); - $platform = $conn->getDatabasePlatform(); + $platform = $this->conn->getDatabasePlatform(); $tables = $schemaDiff->newTables + $schemaDiff->changedTables + $schemaDiff->removedTables; foreach($tables as $tableDiff) { $tableDiff->name = $platform->quoteIdentifier($tableDiff->name); } - - //$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); + return $this->executeSchemaChange($schemaDiff); } /** * @brief drop a table * @param string $tableName the table to drop */ - public static function dropTable($conn, $tableName) { - $sm = $conn->getSchemaManager(); + public function dropTable($tableName) { + $sm = $this->conn->getSchemaManager(); $fromSchema = $sm->createSchema(); $toSchema = clone $fromSchema; $toSchema->dropTable($tableName); - $sql = $fromSchema->getMigrateToSql($toSchema, $conn->getDatabasePlatform()); - $conn->execute($sql); + $sql = $fromSchema->getMigrateToSql($toSchema, $this->conn->getDatabasePlatform()); + $this->conn->executeQuery($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, $conn->getDatabasePlatform()); + public function removeDBStructure($file) { + $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform()); + $fromSchema = $schemaReader->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); + $this->executeSchemaChange($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(); + public function replaceDB( $file ) { + $apps = \OC_App::getAllApps(); + $this->conn->beginTransaction(); // Delete the old tables - self::removeDBStructure( $conn, OC::$SERVERROOT . '/db_structure.xml' ); + $this->removeDBStructure( \OC::$SERVERROOT . '/db_structure.xml' ); foreach($apps as $app) { - $path = OC_App::getAppPath($app).'/appinfo/database.xml'; + $path = \OC_App::getAppPath($app).'/appinfo/database.xml'; if(file_exists($path)) { - self::removeDBStructure( $conn, $path ); + $this->removeDBStructure( $path ); } } // Create new tables - self::commit(); + $this->conn->commit(); } - private static function executeSchemaChange($conn, $schema) { - $conn->beginTransaction(); - foreach($schema->toSql($conn->getDatabasePlatform()) as $sql) { - $conn->query($sql); + /** + * @param \Doctrine\DBAL\Schema\Schema $schema + * @return bool + */ + private function executeSchemaChange($schema) { + $this->conn->beginTransaction(); + foreach($schema->toSql($this->conn->getDatabasePlatform()) as $sql) { + $this->conn->query($sql); } - $conn->commit(); + $this->conn->commit(); + return true; } } diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php index 0ead9528c93..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': @@ -138,8 +176,12 @@ class OC_DB_MDB2SchemaReader { $comment = (string)$child; $options['comment'] = $comment; break; + case 'primary': + $primary = $this->asBool($child); + $options['primary'] = $primary; + break; default: - throw new DomainException('Unknown element: '.$child->getName()); + throw new \DomainException('Unknown element: ' . $child->getName()); } } @@ -153,22 +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'] = $this->asBool($options['default']); + } if (!empty($options['autoincrement']) - && !empty($options['notnull'])) { + && !empty($options['notnull']) + ) { $options['primary'] = true; } $table->addColumn($name, $type, $options); @@ -178,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()); } } @@ -217,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/statementwrapper.php b/lib/db/statementwrapper.php index f7bc45e068f..b8da1afc0e5 100644 --- a/lib/db/statementwrapper.php +++ b/lib/db/statementwrapper.php @@ -53,7 +53,7 @@ class OC_DB_StatementWrapper { */ public function execute($input=array()) { if(OC_Config::getValue( "log_query", false)) { - $params_str = str_replace("\n"," ",var_export($input,true)); + $params_str = str_replace("\n", " ", var_export($input, true)); OC_Log::write('core', 'DB execute with arguments : '.$params_str, OC_Log::DEBUG); } $this->lastArguments = $input; @@ -134,7 +134,7 @@ class OC_DB_StatementWrapper { $host = OC_Config::getValue( "dbhost", "" ); $user = OC_Config::getValue( "dbuser", "" ); $pass = OC_Config::getValue( "dbpassword", "" ); - if (strpos($host,':')) { + if (strpos($host, ':')) { list($host, $port) = explode(':', $host, 2); } else { $port = false; |