I have a migration that creates a postres sequence for auto incrementing a primary identifier, and then executes a statement for altering the column and specifying the default value:
execute 'CREATE SEQUENCE "ServiceAvailability_ID_seq";'
execute <<-SQL
ALTER TABLE "ServiceAvailability"
ALTER COLUMN "ID" set DEFAULT NEXTVAL('ServiceAvailability_ID_seq');
SQL
If I run db:migrate everything seems to work, in that no errors are returned, however, if I run the rails application I get:
Mnull value in column "ID" violates not-null constraint
I have discovered by executing the sql statement in the migration manually, that this error is because the alter statement isn't working, or isn't being executed.
If I manually execute the following statement:
CREATE SEQUENCE "ServiceAvailability_ID_seq;
I get:
error : ERROR: relation "serviceavailability_id_seq" already exists
Which means the migration successfully created the sequence! However, if I manually run:
ALTER TABLE "ServiceProvider"
ALTER COLUMN "ID" set DEFAULT NEXTVAL('ServiceProvider_ID_seq');
SQL
It runs successfully and creates the default NEXTVAL.
So the question is, why is the migration file creating the sequence with the first execute statement, but not altering the table in the second execute? (Remembering, no errors are output on running db:migrate)
Thank you and apologies for tl:dr
I separated the creation of sequences and the altering of tables into two migrations.
When running:
rake db:migrate
The sequences would not be created nor the tables altered and the rake would run successfully.
If however, I ran the migrations seperately:
rake db:migrate VERSION=1
rake db:migrate VERSION=2
The sequences would be created, and the tables altered as expected.
Related
I am using ruby on rails with postgresql database. A weird thing happened that some of the tables_id_seq are not starting from 1, but 980190963. But some of the seq are correctly starting from 1.
The problem is when I tried to insert data into those table which seq not start from 1, unique primary key violation raised occasionally.
--EDIT--
I found that when I do
rake db:migrate test
The problem happens.
If I do
rake db:migrate RAILS_ENV=test
The problem has gone.
If you don't need to keep the data in those tables, you can run the following which will reset the table (THIS WILL REMOVE ANY DATA THERE) and restart the tables id to start at 1. THIS IS ONLY VIABLE IF YOU DON"T NEED THE DATA IN THAT TABLE!
ActiveRecord::Base.connection.execute("TRUNCATE TABLE table_name_here RESTART IDENTITY")
As far as why your tables are starting at that id value I would start by checking your migrations. Maybe somewhere in the code there is an "Alter Sequence" sql statement but again not sure.
I created an integer for a phone number, and then learned that it is better to consider it as a string due to it's size.
I decided then to change directly the migration and apply db:reset instead of adding a new migration since the project is only on my computer at this moment. Db:reset worked but it doesn't seem that my database changed.
It raised a lot of questions :
Is there a command to analyse a database and identify the types of its columns ?
Does db:reset allow to modify a migration, like after rolling back a migration ?
Even though it isn't preferable, what are the conditions to modify directly a migration ?
The db:reset task resets the database by dropping the database and then loading schema.rb - it does not run migrations again. If you dropped the database, then created it and ran db:migrate then you should get the desired outcome
Change the field as string in migration, then run the commands:-
rake db:drop
rake db:create
rake db:migrate
And it will change the field type from integer to string.
I have 3 different schemas in one Rails application. My preparation of the test database using rake db:test:prepare fails with:
psql:/Users/me/myapp/db/structure.sql:7417: ERROR: relation "schema_migrations" does not exist
LINE 1: INSERT INTO schema_migrations (version) VALUES ('20131213203...
That's because it is not proper setting the Postgres search_path before doing all the insertions to the schema_migrations table. I haven't messed with this code in about 8 months and can't remember what I did. I haven't the faintest idea of how I even got those other schema to dump.
You may want to try rake db:structure:dump and / or rake db:schema:dump and try re-running rake db:test:prepare. The former should create the structure.sql and the later the schema.db
I was able to accomplish what I needed by doing two things:
Overriding the purge task under db:test in AR's railties to call a custom drop_database_objects method.
Using a little-known attribute in my database.yml: schema_search_path: public
The first thing lets me drop only the database objects I want, leaving my other support databases intact.
The second thing just creates the structure from my main database, and doesn't try to create the structure from the other databases. It looks like a bug in that it structure:dump doesn't set the schema search path appropriately at the end of the structure.sql script, right before the inserts into the schema_migrations table in a multi-schema instance. These fixes make that not necessary.
I am getting an error when I try to migrate my db. I don't entirely remember how I got here, but I believe I:
created new branch, scaffolded 'Requests', db:migrated, switched back to master, and merged branch
created another branch, did some stuff, db:migrated, and everything was working fine.
pulled from heroku postgres database so i could test out if things worked with actual data. then tried db migrating, but gave me this error:
rake db:migrate
== CreateRequests: migrating =================================================
-- create_table(:requests)
NOTICE: CREATE TABLE will create implicit sequence "requests_id_seq1" for serial column "requests.id"
rake aborted!
An error has occurred, this and all later migrations canceled:
PG::Error: ERROR: relation "requests" already exists
: CREATE TABLE "requests" ("id" serial primary key, "title" character varying(255), "content" text, "category" character varying(255), "status" character varying(255), "requested_track_id" integer, "created_at" timestamp, "updated_at" timestamp)
Any ideas?
I'm not sure exactly what pull strategy you used, but if we make two reasonable assumptions about your pull strategy:
it doesn't drop the database but just overwrites tables, since this requires less permissions.
it is operating in a sort of 'archive mode', meaning it doesn't drop tables on the destination just because they don't exist on the source. Think rsync; you have to specify --delete to get what might be your expected behavior with that utility.
If your steps are correct, then what happened is you overwrote the schema_migrations table, so Rails thinks you haven't added the table yet, but neither did your heroku pull drop the table because of #2 above.
Don't create another migration!!! This will fail on everyone elses' computer except yours, but will only run on yours once.
Instead, run rails dbconsole and execute something like DROP TABLE 'requests' (I forget the postgres syntax, might not be exactly that). Then you can run your migrations.
There is another way to avoid dropping a table with data in it.
What I do in those cases is to check which migration is failing.
Suppose you have a file db/migrate/20130908214222_create_requests.rb, and for some reason, ActiveRecord failed in the past when stored this migration in its "tracking system".
To be sure that this is the case, just find, in the schema_migrations table, a row containing a number like this example: 20130908214222
If that row does not exist, you just have to insert a new one:
INSERT INTO schema_migrations(
version
) VALUES (
20130908214222
);
Next time you run rake db:migrate, ActiveRecord will omit this step, and will continue migrating to end without complications.
I've ended up with 9 migrations effectively duplicated. (I think this is because I installed/updated Gems and/or pulled in their migrations on both my dev and production machines, but am not entirely sure at this stage.)
I moved out one set of the duplicated 9 from the rails directories on the production server, but now that I want to db:migrate on production in order to run another migration, I'm getting:
$ bundle exec rake db:migrate RAILS_ENV=production
[DEPRECATION WARNING] Nested I18n namespace lookup under "activerecord.attributes.checkout" is no longer supported
== CreatePages: migrating ====================================================
-- create_table(:pages)
rake aborted!
An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'pages' already exists: CREATE TABLE `pages` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `title` varchar(255), `body` text, `slug` varchar(255), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
This is because the migrations have effectively already been run.
I'd rather avoid doing db:migrate:down and db:migrate:up for each one - I think this will mean data in the production database is lost. (A couple of static pages in Spree in this case.)
Is there a way I can tell this installation of Rails to forget all outstanding migrations, effectively marking all outstanding migrations as done?
I solved it like this:
Go to the conflicting migration file.
Erase the content and save it.
Run rake db:migrate
Ctrl+Z the file to the previous state.
This was an special case, because I had copied the DB from another app, and I had conflicting migrations, and stuff.
You can add the timestamps of the migrations to the schema_migrations table. However why is that table missing from the database or missing the rows it needs?
It is likely to be the case that this particular migration has got half way through and failed, thus when you are trying to run it again the first part of the migration will not work as it has been done previously. This is a limitation of MySQL as it can't rollback migration changes that fail part of the way through. Postgres on the other hand can rollback structural changes to the database thus avoiding this issue.
By default rake db:migrate runs all the pending migrations. So, in order to get your migrations right.. for the sake ..comment out those migrations and afterwards revert those back to normal. It will ensure that you are ok in future migrations.
You can also, in a Rails console, use the ActiveRecord::SchemaMigration model to add the timestamps into the schema_migrations table.
ActiveRecord::SchemaMigration.create! version: '20210724133241'