diff --git a/.travis.yml b/.travis.yml index 13bd43d..0342075 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,13 +4,26 @@ cache: services: - postgresql + - mysql addons: postgresql: "9.6" + apt: + sources: + - mysql-5.7-trusty + packages: + - mysql-server + - mysql-client before_script: - - psql -c "CREATE DATABASE migration;" -U postgres - - psql -c "CREATE USER migration WITH PASSWORD 'migration';" -U postgres + - psql -c "CREATE DATABASE puremigration;" -U postgres + - psql -c "CREATE USER puremigration WITH PASSWORD 'puremigration';" -U postgres + +before_install: + - sudo mysql_upgrade --force + - mysql -e "CREATE DATABASE puremigration;" + - mysql -e "CREATE USER 'puremigration'@'localhost' IDENTIFIED BY 'puremigration'"; + - mysql -e "GRANT ALL PRIVILEGES ON puremigration.* TO 'puremigration'@'localhost';" language: erlang diff --git a/Makefile b/Makefile index 43954e0..6e2f308 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,13 @@ REBAR = ./rebar3 DOCKER = docker -CONTAINER_NAME = postgres-migration-test-container +CONTAINER_POSTGRES = postgres-migration-test-container +CONTAINER_MYSQL = mysql-migration-test-container all: clean code-checks test cover travis: all coveralls -local: format postgres-bounce all postgres-down +local: format db-bounce all db-down clean: $(REBAR) clean @@ -33,14 +34,34 @@ format: $(REBAR) fmt postgres-up: - $(DOCKER) run --name $(CONTAINER_NAME) \ + $(DOCKER) run --name $(CONTAINER_POSTGRES) \ -p 5432:5432 \ - -e POSTGRES_PASSWORD=migration \ - -e POSTGRES_USER=migration \ - -e POSTGRES_DB=migration \ + -e POSTGRES_PASSWORD=puremigration \ + -e POSTGRES_USER=puremigration \ + -e POSTGRES_DB=puremigration \ -d postgres:9.6-alpine postgres-down: - -$(DOCKER) rm -f $(CONTAINER_NAME) + -$(DOCKER) rm -f $(CONTAINER_POSTGRES) -postgres-bounce: postgres-down postgres-up \ No newline at end of file +mysql-up: + $(DOCKER) run --name $(CONTAINER_MYSQL) \ + -p 3306:3306 \ + -e MYSQL_ALLOW_EMPTY_PASSWORD=true \ + -e MYSQL_USER=puremigration \ + -e MYSQL_PASSWORD=puremigration \ + -e MYSQL_DATABASE=puremigration \ + -d mysql:5.7 + +mysql-wait: + while ! docker exec -it mysql-migration-test-container mysqladmin ping --silent; do \ + echo "mysql image starting, wait for 1 second..."; \ + sleep 1; \ + done; done + +mysql-down: + -$(DOCKER) rm -f $(CONTAINER_MYSQL) + +db-bounce: postgres-down mysql-down postgres-up mysql-up mysql-wait + +db-down: postgres-down mysql-down diff --git a/README.md b/README.md index eab0d25..a561788 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # Erlang ❤ pure database migrations -> Database version control engine. Effects-free. +> PostgreSQL and MySQL version control engine. Effects-free. [![Build Status](https://travis-ci.org/bearmug/erlang-pure-migrations.svg?branch=master)](https://travis-ci.org/bearmug/erlang-pure-migrations) [![Coverage Status](https://coveralls.io/repos/github/bearmug/erlang-pure-migrations/badge.svg?branch=master)](https://coveralls.io/github/bearmug/erlang-pure-migrations?branch=master) [![Hex.pm](https://img.shields.io/hexpm/v/pure_migrations.svg)](https://hex.pm/packages/pure_migrations) -Migrate your Erlang application PostgreSQL database with no effort. +Migrate your PostgreSQL or MySQL database from Erlang code with no effort. This amazing toolkit has [one and only](https://en.wikipedia.org/wiki/Unix_philosophy) purpose - consistently upgrade database schema, using Erlang stack and -plain SQL. Feel free to run it with any PostgreSQL Erlang driver (and see +plain SQL. Feel free to run it with any PostgreSQL/MySQL Erlang library (and see several ready-to-use examples below). As an extra - do this in "no side-effects" mode. @@ -26,7 +26,10 @@ several ready-to-use examples below). As an extra - do this in + [PostgreSQL and processone/p1_pgsql](#postgresql-and--processone-p1-pgsql--https---githubcom-processone-p1-pgsql-) - [Onboarding comments](#onboarding-comments-2) - [Code sample](#code-sample-2) -- [No-effects approach and tools used to achieve it](#no-effects-approach-and-tools-used-to-achieve-it) + + [MySQL and mysql-otp/mysql-otp](#mysql-and--mysql-otp-mysql-otp--https---githubcom-mysql-otp-mysql-otp-) + - [Onboarding comments](#onboarding-comments-3) + - [Code sample](#code-sample-3) +- ["No-effects" approach and tools used to achieve it](#-no-effects--approach-and-tools-used-to-achieve-it) * [Tool #1: effects externalization](#tool--1--effects-externalization) * [Tool #2: make effects explicit](#tool--2--make-effects-explicit) - [Functional programming abstractions used](#functional-programming-abstractions-used) @@ -36,11 +39,17 @@ several ready-to-use examples below). As an extra - do this in # Current limitations * **up** transactional migration available only. No **downgrade** - or **rollback** possible. Either whole **up** migration completes OK - or failed and rolled back to the state before migration. + calls available. Either whole **up** migration completes OK + or failed and rolled back to the state before migration. + * Validated MySQL implementation obviously featured with + [**implicit commit**](https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html) + behavior, which means that truly transactional MySQL upgrades limited + in scope. At the same time you free to use another MySQL library or + have your own transaction callback, as it is proposed by [API](#quick-start). * migrations engine **deliberately isolated from any specific - database library**. This way engine user is free to choose from variety - of frameworks (see tested combinations [here](#compatibility-table)) and so on. + database library**. This way engine user is free to choose from variety + of frameworks (see tested combinations [here](#compatibility-table)) + and so on. # Quick start Just call `pure_migrations:migrate/3` (see specification [here](src/engine.erl#L9)), providing: @@ -51,8 +60,8 @@ Just call `pure_migrations:migrate/3` (see specification [here](src/engine.erl#L Migration logic is idempotent and could be executed multiple times against the same database with the same migration scripts set. Moreover, it is safe to migrate your database concurrently (as a part of nodes -startup in scalable environments, for example). Please see verified -integrations and live code snippets below. +startup in scalable environments and if you providing proper transaction +handler). Please see verified integrations and live code snippets below. ## Compatibility table All integrations validated against PostgreSQL 9.4/9.6 @@ -62,6 +71,7 @@ All integrations validated against PostgreSQL 9.4/9.6 | postgres | [epgsql/epgsql:4.2.1](https://github.com/epgsql/epgsql/releases/tag/4.2.1) | [epgsql test](test/epgsql_migrations_SUITE.erl) | postgres | [semiocast/pgsql:v26.0.2](https://github.com/semiocast/pgsql/releases/tag/v26.0.2) | [spgsql test](test/spgsql_migrations_SUITE.erl) | postgres | [processone/p1_pgsql:1.1.6](https://github.com/processone/p1_pgsql/releases/tag/1.1.6) | [p1pgsql test](test/p1pgsql_migrations_SUITE.erl) +| mysql | [mysql-otp/mysql-otp:1.4.0](https://github.com/mysql-otp/mysql-otp/releases/tag/1.4.0) | [otp_mysql test](test/otp_mysql_migrations_SUITE.erl) | postgres | any library with basic sql functional | [generic test](test/pure_migrations_SUITE.erl) ## Live integrations @@ -211,7 +221,56 @@ Also see examples from live epgsql integration tests [here](test/p1pgsql_migrations_SUITE.erl) -# No-effects approach and tools used to achieve it +### MySQL and [mysql-otp/mysql-otp](https://github.com/mysql-otp/mysql-otp) +#### Onboarding comments ++ almost no result-set parsing required +- [implicit commit](https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html) + specifics a kind an obstacle for simple and safe migration +- mysql docker tooling should be operated carefully and ensured for + proper startup before any use +#### Code sample +
+ Click to expand + + ```erlang + Conn = ?config(conn, Opts), + MigrationCall = + pure_migrations:migrate( + "scripts/folder/path", + fun(F) -> + %% no full-scope tx API available here + %% or use mysql:transaction/2, but please be aware about + %% mysql implicit transactions commit behavior + try F() of + Res -> Res + catch + _:Problem -> {rollback_unavailable, Problem} + end + end, + fun(Q) -> + case mysql:query(Conn, Q) of + {error, Details} -> {error, Details}; + {ok,[<<"version">>,<<"filename">>],[]} -> []; + {ok,[<<"version">>,<<"filename">>], Data} -> + [{V, binary_to_list(F)} || [V, F] <- Data]; + {ok,[<<"max(version)">>],[[null]]} -> -1; + {ok,[<<"max(version)">>],[[V]]} -> V; + {ok, _} -> ok; + ok -> ok + end + end), + ... + %% more preparation steps if needed + ... + %% migration call + ok = MigrationCall(), + + ``` +Also see examples from live epgsql integration tests +[here](test/otp_mysql_migrations_SUITE.erl) +
+ +# "No-effects" approach and tools used to achieve it Oh, **there is more!** Library implemented in the [way](https://en.wikipedia.org/wiki/Pure_function), that all side-effects either externalized or deferred explicitly. Reasons are quite common: diff --git a/rebar.config b/rebar.config index cb0173a..96456a3 100644 --- a/rebar.config +++ b/rebar.config @@ -4,6 +4,7 @@ {epgsql, {git, "https://github.com/epgsql/epgsql", {tag, "4.2.1"}}}, {spgsql, {git, "https://github.com/semiocast/pgsql", {tag, "v26.0.2"}}}, {p1pgsql, {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.6"}}}, + {mysqlotp, {git, "https://github.com/mysql-otp/mysql-otp", {tag, "1.4.0"}}}, {coveralls, {git, "https://github.com/markusn/coveralls-erl", {tag, "v2.0.1"}}} ]}, {eunit_opts , [verbose]}, diff --git a/src/dialect_postgres.erl b/src/db_dialect.erl similarity index 80% rename from src/dialect_postgres.erl rename to src/db_dialect.erl index 15bf272..c6c7685 100644 --- a/src/dialect_postgres.erl +++ b/src/db_dialect.erl @@ -1,6 +1,10 @@ --module(dialect_postgres). +-module(db_dialect). --export([init/0, migrations_done/0, save_migration/2, latest_existing_version/0]). +-export([ init/0 + , migrations_done/0 + , save_migration/2 + , latest_existing_version/0 + ]). init() -> "CREATE TABLE IF NOT EXISTS database_migrations_history ( diff --git a/src/pure_migrations.erl b/src/pure_migrations.erl index b8d0149..a471efb 100644 --- a/src/pure_migrations.erl +++ b/src/pure_migrations.erl @@ -14,7 +14,7 @@ F :: fun(() -> ok | error()), R :: fun(() -> ok | error()). migrate(Path, FTx, FQuery) -> - ok = FQuery(dialect_postgres:init()), + ok = FQuery(db_dialect:init()), fun() -> FTx(flatten(map( find_migrations(Path, FQuery), @@ -26,11 +26,11 @@ do_migration(Path, FQuery, {V, F}) -> compose( fun() -> file:read_file(ScriptPath) end, fun({ok, ScriptBody}) -> - ExpectedVersion = FQuery(dialect_postgres:latest_existing_version()) + 1, + ExpectedVersion = FQuery(db_dialect:latest_existing_version()) + 1, case V of ExpectedVersion -> ok = FQuery(ScriptBody), - ok = FQuery(dialect_postgres:save_migration(V, F)); + ok = FQuery(db_dialect:save_migration(V, F)); _ -> { error, unexpected_version, @@ -45,7 +45,7 @@ find_migrations(ScriptsLocation, FQuery) -> fun(Files) -> filter_script_files(Files, ScriptsLocation, FQuery) end). filter_script_files({ok, Files}, _Folder, FQuery) -> - MigrationsDone = sets:from_list(FQuery(dialect_postgres:migrations_done())), + MigrationsDone = sets:from_list(FQuery(db_dialect:migrations_done())), lists:filter( fun(N) -> not sets:is_element(N, MigrationsDone) end, lists:keysort(1, [version_and_filename(F) || F <- Files])); diff --git a/test/config/test.config b/test/config/test.config index 04811d9..7d503eb 100644 --- a/test/config/test.config +++ b/test/config/test.config @@ -1,11 +1,20 @@ -[{postgres, [{ - config, [ - {host, "localhost"}, - {port, 5432}, - {database, "migration"}, - {username, "migration"}, - {secret, "migration"}, - {timeout, 10000} - ] - }] - }]. +[ {postgres, [{ + config, [ + {host, "localhost"}, + {port, 5432}, + {database, "puremigration"}, + {username, "puremigration"}, + {secret, "puremigration"}, + {timeout, 10000} + ] + }]} +, {mysql, [{ + config, [ + {host, "localhost"}, + {port, 3306}, + {database, "puremigration"}, + {username, "puremigration"}, + {secret, "puremigration"}, + {timeout, 10000} + ] + }]}]. diff --git a/test/otp_mysql_migrations_SUITE.erl b/test/otp_mysql_migrations_SUITE.erl new file mode 100644 index 0000000..6bfc33b --- /dev/null +++ b/test/otp_mysql_migrations_SUITE.erl @@ -0,0 +1,175 @@ +-module(otp_mysql_migrations_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-compile(export_all). + +all() -> [ migrate_one_script_test + , migrate_few_scripts_test + , incremental_migration_test + , wrong_initial_version_test + , migration_gap_test + , transactional_migration_unavailable_for_mysql_test + ]. + +migrate_one_script_test(Opts) -> + Conn = ?config(conn, Opts), + PreparedCall = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "00-single-script-test"]), + otp_mysql_tx_fun(Conn), + otp_mysql_query_fun(Conn) + ), + ?assertEqual(ok, PreparedCall()), + ?assertMatch( + {ok,[<<"max(version)">>],[[0]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")). + +migrate_few_scripts_test(Opts) -> + Conn = ?config(conn, Opts), + PreparedCall = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "01-two-scripts-test"]), + otp_mysql_tx_fun(Conn), + otp_mysql_query_fun(Conn) + ), + ?assertEqual(ok, PreparedCall()), + ?assertMatch( + {ok,[<<"max(version)">>],[[1]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + ?assertMatch( + {ok,[<<"count(*)">>],[[1]]}, + mysql:query(Conn, "select count(*) from fruit where color = 'yellow'")). + +incremental_migration_test(Opts) -> + Conn = ?config(conn, Opts), + MigrationStep1 = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "00-single-script-test"]), + otp_mysql_tx_fun(Conn), otp_mysql_query_fun(Conn) + ), + MigrationStep2 = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "01-two-scripts-test"]), + otp_mysql_tx_fun(Conn), otp_mysql_query_fun(Conn) + ), + + %% assert migrations table created and nothing done + ?assertMatch( + {ok,[<<"max(version)">>],[[null]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + ?assertMatch( + {error, {1146, <<"42S02">>, <<"Table 'puremigration.fruit' doesn't exist">>}}, + mysql:query(Conn, "select count(*) from fruit")), + + %% assert step 1 migration + ok = MigrationStep1(), + ?assertMatch( + {ok,[<<"max(version)">>],[[0]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + + %% assert step 2 migration + ok =MigrationStep2(), + ?assertMatch( + {ok,[<<"max(version)">>],[[1]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + ?assertMatch( + {ok,[<<"count(*)">>],[[1]]}, + mysql:query(Conn, "select count(*) from fruit where color = 'yellow'")). + +wrong_initial_version_test(Opts) -> + Conn = ?config(conn, Opts), + PreparedCall = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "02-wrong-initial-version"]), + otp_mysql_tx_fun(Conn), + otp_mysql_query_fun(Conn) + ), + ?assertEqual( + {rollback_unavailable, {badmatch, {error, unexpected_version, {expected, 0, supplied, 20}}}}, + PreparedCall()). + +migration_gap_test(Opts) -> + Conn = ?config(conn, Opts), + MigrationStep1 = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "00-single-script-test"]), + otp_mysql_tx_fun(Conn), otp_mysql_query_fun(Conn) + ), + MigrationStep2 = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "03-migration-gap"]), + otp_mysql_tx_fun(Conn), otp_mysql_query_fun(Conn) + ), + + %% assert step 1 migration + ok = MigrationStep1(), + ?assertMatch( + {ok,[<<"max(version)">>],[[0]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + + %% assert step 2 failed migration + ?assertEqual( + {rollback_unavailable, {badmatch, {error, unexpected_version, {expected, 1, supplied, 2}}}}, + MigrationStep2()), + ?assertMatch( + {ok,[<<"max(version)">>],[[0]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + ?assertMatch( + {error, {1054, <<"42S22">>, <<"Unknown column 'color' in 'where clause'">>}}, + mysql:query(Conn, "select count(*) from fruit where color = 'yellow'")). + +transactional_migration_unavailable_for_mysql_test(Opts) -> + Conn = ?config(conn, Opts), + PreparedCall = pure_migrations:migrate( + filename:join([?config(data_dir, Opts), "04-last-migration-fail"]), + otp_mysql_tx_fun(Conn), + otp_mysql_query_fun(Conn) + ), + ?assertMatch( + {rollback_unavailable, {badmatch, {error, {_, _, _}}}}, + PreparedCall()), + %% no version values should exist into database + ?assertMatch( + {ok,[<<"max(version)">>],[[0]]}, + mysql:query(Conn, "select max(version) from database_migrations_history")), + %% no fruit table should exist into database + ?assertMatch( + {ok,[<<"count(*)">>],[[1]]}, + mysql:query(Conn, "select count(*) from fruit")). + +otp_mysql_query_fun(Conn) -> + fun(Q) -> + case mysql:query(Conn, Q) of + {error, Details} -> {error, Details}; + {ok,[<<"version">>,<<"filename">>],[]} -> []; + {ok,[<<"version">>,<<"filename">>], Data} -> + [{V, binary_to_list(F)} || [V, F] <- Data]; + {ok,[<<"max(version)">>],[[null]]} -> -1; + {ok,[<<"max(version)">>],[[V]]} -> V; + {ok, _} -> ok; + ok -> ok + end + end. + +otp_mysql_tx_fun(_Conn) -> + fun(F) -> + try F() of + Res -> Res + catch + _:Problem -> {rollback_unavailable, Problem} + end + end. + +init_per_testcase(_TestCase, Opts) -> + {ok, [{host, Host}, + {port, Port}, + {database, Database}, + {username, Username}, + {secret, Secret}, + {timeout, _Timeout}]} = application:get_env(mysql, config), + {ok, Conn} = mysql:start_link([ {host, Host} + , {port, Port} + , {user, Username} + , {password, Secret} + , {database, Database}]), + + ok = mysql:query(Conn, "DROP TABLE IF EXISTS database_migrations_history, fruit"), + [{conn, Conn}|Opts]. + +end_per_testcase(_TestCase, Opts) -> + exit(?config(conn, Opts), normal). diff --git a/test/p1pgsql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql b/test/otp_mysql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql rename to test/otp_mysql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql diff --git a/test/p1pgsql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql b/test/otp_mysql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql rename to test/otp_mysql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql diff --git a/test/otp_mysql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql b/test/otp_mysql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql new file mode 100644 index 0000000..30c954d --- /dev/null +++ b/test/otp_mysql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql @@ -0,0 +1,5 @@ +ALTER TABLE fruit + ADD COLUMN color TEXT NOT NULL; +INSERT INTO fruit (name, color) VALUES ( + 'lemon', 'yellow' +); \ No newline at end of file diff --git a/test/p1pgsql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql b/test/otp_mysql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql rename to test/otp_mysql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql diff --git a/test/p1pgsql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql b/test/otp_mysql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql rename to test/otp_mysql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql diff --git a/test/otp_mysql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql b/test/otp_mysql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql new file mode 100644 index 0000000..30c954d --- /dev/null +++ b/test/otp_mysql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql @@ -0,0 +1,5 @@ +ALTER TABLE fruit + ADD COLUMN color TEXT NOT NULL; +INSERT INTO fruit (name, color) VALUES ( + 'lemon', 'yellow' +); \ No newline at end of file diff --git a/test/p1pgsql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql b/test/otp_mysql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql rename to test/otp_mysql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql diff --git a/test/p1pgsql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql b/test/otp_mysql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql rename to test/otp_mysql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql diff --git a/test/p1pgsql_migrations_SUITE.erl b/test/p1_pgsql_migrations_SUITE.erl similarity index 99% rename from test/p1pgsql_migrations_SUITE.erl rename to test/p1_pgsql_migrations_SUITE.erl index 95a8db7..93c8fc1 100644 --- a/test/p1pgsql_migrations_SUITE.erl +++ b/test/p1_pgsql_migrations_SUITE.erl @@ -1,4 +1,4 @@ --module(p1pgsql_migrations_SUITE). +-module(p1_pgsql_migrations_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). diff --git a/test/p1_pgsql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql b/test/p1_pgsql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql new file mode 100644 index 0000000..5853b2e --- /dev/null +++ b/test/p1_pgsql_migrations_SUITE_data/00-single-script-test/00_initial_version.sql @@ -0,0 +1,7 @@ +CREATE TABLE fruit ( + id SERIAL, + name TEXT NOT NULL +); +INSERT INTO fruit (name) VALUES ( + 'apple' +); \ No newline at end of file diff --git a/test/p1_pgsql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql b/test/p1_pgsql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql new file mode 100644 index 0000000..5853b2e --- /dev/null +++ b/test/p1_pgsql_migrations_SUITE_data/01-two-scripts-test/00_initial_version.sql @@ -0,0 +1,7 @@ +CREATE TABLE fruit ( + id SERIAL, + name TEXT NOT NULL +); +INSERT INTO fruit (name) VALUES ( + 'apple' +); \ No newline at end of file diff --git a/test/p1pgsql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql b/test/p1_pgsql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql rename to test/p1_pgsql_migrations_SUITE_data/01-two-scripts-test/01_next_version.sql diff --git a/test/p1_pgsql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql b/test/p1_pgsql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql new file mode 100644 index 0000000..5853b2e --- /dev/null +++ b/test/p1_pgsql_migrations_SUITE_data/02-wrong-initial-version/20_initial_version.sql @@ -0,0 +1,7 @@ +CREATE TABLE fruit ( + id SERIAL, + name TEXT NOT NULL +); +INSERT INTO fruit (name) VALUES ( + 'apple' +); \ No newline at end of file diff --git a/test/p1_pgsql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql b/test/p1_pgsql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql new file mode 100644 index 0000000..5853b2e --- /dev/null +++ b/test/p1_pgsql_migrations_SUITE_data/03-migration-gap/00_initial_version.sql @@ -0,0 +1,7 @@ +CREATE TABLE fruit ( + id SERIAL, + name TEXT NOT NULL +); +INSERT INTO fruit (name) VALUES ( + 'apple' +); \ No newline at end of file diff --git a/test/p1pgsql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql b/test/p1_pgsql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql similarity index 100% rename from test/p1pgsql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql rename to test/p1_pgsql_migrations_SUITE_data/03-migration-gap/02_gap_version.sql diff --git a/test/p1_pgsql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql b/test/p1_pgsql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql new file mode 100644 index 0000000..5853b2e --- /dev/null +++ b/test/p1_pgsql_migrations_SUITE_data/04-last-migration-fail/00_initial_version.sql @@ -0,0 +1,7 @@ +CREATE TABLE fruit ( + id SERIAL, + name TEXT NOT NULL +); +INSERT INTO fruit (name) VALUES ( + 'apple' +); \ No newline at end of file diff --git a/test/p1_pgsql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql b/test/p1_pgsql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql new file mode 100644 index 0000000..951bb93 --- /dev/null +++ b/test/p1_pgsql_migrations_SUITE_data/04-last-migration-fail/01_faulty_migration.sql @@ -0,0 +1 @@ +GARBAGE scrip4 h3r3!@ \ No newline at end of file