-
Notifications
You must be signed in to change notification settings - Fork 11k
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
[Proposal] Add Schema::hasIndex() method #3253
Comments
Hey mate, It would be the first example of this sort of logic (e.g. querying the database) inside the Schema class, therefore it's probably better suited in the DB Query classes, though, it'd be the first schema-related thing there, so it's tricky. Question, when would you not know if you had an index? If each migration's up/down methods null each other out, there shouldn't be a discrepancy, right? |
Hey Ben, To avoid to stop a migration ( also avoiding all the problems that this thing can cause ) I think that a "hasIndex" or a "dropIndexIfExists" method can be helpful |
Doctrine can probably handle this. The DBAL is accessible via the DB connection. |
@taylorotwell Sorry to bump this up, but it's unclear to me how you suggest to access the DBAL instance inside a migration.
Than something like this:
Where, in the second example, I'm hard-coding laravel's way of doing indexes as well as explicitly bringing up Doctrine's dependency on my code. |
I'll have to add to this, I really don't find the way to do it with Doctrine. @taylorotwell as you said it's easily done with DBAL, can you post a small snippet of code of how it could be done? UPDATE
|
Why is this closed? It's a perfectly valid request and necessary for avoiding errors on complicated migration sets. But thanks @guiwoda for showing how to do this with DBAL |
@guiwoda Awesome, I'll try to work this into my migrations. Thanks! I'm currently facing a problem where adding a unique composite index in a later migration, removes an index on one of the attributes in my new index, which in turn leads to an exception when rolling back, because an index is needed for the fkey to work. My solution: To manually add the old index before deleting the unique index. However, the new index does not get deleted when migrating the new unique key once more, even though it is identical to the one originally created by the foreign() method. Because of this I am now checking whether such an index exists before adding it in my down() method. |
+1 |
It sucks that this was closed considering we already have |
I also would like to request the reopening this issue. Having the ability to check for an index seems like a very natural function for a Schema class. |
+1 thanks @guiwoda |
1 similar comment
+1 thanks @guiwoda |
+1 |
+1 thanks @guiwoda |
This shouldn't be closed |
They look for PR not just suggestion. |
I have run into this often enough that I'm putting together a PR for this. |
This is in PR #14975 |
+1 |
I appreciate the +1s, but can we please close this conversation? |
sample usage base on @guiwoda
|
|
I just hit this issue as well. Seems like a frustrating "gotcha" that my instinct was to do
which doesn't work. |
I'm using mongodb, It's say 'call_user_func_array() expects parameter 1 to be a valid callback, class 'MongoDB\Database' does not have a method 'getDoctrineDriver'' |
This has been a recurring issue since 2014, I think its time I worked on that PR. |
I hit into this issue too recently. I ended up making a using the schema macros and making a macro service provider to register a dropIndexIfExists macro and a hasIndex macro. use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class MacroServiceProvider extends ServiceProvider
{
public function register()
{
$this->registerSchemaMacros();
}
/**
* Register the schema macros.
*/
protected function registerSchemaMacros()
{
Blueprint::macro('dropIndexIfExists', function(string $index): Fluent {
if ($this->hasIndex($index)) {
return $this->dropIndex($index);
}
return new Fluent();
});
Blueprint::macro('hasIndex', function(string $index): bool {
$conn = Schema::getConnection();
$dbSchemaManager = $conn->getDoctrineSchemaManager();
$doctrineTable = $dbSchemaManager->listTableDetails($this->getTable());
return $doctrineTable->hasIndex($index);
});
}
} Then in your migrations you can do the following: Schema::table('users', function (Blueprint $table) {
$table->dropIndexIfExists('users_index_id');
if ($table->hasIndex('another_index')) {
$table->dropIndex('another_index');
}
}); |
@michaeljennings I changed your code to also allow for composite indexes (and generally $index as an array). Remember that Laravel allows you to do:
|
thanks it works in sql server |
This should really exist... many times I find myself writing a migration and then it fails, but some of the code still executes, thus creating the indexes so when you finally end up fixing your code, if you don't go manually delete those indexes, you need to write a bunch of things like :
Possibly this is a problem with laravel itself, if a migration has an error when doing the artisan migrate, it should reverse everything automatically... |
listTableDetails being deprecated, here is what we can do instead (apart waiting for this to be native to laravel): Schema::table('events', function (Blueprint $table) {
$schema_builder = Schema::getConnection()
->getDoctrineSchemaManager()
->introspectTable( $table->getTable() );
if( $schema_builder->hasIndex('events_subs_admin_id_foreign') ){
$table->dropIndex('events_subs_admin_id_foreign');
}
}); |
What about add a method to the Schema class to check if an index exists?
It can be useful in migrations to avoid possible errors on adding/dropping indexes
I know a method on MySQL but I haven't experience with other DB engines.
I've found this informations to make this:
Thoughts?
The text was updated successfully, but these errors were encountered: