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

[11.x] Add dropForeign support on SQLiteGrammar (#51318) #51358

Closed
wants to merge 1 commit into from

Conversation

Gandhi11
Copy link

@Gandhi11 Gandhi11 commented May 9, 2024

This pull request proposes an enhancement to Laravel's SQLiteGrammar in order to support the drop on foreign keys. It uses the same approach as doctrine/dbal which is recreating the table while removing the foreign key constraint and use the logic of the existing compileChange method to do so.

Motivation

The motivation behind this enhancement is to provide developers the ability to use foreign keys on SQLite and be able to drop them.

Use Cases

In a project that uses SQLite and foreign keys on a column. It is currently not possible to drop a column that has a foreign key constraint on it. Currently if we try to drop the foreign key, we receive the following exception: This database driver does not support dropping foreign keys. Therefore, the PR is to provide the ability to drop the foreign key before dropping the column.

For example, this migration will add a foreign key on the user_id of the session table.

return new class extends Migration {
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

        Schema::create('sessions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->nullable()->index()
                ->constrained('users')
                ->onUpdate('CASCADE')
                ->onDelete('CASCADE');

            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->longText('payload');
            $table->integer('last_activity')->index();
        });
    }
}

Then when trying to delete the column user_id which has a foreign key with the following migration will throw an exception when using the SQLite Driver.

return new class extends Migration {
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('sessions', function (Blueprint $table) {
            $table->dropIndex(['user_id']);
        });
        Schema::table('sessions', function (Blueprint $table) {
            $table->dropForeign(['user_id']);
        });
        Schema::table('sessions', function (Blueprint $table) {
            $table->dropColumn('user_id');
        });
    }
}

fix #51318

@Gandhi11 Gandhi11 force-pushed the sqlite-drop-foreign-keys branch from c3c9180 to 0b8d75d Compare May 9, 2024 14:40
@hafezdivandari
Copy link
Contributor

They way it's implemented will causes more problems in the future, unfortunately. As you already noticed, it's not possible to use dropForeign in combination with other commands, so you have used 3 separate Schema::table to make it work. It's definitely confusing for the end user, hard to explain/document and will cause unexpected results.

@Gandhi11
Copy link
Author

Gandhi11 commented May 9, 2024

@hafezdivandari Thank you for the feedback.

Do you have an example of the problem that could occur? It is the same way that doctrine/dbal was doing it.

Yes, the downside is to make sure that the dropForeign is part of is own Schema::table to make it work but I think it is better than not supporting it at all.

I think that adding a block in the Laravel Docs https://laravel.com/docs/11.x/migrations#dropping-foreign-keys about this should be enough to explain the situation.

@taylorotwell
Copy link
Member

Thanks for your pull request to Laravel!

Unfortunately, I'm going to delay merging this code for now. To preserve our ability to adequately maintain the framework, we need to be very careful regarding the amount of code we include.

If possible, please consider releasing your code as a package so that the community can still take advantage of your contributions!

If you feel absolutely certain that this code corrects a bug in the framework, please "@" mention me in a follow-up comment with further explanation so that GitHub will send me a notification of your response.

@Gandhi11
Copy link
Author

Gandhi11 commented May 9, 2024

Hi @taylorotwell,

I really understand your point and I am in line with you regarding the ability to adequately maintain the framework.

I don't know if you had the chance to review the issue #51318, but this is something that used to work since Laravel 5 and now blocking the migration of all our project to Laravel 11 since is it breaking all migrations that drop a column with a foreign key in SQLite.

Can you please reconsider the change or even look into it to find a proper solution if mine is not the best one.

Thanks

@Gandhi11 Gandhi11 deleted the sqlite-drop-foreign-keys branch May 10, 2024 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Laravel 11 SQLite Migration Failure: after drop column: unknown column "XXXXXX" in foreign key definition
3 participants