diff --git a/3rdparty b/3rdparty index 86573beb84..09596e43fb 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 86573beb84cf3b62b6d01ee377225df83b7d2453 +Subproject commit 09596e43fba86a3643879595a8fb6fece4af6a78 diff --git a/apps/contactsinteraction/lib/Db/CardSearchDao.php b/apps/contactsinteraction/lib/Db/CardSearchDao.php index 0636829272..8686183d18 100644 --- a/apps/contactsinteraction/lib/Db/CardSearchDao.php +++ b/apps/contactsinteraction/lib/Db/CardSearchDao.php @@ -82,7 +82,7 @@ class CardSearchDao { ->setMaxResults(1); $result = $cardQuery->execute(); /** @var string|resource|false $card */ - $card = $result->fetchColumn(0); + $card = $result->fetchOne(); if ($card === false) { return null; diff --git a/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php b/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php index 5a32177940..e394890e0e 100644 --- a/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php +++ b/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php @@ -401,7 +401,7 @@ class UpdateCalendarResourcesRoomsBackgroundJob extends TimedJob { return array_map(function ($row) { return $row['resource_id']; - }, $stmt->fetchAll(\PDO::FETCH_NAMED)); + }, $stmt->fetchAll()); } /** @@ -435,6 +435,6 @@ class UpdateCalendarResourcesRoomsBackgroundJob extends TimedJob { ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId))); $stmt = $query->execute(); - return $stmt->fetch(\PDO::FETCH_NAMED)['id']; + return $stmt->fetch()['id']; } } diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 178affc46b..ea1a30c629 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -256,7 +256,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } $result = $query->execute(); - $column = (int)$result->fetchColumn(); + $column = (int)$result->fetchOne(); $result->closeCursor(); return $column; } @@ -1114,7 +1114,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription ->andWhere($q->expr()->eq('calendartype', $q->createNamedParameter($calendarType))); $result = $q->execute(); - $count = (int) $result->fetchColumn(); + $count = (int) $result->fetchOne(); $result->closeCursor(); if ($count !== 0) { @@ -1963,7 +1963,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription // Current synctoken $stmt = $this->db->prepare('SELECT `synctoken` FROM `*PREFIX*calendars` WHERE `id` = ?'); $stmt->execute([ $calendarId ]); - $currentToken = $stmt->fetchColumn(0); + $currentToken = $stmt->fetchOne(); if (is_null($currentToken)) { return null; @@ -2373,7 +2373,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription ->from($table) ->where($query->expr()->eq('id', $query->createNamedParameter($calendarId))); $result = $query->execute(); - $syncToken = (int)$result->fetchColumn(); + $syncToken = (int)$result->fetchOne(); $result->closeCursor(); $query = $this->db->getQueryBuilder(); diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index c95f6b072e..d5c3609695 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -140,7 +140,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))); $result = $query->execute(); - $column = (int) $result->fetchColumn(); + $column = (int) $result->fetchOne(); $result->closeCursor(); return $column; } @@ -661,7 +661,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { ->andWhere($q->expr()->eq('uid', $q->createNamedParameter($uid))) ->setMaxResults(1); $result = $q->execute(); - $count = (bool)$result->fetchColumn(); + $count = (bool)$result->fetchOne(); $result->closeCursor(); if ($count) { throw new \Sabre\DAV\Exception\BadRequest('VCard object with uid already exists in this addressbook collection.'); @@ -864,7 +864,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { // Current synctoken $stmt = $this->db->prepare('SELECT `synctoken` FROM `*PREFIX*addressbooks` WHERE `id` = ?'); $stmt->execute([$addressBookId]); - $currentToken = $stmt->fetchColumn(0); + $currentToken = $stmt->fetchOne(); if (is_null($currentToken)) { return null; diff --git a/apps/dav/lib/Migration/BuildCalendarSearchIndex.php b/apps/dav/lib/Migration/BuildCalendarSearchIndex.php index 7caa53be89..f731fdf896 100644 --- a/apps/dav/lib/Migration/BuildCalendarSearchIndex.php +++ b/apps/dav/lib/Migration/BuildCalendarSearchIndex.php @@ -77,7 +77,7 @@ class BuildCalendarSearchIndex implements IRepairStep { $query->select($query->createFunction('MAX(' . $query->getColumnName('id') . ')')) ->from('calendarobjects'); $result = $query->execute(); - $maxId = (int) $result->fetchColumn(); + $maxId = (int) $result->fetchOne(); $result->closeCursor(); $output->info('Add background job'); diff --git a/apps/dav/lib/Migration/BuildSocialSearchIndex.php b/apps/dav/lib/Migration/BuildSocialSearchIndex.php index 4498643688..b7888b423c 100644 --- a/apps/dav/lib/Migration/BuildSocialSearchIndex.php +++ b/apps/dav/lib/Migration/BuildSocialSearchIndex.php @@ -74,8 +74,8 @@ class BuildSocialSearchIndex implements IRepairStep { $query->select($query->func()->max('cardid')) ->from('cards_properties') ->where($query->expr()->eq('name', $query->createNamedParameter('X-SOCIALPROFILE'))); - $maxId = (int)$query->execute()->fetchColumn(); - + $maxId = (int)$query->execute()->fetchOne(); + if ($maxId === 0) { return; } diff --git a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php index 58096e3f3c..272a0895e9 100644 --- a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php +++ b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php @@ -107,7 +107,7 @@ class CalDAVRemoveEmptyValue implements IRepairStep { $query->select($query->func()->count('*', 'num_entries')) ->from('calendarobjects'); $result = $query->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $result->closeCursor(); $numChunks = ceil($count / $chunkSize); diff --git a/apps/dav/lib/Migration/RegisterBuildReminderIndexBackgroundJob.php b/apps/dav/lib/Migration/RegisterBuildReminderIndexBackgroundJob.php index 0f3ed1f0ad..53087ff467 100644 --- a/apps/dav/lib/Migration/RegisterBuildReminderIndexBackgroundJob.php +++ b/apps/dav/lib/Migration/RegisterBuildReminderIndexBackgroundJob.php @@ -88,7 +88,7 @@ class RegisterBuildReminderIndexBackgroundJob implements IRepairStep { $query->select($query->createFunction('MAX(' . $query->getColumnName('id') . ')')) ->from('calendarobjects'); $result = $query->execute(); - $maxId = (int) $result->fetchColumn(); + $maxId = (int) $result->fetchOne(); $result->closeCursor(); $output->info('Add background job'); diff --git a/apps/files_sharing/lib/Command/CleanupRemoteStorages.php b/apps/files_sharing/lib/Command/CleanupRemoteStorages.php index 259e55ff62..db18e7d249 100644 --- a/apps/files_sharing/lib/Command/CleanupRemoteStorages.php +++ b/apps/files_sharing/lib/Command/CleanupRemoteStorages.php @@ -106,7 +106,7 @@ class CleanupRemoteStorages extends Command { IQueryBuilder::PARAM_STR) ); $result = $queryBuilder->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $output->writeln("$count files can be deleted for storage $numericId"); } diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php index d02ac97ba3..534dd0d2c5 100644 --- a/apps/files_sharing/lib/External/Manager.php +++ b/apps/files_sharing/lib/External/Manager.php @@ -33,6 +33,7 @@ namespace OCA\Files_Sharing\External; +use Doctrine\DBAL\Driver\Exception; use OC\Files\Filesystem; use OCA\FederatedFileSharing\Events\FederatedShareAddedEvent; use OCA\Files_Sharing\Helper; @@ -129,7 +130,7 @@ class Manager { * @param string $remoteId * @param int $parent * @return Mount|null - * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Exception */ public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted = false, $user = null, $remoteId = '', $parent = -1) { $user = $user ? $user : $this->uid; @@ -199,15 +200,17 @@ class Manager { * @param $remoteId * @param $parent * @param $shareType - * @return bool + * + * @return void + * @throws \Doctrine\DBAL\Driver\Exception */ - private function writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType) { + private function writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType): void { $query = $this->connection->prepare(' INSERT INTO `*PREFIX*share_external` (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`, `parent`, `share_type`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '); - return $query->execute([$remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType]); + $query->execute([$remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType]); } /** @@ -222,9 +225,8 @@ class Manager { FROM `*PREFIX*share_external` WHERE `id` = ?'); $result = $getShare->execute([$id]); - - $share = $result ? $getShare->fetch() : []; - + $share = $result->fetch(); + $result->closeCursor(); $validShare = is_array($share) && isset($share['share_type']) && isset($share['user']); // check if the user is allowed to access it @@ -267,19 +269,24 @@ class Manager { WHERE `id` = ? AND `user` = ?'); $userShareAccepted = $acceptShare->execute([1, $mountPoint, $hash, $id, $this->uid]); } else { - $result = $this->writeShareToDb( - $share['remote'], - $share['share_token'], - $share['password'], - $share['name'], - $share['owner'], - $this->uid, - $mountPoint, $hash, 1, - $share['remote_id'], - $id, - $share['share_type']); + try { + $this->writeShareToDb( + $share['remote'], + $share['share_token'], + $share['password'], + $share['name'], + $share['owner'], + $this->uid, + $mountPoint, $hash, 1, + $share['remote_id'], + $id, + $share['share_type']); + $result = true; + } catch (Exception $e) { + $result = false; + } } - if ($userShareAccepted === true) { + if ($userShareAccepted !== false) { $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept'); $event = new FederatedShareAddedEvent($share['remote']); $this->eventDispatcher->dispatchTyped($event); @@ -312,19 +319,24 @@ class Manager { $this->processNotification($id); $result = true; } elseif ($share && (int)$share['share_type'] === IShare::TYPE_GROUP) { - $result = $this->writeShareToDb( - $share['remote'], - $share['share_token'], - $share['password'], - $share['name'], - $share['owner'], - $this->uid, - $share['mountpoint'], - $share['mountpoint_hash'], - 0, - $share['remote_id'], - $id, - $share['share_type']); + try { + $this->writeShareToDb( + $share['remote'], + $share['share_token'], + $share['password'], + $share['name'], + $share['owner'], + $this->uid, + $share['mountpoint'], + $share['mountpoint_hash'], + 0, + $share['remote_id'], + $id, + $share['share_type']); + $result = true; + } catch (Exception $e) { + $result = false; + } $this->processNotification($id); } @@ -484,47 +496,50 @@ class Manager { return $result; } - public function removeShare($mountPoint) { + public function removeShare($mountPoint): bool { $mountPointObj = $this->mountManager->find($mountPoint); $id = $mountPointObj->getStorage()->getCache()->getId(''); $mountPoint = $this->stripPath($mountPoint); $hash = md5($mountPoint); - $getShare = $this->connection->prepare(' - SELECT `remote`, `share_token`, `remote_id`, `share_type`, `id` - FROM `*PREFIX*share_external` - WHERE `mountpoint_hash` = ? AND `user` = ?'); - $result = $getShare->execute([$hash, $this->uid]); + try { + $getShare = $this->connection->prepare(' + SELECT `remote`, `share_token`, `remote_id`, `share_type`, `id` + FROM `*PREFIX*share_external` + WHERE `mountpoint_hash` = ? AND `user` = ?'); + $result = $getShare->execute([$hash, $this->uid]); + $share = $result->fetch(); + $result->closeCursor(); + if ($share !== false && (int)$share['share_type'] === IShare::TYPE_USER) { + try { + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); + } catch (\Throwable $e) { + // if we fail to notify the remote (probably cause the remote is down) + // we still want the share to be gone to prevent undeletable remotes + } - $share = $getShare->fetch(); - $getShare->closeCursor(); - if ($result && $share !== false && (int)$share['share_type'] === IShare::TYPE_USER) { - try { - $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); - } catch (\Throwable $e) { - // if we fail to notify the remote (probably cause the remote is down) - // we still want the share to be gone to prevent undeletable remotes + $query = $this->connection->prepare(' + DELETE FROM `*PREFIX*share_external` + WHERE `id` = ? + '); + $deleteResult = $query->execute([(int)$share['id']]); + $deleteResult->closeCursor(); + } elseif ($share !== false && (int)$share['share_type'] === IShare::TYPE_GROUP) { + $query = $this->connection->prepare(' + UPDATE `*PREFIX*share_external` + SET `accepted` = ? + WHERE `id` = ?'); + $updateResult = $query->execute([0, (int)$share['id']]); + $updateResult->closeCursor(); } - $query = $this->connection->prepare(' - DELETE FROM `*PREFIX*share_external` - WHERE `id` = ? - '); - $result = (bool)$query->execute([(int)$share['id']]); - } elseif ($result && $share !== false && (int)$share['share_type'] === IShare::TYPE_GROUP) { - $query = $this->connection->prepare(' - UPDATE `*PREFIX*share_external` - SET `accepted` = ? - WHERE `id` = ?'); - $result = (bool)$query->execute([0, (int)$share['id']]); - } - - if ($result) { $this->removeReShares($id); + } catch (\Doctrine\DBAL\Exception $ex) { + return false; } - return $result; + return true; } /** @@ -554,27 +569,31 @@ class Manager { * remove all shares for user $uid if the user was deleted * * @param string $uid - * @return bool */ - public function removeUserShares($uid) { - $getShare = $this->connection->prepare(' - SELECT `remote`, `share_token`, `remote_id` - FROM `*PREFIX*share_external` - WHERE `user` = ?'); - $result = $getShare->execute([$uid]); - - if ($result) { - $shares = $getShare->fetchAll(); + public function removeUserShares($uid): bool { + try { + $getShare = $this->connection->prepare(' + SELECT `remote`, `share_token`, `remote_id` + FROM `*PREFIX*share_external` + WHERE `user` = ?'); + $result = $getShare->execute([$uid]); + $shares = $result->fetchAll(); + $result->closeCursor(); foreach ($shares as $share) { $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); } + + $query = $this->connection->prepare(' + DELETE FROM `*PREFIX*share_external` + WHERE `user` = ? + '); + $deleteResult = $query->execute([$uid]); + $deleteResult->closeCursor(); + } catch (\Doctrine\DBAL\Exception $ex) { + return false; } - $query = $this->connection->prepare(' - DELETE FROM `*PREFIX*share_external` - WHERE `user` = ? - '); - return (bool)$query->execute([$uid]); + return true; } /** @@ -621,9 +640,14 @@ class Manager { } $query .= ' ORDER BY `id` ASC'; - $shares = $this->connection->prepare($query); - $result = $shares->execute($parameters); - - return $result ? $shares->fetchAll() : []; + $sharesQuery = $this->connection->prepare($query); + try { + $result = $sharesQuery->execute($parameters); + $shares = $result->fetchAll(); + $result->closeCursor(); + return $shares; + } catch (\Doctrine\DBAL\Exception $e) { + return []; + } } } diff --git a/apps/files_trashbin/tests/Command/CleanUpTest.php b/apps/files_trashbin/tests/Command/CleanUpTest.php index 329089bcaf..dad73aaadf 100644 --- a/apps/files_trashbin/tests/Command/CleanUpTest.php +++ b/apps/files_trashbin/tests/Command/CleanUpTest.php @@ -30,6 +30,7 @@ namespace OCA\Files_Trashbin\Tests\Command; use OC\User\Manager; use OCA\Files_Trashbin\Command\CleanUp; use OCP\Files\IRootFolder; +use OCP\IDBConnection; use Symfony\Component\Console\Exception\InvalidOptionException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -53,7 +54,7 @@ class CleanUpTest extends TestCase { /** @var \PHPUnit\Framework\MockObject\MockObject | IRootFolder */ protected $rootFolder; - /** @var \OC\DB\Connection */ + /** @var IDBConnection */ protected $dbConnection; /** @var string */ diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php index 5b004d753e..6acd970c40 100644 --- a/apps/settings/lib/Controller/CheckSetupController.php +++ b/apps/settings/lib/Controller/CheckSetupController.php @@ -44,8 +44,9 @@ namespace OCA\Settings\Controller; use bantu\IniGetWrapper\IniGetWrapper; use DirectoryIterator; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\SqlitePlatform; +use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Types; use GuzzleHttp\Exception\ClientException; use OC; @@ -94,7 +95,7 @@ class CheckSetupController extends Controller { private $logger; /** @var EventDispatcherInterface */ private $dispatcher; - /** @var IDBConnection|Connection */ + /** @var Connection */ private $db; /** @var ILockingProvider */ private $lockingProvider; @@ -116,7 +117,7 @@ class CheckSetupController extends Controller { Checker $checker, ILogger $logger, EventDispatcherInterface $dispatcher, - IDBConnection $db, + Connection $db, ILockingProvider $lockingProvider, IDateTimeFormatter $dateTimeFormatter, MemoryInfo $memoryInfo, @@ -492,8 +493,8 @@ Raw output return true; } - return $this->db->getTransactionIsolation() === Connection::TRANSACTION_READ_COMMITTED; - } catch (DBALException $e) { + return $this->db->getTransactionIsolation() === TransactionIsolationLevel::READ_COMMITTED; + } catch (Exception $e) { // ignore } diff --git a/apps/user_ldap/lib/Mapping/AbstractMapping.php b/apps/user_ldap/lib/Mapping/AbstractMapping.php index 15f95744cd..f9f2b125d0 100644 --- a/apps/user_ldap/lib/Mapping/AbstractMapping.php +++ b/apps/user_ldap/lib/Mapping/AbstractMapping.php @@ -27,7 +27,9 @@ namespace OCA\User_LDAP\Mapping; +use Doctrine\DBAL\Exception; use OC\DB\QueryBuilder\QueryBuilder; +use OCP\DB\IPreparedStatement; /** * Class AbstractMapping @@ -95,24 +97,32 @@ abstract class AbstractMapping { WHERE `' . $compareCol . '` = ? '); - $res = $query->execute([$search]); - if ($res !== false) { - return $query->fetchColumn(); + try { + $res = $query->execute([$search]); + $data = $res->fetchOne(); + $res->closeCursor(); + return $data; + } catch (Exception $e) { + return false; } - - return false; } /** * Performs a DELETE or UPDATE query to the database. * - * @param \Doctrine\DBAL\Driver\Statement $query + * @param IPreparedStatement $statement * @param array $parameters * @return bool true if at least one row was modified, false otherwise */ - protected function modify($query, $parameters) { - $result = $query->execute($parameters); - return ($result === true && $query->rowCount() > 0); + protected function modify(IPreparedStatement $statement, $parameters) { + try { + $result = $statement->execute($parameters); + $updated = $result->rowCount() > 0; + $result->closeCursor(); + return $updated; + } catch (Exception $e) { + return false; + } } /** @@ -139,13 +149,13 @@ abstract class AbstractMapping { */ public function setDNbyUUID($fdn, $uuid) { $oldDn = $this->getDnByUUID($uuid); - $query = $this->dbc->prepare(' + $statement = $this->dbc->prepare(' UPDATE `' . $this->getTableName() . '` SET `ldap_dn` = ? WHERE `directory_uuid` = ? '); - $r = $this->modify($query, [$fdn, $uuid]); + $r = $this->modify($statement, [$fdn, $uuid]); if ($r && is_string($oldDn) && isset($this->cache[$oldDn])) { $this->cache[$fdn] = $this->cache[$oldDn]; @@ -165,7 +175,7 @@ abstract class AbstractMapping { * @return bool */ public function setUUIDbyDN($uuid, $fdn) { - $query = $this->dbc->prepare(' + $statement = $this->dbc->prepare(' UPDATE `' . $this->getTableName() . '` SET `directory_uuid` = ? WHERE `ldap_dn` = ? @@ -173,7 +183,7 @@ abstract class AbstractMapping { unset($this->cache[$fdn]); - return $this->modify($query, [$uuid, $fdn]); + return $this->modify($statement, [$uuid, $fdn]); } /** @@ -215,18 +225,20 @@ abstract class AbstractMapping { * @return string[] */ public function getNamesBySearch($search, $prefixMatch = "", $postfixMatch = "") { - $query = $this->dbc->prepare(' + $statement = $this->dbc->prepare(' SELECT `owncloud_name` FROM `' . $this->getTableName() . '` WHERE `owncloud_name` LIKE ? '); - $res = $query->execute([$prefixMatch . $this->dbc->escapeLikeParameter($search) . $postfixMatch]); + try { + $res = $statement->execute([$prefixMatch . $this->dbc->escapeLikeParameter($search) . $postfixMatch]); + } catch (Exception $e) { + return []; + } $names = []; - if ($res !== false) { - while ($row = $query->fetch()) { - $names[] = $row['owncloud_name']; - } + while ($row = $res->fetch()) { + $names[] = $row['owncloud_name']; } return $names; } @@ -323,15 +335,15 @@ abstract class AbstractMapping { * @return bool */ public function unmap($name) { - $query = $this->dbc->prepare(' + $statement = $this->dbc->prepare(' DELETE FROM `' . $this->getTableName() . '` WHERE `owncloud_name` = ?'); - return $this->modify($query, [$name]); + return $this->modify($statement, [$name]); } /** - * Truncate's the mapping table + * Truncates the mapping table * * @return bool */ @@ -339,7 +351,13 @@ abstract class AbstractMapping { $sql = $this->dbc ->getDatabasePlatform() ->getTruncateTableSQL('`' . $this->getTableName() . '`'); - return $this->dbc->prepare($sql)->execute(); + try { + $this->dbc->executeQuery($sql); + + return true; + } catch (Exception $e) { + return false; + } } /** @@ -357,7 +375,7 @@ abstract class AbstractMapping { ->from($this->getTableName()); $cursor = $picker->execute(); $result = true; - while ($id = $cursor->fetchColumn(0)) { + while ($id = $cursor->fetchOne()) { $preCallback($id); if ($isUnmapped = $this->unmap($id)) { $postCallback($id); @@ -378,7 +396,7 @@ abstract class AbstractMapping { $query = $qb->select($qb->func()->count('ldap_dn')) ->from($this->getTableName()); $res = $query->execute(); - $count = $res->fetchColumn(); + $count = $res->fetchOne(); $res->closeCursor(); return (int)$count; } diff --git a/apps/workflowengine/lib/Controller/AWorkflowController.php b/apps/workflowengine/lib/Controller/AWorkflowController.php index 6d109f7dcc..8b0d35ef62 100644 --- a/apps/workflowengine/lib/Controller/AWorkflowController.php +++ b/apps/workflowengine/lib/Controller/AWorkflowController.php @@ -25,7 +25,7 @@ declare(strict_types=1); namespace OCA\WorkflowEngine\Controller; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use OCA\WorkflowEngine\Helper\ScopeContext; use OCA\WorkflowEngine\Manager; use OCP\AppFramework\Http\DataResponse; @@ -112,7 +112,7 @@ abstract class AWorkflowController extends OCSController { throw new OCSBadRequestException($e->getMessage(), $e); } catch (\DomainException $e) { throw new OCSForbiddenException($e->getMessage(), $e); - } catch (DBALException $e) { + } catch (Exception $e) { throw new OCSException('An internal error occurred', $e->getCode(), $e); } } @@ -139,7 +139,7 @@ abstract class AWorkflowController extends OCSController { throw new OCSBadRequestException($e->getMessage(), $e); } catch (\DomainException $e) { throw new OCSForbiddenException($e->getMessage(), $e); - } catch (DBALException $e) { + } catch (Exception $e) { throw new OCSException('An internal error occurred', $e->getCode(), $e); } } @@ -157,7 +157,7 @@ abstract class AWorkflowController extends OCSController { throw new OCSBadRequestException($e->getMessage(), $e); } catch (\DomainException $e) { throw new OCSForbiddenException($e->getMessage(), $e); - } catch (DBALException $e) { + } catch (Exception $e) { throw new OCSException('An internal error occurred', $e->getCode(), $e); } } diff --git a/apps/workflowengine/lib/Manager.php b/apps/workflowengine/lib/Manager.php index 87c3c5de6b..8c37e4d988 100644 --- a/apps/workflowengine/lib/Manager.php +++ b/apps/workflowengine/lib/Manager.php @@ -21,7 +21,7 @@ namespace OCA\WorkflowEngine; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use OC\Cache\CappedMemoryCache; use OCA\WorkflowEngine\AppInfo\Application; use OCA\WorkflowEngine\Check\FileMimeType; @@ -290,7 +290,7 @@ class Manager implements IManager { * @param string $operation * @return array The added operation * @throws \UnexpectedValueException - * @throws DBALException + * @throw Exception */ public function addOperation( string $class, @@ -315,7 +315,7 @@ class Manager implements IManager { $this->addScope($id, $scope); $this->connection->commit(); - } catch (DBALException $e) { + } catch (Exception $e) { $this->connection->rollBack(); throw $e; } @@ -342,7 +342,7 @@ class Manager implements IManager { $result = $qb->execute(); $this->operationsByScope[$scopeContext->getHash()] = []; - while ($opId = $result->fetchColumn(0)) { + while ($opId = $result->fetchOne()) { $this->operationsByScope[$scopeContext->getHash()][] = (int)$opId; } $result->closeCursor(); @@ -358,7 +358,7 @@ class Manager implements IManager { * @return array The updated operation * @throws \UnexpectedValueException * @throws \DomainException - * @throws DBALException + * @throws Exception */ public function updateOperation( int $id, @@ -392,7 +392,7 @@ class Manager implements IManager { ->where($query->expr()->eq('id', $query->createNamedParameter($id))); $query->execute(); $this->connection->commit(); - } catch (DBALException $e) { + } catch (Exception $e) { $this->connection->rollBack(); throw $e; } @@ -405,7 +405,7 @@ class Manager implements IManager { * @param int $id * @return bool * @throws \UnexpectedValueException - * @throws DBALException + * @throws Exception * @throws \DomainException */ public function deleteOperation($id, ScopeContext $scopeContext) { @@ -425,7 +425,7 @@ class Manager implements IManager { ->execute(); } $this->connection->commit(); - } catch (DBALException $e) { + } catch (Exception $e) { $this->connection->rollBack(); throw $e; } diff --git a/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php b/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php index 50b38f8199..290dae4c67 100644 --- a/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php +++ b/apps/workflowengine/lib/Migration/PopulateNewlyIntroducedDatabaseFields.php @@ -25,7 +25,7 @@ declare(strict_types=1); namespace OCA\WorkflowEngine\Migration; -use Doctrine\DBAL\Driver\Statement; +use OCP\DB\IResult; use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; @@ -52,17 +52,17 @@ class PopulateNewlyIntroducedDatabaseFields implements IRepairStep { $result->closeCursor(); } - protected function populateScopeTable(Statement $ids): void { + protected function populateScopeTable(IResult $ids): void { $qb = $this->dbc->getQueryBuilder(); $insertQuery = $qb->insert('flow_operations_scope'); - while ($id = $ids->fetchColumn(0)) { + while ($id = $ids->fetchOne()) { $insertQuery->values(['operation_id' => $qb->createNamedParameter($id), 'type' => IManager::SCOPE_ADMIN]); $insertQuery->execute(); } } - protected function getIdsWithoutScope(): Statement { + protected function getIdsWithoutScope(): IResult { $qb = $this->dbc->getQueryBuilder(); $selectQuery = $qb->select('o.id') ->from('flow_operations', 'o') @@ -71,6 +71,8 @@ class PopulateNewlyIntroducedDatabaseFields implements IRepairStep { // The left join operation is not necessary, usually, but it's a safe-guard // in case the repair step is executed multiple times for whatever reason. - return $selectQuery->execute(); + /** @var IResult $result */ + $result = $selectQuery->execute(); + return $result; } } diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index d461cdfc70..98f849eb81 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -3061,10 +3061,14 @@ - + + false + + $this->tar->extractInString($path) - + + resource string @@ -3076,6 +3080,10 @@ boolean|null boolean|null + + + resource + @@ -3584,6 +3592,9 @@ $eventName + + void + $eventName diff --git a/core/Application.php b/core/Application.php index 987358b5b9..c3cb6f02ed 100644 --- a/core/Application.php +++ b/core/Application.php @@ -41,6 +41,7 @@ use OC\Authentication\Listeners\UserDeletedStoreCleanupListener; use OC\Authentication\Listeners\UserDeletedTokenCleanupListener; use OC\Authentication\Notifications\Notifier as AuthenticationNotifier; use OC\Core\Notification\CoreNotifier; +use OC\DB\Connection; use OC\DB\MissingColumnInformation; use OC\DB\MissingIndexInformation; use OC\DB\MissingPrimaryKeyInformation; @@ -82,7 +83,7 @@ class Application extends App { /** @var MissingIndexInformation $subject */ $subject = $event->getSubject(); - $schema = new SchemaWrapper($container->query(IDBConnection::class)); + $schema = new SchemaWrapper($container->query(Connection::class)); if ($schema->hasTable('share')) { $table = $schema->getTable('share'); @@ -192,7 +193,7 @@ class Application extends App { /** @var MissingPrimaryKeyInformation $subject */ $subject = $event->getSubject(); - $schema = new SchemaWrapper($container->query(IDBConnection::class)); + $schema = new SchemaWrapper($container->query(Connection::class)); if ($schema->hasTable('federated_reshares')) { $table = $schema->getTable('federated_reshares'); @@ -249,7 +250,7 @@ class Application extends App { /** @var MissingColumnInformation $subject */ $subject = $event->getSubject(); - $schema = new SchemaWrapper($container->query(IDBConnection::class)); + $schema = new SchemaWrapper($container->query(Connection::class)); if ($schema->hasTable('comments')) { $table = $schema->getTable('comments'); diff --git a/core/Command/Db/AddMissingColumns.php b/core/Command/Db/AddMissingColumns.php index 3ace75b4ee..4b7fa03995 100644 --- a/core/Command/Db/AddMissingColumns.php +++ b/core/Command/Db/AddMissingColumns.php @@ -26,6 +26,7 @@ declare(strict_types=1); namespace OC\Core\Command\Db; +use OC\DB\Connection; use OC\DB\SchemaWrapper; use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; @@ -44,13 +45,13 @@ use Symfony\Component\EventDispatcher\GenericEvent; */ class AddMissingColumns extends Command { - /** @var IDBConnection */ + /** @var Connection */ private $connection; /** @var EventDispatcherInterface */ private $dispatcher; - public function __construct(IDBConnection $connection, EventDispatcherInterface $dispatcher) { + public function __construct(Connection $connection, EventDispatcherInterface $dispatcher) { parent::__construct(); $this->connection = $connection; diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php index 5cbd6ee405..1acff55fa4 100644 --- a/core/Command/Db/AddMissingIndices.php +++ b/core/Command/Db/AddMissingIndices.php @@ -33,6 +33,7 @@ declare(strict_types=1); namespace OC\Core\Command\Db; +use OC\DB\Connection; use OC\DB\SchemaWrapper; use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; @@ -51,13 +52,13 @@ use Symfony\Component\EventDispatcher\GenericEvent; */ class AddMissingIndices extends Command { - /** @var IDBConnection */ + /** @var Connection */ private $connection; /** @var EventDispatcherInterface */ private $dispatcher; - public function __construct(IDBConnection $connection, EventDispatcherInterface $dispatcher) { + public function __construct(Connection $connection, EventDispatcherInterface $dispatcher) { parent::__construct(); $this->connection = $connection; diff --git a/core/Command/Db/AddMissingPrimaryKeys.php b/core/Command/Db/AddMissingPrimaryKeys.php index ef3d6a05f2..7113ecb210 100644 --- a/core/Command/Db/AddMissingPrimaryKeys.php +++ b/core/Command/Db/AddMissingPrimaryKeys.php @@ -26,6 +26,7 @@ declare(strict_types=1); namespace OC\Core\Command\Db; +use OC\DB\Connection; use OC\DB\SchemaWrapper; use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; @@ -44,13 +45,13 @@ use Symfony\Component\EventDispatcher\GenericEvent; */ class AddMissingPrimaryKeys extends Command { - /** @var IDBConnection */ + /** @var Connection */ private $connection; /** @var EventDispatcherInterface */ private $dispatcher; - public function __construct(IDBConnection $connection, EventDispatcherInterface $dispatcher) { + public function __construct(Connection $connection, EventDispatcherInterface $dispatcher) { parent::__construct(); $this->connection = $connection; diff --git a/core/Command/Db/ConvertFilecacheBigInt.php b/core/Command/Db/ConvertFilecacheBigInt.php index 77f5034315..6001de6fb9 100644 --- a/core/Command/Db/ConvertFilecacheBigInt.php +++ b/core/Command/Db/ConvertFilecacheBigInt.php @@ -34,8 +34,8 @@ namespace OC\Core\Command\Db; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use OC\DB\Connection; use OC\DB\SchemaWrapper; -use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -43,13 +43,13 @@ use Symfony\Component\Console\Question\ConfirmationQuestion; class ConvertFilecacheBigInt extends Command { - /** @var IDBConnection */ + /** @var Connection */ private $connection; /** - * @param IDBConnection $connection + * @param Connection $connection */ - public function __construct(IDBConnection $connection) { + public function __construct(Connection $connection) { $this->connection = $connection; parent::__construct(); } diff --git a/core/Command/Db/ConvertMysqlToMB4.php b/core/Command/Db/ConvertMysqlToMB4.php index 4305f44628..55633ea994 100644 --- a/core/Command/Db/ConvertMysqlToMB4.php +++ b/core/Command/Db/ConvertMysqlToMB4.php @@ -24,7 +24,7 @@ namespace OC\Core\Command\Db; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use OC\DB\MySqlTools; use OC\Migration\ConsoleOutput; use OC\Repair\Collation; @@ -70,7 +70,7 @@ class ConvertMysqlToMB4 extends Command { } protected function execute(InputInterface $input, OutputInterface $output): int { - if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) { + if (!$this->connection->getDatabasePlatform() instanceof MySQLPlatform) { $output->writeln("This command is only valid for MySQL/MariaDB databases."); return 1; } diff --git a/core/Command/Db/ConvertType.php b/core/Command/Db/ConvertType.php index d89d57ff60..32b7492d96 100644 --- a/core/Command/Db/ConvertType.php +++ b/core/Command/Db/ConvertType.php @@ -33,9 +33,10 @@ namespace OC\Core\Command\Db; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Schema\AbstractAsset; use Doctrine\DBAL\Schema\Table; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use OC\DB\Connection; use OC\DB\ConnectionFactory; use OC\DB\MigrationService; @@ -52,6 +53,8 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; +use function preg_match; +use function preg_quote; class ConvertType extends Command implements CompletionAwareInterface { /** @@ -192,7 +195,8 @@ class ConvertType extends Command implements CompletionAwareInterface { $this->validateInput($input, $output); $this->readPassword($input, $output); - $fromDB = \OC::$server->getDatabaseConnection(); + /** @var Connection $fromDB */ + $fromDB = \OC::$server->get(Connection::class); $toDB = $this->getToDBConnection($input, $output); if ($input->getOption('clear-schema')) { @@ -283,9 +287,14 @@ class ConvertType extends Command implements CompletionAwareInterface { } protected function getTables(Connection $db) { - $filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/'; - $db->getConfiguration()-> - setFilterSchemaAssetsExpression($filterExpression); + $db->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; + }); return $db->getSchemaManager()->listTableNames(); } @@ -309,7 +318,7 @@ class ConvertType extends Command implements CompletionAwareInterface { $query->select($query->func()->count('*', 'num_entries')) ->from($table->getName()); $result = $query->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $result->closeCursor(); $numChunks = ceil($count / $chunkSize); @@ -330,7 +339,7 @@ class ConvertType extends Command implements CompletionAwareInterface { try { $orderColumns = $table->getPrimaryKeyColumns(); - } catch (DBALException $e) { + } catch (Exception $e) { $orderColumns = []; foreach ($table->getColumns() as $column) { $orderColumns[] = $column->getName(); @@ -384,11 +393,11 @@ class ConvertType extends Command implements CompletionAwareInterface { $type = $table->getColumn($columnName)->getType()->getName(); switch ($type) { - case Type::BLOB: - case Type::TEXT: + case Types::BLOB: + case Types::TEXT: $this->columnTypes[$tableName][$columnName] = IQueryBuilder::PARAM_LOB; break; - case Type::BOOLEAN: + case Types::BOOLEAN: $this->columnTypes[$tableName][$columnName] = IQueryBuilder::PARAM_BOOL; break; default: diff --git a/core/Command/Db/Migrations/ExecuteCommand.php b/core/Command/Db/Migrations/ExecuteCommand.php index 95f1acd14f..cc3f7d67fc 100644 --- a/core/Command/Db/Migrations/ExecuteCommand.php +++ b/core/Command/Db/Migrations/ExecuteCommand.php @@ -23,11 +23,10 @@ namespace OC\Core\Command\Db\Migrations; +use OC\DB\Connection; use OC\DB\MigrationService; use OC\Migration\ConsoleOutput; -use OCP\App\IAppManager; use OCP\IConfig; -use OCP\IDBConnection; use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; use Symfony\Component\Console\Command\Command; @@ -37,23 +36,19 @@ use Symfony\Component\Console\Output\OutputInterface; class ExecuteCommand extends Command implements CompletionAwareInterface { - /** @var IDBConnection */ + /** @var Connection */ private $connection; /** @var IConfig */ private $config; - /** @var IAppManager */ - protected $appManager; - /** * ExecuteCommand constructor. * - * @param IDBConnection $connection + * @param Connection $connection * @param IConfig $config - * @param IAppManager $appManager */ - public function __construct(IDBConnection $connection, IAppManager $appManager, IConfig $config) { + public function __construct(Connection $connection, IConfig $config) { $this->connection = $connection; $this->config = $config; diff --git a/core/Command/Db/Migrations/GenerateCommand.php b/core/Command/Db/Migrations/GenerateCommand.php index fcafa9431c..48fc59e77f 100644 --- a/core/Command/Db/Migrations/GenerateCommand.php +++ b/core/Command/Db/Migrations/GenerateCommand.php @@ -25,10 +25,10 @@ namespace OC\Core\Command\Db\Migrations; +use OC\DB\Connection; use OC\DB\MigrationService; use OC\Migration\ConsoleOutput; use OCP\App\IAppManager; -use OCP\IDBConnection; use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; use Symfony\Component\Console\Command\Command; @@ -83,17 +83,17 @@ class {{classname}} extends SimpleMigrationStep { } '; - /** @var IDBConnection */ + /** @var Connection */ protected $connection; /** @var IAppManager */ protected $appManager; /** - * @param IDBConnection $connection + * @param Connection $connection * @param IAppManager $appManager */ - public function __construct(IDBConnection $connection, IAppManager $appManager) { + public function __construct(Connection $connection, IAppManager $appManager) { $this->connection = $connection; $this->appManager = $appManager; diff --git a/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php b/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php index 71349c0fa5..9101957a97 100644 --- a/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php +++ b/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php @@ -26,12 +26,12 @@ namespace OC\Core\Command\Db\Migrations; use Doctrine\DBAL\Schema\Schema; +use OC\DB\Connection; use OC\DB\MDB2SchemaReader; use OC\DB\MigrationService; use OC\Migration\ConsoleOutput; use OCP\App\IAppManager; use OCP\IConfig; -use OCP\IDBConnection; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -40,7 +40,7 @@ class GenerateFromSchemaFileCommand extends GenerateCommand { /** @var IConfig */ protected $config; - public function __construct(IConfig $config, IAppManager $appManager, IDBConnection $connection) { + public function __construct(IConfig $config, IAppManager $appManager, Connection $connection) { parent::__construct($connection, $appManager); $this->config = $config; } diff --git a/core/Command/Db/Migrations/MigrateCommand.php b/core/Command/Db/Migrations/MigrateCommand.php index 229288c794..218c8aaf51 100644 --- a/core/Command/Db/Migrations/MigrateCommand.php +++ b/core/Command/Db/Migrations/MigrateCommand.php @@ -22,9 +22,9 @@ namespace OC\Core\Command\Db\Migrations; +use OC\DB\Connection; use OC\DB\MigrationService; use OC\Migration\ConsoleOutput; -use OCP\IDBConnection; use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; use Symfony\Component\Console\Command\Command; @@ -34,13 +34,13 @@ use Symfony\Component\Console\Output\OutputInterface; class MigrateCommand extends Command implements CompletionAwareInterface { - /** @var IDBConnection */ + /** @var Connection */ private $connection; /** - * @param IDBConnection $connection + * @param Connection $connection */ - public function __construct(IDBConnection $connection) { + public function __construct(Connection $connection) { $this->connection = $connection; parent::__construct(); } diff --git a/core/Command/Db/Migrations/StatusCommand.php b/core/Command/Db/Migrations/StatusCommand.php index 83763ee79b..6c78bcd180 100644 --- a/core/Command/Db/Migrations/StatusCommand.php +++ b/core/Command/Db/Migrations/StatusCommand.php @@ -24,9 +24,9 @@ namespace OC\Core\Command\Db\Migrations; +use OC\DB\Connection; use OC\DB\MigrationService; use OC\Migration\ConsoleOutput; -use OCP\IDBConnection; use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; use Symfony\Component\Console\Command\Command; @@ -36,13 +36,10 @@ use Symfony\Component\Console\Output\OutputInterface; class StatusCommand extends Command implements CompletionAwareInterface { - /** @var IDBConnection */ + /** @var Connection */ private $connection; - /** - * @param IDBConnection $connection - */ - public function __construct(IDBConnection $connection) { + public function __construct(Connection $connection) { $this->connection = $connection; parent::__construct(); } diff --git a/core/Migrations/Version16000Date20190427105638.php b/core/Migrations/Version16000Date20190427105638.php index cf48108d9e..a2a58c7449 100644 --- a/core/Migrations/Version16000Date20190427105638.php +++ b/core/Migrations/Version16000Date20190427105638.php @@ -60,7 +60,6 @@ class Version16000Date20190427105638 extends SimpleMigrationStep { * @param array $options * @return null|ISchemaWrapper * @throws \Doctrine\DBAL\Schema\SchemaException - * @throws \Doctrine\DBAL\DBALException */ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { /** @var ISchemaWrapper $schema */ diff --git a/core/Migrations/Version20000Date20201109081918.php b/core/Migrations/Version20000Date20201109081918.php index 71c433a213..c5a19d0cbf 100644 --- a/core/Migrations/Version20000Date20201109081918.php +++ b/core/Migrations/Version20000Date20201109081918.php @@ -28,7 +28,7 @@ declare(strict_types=1); namespace OC\Core\Migrations; use Closure; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use OCP\DB\ISchemaWrapper; use OCP\IDBConnection; use OCP\Migration\IOutput; @@ -55,20 +55,20 @@ class Version20000Date20201109081918 extends SimpleMigrationStep { if (!$schema->hasTable('storages_credentials')) { $table = $schema->createTable('storages_credentials'); - $table->addColumn('id', Type::BIGINT, [ + $table->addColumn('id', Types::BIGINT, [ 'autoincrement' => true, 'notnull' => true, 'length' => 64, ]); - $table->addColumn('user', Type::STRING, [ + $table->addColumn('user', Types::STRING, [ 'notnull' => false, 'length' => 64, ]); - $table->addColumn('identifier', Type::STRING, [ + $table->addColumn('identifier', Types::STRING, [ 'notnull' => true, 'length' => 64, ]); - $table->addColumn('credentials', Type::TEXT, [ + $table->addColumn('credentials', Types::TEXT, [ 'notnull' => false, ]); $table->setPrimaryKey(['id']); diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index 9d3f1ddc50..c483454cb9 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -513,6 +513,7 @@ OC.SetupChecks.addGenericSetupCheck(data, 'OCA\\Settings\\SetupChecks\\PhpOutputBuffering', messages) OC.SetupChecks.addGenericSetupCheck(data, 'OCA\\Settings\\SetupChecks\\LegacySSEKeyFormat', messages) OC.SetupChecks.addGenericSetupCheck(data, 'OCA\\Settings\\SetupChecks\\CheckUserCertificates', messages) + OC.SetupChecks.addGenericSetupCheck(data, 'OCA\\Settings\\SetupChecks\\SupportedDatabase', messages) } else { messages.push({ diff --git a/core/register_command.php b/core/register_command.php index fe998020d2..605c545554 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -100,15 +100,15 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()))); $application->add(new OC\Core\Command\Db\ConvertMysqlToMB4(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection(), \OC::$server->getURLGenerator(), \OC::$server->getLogger())); - $application->add(new OC\Core\Command\Db\ConvertFilecacheBigInt(\OC::$server->getDatabaseConnection())); - $application->add(new OC\Core\Command\Db\AddMissingIndices(\OC::$server->getDatabaseConnection(), \OC::$server->getEventDispatcher())); - $application->add(new OC\Core\Command\Db\AddMissingColumns(\OC::$server->getDatabaseConnection(), \OC::$server->getEventDispatcher())); - $application->add(new OC\Core\Command\Db\AddMissingPrimaryKeys(\OC::$server->getDatabaseConnection(), \OC::$server->getEventDispatcher())); - $application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->getDatabaseConnection())); - $application->add(new OC\Core\Command\Db\Migrations\MigrateCommand(\OC::$server->getDatabaseConnection())); - $application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->getDatabaseConnection(), \OC::$server->getAppManager())); - $application->add(new OC\Core\Command\Db\Migrations\GenerateFromSchemaFileCommand(\OC::$server->getConfig(), \OC::$server->getAppManager(), \OC::$server->getDatabaseConnection())); - $application->add(new OC\Core\Command\Db\Migrations\ExecuteCommand(\OC::$server->getDatabaseConnection(), \OC::$server->getAppManager(), \OC::$server->getConfig())); + $application->add(new OC\Core\Command\Db\ConvertFilecacheBigInt(\OC::$server->get(\OC\DB\Connection::class))); + $application->add(new OC\Core\Command\Db\AddMissingIndices(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher())); + $application->add(new OC\Core\Command\Db\AddMissingColumns(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher())); + $application->add(new OC\Core\Command\Db\AddMissingPrimaryKeys(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher())); + $application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->get(\OC\DB\Connection::class))); + $application->add(new OC\Core\Command\Db\Migrations\MigrateCommand(\OC::$server->get(\OC\DB\Connection::class))); + $application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getAppManager())); + $application->add(new OC\Core\Command\Db\Migrations\GenerateFromSchemaFileCommand(\OC::$server->getConfig(), \OC::$server->getAppManager(), \OC::$server->get(\OC\DB\Connection::class))); + $application->add(new OC\Core\Command\Db\Migrations\ExecuteCommand(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getConfig())); $application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig())); $application->add(new OC\Core\Command\Encryption\Enable(\OC::$server->getConfig(), \OC::$server->getEncryptionManager())); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 3a65a05c5a..a69437f1d4 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -161,6 +161,8 @@ return array( 'OCP\\Contacts\\ContactsMenu\\IProvider' => $baseDir . '/lib/public/Contacts/ContactsMenu/IProvider.php', 'OCP\\Contacts\\Events\\ContactInteractedWithEvent' => $baseDir . '/lib/public/Contacts/Events/ContactInteractedWithEvent.php', 'OCP\\Contacts\\IManager' => $baseDir . '/lib/public/Contacts/IManager.php', + 'OCP\\DB\\IPreparedStatement' => $baseDir . '/lib/public/DB/IPreparedStatement.php', + 'OCP\\DB\\IResult' => $baseDir . '/lib/public/DB/IResult.php', 'OCP\\DB\\ISchemaWrapper' => $baseDir . '/lib/public/DB/ISchemaWrapper.php', 'OCP\\DB\\QueryBuilder\\ICompositeExpression' => $baseDir . '/lib/public/DB/QueryBuilder/ICompositeExpression.php', 'OCP\\DB\\QueryBuilder\\IExpressionBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/IExpressionBuilder.php', @@ -948,10 +950,10 @@ return array( 'OC\\DB\\AdapterPgSql' => $baseDir . '/lib/private/DB/AdapterPgSql.php', 'OC\\DB\\AdapterSqlite' => $baseDir . '/lib/private/DB/AdapterSqlite.php', 'OC\\DB\\Connection' => $baseDir . '/lib/private/DB/Connection.php', + 'OC\\DB\\ConnectionAdapter' => $baseDir . '/lib/private/DB/ConnectionAdapter.php', 'OC\\DB\\ConnectionFactory' => $baseDir . '/lib/private/DB/ConnectionFactory.php', 'OC\\DB\\MDB2SchemaManager' => $baseDir . '/lib/private/DB/MDB2SchemaManager.php', 'OC\\DB\\MDB2SchemaReader' => $baseDir . '/lib/private/DB/MDB2SchemaReader.php', - 'OC\\DB\\MDB2SchemaWriter' => $baseDir . '/lib/private/DB/MDB2SchemaWriter.php', 'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php', 'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php', 'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php', @@ -965,6 +967,7 @@ return array( 'OC\\DB\\OracleMigrator' => $baseDir . '/lib/private/DB/OracleMigrator.php', 'OC\\DB\\PgSqlTools' => $baseDir . '/lib/private/DB/PgSqlTools.php', 'OC\\DB\\PostgreSqlMigrator' => $baseDir . '/lib/private/DB/PostgreSqlMigrator.php', + 'OC\\DB\\PreparedStatement' => $baseDir . '/lib/private/DB/PreparedStatement.php', 'OC\\DB\\QueryBuilder\\CompositeExpression' => $baseDir . '/lib/private/DB/QueryBuilder/CompositeExpression.php', 'OC\\DB\\QueryBuilder\\ExpressionBuilder\\ExpressionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php', 'OC\\DB\\QueryBuilder\\ExpressionBuilder\\MySqlExpressionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php', @@ -981,6 +984,7 @@ return array( 'OC\\DB\\QueryBuilder\\QueryFunction' => $baseDir . '/lib/private/DB/QueryBuilder/QueryFunction.php', 'OC\\DB\\QueryBuilder\\QuoteHelper' => $baseDir . '/lib/private/DB/QueryBuilder/QuoteHelper.php', 'OC\\DB\\ReconnectWrapper' => $baseDir . '/lib/private/DB/ReconnectWrapper.php', + 'OC\\DB\\ResultAdapter' => $baseDir . '/lib/private/DB/ResultAdapter.php', 'OC\\DB\\SQLiteMigrator' => $baseDir . '/lib/private/DB/SQLiteMigrator.php', 'OC\\DB\\SQLiteSessionInit' => $baseDir . '/lib/private/DB/SQLiteSessionInit.php', 'OC\\DB\\SchemaWrapper' => $baseDir . '/lib/private/DB/SchemaWrapper.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 521991cff7..4c46c7bc43 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -190,6 +190,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Contacts\\ContactsMenu\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IProvider.php', 'OCP\\Contacts\\Events\\ContactInteractedWithEvent' => __DIR__ . '/../../..' . '/lib/public/Contacts/Events/ContactInteractedWithEvent.php', 'OCP\\Contacts\\IManager' => __DIR__ . '/../../..' . '/lib/public/Contacts/IManager.php', + 'OCP\\DB\\IPreparedStatement' => __DIR__ . '/../../..' . '/lib/public/DB/IPreparedStatement.php', + 'OCP\\DB\\IResult' => __DIR__ . '/../../..' . '/lib/public/DB/IResult.php', 'OCP\\DB\\ISchemaWrapper' => __DIR__ . '/../../..' . '/lib/public/DB/ISchemaWrapper.php', 'OCP\\DB\\QueryBuilder\\ICompositeExpression' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/ICompositeExpression.php', 'OCP\\DB\\QueryBuilder\\IExpressionBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IExpressionBuilder.php', @@ -977,10 +979,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\DB\\AdapterPgSql' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterPgSql.php', 'OC\\DB\\AdapterSqlite' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterSqlite.php', 'OC\\DB\\Connection' => __DIR__ . '/../../..' . '/lib/private/DB/Connection.php', + 'OC\\DB\\ConnectionAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ConnectionAdapter.php', 'OC\\DB\\ConnectionFactory' => __DIR__ . '/../../..' . '/lib/private/DB/ConnectionFactory.php', 'OC\\DB\\MDB2SchemaManager' => __DIR__ . '/../../..' . '/lib/private/DB/MDB2SchemaManager.php', 'OC\\DB\\MDB2SchemaReader' => __DIR__ . '/../../..' . '/lib/private/DB/MDB2SchemaReader.php', - 'OC\\DB\\MDB2SchemaWriter' => __DIR__ . '/../../..' . '/lib/private/DB/MDB2SchemaWriter.php', 'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php', 'OC\\DB\\MigrationService' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationService.php', 'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php', @@ -994,6 +996,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\DB\\OracleMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/OracleMigrator.php', 'OC\\DB\\PgSqlTools' => __DIR__ . '/../../..' . '/lib/private/DB/PgSqlTools.php', 'OC\\DB\\PostgreSqlMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/PostgreSqlMigrator.php', + 'OC\\DB\\PreparedStatement' => __DIR__ . '/../../..' . '/lib/private/DB/PreparedStatement.php', 'OC\\DB\\QueryBuilder\\CompositeExpression' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/CompositeExpression.php', 'OC\\DB\\QueryBuilder\\ExpressionBuilder\\ExpressionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php', 'OC\\DB\\QueryBuilder\\ExpressionBuilder\\MySqlExpressionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php', @@ -1010,6 +1013,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\DB\\QueryBuilder\\QueryFunction' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/QueryFunction.php', 'OC\\DB\\QueryBuilder\\QuoteHelper' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/QuoteHelper.php', 'OC\\DB\\ReconnectWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/ReconnectWrapper.php', + 'OC\\DB\\ResultAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ResultAdapter.php', 'OC\\DB\\SQLiteMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteMigrator.php', 'OC\\DB\\SQLiteSessionInit' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteSessionInit.php', 'OC\\DB\\SchemaWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/SchemaWrapper.php', diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php index 84305e60a1..6a0dc2fab2 100644 --- a/lib/private/AppConfig.php +++ b/lib/private/AppConfig.php @@ -33,10 +33,10 @@ namespace OC; +use OC\DB\Connection; use OC\DB\OracleConnection; use OCP\IAppConfig; use OCP\IConfig; -use OCP\IDBConnection; /** * This class provides an easy way for apps to store config values in the @@ -68,7 +68,7 @@ class AppConfig implements IAppConfig { ], ]; - /** @var \OCP\IDBConnection */ + /** @var Connection */ protected $conn; /** @var array[] */ @@ -78,11 +78,10 @@ class AppConfig implements IAppConfig { private $configLoaded = false; /** - * @param IDBConnection $conn + * @param Connection $conn */ - public function __construct(IDBConnection $conn) { + public function __construct(Connection $conn) { $this->conn = $conn; - $this->configLoaded = false; } /** diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php index 47e6650c99..828864f1e0 100644 --- a/lib/private/AppFramework/Http/Dispatcher.php +++ b/lib/private/AppFramework/Http/Dispatcher.php @@ -36,12 +36,11 @@ namespace OC\AppFramework\Http; use OC\AppFramework\Http; use OC\AppFramework\Middleware\MiddlewareDispatcher; use OC\AppFramework\Utility\ControllerMethodReflector; -use OC\DB\Connection; +use OC\DB\ConnectionAdapter; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\Response; use OCP\IConfig; -use OCP\IDBConnection; use OCP\IRequest; use Psr\Log\LoggerInterface; @@ -65,7 +64,7 @@ class Dispatcher { /** @var IConfig */ private $config; - /** @var IDBConnection|Connection */ + /** @var ConnectionAdapter */ private $connection; /** @var LoggerInterface */ @@ -79,7 +78,7 @@ class Dispatcher { * the arguments for the controller * @param IRequest $request the incoming request * @param IConfig $config - * @param IDBConnection $connection + * @param ConnectionAdapter $connection * @param LoggerInterface $logger */ public function __construct(Http $protocol, @@ -87,7 +86,7 @@ class Dispatcher { ControllerMethodReflector $reflector, IRequest $request, IConfig $config, - IDBConnection $connection, + ConnectionAdapter $connection, LoggerInterface $logger) { $this->protocol = $protocol; $this->middlewareDispatcher = $middlewareDispatcher; @@ -122,13 +121,13 @@ class Dispatcher { $databaseStatsBefore = []; if ($this->config->getSystemValueBool('debug', false)) { - $databaseStatsBefore = $this->connection->getStats(); + $databaseStatsBefore = $this->connection->getInner()->getStats(); } $response = $this->executeController($controller, $methodName); if (!empty($databaseStatsBefore)) { - $databaseStatsAfter = $this->connection->getStats(); + $databaseStatsAfter = $this->connection->getInner()->getStats(); $numBuilt = $databaseStatsAfter['built'] - $databaseStatsBefore['built']; $numExecuted = $databaseStatsAfter['executed'] - $databaseStatsBefore['executed']; diff --git a/lib/private/DB/Adapter.php b/lib/private/DB/Adapter.php index 26fd018dec..49b831301b 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 77f0b6b772..0d8794d59a 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 5731ee1721..a62960bae1 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 b024989ac0..c67c6df082 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -1,4 +1,7 @@ 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 0000000000..97a0b60044 --- /dev/null +++ b/lib/private/DB/ConnectionAdapter.php @@ -0,0 +1,172 @@ + + * + * @author 2020 Christoph Wurst + * + * @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 . + */ + +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 44ea398621..18549eb1fa 100644 --- a/lib/private/DB/MDB2SchemaManager.php +++ b/lib/private/DB/MDB2SchemaManager.php @@ -31,35 +31,23 @@ 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 @@ -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 2c1f6a5e54..0000000000 --- a/lib/private/DB/MDB2SchemaWriter.php +++ /dev/null @@ -1,181 +0,0 @@ - - * @author Christoph Wurst - * @author Jörn Friedrich Dreyer - * @author Morris Jobke - * @author tbelau666 - * @author Thomas Müller - * - * @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 - * - */ - -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(''); - $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 6a1cb4be01..4470791109 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 569b1a6c28..f62735ea6b 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 { @@ -101,34 +103,6 @@ class Migrator { return $script; } - /** - * @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 * @@ -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 007388d561..e738a2bd94 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 cad5390f09..7a327a4279 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 724344ac2a..d555bfb391 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 0000000000..f679576a42 --- /dev/null +++ b/lib/private/DB/PreparedStatement.php @@ -0,0 +1,101 @@ + + * + * @author 2021 Christoph Wurst + * + * @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 . + */ + +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 61eea80640..d4c1a9db88 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 ExpressionBuilder. * - * @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 899f927743..3e4119bb11 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 2d5fe6ce57..657e52e54b 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) { - return new PgSqlExpressionBuilder($this->connection, $this); - } elseif ($this->connection->getDatabasePlatform() instanceof MySqlPlatform) { - return new MySqlExpressionBuilder($this->connection, $this); - } elseif ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { - return new SqliteExpressionBuilder($this->connection, $this); - } else { - return new ExpressionBuilder($this->connection, $this); } + if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) { + return new PgSqlExpressionBuilder($this->connection, $this); + } + if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) { + return new MySqlExpressionBuilder($this->connection, $this); + } + if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { + return new SqliteExpressionBuilder($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) { - return new SqliteFunctionBuilder($this->helper); - } elseif ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) { - return new PgSqlFunctionBuilder($this->helper); - } else { - return new FunctionBuilder($this->helper); } + if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) { + return new SqliteFunctionBuilder($this->helper); + } + if ($this->connection->getDatabasePlatform() instanceof PostgreSQL94Platform) { + return new PgSqlFunctionBuilder($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 9599d6b0fe..a017015286 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 0000000000..176de5b45e --- /dev/null +++ b/lib/private/DB/ResultAdapter.php @@ -0,0 +1,71 @@ + + * + * @author 2021 Christoph Wurst + * + * @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 . + */ + +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 16f18be135..24b6c02b31 100644 --- a/lib/private/DB/SQLiteMigrator.php +++ b/lib/private/DB/SQLiteMigrator.php @@ -26,49 +26,12 @@ namespace OC\DB; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Types\BigIntType; 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 diff --git a/lib/private/DB/SQLiteSessionInit.php b/lib/private/DB/SQLiteSessionInit.php index 0c53a0587f..924a3b2758 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 440008d35b..20ae5b6faa 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(); } diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index dbe0dd9d77..2513abd525 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -39,8 +39,8 @@ namespace OC\Files\Cache; -use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; +use OCP\DB\IResult; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\CacheEntryInsertedEvent; @@ -486,7 +486,7 @@ class Cache implements ICache { ->wherePath($file); $result = $query->execute(); - $id = $result->fetchColumn(); + $id = $result->fetchOne(); $result->closeCursor(); return $id === false ? -1 : (int)$id; @@ -746,7 +746,7 @@ class Cache implements ICache { ->wherePath($file); $result = $query->execute(); - $size = $result->fetchColumn(); + $size = $result->fetchOne(); $result->closeCursor(); if ($size !== false) { @@ -793,10 +793,10 @@ class Cache implements ICache { } /** - * @param Statement $result + * @param IResult $result * @return CacheEntry[] */ - private function searchResultToCacheEntries(Statement $result) { + private function searchResultToCacheEntries(IResult $result): array { $files = $result->fetchAll(); return array_map(function (array $data) { @@ -870,7 +870,9 @@ class Cache implements ICache { } $result = $query->execute(); - return $this->searchResultToCacheEntries($result); + $cacheEntries = $this->searchResultToCacheEntries($result); + $result->closeCursor(); + return $cacheEntries; } /** @@ -912,7 +914,7 @@ class Cache implements ICache { ->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))); $result = $query->execute(); - $size = (int)$result->fetchColumn(); + $size = (int)$result->fetchOne(); $result->closeCursor(); return $size; @@ -1002,7 +1004,7 @@ class Cache implements ICache { ->setMaxResults(1); $result = $query->execute(); - $path = $result->fetchColumn(); + $path = $result->fetchOne(); $result->closeCursor(); return $path; @@ -1022,7 +1024,7 @@ class Cache implements ICache { ->whereFileId($id); $result = $query->execute(); - $path = $result->fetchColumn(); + $path = $result->fetchOne(); $result->closeCursor(); if ($path === false) { diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 26264321a9..0dbc34fae2 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -36,6 +36,7 @@ namespace OC\Files\Cache; +use Doctrine\DBAL\Exception; use OC\Files\Filesystem; use OC\Hooks\BasicEmitter; use OCP\Files\Cache\IScanner; @@ -437,7 +438,7 @@ class Scanner extends BasicEmitter implements IScanner { $size += $data['size']; } } - } catch (\Doctrine\DBAL\DBALException $ex) { + } catch (Exception $ex) { // might happen if inserting duplicate while a scanning // process is running in parallel // log and ignore diff --git a/lib/private/Group/Database.php b/lib/private/Group/Database.php index 97094c6772..c49f3bce59 100644 --- a/lib/private/Group/Database.php +++ b/lib/private/Group/Database.php @@ -410,7 +410,7 @@ class Database extends ABackend implements } $result = $query->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $result->closeCursor(); if ($count !== false) { @@ -442,7 +442,7 @@ class Database extends ABackend implements ->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR)); $result = $query->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $result->closeCursor(); if ($count !== false) { @@ -467,7 +467,7 @@ class Database extends ABackend implements ->where($query->expr()->eq('gid', $query->createNamedParameter($gid))); $result = $query->execute(); - $displayName = $result->fetchColumn(); + $displayName = $result->fetchOne(); $result->closeCursor(); return (string) $displayName; diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 0b020aed56..e0eb8e9de1 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -45,6 +45,7 @@ use OC\App\AppStore\Bundles\Bundle; use OC\App\AppStore\Fetcher\AppFetcher; use OC\AppFramework\Bootstrap\Coordinator; use OC\Archive\TAR; +use OC\DB\Connection; use OC_App; use OC_DB; use OC_Helper; @@ -158,7 +159,7 @@ class Installer { OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml'); } } else { - $ms = new \OC\DB\MigrationService($info['id'], \OC::$server->getDatabaseConnection()); + $ms = new \OC\DB\MigrationService($info['id'], \OC::$server->get(Connection::class)); $ms->migrate('latest', true); } if ($previousVersion) { @@ -593,7 +594,7 @@ class Installer { ); } } else { - $ms = new \OC\DB\MigrationService($app, \OC::$server->getDatabaseConnection()); + $ms = new \OC\DB\MigrationService($app, \OC::$server->get(Connection::class)); $ms->migrate('latest', true); } diff --git a/lib/private/Lock/DBLockingProvider.php b/lib/private/Lock/DBLockingProvider.php index c6b9cf6378..30566c7b25 100644 --- a/lib/private/Lock/DBLockingProvider.php +++ b/lib/private/Lock/DBLockingProvider.php @@ -159,7 +159,7 @@ class DBLockingProvider extends AbstractLockingProvider { } $query = $this->connection->prepare('SELECT `lock` from `*PREFIX*file_locks` WHERE `key` = ?'); $query->execute([$path]); - $lockValue = (int)$query->fetchColumn(); + $lockValue = (int)$query->fetchOne(); if ($type === self::LOCK_SHARED) { if ($this->isLocallyLocked($path)) { // if we have a shared lock we kept open locally but it's released we always have at least 1 shared lock in the db diff --git a/lib/private/Repair.php b/lib/private/Repair.php index 80a8a8a87c..e4f75b43fd 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -36,6 +36,8 @@ namespace OC; use OC\App\AppStore\Bundles\BundleFetcher; use OC\Avatar\AvatarManager; +use OC\DB\Connection; +use OC\DB\ConnectionAdapter; use OC\Repair\AddBruteForceCleanupJob; use OC\Repair\AddCleanupUpdaterBackupsJob; use OC\Repair\CleanTags; @@ -210,13 +212,16 @@ class Repair implements IOutput { * @return IRepairStep[] */ public static function getBeforeUpgradeRepairSteps() { - $connection = \OC::$server->getDatabaseConnection(); + /** @var Connection $connection */ + $connection = \OC::$server->get(Connection::class); + /** @var ConnectionAdapter $connectionAdapter */ + $connectionAdapter = \OC::$server->get(ConnectionAdapter::class); $config = \OC::$server->getConfig(); $steps = [ - new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connection, true), + new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connectionAdapter, true), new SqliteAutoincrement($connection), - new SaveAccountsTableData($connection, $config), - new DropAccountTermsTable($connection) + new SaveAccountsTableData($connectionAdapter, $config), + new DropAccountTermsTable($connectionAdapter) ]; return $steps; diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php index fb0e019269..d2974c1680 100644 --- a/lib/private/Repair/Collation.php +++ b/lib/private/Repair/Collation.php @@ -28,7 +28,7 @@ namespace OC\Repair; use Doctrine\DBAL\Exception\DriverException; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use OCP\IConfig; use OCP\IDBConnection; use OCP\ILogger; @@ -69,7 +69,7 @@ class Collation implements IRepairStep { * Fix mime types */ public function run(IOutput $output) { - if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) { + if (!$this->connection->getDatabasePlatform() instanceof MySQLPlatform) { $output->info('Not a mysql database -> nothing to do'); return; } diff --git a/lib/private/Repair/RemoveLinkShares.php b/lib/private/Repair/RemoveLinkShares.php index 3a0dd6f288..32cbd1f73f 100644 --- a/lib/private/Repair/RemoveLinkShares.php +++ b/lib/private/Repair/RemoveLinkShares.php @@ -30,8 +30,8 @@ declare(strict_types=1); namespace OC\Repair; -use Doctrine\DBAL\Driver\Statement; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\DB\IResult; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; use OCP\IDBConnection; @@ -138,10 +138,8 @@ class RemoveLinkShares implements IRepairStep { /** * Get the cursor to fetch all the shares - * - * @return \Doctrine\DBAL\Driver\Statement */ - private function getShares(): Statement { + private function getShares(): IResult { $subQuery = $this->connection->getQueryBuilder(); $subQuery->select('*') ->from('share') @@ -160,7 +158,9 @@ class RemoveLinkShares implements IRepairStep { $query->expr()->eq('s2.share_type', $query->expr()->literal(2, IQueryBuilder::PARAM_INT)) )) ->andWhere($query->expr()->eq('s1.item_source', 's2.item_source')); - return $query->execute(); + /** @var IResult $result */ + $result = $query->execute(); + return $result; } /** @@ -210,13 +210,13 @@ class RemoveLinkShares implements IRepairStep { private function repair(IOutput $output, int $total): void { $output->startProgress($total); - $shareCursor = $this->getShares(); - while ($data = $shareCursor->fetch()) { + $shareResult = $this->getShares(); + while ($data = $shareResult->fetch()) { $this->processShare($data); $output->advance(); } $output->finishProgress(); - $shareCursor->closeCursor(); + $shareResult->closeCursor(); // Notifiy all admins $adminGroup = $this->groupManager->get('admin'); diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php index 3e6fa51b19..d0e3bbff70 100644 --- a/lib/private/Repair/RepairMimeTypes.php +++ b/lib/private/Repair/RepairMimeTypes.php @@ -71,7 +71,7 @@ class RepairMimeTypes implements IRepairStep { if (empty($this->folderMimeTypeId)) { $query->setParameter('mimetype', 'httpd/unix-directory'); $result = $query->execute(); - $this->folderMimeTypeId = (int)$result->fetchColumn(); + $this->folderMimeTypeId = (int)$result->fetchOne(); $result->closeCursor(); } @@ -88,7 +88,7 @@ class RepairMimeTypes implements IRepairStep { // get target mimetype id $query->setParameter('mimetype', $mimetype); $result = $query->execute(); - $mimetypeId = (int)$result->fetchColumn(); + $mimetypeId = (int)$result->fetchOne(); $result->closeCursor(); if (!$mimetypeId) { @@ -242,7 +242,7 @@ class RepairMimeTypes implements IRepairStep { if (version_compare($ocVersionFromBeforeUpdate, '20.0.0.5', '<') && $this->introduceOpenDocumentTemplates()) { $out->info('Fixed OpenDocument template mime types'); } - + if (version_compare($ocVersionFromBeforeUpdate, '21.0.0.7', '<') && $this->introduceOrgModeType()) { $out->info('Fixed orgmode mime types'); } diff --git a/lib/private/Server.php b/lib/private/Server.php index 687eba68e7..680eea3bec 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -77,6 +77,8 @@ use OC\Comments\ManagerFactory as CommentsManagerFactory; use OC\Contacts\ContactsMenu\ActionFactory; use OC\Contacts\ContactsMenu\ContactsStore; use OC\Dashboard\DashboardManager; +use OC\DB\Connection; +use OC\DB\ConnectionAdapter; use OC\Diagnostics\EventLogger; use OC\Diagnostics\QueryLogger; use OC\EventDispatcher\SymfonyAdapter; @@ -792,7 +794,8 @@ class Server extends ServerContainer implements IServerContainer { /** @deprecated 19.0.0 */ $this->registerDeprecatedAlias('CredentialsManager', ICredentialsManager::class); - $this->registerService(IDBConnection::class, function (Server $c) { + $this->registerAlias(IDBConnection::class, ConnectionAdapter::class); + $this->registerService(Connection::class, function (Server $c) { $systemConfig = $c->get(SystemConfig::class); $factory = new \OC\DB\ConnectionFactory($systemConfig); $type = $systemConfig->getValue('dbtype', 'sqlite'); diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 8a9aed09f1..e0761db307 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -29,6 +29,7 @@ namespace OC\Setup; +use OC\DB\Connection; use OC\DB\ConnectionFactory; use OC\DB\MigrationService; use OC\SystemConfig; @@ -108,7 +109,7 @@ abstract class AbstractDatabase { * @param array $configOverwrite * @return \OC\DB\Connection */ - protected function connect(array $configOverwrite = []) { + protected function connect(array $configOverwrite = []): Connection { $connectionParams = [ 'host' => $this->dbHost, 'user' => $this->dbUser, @@ -149,7 +150,7 @@ abstract class AbstractDatabase { if (!is_dir(\OC::$SERVERROOT."/core/Migrations")) { return; } - $ms = new MigrationService('core', \OC::$server->getDatabaseConnection()); + $ms = new MigrationService('core', \OC::$server->get(Connection::class)); $ms->migrate('latest', true); } } diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php index 966c97edf5..21339dc46d 100644 --- a/lib/private/Setup/MySQL.php +++ b/lib/private/Setup/MySQL.php @@ -31,6 +31,7 @@ namespace OC\Setup; +use OC\DB\ConnectionAdapter; use OC\DB\MySqlTools; use OCP\IDBConnection; use OCP\ILogger; @@ -45,12 +46,12 @@ class MySQL extends AbstractDatabase { // detect mb4 $tools = new MySqlTools(); - if ($tools->supports4ByteCharset($connection)) { + if ($tools->supports4ByteCharset(new ConnectionAdapter($connection))) { $this->config->setValue('mysql.utf8mb4', true); $connection = $this->connect(['dbname' => null]); } - $this->createSpecificUser($username, $connection); + $this->createSpecificUser($username, new ConnectionAdapter($connection)); //create the database $this->createDatabase($connection); @@ -156,27 +157,24 @@ class MySQL extends AbstractDatabase { $result = $connection->executeQuery($query, [$adminUser]); //current dbuser has admin rights - if ($result) { - $data = $result->fetchAll(); - //new dbuser does not exist - if (count($data) === 0) { - //use the admin login data for the new database user - $this->dbUser = $adminUser; + $data = $result->fetchAll(); + $result->closeCursor(); + //new dbuser does not exist + if (count($data) === 0) { + //use the admin login data for the new database user + $this->dbUser = $adminUser; - //create a random password so we don't need to store the admin password in the config file - $this->dbPassword = $this->random->generate(30); + //create a random password so we don't need to store the admin password in the config file + $this->dbPassword = $this->random->generate(30); - $this->createDBUser($connection); + $this->createDBUser($connection); - break; - } else { - //repeat with different username - $length = strlen((string)$i); - $adminUser = substr('oc_' . $username, 0, 16 - $length) . $i; - $i++; - } - } else { break; + } else { + //repeat with different username + $length = strlen((string)$i); + $adminUser = substr('oc_' . $username, 0, 16 - $length) . $i; + $i++; } } } diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php index 1f0b7b8f89..7e59bf297f 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -30,8 +30,8 @@ namespace OC\Setup; use OC\DatabaseException; +use OC\DB\Connection; use OC\DB\QueryBuilder\Literal; -use OCP\IDBConnection; class PostgreSQL extends AbstractDatabase { public $dbprettyname = 'PostgreSQL'; @@ -103,7 +103,7 @@ class PostgreSQL extends AbstractDatabase { } } - private function createDatabase(IDBConnection $connection) { + private function createDatabase(Connection $connection) { if (!$this->databaseExists($connection)) { //The database does not exists... let's create it $query = $connection->prepare("CREATE DATABASE " . addslashes($this->dbName) . " OWNER " . addslashes($this->dbUser)); @@ -124,7 +124,7 @@ class PostgreSQL extends AbstractDatabase { } } - private function userExists(IDBConnection $connection) { + private function userExists(Connection $connection) { $builder = $connection->getQueryBuilder(); $builder->automaticTablePrefix(false); $query = $builder->select('*') @@ -134,7 +134,7 @@ class PostgreSQL extends AbstractDatabase { return $result->rowCount() > 0; } - private function databaseExists(IDBConnection $connection) { + private function databaseExists(Connection $connection) { $builder = $connection->getQueryBuilder(); $builder->automaticTablePrefix(false); $query = $builder->select('datname') @@ -144,7 +144,7 @@ class PostgreSQL extends AbstractDatabase { return $result->rowCount() > 0; } - private function createDBUser(IDBConnection $connection) { + private function createDBUser(Connection $connection) { $dbUser = $this->dbUser; try { $i = 1; diff --git a/lib/private/Tags.php b/lib/private/Tags.php index 720e9dd5d7..8e32f3925e 100644 --- a/lib/private/Tags.php +++ b/lib/private/Tags.php @@ -230,10 +230,6 @@ class Tags implements ITags { } $entries[$objId][] = $row['category']; } - if ($result === null) { - \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR); - return false; - } } } catch (\Exception $e) { \OC::$server->getLogger()->logException($e, [ diff --git a/lib/private/Updater.php b/lib/private/Updater.php index ec0a50cc6c..09aa955283 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -37,6 +37,7 @@ namespace OC; +use OC\DB\Connection; use OC\DB\MigrationService; use OC\Hooks\BasicEmitter; use OC\IntegrityCheck\Checker; @@ -298,7 +299,7 @@ class Updater extends BasicEmitter { $this->emit('\OC\Updater', 'dbUpgradeBefore'); // execute core migrations - $ms = new MigrationService('core', \OC::$server->getDatabaseConnection()); + $ms = new MigrationService('core', \OC::$server->get(Connection::class)); $ms->migrate(); $this->emit('\OC\Updater', 'dbUpgrade'); diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 7c936acd0b..85e22d196e 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -436,7 +436,7 @@ class Database extends ABackend implements ->from($this->table); $result = $query->execute(); - return $result->fetchColumn(); + return $result->fetchOne(); } /** diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 1d58c68268..39e3a37254 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -491,7 +491,7 @@ class Manager extends PublicEmitter implements IUserManager { $result = $queryBuilder->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $result->closeCursor(); if ($count !== false) { @@ -521,7 +521,7 @@ class Manager extends PublicEmitter implements IUserManager { ->andWhere($queryBuilder->expr()->in('gid', $queryBuilder->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY))); $result = $queryBuilder->execute(); - $count = $result->fetchColumn(); + $count = $result->fetchOne(); $result->closeCursor(); if ($count !== false) { @@ -549,7 +549,7 @@ class Manager extends PublicEmitter implements IUserManager { $query = $queryBuilder->execute(); - $result = (int)$query->fetchColumn(); + $result = (int)$query->fetchOne(); $query->closeCursor(); return $result; diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php index 32d2569d0a..a64b13f1e2 100644 --- a/lib/private/legacy/OC_App.php +++ b/lib/private/legacy/OC_App.php @@ -989,7 +989,7 @@ class OC_App { if (file_exists($appPath . '/appinfo/database.xml')) { OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml'); } else { - $ms = new MigrationService($appId, \OC::$server->getDatabaseConnection()); + $ms = new MigrationService($appId, \OC::$server->get(\OC\DB\Connection::class)); $ms->migrate(); } diff --git a/lib/private/legacy/OC_DB.php b/lib/private/legacy/OC_DB.php index 11cd1f4cae..b5b6c73704 100644 --- a/lib/private/legacy/OC_DB.php +++ b/lib/private/legacy/OC_DB.php @@ -44,7 +44,7 @@ class OC_DB { * @return \OC\DB\MDB2SchemaManager */ private static function getMDB2SchemaManager() { - return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection()); + return new \OC\DB\MDB2SchemaManager(\OC::$server->get(\OC\DB\Connection::class)); } /** @@ -70,7 +70,7 @@ class OC_DB { // return the result try { $result = $connection->prepare($query, $limit, $offset); - } catch (\Doctrine\DBAL\DBALException $e) { + } catch (\Doctrine\DBAL\Exception $e) { throw new \OC\DatabaseException($e->getMessage()); } // differentiate between query and manipulation @@ -159,18 +159,6 @@ class OC_DB { return $result; } - /** - * saves database schema to xml file - * @param string $file name of file - * @return bool - * - * TODO: write more documentation - */ - public static function getDbStructure($file) { - $schemaManager = self::getMDB2SchemaManager(); - return $schemaManager->getDbStructure($file); - } - /** * Creates tables from XML file * @param string $file file to read structure from @@ -211,7 +199,7 @@ class OC_DB { } /** - * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException + * check if a result is an error and throws an exception, works with \Doctrine\DBAL\Exception * @param mixed $result * @param string $message * @return void diff --git a/lib/private/legacy/OC_DB_StatementWrapper.php b/lib/private/legacy/OC_DB_StatementWrapper.php index 667c2de967..cc2320015a 100644 --- a/lib/private/legacy/OC_DB_StatementWrapper.php +++ b/lib/private/legacy/OC_DB_StatementWrapper.php @@ -28,6 +28,8 @@ * */ +use OCP\DB\IPreparedStatement; + /** * small wrapper around \Doctrine\DBAL\Driver\Statement to make it behave, more like an MDB2 Statement * @@ -38,17 +40,20 @@ * @method array fetchAll(integer $fetchMode = null); */ class OC_DB_StatementWrapper { - /** - * @var \Doctrine\DBAL\Driver\Statement - */ + /** @var IPreparedStatement */ private $statement = null; + + /** @var bool */ private $isManipulation = false; + + /** @var array */ private $lastArguments = []; /** + * @param IPreparedStatement $statement * @param boolean $isManipulation */ - public function __construct($statement, $isManipulation) { + public function __construct(IPreparedStatement $statement, $isManipulation) { $this->statement = $statement; $this->isManipulation = $isManipulation; } @@ -63,31 +68,34 @@ class OC_DB_StatementWrapper { /** * make execute return the result instead of a bool * - * @param array $input + * @param mixed[] $input * @return \OC_DB_StatementWrapper|int|bool + * @deprecated */ public function execute($input = []) { $this->lastArguments = $input; - if (count($input) > 0) { - $result = $this->statement->execute($input); - } else { - $result = $this->statement->execute(); - } - - if ($result === false) { + try { + if (count($input) > 0) { + $result = $this->statement->execute($input); + } else { + $result = $this->statement->execute(); + } + } catch (\Doctrine\DBAL\Exception $e) { return false; } + if ($this->isManipulation) { return $this->statement->rowCount(); - } else { - return $this; } + + return $this; } /** * provide an alias for fetch * * @return mixed + * @deprecated */ public function fetchRow() { return $this->statement->fetch(); @@ -97,11 +105,11 @@ class OC_DB_StatementWrapper { * Provide a simple fetchOne. * * fetch single column from the next row - * @param int $column the column number to fetch * @return string + * @deprecated */ - public function fetchOne($column = 0) { - return $this->statement->fetchColumn($column); + public function fetchOne() { + return $this->statement->fetchOne(); } /** diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 4176dfbb22..d5805719ea 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -993,7 +993,7 @@ class OC_Util { ]; } } - } catch (\Doctrine\DBAL\DBALException $e) { + } catch (\Doctrine\DBAL\Exception $e) { $logger = \OC::$server->getLogger(); $logger->warning('Error occurred while checking PostgreSQL version, assuming >= 9'); $logger->logException($e); diff --git a/lib/public/DB/IPreparedStatement.php b/lib/public/DB/IPreparedStatement.php new file mode 100644 index 0000000000..6b6617ba5e --- /dev/null +++ b/lib/public/DB/IPreparedStatement.php @@ -0,0 +1,127 @@ + + * + * @author 2021 Christoph Wurst + * + * @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 . + */ + +namespace OCP\DB; + +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\ParameterType; +use PDO; + +/** + * @since 21.0.0 + */ +interface IPreparedStatement { + + /** + * @return true + * + * @since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\IResult::closeCursor on the \OCP\DB\IResult returned by \OCP\IDBConnection::prepare + */ + public function closeCursor(): bool; + + /** + * @param int $fetchMode + * + * @return mixed + * + * @since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\IResult::fetch on the \OCP\DB\IResult returned by \OCP\IDBConnection::prepare + */ + public function fetch(int $fetchMode = PDO::FETCH_ASSOC); + + /** + * @param int $fetchMode + * + * @return mixed[] + * + * @since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\IResult::fetchAll on the \OCP\DB\IResult returned by \OCP\IDBConnection::prepare + */ + public function fetchAll(int $fetchMode = PDO::FETCH_ASSOC); + + /** + * @return mixed + * + * @since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\IResult::fetchColumn on the \OCP\DB\IResult returned by \OCP\IDBConnection::prepare + */ + public function fetchColumn(); + + /** + * @return mixed + * + * @since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\IResult::fetchOne on the \OCP\DB\IResult returned by \OCP\IDBConnection::prepare + */ + public function fetchOne(); + + /** + * @param int|string $param + * @param mixed $value + * @param int $type + * + * @return bool + * + * @throws Exception + * + * @since 21.0.0 + */ + public function bindValue($param, $value, $type = ParameterType::STRING): bool; + + /** + * @param int|string $param + * @param mixed $variable + * @param int $type + * @param int|null $length + * + * @return bool + * + * @throws Exception + * + * @since 21.0.0 + */ + public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool; + + /** + * @param mixed[]|null $params + * + * @return IResult + * + * @since 21.0.0 + * @throws Exception + */ + public function execute($params = null): IResult; + + /** + * @return int + * + * @since 21.0.0 + * + * @throws Exception + * @deprecated 21.0.0 use \OCP\DB\IResult::rowCount on the \OCP\DB\IResult returned by \OCP\IDBConnection::prepare + */ + public function rowCount(): int; +} diff --git a/lib/public/DB/IResult.php b/lib/public/DB/IResult.php new file mode 100644 index 0000000000..10c788ebbf --- /dev/null +++ b/lib/public/DB/IResult.php @@ -0,0 +1,83 @@ + + * + * @author 2021 Christoph Wurst + * + * @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 . + */ + +namespace OCP\DB; + +use PDO; + +/** + * @since 21.0.0 + */ +interface IResult { + + /** + * @return true + * + * @since 21.0.0 + */ + public function closeCursor(): bool; + + /** + * @param int $fetchMode + * + * @return mixed + * + * @since 21.0.0 + */ + public function fetch(int $fetchMode = PDO::FETCH_ASSOC); + + /** + * @param int $fetchMode (one of PDO::FETCH_ASSOC, PDO::FETCH_NUM or PDO::FETCH_COLUMN (2, 3 or 7) + * + * @return mixed[] + * + * @since 21.0.0 + */ + public function fetchAll(int $fetchMode = PDO::FETCH_ASSOC): array; + + /** + * @return mixed + * + * @since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\IResult::fetchOne + */ + public function fetchColumn(); + + /** + * @param int $columnIndex + * + * @return false|mixed + * + * @since 21.0.0 + */ + public function fetchOne(); + + /** + * @return int + * + * @since 21.0.0 + */ + public function rowCount(): int; +} diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php index b4255f9583..8fcbd6c327 100644 --- a/lib/public/DB/QueryBuilder/IQueryBuilder.php +++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php @@ -29,6 +29,7 @@ namespace OCP\DB\QueryBuilder; use Doctrine\DBAL\Connection; +use OCP\DB\IResult; /** * This class provides a wrapper around Doctrine's QueryBuilder @@ -148,7 +149,11 @@ interface IQueryBuilder { * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} * for insert, update and delete statements. * - * @return \Doctrine\DBAL\Driver\Statement|int + * Warning: until Nextcloud 20, this method could return a \Doctrine\DBAL\Driver\Statement but since + * that interface changed in a breaking way the adapter \OCP\DB\QueryBuilder\IStatement is returned + * to bridge old code to the new API + * + * @return IResult|int * @since 8.2.0 */ public function execute(); diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index 11fa301ab8..16a5f998fd 100644 --- a/lib/public/IDBConnection.php +++ b/lib/public/IDBConnection.php @@ -39,7 +39,10 @@ namespace OCP; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Schema\Schema; +use OCP\DB\IPreparedStatement; +use OCP\DB\IResult; use OCP\DB\QueryBuilder\IQueryBuilder; /** @@ -68,10 +71,11 @@ interface IDBConnection { * @param string $sql the sql query with ? placeholder for params * @param int $limit the maximum number of rows * @param int $offset from which row we want to start - * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + * @return IPreparedStatement The prepared statement. * @since 6.0.0 + * @throws Exception since 21.0.0 */ - public function prepare($sql, $limit = null, $offset = null); + public function prepare($sql, $limit = null, $offset = null): IPreparedStatement; /** * Executes an, optionally parameterized, SQL query. @@ -82,10 +86,11 @@ interface IDBConnection { * @param string $sql The SQL query to execute. * @param string[] $params The parameters to bind to the query, if any. * @param array $types The types the previous parameters are in. - * @return \Doctrine\DBAL\Driver\Statement The executed statement. + * @return IResult The executed statement. * @since 8.0.0 + * @throws Exception since 21.0.0 */ - public function executeQuery($sql, array $params = [], $types = []); + public function executeQuery(string $sql, array $params = [], $types = []): IResult; /** * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters @@ -96,12 +101,12 @@ interface IDBConnection { * @param string $sql The SQL query. * @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. * @since 8.0.0 * * @deprecated 21.0.0 use executeStatement */ - public function executeUpdate($sql, array $params = [], array $types = []); + public function executeUpdate(string $sql, array $params = [], array $types = []): int; /** * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters @@ -112,18 +117,20 @@ interface IDBConnection { * @param string $sql The SQL query. * @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. * @since 21.0.0 */ - public function executeStatement($sql, array $params = [], array $types = []); + public function executeStatement($sql, array $params = [], array $types = []): int; /** * Used to get the id of the just inserted element * @param string $table the name of the table where we inserted the item * @return int the id of the inserted element * @since 6.0.0 + * @throws Exception since 21.0.0 + * @deprecated 21.0.0 use \OCP\DB\QueryBuilder\IQueryBuilder::getLastInsertId */ - public function lastInsertId($table = null); + public function lastInsertId(string $table): int; /** * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance @@ -136,11 +143,11 @@ interface 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 Exception * @since 6.0.0 - parameter $compare was added in 8.1.0, return type changed from boolean in 8.1.0 * @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); + public function insertIfNotExist(string $table, array $input, array $compare = null); /** @@ -164,11 +171,11 @@ interface 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 Exception * @throws PreconditionNotMetException * @since 9.0.0 */ - public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []); + public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []): int; /** * Create an exclusive read+write lock on a table @@ -180,20 +187,21 @@ interface IDBConnection { * @param string $tableName * @since 9.1.0 */ - public function lockTable($tableName); + public function lockTable($tableName): void; /** * Release a previous acquired lock again * * @since 9.1.0 */ - public function unlockTable(); + public function unlockTable(): void; /** * Start a transaction * @since 6.0.0 + * @throws Exception since 21.0.0 */ - public function beginTransaction(); + public function beginTransaction(): void; /** * Check if a transaction is active @@ -201,32 +209,36 @@ interface IDBConnection { * @return bool * @since 8.2.0 */ - public function inTransaction(); + public function inTransaction(): bool; /** * Commit the database changes done during a transaction that is in progress * @since 6.0.0 + * @throws Exception since 21.0.0 */ - public function commit(); + public function commit(): void; /** * Rollback the database changes done during a transaction that is in progress * @since 6.0.0 + * @throws Exception since 21.0.0 */ - public function rollBack(); + public function rollBack(): void; /** * Gets the error code and message as a string for logging * @return string * @since 6.0.0 + * @deprecated 21.0.0 doesn't return anything meaningful */ - public function getError(); + public function getError(): string; /** * Fetch the SQLSTATE associated with the last database operation. * * @return integer The last error code. * @since 8.0.0 + * @deprecated 21.0.0 doesn't return anything anymore */ public function errorCode(); @@ -235,6 +247,7 @@ interface IDBConnection { * * @return array The last error information. * @since 8.0.0 + * @deprecated 21.0.0 doesn't return anything anymore */ public function errorInfo(); @@ -244,20 +257,20 @@ interface IDBConnection { * @return bool * @since 8.0.0 */ - public function connect(); + public function connect(): bool; /** * Close the database connection * @since 8.0.0 */ - public function close(); + public function close(): void; /** * Quotes a given input parameter. * * @param mixed $input Parameter to be quoted. * @param int $type Type of the parameter. - * @return string The quoted parameter. + * @return mixed The quoted parameter. * @since 8.0.0 */ public function quote($input, $type = IQueryBuilder::PARAM_STR); @@ -277,7 +290,7 @@ interface IDBConnection { * @param string $table table name without the prefix * @since 8.0.0 */ - public function dropTable($table); + public function dropTable(string $table): void; /** * Check if a table exists @@ -286,7 +299,7 @@ interface IDBConnection { * @return bool * @since 8.0.0 */ - public function tableExists($table); + public function tableExists(string $table): bool; /** * Escape a parameter to be used in a LIKE query @@ -295,7 +308,7 @@ interface IDBConnection { * @return string * @since 9.0.0 */ - public function escapeLikeParameter($param); + public function escapeLikeParameter(string $param): string; /** * Check whether or not the current database support 4byte wide unicode @@ -303,7 +316,7 @@ interface IDBConnection { * @return bool * @since 11.0.0 */ - public function supports4ByteText(); + public function supports4ByteText(): bool; /** * Create the schema of the connected database @@ -311,7 +324,7 @@ interface IDBConnection { * @return Schema * @since 13.0.0 */ - public function createSchema(); + public function createSchema(): Schema; /** * Migrate the database to the given schema @@ -319,5 +332,5 @@ interface IDBConnection { * @param Schema $toSchema * @since 13.0.0 */ - public function migrateToSchema(Schema $toSchema); + public function migrateToSchema(Schema $toSchema): void; } diff --git a/tests/lib/AppConfigTest.php b/tests/lib/AppConfigTest.php index d2643d599f..d4ae66cb2f 100644 --- a/tests/lib/AppConfigTest.php +++ b/tests/lib/AppConfigTest.php @@ -10,6 +10,7 @@ namespace Test; use OC\AppConfig; +use OC\DB\Connection; use OCP\IConfig; /** @@ -23,7 +24,7 @@ class AppConfigTest extends TestCase { /** @var \OCP\IAppConfig */ protected $appConfig; - /** @var \OCP\IDBConnection */ + /** @var Connection */ protected $connection; protected $originalConfig; @@ -31,7 +32,7 @@ class AppConfigTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(Connection::class); $sql = $this->connection->getQueryBuilder(); $sql->select('*') ->from('appconfig'); @@ -138,7 +139,7 @@ class AppConfigTest extends TestCase { } public function testGetApps() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertEqualsCanonicalizing([ 'anotherapp', @@ -149,7 +150,7 @@ class AppConfigTest extends TestCase { } public function testGetKeys() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $keys = $config->getKeys('testapp'); $this->assertEqualsCanonicalizing([ @@ -162,7 +163,7 @@ class AppConfigTest extends TestCase { } public function testGetValue() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $value = $config->getValue('testapp', 'installed_version'); $this->assertConfigKey('testapp', 'installed_version', $value); @@ -175,7 +176,7 @@ class AppConfigTest extends TestCase { } public function testHasKey() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertTrue($config->hasKey('testapp', 'installed_version')); $this->assertFalse($config->hasKey('testapp', 'nonexistant')); @@ -183,13 +184,13 @@ class AppConfigTest extends TestCase { } public function testSetValueUpdate() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertEquals('1.2.3', $config->getValue('testapp', 'installed_version')); $this->assertConfigKey('testapp', 'installed_version', '1.2.3'); $wasModified = $config->setValue('testapp', 'installed_version', '1.2.3'); - if (!(\OC::$server->getDatabaseConnection() instanceof \OC\DB\OracleConnection)) { + if (!(\OC::$server->get(Connection::class) instanceof \OC\DB\OracleConnection)) { $this->assertFalse($wasModified); } @@ -207,7 +208,7 @@ class AppConfigTest extends TestCase { } public function testSetValueInsert() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertFalse($config->hasKey('someapp', 'somekey')); $this->assertNull($config->getValue('someapp', 'somekey')); @@ -219,13 +220,13 @@ class AppConfigTest extends TestCase { $this->assertConfigKey('someapp', 'somekey', 'somevalue'); $wasInserted = $config->setValue('someapp', 'somekey', 'somevalue'); - if (!(\OC::$server->getDatabaseConnection() instanceof \OC\DB\OracleConnection)) { + if (!(\OC::$server->get(Connection::class) instanceof \OC\DB\OracleConnection)) { $this->assertFalse($wasInserted); } } public function testDeleteKey() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertTrue($config->hasKey('testapp', 'deletethis')); @@ -247,7 +248,7 @@ class AppConfigTest extends TestCase { } public function testDeleteApp() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertTrue($config->hasKey('someapp', 'otherkey')); @@ -267,7 +268,7 @@ class AppConfigTest extends TestCase { } public function testGetValuesNotAllowed() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $this->assertFalse($config->getValues('testapp', 'enabled')); @@ -275,7 +276,7 @@ class AppConfigTest extends TestCase { } public function testGetValues() { - $config = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $config = new \OC\AppConfig(\OC::$server->get(Connection::class)); $sql = \OC::$server->getDatabaseConnection()->getQueryBuilder(); $sql->select(['configkey', 'configvalue']) @@ -311,7 +312,7 @@ class AppConfigTest extends TestCase { public function testGetFilteredValues() { /** @var \OC\AppConfig|\PHPUnit\Framework\MockObject\MockObject $config */ $config = $this->getMockBuilder(\OC\AppConfig::class) - ->setConstructorArgs([\OC::$server->getDatabaseConnection()]) + ->setConstructorArgs([\OC::$server->get(Connection::class)]) ->setMethods(['getValues']) ->getMock(); @@ -333,8 +334,8 @@ class AppConfigTest extends TestCase { } public function testSettingConfigParallel() { - $appConfig1 = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); - $appConfig2 = new \OC\AppConfig(\OC::$server->getDatabaseConnection()); + $appConfig1 = new \OC\AppConfig(\OC::$server->get(Connection::class)); + $appConfig2 = new \OC\AppConfig(\OC::$server->get(Connection::class)); $appConfig1->getValue('testapp', 'foo', 'v1'); $appConfig2->getValue('testapp', 'foo', 'v1'); diff --git a/tests/lib/AppFramework/Db/MapperTestUtility.php b/tests/lib/AppFramework/Db/MapperTestUtility.php index b25ff9f3e1..e17b875e4c 100644 --- a/tests/lib/AppFramework/Db/MapperTestUtility.php +++ b/tests/lib/AppFramework/Db/MapperTestUtility.php @@ -23,12 +23,15 @@ namespace Test\AppFramework\Db; +use OCP\DB\IPreparedStatement; +use OCP\DB\IResult; + /** * Simple utility class for testing mappers */ abstract class MapperTestUtility extends \Test\TestCase { protected $db; - private $query; + private $statement; private $queryAt; private $prepareAt; private $fetchAt; @@ -47,7 +50,7 @@ abstract class MapperTestUtility extends \Test\TestCase { ->disableOriginalConstructor() ->getMock(); - $this->query = $this->createMock('\PDOStatement'); + $this->statement = $this->createMock(IPreparedStatement::class); $this->queryAt = 0; $this->prepareAt = 0; $this->iterators = []; @@ -94,26 +97,26 @@ abstract class MapperTestUtility extends \Test\TestCase { $this->db->expects($this->at($this->prepareAt)) ->method('prepare') ->with($this->equalTo($sql)) - ->will(($this->returnValue($this->query))); + ->will(($this->returnValue($this->statement))); } elseif ($limit !== null && $offset === null) { $this->db->expects($this->at($this->prepareAt)) ->method('prepare') ->with($this->equalTo($sql), $this->equalTo($limit)) - ->will(($this->returnValue($this->query))); + ->will(($this->returnValue($this->statement))); } elseif ($limit === null && $offset !== null) { $this->db->expects($this->at($this->prepareAt)) ->method('prepare') ->with($this->equalTo($sql), $this->equalTo(null), $this->equalTo($offset)) - ->will(($this->returnValue($this->query))); + ->will(($this->returnValue($this->statement))); } else { $this->db->expects($this->at($this->prepareAt)) ->method('prepare') ->with($this->equalTo($sql), $this->equalTo($limit), $this->equalTo($offset)) - ->will(($this->returnValue($this->query))); + ->will(($this->returnValue($this->statement))); } $this->iterators[] = new ArgumentIterator($returnRows); @@ -121,7 +124,7 @@ abstract class MapperTestUtility extends \Test\TestCase { $iterators = $this->iterators; $fetchAt = $this->fetchAt; - $this->query->expects($this->any()) + $this->statement->expects($this->any()) ->method('fetch') ->willReturnCallback( function () use ($iterators, $fetchAt) { @@ -141,7 +144,7 @@ abstract class MapperTestUtility extends \Test\TestCase { if ($this->isAssocArray($arguments)) { foreach ($arguments as $key => $argument) { $pdoConstant = $this->getPDOType($argument); - $this->query->expects($this->at($this->queryAt)) + $this->statement->expects($this->at($this->queryAt)) ->method('bindValue') ->with($this->equalTo($key), $this->equalTo($argument), @@ -152,7 +155,7 @@ abstract class MapperTestUtility extends \Test\TestCase { $index = 1; foreach ($arguments as $argument) { $pdoConstant = $this->getPDOType($argument); - $this->query->expects($this->at($this->queryAt)) + $this->statement->expects($this->at($this->queryAt)) ->method('bindValue') ->with($this->equalTo($index), $this->equalTo($argument), @@ -162,9 +165,10 @@ abstract class MapperTestUtility extends \Test\TestCase { } } - $this->query->expects($this->at($this->queryAt)) + $this->statement->expects($this->at($this->queryAt)) ->method('execute') ->willReturnCallback(function ($sql, $p = null, $o = null, $s = null) { + return $this->createMock(IResult::class); }); $this->queryAt++; @@ -175,7 +179,7 @@ abstract class MapperTestUtility extends \Test\TestCase { } else { $closing = $this->any(); } - $this->query->expects($closing)->method('closeCursor'); + $this->statement->expects($closing)->method('closeCursor'); $this->queryAt++; $this->prepareAt++; diff --git a/tests/lib/DB/ConnectionTest.php b/tests/lib/DB/ConnectionTest.php index cab6133c3c..d628d9814e 100644 --- a/tests/lib/DB/ConnectionTest.php +++ b/tests/lib/DB/ConnectionTest.php @@ -44,7 +44,7 @@ class ConnectionTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(\OC\DB\Connection::class); } protected function tearDown(): void { @@ -234,7 +234,7 @@ class ConnectionTest extends \Test\TestCase { $query = $this->connection->prepare('SELECT * FROM `*PREFIX*table`'); $result = $query->execute(); $this->assertTrue((bool)$result); - $this->assertEquals(7, count($query->fetchAll())); + $this->assertEquals(7, count($result->fetchAll())); } public function testInsertIfNotExistNull() { @@ -263,7 +263,7 @@ class ConnectionTest extends \Test\TestCase { $query = $this->connection->prepare('SELECT * FROM `*PREFIX*table`'); $result = $query->execute(); $this->assertTrue((bool)$result); - $this->assertEquals(2, count($query->fetchAll())); + $this->assertEquals(2, count($result->fetchAll())); } public function testInsertIfNotExistDonTOverwrite() { @@ -278,11 +278,10 @@ class ConnectionTest extends \Test\TestCase { // Normal test to have same known data inserted. $query = $this->connection->prepare('INSERT INTO `*PREFIX*table` (`textfield`, `clobfield`) VALUES (?, ?)'); $result = $query->execute([$fullName, $uri]); - $this->assertEquals(1, $result); + $this->assertEquals(1, $result->rowCount()); $query = $this->connection->prepare('SELECT `textfield`, `clobfield` FROM `*PREFIX*table` WHERE `clobfield` = ?'); $result = $query->execute([$uri]); - $this->assertTrue($result); - $rowset = $query->fetchAll(); + $rowset = $result->fetchAll(); $this->assertEquals(1, count($rowset)); $this->assertArrayHasKey('textfield', $rowset[0]); $this->assertEquals($fullName, $rowset[0]['textfield']); @@ -297,10 +296,9 @@ class ConnectionTest extends \Test\TestCase { $query = $this->connection->prepare('SELECT `textfield`, `clobfield` FROM `*PREFIX*table` WHERE `clobfield` = ?'); $result = $query->execute([$uri]); - $this->assertTrue($result); // Test that previously inserted data isn't overwritten // And that a new row hasn't been inserted. - $rowset = $query->fetchAll(); + $rowset = $result->fetchAll(); $this->assertEquals(1, count($rowset)); $this->assertArrayHasKey('textfield', $rowset[0]); $this->assertEquals($fullName, $rowset[0]['textfield']); diff --git a/tests/lib/DB/DBSchemaTest.php b/tests/lib/DB/DBSchemaTest.php index 9f575a75da..4f24c3f67a 100644 --- a/tests/lib/DB/DBSchemaTest.php +++ b/tests/lib/DB/DBSchemaTest.php @@ -64,7 +64,6 @@ class DBSchemaTest extends TestCase { public function testSchema() { $this->doTestSchemaCreating(); $this->doTestSchemaChanging(); - $this->doTestSchemaDumping(); $this->doTestSchemaRemoving(); } @@ -79,14 +78,6 @@ class DBSchemaTest extends TestCase { $this->assertTableExist($this->table2); } - public function doTestSchemaDumping() { - $outfile = $this->tempManager->getTemporaryFile(); - OC_DB::getDbStructure($outfile); - $content = file_get_contents($outfile); - $this->assertStringContainsString($this->table1, $content); - $this->assertStringContainsString($this->table2, $content); - } - public function doTestSchemaRemoving() { OC_DB::removeDBStructure($this->schema_file); $this->assertTableNotExist($this->table1); diff --git a/tests/lib/DB/MDB2SchemaManagerTest.php b/tests/lib/DB/MDB2SchemaManagerTest.php index 18af971650..693de746b5 100644 --- a/tests/lib/DB/MDB2SchemaManagerTest.php +++ b/tests/lib/DB/MDB2SchemaManagerTest.php @@ -30,7 +30,7 @@ class MDB2SchemaManagerTest extends \Test\TestCase { } public function testAutoIncrement() { - $connection = \OC::$server->getDatabaseConnection(); + $connection = \OC::$server->get(\OC\DB\Connection::class); if ($connection->getDatabasePlatform() instanceof OraclePlatform) { $this->markTestSkipped('Adding auto increment columns in Oracle is not supported.'); } diff --git a/tests/lib/DB/MDB2SchemaReaderTest.php b/tests/lib/DB/MDB2SchemaReaderTest.php index b3dd98fd6b..1e7d3a20b7 100644 --- a/tests/lib/DB/MDB2SchemaReaderTest.php +++ b/tests/lib/DB/MDB2SchemaReaderTest.php @@ -9,7 +9,7 @@ namespace Test\DB; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Schema\Schema; use OC\DB\MDB2SchemaReader; use OCP\IConfig; @@ -50,7 +50,7 @@ class MDB2SchemaReaderTest extends TestCase { } public function testRead() { - $reader = new MDB2SchemaReader($this->getConfig(), new MySqlPlatform()); + $reader = new MDB2SchemaReader($this->getConfig(), new MySQLPlatform()); $schema = $reader->loadSchemaFromFile(__DIR__ . '/testschema.xml', new Schema()); $this->assertCount(1, $schema->getTables()); diff --git a/tests/lib/DB/MigratorTest.php b/tests/lib/DB/MigratorTest.php index 52b0b0ff03..539eb404bb 100644 --- a/tests/lib/DB/MigratorTest.php +++ b/tests/lib/DB/MigratorTest.php @@ -9,7 +9,7 @@ namespace Test\DB; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\SchemaConfig; @@ -49,7 +49,7 @@ class MigratorTest extends \Test\TestCase { parent::setUp(); $this->config = \OC::$server->getConfig(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(\OC\DB\Connection::class); if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { $this->markTestSkipped('DB migration tests are not supported on OCI'); } @@ -66,12 +66,12 @@ class MigratorTest extends \Test\TestCase { // Try to delete if exists (IF EXISTS NOT SUPPORTED IN ORACLE) try { $this->connection->exec('DROP TABLE ' . $this->connection->quoteIdentifier($this->tableNameTmp)); - } catch (\Doctrine\DBAL\DBALException $e) { + } catch (Exception $e) { } try { $this->connection->exec('DROP TABLE ' . $this->connection->quoteIdentifier($this->tableName)); - } catch (\Doctrine\DBAL\DBALException $e) { + } catch (Exception $e) { } parent::tearDown(); } @@ -125,9 +125,9 @@ class MigratorTest extends \Test\TestCase { return $this->connection->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver; } - + public function testDuplicateKeyUpgrade() { - $this->expectException(\OC\DB\MigrationException::class); + $this->expectException(Exception\UniqueConstraintViolationException::class); if ($this->isSQLite()) { $this->markTestSkipped('sqlite does not throw errors when creating a new key on existing data'); @@ -140,8 +140,12 @@ class MigratorTest extends \Test\TestCase { $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'bar']); $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'qwerty']); - $migrator->checkMigrate($endSchema); - $this->fail('checkMigrate should have failed'); + try { + $migrator->migrate($endSchema); + } catch (Exception\UniqueConstraintViolationException $e) { + $this->connection->rollBack(); + throw $e; + } } public function testChangeToString() { @@ -156,7 +160,6 @@ class MigratorTest extends \Test\TestCase { $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'bar']); $this->connection->insert($this->tableName, ['id' => 3, 'name' => 'qwerty']); - $migrator->checkMigrate($endSchema); $migrator->migrate($endSchema); $this->addToAssertionCount(1); @@ -181,7 +184,6 @@ class MigratorTest extends \Test\TestCase { $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'bar']); $this->connection->insert($this->tableName, ['id' => 3, 'name' => 'qwerty']); - $migrator->checkMigrate($endSchema); $migrator->migrate($endSchema); $this->addToAssertionCount(1); } @@ -200,7 +202,6 @@ class MigratorTest extends \Test\TestCase { $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'bar']); $this->connection->insert($this->tableName, ['id' => 3, 'name' => 'qwerty']); - $migrator->checkMigrate($endSchema); $migrator->migrate($endSchema); $this->addToAssertionCount(1); @@ -219,7 +220,7 @@ class MigratorTest extends \Test\TestCase { try { $this->connection->insert($this->tableName, ['id' => 2, 'name' => 'qwerty']); $this->fail('Expected duplicate key insert to fail'); - } catch (DBALException $e) { + } catch (Exception $e) { $this->addToAssertionCount(1); } } @@ -239,7 +240,6 @@ class MigratorTest extends \Test\TestCase { $migrator = $this->manager->getMigrator(); $migrator->migrate($startSchema); - $migrator->checkMigrate($endSchema); $migrator->migrate($endSchema); $this->addToAssertionCount(1); @@ -261,7 +261,6 @@ class MigratorTest extends \Test\TestCase { $migrator = $this->manager->getMigrator(); $migrator->migrate($startSchema); - $migrator->checkMigrate($endSchema); $migrator->migrate($endSchema); $this->addToAssertionCount(1); diff --git a/tests/lib/DB/MySqlMigrationTest.php b/tests/lib/DB/MySqlMigrationTest.php index 36ab8ef731..38cb64916e 100644 --- a/tests/lib/DB/MySqlMigrationTest.php +++ b/tests/lib/DB/MySqlMigrationTest.php @@ -24,7 +24,7 @@ class MySqlMigrationTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(\OC\DB\Connection::class); if (!$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MySqlPlatform) { $this->markTestSkipped("Test only relevant on MySql"); } diff --git a/tests/lib/DB/OCPostgreSqlPlatformTest.php b/tests/lib/DB/OCPostgreSqlPlatformTest.php index 62a2fc3471..334a2ecc77 100644 --- a/tests/lib/DB/OCPostgreSqlPlatformTest.php +++ b/tests/lib/DB/OCPostgreSqlPlatformTest.php @@ -21,7 +21,7 @@ namespace Test\DB; -use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Platforms\PostgreSQL100Platform; use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Types\Types; @@ -38,7 +38,7 @@ use Doctrine\DBAL\Types\Types; */ class OCPostgreSqlPlatformTest extends \Test\TestCase { public function testAlterBigint() { - $platform = new PostgreSqlPlatform(); + $platform = new PostgreSQL100Platform(); $sourceSchema = new Schema(); $targetSchema = new Schema(); diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php index 8fd86a638f..d7f6b4ac11 100644 --- a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php +++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php @@ -68,7 +68,7 @@ class ExpressionBuilderDBTest extends TestCase { ->where($query->expr()->like($query->createNamedParameter($param1), $query->createNamedParameter($param2))); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals($match, $column); } @@ -105,7 +105,7 @@ class ExpressionBuilderDBTest extends TestCase { ->where($query->expr()->iLike($query->createNamedParameter($param1), $query->createNamedParameter($param2))); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals($match, $column); } diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php index b3e9124e7d..2a3a4e9a9c 100644 --- a/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php +++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php @@ -40,19 +40,23 @@ class ExpressionBuilderTest extends TestCase { /** @var DoctrineExpressionBuilder */ protected $doctrineExpressionBuilder; - /** @var \Doctrine\DBAL\Connection|\OCP\IDBConnection */ + /** @var \OCP\IDBConnection */ protected $connection; + /** @var \Doctrine\DBAL\Connection */ + protected $internalConnection; + protected function setUp(): void { parent::setUp(); $this->connection = \OC::$server->getDatabaseConnection(); + $this->internalConnection = \OC::$server->get(\OC\DB\Connection::class); $queryBuilder = $this->createMock(IQueryBuilder::class); $this->expressionBuilder = new ExpressionBuilder($this->connection, $queryBuilder); - $this->doctrineExpressionBuilder = new DoctrineExpressionBuilder($this->connection); + $this->doctrineExpressionBuilder = new DoctrineExpressionBuilder($this->internalConnection); } public function dataComparison() { diff --git a/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php b/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php index fad991bfa9..71ae3d5c7f 100644 --- a/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php +++ b/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php @@ -49,7 +49,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals('foobar', $column); } @@ -62,7 +62,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(md5('foobar'), $column); } @@ -75,7 +75,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals('oo', $column); } @@ -88,7 +88,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals('oobar', $column); } @@ -101,7 +101,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals('foobar', $column); } @@ -114,7 +114,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(3, $column); } @@ -127,7 +127,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(1, $column); } @@ -140,7 +140,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $column = $result->fetchColumn(); + $column = $result->fetchOne(); $result->closeCursor(); $this->assertGreaterThan(1, $column); } @@ -176,7 +176,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $row = $result->fetchColumn(); + $row = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(null, $row); } @@ -192,7 +192,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $row = $result->fetchColumn(); + $row = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(null, $row); } @@ -211,7 +211,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $row = $result->fetchColumn(); + $row = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(20, $row); } @@ -230,7 +230,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $row = $result->fetchColumn(); + $row = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(10, $row); } @@ -243,7 +243,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $row = $result->fetchColumn(); + $row = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(2, $row); } @@ -256,7 +256,7 @@ class FunctionBuilderTest extends TestCase { ->setMaxResults(1); $result = $query->execute(); - $row = $result->fetchColumn(); + $row = $result->fetchOne(); $result->closeCursor(); $this->assertEquals(1, $row); } diff --git a/tests/lib/DB/SchemaDiffTest.php b/tests/lib/DB/SchemaDiffTest.php index 6394fa41b8..0e5612e3b3 100644 --- a/tests/lib/DB/SchemaDiffTest.php +++ b/tests/lib/DB/SchemaDiffTest.php @@ -26,6 +26,7 @@ use Doctrine\DBAL\Schema\SchemaDiff; use OC\DB\MDB2SchemaManager; use OC\DB\MDB2SchemaReader; use OCP\IConfig; +use OCP\IDBConnection; use Test\TestCase; /** @@ -36,8 +37,10 @@ use Test\TestCase; * @package Test\DB */ class SchemaDiffTest extends TestCase { - /** @var \Doctrine\DBAL\Connection $connection */ + /** @var IDBConnection $connection */ private $connection; + /** @var \Doctrine\DBAL\Connection $connection */ + private $internalConnection; /** @var MDB2SchemaManager */ private $manager; @@ -57,7 +60,8 @@ class SchemaDiffTest extends TestCase { $this->config = \OC::$server->getConfig(); $this->connection = \OC::$server->getDatabaseConnection(); - $this->manager = new MDB2SchemaManager($this->connection); + $this->internalConnection = \OC::$server->get(\OC\DB\Connection::class); + $this->manager = new MDB2SchemaManager($this->internalConnection); $this->testPrefix = strtolower($this->getUniqueID($this->config->getSystemValue('dbtableprefix', 'oc_'), 3)); } @@ -79,17 +83,17 @@ class SchemaDiffTest extends TestCase { $this->manager->createDbFromStructure($schemaFile); $schemaReader = new MDB2SchemaReader($this->config, $this->connection->getDatabasePlatform()); - $toSchema = new Schema([], [], $this->connection->getSchemaManager()->createSchemaConfig()); + $toSchema = new Schema([], [], $this->internalConnection->getSchemaManager()->createSchemaConfig()); $endSchema = $schemaReader->loadSchemaFromFile($schemaFile, $toSchema); // get the diff /** @var SchemaDiff $diff */ $migrator = $this->manager->getMigrator(); - $diff = $this->invokePrivate($migrator, 'getDiff', [$endSchema, $this->connection]); + $diff = $this->invokePrivate($migrator, 'getDiff', [$endSchema, $this->internalConnection]); // no sql statement is expected $sqls = $diff->toSql($this->connection->getDatabasePlatform()); - $this->assertEquals([], $sqls); + $this->assertEmpty($sqls); } public function providesSchemaFiles() { diff --git a/tests/lib/DB/SqliteMigrationTest.php b/tests/lib/DB/SqliteMigrationTest.php index 480a5ebe74..b0bf39b403 100644 --- a/tests/lib/DB/SqliteMigrationTest.php +++ b/tests/lib/DB/SqliteMigrationTest.php @@ -24,14 +24,14 @@ class SqliteMigrationTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(\OC\DB\Connection::class); if (!$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) { $this->markTestSkipped("Test only relevant on Sqlite"); } $dbPrefix = \OC::$server->getConfig()->getSystemValue("dbtableprefix"); $this->tableName = $this->getUniqueID($dbPrefix . '_enum_bit_test'); - $this->connection->exec("CREATE TABLE $this->tableName(t0 tinyint unsigned, t1 tinyint)"); + $this->connection->prepare("CREATE TABLE $this->tableName(t0 tinyint unsigned, t1 tinyint)")->execute(); } protected function tearDown(): void { diff --git a/tests/lib/Files/Cache/CacheTest.php b/tests/lib/Files/Cache/CacheTest.php index a6d429798e..d74f9cc723 100644 --- a/tests/lib/Files/Cache/CacheTest.php +++ b/tests/lib/Files/Cache/CacheTest.php @@ -116,7 +116,7 @@ class CacheTest extends \Test\TestCase { public function testFolder($folder) { if (strpos($folder, 'F09F9890')) { // 4 byte UTF doesn't work on mysql - $params = \OC::$server->getDatabaseConnection()->getParams(); + $params = \OC::$server->get(\OC\DB\Connection::class)->getParams(); if (\OC::$server->getDatabaseConnection()->getDatabasePlatform() instanceof MySqlPlatform && $params['charset'] !== 'utf8mb4') { $this->markTestSkipped('MySQL doesn\'t support 4 byte UTF-8'); } diff --git a/tests/lib/Files/Config/UserMountCacheTest.php b/tests/lib/Files/Config/UserMountCacheTest.php index 6f347a504c..2bea4f8389 100644 --- a/tests/lib/Files/Config/UserMountCacheTest.php +++ b/tests/lib/Files/Config/UserMountCacheTest.php @@ -337,7 +337,7 @@ class UserMountCacheTest extends TestCase { $sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` =?'; $query = $this->connection->prepare($sql); $query->execute([$storageId, md5($internalPath)]); - return (int)$query->fetchColumn(); + return (int)$query->fetchOne(); } return $id; } diff --git a/tests/lib/Lock/DBLockingProviderTest.php b/tests/lib/Lock/DBLockingProviderTest.php index 3f53589d8f..31abd330fe 100644 --- a/tests/lib/Lock/DBLockingProviderTest.php +++ b/tests/lib/Lock/DBLockingProviderTest.php @@ -94,7 +94,7 @@ class DBLockingProviderTest extends LockingProvider { private function getLockEntryCount() { $query = $this->connection->prepare('SELECT count(*) FROM `*PREFIX*file_locks`'); $query->execute(); - return $query->fetchColumn(); + return $query->fetchOne(); } protected function getLockValue($key) { @@ -104,7 +104,7 @@ class DBLockingProviderTest extends LockingProvider { ->where($query->expr()->eq('key', $query->createNamedParameter($key))); $result = $query->execute(); - $rows = $result->fetchColumn(); + $rows = $result->fetchOne(); $result->closeCursor(); return $rows; diff --git a/tests/lib/Repair/CleanTagsTest.php b/tests/lib/Repair/CleanTagsTest.php index a56d79f9bc..3f3ac0bf18 100644 --- a/tests/lib/Repair/CleanTagsTest.php +++ b/tests/lib/Repair/CleanTagsTest.php @@ -122,7 +122,7 @@ class CleanTagsTest extends \Test\TestCase { ->from($tableName) ->execute(); - $this->assertEquals($expected, $result->fetchColumn(), $message); + $this->assertEquals($expected, $result->fetchOne(), $message); } /** diff --git a/tests/lib/Repair/RepairCollationTest.php b/tests/lib/Repair/RepairCollationTest.php index 9cba3e8e30..35679eb863 100644 --- a/tests/lib/Repair/RepairCollationTest.php +++ b/tests/lib/Repair/RepairCollationTest.php @@ -8,7 +8,6 @@ namespace Test\Repair; -use Doctrine\DBAL\Connection; use Doctrine\DBAL\Platforms\MySqlPlatform; use OC\Repair\Collation; use OCP\IDBConnection; @@ -41,7 +40,7 @@ class RepairCollationTest extends TestCase { private $repair; /** - * @var Connection|IDBConnection + * @var IDBConnection */ private $connection; @@ -61,7 +60,7 @@ class RepairCollationTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(IDBConnection::class); $this->logger = $this->createMock(ILogger::class); $this->config = \OC::$server->getConfig(); if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) { @@ -70,13 +69,13 @@ class RepairCollationTest extends TestCase { $dbPrefix = $this->config->getSystemValue("dbtableprefix"); $this->tableName = $this->getUniqueID($dbPrefix . "_collation_test"); - $this->connection->exec("CREATE TABLE $this->tableName(text VARCHAR(16)) COLLATE utf8_unicode_ci"); + $this->connection->prepare("CREATE TABLE $this->tableName(text VARCHAR(16)) COLLATE utf8_unicode_ci")->execute(); $this->repair = new TestCollationRepair($this->config, $this->logger, $this->connection, false); } protected function tearDown(): void { - $this->connection->getSchemaManager()->dropTable($this->tableName); + $this->connection->getInner()->getSchemaManager()->dropTable($this->tableName); parent::tearDown(); } diff --git a/tests/lib/Repair/RepairSqliteAutoincrementTest.php b/tests/lib/Repair/RepairSqliteAutoincrementTest.php index 9db0d5630a..c03eb12b89 100644 --- a/tests/lib/Repair/RepairSqliteAutoincrementTest.php +++ b/tests/lib/Repair/RepairSqliteAutoincrementTest.php @@ -8,6 +8,7 @@ namespace Test\Repair; +use OC\DB\Connection; use OCP\Migration\IOutput; /** @@ -23,7 +24,7 @@ class RepairSqliteAutoincrementTest extends \Test\TestCase { private $repair; /** - * @var \Doctrine\DBAL\Connection + * @var Connection */ private $connection; @@ -40,7 +41,7 @@ class RepairSqliteAutoincrementTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = \OC::$server->get(\OC\DB\Connection::class); $this->config = \OC::$server->getConfig(); if (!$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) { $this->markTestSkipped("Test only relevant on Sqlite"); @@ -48,7 +49,7 @@ class RepairSqliteAutoincrementTest extends \Test\TestCase { $dbPrefix = $this->config->getSystemValue('dbtableprefix', 'oc_'); $this->tableName = $this->getUniqueID($dbPrefix . 'autoinc_test'); - $this->connection->exec('CREATE TABLE ' . $this->tableName . '("someid" INTEGER NOT NULL, "text" VARCHAR(16), PRIMARY KEY("someid"))'); + $this->connection->prepare('CREATE TABLE ' . $this->tableName . '("someid" INTEGER NOT NULL, "text" VARCHAR(16), PRIMARY KEY("someid"))')->execute(); $this->repair = new \OC\Repair\SqliteAutoincrement($this->connection); } diff --git a/tests/lib/Security/CredentialsManagerTest.php b/tests/lib/Security/CredentialsManagerTest.php index 9c1a0cb929..3ce80227f4 100644 --- a/tests/lib/Security/CredentialsManagerTest.php +++ b/tests/lib/Security/CredentialsManagerTest.php @@ -21,6 +21,7 @@ namespace Test\Security; +use OC\DB\ConnectionAdapter; use OC\Security\CredentialsManager; use OC\SystemConfig; use OCP\IDBConnection; @@ -38,13 +39,19 @@ class CredentialsManagerTest extends \Test\TestCase { /** @var IDBConnection */ protected $dbConnection; + /** @var ConnectionAdapter */ + protected $dbConnectionAdapter; + /** @var CredentialsManager */ protected $manager; protected function setUp(): void { parent::setUp(); $this->crypto = $this->createMock(ICrypto::class); - $this->dbConnection = $this->getMockBuilder('\OC\DB\Connection') + $this->dbConnection = $this->getMockBuilder(IDBConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->dbConnectionAdapter = $this->getMockBuilder(ConnectionAdapter::class) ->disableOriginalConstructor() ->getMock(); $this->manager = new CredentialsManager($this->crypto, $this->dbConnection); @@ -91,9 +98,9 @@ class CredentialsManagerTest extends \Test\TestCase { ->with('baz') ->willReturn(json_encode('bar')); - $qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder') + $qb = $this->getMockBuilder(\OC\DB\QueryBuilder\QueryBuilder::class) ->setConstructorArgs([ - $this->dbConnection, + $this->dbConnectionAdapter, $this->createMock(SystemConfig::class), $this->createMock(ILogger::class), ]) @@ -103,7 +110,7 @@ class CredentialsManagerTest extends \Test\TestCase { ->method('execute') ->willReturn($this->getQueryResult(['credentials' => 'baz'])); - $this->dbConnection->expects($this->once()) + $this->dbConnectionAdapter->expects($this->once()) ->method('getQueryBuilder') ->willReturn($qb); diff --git a/tests/lib/ServerTest.php b/tests/lib/ServerTest.php index 1054c4195b..8df39ca7cc 100644 --- a/tests/lib/ServerTest.php +++ b/tests/lib/ServerTest.php @@ -72,7 +72,7 @@ class ServerTest extends \Test\TestCase { ['CryptoWrapper', '\OC\Session\CryptoWrapper'], ['CsrfTokenManager', '\OC\Security\CSRF\CsrfTokenManager'], - ['DatabaseConnection', '\OC\DB\Connection'], + ['DatabaseConnection', '\OC\DB\ConnectionAdapter'], ['DatabaseConnection', '\OCP\IDBConnection'], ['DateTimeFormatter', '\OC\DateTimeFormatter'], ['DateTimeFormatter', '\OCP\IDateTimeFormatter'],