为什么Doctrine 2迁移在Symfony项目中无声地失败?

Ric*_*son 6 mysql doctrine symfony doctrine-orm

我的问题是:

  1. 为什么Symfony中的doctrine migration命令无法报告我在下面列出的SQL错误
  2. 如何让它报告此类错误,而不是看起来已成功.

要清楚 - 我知道为什么SQL本身会失败.这很容易.失败的沉默本质就是问题所在.

我在PHP文件中有一个学说迁移,如下所示:

[... boilerplate ...]

public function up(Schema $schema)
{
    $this->addSql(<<<SQL

    -- This runs fine
    CREATE TABLE [[redacted - this part runs fine]];

    -- This fails with a unique key constraint
    INSERT INTO `users_orgs` (`org_id`, `user_id`, `active`)
    SELECT `oid`, `uid`, 1 as `active` FROM `orgs`;

    -- Never gets here
    ALTER TABLE `orgs` CHANGE `uid` `primary_user_id` int(11) unsigned DEFAULT NULL;

SQL
    );
}

[... boilerplate ...]
Run Code Online (Sandbox Code Playgroud)

实际结果

第二个语句由于唯一的键约束而失败(例如"键'PRIMARY'的重复条目'6-3'" - 它是复合键)但是没有报告错误.我知道它失败了,因为很明显最终语句永远不会运行,如果我手动运行违规语句,它就会失败.当我跑:

./bin/console doctrine:migrations:migrate
Run Code Online (Sandbox Code Playgroud)

从我的Symfony应用程序中调用doctrine迁移代码,它报告:

$ ./bin/console doctrine:migrations:migrate

                Application Migrations                    


WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y
Migrating up to 20160822090333 from 20160820232349

  ++ migrating 20160822090333

     -> CREATE TABLE [[redacted - works fine]];

INSERT INTO `users_orgs` (`org_id`, `user_id`, `active`)
SELECT `oid`, `uid`, 1 as `active` FROM `orgs`;

ALTER TABLE `orgs` CHANGE `uid` `primary_user_id` int(11) unsigned  DEFAULT NULL;


  ++ migrated (0.1s)

  ------------------------

  ++ finished in 0.1s
  ++ 1 migrations executed
  ++ 1 sql queries
Run Code Online (Sandbox Code Playgroud)

预期结果

我期待它报告错误.作为测试,我创建了一个带有主键的单列表.我尝试插入一条记录,该记录会在迁移中生成唯一的约束违规.当我执行迁移时,doctrine报告了这个:

Migration 20160908112332 failed during Execution. Error An exception occurred while executing '        insert into FOO values (1)':

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'
Run Code Online (Sandbox Code Playgroud)

我的配置

这是我安装的(通过作曲家):

doctrine/annotations                 v1.2.7             Docblock Annotations Parser
doctrine/cache                       v1.6.0             Caching library offering an object-oriented API for many cache backends
doctrine/collections                 v1.3.0             Collections Abstraction library
doctrine/common                      v2.6.1             Common Library for Doctrine projects
doctrine/dbal                        v2.5.4             Database Abstraction Layer
doctrine/doctrine-bundle             1.6.4              Symfony DoctrineBundle
doctrine/doctrine-cache-bundle       1.3.0              Symfony Bundle for Doctrine Cache
doctrine/doctrine-migrations-bundle  v1.2.0             Symfony DoctrineMigrationsBundle
doctrine/inflector                   v1.1.0             Common String Manipulations with regard to casing and singular/plural rules.
doctrine/lexer                       v1.0.1             Base library for a lexer that can be used in Top-Down, Recursive Descent Pa...
doctrine/migrations                  1.4.1              Database Schema migrations using Doctrine DBAL
symfony/symfony                      v3.0.9
Run Code Online (Sandbox Code Playgroud)

MySQL的:

mysql Ver 14.14 Distrib 5.6.27, for Linux (x86_64) using  EditLine wrapper
Run Code Online (Sandbox Code Playgroud)

我试过的

我在谷歌和这里搜索了"沉默的教条失败","沉默的学说迁移失败",我没有看到任何东西.任何见解将不胜感激.

jkr*_*nak 4

这与在一个查询中执行多个语句有关。

学说迁移文档说:

在内部,addSql 调用被传递到dbal executeQuery method.

我尝试执行多个语句,executeQuery它的行为与您的相同。(我有不同的软件包版本,但仅补丁级别不同)。当我有多个语句时,如果第一个语句失败,它只会抛出错误。

考虑这个例子:

/** @var \Doctrine\DBAL\Connection $connection */
$connection = $this->getDoctrine()->getConnection();

$createTable = "CREATE TABLE test (org_id int not null, user_id int not null, PRIMARY KEY(org_id, user_id));";

$insert = "INSERT INTO test (org_id, user_id) VALUES (1, 1);";

// this will create the table (if doesn't exist) and add a record, the second insert silently fails.
$connection->executeQuery("{$createTable}{$insert}{$insert}"); 
Run Code Online (Sandbox Code Playgroud)

但:

// ... same as above except for executeQuery
$connection->executeQuery("{$createTable}");
$connection->executeQuery("{$insert}");
$connection->executeQuery("{$insert}"); // <- duplicate key error is thrown
Run Code Online (Sandbox Code Playgroud)

我想要达到的目的是addSql()为每个语句使用单独的语句。

[... boilerplate ...]

public function up(Schema $schema)
{
    $this->addSql("CREATE TABLE [[redacted - this part runs fine]];");

    $this->addSql("INSERT INTO `users_orgs` (`org_id`, `user_id`, `active`) SELECT `oid`, `uid`, 1 as `active` FROM `orgs`;");

    $this->addSql("ALTER TABLE `orgs` CHANGE `uid` `primary_user_id` int(11) unsigned DEFAULT NULL;");
}

[... boilerplate ...]
Run Code Online (Sandbox Code Playgroud)