or: How I Learned to Stop Worrying and Love the WWW
Home RSS

I Like to Migrate, Migrate

I actually normally wouldn't enjoy this but thankfully this Mojo::Pg wrapper makes it easy. I honestly don't have any experience with the original DBD::Pg as I'm still very new to the database world so I hope this doesn't read too much like I'm lost in the sauce. First I took a look at my current tables using the psql tool:

post_text=> \d
                   List of relations
 Schema |         Name          |   Type   |   Owner
--------+-----------------------+----------+-----------
 public | mojo_migrations       | table    | post_text
 public | replies               | table    | post_text
 public | replies_reply_id_seq  | sequence | post_text
 public | threads               | table    | post_text
 public | threads_thread_id_seq | sequence | post_text
(5 rows)

post_text=> \d replies;
                                            Table "public.replies"
     Column     |           Type           | Collation | Nullable |                  Default
----------------+--------------------------+-----------+----------+-------------------------------------------
 reply_id       | integer                  |           | not null | nextval('replies_reply_id_seq'::regclass)
 thread_id      | integer                  |           |          |
 reply_date     | timestamp with time zone |           | not null | now()
 reply_author   | character varying(64)    |           |          |
 reply_body     | character varying(4096)  |           |          |
 hidden_status  | boolean                  |           | not null |
 flagged_status | boolean                  |           | not null |
Indexes:
    "replies_pkey" PRIMARY KEY, btree (reply_id)
Foreign-key constraints:
    "replies_thread_id_fkey" FOREIGN KEY (thread_id) REFERENCES threads(thread_id)

These long lines are ugly so here's a pastebin link. Essentially I need to s/reply_/remark_/g; including that sequence, index and foreign-key constraint:

-- This file is migrations/5/up.sql btw

 ALTER TABLE replies
RENAME TO remarks;

 ALTER TABLE remarks
RENAME reply_id
    TO remark_id;

 ALTER TABLE remarks
RENAME reply_date
    TO remark_date;

 ALTER TABLE remarks
RENAME reply_author
   TO remark_author;

 ALTER TABLE remarks
RENAME reply_body
    TO remark_body;

 ALTER TABLE remarks
RENAME CONSTRAINT replies_thread_id_fkey
    TO remarks_thread_id_fkey;

 ALTER INDEX replies_pkey
RENAME TO remarks_pkey;

 ALTER SEQUENCE replies_reply_id_seq
RENAME TO remarks_remark_id_seq;

I'm also going to do the exact opposite for our rolling-back pleasure:

-- This one is migrations/5/down.sql

 ALTER TABLE remarks
RENAME TO replies;

 ALTER TABLE replies
RENAME remark_id
    TO reply_id;

 ALTER TABLE replies
RENAME remark_date
    TO reply_date;

 ALTER TABLE replies
RENAME remark_author
    TO reply_author;

 ALTER TABLE replies
RENAME remark_body
    TO reply_body;

 ALTER TABLE replies
RENAME CONSTRAINT remarks_thread_id_fkey
    TO replies_thread_id_fkey;

 ALTER INDEX remarks_pkey
RENAME TO replies_pkey;

 ALTER SEQUENCE remarks_remark_id_seq
RENAME TO replies_reply_id_seq;

Idk why but I always find this step feels weird to me because it feels like I'm undoing the undo lol. But we will need it later so let's absolutely include it. Now I'm gunna see if it works...

daniel@netburst:~/git/PostText$ ./PostText.pl eval 'app->pg->migrations->from_dir("migrations")->migrate(5);'
daniel@netburst:~/git/PostText$ echo $?
0

No news is good news I guess. Let's whip out psql again and see how it looks:

post_text=> \d
                   List of relations
 Schema |         Name          |   Type   |   Owner
--------+-----------------------+----------+-----------
 public | mojo_migrations       | table    | post_text
 public | remarks               | table    | post_text
 public | remarks_remark_id_seq | sequence | post_text
 public | threads               | table    | post_text
 public | threads_thread_id_seq | sequence | post_text
(5 rows)

post_text=> \d remarks;
                                            Table "public.remarks"
     Column     |           Type           | Collation | Nullable |                  Default
----------------+--------------------------+-----------+----------+--------------------------------------------
 remark_id      | integer                  |           | not null | nextval('remarks_remark_id_seq'::regclass)
 thread_id      | integer                  |           |          |
 remark_date    | timestamp with time zone |           | not null | now()
 remark_author  | character varying(64)    |           |          |
 remark_body    | character varying(4096)  |           |          |
 hidden_status  | boolean                  |           | not null |
 flagged_status | boolean                  |           | not null |
Indexes:
    "remarks_pkey" PRIMARY KEY, btree (remark_id)
Foreign-key constraints:
    "remarks_thread_id_fkey" FOREIGN KEY (thread_id) REFERENCES threads(thread_id)

Aaaaaand the pastebin. I think we're in good shape. I'm going to migrate back for now as I still need to make some changes in the controller logic to use the new Remark model instead of my old Reply model.

daniel@netburst:~/git/PostText$ ./PostText.pl eval 'app->pg->migrations->from_dir("migrations")->migrate(4);'
daniel@netburst:~/git/PostText$ echo $?
0

I keep the migration hard-coded in the method call in the app itself just to save myself from accidentally migrating to the latest before it's ready:

# From PostText.pl
app->pg->migrations->from_dir('migrations')->migrate(4);

I know there's some reason I started doing that... I accidentally something but now I can't remember. Gunna just stick with the cargo cult and leave it be.

Next I gotta work on the aforementioned controller logic. And then moar tests.

#database
#mojolicious
#perl
#sql
#webdev