Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

artisan migrate with --pretend flag doesn't work with multiple connections #36596

Closed
dshafik opened this issue Mar 15, 2021 · 4 comments
Closed

Comments

@dshafik
Copy link
Contributor

dshafik commented Mar 15, 2021

  • Laravel Version: 8.22.1
  • PHP Version: 7.4.13
  • Database Driver & Version: pdo_mysql, MySQL 5.6

Description:

When using the --pretend flag with php artisan migrate and using multiple connections, the schema changes are actually applied to the non-default DB.

Steps To Reproduce:

Add a second DB to config/database.php e.g. testing:

     'testing' => [
            'host' => env('DB_TESTING_HOST', '127.0.0.1'),
            'driver' => 'mysql',
            'port' => env('DB_TESTING_PORT', '3306'),
            'database' => env('DB_TESTING_DATABASE', 'analytics'),
            'username' => env('DB_TESTING_USERNAME', 'root'),
            'password' => env('DB_TESTING_PASSWORD', ''),
            'unix_socket' => '',
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

Create a fresh migration:

php artisan make:migration create_testing_table

Update the up() method to use the new connection:

    public function up()
    {
        Schema::connect('testing')->create('testing', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

Run migrate with pretend:

php artisan migrate --pretend

When doing this, I see the standard --pretend SQL output for migrations using the default DB connection, but this migration runs no matter what (and no --pretend SQL output), e.g. if you also php artisan make:migration create_foo_table and don't modify it:

$ php artisan migrate --pretend
CreateFooTable: create table `foo` (`id` bigint unsigned not null auto_increment primary key, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci'

Additionally the migrations table isn't updated (as expected), so If you run it again, it'll fail because the testing table already exists, and if you try to rollback, it'll rollback the previous migration, which could be disastrous.

@taylorotwell
Copy link
Member

Hey @dshafik! When controlling the connection within migrations, set the $connection property on the schema and the pretend should work. I'll make sure we are documenting this.

    protected $connection = 'testing';

    public function up()
    {
        Schema::create('testing', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

@dshafik
Copy link
Contributor Author

dshafik commented Mar 15, 2021

@taylorotwell I tested with protected $connection (and removed the ::connection() call) and the behavior is the same… actually, it's worse: it now applies the schema update to the default database, even with --pretend.

@taylorotwell taylorotwell reopened this Mar 15, 2021
@taylorotwell
Copy link
Member

@dshafik what if you do the $connection property and use the connection() call? That seems to exhibit the correct behavior for me.

@taylorotwell
Copy link
Member

taylorotwell commented Mar 15, 2021

So - digging into the code - it seems the connection property has a couple purposes 1) it informs the migrator what connection the migration will be running on when pretend is used and 2) it determines if the migration can be run within a transaction ... meaning is it running on a database that supports transactions on table alterations. If so, a transaction is started before calling your migration's up and down methods.

However, it seems within your migration up and down methods you still need to use the connection method as well in order to make the migration itself use that connection when modifying the table.

I somewhat expected the connection property to set the default database connection before the up or down methods are called and then revert the default connection back to its previous state after the method is finished but it appears that is not the case and would be a breaking change on 8.x 🤷‍♂️ 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants