diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2021-01-03 15:28:31 +0100 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2021-01-08 11:45:19 +0100 |
commit | 8b64e92b9262d2a2eec6345685ce421050f95c66 (patch) | |
tree | dd51490b8a184b2643414d11867a9fa450aa5065 /lib/private/DB | |
parent | 84e6e9f7cf19207041925eaa237d24e1c12c2c2d (diff) | |
download | nextcloud-server-8b64e92b9262d2a2eec6345685ce421050f95c66.tar.gz nextcloud-server-8b64e92b9262d2a2eec6345685ce421050f95c66.zip |
Bump doctrine/dbal from 2.12.0 to 3.0.0
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'lib/private/DB')
21 files changed, 491 insertions, 357 deletions
diff --git a/lib/private/DB/Adapter.php b/lib/private/DB/Adapter.php index 26fd018dec1..49b831301be 100644 --- a/lib/private/DB/Adapter.php +++ b/lib/private/DB/Adapter.php @@ -52,7 +52,7 @@ class Adapter { * @return int id of last insert statement */ public function lastInsertId($table) { - return $this->conn->realLastInsertId($table); + return (int) $this->conn->realLastInsertId($table); } /** @@ -94,7 +94,7 @@ class Adapter { * If this is null or an empty array, all keys of $input will be compared * Please note: text fields (clob) must not be used in the compare array * @return int number of inserted rows - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371 */ public function insertIfNotExist($table, $input, array $compare = null) { diff --git a/lib/private/DB/AdapterPgSql.php b/lib/private/DB/AdapterPgSql.php index 77f0b6b7722..0d8794d59ac 100644 --- a/lib/private/DB/AdapterPgSql.php +++ b/lib/private/DB/AdapterPgSql.php @@ -31,7 +31,10 @@ class AdapterPgSql extends Adapter { protected $compatModePre9_5 = null; public function lastInsertId($table) { - return $this->conn->fetchColumn('SELECT lastval()'); + $result = $this->conn->executeQuery('SELECT lastval()'); + $val = $result->fetchOne(); + $result->free(); + return (int)$val; } public const UNIX_TIMESTAMP_REPLACEMENT = 'cast(extract(epoch from current_timestamp) as integer)'; @@ -62,7 +65,9 @@ class AdapterPgSql extends Adapter { return $this->compatModePre9_5; } - $version = $this->conn->fetchColumn('SHOW SERVER_VERSION'); + $result = $this->conn->executeQuery('SHOW SERVER_VERSION'); + $version = $result->fetchOne(); + $result->free(); $this->compatModePre9_5 = version_compare($version, '9.5', '<'); return $this->compatModePre9_5; diff --git a/lib/private/DB/AdapterSqlite.php b/lib/private/DB/AdapterSqlite.php index 5731ee1721a..a62960bae1a 100644 --- a/lib/private/DB/AdapterSqlite.php +++ b/lib/private/DB/AdapterSqlite.php @@ -62,7 +62,7 @@ class AdapterSqlite extends Adapter { * If this is null or an empty array, all keys of $input will be compared * Please note: text fields (clob) must not be used in the compare array * @return int number of inserted rows - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371 */ public function insertIfNotExist($table, $input, array $compare = null) { diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index b024989ac04..c67c6df0826 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -36,20 +39,21 @@ namespace OC\DB; use Doctrine\Common\EventManager; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Configuration; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception\ConstraintViolationException; use Doctrine\DBAL\Exception\NotNullConstraintViolationException; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Statement; use OC\DB\QueryBuilder\QueryBuilder; use OC\SystemConfig; use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\IDBConnection; use OCP\ILogger; use OCP\PreConditionNotMetException; -class Connection extends ReconnectWrapper implements IDBConnection { +class Connection extends ReconnectWrapper { /** @var string */ protected $tablePrefix; @@ -73,9 +77,9 @@ class Connection extends ReconnectWrapper implements IDBConnection { public function connect() { try { return parent::connect(); - } catch (DBALException $e) { + } catch (Exception $e) { // throw a new exception to prevent leaking info from the stacktrace - throw new DBALException('Failed to connect to the database: ' . $e->getMessage(), $e->getCode()); + throw new Exception('Failed to connect to the database: ' . $e->getMessage(), $e->getCode()); } } @@ -88,13 +92,11 @@ class Connection extends ReconnectWrapper implements IDBConnection { /** * Returns a QueryBuilder for the connection. - * - * @return \OCP\DB\QueryBuilder\IQueryBuilder */ - public function getQueryBuilder() { + public function getQueryBuilder(): IQueryBuilder { $this->queriesBuilt++; return new QueryBuilder( - $this, + new ConnectionAdapter($this), $this->systemConfig, $this->logger ); @@ -181,9 +183,9 @@ class Connection extends ReconnectWrapper implements IDBConnection { * @param string $statement The SQL statement to prepare. * @param int $limit * @param int $offset - * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + * @return Statement The prepared statement. */ - public function prepare($statement, $limit = null, $offset = null) { + public function prepare($statement, $limit = null, $offset = null): Statement { if ($limit === -1) { $limit = null; } @@ -208,18 +210,18 @@ class Connection extends ReconnectWrapper implements IDBConnection { * @param array $types The types the previous parameters are in. * @param \Doctrine\DBAL\Cache\QueryCacheProfile|null $qcp The query cache profile, optional. * - * @return \Doctrine\DBAL\Driver\Statement The executed statement. + * @return Result The executed statement. * - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception */ - public function executeQuery($sql, array $params = [], $types = [], QueryCacheProfile $qcp = null) { + public function executeQuery(string $sql, array $params = [], $types = [], QueryCacheProfile $qcp = null): Result { $sql = $this->replaceTablePrefix($sql); $sql = $this->adapter->fixupStatement($sql); $this->queriesExecuted++; return parent::executeQuery($sql, $params, $types, $qcp); } - public function executeUpdate($sql, array $params = [], array $types = []) { + public function executeUpdate(string $sql, array $params = [], array $types = []): int { $sql = $this->replaceTablePrefix($sql); $sql = $this->adapter->fixupStatement($sql); $this->queriesExecuted++; @@ -236,11 +238,11 @@ class Connection extends ReconnectWrapper implements IDBConnection { * @param array $params The query parameters. * @param array $types The parameter types. * - * @return integer The number of affected rows. + * @return int The number of affected rows. * - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception */ - public function executeStatement($sql, array $params = [], array $types = []) { + public function executeStatement($sql, array $params = [], array $types = []): int { $sql = $this->replaceTablePrefix($sql); $sql = $this->adapter->fixupStatement($sql); $this->queriesExecuted++; @@ -256,7 +258,7 @@ class Connection extends ReconnectWrapper implements IDBConnection { * 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. + * @return string the last inserted ID. */ public function lastInsertId($seqName = null) { if ($seqName) { @@ -281,7 +283,7 @@ class Connection extends ReconnectWrapper implements IDBConnection { * If this is null or an empty array, all keys of $input will be compared * Please note: text fields (clob) must not be used in the compare array * @return int number of inserted rows - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371 */ public function insertIfNotExist($table, $input, array $compare = null) { @@ -310,7 +312,7 @@ class Connection extends ReconnectWrapper implements IDBConnection { * @param array $values (column name => value) * @param array $updatePreconditionValues ensure values match preconditions (column name => value) * @return int number of new rows - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception * @throws PreConditionNotMetException */ public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) { @@ -393,7 +395,7 @@ class Connection extends ReconnectWrapper implements IDBConnection { public function getError() { $msg = $this->errorCode() . ': '; $errorInfo = $this->errorInfo(); - if (is_array($errorInfo)) { + if (!empty($errorInfo)) { $msg .= 'SQLSTATE = '.$errorInfo[0] . ', '; $msg .= 'Driver Code = '.$errorInfo[1] . ', '; $msg .= 'Driver Message = '.$errorInfo[2]; @@ -401,6 +403,14 @@ class Connection extends ReconnectWrapper implements IDBConnection { return $msg; } + public function errorCode() { + return -1; + } + + public function errorInfo() { + return []; + } + /** * Drop a table from the database if it exists * @@ -462,7 +472,7 @@ class Connection extends ReconnectWrapper implements IDBConnection { * @since 11.0.0 */ public function supports4ByteText() { - if (!$this->getDatabasePlatform() instanceof MySqlPlatform) { + if (!$this->getDatabasePlatform() instanceof MySQLPlatform) { return true; } return $this->getParams()['charset'] === 'utf8mb4'; diff --git a/lib/private/DB/ConnectionAdapter.php b/lib/private/DB/ConnectionAdapter.php new file mode 100644 index 00000000000..97a0b60044d --- /dev/null +++ b/lib/private/DB/ConnectionAdapter.php @@ -0,0 +1,172 @@ +<?php + +declare(strict_types=1); + +/* + * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OC\DB; + +use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Schema\Schema; +use OCP\DB\IPreparedStatement; +use OCP\DB\IResult; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; + +/** + * Adapts the public API to our internal DBAL connection wrapper + */ +class ConnectionAdapter implements IDBConnection { + + /** @var Connection */ + private $inner; + + public function __construct(Connection $inner) { + $this->inner = $inner; + } + + public function getQueryBuilder(): IQueryBuilder { + return $this->inner->getQueryBuilder(); + } + + public function prepare($sql, $limit = null, $offset = null): IPreparedStatement { + return new PreparedStatement( + $this->inner->prepare($sql, $limit, $offset) + ); + } + + public function executeQuery(string $sql, array $params = [], $types = []): IResult { + return new ResultAdapter( + $this->inner->executeQuery($sql, $params, $types) + ); + } + + public function executeUpdate(string $sql, array $params = [], array $types = []): int { + return $this->inner->executeUpdate($sql, $params, $types); + } + + public function executeStatement($sql, array $params = [], array $types = []): int { + return $this->inner->executeStatement($sql, $params, $types); + } + + public function lastInsertId(string $table): int { + return (int) $this->inner->lastInsertId($table); + } + + public function insertIfNotExist(string $table, array $input, array $compare = null) { + return $this->inner->insertIfNotExist($table, $input, $compare); + } + + public function insertIgnoreConflict(string $table, array $values): int { + return $this->inner->insertIgnoreConflict($table, $values); + } + + public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []): int { + return $this->inner->setValues($table, $keys, $values, $updatePreconditionValues); + } + + public function lockTable($tableName): void { + $this->inner->lockTable($tableName); + } + + public function unlockTable(): void { + $this->inner->unlockTable(); + } + + public function beginTransaction(): void { + $this->inner->beginTransaction(); + } + + public function inTransaction(): bool { + return $this->inner->inTransaction(); + } + + public function commit(): void { + $this->inner->commit(); + } + + public function rollBack(): void { + $this->inner->rollBack(); + } + + public function getError(): string { + return $this->inner->getError(); + } + + public function errorCode() { + return $this->inner->errorCode(); + } + + public function errorInfo() { + return $this->inner->errorInfo(); + } + + public function connect(): bool { + return $this->inner->connect(); + } + + public function close(): void { + $this->inner->close(); + } + + public function quote($input, $type = IQueryBuilder::PARAM_STR) { + return $this->inner->quote($input, $type); + } + + /** + * @todo we are leaking a 3rdparty type here + */ + public function getDatabasePlatform(): AbstractPlatform { + return $this->inner->getDatabasePlatform(); + } + + public function dropTable(string $table): void { + $this->inner->dropTable($table); + } + + public function tableExists(string $table): bool { + return $this->inner->tableExists($table); + } + + public function escapeLikeParameter(string $param): string { + return $this->inner->escapeLikeParameter($param); + } + + public function supports4ByteText(): bool { + return $this->inner->supports4ByteText(); + } + + /** + * @todo leaks a 3rdparty type + */ + public function createSchema(): Schema { + return $this->inner->createSchema(); + } + + public function migrateToSchema(Schema $toSchema): void { + $this->inner->migrateToSchema($toSchema); + } + + public function getInner(): Connection { + return $this->inner; + } +} diff --git a/lib/private/DB/MDB2SchemaManager.php b/lib/private/DB/MDB2SchemaManager.php index 44ea3986214..18549eb1fa2 100644 --- a/lib/private/DB/MDB2SchemaManager.php +++ b/lib/private/DB/MDB2SchemaManager.php @@ -31,36 +31,24 @@ namespace OC\DB; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Platforms\OraclePlatform; -use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Platforms\PostgreSQL94Platform; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\Schema; -use OCP\IDBConnection; class MDB2SchemaManager { - /** @var \OC\DB\Connection $conn */ + /** @var Connection $conn */ protected $conn; /** - * @param IDBConnection $conn + * @param Connection $conn */ public function __construct($conn) { $this->conn = $conn; } /** - * saves database scheme to xml file - * @param string $file name of file - * @return bool - * - * TODO: write more documentation - */ - public function getDbStructure($file) { - return \OC\DB\MDB2SchemaWriter::saveSchemaToFile($file, $this->conn); - } - - /** * Creates tables from XML file * @param string $file file to read structure from * @return bool @@ -86,9 +74,9 @@ class MDB2SchemaManager { return new SQLiteMigrator($this->conn, $random, $config, $dispatcher); } elseif ($platform instanceof OraclePlatform) { return new OracleMigrator($this->conn, $random, $config, $dispatcher); - } elseif ($platform instanceof MySqlPlatform) { + } elseif ($platform instanceof MySQLPlatform) { return new MySQLMigrator($this->conn, $random, $config, $dispatcher); - } elseif ($platform instanceof PostgreSqlPlatform) { + } elseif ($platform instanceof PostgreSQL94Platform) { return new PostgreSqlMigrator($this->conn, $random, $config, $dispatcher); } else { return new Migrator($this->conn, $random, $config, $dispatcher); diff --git a/lib/private/DB/MDB2SchemaWriter.php b/lib/private/DB/MDB2SchemaWriter.php deleted file mode 100644 index 2c1f6a5e545..00000000000 --- a/lib/private/DB/MDB2SchemaWriter.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bart Visscher <bartv@thisnet.nl> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author tbelau666 <thomas.belau@gmx.de> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OC\DB; - -use Doctrine\DBAL\Schema\Column; -use Doctrine\DBAL\Schema\Index; - -class MDB2SchemaWriter { - - /** - * @param string $file - * @param \OC\DB\Connection $conn - * @return bool - */ - public static function saveSchemaToFile($file, \OC\DB\Connection $conn) { - $config = \OC::$server->getConfig(); - - $xml = new \SimpleXMLElement('<database/>'); - $xml->addChild('name', $config->getSystemValue('dbname', 'owncloud')); - $xml->addChild('create', 'true'); - $xml->addChild('overwrite', 'false'); - if ($config->getSystemValue('dbtype', 'sqlite') === 'mysql' && $config->getSystemValue('mysql.utf8mb4', false)) { - $xml->addChild('charset', 'utf8mb4'); - } else { - $xml->addChild('charset', 'utf8'); - } - - // FIX ME: bloody work around - if ($config->getSystemValue('dbtype', 'sqlite') === 'oci') { - $filterExpression = '/^"' . preg_quote($conn->getPrefix()) . '/'; - } else { - $filterExpression = '/^' . preg_quote($conn->getPrefix()) . '/'; - } - $conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); - - foreach ($conn->getSchemaManager()->listTables() as $table) { - self::saveTable($table, $xml->addChild('table')); - } - file_put_contents($file, $xml->asXML()); - return true; - } - - /** - * @param \Doctrine\DBAL\Schema\Table $table - * @param \SimpleXMLElement $xml - */ - private static function saveTable($table, $xml) { - $xml->addChild('name', $table->getName()); - $declaration = $xml->addChild('declaration'); - foreach ($table->getColumns() as $column) { - self::saveColumn($column, $declaration->addChild('field')); - } - foreach ($table->getIndexes() as $index) { - if ($index->getName() == 'PRIMARY') { - $autoincrement = false; - foreach ($index->getColumns() as $column) { - if ($table->getColumn($column)->getAutoincrement()) { - $autoincrement = true; - } - } - if ($autoincrement) { - continue; - } - } - self::saveIndex($index, $declaration->addChild('index')); - } - } - - /** - * @param Column $column - * @param \SimpleXMLElement $xml - */ - private static function saveColumn($column, $xml) { - $xml->addChild('name', $column->getName()); - switch ($column->getType()) { - case 'SmallInt': - case 'Integer': - case 'BigInt': - $xml->addChild('type', 'integer'); - $default = $column->getDefault(); - if (is_null($default) && $column->getAutoincrement()) { - $default = '0'; - } - $xml->addChild('default', $default); - $xml->addChild('notnull', self::toBool($column->getNotnull())); - if ($column->getAutoincrement()) { - $xml->addChild('autoincrement', '1'); - } - if ($column->getUnsigned()) { - $xml->addChild('unsigned', 'true'); - } - $length = '4'; - if ($column->getType() == 'SmallInt') { - $length = '2'; - } elseif ($column->getType() == 'BigInt') { - $length = '8'; - } - $xml->addChild('length', $length); - break; - case 'String': - $xml->addChild('type', 'text'); - $default = trim($column->getDefault()); - if ($default === '') { - $default = false; - } - $xml->addChild('default', $default); - $xml->addChild('notnull', self::toBool($column->getNotnull())); - $xml->addChild('length', $column->getLength()); - break; - case 'Text': - $xml->addChild('type', 'clob'); - $xml->addChild('notnull', self::toBool($column->getNotnull())); - break; - case 'Decimal': - $xml->addChild('type', 'decimal'); - $xml->addChild('default', $column->getDefault()); - $xml->addChild('notnull', self::toBool($column->getNotnull())); - $xml->addChild('length', '15'); - break; - case 'Boolean': - $xml->addChild('type', 'integer'); - $xml->addChild('default', $column->getDefault()); - $xml->addChild('notnull', self::toBool($column->getNotnull())); - $xml->addChild('length', '1'); - break; - case 'DateTime': - $xml->addChild('type', 'timestamp'); - $xml->addChild('default', $column->getDefault()); - $xml->addChild('notnull', self::toBool($column->getNotnull())); - break; - - } - } - - /** - * @param Index $index - * @param \SimpleXMLElement $xml - */ - private static function saveIndex($index, $xml) { - $xml->addChild('name', $index->getName()); - if ($index->isPrimary()) { - $xml->addChild('primary', 'true'); - } elseif ($index->isUnique()) { - $xml->addChild('unique', 'true'); - } - foreach ($index->getColumns() as $column) { - $field = $xml->addChild('field'); - $field->addChild('name', $column); - $field->addChild('sorting', 'ascending'); - } - } - - private static function toBool($bool) { - return $bool ? 'true' : 'false'; - } -} diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index 6a1cb4be016..44707911092 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -30,7 +30,7 @@ namespace OC\DB; use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Platforms\OraclePlatform; -use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Platforms\PostgreSQL94Platform; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\SchemaException; @@ -42,7 +42,6 @@ use OC\IntegrityCheck\Helpers\AppLocator; use OC\Migration\SimpleOutput; use OCP\AppFramework\App; use OCP\AppFramework\QueryException; -use OCP\IDBConnection; use OCP\Migration\IMigrationStep; use OCP\Migration\IOutput; @@ -65,12 +64,12 @@ class MigrationService { * MigrationService constructor. * * @param $appName - * @param IDBConnection $connection + * @param Connection $connection * @param AppLocator $appLocator * @param IOutput|null $output * @throws \Exception */ - public function __construct($appName, IDBConnection $connection, IOutput $output = null, AppLocator $appLocator = null) { + public function __construct($appName, Connection $connection, IOutput $output = null, AppLocator $appLocator = null) { $this->appName = $appName; $this->connection = $connection; $this->output = $output; @@ -591,7 +590,7 @@ class MigrationService { $indexName = strtolower($primaryKey->getName()); $isUsingDefaultName = $indexName === 'primary'; - if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) { + if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) { $defaultName = $table->getName() . '_pkey'; $isUsingDefaultName = strtolower($defaultName) === $indexName; diff --git a/lib/private/DB/Migrator.php b/lib/private/DB/Migrator.php index 569b1a6c282..f62735ea6b2 100644 --- a/lib/private/DB/Migrator.php +++ b/lib/private/DB/Migrator.php @@ -31,7 +31,8 @@ namespace OC\DB; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Schema\AbstractAsset; use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Schema; @@ -43,6 +44,7 @@ use OCP\IConfig; use OCP\Security\ISecureRandom; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; +use function preg_match; class Migrator { @@ -102,34 +104,6 @@ class Migrator { } /** - * @param Schema $targetSchema - * @throws \OC\DB\MigrationException - */ - public function checkMigrate(Schema $targetSchema) { - $this->noEmit = true; - /**@var \Doctrine\DBAL\Schema\Table[] $tables */ - $tables = $targetSchema->getTables(); - $filterExpression = $this->getFilterExpression(); - $this->connection->getConfiguration()-> - setFilterSchemaAssetsExpression($filterExpression); - $existingTables = $this->connection->getSchemaManager()->listTableNames(); - - $step = 0; - foreach ($tables as $table) { - if (strpos($table->getName(), '.')) { - list(, $tableName) = explode('.', $table->getName()); - } else { - $tableName = $table->getName(); - } - $this->emitCheckStep($tableName, $step++, count($tables)); - // don't need to check for new tables - if (array_search($tableName, $existingTables) !== false) { - $this->checkTableMigrate($table); - } - } - } - - /** * Create a unique name for the temporary table * * @param string $name @@ -160,7 +134,7 @@ class Migrator { try { $this->applySchema($schema); $this->dropTable($tmpName); - } catch (DBALException $e) { + } catch (Exception $e) { // pgsql needs to commit it's failed transaction before doing anything else if ($this->connection->isTransactionActive()) { $this->connection->commit(); @@ -193,12 +167,18 @@ class Migrator { } // foreign keys are not supported so we just set it to an empty array - return new Table($newName, $table->getColumns(), $newIndexes, [], 0, $table->getOptions()); + return new Table($newName, $table->getColumns(), $newIndexes, [], [], $table->getOptions()); } public function createSchema() { - $filterExpression = $this->getFilterExpression(); - $this->connection->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); + $this->connection->getConfiguration()->setSchemaAssetsFilter(function ($asset) { + /** @var string|AbstractAsset $asset */ + $filterExpression = $this->getFilterExpression(); + if ($asset instanceof AbstractAsset) { + return preg_match($filterExpression, $asset->getName()) !== false; + } + return preg_match($filterExpression, $asset) !== false; + }); return $this->connection->getSchemaManager()->createSchema(); } @@ -206,7 +186,6 @@ class Migrator { * @param Schema $targetSchema * @param \Doctrine\DBAL\Connection $connection * @return \Doctrine\DBAL\Schema\SchemaDiff - * @throws DBALException */ protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) { // adjust varchar columns with a length higher then getVarcharMaxLength to clob @@ -221,8 +200,14 @@ class Migrator { } } - $filterExpression = $this->getFilterExpression(); - $this->connection->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); + $this->connection->getConfiguration()->setSchemaAssetsFilter(function ($asset) { + /** @var string|AbstractAsset $asset */ + $filterExpression = $this->getFilterExpression(); + if ($asset instanceof AbstractAsset) { + return preg_match($filterExpression, $asset->getName()) !== false; + } + return preg_match($filterExpression, $asset) !== false; + }); $sourceSchema = $connection->getSchemaManager()->createSchema(); // remove tables we don't know about diff --git a/lib/private/DB/MySqlTools.php b/lib/private/DB/MySqlTools.php index 007388d5615..e738a2bd94a 100644 --- a/lib/private/DB/MySqlTools.php +++ b/lib/private/DB/MySqlTools.php @@ -32,7 +32,7 @@ use OCP\IDBConnection; class MySqlTools { /** - * @param Connection $connection + * @param IDBConnection $connection * @return bool */ public function supports4ByteCharset(IDBConnection $connection) { diff --git a/lib/private/DB/OracleMigrator.php b/lib/private/DB/OracleMigrator.php index cad5390f092..7a327a42797 100644 --- a/lib/private/DB/OracleMigrator.php +++ b/lib/private/DB/OracleMigrator.php @@ -30,7 +30,7 @@ namespace OC\DB; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\ForeignKeyConstraint; @@ -113,7 +113,7 @@ class OracleMigrator extends Migrator { * @param Schema $targetSchema * @param \Doctrine\DBAL\Connection $connection * @return \Doctrine\DBAL\Schema\SchemaDiff - * @throws DBALException + * @throws Exception */ protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) { $schemaDiff = parent::getDiff($targetSchema, $connection); @@ -128,10 +128,10 @@ class OracleMigrator extends Migrator { array_map(function (Index $index) { return $this->quoteIndex($index); }, $table->getIndexes()), + [], array_map(function (ForeignKeyConstraint $fck) { return $this->quoteForeignKeyConstraint($fck); }, $table->getForeignKeys()), - 0, $table->getOptions() ); }, $schemaDiff->newTables); @@ -141,8 +141,8 @@ class OracleMigrator extends Migrator { $this->connection->quoteIdentifier($table->getName()), $table->getColumns(), $table->getIndexes(), + [], $table->getForeignKeys(), - 0, $table->getOptions() ); }, $schemaDiff->removedTables); diff --git a/lib/private/DB/PgSqlTools.php b/lib/private/DB/PgSqlTools.php index 724344ac2a1..d555bfb391b 100644 --- a/lib/private/DB/PgSqlTools.php +++ b/lib/private/DB/PgSqlTools.php @@ -26,7 +26,10 @@ namespace OC\DB; +use Doctrine\DBAL\Schema\AbstractAsset; use OCP\IConfig; +use function preg_match; +use function preg_quote; /** * Various PostgreSQL specific helper functions. @@ -50,20 +53,30 @@ class PgSqlTools { * @return null */ public function resynchronizeDatabaseSequences(Connection $conn) { - $filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/'; $databaseName = $conn->getDatabase(); - $conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); + $conn->getConfiguration()->setSchemaAssetsFilter(function ($asset) { + /** @var string|AbstractAsset $asset */ + $filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/'; + if ($asset instanceof AbstractAsset) { + return preg_match($filterExpression, $asset->getName()) !== false; + } + return preg_match($filterExpression, $asset) !== false; + }); foreach ($conn->getSchemaManager()->listSequences() as $sequence) { $sequenceName = $sequence->getName(); $sqlInfo = 'SELECT table_schema, table_name, column_name FROM information_schema.columns WHERE column_default = ? AND table_catalog = ?'; - $sequenceInfo = $conn->fetchAssoc($sqlInfo, [ + $result = $conn->executeQuery($sqlInfo, [ "nextval('$sequenceName'::regclass)", $databaseName ]); + $sequenceInfo = $result->fetchAssociative(); + $result->free(); + /** @var string $tableName */ $tableName = $sequenceInfo['table_name']; + /** @var string $columnName */ $columnName = $sequenceInfo['column_name']; $sqlMaxId = "SELECT MAX($columnName) FROM $tableName"; $sqlSetval = "SELECT setval('$sequenceName', ($sqlMaxId))"; diff --git a/lib/private/DB/PreparedStatement.php b/lib/private/DB/PreparedStatement.php new file mode 100644 index 00000000000..f679576a428 --- /dev/null +++ b/lib/private/DB/PreparedStatement.php @@ -0,0 +1,101 @@ +<?php + +declare(strict_types=1); + +/* + * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2021 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OC\DB; + +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\ParameterType; +use Doctrine\DBAL\Statement; +use OCP\DB\IPreparedStatement; +use OCP\DB\IResult; +use PDO; + +/** + * Adapts our public API to what doctrine/dbal exposed with 2.6 + * + * The old dbal statement had stateful methods e.g. to fetch data from an executed + * prepared statement. To provide backwards compatibility to apps we need to make + * this class stateful. As soon as those now deprecated exposed methods are gone, + * we can limit the API of this adapter to the methods that map to the direct dbal + * methods without much magic. + */ +class PreparedStatement implements IPreparedStatement { + + /** @var Statement */ + private $statement; + + /** @var IResult|null */ + private $result; + + public function __construct(Statement $statement) { + $this->statement = $statement; + } + + public function closeCursor(): bool { + $this->getResult()->closeCursor(); + + return true; + } + + public function fetch(int $fetchMode = PDO::FETCH_ASSOC) { + return $this->getResult()->fetch($fetchMode); + } + + public function fetchAll(int $fetchMode = PDO::FETCH_ASSOC): array { + return $this->getResult()->fetchAll($fetchMode); + } + + public function fetchColumn() { + return $this->getResult()->fetchOne(); + } + + public function fetchOne() { + return $this->getResult()->fetchOne(); + } + + public function bindValue($param, $value, $type = ParameterType::STRING): bool { + return $this->statement->bindValue($param, $value, $type); + } + + public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool { + return $this->statement->bindParam($param, $variable, $type, $length); + } + + public function execute($params = null): IResult { + return ($this->result = new ResultAdapter($this->statement->execute($params))); + } + + public function rowCount(): int { + return $this->getResult()->rowCount(); + } + + private function getResult(): IResult { + if ($this->result !== null) { + return $this->result; + } + + throw new Exception("You have to execute the prepared statement before accessing the results"); + } +} diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php index 61eea80640e..d4c1a9db881 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php @@ -27,6 +27,7 @@ namespace OC\DB\QueryBuilder\ExpressionBuilder; use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder; +use OC\DB\ConnectionAdapter; use OC\DB\QueryBuilder\CompositeExpression; use OC\DB\QueryBuilder\FunctionBuilder\FunctionBuilder; use OC\DB\QueryBuilder\Literal; @@ -55,13 +56,13 @@ class ExpressionBuilder implements IExpressionBuilder { /** * Initializes a new <tt>ExpressionBuilder</tt>. * - * @param IDBConnection $connection + * @param ConnectionAdapter $connection * @param IQueryBuilder $queryBuilder */ - public function __construct(IDBConnection $connection, IQueryBuilder $queryBuilder) { + public function __construct(ConnectionAdapter $connection, IQueryBuilder $queryBuilder) { $this->connection = $connection; $this->helper = new QuoteHelper(); - $this->expressionBuilder = new DoctrineExpressionBuilder($connection); + $this->expressionBuilder = new DoctrineExpressionBuilder($connection->getInner()); $this->functionBuilder = $queryBuilder->func(); } diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php index 899f9277439..3e4119bb11c 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php @@ -24,9 +24,8 @@ namespace OC\DB\QueryBuilder\ExpressionBuilder; -use OC\DB\Connection; +use OC\DB\ConnectionAdapter; use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\IDBConnection; class MySqlExpressionBuilder extends ExpressionBuilder { @@ -34,13 +33,13 @@ class MySqlExpressionBuilder extends ExpressionBuilder { protected $charset; /** - * @param \OCP\IDBConnection|Connection $connection + * @param ConnectionAdapter $connection * @param IQueryBuilder $queryBuilder */ - public function __construct(IDBConnection $connection, IQueryBuilder $queryBuilder) { + public function __construct(ConnectionAdapter $connection, IQueryBuilder $queryBuilder) { parent::__construct($connection, $queryBuilder); - $params = $connection->getParams(); + $params = $connection->getInner()->getParams(); $this->charset = isset($params['charset']) ? $params['charset'] : 'utf8'; } diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php index 2d5fe6ce575..657e52e54bc 100644 --- a/lib/private/DB/QueryBuilder/QueryBuilder.php +++ b/lib/private/DB/QueryBuilder/QueryBuilder.php @@ -30,11 +30,12 @@ namespace OC\DB\QueryBuilder; -use Doctrine\DBAL\Platforms\MySqlPlatform; -use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Platforms\OraclePlatform; +use Doctrine\DBAL\Platforms\PostgreSQL94Platform; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Query\QueryException; -use OC\DB\OracleConnection; +use OC\DB\ConnectionAdapter; use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder; use OC\DB\QueryBuilder\ExpressionBuilder\MySqlExpressionBuilder; use OC\DB\QueryBuilder\ExpressionBuilder\OCIExpressionBuilder; @@ -44,17 +45,18 @@ use OC\DB\QueryBuilder\FunctionBuilder\FunctionBuilder; use OC\DB\QueryBuilder\FunctionBuilder\OCIFunctionBuilder; use OC\DB\QueryBuilder\FunctionBuilder\PgSqlFunctionBuilder; use OC\DB\QueryBuilder\FunctionBuilder\SqliteFunctionBuilder; +use OC\DB\ResultAdapter; use OC\SystemConfig; +use OCP\DB\IResult; use OCP\DB\QueryBuilder\ILiteral; use OCP\DB\QueryBuilder\IParameter; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryFunction; -use OCP\IDBConnection; use OCP\ILogger; class QueryBuilder implements IQueryBuilder { - /** @var \OCP\IDBConnection */ + /** @var ConnectionAdapter */ private $connection; /** @var SystemConfig */ @@ -78,15 +80,15 @@ class QueryBuilder implements IQueryBuilder { /** * Initializes a new QueryBuilder. * - * @param IDBConnection $connection + * @param ConnectionAdapter $connection * @param SystemConfig $systemConfig * @param ILogger $logger */ - public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger) { + public function __construct(ConnectionAdapter $connection, SystemConfig $systemConfig, ILogger $logger) { $this->connection = $connection; $this->systemConfig = $systemConfig; $this->logger = $logger; - $this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection); + $this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection->getInner()); $this->helper = new QuoteHelper(); } @@ -118,17 +120,20 @@ class QueryBuilder implements IQueryBuilder { * @return \OCP\DB\QueryBuilder\IExpressionBuilder */ public function expr() { - if ($this->connection instanceof OracleConnection) { + if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { return new OCIExpressionBuilder($this->connection, $this); - } elseif ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) { + } + if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) { return new PgSqlExpressionBuilder($this->connection, $this); - } elseif ($this->connection->getDatabasePlatform() instanceof MySqlPlatform) { + } + if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) { return new MySqlExpressionBuilder($this->connection, $this); - } elseif ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { + } + if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { return new SqliteExpressionBuilder($this->connection, $this); - } else { - return new ExpressionBuilder($this->connection, $this); } + + return new ExpressionBuilder($this->connection, $this); } /** @@ -148,15 +153,17 @@ class QueryBuilder implements IQueryBuilder { * @return \OCP\DB\QueryBuilder\IFunctionBuilder */ public function func() { - if ($this->connection instanceof OracleConnection) { + if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { return new OCIFunctionBuilder($this->helper); - } elseif ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { + } + if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { return new SqliteFunctionBuilder($this->helper); - } elseif ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) { + } + if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) { return new PgSqlFunctionBuilder($this->helper); - } else { - return new FunctionBuilder($this->helper); } + + return new FunctionBuilder($this->helper); } /** @@ -192,7 +199,7 @@ class QueryBuilder implements IQueryBuilder { * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} * for insert, update and delete statements. * - * @return \Doctrine\DBAL\Driver\Statement|int + * @return IResult|int */ public function execute() { if ($this->systemConfig->getValue('log_query', false)) { @@ -246,7 +253,11 @@ class QueryBuilder implements IQueryBuilder { } } - return $this->queryBuilder->execute(); + $result = $this->queryBuilder->execute(); + if (is_int($result)) { + return $result; + } + return new ResultAdapter($result); } /** diff --git a/lib/private/DB/ReconnectWrapper.php b/lib/private/DB/ReconnectWrapper.php index 9599d6b0fe6..a0170152862 100644 --- a/lib/private/DB/ReconnectWrapper.php +++ b/lib/private/DB/ReconnectWrapper.php @@ -44,12 +44,12 @@ class ReconnectWrapper extends \Doctrine\DBAL\Connection { if ($this->lastConnectionCheck > $checkTime || $this->isTransactionActive()) { return parent::connect(); - } else { - $this->lastConnectionCheck = $now; - if (!$this->ping()) { - $this->close(); - } - return parent::connect(); } + + $this->lastConnectionCheck = $now; + if (!$this->isConnected()) { + $this->close(); + } + return parent::connect(); } } diff --git a/lib/private/DB/ResultAdapter.php b/lib/private/DB/ResultAdapter.php new file mode 100644 index 00000000000..176de5b45ea --- /dev/null +++ b/lib/private/DB/ResultAdapter.php @@ -0,0 +1,71 @@ +<?php +/* + * @copyright 2021 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2021 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +declare(strict_types=1); + +namespace OC\DB; + +use Doctrine\DBAL\Result; +use OCP\DB\IResult; +use PDO; + +/** + * Adapts DBAL 2.6 API for DBAL 3.x for backwards compatibility of a leaked type + */ +class ResultAdapter implements IResult { + + /** @var Result */ + private $inner; + + public function __construct(Result $inner) { + $this->inner = $inner; + } + + public function closeCursor(): bool { + $this->inner->free(); + + return true; + } + + public function fetch(int $fetchMode = PDO::FETCH_ASSOC) { + return $this->inner->fetch($fetchMode); + } + + public function fetchAll(int $fetchMode = PDO::FETCH_ASSOC): array { + if ($fetchMode !== PDO::FETCH_ASSOC && $fetchMode !== PDO::FETCH_NUM && $fetchMode !== PDO::FETCH_COLUMN) { + throw new \Exception('Fetch mode needs to be assoc, num or column.'); + } + return $this->inner->fetchAll($fetchMode); + } + + public function fetchColumn($columnIndex = 0) { + return $this->inner->fetchOne(); + } + + public function fetchOne() { + return $this->inner->fetchOne(); + } + + public function rowCount(): int { + return $this->inner->rowCount(); + } +} diff --git a/lib/private/DB/SQLiteMigrator.php b/lib/private/DB/SQLiteMigrator.php index 16f18be135e..24b6c02b31c 100644 --- a/lib/private/DB/SQLiteMigrator.php +++ b/lib/private/DB/SQLiteMigrator.php @@ -26,7 +26,6 @@ namespace OC\DB; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Types\BigIntType; use Doctrine\DBAL\Types\Type; @@ -34,42 +33,6 @@ use Doctrine\DBAL\Types\Type; class SQLiteMigrator extends Migrator { /** - * @param \Doctrine\DBAL\Schema\Schema $targetSchema - * @throws \OC\DB\MigrationException - * - * For sqlite we simple make a copy of the entire database, and test the migration on that - */ - public function checkMigrate(\Doctrine\DBAL\Schema\Schema $targetSchema) { - $dbFile = $this->connection->getDatabase(); - $tmpFile = $this->buildTempDatabase(); - copy($dbFile, $tmpFile); - - $connectionParams = [ - 'path' => $tmpFile, - 'driver' => 'pdo_sqlite', - ]; - $conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); - try { - $this->applySchema($targetSchema, $conn); - $conn->close(); - unlink($tmpFile); - } catch (DBALException $e) { - $conn->close(); - unlink($tmpFile); - throw new MigrationException('', $e->getMessage()); - } - } - - /** - * @return string - */ - private function buildTempDatabase() { - $dataDir = $this->config->getSystemValue("datadirectory", \OC::$SERVERROOT . '/data'); - $tmpFile = uniqid("oc_"); - return "$dataDir/$tmpFile.db"; - } - - /** * @param Schema $targetSchema * @param \Doctrine\DBAL\Connection $connection * @return \Doctrine\DBAL\Schema\SchemaDiff diff --git a/lib/private/DB/SQLiteSessionInit.php b/lib/private/DB/SQLiteSessionInit.php index 0c53a0587f0..924a3b2758c 100644 --- a/lib/private/DB/SQLiteSessionInit.php +++ b/lib/private/DB/SQLiteSessionInit.php @@ -60,8 +60,9 @@ class SQLiteSessionInit implements EventSubscriber { $sensitive = $this->caseSensitiveLike ? 'true' : 'false'; $args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = ' . $sensitive); $args->getConnection()->executeUpdate('PRAGMA journal_mode = ' . $this->journalMode); - /** @var \PDO $pdo */ - $pdo = $args->getConnection()->getWrappedConnection(); + /** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */ + $connection = $args->getConnection()->getWrappedConnection(); + $pdo = $connection->getWrappedConnection(); $pdo->sqliteCreateFunction('md5', 'md5', 1); } diff --git a/lib/private/DB/SchemaWrapper.php b/lib/private/DB/SchemaWrapper.php index 440008d35b3..20ae5b6faa6 100644 --- a/lib/private/DB/SchemaWrapper.php +++ b/lib/private/DB/SchemaWrapper.php @@ -26,11 +26,10 @@ namespace OC\DB; use Doctrine\DBAL\Schema\Schema; use OCP\DB\ISchemaWrapper; -use OCP\IDBConnection; class SchemaWrapper implements ISchemaWrapper { - /** @var IDBConnection|Connection */ + /** @var Connection */ protected $connection; /** @var Schema */ @@ -39,10 +38,7 @@ class SchemaWrapper implements ISchemaWrapper { /** @var array */ protected $tablesToDelete = []; - /** - * @param IDBConnection $connection - */ - public function __construct(IDBConnection $connection) { + public function __construct(Connection $connection) { $this->connection = $connection; $this->schema = $this->connection->createSchema(); } |