summaryrefslogtreecommitdiffstats
path: root/lib/private/DB
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2017-09-29 11:07:50 +0200
committerJoas Schilling <coding@schilljs.com>2017-09-29 11:10:57 +0200
commita3bdb318e9f552f342de401d0aff24384a80fcd8 (patch)
tree915112882a6f92b736b3cebe3d3840404c72bdd9 /lib/private/DB
parent155d451cf82b0feb1c68f9d83877645c5e8a8112 (diff)
downloadnextcloud-server-a3bdb318e9f552f342de401d0aff24384a80fcd8.tar.gz
nextcloud-server-a3bdb318e9f552f342de401d0aff24384a80fcd8.zip
Fix bigint handling on postgres
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib/private/DB')
-rw-r--r--lib/private/DB/ConnectionFactory.php4
-rw-r--r--lib/private/DB/OCPostgreSqlPlatform.php94
2 files changed, 98 insertions, 0 deletions
diff --git a/lib/private/DB/ConnectionFactory.php b/lib/private/DB/ConnectionFactory.php
index d90d7737d40..8848f6db3b4 100644
--- a/lib/private/DB/ConnectionFactory.php
+++ b/lib/private/DB/ConnectionFactory.php
@@ -137,6 +137,10 @@ class ConnectionFactory {
}
unset($additionalConnectionParams['host']);
break;
+
+ case 'pgsql':
+ $additionalConnectionParams['platform'] = new OCPostgreSqlPlatform();
+ break;
case 'sqlite3':
$journalMode = $additionalConnectionParams['sqlite.journal_mode'];
$additionalConnectionParams['platform'] = new OCSqlitePlatform();
diff --git a/lib/private/DB/OCPostgreSqlPlatform.php b/lib/private/DB/OCPostgreSqlPlatform.php
new file mode 100644
index 00000000000..524a62c2beb
--- /dev/null
+++ b/lib/private/DB/OCPostgreSqlPlatform.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ *
+ * @copyright Copyright (c) 2017, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\DB;
+
+use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
+use Doctrine\DBAL\Schema\ColumnDiff;
+use Doctrine\DBAL\Schema\TableDiff;
+use Doctrine\DBAL\Types\Type;
+
+class OCPostgreSqlPlatform extends PostgreSqlPlatform {
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getAlterTableSQL(TableDiff $diff){
+ $queries = parent::getAlterTableSQL($diff);
+ foreach ($queries as $index => $sql){
+ // BIGSERIAL could not be used in statements altering column type
+ // That's why we replace it with BIGINT
+ // see https://github.com/owncloud/core/pull/28364#issuecomment-315006853
+ if (preg_match('|(ALTER TABLE\s+\S+\s+ALTER\s+\S+\s+TYPE\s+)(BIGSERIAL)|i', $sql, $matches)) {
+ $alterTable = $matches[1];
+ $queries[$index] = $alterTable . 'BIGINT';
+ }
+
+ // Changing integer to bigint kills next autoincrement value
+ // see https://github.com/owncloud/core/pull/28364#issuecomment-315006853
+ if (preg_match('|ALTER TABLE\s+(\S+)\s+ALTER\s+(\S+)\s+DROP DEFAULT|i', $sql, $matches)) {
+ $queryColumnName = $matches[2];
+ $columnDiff = $this->findColumnDiffByName($diff, $queryColumnName);
+ if ($columnDiff && $this->shouldSkipDropDefault($columnDiff)) {
+ unset($queries[$index]);
+ continue;
+ }
+ }
+ }
+
+ return $queries;
+ }
+
+ /**
+ * We should NOT drop next sequence value if
+ * - type was changed from INTEGER to BIGINT
+ * - column keeps an autoincrement
+ * - default value is kept NULL
+ *
+ * @param ColumnDiff $columnDiff
+ * @return bool
+ */
+ private function shouldSkipDropDefault(ColumnDiff $columnDiff) {
+ $column = $columnDiff->column;
+ $fromColumn = $columnDiff->fromColumn;
+ return $fromColumn->getType()->getName() === Type::INTEGER
+ && $column->getType()->getName() === Type::BIGINT
+ && $fromColumn->getDefault() === null
+ && $column->getDefault() === null
+ && $fromColumn->getAutoincrement()
+ && $column->getAutoincrement();
+ }
+
+ /**
+ * @param TableDiff $diff
+ * @param string $name
+ * @return ColumnDiff | false
+ */
+ private function findColumnDiffByName(TableDiff $diff, $name) {
+ foreach ($diff->changedColumns as $columnDiff) {
+ $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this);
+ if ($oldColumnName === $name) {
+ return $columnDiff;
+ }
+ }
+ return false;
+ }
+}