diff --git a/README.md b/README.md index 659648f..00a240d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Micrate is a database migration tool written in crystal. -It is shamelessly inspired by [goose](https://bitbucket.org/liamstask/goose/). Much of the code was ported from there, so check it out. +It is inspired by [goose](https://bitbucket.org/liamstask/goose/). Some code was ported from there too, so check it out. This is still a work in progress! @@ -23,7 +23,7 @@ dependencies: github: juanedi/micrate ``` -If you need to use micrate's CLI without installing the tool (which could be convenient in a CI environment) you can create a simple script like the following: +This allows you to programatically use micrate's features. You'll see the `Micrate` module has an equivalent for every CLI command. If you need to use micrate's CLI without installing the tool (which could be convenient in a CI environment) you can create a simple script like the following: ```crystal #! /usr/bin/env crystal @@ -57,19 +57,16 @@ Comments that start with `+micrate` are interpreted by micrate when running your ```sql -- +micrate Up --- SQL in section 'Up' is executed when this migration is applied CREATE TABLE users(id INT PRIMARY KEY, email VARCHAR NOT NULL); -- +micrate Down --- SQL section 'Down' is executed when this migration is rolled back DROP TABLE users; ``` - Now run it using `micrate up`. This command will execute all pending migrations: ``` $ micrate up -micrate: migrating db, current version: 0, target: 20160524162947 +Migrating db, current version: 0, target: 20160524162947 OK 20160524162446_add_users_table.sql $ micrate dbversion # at any time you can find out the current version of the database @@ -80,11 +77,38 @@ If you ever need to roll back the last migration, you can do so by executing `mi ``` $ micrate status -micrate: status - Applied At Migration - ======================================= - 2016-05-24 16:31:07 UTC -- 20160524162446_add_users_table.sql - Pending -- 20160524163425_add_address_to_users.sql +Applied At Migration +======================================= +2016-05-24 16:31:07 UTC -- 20160524162446_add_users_table.sql +Pending -- 20160524163425_add_address_to_users.sql +``` + +If using complex statements that might contain semicolons, you must give micrate a hint on how to split the script into separate statements. You can do this with `StatementBegin` and `StatementEnd` directives: (thanks [goose](https://bitbucket.org/liamstask/goose/) for this!) + +``` +-- +micrate Up +-- +micrate StatementBegin +CREATE OR REPLACE FUNCTION histories_partition_creation( DATE, DATE ) +returns void AS $$ +DECLARE + create_query text; +BEGIN + FOR create_query IN SELECT + 'CREATE TABLE IF NOT EXISTS histories_' + || TO_CHAR( d, 'YYYY_MM' ) + || ' ( CHECK( created_at >= timestamp ''' + || TO_CHAR( d, 'YYYY-MM-DD 00:00:00' ) + || ''' AND created_at < timestamp ''' + || TO_CHAR( d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00' ) + || ''' ) ) inherits ( histories );' + FROM generate_series( $1, $2, '1 month' ) AS d + LOOP + EXECUTE create_query; + END LOOP; -- LOOP END +END; -- FUNCTION END +$$ +language plpgsql; +-- +micrate StatementEnd ``` ## Contributing diff --git a/src/micrate/migration.cr b/src/micrate/migration.cr index a9f8aed..33555ed 100644 --- a/src/micrate/migration.cr +++ b/src/micrate/migration.cr @@ -9,6 +9,10 @@ module Micrate def initialize(@version : Int64, @name : String, @source : String) end + # Algorithm ported from Goose + # + # Complex statements cannot be resolved by just splitting the script by semicolons. + # In this cases we allow using StatementBegin and StatementEnd directives as hints. def statements(direction) statements = [] of String