Pastes-Bin/BLOG.md

4.7 KiB

Migrations

All migrations go into a single file I'll creatively call migrations:

-- 1 up
CREATE TABLE IF NOT EXISTS pastes (
         paste_id SERIAL PRIMARY KEY,
       paste_body TEXT
       );

-- 1 down
DROP TABLE pastes;

Connect to the database and then apply the migrations:

my $dbh = DBIish.connect:
    'Pg',
    :host<devbussy.swagg.net>,
    :database<pastes_bin>,
    :user<pastes_bin>,
    password => prompt 'enter DB password: ';

my $m = DB::Migration::Simple.new:
    :$dbh,
    :migration-file<migrations>;

$m.migrate: :version<1>;

Get prompted for password for now:

$ ./bin/pastes-bin
enter DB password: hogrider69
line: -- 1 up
version: 1, direction: up
line: CREATE TABLE IF NOT EXISTS pastes (
line:          paste_id SERIAL PRIMARY KEY,
line:        paste_body TEXT
line:        );
line: -- 1 down
version: 1, direction: down
line: DROP TABLE pastes;
initializing db-migrations-simple-meta
set initial version to 0
{1 => {down => DROP TABLE pastes;
, up => CREATE TABLE IF NOT EXISTS pastes (
         paste_id SERIAL PRIMARY KEY,
       paste_body TEXT
       );
}}
migrating from version '0' to version '1'
True migrating 'up' from version '0' to version '1'
doing 'up' migrations for 1
executing CREATE TABLE IF NOT EXISTS pastes (
         paste_id SERIAL PRIMARY KEY,
       paste_body TEXT
       )
Humming-Bird listening on port http://localhost:3000

Let's check on DB:

$ psql -h devbussy.swagg.net -U pastes_bin
Password for user pastes_bin: 
psql (15.3 (Debian 15.3-0+deb12u1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

pastes_bin=> \d
                     List of relations
 Schema |           Name            |   Type   |   Owner    
--------+---------------------------+----------+------------
 public | db-migrations-simple-meta | table    | pastes_bin
 public | pastes                    | table    | pastes_bin
 public | pastes_paste_id_seq       | sequence | pastes_bin
(3 rows)

pastes_bin=> \d pastes;
                                 Table "public.pastes"
   Column   |  Type   | Collation | Nullable |                 Default                  
------------+---------+-----------+----------+------------------------------------------
 paste_id   | integer |           | not null | nextval('pastes_paste_id_seq'::regclass)
 paste_body | text    |           |          | 
Indexes:
    "pastes_pkey" PRIMARY KEY, btree (paste_id)

Some mock-up 'model' code:

use Pastes-Bin::Model::Paste;

# No routes yet just prompt to 'fake it'
my $new-paste = prompt 'enter a new paste: ';
Pastes-Bin::Model::Paste.create: $new-paste;

Now test it:

$ ./bin/pastes-bin 
enter DB password: C65VCQyp&zKsi#wKXzTLUM5V
line: -- 1 up
version: 1, direction: up
line: CREATE TABLE IF NOT EXISTS pastes (
line:          paste_id SERIAL PRIMARY KEY,
line:        paste_body TEXT
line:        );
line: -- 1 down
version: 1, direction: down
line: DROP TABLE pastes;
current-version: allrows: [[1]]
{1 => {down => DROP TABLE pastes;
, up => CREATE TABLE IF NOT EXISTS pastes (
         paste_id SERIAL PRIMARY KEY,
       paste_body TEXT
       );
}}
migrating from version '1' to version '1'
DB already at version 1
enter a new paste: testing 123...
Humming-Bird listening on port http://localhost:3000
^C

Now check the DB for the paste:

pastes_bin=> SELECT * FROM pastes;
 paste_id | paste_body 
----------+------------
(0 rows)

pastes_bin=> SELECT * FROM pastes;
 paste_id |   paste_body   
----------+----------------
        1 | testing 123...
(1 row)

End result:

use Humming-Bird::Core;
use Humming-Bird::Middleware;
use Humming-Bird::Advice;
use DB::Migration::Simple;
use DBIish;

# Local libs
use Pastes-Bin::Model::Paste;

# Logging
middleware &middleware-logger;
advice     &advice-logger;

# Database stuff
my $*dbh = DBIish.connect:
    'Pg',
    :host<devbussy.swagg.net>,
    :database<pastes_bin>,
    :user<pastes_bin>,
    password => prompt 'enter DB password: ';

my $m = DB::Migration::Simple.new:
    :$*dbh,
    :migration-file<migrations>,
    :verbose;

$m.migrate: :version<1>;

# No routes yet just prompt to 'fake it'
my $new-paste = prompt 'enter a new paste: ';
Pastes-Bin::Model::Paste.create: $new-paste;