Skip to content
Snippets Groups Projects
Commit f9853b25 authored by Andreas Fischer's avatar Andreas Fischer
Browse files

Deduplicate connection handling code into \OC\DB\ConnectionFactory

parent a585cec5
No related branches found
No related tags found
No related merge requests found
......@@ -21,11 +21,18 @@ class ConvertType extends Command {
*/
protected $config;
/**
* @var \OC\DB\ConnectionFactory
*/
protected $connectionFactory;
/**
* @param \OC\Config $config
* @param \OC\DB\ConnectionFactory $connectionFactory
*/
public function __construct($config) {
public function __construct($config, $connectionFactory) {
$this->config = $config;
$this->connectionFactory = $connectionFactory;
parent::__construct();
}
......@@ -87,12 +94,6 @@ class ConvertType extends Command {
;
}
private static $type2driver = array(
'mysql' => 'pdo_mysql',
'pgsql' => 'pdo_pgsql',
'oci' => 'oci8',
'mssql' => 'pdo_sqlsrv',
);
protected function execute(InputInterface $input, OutputInterface $output) {
$fromDB = \OC_DB::getConnection();
$toDB = $this->getToDBConnection($input, $output);
......@@ -140,35 +141,17 @@ class ConvertType extends Command {
private function getToDBConnection($input, $output) {
$type = $input->getArgument('type');
$username = $input->getArgument('username');
$hostname = $input->getArgument('hostname');
$dbname = $input->getArgument('database');
$password = $input->getOption('password');
if (!isset(self::$type2driver[$type])) {
throw new \InvalidArgumentException('Unknown type: '.$type);
}
$connectionParams = array(
'driver' => self::$type2driver[$type],
'user' => $username,
'password' => $password,
'host' => $hostname,
'dbname' => $dbname,
'host' => $input->getArgument('hostname'),
'user' => $input->getArgument('username'),
'password' => $input->getOption('password'),
'dbname' => $input->getArgument('database'),
'tablePrefix' => $this->config->getValue('dbtableprefix', 'oc_'),
);
if ($input->getOption('port')) {
$connectionParams['port'] = $input->getOption('port');
}
switch ($type) {
case 'mysql':
case 'mssql':
$connectionParams['charset'] = 'UTF8';
break;
case 'oci':
$connectionParams['charset'] = 'AL32UTF8';
break;
}
return \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
return $this->connectionFactory->getConnection($type, $connectionParams);
}
private function getTables($db) {
......
......@@ -9,7 +9,7 @@
/** @var $application Symfony\Component\Console\Application */
$application->add(new OC\Core\Command\Status);
$application->add(new OC\Core\Command\Db\GenerateChangeScript());
$application->add(new OC\Core\Command\Db\ConvertType(OC_Config::getObject()));
$application->add(new OC\Core\Command\Db\ConvertType(OC_Config::getObject(), new \OC\DB\ConnectionFactory()));
$application->add(new OC\Core\Command\Upgrade());
$application->add(new OC\Core\Command\Maintenance\SingleUser());
$application->add(new OC\Core\Command\App\Disable());
......
......@@ -72,102 +72,45 @@ class OC_DB {
$port=false;
}
// do nothing if the connection already has been established
if (!self::$connection) {
$config = new \Doctrine\DBAL\Configuration();
$eventManager = new \Doctrine\Common\EventManager();
switch($type) {
case 'sqlite':
case 'sqlite3':
$datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' );
$connectionParams = array(
'user' => $user,
'password' => $pass,
'path' => $datadir.'/'.$name.'.db',
'driver' => 'pdo_sqlite',
);
$connectionParams['adapter'] = '\OC\DB\AdapterSqlite';
$connectionParams['wrapperClass'] = 'OC\DB\Connection';
break;
case 'mysql':
$connectionParams = array(
'user' => $user,
'password' => $pass,
'host' => $host,
'port' => $port,
'dbname' => $name,
'charset' => 'UTF8',
'driver' => 'pdo_mysql',
);
$connectionParams['adapter'] = '\OC\DB\Adapter';
$connectionParams['wrapperClass'] = 'OC\DB\Connection';
// Send "SET NAMES utf8". Only required on PHP 5.3 below 5.3.6.
// See http://stackoverflow.com/questions/4361459/php-pdo-charset-set-names#4361485
$eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\MysqlSessionInit);
break;
case 'pgsql':
$connectionParams = array(
'user' => $user,
'password' => $pass,
'host' => $host,
'port' => $port,
'dbname' => $name,
'driver' => 'pdo_pgsql',
);
$connectionParams['adapter'] = '\OC\DB\AdapterPgSql';
$connectionParams['wrapperClass'] = 'OC\DB\Connection';
break;
case 'oci':
$connectionParams = array(
'user' => $user,
'password' => $pass,
'host' => $host,
'dbname' => $name,
'charset' => 'AL32UTF8',
'driver' => 'oci8',
);
if (!empty($port)) {
$connectionParams['port'] = $port;
}
$connectionParams['adapter'] = '\OC\DB\AdapterOCI8';
$connectionParams['wrapperClass'] = 'OC\DB\OracleConnection';
$eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\OracleSessionInit);
break;
case 'mssql':
$connectionParams = array(
'user' => $user,
'password' => $pass,
'host' => $host,
'port' => $port,
'dbname' => $name,
'charset' => 'UTF8',
'driver' => 'pdo_sqlsrv',
);
$connectionParams['adapter'] = '\OC\DB\AdapterSQLSrv';
$connectionParams['wrapperClass'] = 'OC\DB\Connection';
break;
default:
return false;
}
$connectionParams['tablePrefix'] = OC_Config::getValue('dbtableprefix', 'oc_' );
try {
self::$connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config, $eventManager);
if ($type === 'sqlite' || $type === 'sqlite3') {
// Sqlite doesn't handle query caching and schema changes
// TODO: find a better way to handle this
self::$connection->disableQueryStatementCaching();
}
} catch(\Doctrine\DBAL\DBALException $e) {
OC_Log::write('core', $e->getMessage(), OC_Log::FATAL);
OC_User::setUserId(null);
// send http status 503
header('HTTP/1.1 503 Service Temporarily Unavailable');
header('Status: 503 Service Temporarily Unavailable');
OC_Template::printErrorPage('Failed to connect to database');
die();
$factory = new \OC\DB\ConnectionFactory();
if (!$factory->isValidType($type)) {
return false;
}
if ($factory->normalizeType($type) === 'sqlite3') {
$datadir = OC_Config::getValue("datadirectory", OC::$SERVERROOT.'/data');
$connectionParams = array(
'user' => $user,
'password' => $pass,
'path' => $datadir.'/'.$name.'.db',
);
} else {
$connectionParams = array(
'user' => $user,
'password' => $pass,
'host' => $host,
'dbname' => $name,
);
if (!empty($port)) {
$connectionParams['port'] = $port;
}
}
$connectionParams['tablePrefix'] = OC_Config::getValue('dbtableprefix', 'oc_');
try {
self::$connection = $factory->getConnection($type, $connectionParams);
} catch(\Doctrine\DBAL\DBALException $e) {
OC_Log::write('core', $e->getMessage(), OC_Log::FATAL);
OC_User::setUserId(null);
// send http status 503
header('HTTP/1.1 503 Service Temporarily Unavailable');
header('Status: 503 Service Temporarily Unavailable');
OC_Template::printErrorPage('Failed to connect to database');
die();
}
return true;
}
......@@ -202,12 +145,12 @@ class OC_DB {
*/
static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
self::connect();
if ($isManipulation === null) {
//try to guess, so we return the number of rows on manipulations
$isManipulation = self::isManipulation($query);
}
// return the result
try {
$result = self::$connection->prepare($query, $limit, $offset);
......@@ -222,7 +165,7 @@ class OC_DB {
/**
* tries to guess the type of statement based on the first 10 characters
* the current check allows some whitespace but does not work with IF EXISTS or other more complex statements
*
*
* @param string $sql
* @return bool
*/
......@@ -245,7 +188,7 @@ class OC_DB {
}
return false;
}
/**
* @brief execute a prepared statement, on error write log and throw exception
* @param mixed $stmt OC_DB_StatementWrapper,
......
<?php
/**
* Copyright (c) 2014 Andreas Fischer <bantu@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\DB;
/**
* Takes care of creating and configurating Doctrine connections.
*/
class ConnectionFactory {
/**
* @var array
*
* Array mapping DBMS type to default connection parameters passed to
* \Doctrine\DBAL\DriverManager::getConnection().
*/
protected $defaultConnectionParams = array(
'mssql' => array(
'adapter' => '\OC\DB\AdapterSQLSrv',
'charset' => 'UTF8',
'driver' => 'pdo_sqlsrv',
'wrapperClass' => 'OC\DB\Connection',
),
'mysql' => array(
'adapter' => '\OC\DB\Adapter',
'charset' => 'UTF8',
'driver' => 'pdo_mysql',
'wrapperClass' => 'OC\DB\Connection',
),
'oci' => array(
'adapter' => '\OC\DB\AdapterOCI8',
'charset' => 'AL32UTF8',
'driver' => 'oci8',
'wrapperClass' => 'OC\DB\OracleConnection',
),
'pgsql' => array(
'adapter' => '\OC\DB\AdapterPgSql',
'driver' => 'pdo_pgsql',
'wrapperClass' => 'OC\DB\Connection',
),
'sqlite3' => array(
'adapter' => '\OC\DB\AdapterSqlite',
'driver' => 'pdo_sqlite',
'wrapperClass' => 'OC\DB\Connection',
),
);
/**
* @brief Get default connection parameters for a given DBMS.
* @param string $type DBMS type
* @throws \InvalidArgumentException If $type is invalid
* @return array Default connection parameters.
*/
public function getDefaultConnectionParams($type) {
$normalizedType = $this->normalizeType($type);
if (!isset($this->defaultConnectionParams[$normalizedType])) {
throw new \InvalidArgumentException("Unsupported type: $type");
}
return $this->defaultConnectionParams[$normalizedType];
}
/**
* @brief Get default connection parameters for a given DBMS.
* @param string $type DBMS type
* @param array $additionalConnectionParams Additional connection parameters
* @return \OC\DB\Connection
*/
public function getConnection($type, $additionalConnectionParams) {
$normalizedType = $this->normalizeType($type);
$eventManager = new \Doctrine\Common\EventManager();
switch ($normalizedType) {
case 'mysql':
// Send "SET NAMES utf8". Only required on PHP 5.3 below 5.3.6.
// See http://stackoverflow.com/questions/4361459/php-pdo-charset-set-names#4361485
$eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\MysqlSessionInit);
break;
case 'oci':
$eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\OracleSessionInit);
break;
}
$connection = \Doctrine\DBAL\DriverManager::getConnection(
array_merge($this->getDefaultConnectionParams($type), $additionalConnectionParams),
new \Doctrine\DBAL\Configuration(),
$eventManager
);
switch ($normalizedType) {
case 'sqlite3':
// Sqlite doesn't handle query caching and schema changes
// TODO: find a better way to handle this
$connection->disableQueryStatementCaching();
break;
}
return $connection;
}
/**
* @brief Normalize DBMS type
* @param string $type DBMS type
* @return string Normalized DBMS type
*/
public function normalizeType($type) {
return $type === 'sqlite' ? 'sqlite3' : $type;
}
/**
* @brief Checks whether the specififed DBMS type is valid.
* @return bool
*/
public function isValidType($type) {
$normalizedType = $this->normalizeType($type);
return isset($this->defaultConnectionParams[$normalizedType]);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment