mirror of
https://github.com/nextcloud/server.git
synced 2026-04-21 06:08:46 -04:00
Deduplicate connection handling code into \OC\DB\ConnectionFactory
This commit is contained in:
parent
a585cec530
commit
f9853b253c
4 changed files with 173 additions and 130 deletions
|
|
@ -22,10 +22,17 @@ class ConvertType extends Command {
|
|||
protected $config;
|
||||
|
||||
/**
|
||||
* @param \OC\Config $config
|
||||
* @var \OC\DB\ConnectionFactory
|
||||
*/
|
||||
public function __construct($config) {
|
||||
protected $connectionFactory;
|
||||
|
||||
/**
|
||||
* @param \OC\Config $config
|
||||
* @param \OC\DB\ConnectionFactory $connectionFactory
|
||||
*/
|
||||
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);
|
||||
$factory = new \OC\DB\ConnectionFactory();
|
||||
if (!$factory->isValidType($type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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();
|
||||
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,
|
||||
|
|
|
|||
117
lib/private/db/connectionfactory.php
Normal file
117
lib/private/db/connectionfactory.php
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<?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]);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue