From fb97521fcb1257cc36a6b6ef6f51b7d0a4c29a44 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Tue, 18 Jun 2019 10:54:26 -0100 Subject: fix migration on pgsql Signed-off-by: Maxence Lange -logger Signed-off-by: Maxence Lange add details field Signed-off-by: Maxence Lange --- lib/Migration/Version0002Date20190618000001.php | 393 ++++++++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 lib/Migration/Version0002Date20190618000001.php diff --git a/lib/Migration/Version0002Date20190618000001.php b/lib/Migration/Version0002Date20190618000001.php new file mode 100644 index 00000000..10dcadd9 --- /dev/null +++ b/lib/Migration/Version0002Date20190618000001.php @@ -0,0 +1,393 @@ + + * @copyright 2018, Maxence Lange + * @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 OCA\Social\Migration; + + +use Closure; +use DateTime; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; +use Doctrine\DBAL\Schema\SchemaException; +use Doctrine\DBAL\Types\Type; +use Exception; +use OCA\Social\Exceptions\CacheActorDoesNotExistException; +use OCP\DB\ISchemaWrapper; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + + +/** + * Class Version0002Date20190226000001 + * + * @package OCA\Social\Migration + */ +class Version0002Date20190618000001 extends SimpleMigrationStep { + + + /** @var IDBConnection */ + private $connection; + + + /** + * @param IDBConnection $connection + */ + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + } + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + * @throws SchemaException + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options + ): ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + if (!$schema->hasTable('social_a2_stream')) { + return $schema; + } + + $table = $schema->getTable('social_a2_stream'); + $table->addColumn( + 'details', Type::TEXT, + [ + 'notnull' => false + ] + ); + + return $schema; + } + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @throws Exception + */ + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { + + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + + $this->check( + $schema, 'id', 'social_server_follows', 'social_a2_follows', 'accepted', 'boolean' + ); + $this->check( + $schema, 'id', 'social_server_notes', 'social_a2_stream', 'local', 'boolean' + ); + $this->check( + $schema, 'id', 'social_cache_actors', 'social_a2_cache_actors', 'local', 'boolean' + ); + $this->check( + $schema, 'id', 'social_cache_documents', 'social_a2_cache_documts', 'public', + 'boolean' + ); + + + $this->check( + $schema, 'id', 'social_server_actors', 'social_a2_actors', 'creation', 'datetime' + ); + $this->check( + $schema, 'id', 'social_server_follows', 'social_a2_follows', 'creation', 'datetime' + ); + $this->check( + $schema, 'id', 'social_server_notes', 'social_a2_stream', 'creation', 'datetime' + ); + $this->check( + $schema, 'id', 'social_cache_actors', 'social_a2_cache_actors', 'creation', + 'datetime' + ); + $this->check( + $schema, 'id', 'social_cache_documents', 'social_a2_cache_documts', 'creation', + 'datetime' + ); + + $this->check( + $schema, 'id', 'social_cache_documents', 'social_a2_cache_documts', 'caching', + 'datetime' + ); + +// $this->check($schema, 'id', 'social_request_queue', 'social_a2_request_queue','last', 'datetime'); +// $this->check($schema, 'id', 'social_queue_stream', 'social_a2_stream_queue', 'last', 'datetime'); + + $this->check( + $schema, 'id', 'social_server_notes', 'social_a2_stream', 'published_time', + 'datetime' + ); + } + + + private function check( + ISchemaWrapper $schema, + string $prim, + string $source, + string $dest, + string $field, + string $type + ) { + if (!$schema->hasTable($source)) { + return; + } + + $qb = $this->connection->getQueryBuilder(); + $qb->select($prim, $field) + ->from($source); + + $cursor = $qb->execute(); + while ($data = $cursor->fetch()) { + $this->fixMigration($dest, $prim, $field, $type, $data); + } + + $cursor->closeCursor(); + } + + + /** + * @param string $k + * @param array $arr + * @param string $default + * + * @return string + */ + private function get(string $k, array $arr, string $default = ''): string { + if ($arr === null) { + return $default; + } + + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + $r = $arr[$subs[0]]; + if (!is_array($r)) { + return $default; + } + + return $this->get($subs[1], $r, $default); + } else { + return $default; + } + } + + if ($arr[$k] === null || !is_string($arr[$k]) && (!is_int($arr[$k]))) { + return $default; + } + + return (string)$arr[$k]; + } + + + /** + * @param string $k + * @param array $arr + * @param bool $default + * + * @return bool + */ + protected function getBool(string $k, array $arr, bool $default = false): bool { + if ($arr === null) { + return $default; + } + + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + return $this->getBool($subs[1], $arr[$subs[0]], $default); + } else { + return $default; + } + } + + if ($arr[$k] === null) { + return $default; + } + + if (is_bool($arr[$k])) { + return $arr[$k]; + } + + if ($arr[$k] === '1') { + return true; + } + + if ($arr[$k] === '0') { + return false; + } + + return $default; + } + + + +// +// +// /** +// * @param string $table +// * @param array $fields +// * @param array $data +// * +// * @throws Exception +// */ +// private function insertInto(string $table, array $fields, array $data) { +// $insert = $this->connection->getQueryBuilder(); +// $insert->insert($table); +// +// $datetimeFields = [ +// 'creation', +// 'last', +// 'caching', +// 'published_time' +// ]; +// +// $booleanFields = [ +// 'local', +// 'public', +// 'accepted', +// 'hidden_on_timeline' +// ]; +// +// foreach ($fields as $field) { +// $value = $this->get($field, $data, ''); +// if ($field === 'id_prim' +// && $value === '' +// && $this->get('id', $data, '') !== '') { +// $value = hash('sha512', $this->get('id', $data, '')); +// } +// +// if (in_array($field, $datetimeFields) && $value === '') { +// $insert->setValue( +// $field, +// $insert->createNamedParameter(new DateTime('now'), IQueryBuilder::PARAM_DATE) +// ); +// } else if (in_array($field, $booleanFields) && $value === '') { +// $insert->setValue( +// $field, $insert->createNamedParameter('0') +// ); +// } else { +// $insert->setValue( +// $field, $insert->createNamedParameter($value) +// ); +// } +// } +// +// try { +// $insert->execute(); +// } catch (UniqueConstraintViolationException $e) { +// } +// } + + + /** + * @param string $dest + * @param string $prim + * @param string $field + * @param string $type + * @param array $old + */ + private function fixMigration( + string $dest, string $prim, string $field, string $type, array $old + ) { + +// foreach ($fields as $field) { +// $value = $this->get($field, $data, ''); +// if ($field === 'id_prim' +// && $value === '' +// && $this->get('id', $data, '') !== '') { +// $value = hash('sha512', $this->get('id', $data, '')); +// } + + $current = $this->connection->getQueryBuilder(); + $current->select($field) + ->from($dest); + + $cursor = $current->execute(); + $data = $cursor->fetch(); + $cursor->closeCursor(); + + if ($data === false) { + return; + } + + switch ($type) { + case 'datetime': + $oldValue = $this->get($field, $old); + $oldId = $this->get($prim, $old); + $currValue = $this->get($field, $data, ''); + if ($currValue !== '') { + return; + } + + $update = $this->connection->getQueryBuilder(); + $update->update($dest); + $update->set($field, $update->createNamedParameter($oldValue)); + $expr = $update->expr(); + + $update->where($expr->eq($prim, $update->createNamedParameter($oldId))); + + $update->execute(); + break; + + case 'boolean': + $oldValue = $this->getBool($field, $old); + $oldId = $this->get($prim, $old); + $update = $this->connection->getQueryBuilder(); + $update->update($dest); + $update->set($field, $update->createNamedParameter(($oldValue) ? '1' : '0')); + $expr = $update->expr(); + + $update->where($expr->eq($prim, $update->createNamedParameter($oldId))); + + $update->execute(); + + + break; + } + } + + +} + -- cgit v1.2.3