Error with index when converting Laravel mysql migrations to postgresql - laravel

I have written about 10 Laravel migrations for a MySQL database. I want to now switch out my database for a Postgresql database but am having some trouble with indexes it seems.
I followed a tutorial about a voting module so I didnt write the migrations myself but they did all work when migrating on MySQL.
The error im getting is as follows;
SQLSTATE[42P07]: Duplicate table: 7 ERROR: relation "poll_id" already exists (SQL: create index "poll_id" on "gp_poll_votes" ("poll_id"))
There is no duplicate table and these migrations have been working for the last year or so.
The migration it is getting stuck on is as follows;
Schema::create('gp_poll_votes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('poll_id')->unsigned();
$table->bigInteger('poll_option_id')->unsigned();
$table->bigInteger('vote_count');
$table->timestamps();
$table->index('poll_id', 'poll_id');
$table->index('poll_option_id', 'poll_option_id');
$table->foreign('poll_id')->references('id')->on('gp_polls')->onDelete('cascade');
$table->foreign('poll_option_id')->references('id')->on('gp_poll_options')->onDelete('cascade');
});
There is 2 more migrations associated with the votes which are run before the erroring one, which are;
Schema::create('gp_polls', function (Blueprint $table) {
$table->bigIncrements('id');
$table->tinyInteger('status')->nullable(false)->default(1);
$table->timestamps();
});
and
Schema::create('gp_poll_options', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('poll_id')->unsigned();
$table->bigInteger('image_id')->unsigned();
$table->tinyInteger('status')->nullable(false)->default(1);
$table->timestamps();
$table->index('poll_id', 'poll_id');
$table->index('image_id', 'image_id');
$table->foreign('image_id')->references('id')->on('gp_submit_images');
$table->foreign('poll_id')->references('id')->on('gp_polls')->onDelete('cascade');
});

In Postgres the index names have to be unique across the database it would seem, in MySQL that doesn't seem to matter.
You can create your indexes without passing a second argument, the name of the index, and Blueprint will create a more unique index name for you.
$table->index('poll_id'); // "gp_poll_options_poll_id_index"
It will use something like "{$prefix}{$table}_{$column}_{$typeOfIndex}" to generate the index name for you.

Related

laravel6: how to change references of a foreign key with migration

I have tried to change foreign key reference by dropforeign key.I think everything is ok but i get this error:
SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP
FOREIGN KEY teacher_schedule_calendars_product_id_foreign; check
that it exists (SQL: alter table teacher_schedule_calendars drop
foreign key teacher_schedule_calendars_product_id_foreign)
How can I solve it?
my migration code is :
Schema::table('teacher_schedule_calendars', function (Blueprint $table) {
$table->dropForeign(['product_id']);
$table->foreign('product_id')->references('id') ->on('courses')->onDelete('cascade');
});
firstly, I ave removed the foreign and then add references. but it did not work.
I'm assuming you created a foreign key on the product_id column in a previous migration and you simply want to renew it or replace it with a foreign key to another table. In this case, what you are attempting to do might be problematic due to the way how migrations work and how individual database grammatics translate the commands.
What you can do to mitigate the issue is splitting the commands into two Schema::table($table) blocks:
Schema::table('teacher_schedule_calendars', function (Blueprint $table) {
$table->dropForeign(['product_id']));
});
Schema::table('teacher_schedule_calendars', function (Blueprint $table) {
$table->foreign('product_id')->references('id')->on('courses')->onDelete('cascade');
});

Change the datatype in the column with data in laravel migration

This is the migration? i have to change the string data column into integer data column with existing data
public function up()
{
Schema::table('SYS_tenants' ,function (Blueprint $table){
$table->integer('tena_type')->unsigned()->nullable()->change();
$table->foreign('tena_type')->references('id')->on('account_types');
});
}
As per laravel Documentation you can create a new migration and do it like this:
Schema::table('SYS_tenants', function (Blueprint $table) {
$table->integer('tena_type')->unsigned()->nullable()->change();
});
Before modifying a column, be sure to add the doctrine/dbal dependency
to your composer.json file.
composer require doctrine/dbal
Reference: Laravel -> Database: Migrations-> Modifying Columns
You can use change method on the field which you want to change the type after setting the new field type.
public function up() {
Schema::table('SYS_tenants' ,function (Blueprint $table){
$table->string('tena_type')->change();
});
}
I supposed the migration which create the table has already call all requirement you need like unique, nullable and so on. You can call change method, by the way there isn't restriction about any modification you want to perform like add other mysql index on that field.
Do not forget to add doctrine/dbal in composer.json file
Migrations#Modifying Columns
Looks like what you have should work:
Schema::table('SYS_tenants' ,function (Blueprint $table){
$table->integer('tena_type')->unsigned()->nullable()->change();
});
Depending on your database you may need to cast the values to the new type: (for mysql: https://www.mysqltutorial.org/mysql-cast/)
I already use this Laravel Migration
$table->integer('tena_type')->unsigned()->nullable()->change();
But it doesn't work because, the data already in the table. In that case it can't change the datatype.I use this DB statement to change the datatype with data.it's working properly.
DB::statement("alter table SYS_tenants modify tena_type integer not null"):

How to get relation 'table1' OR 'table2' OR 'table3' into one table in laravel?

I'm a newbie here and also in Laravel, so please excuse me. I have a table named 'products' and this table related to the 'recipes' table via many-to-one relation(One of the recipes has a lot of products). -'recipes' table keeps reference code- Here's where I stuck; the 'recipes' table has one-to-one relations to three different tables that keeping the "real" product recipes. Those tables have different recipe contents like,
Alkaline table;
Schema::create('alkalines', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('recipe_id');
$table->integer('sodium_bicarbonate');
$table->timestamps();
});
Acets table;
Schema::create('acets', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('recipe_id');
$table->integer('sodium_chloride');
$table->integer('acetic_acid');
$table->timestamps();
});
I'm able to fetch all relations if I start with one of these(e.g with Acet model). But if, I list all of products and try to fetch it's recipe, I have to use a bunch of 'if and else's. Just can't get the recipe like;
$product->recipe-> "one of the three recipe tables' content"
And my 'recipes' table:
Schema::create('recipes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('ref');
$table->timestamps();
});
I believe it's easy, just missing something. Please help! Thanks in advance!
I think
You can get every relation individual them merge the arrays
like
$arr1=Alkalines::with('recipe')->get()->toArray();
$arr2==Acets::with('recipe')->get()->toArray();
$arr3=***************************;
array_merge($arr1,$arr2,$arr3)
Welcome to SO.
If you have relations set up properly, you can use 'collection->pluck()' to retrieve their results, no matter how deeply nested in different relations.
Example:
$game->players->stats won't work, because players is a collection that doesn't have a stats attribute, method or field.
So, what you can do is use pluck() and collapse() to retrieve result of relations:
$game->players->pluck('stats')->collapse()
I edit the code from #mohamedhassan a little bit, and it worked!
public function solutionMerge()
{
$arr1=Alkaline::with('recipe')->get();
$arr2=Acet::with('recipe')->get();
$arr3=Glucose::with('recipe')->get();
$solutionMerge = collect([$arr1,$arr2,$arr3]);
return $solutionMerge;
}
Just assigned arrays into a collection. And then use collapse().
And now, I'm able to fetch data like $solutionMerge->recipe->id
Thank you people, for your precious time and immense knowledge!

onDelete Cascade two sides

I'm using Laravel Framework, I have multiple connected tables, I successfully could remove a operation from operations table when the related transaction is deleted from transactions table, but i couldn't get it to work in the opposite side, as it throws an error on migration and also when adding new rows to operations table.
Schema::create('operations', function (Blueprint $table) {
$table->increments('id');
$table->integer('car_id')->unsigned();
$table->string('operation');
$table->integer('transaction')->unsigned();
$table->timestamps();
});
Schema::table('operations', function($table) {
$table->foreign('car_id')->references('id')->on('cars')->onDelete('cascade');
$table->foreign('transaction')->references('id')->on('transactions')->onDelete('cascade');
});
What I need is to also delete the transaction when a related operation is deleted:
Schema::create('transactions', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->string('status')->index();
$table->date('date')->index();
$table->string('user_added');
$table->string('note')->nullable();
$table->timestamps();
});
Schema::table('transactions', function($table) {
$table->foreign('id')->references('transaction')->on('operations')->onDelete('cascade');
});
Is there a way to achieve that?
For now it throws an error on migration:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key
constraint (SQL : alter table transactions add constraint
transactions_id_foreign foreign key (i d) references
operations (transaction) on delete cascade)
Which is normal because operations table comes after transactions in order, even if i put the second part of the code in operations table, it throws a similar error when i start inserting rows to table.
I appreciate leading me to a solution.
its looks like you added your primarykey as foreignkey
Schema::table('transactions', function($table) {
$table->foreign('id')->references('transaction')->on('operations')->onDelete('cascade');
please adding 1 column on transaction table "operations_id" and change your schema like this
Schema::table('transactions', function($table) {
$table->foreign('operations_id')->references('id')->on('operations')->onDelete('cascade');

Updating columns with migration Laravel 5.4

I have a running application, I see a field in a form is not required and can be left empty. but by the migrations, that field in database is set to be "not null". I wanted to to change it so I did it by checking Null. But how I do the same thing with migrations?? I read documentation and created this
public function up()
{
Scheme::table('modules', function (Blueprint $table) {
$table->text('content')->nullable();
});
}
but when I run migration, it give me error table already exists (obviously, because other migration files are there). How should I do it to achieve my target.
Change your code to this and notice the ->change() part:
public function up()
{
Scheme::table('modules', function (Blueprint $table) {
$table->text('content')->nullable()->change();
});
}
Documentation on changing columns
NB:
You'll need the Doctrine/DBal package in order for this to work:
Before modifying a column, be sure to add the doctrine/dbal dependency to your composer.json file. The Doctrine DBAL library is used to determine the current state of the column and create the SQL queries needed to make the specified adjustments to the column

Resources