From 62ce3a5613a273c9208f272728ae5002d43d5096 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 08:32:38 +0100 Subject: [PATCH 01/23] Only close db connection when disconnecting, keep the connection object --- lib/db.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/db.php b/lib/db.php index e70d66fc2b..44d77bce80 100644 --- a/lib/db.php +++ b/lib/db.php @@ -380,8 +380,8 @@ class OC_DB { public static function disconnect() { // Cut connection if required if(self::$connection) { - self::$connection=false; - self::$DOCTRINE=false; + self::$connection->close(); + self::$preparedQueries = array(); } return true; From 66a215651badf8472e9922b7591cba3cfe9ce333 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 08:19:49 +0100 Subject: [PATCH 02/23] Create DB Connection wrapper and DB\Adapter* classes --- lib/db.php | 6 +++ lib/db/adapter.php | 17 ++++++++ lib/db/adapteroci8.php | 13 ++++++ lib/db/adapterpgsql.php | 13 ++++++ lib/db/adaptersqlite.php | 13 ++++++ lib/db/adaptersqlsrv.php | 13 ++++++ lib/db/connection.php | 88 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 163 insertions(+) create mode 100644 lib/db/adapter.php create mode 100644 lib/db/adapteroci8.php create mode 100644 lib/db/adapterpgsql.php create mode 100644 lib/db/adaptersqlite.php create mode 100644 lib/db/adaptersqlsrv.php create mode 100644 lib/db/connection.php diff --git a/lib/db.php b/lib/db.php index 44d77bce80..95145fb7c5 100644 --- a/lib/db.php +++ b/lib/db.php @@ -129,6 +129,7 @@ class OC_DB { 'path' => $datadir.'/'.$name.'.db', 'driver' => 'pdo_sqlite', ); + $connectionParams['adapter'] = '\OC\DB\AdapterSqlite'; break; case 'mysql': $connectionParams = array( @@ -140,6 +141,7 @@ class OC_DB { 'charset' => 'UTF8', 'driver' => 'pdo_mysql', ); + $connectionParams['adapter'] = '\OC\DB\Adapter'; break; case 'pgsql': $connectionParams = array( @@ -150,6 +152,7 @@ class OC_DB { 'dbname' => $name, 'driver' => 'pdo_pgsql', ); + $connectionParams['adapter'] = '\OC\DB\AdapterPgSql'; break; case 'oci': $connectionParams = array( @@ -163,6 +166,7 @@ class OC_DB { if (!empty($port)) { $connectionParams['port'] = $port; } + $connectionParams['adapter'] = '\OC\DB\AdapterOCI8'; break; case 'mssql': $connectionParams = array( @@ -174,10 +178,12 @@ class OC_DB { 'charset' => 'UTF8', 'driver' => 'pdo_sqlsrv', ); + $connectionParams['adapter'] = '\OC\DB\AdapterSQLSrv'; break; default: return false; } + $connectionParams['wrapperClass'] = 'OC\DB\Connection'; try { self::$DOCTRINE = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config); } catch(\Doctrine\DBAL\DBALException $e) { diff --git a/lib/db/adapter.php b/lib/db/adapter.php new file mode 100644 index 0000000000..c62e35495c --- /dev/null +++ b/lib/db/adapter.php @@ -0,0 +1,17 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\DB; + +class Adapter { + protected $conn; + + public function __construct($conn) { + $this->conn = $conn; + } +} diff --git a/lib/db/adapteroci8.php b/lib/db/adapteroci8.php new file mode 100644 index 0000000000..7ffff4909e --- /dev/null +++ b/lib/db/adapteroci8.php @@ -0,0 +1,13 @@ + + * 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 { +} diff --git a/lib/db/adapterpgsql.php b/lib/db/adapterpgsql.php new file mode 100644 index 0000000000..d3b09357c0 --- /dev/null +++ b/lib/db/adapterpgsql.php @@ -0,0 +1,13 @@ + + * 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 { +} diff --git a/lib/db/adaptersqlite.php b/lib/db/adaptersqlite.php new file mode 100644 index 0000000000..0b8107ac53 --- /dev/null +++ b/lib/db/adaptersqlite.php @@ -0,0 +1,13 @@ + + * 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 { +} diff --git a/lib/db/adaptersqlsrv.php b/lib/db/adaptersqlsrv.php new file mode 100644 index 0000000000..281daf81d1 --- /dev/null +++ b/lib/db/adaptersqlsrv.php @@ -0,0 +1,13 @@ + + * 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 { +} diff --git a/lib/db/connection.php b/lib/db/connection.php new file mode 100644 index 0000000000..5466609e67 --- /dev/null +++ b/lib/db/connection.php @@ -0,0 +1,88 @@ + + * 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 { + protected $table_prefix; + protected $sequence_suffix; + + protected $adapter; + + /** + * Initializes a new instance of the Connection class. + * + * @param array $params The connection parameters. + * @param Driver $driver + * @param Configuration $config + * @param EventManager $eventManager + */ + public function __construct(array $params, Driver $driver, Configuration $config = null, + EventManager $eventManager = null) + { + if (!isset($params['adapter'])) { + throw new Exception('adapter not set'); + } + parent::__construct($params, $driver, $config, $eventManager); + $this->adapter = new $params['adapter']($this); + } + + /** + * Prepares an SQL statement. + * + * @param string $statement The SQL statement to prepare. + * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + */ + public function prepare( $statement, $limit=null, $offset=null ) { + // TODO: prefix + // TODO: limit & offset + // TODO: prepared statement cache + return parent::prepare($statement); + } + + /** + * 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) + { + // TODO: prefix + 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()) + { + // TODO: prefix + return parent::executeUpdate($query, $params, $types); + } +} From cd98ff1eafabf5b10ff67594b65d979a943afe09 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 08:19:49 +0100 Subject: [PATCH 03/23] Move db prefix handling to Connection wrapper --- lib/db.php | 20 +++++--------------- lib/db/connection.php | 12 ++++++++++-- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/db.php b/lib/db.php index 95145fb7c5..a323370610 100644 --- a/lib/db.php +++ b/lib/db.php @@ -57,7 +57,6 @@ class OC_DB { static private $DOCTRINE=null; static private $inTransaction=false; - static private $prefix=null; static private $type=null; /** @@ -184,6 +183,7 @@ class OC_DB { return false; } $connectionParams['wrapperClass'] = 'OC\DB\Connection'; + $connectionParams['table_prefix'] = OC_Config::getValue( "dbtableprefix", "oc_" ); try { self::$DOCTRINE = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config); } catch(\Doctrine\DBAL\DBALException $e) { @@ -353,8 +353,7 @@ class OC_DB { return $row['id']; } else if( $type === 'mssql') { if($table !== null) { - $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); - $table = str_replace( '*PREFIX*', $prefix, $table ); + $table = self::$connection->replaceTablePrefix( $table ); } return self::$connection->lastInsertId($table); } @@ -367,9 +366,8 @@ class OC_DB { return self::$connection->lastInsertId($table); } else { if($table !== null) { - $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); $suffix = OC_Config::getValue( "dbsequencesuffix", "_id_seq" ); - $table = str_replace( '*PREFIX*', $prefix, $table ).$suffix; + $table = self::$connection->replaceTablePrefix( $table ).$suffix; } $result = self::$connection->lastInsertId($table); } @@ -443,8 +441,7 @@ class OC_DB { */ public static function insertIfNotExist($table, $input) { self::connect(); - $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); - $table = str_replace( '*PREFIX*', $prefix, $table ); + $table = self::$connection->replaceTablePrefix( $table ); if(is_null(self::$type)) { self::$type=OC_Config::getValue( "dbtype", "sqlite" ); @@ -508,15 +505,11 @@ class OC_DB { */ private static function processQuery( $query ) { self::connect(); - // We need Database type and table prefix + // We need Database type if(is_null(self::$type)) { self::$type=OC_Config::getValue( "dbtype", "sqlite" ); } $type = self::$type; - if(is_null(self::$prefix)) { - self::$prefix=OC_Config::getValue( "dbtableprefix", "oc_" ); - } - $prefix = self::$prefix; // differences in escaping of table names ('`' for mysql) and getting the current timestamp if( $type == 'sqlite' || $type == 'sqlite3' ) { @@ -541,9 +534,6 @@ class OC_DB { $query = self::fixLimitClauseForMSSQL($query); } - // replace table name prefix - $query = str_replace( '*PREFIX*', $prefix, $query ); - return $query; } diff --git a/lib/db/connection.php b/lib/db/connection.php index 5466609e67..40809330da 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -14,7 +14,6 @@ use Doctrine\Common\EventManager; class Connection extends \Doctrine\DBAL\Connection { protected $table_prefix; - protected $sequence_suffix; protected $adapter; @@ -32,8 +31,12 @@ class Connection extends \Doctrine\DBAL\Connection { if (!isset($params['adapter'])) { throw new Exception('adapter not set'); } + if (!isset($params['table_prefix'])) { + throw new Exception('table_prefix not set'); + } parent::__construct($params, $driver, $config, $eventManager); $this->adapter = new $params['adapter']($this); + $this->table_prefix = $params['table_prefix']; } /** @@ -43,7 +46,7 @@ class Connection extends \Doctrine\DBAL\Connection { * @return \Doctrine\DBAL\Driver\Statement The prepared statement. */ public function prepare( $statement, $limit=null, $offset=null ) { - // TODO: prefix + $statement = $this->replaceTablePrefix($statement); // TODO: limit & offset // TODO: prepared statement cache return parent::prepare($statement); @@ -85,4 +88,9 @@ class Connection extends \Doctrine\DBAL\Connection { // TODO: prefix return parent::executeUpdate($query, $params, $types); } + + // internal use + public function replaceTablePrefix($statement) { + return str_replace( '*PREFIX*', $this->table_prefix, $statement ); + } } From e3c5fea989f26a4ad16b841be25ea485c8aad8c4 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Fri, 22 Mar 2013 18:36:40 +0100 Subject: [PATCH 04/23] Move lastInsertId to adapter classes --- lib/db.php | 29 +---------------------------- lib/db/adapter.php | 4 ++++ lib/db/adapteroci8.php | 8 ++++++++ lib/db/adapterpgsql.php | 3 +++ lib/db/adaptersqlsrv.php | 6 ++++++ lib/db/connection.php | 31 +++++++++++++++++++++++++++++-- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/lib/db.php b/lib/db.php index a323370610..c1c419df54 100644 --- a/lib/db.php +++ b/lib/db.php @@ -345,34 +345,7 @@ class OC_DB { */ public static function insertid($table=null) { self::connect(); - $type = OC_Config::getValue( "dbtype", "sqlite" ); - if( $type === 'pgsql' ) { - $result = self::executeAudited('SELECT lastval() AS id'); - $row = $result->fetchRow(); - self::raiseExceptionOnError($row, 'fetching row for insertid failed'); - return $row['id']; - } else if( $type === 'mssql') { - if($table !== null) { - $table = self::$connection->replaceTablePrefix( $table ); - } - return self::$connection->lastInsertId($table); - } - if( $type === 'oci' ) { - if($table !== null) { - $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); - $suffix = '_SEQ'; - $table = '"'.str_replace( '*PREFIX*', $prefix, $table ).$suffix.'"'; - } - return self::$connection->lastInsertId($table); - } else { - if($table !== null) { - $suffix = OC_Config::getValue( "dbsequencesuffix", "_id_seq" ); - $table = self::$connection->replaceTablePrefix( $table ).$suffix; - } - $result = self::$connection->lastInsertId($table); - } - self::raiseExceptionOnError($result, 'insertid failed'); - return $result; + return self::$connection->lastInsertId($table); } /** diff --git a/lib/db/adapter.php b/lib/db/adapter.php index c62e35495c..b0c9aab9c7 100644 --- a/lib/db/adapter.php +++ b/lib/db/adapter.php @@ -14,4 +14,8 @@ class Adapter { public function __construct($conn) { $this->conn = $conn; } + + public function lastInsertId($table) { + return $this->conn->realLastInsertId($table); + } } diff --git a/lib/db/adapteroci8.php b/lib/db/adapteroci8.php index 7ffff4909e..50c4d07824 100644 --- a/lib/db/adapteroci8.php +++ b/lib/db/adapteroci8.php @@ -10,4 +10,12 @@ namespace OC\DB; class AdapterOCI8 extends Adapter { + public function lastInsertId($table) { + if($table !== null) { + $suffix = '_SEQ'; + $table = '"'.$table.$suffix.'"'; + $table = $this->conn->replaceTablePrefix( $table ); + } + return $this->conn->lastInsertId($table); + } } diff --git a/lib/db/adapterpgsql.php b/lib/db/adapterpgsql.php index d3b09357c0..0084aad470 100644 --- a/lib/db/adapterpgsql.php +++ b/lib/db/adapterpgsql.php @@ -10,4 +10,7 @@ namespace OC\DB; class AdapterPgSql extends Adapter { + public function lastInsertId($table) { + return $this->conn->fetchColumn('SELECT lastval()'); + } } diff --git a/lib/db/adaptersqlsrv.php b/lib/db/adaptersqlsrv.php index 281daf81d1..602c70456e 100644 --- a/lib/db/adaptersqlsrv.php +++ b/lib/db/adaptersqlsrv.php @@ -10,4 +10,10 @@ namespace OC\DB; class AdapterSQLSrv extends Adapter { + public function lastInsertId($table) { + if($table !== null) { + $table = $this->conn->replaceTablePrefix( $table ); + } + return $this->conn->lastInsertId($table); + } } diff --git a/lib/db/connection.php b/lib/db/connection.php index 40809330da..7d56452678 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -67,7 +67,8 @@ class Connection extends \Doctrine\DBAL\Connection { */ public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) { - // TODO: prefix + $query = $this->replaceTablePrefix($query); + // TODO: fixup return parent::executeQuery($query, $params, $types, $qcp); } @@ -85,10 +86,36 @@ class Connection extends \Doctrine\DBAL\Connection { */ public function executeUpdate($query, array $params = array(), array $types = array()) { - // TODO: prefix + $query = $this->replaceTablePrefix($query); + // TODO: fixup 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); + } + // internal use public function replaceTablePrefix($statement) { return str_replace( '*PREFIX*', $this->table_prefix, $statement ); From a48e9c488b7ccf22a911a0fb33b69ef782f63a81 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 21:35:11 +0100 Subject: [PATCH 05/23] Move prepared query cache handling to Connection wrapper --- lib/db.php | 27 +++++++++------------------ lib/db/connection.php | 28 +++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/lib/db.php b/lib/db.php index c1c419df54..c5690bdd8a 100644 --- a/lib/db.php +++ b/lib/db.php @@ -43,9 +43,6 @@ class DatabaseException extends Exception { class OC_DB { const BACKEND_DOCTRINE=2; - static private $preparedQueries = array(); - static private $cachingEnabled = true; - /** * @var \Doctrine\DBAL\Connection */ @@ -102,7 +99,6 @@ class OC_DB { return true; } } - self::$preparedQueries = array(); // The global data we need $name = OC_Config::getValue( "dbname", "owncloud" ); $host = OC_Config::getValue( "dbhost", "" ); @@ -186,6 +182,11 @@ class OC_DB { $connectionParams['table_prefix'] = OC_Config::getValue( "dbtableprefix", "oc_" ); try { self::$DOCTRINE = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config); + 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); @@ -219,12 +220,8 @@ class OC_DB { } $platform = self::$connection->getDatabasePlatform(); $query = $platform->modifyLimitQuery($query, $limit, $offset); - } else { - if (isset(self::$preparedQueries[$query]) and self::$cachingEnabled) { - return self::$preparedQueries[$query]; } } - $rawQuery = $query; // Optimize the query $query = self::processQuery( $query ); @@ -248,12 +245,6 @@ class OC_DB { // differentiate between query and manipulation $result=new OC_DB_StatementWrapper($result, $isManipulation); } - if ((is_null($limit) || $limit == -1) and self::$cachingEnabled ) { - $type = OC_Config::getValue( "dbtype", "sqlite" ); - if( $type != 'sqlite' && $type != 'sqlite3' ) { - self::$preparedQueries[$rawQuery] = $result; - } - } return $result; } @@ -358,7 +349,6 @@ class OC_DB { // Cut connection if required if(self::$connection) { self::$connection->close(); - self::$preparedQueries = array(); } return true; @@ -672,9 +662,10 @@ class OC_DB { * @param bool $enabled */ static public function enableCaching($enabled) { - if (!$enabled) { - self::$preparedQueries = array(); + if ($enabled) { + self::$connection->enableQueryStatementCaching(); + } else { + self::$connection->disableQueryStatementCaching(); } - self::$cachingEnabled = $enabled; } } diff --git a/lib/db/connection.php b/lib/db/connection.php index 7d56452678..763251c190 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -17,6 +17,9 @@ class Connection extends \Doctrine\DBAL\Connection { protected $adapter; + protected $preparedQueries = array(); + protected $cachingQueryStatementEnabled = true; + /** * Initializes a new instance of the Connection class. * @@ -47,9 +50,19 @@ class Connection extends \Doctrine\DBAL\Connection { */ public function prepare( $statement, $limit=null, $offset=null ) { $statement = $this->replaceTablePrefix($statement); - // TODO: limit & offset - // TODO: prepared statement cache - return parent::prepare($statement); + if (!is_null($limit) && $limit != -1) { + // TODO: limit & offset + } else { + if (isset($this->preparedQueries[$statement]) && $this->cachingQueryStatementEnabled) { + return $this->preparedQueries[$statement]; + } + } + $rawQuery = $statement; + $result = parent::prepare($statement); + if ((is_null($limit) || $limit == -1) && $this->cachingQueryStatementEnabled) { + $this->preparedQueries[$rawQuery] = $result; + } + return $result; } /** @@ -120,4 +133,13 @@ class Connection extends \Doctrine\DBAL\Connection { public function replaceTablePrefix($statement) { return str_replace( '*PREFIX*', $this->table_prefix, $statement ); } + + public function enableQueryStatementCaching() { + $this->cachingQueryStatementEnabled = true; + } + + public function disableQueryStatementCaching() { + $this->cachingQueryStatementEnabled = false; + $this->preparedQueries = array(); + } } From 1d5d23a1de5a490595d8bb7ea81b8bda48b8feeb Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 21:46:03 +0100 Subject: [PATCH 06/23] Move limit/offset handling to Connection wrapper --- lib/db.php | 65 +------------------------------------------ lib/db/connection.php | 10 +++++-- 2 files changed, 8 insertions(+), 67 deletions(-) diff --git a/lib/db.php b/lib/db.php index c5690bdd8a..4451f81390 100644 --- a/lib/db.php +++ b/lib/db.php @@ -213,16 +213,6 @@ class OC_DB { * SQL query via Doctrine prepare(), needs to be execute()'d! */ static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) { - - if (!is_null($limit) && $limit != -1) { - if ($limit === -1) { - $limit = null; - } - $platform = self::$connection->getDatabasePlatform(); - $query = $platform->modifyLimitQuery($query, $limit, $offset); - } - } - // Optimize the query $query = self::processQuery( $query ); if(OC_Config::getValue( "log_query", false)) { @@ -238,7 +228,7 @@ class OC_DB { // return the result if (self::$backend == self::BACKEND_DOCTRINE) { try { - $result=self::$connection->prepare($query); + $result=self::$connection->prepare($query, $limit, $offset); } catch(\Doctrine\DBAL\DBALException $e) { throw new \DatabaseException($e->getMessage(), $query); } @@ -493,64 +483,11 @@ class OC_DB { $query = str_replace( 'LENGTH(', 'LEN(', $query ); $query = str_replace( 'SUBSTR(', 'SUBSTRING(', $query ); $query = str_ireplace( 'UNIX_TIMESTAMP()', 'DATEDIFF(second,{d \'1970-01-01\'},GETDATE())', $query ); - - $query = self::fixLimitClauseForMSSQL($query); } return $query; } - private static function fixLimitClauseForMSSQL($query) { - $limitLocation = stripos ($query, "LIMIT"); - - if ( $limitLocation === false ) { - return $query; - } - - // total == 0 means all results - not zero results - // - // First number is either total or offset, locate it by first space - // - $offset = substr ($query, $limitLocation + 5); - $offset = substr ($offset, 0, stripos ($offset, ' ')); - $offset = trim ($offset); - - // check for another parameter - if (stripos ($offset, ',') === false) { - // no more parameters - $offset = 0; - $total = intval ($offset); - } else { - // found another parameter - $offset = intval ($offset); - - $total = substr ($query, $limitLocation + 5); - $total = substr ($total, stripos ($total, ',')); - - $total = substr ($total, 0, stripos ($total, ' ')); - $total = intval ($total); - } - - $query = trim (substr ($query, 0, $limitLocation)); - - if ($offset == 0 && $total !== 0) { - if (strpos($query, "SELECT") === false) { - $query = "TOP {$total} " . $query; - } else { - $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query); - } - } else if ($offset > 0) { - $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query); - $query = 'SELECT * - FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3 - FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3'; - - if ($total > 0) { - $query .= ' WHERE line3 BETWEEN ' . ($offset + 1) . ' AND ' . ($offset + $total); - } else { - $query .= ' WHERE line3 > ' . $offset; - } - } return $query; } diff --git a/lib/db/connection.php b/lib/db/connection.php index 763251c190..c8695b1319 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -50,8 +50,12 @@ class Connection extends \Doctrine\DBAL\Connection { */ public function prepare( $statement, $limit=null, $offset=null ) { $statement = $this->replaceTablePrefix($statement); - if (!is_null($limit) && $limit != -1) { - // TODO: limit & offset + 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]; @@ -59,7 +63,7 @@ class Connection extends \Doctrine\DBAL\Connection { } $rawQuery = $statement; $result = parent::prepare($statement); - if ((is_null($limit) || $limit == -1) && $this->cachingQueryStatementEnabled) { + if (is_null($limit) && $this->cachingQueryStatementEnabled) { $this->preparedQueries[$rawQuery] = $result; } return $result; From 58991150ab17846640907d43a6d4b0ff502d4986 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 22:49:55 +0100 Subject: [PATCH 07/23] Move query statement fixup handling to Connection wrapper --- lib/db.php | 48 ---------------------------------------- lib/db/adapter.php | 4 ++++ lib/db/adapteroci8.php | 7 ++++++ lib/db/adapterpgsql.php | 6 +++++ lib/db/adaptersqlite.php | 6 +++++ lib/db/adaptersqlsrv.php | 9 ++++++++ lib/db/connection.php | 9 ++++++-- 7 files changed, 39 insertions(+), 50 deletions(-) diff --git a/lib/db.php b/lib/db.php index 4451f81390..0ad8a9b35d 100644 --- a/lib/db.php +++ b/lib/db.php @@ -213,11 +213,6 @@ class OC_DB { * SQL query via Doctrine prepare(), needs to be execute()'d! */ static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) { - // Optimize the query - $query = self::processQuery( $query ); - if(OC_Config::getValue( "log_query", false)) { - OC_Log::write('core', 'DB prepare : '.$query, OC_Log::DEBUG); - } self::connect(); if ($isManipulation === null) { @@ -448,49 +443,6 @@ class OC_DB { return $result; } - /** - * @brief does minor changes to query - * @param string $query Query string - * @return string corrected query string - * - * This function replaces *PREFIX* with the value of $CONFIG_DBTABLEPREFIX - * and replaces the ` with ' or " according to the database driver. - */ - private static function processQuery( $query ) { - self::connect(); - // We need Database type - if(is_null(self::$type)) { - self::$type=OC_Config::getValue( "dbtype", "sqlite" ); - } - $type = self::$type; - - // differences in escaping of table names ('`' for mysql) and getting the current timestamp - if( $type == 'sqlite' || $type == 'sqlite3' ) { - $query = str_replace( '`', '"', $query ); - $query = str_ireplace( 'NOW()', 'datetime(\'now\')', $query ); - $query = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $query ); - } elseif( $type == 'pgsql' ) { - $query = str_replace( '`', '"', $query ); - $query = str_ireplace( 'UNIX_TIMESTAMP()', 'cast(extract(epoch from current_timestamp) as integer)', - $query ); - } elseif( $type == 'oci' ) { - $query = str_replace( '`', '"', $query ); - $query = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); - $query = str_ireplace( 'UNIX_TIMESTAMP()', "(cast(sys_extract_utc(systimestamp) as date) - date'1970-01-01') * 86400", $query ); - }elseif( $type == 'mssql' ) { - $query = preg_replace( "/\`(.*?)`/", "[$1]", $query ); - $query = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); - $query = str_replace( 'LENGTH(', 'LEN(', $query ); - $query = str_replace( 'SUBSTR(', 'SUBSTRING(', $query ); - $query = str_ireplace( 'UNIX_TIMESTAMP()', 'DATEDIFF(second,{d \'1970-01-01\'},GETDATE())', $query ); - } - - return $query; - } - - return $query; - } - /** * @brief drop a table * @param string $tableName the table to drop diff --git a/lib/db/adapter.php b/lib/db/adapter.php index b0c9aab9c7..3b83853289 100644 --- a/lib/db/adapter.php +++ b/lib/db/adapter.php @@ -18,4 +18,8 @@ class Adapter { public function lastInsertId($table) { return $this->conn->realLastInsertId($table); } + + public function fixupStatement($statement) { + return $statement; + } } diff --git a/lib/db/adapteroci8.php b/lib/db/adapteroci8.php index 50c4d07824..6123007cb2 100644 --- a/lib/db/adapteroci8.php +++ b/lib/db/adapteroci8.php @@ -18,4 +18,11 @@ class AdapterOCI8 extends Adapter { } return $this->conn->lastInsertId($table); } + + public function fixupStatement($statement) { + $statement = str_replace( '`', '"', $statement ); + $statement = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', "(cast(sys_extract_utc(systimestamp) as date) - date'1970-01-01') * 86400", $statement ); + return $statement; + } } diff --git a/lib/db/adapterpgsql.php b/lib/db/adapterpgsql.php index 0084aad470..acfc420162 100644 --- a/lib/db/adapterpgsql.php +++ b/lib/db/adapterpgsql.php @@ -13,4 +13,10 @@ class AdapterPgSql extends Adapter { public function lastInsertId($table) { return $this->conn->fetchColumn('SELECT lastval()'); } + + public function fixupStatement($statement) { + $statement = str_replace( '`', '"', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', 'cast(extract(epoch from current_timestamp) as integer)', $statement ); + return $statement; + } } diff --git a/lib/db/adaptersqlite.php b/lib/db/adaptersqlite.php index 0b8107ac53..f0057ab489 100644 --- a/lib/db/adaptersqlite.php +++ b/lib/db/adaptersqlite.php @@ -10,4 +10,10 @@ 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; + } } diff --git a/lib/db/adaptersqlsrv.php b/lib/db/adaptersqlsrv.php index 602c70456e..d0a67af28a 100644 --- a/lib/db/adaptersqlsrv.php +++ b/lib/db/adaptersqlsrv.php @@ -16,4 +16,13 @@ class AdapterSQLSrv extends Adapter { } 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 index c8695b1319..8442efc47c 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -50,6 +50,8 @@ class Connection extends \Doctrine\DBAL\Connection { */ public function prepare( $statement, $limit=null, $offset=null ) { $statement = $this->replaceTablePrefix($statement); + $statement = $this->adapter->fixupStatement($statement); + if ($limit === -1) { $limit = null; } @@ -62,6 +64,9 @@ class Connection extends \Doctrine\DBAL\Connection { } } $rawQuery = $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[$rawQuery] = $result; @@ -85,7 +90,7 @@ class Connection extends \Doctrine\DBAL\Connection { public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) { $query = $this->replaceTablePrefix($query); - // TODO: fixup + $query = $this->adapter->fixupStatement($query); return parent::executeQuery($query, $params, $types, $qcp); } @@ -104,7 +109,7 @@ class Connection extends \Doctrine\DBAL\Connection { public function executeUpdate($query, array $params = array(), array $types = array()) { $query = $this->replaceTablePrefix($query); - // TODO: fixup + $query = $this->adapter->fixupStatement($query); return parent::executeUpdate($query, $params, $types); } From 19b9c896340c572d9a42d033cd8824f33d18efa3 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 26 Feb 2013 08:30:42 +0100 Subject: [PATCH 08/23] Move insertIfNotExist to Connection wrapper Real implementation is in DB\Adapter* classes --- lib/db.php | 53 +--------------------------------------- lib/db/adapter.php | 28 +++++++++++++++++++++ lib/db/adaptersqlite.php | 41 +++++++++++++++++++++++++++++++ lib/db/connection.php | 12 ++++++++- 4 files changed, 81 insertions(+), 53 deletions(-) diff --git a/lib/db.php b/lib/db.php index 0ad8a9b35d..1f62326eea 100644 --- a/lib/db.php +++ b/lib/db.php @@ -389,58 +389,7 @@ class OC_DB { */ public static function insertIfNotExist($table, $input) { self::connect(); - $table = self::$connection->replaceTablePrefix( $table ); - - if(is_null(self::$type)) { - self::$type=OC_Config::getValue( "dbtype", "sqlite" ); - } - $type = self::$type; - - $query = ''; - $inserts = array_values($input); - // differences in escaping of table names ('`' for mysql) and getting the current timestamp - if( $type == 'sqlite' || $type == 'sqlite3' ) { - // NOTE: For SQLite we have to use this clumsy approach - // otherwise all fieldnames used must have a unique key. - $query = 'SELECT * FROM `' . $table . '` WHERE '; - foreach($input as $key => $value) { - $query .= '`' . $key . '` = ? AND '; - } - $query = substr($query, 0, strlen($query) - 5); - try { - $result = self::executeAudited($query, $inserts); - } catch(DatabaseException $e) { - OC_Template::printExceptionErrorPage( $e ); - } - - if((int)$result->numRows() === 0) { - $query = 'INSERT INTO `' . $table . '` (`' - . implode('`,`', array_keys($input)) . '`) VALUES(' - . str_repeat('?,', count($input)-1).'? ' . ')'; - } else { - return 0; //no rows updated - } - } elseif( $type == 'pgsql' || $type == 'oci' || $type == 'mysql' || $type == 'mssql') { - $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_merge($inserts, $inserts); - } - - try { - $result = self::executeAudited($query, $inserts); - } catch(\Doctrine\DBAL\DBALException $e) { - OC_Template::printExceptionErrorPage( $e ); - } - - return $result; + return self::$connection->insertIfNotExist($table, $input); } /** diff --git a/lib/db/adapter.php b/lib/db/adapter.php index 3b83853289..3b95033119 100644 --- a/lib/db/adapter.php +++ b/lib/db/adapter.php @@ -22,4 +22,32 @@ class Adapter { public function fixupStatement($statement) { return $statement; } + + 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 { + $statement = $this->conn->prepare($query); + $result = $statement->execute($inserts); + } catch(\Doctrine\DBAL\DBALException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"
'; + $entry .= 'Offending command was: ' . $query.'
'; + OC_Log::write('core', $entry, OC_Log::FATAL); + error_log('DB error: ' . $entry); + OC_Template::printErrorPage( $entry ); + } + + return $result; + } } diff --git a/lib/db/adaptersqlite.php b/lib/db/adaptersqlite.php index f0057ab489..252fd94b0c 100644 --- a/lib/db/adaptersqlite.php +++ b/lib/db/adaptersqlite.php @@ -16,4 +16,45 @@ class AdapterSqlite extends Adapter { $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($input)); + } catch(\Doctrine\DBAL\DBALException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"
'; + $entry .= 'Offending command was: ' . $query . '
'; + 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() . '"
'; + $entry .= 'Offending command was: ' . $query.'
'; + OC_Log::write('core', $entry, OC_Log::FATAL); + error_log('DB error: ' . $entry); + OC_Template::printErrorPage( $entry ); + } + + return $result; + } } diff --git a/lib/db/connection.php b/lib/db/connection.php index 8442efc47c..e18062d78f 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -138,8 +138,18 @@ class Connection extends \Doctrine\DBAL\Connection { 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 + * @returns bool The return value from execute() + */ + public function insertIfNotExist($table, $input) { + return $this->adapter->insertIfNotExist($table, $input); + } + // internal use - public function replaceTablePrefix($statement) { + protected function replaceTablePrefix($statement) { return str_replace( '*PREFIX*', $this->table_prefix, $statement ); } From 8a332cdc941c7f1c059dcfdf04fc851364abc1b4 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 22:59:06 +0100 Subject: [PATCH 09/23] Simplify OC_DB transaction functions --- lib/db.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/db.php b/lib/db.php index 1f62326eea..59fd73b37c 100644 --- a/lib/db.php +++ b/lib/db.php @@ -53,7 +53,6 @@ class OC_DB { */ static private $DOCTRINE=null; - static private $inTransaction=false; static private $type=null; /** @@ -421,27 +420,18 @@ class OC_DB { /** * Start a transaction - * @return bool */ public static function beginTransaction() { self::connect(); self::$connection->beginTransaction(); - self::$inTransaction=true; - return true; } /** * Commit the database changes done during a transaction that is in progress - * @return bool */ public static function commit() { self::connect(); - if(!self::$inTransaction) { - return false; - } self::$connection->commit(); - self::$inTransaction=false; - return true; } /** From 3e0e2cfa19389edc2da8426620b7b412819208ca Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Sun, 24 Feb 2013 22:12:02 +0100 Subject: [PATCH 10/23] Use $connection for schema changes --- lib/db.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/db.php b/lib/db.php index 59fd73b37c..b317d17431 100644 --- a/lib/db.php +++ b/lib/db.php @@ -347,8 +347,8 @@ class OC_DB { * TODO: write more documentation */ public static function getDbStructure( $file, $mode=MDB2_SCHEMA_DUMP_STRUCTURE) { - self::connectDoctrine(); - return OC_DB_Schema::getDbStructure(self::$DOCTRINE, $file); + self::connect(); + return OC_DB_Schema::getDbStructure(self::$connection, $file); } /** @@ -359,8 +359,9 @@ class OC_DB { * TODO: write more documentation */ public static function createDbFromStructure( $file ) { - self::connectDoctrine(); - return OC_DB_Schema::createDbFromStructure(self::$DOCTRINE, $file); + self::connect(); + $result = OC_DB_Schema::createDbFromStructure(self::$connection, $file); + return $result; } /** @@ -370,9 +371,9 @@ class OC_DB { * @return bool */ public static function updateDbFromStructure($file) { - self::connectDoctrine(); + self::connect(); try { - $result = OC_DB_Schema::updateDbFromStructure(self::$DOCTRINE, $file); + $result = OC_DB_Schema::updateDbFromStructure(self::$connection, $file); } catch (Exception $e) { OC_Log::write('core', 'Failed to update database structure ('.$e.')', OC_Log::FATAL); throw $e; @@ -396,8 +397,8 @@ class OC_DB { * @param string $tableName the table to drop */ public static function dropTable($tableName) { - self::connectDoctrine(); - OC_DB_Schema::dropTable(self::$DOCTRINE, $tableName); + self::connect(); + OC_DB_Schema::dropTable(self::$connection, $tableName); } /** @@ -405,8 +406,8 @@ class OC_DB { * @param string $file the xml file describing the tables */ public static function removeDBStructure($file) { - self::connectDoctrine(); - OC_DB_Schema::removeDBStructure(self::$DOCTRINE, $file); + self::connect(); + OC_DB_Schema::removeDBStructure(self::$connection, $file); } /** @@ -414,8 +415,8 @@ class OC_DB { * @param $file string path to the MDB2 xml db export file */ public static function replaceDB( $file ) { - self::connectDoctrine(); - OC_DB_Schema::replaceDB(self::$DOCTRINE, $file); + self::connect(); + OC_DB_Schema::replaceDB(self::$connection, $file); } /** From 013333fe6a41c4681efcff64391d2bf7b1af5ab3 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Feb 2013 23:45:07 +0100 Subject: [PATCH 11/23] Cleanup: remove code for multiple database backends --- lib/db.php | 69 +++++++++++------------------------------------------- 1 file changed, 14 insertions(+), 55 deletions(-) diff --git a/lib/db.php b/lib/db.php index b317d17431..ac40be348b 100644 --- a/lib/db.php +++ b/lib/db.php @@ -41,63 +41,27 @@ class DatabaseException extends Exception { * Doctrine with some adaptions. */ class OC_DB { - const BACKEND_DOCTRINE=2; - /** * @var \Doctrine\DBAL\Connection */ - static private $connection; //the preferred connection to use, only Doctrine - static private $backend=null; /** * @var \Doctrine\DBAL\Connection */ - static private $DOCTRINE=null; + static private $connection; //the prefered connection to use, only Doctrine static private $type=null; - /** - * check which backend we should use - * @return int BACKEND_DOCTRINE - */ - private static function getDBBackend() { - return self::BACKEND_DOCTRINE; - } - /** * @brief connects to the database - * @param int $backend * @return bool true if connection can be established or false on error * * Connects to the database as specified in config.php */ - public static function connect($backend=null) { + public static function connect() { if(self::$connection) { return true; } - if(is_null($backend)) { - $backend=self::getDBBackend(); - } - if($backend==self::BACKEND_DOCTRINE) { - $success = self::connectDoctrine(); - self::$connection=self::$DOCTRINE; - self::$backend=self::BACKEND_DOCTRINE; - } - return $success; - } - /** - * connect to the database using doctrine - * - * @return bool - */ - public static function connectDoctrine() { - if(self::$connection) { - if(self::$backend!=self::BACKEND_DOCTRINE) { - self::disconnect(); - } else { - return true; - } - } // The global data we need $name = OC_Config::getValue( "dbname", "owncloud" ); $host = OC_Config::getValue( "dbhost", "" ); @@ -111,7 +75,7 @@ class OC_DB { } // do nothing if the connection already has been established - if(!self::$DOCTRINE) { + if(!self::$connection) { $config = new \Doctrine\DBAL\Configuration(); switch($type) { case 'sqlite': @@ -180,7 +144,7 @@ class OC_DB { $connectionParams['wrapperClass'] = 'OC\DB\Connection'; $connectionParams['table_prefix'] = OC_Config::getValue( "dbtableprefix", "oc_" ); try { - self::$DOCTRINE = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config); + self::$connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config); if ($type === 'sqlite' || $type === 'sqlite3') { // Sqlite doesn't handle query caching and schema changes // TODO: find a better way to handle this @@ -220,18 +184,16 @@ class OC_DB { } // return the result - if (self::$backend == self::BACKEND_DOCTRINE) { - try { - $result=self::$connection->prepare($query, $limit, $offset); - } catch(\Doctrine\DBAL\DBALException $e) { - throw new \DatabaseException($e->getMessage(), $query); - } - // differentiate between query and manipulation - $result=new OC_DB_StatementWrapper($result, $isManipulation); + try { + $result=self::$connection->prepare($query, $limit, $offset); + } catch(\Doctrine\DBAL\DBALException $e) { + throw new \DatabaseException($e->getMessage(), $query); } + // differentiate between query and manipulation + $result=new OC_DB_StatementWrapper($result, $isManipulation); return $result; } - + /** * 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 @@ -325,7 +287,6 @@ class OC_DB { /** * @brief Disconnect - * @return bool * * This is good bye, good bye, yeah! */ @@ -334,8 +295,6 @@ class OC_DB { if(self::$connection) { self::$connection->close(); } - - return true; } /** else { @@ -473,9 +432,9 @@ class OC_DB { * @return string */ public static function getErrorMessage($error) { - if (self::$backend==self::BACKEND_DOCTRINE and self::$DOCTRINE) { - $msg = self::$DOCTRINE->errorCode() . ': '; - $errorInfo = self::$DOCTRINE->errorInfo(); + if (self::$connection) { + $msg = self::$connection->errorCode() . ': '; + $errorInfo = self::$connection->errorInfo(); if (is_array($errorInfo)) { $msg .= 'SQLSTATE = '.$errorInfo[0] . ', '; $msg .= 'Driver Code = '.$errorInfo[1] . ', '; From de83bf98c759d8af9483306ddea07006693f74be Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 26 Feb 2013 17:39:13 +0100 Subject: [PATCH 12/23] Group database connection and schema function --- lib/db.php | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/db.php b/lib/db.php index ac40be348b..48e1439a33 100644 --- a/lib/db.php +++ b/lib/db.php @@ -285,6 +285,33 @@ class OC_DB { return self::$connection->lastInsertId($table); } + /** + * @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 + * @returns int number of updated rows + */ + public static function insertIfNotExist($table, $input) { + self::connect(); + return self::$connection->insertIfNotExist($table, $input); + } + + /** + * Start a transaction + */ + public static function beginTransaction() { + self::connect(); + self::$connection->beginTransaction(); + } + + /** + * Commit the database changes done during a transaction that is in progress + */ + public static function commit() { + self::connect(); + self::$connection->commit(); + } + /** * @brief Disconnect * @@ -340,17 +367,6 @@ class OC_DB { return $result; } - /** - * @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 - * @returns int number of updated rows - */ - public static function insertIfNotExist($table, $input) { - self::connect(); - return self::$connection->insertIfNotExist($table, $input); - } - /** * @brief drop a table * @param string $tableName the table to drop @@ -378,22 +394,6 @@ class OC_DB { OC_DB_Schema::replaceDB(self::$connection, $file); } - /** - * Start a transaction - */ - public static function beginTransaction() { - self::connect(); - self::$connection->beginTransaction(); - } - - /** - * Commit the database changes done during a transaction that is in progress - */ - public static function commit() { - self::connect(); - self::$connection->commit(); - } - /** * check if a result is an error, works with Doctrine * @param mixed $result From 000b5a801f27914d0a906b5f4c6ff58e14e5aebe Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 1 Jul 2013 18:20:27 +0200 Subject: [PATCH 13/23] Move building error string to connection --- lib/db.php | 10 +--------- lib/db/connection.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/db.php b/lib/db.php index 48e1439a33..9270b2a151 100644 --- a/lib/db.php +++ b/lib/db.php @@ -433,16 +433,8 @@ class OC_DB { */ public static function getErrorMessage($error) { if (self::$connection) { - $msg = self::$connection->errorCode() . ': '; - $errorInfo = self::$connection->errorInfo(); - if (is_array($errorInfo)) { - $msg .= 'SQLSTATE = '.$errorInfo[0] . ', '; - $msg .= 'Driver Code = '.$errorInfo[1] . ', '; - $msg .= 'Driver Message = '.$errorInfo[2]; - } - return $msg; + return self::$connection->getError(); } - return ''; } diff --git a/lib/db/connection.php b/lib/db/connection.php index e18062d78f..1f01fae4f7 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -148,6 +148,23 @@ class Connection extends \Doctrine\DBAL\Connection { return $this->adapter->insertIfNotExist($table, $input); } + /** + * returns the error code and message as a string for logging + * works with DoctrineException + * @param mixed $error + * @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 protected function replaceTablePrefix($statement) { return str_replace( '*PREFIX*', $this->table_prefix, $statement ); From b66c9098bd4188a1fbeb92351d1370736c10d1b4 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Thu, 18 Jul 2013 23:57:15 +0200 Subject: [PATCH 14/23] Correct namespace of OC_ classes --- lib/db/adapter.php | 4 ++-- lib/db/adaptersqlite.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/db/adapter.php b/lib/db/adapter.php index 3b95033119..92c24b46ff 100644 --- a/lib/db/adapter.php +++ b/lib/db/adapter.php @@ -43,9 +43,9 @@ class Adapter { } catch(\Doctrine\DBAL\DBALException $e) { $entry = 'DB Error: "'.$e->getMessage() . '"
'; $entry .= 'Offending command was: ' . $query.'
'; - OC_Log::write('core', $entry, OC_Log::FATAL); + \OC_Log::write('core', $entry, \OC_Log::FATAL); error_log('DB error: ' . $entry); - OC_Template::printErrorPage( $entry ); + \OC_Template::printErrorPage( $entry ); } return $result; diff --git a/lib/db/adaptersqlite.php b/lib/db/adaptersqlite.php index 252fd94b0c..61cfaa4424 100644 --- a/lib/db/adaptersqlite.php +++ b/lib/db/adaptersqlite.php @@ -31,9 +31,9 @@ class AdapterSqlite extends Adapter { } catch(\Doctrine\DBAL\DBALException $e) { $entry = 'DB Error: "'.$e->getMessage() . '"
'; $entry .= 'Offending command was: ' . $query . '
'; - OC_Log::write('core', $entry, OC_Log::FATAL); + \OC_Log::write('core', $entry, \OC_Log::FATAL); error_log('DB error: '.$entry); - OC_Template::printErrorPage( $entry ); + \OC_Template::printErrorPage( $entry ); } if ($stmt->fetchColumn() === 0) { @@ -50,9 +50,9 @@ class AdapterSqlite extends Adapter { } catch(\Doctrine\DBAL\DBALException $e) { $entry = 'DB Error: "'.$e->getMessage() . '"
'; $entry .= 'Offending command was: ' . $query.'
'; - OC_Log::write('core', $entry, OC_Log::FATAL); + \OC_Log::write('core', $entry, \OC_Log::FATAL); error_log('DB error: ' . $entry); - OC_Template::printErrorPage( $entry ); + \OC_Template::printErrorPage( $entry ); } return $result; From be7c6139938564fc2ce5a12982eb82f60087f900 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Fri, 19 Jul 2013 11:07:17 +0200 Subject: [PATCH 15/23] Fix errors from unit tests --- lib/db/adapter.php | 3 +-- lib/db/adaptersqlite.php | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/db/adapter.php b/lib/db/adapter.php index 92c24b46ff..20e7ea4a60 100644 --- a/lib/db/adapter.php +++ b/lib/db/adapter.php @@ -38,8 +38,7 @@ class Adapter { $inserts = array_merge($inserts, $inserts); try { - $statement = $this->conn->prepare($query); - $result = $statement->execute($inserts); + $result = $this->conn->executeUpdate($query, $inserts); } catch(\Doctrine\DBAL\DBALException $e) { $entry = 'DB Error: "'.$e->getMessage() . '"
'; $entry .= 'Offending command was: ' . $query.'
'; diff --git a/lib/db/adaptersqlite.php b/lib/db/adaptersqlite.php index 61cfaa4424..fa6d308ae3 100644 --- a/lib/db/adaptersqlite.php +++ b/lib/db/adaptersqlite.php @@ -27,7 +27,7 @@ class AdapterSqlite extends Adapter { $query = substr($query, 0, strlen($query) - 5); try { $stmt = $this->conn->prepare($query); - $result = $stmt->execute(array($input)); + $result = $stmt->execute(array_values($input)); } catch(\Doctrine\DBAL\DBALException $e) { $entry = 'DB Error: "'.$e->getMessage() . '"
'; $entry .= 'Offending command was: ' . $query . '
'; @@ -36,7 +36,7 @@ class AdapterSqlite extends Adapter { \OC_Template::printErrorPage( $entry ); } - if ($stmt->fetchColumn() === 0) { + if ($stmt->fetchColumn() === '0') { $query = 'INSERT INTO `' . $table . '` (`' . implode('`,`', array_keys($input)) . '`) VALUES(' . str_repeat('?,', count($input)-1).'? ' . ')'; From 3eb5fff02a477fbb3bd4080a4eb4e773e8db5d1f Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 23 Jul 2013 18:09:38 +0200 Subject: [PATCH 16/23] Add documentation to OC\DB\adapter class --- lib/db/adapter.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/db/adapter.php b/lib/db/adapter.php index 20e7ea4a60..2e4f230f36 100644 --- a/lib/db/adapter.php +++ b/lib/db/adapter.php @@ -8,6 +8,10 @@ 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 { protected $conn; @@ -15,14 +19,28 @@ class Adapter { $this->conn = $conn; } + /** + * @param string $table name + * @return int id of last insert statement + */ public function lastInsertId($table) { return $this->conn->realLastInsertId($table); } + /** + * @param $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 key->value pairs + * @return count of inserted rows + */ public function insertIfNotExist($table, $input) { $query = 'INSERT INTO `' .$table . '` (`' . implode('`,`', array_keys($input)) . '`) SELECT ' From 793ff0fec9d438bfdcf63e04f1d6897cadbf7a8a Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 23 Jul 2013 22:16:04 +0200 Subject: [PATCH 17/23] Fix lastInsertId for OCI8 adapter --- lib/db/adapteroci8.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/db/adapteroci8.php b/lib/db/adapteroci8.php index 6123007cb2..3ff98af04f 100644 --- a/lib/db/adapteroci8.php +++ b/lib/db/adapteroci8.php @@ -14,9 +14,8 @@ class AdapterOCI8 extends Adapter { if($table !== null) { $suffix = '_SEQ'; $table = '"'.$table.$suffix.'"'; - $table = $this->conn->replaceTablePrefix( $table ); } - return $this->conn->lastInsertId($table); + return $this->conn->realLastInsertId($table); } public function fixupStatement($statement) { From d7916363e1efbc15a5dba51056fb8af93330e5eb Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Sat, 2 Mar 2013 17:17:11 +0100 Subject: [PATCH 18/23] Make DB connection available to use for dependency injection --- lib/db.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/db.php b/lib/db.php index 9270b2a151..102782ac6b 100644 --- a/lib/db.php +++ b/lib/db.php @@ -164,6 +164,11 @@ class OC_DB { return true; } + static public function getConnection() { + self::connect(); + return self::$connection; + } + /** * @brief Prepare a SQL query * @param string $query Query string From ed054e67d60e8ad8074b38842935e5dff927350c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 2 Aug 2013 20:10:26 +0200 Subject: [PATCH 19/23] DB: remove invalid asserts --- tests/lib/db.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/lib/db.php b/tests/lib/db.php index 79e05f30a1..51edbf7b30 100644 --- a/tests/lib/db.php +++ b/tests/lib/db.php @@ -76,13 +76,11 @@ class Test_DB extends PHPUnit_Framework_TestCase { $query = OC_DB::prepare('INSERT INTO `*PREFIX*'.$this->table2.'` (`fullname`,`uri`) VALUES (?,?)'); $result1 = OC_DB::executeAudited($query, array('insertid 1','uri_1')); $id1 = OC_DB::insertid('*PREFIX*'.$this->table2); - $this->assertInternalType('int', $id1); // we don't know the id we should expect, so insert another row $result2 = OC_DB::executeAudited($query, array('insertid 2','uri_2')); $id2 = OC_DB::insertid('*PREFIX*'.$this->table2); // now we can check if the two ids are in correct order - $this->assertInternalType('int', $id2); $this->assertGreaterThan($id1, $id2); } From 2cc94cbc7387a7cd15803c8e3b4d450f05e7b041 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 7 Aug 2013 18:16:34 +0200 Subject: [PATCH 20/23] Style fixes --- lib/db.php | 4 ++-- lib/db/adapteroci8.php | 3 ++- lib/db/adapterpgsql.php | 3 ++- lib/db/statementwrapper.php | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/db.php b/lib/db.php index 2b6cd59366..d004d491ef 100644 --- a/lib/db.php +++ b/lib/db.php @@ -249,7 +249,7 @@ class OC_DB { static public function executeAudited( $stmt, array $parameters = null) { if (is_string($stmt)) { // convert to an array with 'sql' - if (stripos($stmt,'LIMIT') !== false) { //OFFSET requires LIMIT, se we only neet to check for LIMIT + if (stripos($stmt, 'LIMIT') !== false) { //OFFSET requires LIMIT, so we only need to check for LIMIT // TODO try to convert LIMIT OFFSET notation to parameters, see fixLimitClauseForMSSQL $message = 'LIMIT and OFFSET are forbidden for portability reasons,' . ' pass an array with \'limit\' and \'offset\' instead'; @@ -257,7 +257,7 @@ class OC_DB { } $stmt = array('sql' => $stmt, 'limit' => null, 'offset' => null); } - if (is_array($stmt)){ + if (is_array($stmt)) { // convert to prepared statement if ( ! array_key_exists('sql', $stmt) ) { $message = 'statement array must at least contain key \'sql\''; diff --git a/lib/db/adapteroci8.php b/lib/db/adapteroci8.php index 3ff98af04f..bc226e979e 100644 --- a/lib/db/adapteroci8.php +++ b/lib/db/adapteroci8.php @@ -18,10 +18,11 @@ class AdapterOCI8 extends Adapter { 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()', "(cast(sys_extract_utc(systimestamp) as date) - date'1970-01-01') * 86400", $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 index acfc420162..990d71c9f2 100644 --- a/lib/db/adapterpgsql.php +++ b/lib/db/adapterpgsql.php @@ -14,9 +14,10 @@ class AdapterPgSql extends Adapter { 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()', 'cast(extract(epoch from current_timestamp) as integer)', $statement ); + $statement = str_ireplace( 'UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement ); return $statement; } } diff --git a/lib/db/statementwrapper.php b/lib/db/statementwrapper.php index f7bc45e068..b8da1afc0e 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; From 0783267e2ccca0ab3e8dc8143308bd379320ef1e Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 7 Aug 2013 18:21:49 +0200 Subject: [PATCH 21/23] Move query processing after the check for prepared statement cache --- lib/db/connection.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/db/connection.php b/lib/db/connection.php index 7f207ff76e..24466d7bdd 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -62,9 +62,6 @@ class Connection extends \Doctrine\DBAL\Connection { * @return \Doctrine\DBAL\Driver\Statement The prepared statement. */ public function prepare( $statement, $limit=null, $offset=null ) { - $statement = $this->replaceTablePrefix($statement); - $statement = $this->adapter->fixupStatement($statement); - if ($limit === -1) { $limit = null; } @@ -76,7 +73,10 @@ class Connection extends \Doctrine\DBAL\Connection { return $this->preparedQueries[$statement]; } } - if(\OC_Config::getValue( "log_query", false)) { + $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); From 83988a5906443164ba9b092664d893519b2b85e6 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 7 Aug 2013 21:01:31 +0200 Subject: [PATCH 22/23] Fix stupid bug --- lib/db/connection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/db/connection.php b/lib/db/connection.php index 24466d7bdd..e8905d041f 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -72,6 +72,7 @@ class Connection extends \Doctrine\DBAL\Connection { if (isset($this->preparedQueries[$statement]) && $this->cachingQueryStatementEnabled) { return $this->preparedQueries[$statement]; } + $origStatement = $statement; } $statement = $this->replaceTablePrefix($statement); $statement = $this->adapter->fixupStatement($statement); @@ -81,7 +82,7 @@ class Connection extends \Doctrine\DBAL\Connection { } $result = parent::prepare($statement); if (is_null($limit) && $this->cachingQueryStatementEnabled) { - $this->preparedQueries[$statement] = $result; + $this->preparedQueries[$origStatement] = $result; } return $result; } From d563367b0f0bc6a419b8bf61b85aa701231bcad0 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 7 Aug 2013 22:22:33 +0200 Subject: [PATCH 23/23] More style fixes --- lib/db.php | 18 +++++++++--------- lib/db/connection.php | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/db.php b/lib/db.php index d004d491ef..ebd012c72f 100644 --- a/lib/db.php +++ b/lib/db.php @@ -73,7 +73,7 @@ class OC_DB { } // do nothing if the connection already has been established - if(!self::$connection) { + if (!self::$connection) { $config = new \Doctrine\DBAL\Configuration(); switch($type) { case 'sqlite': @@ -140,7 +140,7 @@ class OC_DB { return false; } $connectionParams['wrapperClass'] = 'OC\DB\Connection'; - $connectionParams['table_prefix'] = OC_Config::getValue( "dbtableprefix", "oc_" ); + $connectionParams['tablePrefix'] = OC_Config::getValue('dbtableprefix', 'oc_' ); try { self::$connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config); if ($type === 'sqlite' || $type === 'sqlite3') { @@ -201,12 +201,12 @@ class OC_DB { // return the result try { - $result=self::$connection->prepare($query, $limit, $offset); - } catch(\Doctrine\DBAL\DBALException $e) { + $result = self::$connection->prepare($query, $limit, $offset); + } catch (\Doctrine\DBAL\DBALException $e) { throw new \DatabaseException($e->getMessage(), $query); } // differentiate between query and manipulation - $result=new OC_DB_StatementWrapper($result, $isManipulation); + $result = new OC_DB_StatementWrapper($result, $isManipulation); return $result; } @@ -218,19 +218,19 @@ class OC_DB { * @return bool */ static public function isManipulation( $sql ) { - $selectOccurrence = stripos ($sql, "SELECT"); + $selectOccurrence = stripos($sql, 'SELECT'); if ($selectOccurrence !== false && $selectOccurrence < 10) { return false; } - $insertOccurrence = stripos ($sql, "INSERT"); + $insertOccurrence = stripos($sql, 'INSERT'); if ($insertOccurrence !== false && $insertOccurrence < 10) { return true; } - $updateOccurrence = stripos ($sql, "UPDATE"); + $updateOccurrence = stripos($sql, 'UPDATE'); if ($updateOccurrence !== false && $updateOccurrence < 10) { return true; } - $deleteOccurrence = stripos ($sql, "DELETE"); + $deleteOccurrence = stripos($sql, 'DELETE'); if ($deleteOccurrence !== false && $deleteOccurrence < 10) { return true; } diff --git a/lib/db/connection.php b/lib/db/connection.php index e8905d041f..2581969dbd 100644 --- a/lib/db/connection.php +++ b/lib/db/connection.php @@ -14,9 +14,9 @@ use Doctrine\Common\EventManager; class Connection extends \Doctrine\DBAL\Connection { /** - * @var string $table_prefix + * @var string $tablePrefix */ - protected $table_prefix; + protected $tablePrefix; /** * @var \OC\DB\Adapter $adapter @@ -45,12 +45,12 @@ class Connection extends \Doctrine\DBAL\Connection { if (!isset($params['adapter'])) { throw new \Exception('adapter not set'); } - if (!isset($params['table_prefix'])) { - throw new \Exception('table_prefix 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->table_prefix = $params['table_prefix']; + $this->tablePrefix = $params['tablePrefix']; } /** @@ -183,7 +183,7 @@ class Connection extends \Doctrine\DBAL\Connection { * @return string */ protected function replaceTablePrefix($statement) { - return str_replace( '*PREFIX*', $this->table_prefix, $statement ); + return str_replace( '*PREFIX*', $this->tablePrefix, $statement ); } public function enableQueryStatementCaching() {