Migration for database update

This commit is contained in:
Jake Barnby 2023-02-15 20:35:24 +13:00
parent 6012171258
commit d543705a54
No known key found for this signature in database
GPG key ID: C437A8CC85B96E9C
4 changed files with 157 additions and 5 deletions

View file

@ -85,6 +85,7 @@ $cli
try {
$migration
->setProject($project, $projectDB, $consoleDB)
->setPDO($register->get('db'))
->execute();
} catch (\Throwable $th) {
throw $th;

View file

@ -37,6 +37,8 @@ abstract class Migration
*/
protected Database $consoleDB;
protected \PDO $pdo;
/**
* @var array
*/
@ -49,6 +51,7 @@ abstract class Migration
'1.1.1' => 'V16',
'1.1.2' => 'V16',
'1.2.0' => 'V17',
'1.3.0' => 'V18',
];
/**
@ -97,6 +100,13 @@ abstract class Migration
return $this;
}
public function setPDO(\PDO $pdo): self
{
$this->pdo = $pdo;
return $this;
}
/**
* Iterates through every document.
*
@ -330,6 +340,29 @@ abstract class Migration
);
}
/**
* Change a collection attribute's internal type
*
* @param string $collection
* @param string $attribute
* @param string $type
* @return void
*/
protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void
{
$stmt = $this->pdo->prepare('ALTER TABLE :table MODIFY :attribute :type;');
$stmt->bindValue(':table', "{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$collection}`");
$stmt->bindValue(':attribute', $attribute);
$stmt->bindValue(':type', $type);
try {
$stmt->execute();
} catch (\Exception $e) {
Console::warning($e->getMessage());
}
}
/**
* Executes migration for set project.
*/

View file

@ -17,11 +17,6 @@ use Utopia\Database\Helpers\Role;
class V15 extends Migration
{
/**
* @var \PDO $pdo
*/
private $pdo;
/**
* @var array<string>
*/

View file

@ -0,0 +1,123 @@
<?php
namespace Appwrite\Migration\Version;
use Appwrite\Auth\Auth;
use Appwrite\Migration\Migration;
use Appwrite\Query;
use PDO;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\Document;
class V18 extends Migration
{
private \Redis $redis;
public function execute(): void
{
global $register;
$this->redis = $register->get('cache');
/**
* Disable SubQueries for Performance.
*/
foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables'] as $name) {
Database::addFilter(
$name,
fn () => null,
fn () => []
);
}
Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')');
$this->projectDB->setNamespace("_{$this->project->getInternalId()}");
Console::info('Migrating Databases');
$this->migrateDatabases();
Console::info('Migrating Collections');
$this->migrateCollections();
Console::info('Migrating Documents');
$this->forEachDocument([$this, 'migrateDocument']);
Console::info('Migrating Cache');
$this->forEachDocument([$this, 'migrateCache']);
}
/**
* Migrate all Databases.
*
* @return void
* @throws \Exception
*/
private function migrateDatabases(): void
{
foreach ($this->documentsIterator('databases') as $database) {
$databaseTable = "database_{$database->getInternalId()}";
Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})");
foreach ($this->documentsIterator($databaseTable) as $collection) {
$collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}";
$floats = \array_filter($collection->getAttributes(), function ($attribute) {
return $attribute->getAttribute('type') === Database::VAR_FLOAT;
});
foreach ($floats as $attribute) {
$this->changeAttributeInternalType($collectionTable, $attribute->getId(), 'DOUBLE');
}
}
}
}
/**
* Migrate all Collections.
*
* @return void
*/
private function migrateCollections(): void
{
foreach ($this->collections as $collection) {
$id = $collection['$id'];
Console::log("Migrating Collection \"{$id}\"");
$floats = \array_filter($collection, function ($attribute) {
return $attribute['type'] === Database::VAR_FLOAT;
});
foreach ($floats as $attribute) {
$this->changeAttributeInternalType($id, $attribute->getId(), 'DOUBLE');
}
}
}
/**
* Fix run on each document
*
* @param Document $document
* @return Document
*/
private function migrateDocument(Document $document): Document
{
switch ($document->getCollection()) {
case 'projects':
$document->setAttribute('version', '1.3.0');
break;
}
return $document;
}
private function migrateCache(Document $document) {
$key = "cache-_{$this->project->getInternalId()}:_{$document->getCollection()}:{$document->getId()}";
$value = $this->redis->get($key);
if ($value) {
$this->redis->del($key);
$this->redis->set( $key. ':*', $value);
}
}
}