phpsqlmysqldoctrine

Skip a statement in Doctrine migration if there if there is a certain value in a table


I'm in the process of rolling out a feature to all clients, but some clients already have existing data, and I cannot override the content present in their meal_moment table.

I need to create a default meal_moment with ID 0 for all clients who don't have any meal_moment data, while also updating all orders to mealmoment_id 0, as I need to override that.

Clients where the feature is already deployed have a meal_moment with ID 0.

Here is my migration code:

public function up(Schema $schema): void
{
    // if no mealmoment with the id 0 exists, create it
    $this->addSql("
        INSERT INTO `meal_moment` (`id`, `name`, `code`, `ordre`, `customer_id`)
        VALUES (0, 'None', 'None', 0, 0);
        UPDATE `order` SET mealmoment_id = 0 WHERE mealmoment_id IS NULL
    ");
}

public function down(Schema $schema): void
{
    $this->addSql('UPDATE `order` SET mealmoment_id = NULL WHERE mealmoment_id = 0');
    $this->addSql('DELETE FROM meal_moment WHERE id = 0');
}

This craches approch craches for some clients but works in our dev envs where there is no mealmoment. Also, for a reason I can't find, the id = 0 in the insert always gets replaced by id = 1

Thanks for your help and suggestions !


Solution

  • The solution turned out to be quite straightforward, and I'm a bit embarrassed that I didn't realize it earlier. I needed to access the protected connection property of the parent class and execute a query to conditionally handle my migration. (Thanks to @iainn for the suggestion.)

    For the specific case where id = 0, @AymDev was correct in pointing out that it was a SQL mode issue. The solution involved setting the SQL mode to include NO_AUTO_VALUE_ON_ZERO before the insertion and then resetting it afterward.

    public function up(Schema $schema): void
    {
    
        $r = $this->connection->prepare('SELECT COUNT(*) FROM meal_moment WHERE id = 0')
            ->executeQuery()
            ->fetchOne();
    
        if ($r == 0) {
            $modes = $this->connection->prepare("SELECT @@sql_mode;")
                ->executeQuery()
                ->fetchOne();
    
            $this->addSql("
                SET sql_mode = CONCAT(@@sql_mode, ',NO_AUTO_VALUE_ON_ZERO');
                INSERT INTO `meal_moment` (`id`, `name`, `code`, `ordre`, `customer_id`) VALUES (0, 'Aucun', 'Aucun', 0, 0);
                SET sql_mode = :modes
                ", ['modes' => $modes]);
    
        }
        $this->addSql("UPDATE `order` SET mealmoment_id = 0 WHERE mealmoment_id IS NULL");
    
    }
    
    public function down(Schema $schema): void
    {
        $this->addSql('UPDATE `order` SET mealmoment_id = NULL WHERE mealmoment_id = 0');
        $this->addSql('DELETE FROM meal_moment WHERE id = 0');
    
    }