summaryrefslogtreecommitdiffstats
path: root/lib/private/DB
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2021-01-03 15:28:31 +0100
committerChristoph Wurst <christoph@winzerhof-wurst.at>2021-01-08 11:45:19 +0100
commit8b64e92b9262d2a2eec6345685ce421050f95c66 (patch)
treedd51490b8a184b2643414d11867a9fa450aa5065 /lib/private/DB
parent84e6e9f7cf19207041925eaa237d24e1c12c2c2d (diff)
downloadnextcloud-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')
-rw-r--r--lib/private/DB/Adapter.php4
-rw-r--r--lib/private/DB/AdapterPgSql.php9
-rw-r--r--lib/private/DB/AdapterSqlite.php2
-rw-r--r--lib/private/DB/Connection.php58
-rw-r--r--lib/private/DB/ConnectionAdapter.php172
-rw-r--r--lib/private/DB/MDB2SchemaManager.php24
-rw-r--r--lib/private/DB/MDB2SchemaWriter.php181
-rw-r--r--lib/private/DB/MigrationService.php9
-rw-r--r--lib/private/DB/Migrator.php57
-rw-r--r--lib/private/DB/MySqlTools.php2
-rw-r--r--lib/private/DB/OracleMigrator.php8
-rw-r--r--lib/private/DB/PgSqlTools.php19
-rw-r--r--lib/private/DB/PreparedStatement.php101
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php7
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php9
-rw-r--r--lib/private/DB/QueryBuilder/QueryBuilder.php53
-rw-r--r--lib/private/DB/ReconnectWrapper.php12
-rw-r--r--lib/private/DB/ResultAdapter.php71
-rw-r--r--lib/private/DB/SQLiteMigrator.php37
-rw-r--r--lib/private/DB/SQLiteSessionInit.php5
-rw-r--r--lib/private/DB/SchemaWrapper.php8
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();
}