fix migration for sqlite (#881)

This commit is contained in:
Kevin Papst
2019-06-30 15:16:44 +02:00
committed by GitHub
parent d8621f0b7a
commit 834a0a873f
7 changed files with 62 additions and 44 deletions

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace App\API;
use App\Entity\Activity;
use App\Event\ActivityMetaDefinitionEvent;
use App\Form\API\ActivityApiEditForm;
use App\Repository\ActivityRepository;
use App\Repository\Query\ActivityQuery;
@@ -23,7 +22,6 @@ use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -43,16 +41,11 @@ class ActivityController extends BaseApiController
* @var ViewHandlerInterface
*/
protected $viewHandler;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
public function __construct(ViewHandlerInterface $viewHandler, ActivityRepository $repository, EventDispatcherInterface $dispatcher)
public function __construct(ViewHandlerInterface $viewHandler, ActivityRepository $repository)
{
$this->viewHandler = $viewHandler;
$this->repository = $repository;
$this->dispatcher = $dispatcher;
}
/**
@@ -142,11 +135,6 @@ class ActivityController extends BaseApiController
throw new NotFoundException();
}
// make sure the fields are properly setup and we know, which meta fields
// should be exposed and which not
$event = new ActivityMetaDefinitionEvent($data);
$this->dispatcher->dispatch(ActivityMetaDefinitionEvent::class, $event);
$view = new View($data, 200);
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace App\API;
use App\Entity\Customer;
use App\Event\CustomerMetaDefinitionEvent;
use App\Form\API\CustomerApiEditForm;
use App\Repository\CustomerRepository;
use App\Repository\Query\CustomerQuery;
@@ -23,7 +22,6 @@ use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -43,16 +41,11 @@ class CustomerController extends BaseApiController
* @var ViewHandlerInterface
*/
protected $viewHandler;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
public function __construct(ViewHandlerInterface $viewHandler, CustomerRepository $repository, EventDispatcherInterface $dispatcher)
public function __construct(ViewHandlerInterface $viewHandler, CustomerRepository $repository)
{
$this->viewHandler = $viewHandler;
$this->repository = $repository;
$this->dispatcher = $dispatcher;
}
/**
@@ -120,11 +113,6 @@ class CustomerController extends BaseApiController
throw new NotFoundException();
}
// make sure the fields are properly setup and we know, which meta fields
// should be exposed and which not
$event = new CustomerMetaDefinitionEvent($data);
$this->dispatcher->dispatch(CustomerMetaDefinitionEvent::class, $event);
$view = new View($data, 200);
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace App\API;
use App\Entity\Project;
use App\Event\ProjectMetaDefinitionEvent;
use App\Form\API\ProjectApiEditForm;
use App\Repository\ProjectRepository;
use App\Repository\Query\ProjectQuery;
@@ -23,7 +22,6 @@ use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -43,16 +41,11 @@ class ProjectController extends BaseApiController
* @var ViewHandlerInterface
*/
protected $viewHandler;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
public function __construct(ViewHandlerInterface $viewHandler, ProjectRepository $repository, EventDispatcherInterface $dispatcher)
public function __construct(ViewHandlerInterface $viewHandler, ProjectRepository $repository)
{
$this->viewHandler = $viewHandler;
$this->repository = $repository;
$this->dispatcher = $dispatcher;
}
/**
@@ -126,11 +119,6 @@ class ProjectController extends BaseApiController
throw new NotFoundException();
}
// make sure the fields are properly setup and we know, which meta fields
// should be exposed and which not
$event = new ProjectMetaDefinitionEvent($data);
$this->dispatcher->dispatch(ProjectMetaDefinitionEvent::class, $event);
$view = new View($data, 200);
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);

View File

@@ -52,6 +52,25 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai
return 'kimai2_' . $name;
}
protected function isSupportingForeignKeys(): bool
{
return true;
}
protected function deactivateForeignKeysOnSqlite()
{
if ($this->isPlatformSqlite() && !$this->isSupportingForeignKeys()) {
$this->addSql('PRAGMA foreign_keys = OFF;');
}
}
private function activateForeignKeysOnSqlite()
{
if ($this->isPlatformSqlite() && !$this->isSupportingForeignKeys()) {
$this->addSql('PRAGMA foreign_keys = ON;');
}
}
/**
* @param Schema $schema
* @throws DBALException
@@ -59,6 +78,16 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai
public function preUp(Schema $schema): void
{
$this->abortIfPlatformNotSupported();
$this->deactivateForeignKeysOnSqlite();
}
/**
* @param Schema $schema
* @throws DBALException
*/
public function postUp(Schema $schema): void
{
$this->activateForeignKeysOnSqlite();
}
/**
@@ -68,6 +97,16 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai
public function preDown(Schema $schema): void
{
$this->abortIfPlatformNotSupported();
$this->deactivateForeignKeysOnSqlite();
}
/**
* @param Schema $schema
* @throws DBALException
*/
public function postDown(Schema $schema): void
{
$this->activateForeignKeysOnSqlite();
}
/**

View File

@@ -35,6 +35,6 @@ class SqliteSessionInitSubscriber implements EventSubscriber
return;
}
$args->getConnection()->executeUpdate('PRAGMA foreign_keys = ON;');
$args->getConnection()->exec('PRAGMA foreign_keys = ON;');
}
}

View File

@@ -26,6 +26,21 @@ final class Version20190605171157 extends AbstractMigration
return 'Creates the budget columns on: customer, project, activity';
}
protected function isSupportingForeignKeys(): bool
{
return false;
}
public function isTransactional(): bool
{
if ($this->isPlatformSqlite()) {
// does fail if we use transactions, as tables are re-created and foreign keys would fail
return false;
}
return true;
}
public function up(Schema $schema): void
{
$customers = $schema->getTable('kimai2_customers');

View File

@@ -41,12 +41,12 @@ class SqliteSessionInitSubscriberTest extends TestCase
$platformMock->expects($this->once())->method('getName')->willReturn('sqlite');
$connectionMock = $this->getMockBuilder(Connection::class)
->setMethods(['getDatabasePlatform', 'getConnection', 'executeUpdate'])
->setMethods(['getDatabasePlatform', 'getConnection', 'exec'])
->disableOriginalConstructor()
->getMock();
$connectionMock->expects($this->once())->method('getDatabasePlatform')->willReturn($platformMock);
$connectionMock->expects($this->once())->method('executeUpdate')->with('PRAGMA foreign_keys = ON;', [], []);
$connectionMock->expects($this->once())->method('exec')->with('PRAGMA foreign_keys = ON;');
$args = new ConnectionEventArgs($connectionMock);
$sut->postConnect($args);
@@ -64,12 +64,12 @@ class SqliteSessionInitSubscriberTest extends TestCase
$platformMock->expects($this->once())->method('getName')->willReturn('mysql');
$connectionMock = $this->getMockBuilder(Connection::class)
->setMethods(['getDatabasePlatform', 'getConnection', 'executeUpdate'])
->setMethods(['getDatabasePlatform', 'getConnection', 'exec'])
->disableOriginalConstructor()
->getMock();
$connectionMock->expects($this->once())->method('getDatabasePlatform')->willReturn($platformMock);
$connectionMock->expects($this->never())->method('executeUpdate')->with('PRAGMA foreign_keys = ON;', [], []);
$connectionMock->expects($this->never())->method('exec')->with('PRAGMA foreign_keys = ON;');
$args = new ConnectionEventArgs($connectionMock);
$sut->postConnect($args);