From 99a3e087ed9737e237ad8d93184c9c0c15a10748 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 25 May 2024 09:40:41 +0200 Subject: [PATCH] refactor database schema upgrade to support skipping versions --- lib/Data/Database.php | 149 +++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 76 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 19d7ff8f..2c5e807d 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -853,90 +853,87 @@ class Database extends AbstractData { $dataType = $this->_getDataType(); $attachmentType = $this->_getAttachmentType(); - switch ($oldversion) { - case '0.21': - // create the meta column if necessary (pre 0.21 change) - try { - $this->_db->exec( - 'SELECT "meta" FROM "' . $this->_sanitizeIdentifier('paste') . '" ' . - ($this->_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1') - ); - } catch (PDOException $e) { - $this->_db->exec('ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . '" ADD COLUMN "meta" TEXT'); - } - // SQLite only allows one ALTER statement at a time... + if (version_compare($oldversion, '0.21', '<=')) { + // create the meta column if necessary (pre 0.21 change) + try { + $this->_db->exec( + 'SELECT "meta" FROM "' . $this->_sanitizeIdentifier('paste') . '" ' . + ($this->_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1') + ); + } catch (PDOException $e) { + $this->_db->exec('ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . '" ADD COLUMN "meta" TEXT'); + } + // SQLite only allows one ALTER statement at a time... + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . + "\" ADD COLUMN \"attachment\" $attachmentType" + ); + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType" + ); + // SQLite doesn't support MODIFY, but it allows TEXT of similar + // size as BLOB, so there is no need to change it there + if ($this->_type !== 'sqlite') { $this->_db->exec( 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . - "\" ADD COLUMN \"attachment\" $attachmentType" + "\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType" ); $this->_db->exec( - 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType" + 'ALTER TABLE "' . $this->_sanitizeIdentifier('comment') . + "\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " . + "MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType" ); - // SQLite doesn't support MODIFY, but it allows TEXT of similar - // size as BLOB, so there is no need to change it there - if ($this->_type !== 'sqlite') { - $this->_db->exec( - 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . - "\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType" - ); - $this->_db->exec( - 'ALTER TABLE "' . $this->_sanitizeIdentifier('comment') . - "\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " . - "MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType" - ); - } else { - $this->_db->exec( - 'CREATE UNIQUE INDEX IF NOT EXISTS "' . - $this->_sanitizeIdentifier('paste_dataid') . '" ON "' . - $this->_sanitizeIdentifier('paste') . '" ("dataid")' - ); - $this->_db->exec( - 'CREATE UNIQUE INDEX IF NOT EXISTS "' . - $this->_sanitizeIdentifier('comment_dataid') . '" ON "' . - $this->_sanitizeIdentifier('comment') . '" ("dataid")' - ); - } - // CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0 + } else { $this->_db->exec( - 'CREATE INDEX "' . - $this->_sanitizeIdentifier('comment_parent') . '" ON "' . - $this->_sanitizeIdentifier('comment') . '" ("pasteid")' + 'CREATE UNIQUE INDEX IF NOT EXISTS "' . + $this->_sanitizeIdentifier('paste_dataid') . '" ON "' . + $this->_sanitizeIdentifier('paste') . '" ("dataid")' ); - // no break, continue with updates for 0.22 and later - case '1.3': - // SQLite doesn't support MODIFY, but it allows TEXT of similar - // size as BLOB and PostgreSQL uses TEXT, so there is no need - // to change it there - if ($this->_type !== 'sqlite' && $this->_type !== 'pgsql') { - $this->_db->exec( - 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . - "\" MODIFY COLUMN \"data\" $attachmentType" - ); - } - // no break, continue with updates for all newer versions - case '1.7.2': - $supportsDropColumn = true; - if ($this->_type === 'sqlite') { - try { - $row = $this->_select('SELECT sqlite_version() AS "v"', array(), true); - $supportsDropColumn = version_compare($row['v'], '3.35.0', '>='); - } catch (PDOException $e) { - $supportsDropColumn = false; - } - } - if ($supportsDropColumn) { - $this->_db->exec( - 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . - '" DROP COLUMN "postdate"' - ); - } - // no break, continue with updates for all newer versions - default: - $this->_exec( - 'UPDATE "' . $this->_sanitizeIdentifier('config') . - '" SET "value" = ? WHERE "id" = ?', - array(Controller::VERSION, 'VERSION') + $this->_db->exec( + 'CREATE UNIQUE INDEX IF NOT EXISTS "' . + $this->_sanitizeIdentifier('comment_dataid') . '" ON "' . + $this->_sanitizeIdentifier('comment') . '" ("dataid")' ); + } + // CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0 + $this->_db->exec( + 'CREATE INDEX "' . + $this->_sanitizeIdentifier('comment_parent') . '" ON "' . + $this->_sanitizeIdentifier('comment') . '" ("pasteid")' + ); } + if (version_compare($oldversion, '1.3', '<=')) { + // SQLite doesn't support MODIFY, but it allows TEXT of similar + // size as BLOB and PostgreSQL uses TEXT, so there is no need + // to change it there + if ($this->_type !== 'sqlite' && $this->_type !== 'pgsql') { + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . + "\" MODIFY COLUMN \"data\" $attachmentType" + ); + } + } + if (version_compare($oldversion, '1.7.1', '<=')) { + $supportsDropColumn = true; + if ($this->_type === 'sqlite') { + try { + $row = $this->_select('SELECT sqlite_version() AS "v"', array(), true); + $supportsDropColumn = version_compare($row['v'], '3.35.0', '>='); + } catch (PDOException $e) { + $supportsDropColumn = false; + } + } + if ($supportsDropColumn) { + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . + '" DROP COLUMN "postdate"' + ); + } + } + $this->_exec( + 'UPDATE "' . $this->_sanitizeIdentifier('config') . + '" SET "value" = ? WHERE "id" = ?', + array(Controller::VERSION, 'VERSION') + ); } }