pg_migrate 0.1.7 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +34 -34
- data/.gitmodules +3 -3
- data/Gemfile +9 -9
- data/Gemfile.lock +39 -39
- data/LICENSE +21 -21
- data/README.md +33 -33
- data/Rakefile +2 -2
- data/bin/pg_migrate +6 -6
- data/lib/pg_migrate/builder.rb +214 -214
- data/lib/pg_migrate/command_line.rb +242 -242
- data/lib/pg_migrate/config_parser.rb +48 -48
- data/lib/pg_migrate/manifest_reader.rb +102 -102
- data/lib/pg_migrate/migration.rb +11 -11
- data/lib/pg_migrate/migrator.rb +94 -94
- data/lib/pg_migrate/package.rb +152 -152
- data/lib/pg_migrate/package_templates/Gemfile.erb +3 -3
- data/lib/pg_migrate/package_templates/bin/migrate.rb +9 -9
- data/lib/pg_migrate/package_templates/gemspec.erb +21 -21
- data/lib/pg_migrate/package_templates/lib/gem/version.rb +3 -3
- data/lib/pg_migrate/package_templates/lib/gem.rb +12 -12
- data/lib/pg_migrate/props.rb +19 -19
- data/lib/pg_migrate/sql_reader.rb +51 -51
- data/lib/pg_migrate/templates/bootstrap.erb +175 -175
- data/lib/pg_migrate/templates/up.erb +30 -30
- data/lib/pg_migrate/util.rb +73 -73
- data/lib/pg_migrate/version.rb +3 -3
- data/lib/pg_migrate.rb +40 -40
- data/pg_migrate.gemspec +29 -28
- data/spec/database.yml +8 -8
- data/spec/pg_migrate/builder_spec.rb +113 -113
- data/spec/pg_migrate/command_line_spec.rb +53 -53
- data/spec/pg_migrate/config_parser_spec.rb +18 -18
- data/spec/pg_migrate/db_utility.rb +73 -73
- data/spec/pg_migrate/input_manifests/single_manifest/manifest +3 -3
- data/spec/pg_migrate/input_manifests/single_manifest/up/single1.sql +29 -29
- data/spec/pg_migrate/manifest_reader_spec.rb +19 -19
- data/spec/pg_migrate/migrator_spec.rb +68 -68
- data/spec/pg_migrate/package_spec.rb +38 -38
- data/spec/pg_migrate/sql_reader_spec.rb +21 -21
- data/spec/spec_helper.rb +15 -15
- metadata +5 -5
@@ -1,175 +1,175 @@
|
|
1
|
-
-- pg_migrate bootstrap
|
2
|
-
-- purpose: responsible for creating or updating pg_migration internal tables
|
3
|
-
-- when: this script should be called before every migration attempt, to be safe.
|
4
|
-
-- except: if you know you have not updated the pg_migrate tool itself,
|
5
|
-
-- and you know you have run this file at least once before on the current database,
|
6
|
-
-- then you don't have to run this again.
|
7
|
-
|
8
|
-
\set ON_ERROR_STOP 1
|
9
|
-
|
10
|
-
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
11
|
-
|
12
|
-
-- bootstrap in the pgmigrate schema namespace, if it doesn't exist
|
13
|
-
DO $$DECLARE already_exists boolean;
|
14
|
-
BEGIN
|
15
|
-
|
16
|
-
SELECT exists INTO STRICT already_exists (select * from pg_catalog.pg_namespace where nspname = 'pgmigrate');
|
17
|
-
|
18
|
-
IF NOT already_exists THEN
|
19
|
-
create schema pgmigrate;
|
20
|
-
END IF;
|
21
|
-
|
22
|
-
END$$;
|
23
|
-
|
24
|
-
|
25
|
-
CREATE OR REPLACE FUNCTION pgmigrate.bootstrap_pg_migrate() RETURNS void AS $$
|
26
|
-
DECLARE
|
27
|
-
found_pg_migrate information_schema.tables;
|
28
|
-
found_pg_migrations information_schema.tables;
|
29
|
-
|
30
|
-
BEGIN
|
31
|
-
BEGIN
|
32
|
-
SELECT * INTO STRICT found_pg_migrate FROM information_schema.tables WHERE table_name = 'pg_migrate' and table_schema = 'pgmigrate';
|
33
|
-
|
34
|
-
EXCEPTION
|
35
|
-
WHEN NO_DATA_FOUND THEN
|
36
|
-
CREATE TABLE pgmigrate.pg_migrate (id BIGSERIAL PRIMARY KEY, template_version VARCHAR(255), builder_version VARCHAR(255), migrator_version VARCHAR(255), database_version VARCHAR(1024));
|
37
|
-
CREATE INDEX pg_migrate_unique_index ON pgmigrate.pg_migrate (template_version, builder_version, migrator_version, database_version);
|
38
|
-
|
39
|
-
WHEN TOO_MANY_ROWS THEN
|
40
|
-
RAISE EXCEPTION 'Multiple pg_migrate tables. Unique key on information_schema.tables should have prevented this.';
|
41
|
-
END;
|
42
|
-
|
43
|
-
BEGIN
|
44
|
-
SELECT * INTO STRICT found_pg_migrations FROM information_schema.tables WHERE table_name = 'pg_migrations' and table_schema = 'pgmigrate';
|
45
|
-
|
46
|
-
EXCEPTION
|
47
|
-
WHEN NO_DATA_FOUND THEN
|
48
|
-
CREATE TABLE pgmigrate.pg_migrations(
|
49
|
-
name VARCHAR(255) PRIMARY KEY,
|
50
|
-
ordinal INTEGER NOT NULL,
|
51
|
-
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
52
|
-
finalized SMALLINT DEFAULT 1,
|
53
|
-
pg_migrate_id BIGINT NOT NULL REFERENCES pgmigrate.pg_migrate(id));
|
54
|
-
WHEN TOO_MANY_ROWS THEN
|
55
|
-
RAISE EXCEPTION 'Multiple pg_migrations tables. Unique key on information_schema.tables should have prevented this.';
|
56
|
-
END;
|
57
|
-
|
58
|
-
END;
|
59
|
-
$$ LANGUAGE plpgsql;
|
60
|
-
|
61
|
-
|
62
|
-
SELECT pgmigrate.bootstrap_pg_migrate();
|
63
|
-
|
64
|
-
-- verifies that the specified migration name has the expected ordinal. No exception is thrown if no migration
|
65
|
-
-- of this name exists, and no exception is thrown if the migration + ordinal pair is found on a single row.
|
66
|
-
-- Only if the migrtion is found with the wrong row is an exception thrown.
|
67
|
-
CREATE OR REPLACE FUNCTION pgmigrate.verify_against_existing_migrations(migration varchar(255), ordinal integer) RETURNS VOID AS $$
|
68
|
-
DECLARE
|
69
|
-
found_migration pgmigrate.pg_migrations;
|
70
|
-
BEGIN
|
71
|
-
BEGIN
|
72
|
-
EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration;
|
73
|
-
EXCEPTION
|
74
|
-
WHEN NO_DATA_FOUND THEN
|
75
|
-
-- if no data, then this migration is unrun. One more check remains...
|
76
|
-
-- if the last run migration's ordinal is 1 less than this one, we are ready to go.
|
77
|
-
IF coalesce((SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p), -1) <> ordinal - 1 THEN
|
78
|
-
RAISE EXCEPTION 'pg_migrate: code=missing_migration, migration=%, ordinal=%, last_ordinal=%', migration, ordinal, (SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p);
|
79
|
-
END IF;
|
80
|
-
|
81
|
-
RETURN;
|
82
|
-
WHEN TOO_MANY_ROWS THEN
|
83
|
-
-- this is certainly an odd scenario, because how could this happen unless the user dropped unique key on 'name' column?
|
84
|
-
RAISE EXCEPTION 'pg_migrate: code=pg_migrations_uniqueness_error, migration=%', migration;
|
85
|
-
END;
|
86
|
-
|
87
|
-
-- one row has been found; verify ordinal is correct
|
88
|
-
IF found_migration.ordinal <> ordinal THEN
|
89
|
-
RAISE EXCEPTION 'pg_migrate: code=incorrect_ordinal, migration=%, expected_ordinal=%, actual_ordinal', migration, ordinal, found_migration.ordinal;
|
90
|
-
END IF;
|
91
|
-
|
92
|
-
END;
|
93
|
-
$$ LANGUAGE plpgsql;
|
94
|
-
|
95
|
-
|
96
|
-
-- checks if the current script has been executed or not, and throws an exception if so
|
97
|
-
-- callers should check for 'pg_migrate: code=migration_exists' to know whether they should quietly ignore exception.
|
98
|
-
-- psql can only do this by calling \set ON_ERROR_STOP 1 (which is done by templates already)
|
99
|
-
CREATE OR REPLACE FUNCTION pgmigrate.bypass_existing_migration(migration varchar(255)) RETURNS VOID AS $$
|
100
|
-
DECLARE
|
101
|
-
found_migration pgmigrate.pg_migrations;
|
102
|
-
BEGIN
|
103
|
-
BEGIN
|
104
|
-
EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration ;
|
105
|
-
EXCEPTION
|
106
|
-
WHEN NO_DATA_FOUND THEN
|
107
|
-
-- if no data, then success. just return with no exception thrown
|
108
|
-
RETURN;
|
109
|
-
WHEN TOO_MANY_ROWS THEN
|
110
|
-
-- this path should never happen because this same condition is already checked via 'verify_against_existing_migrations'
|
111
|
-
RAISE EXCEPTION 'pg_migrate: code=pg_migrations_uniqueness_error, migration=%', migration;
|
112
|
-
END;
|
113
|
-
|
114
|
-
RAISE EXCEPTION 'pg_migrate: code=migration_exists, migration=%', migration;
|
115
|
-
END;
|
116
|
-
$$ LANGUAGE plpgsql;
|
117
|
-
|
118
|
-
|
119
|
-
-- used to verify that the migration being applied is the same as this set or newer. While the parameter
|
120
|
-
-- today is called 'manifest_version', in reality this is just the highest ordinal from the manifest.
|
121
|
-
-- so if we find that the database has a higher ordinal than the manifest that built this migration,
|
122
|
-
-- then we can kick this out
|
123
|
-
CREATE OR REPLACE FUNCTION pgmigrate.verify_manifest_is_not_old(manifest_version INTEGER) RETURNS VOID AS $$
|
124
|
-
DECLARE
|
125
|
-
max_ordinal INTEGER;
|
126
|
-
BEGIN
|
127
|
-
EXECUTE 'SELECT max(ordinal) FROM pgmigrate.pg_migrations' INTO max_ordinal;
|
128
|
-
|
129
|
-
IF max_ordinal > manifest_version THEN
|
130
|
-
RAISE EXCEPTION 'pg_migrate: code=old_manifest, max_ordinal_in_db=%, manifest_version=%', max_ordinal, manifest_version;
|
131
|
-
END IF;
|
132
|
-
END;
|
133
|
-
$$ LANGUAGE plpgsql;
|
134
|
-
|
135
|
-
|
136
|
-
-- used to mark a migration as finished
|
137
|
-
CREATE OR REPLACE FUNCTION pgmigrate.record_migration(migration varchar(255), ordinal INTEGER, template_version VARCHAR(255), builder_version VARCHAR(255)) RETURNS VOID AS $$
|
138
|
-
DECLARE
|
139
|
-
found_pg_migrate_id BIGINT;
|
140
|
-
migrator_version VARCHAR(255);
|
141
|
-
BEGIN
|
142
|
-
|
143
|
-
EXECUTE 'SELECT current_setting(''application_name'')' INTO migrator_version;
|
144
|
-
|
145
|
-
BEGIN
|
146
|
-
-- first look for existing pg_migrate row satisfying version columns
|
147
|
-
-- but if not found, create that row
|
148
|
-
-- in either case, found_pg_migrate_id will have the row id
|
149
|
-
EXECUTE 'SELECT id FROM pgmigrate.pg_migrate WHERE
|
150
|
-
template_version=$1 and builder_version=$2 and migrator_version=$3 and database_version=$4'
|
151
|
-
INTO found_pg_migrate_id USING template_version, builder_version, migrator_version, (select version());
|
152
|
-
EXCEPTION
|
153
|
-
WHEN NO_DATA_FOUND THEN
|
154
|
-
found_pg_migrate_id = NULL;
|
155
|
-
WHEN TOO_MANY_ROWS THEN
|
156
|
-
-- this path should never occur because of the multi-column index on pg_migrate
|
157
|
-
RAISE EXCEPTION 'pg_migrate: code=pg_migrate_uniqueness_error, migration=%, ordinal=%, template_version=%, builder_version=%, migrator_version=%, database_version', migration, ordinal, template_version, builder_version, migrator_version, (select version());
|
158
|
-
END;
|
159
|
-
|
160
|
-
IF found_pg_migrate_id IS NULL THEN
|
161
|
-
INSERT INTO pgmigrate.pg_migrate(id, template_version, builder_version, migrator_version, database_version)
|
162
|
-
VALUES (default, template_version, builder_version, migrator_version, (select version())) RETURNING id INTO found_pg_migrate_id;
|
163
|
-
END IF;
|
164
|
-
|
165
|
-
-- create a new record in pg_migrations table, ensuring this migration won't be run again
|
166
|
-
EXECUTE 'INSERT INTO pgmigrate.pg_migrations(name, ordinal, created, finalized, pg_migrate_id)
|
167
|
-
VALUES ($1, $2, CURRENT_TIMESTAMP, 1, $3)' USING migration, ordinal, found_pg_migrate_id;
|
168
|
-
|
169
|
-
END;
|
170
|
-
$$ LANGUAGE plpgsql;
|
171
|
-
|
172
|
-
COMMIT;
|
173
|
-
|
174
|
-
|
175
|
-
|
1
|
+
-- pg_migrate bootstrap
|
2
|
+
-- purpose: responsible for creating or updating pg_migration internal tables
|
3
|
+
-- when: this script should be called before every migration attempt, to be safe.
|
4
|
+
-- except: if you know you have not updated the pg_migrate tool itself,
|
5
|
+
-- and you know you have run this file at least once before on the current database,
|
6
|
+
-- then you don't have to run this again.
|
7
|
+
|
8
|
+
\set ON_ERROR_STOP 1
|
9
|
+
|
10
|
+
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
11
|
+
|
12
|
+
-- bootstrap in the pgmigrate schema namespace, if it doesn't exist
|
13
|
+
DO $$DECLARE already_exists boolean;
|
14
|
+
BEGIN
|
15
|
+
|
16
|
+
SELECT exists INTO STRICT already_exists (select * from pg_catalog.pg_namespace where nspname = 'pgmigrate');
|
17
|
+
|
18
|
+
IF NOT already_exists THEN
|
19
|
+
create schema pgmigrate;
|
20
|
+
END IF;
|
21
|
+
|
22
|
+
END$$;
|
23
|
+
|
24
|
+
|
25
|
+
CREATE OR REPLACE FUNCTION pgmigrate.bootstrap_pg_migrate() RETURNS void AS $$
|
26
|
+
DECLARE
|
27
|
+
found_pg_migrate information_schema.tables;
|
28
|
+
found_pg_migrations information_schema.tables;
|
29
|
+
|
30
|
+
BEGIN
|
31
|
+
BEGIN
|
32
|
+
SELECT * INTO STRICT found_pg_migrate FROM information_schema.tables WHERE table_name = 'pg_migrate' and table_schema = 'pgmigrate';
|
33
|
+
|
34
|
+
EXCEPTION
|
35
|
+
WHEN NO_DATA_FOUND THEN
|
36
|
+
CREATE TABLE pgmigrate.pg_migrate (id BIGSERIAL PRIMARY KEY, template_version VARCHAR(255), builder_version VARCHAR(255), migrator_version VARCHAR(255), database_version VARCHAR(1024));
|
37
|
+
CREATE INDEX pg_migrate_unique_index ON pgmigrate.pg_migrate (template_version, builder_version, migrator_version, database_version);
|
38
|
+
|
39
|
+
WHEN TOO_MANY_ROWS THEN
|
40
|
+
RAISE EXCEPTION 'Multiple pg_migrate tables. Unique key on information_schema.tables should have prevented this.';
|
41
|
+
END;
|
42
|
+
|
43
|
+
BEGIN
|
44
|
+
SELECT * INTO STRICT found_pg_migrations FROM information_schema.tables WHERE table_name = 'pg_migrations' and table_schema = 'pgmigrate';
|
45
|
+
|
46
|
+
EXCEPTION
|
47
|
+
WHEN NO_DATA_FOUND THEN
|
48
|
+
CREATE TABLE pgmigrate.pg_migrations(
|
49
|
+
name VARCHAR(255) PRIMARY KEY,
|
50
|
+
ordinal INTEGER NOT NULL,
|
51
|
+
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
52
|
+
finalized SMALLINT DEFAULT 1,
|
53
|
+
pg_migrate_id BIGINT NOT NULL REFERENCES pgmigrate.pg_migrate(id));
|
54
|
+
WHEN TOO_MANY_ROWS THEN
|
55
|
+
RAISE EXCEPTION 'Multiple pg_migrations tables. Unique key on information_schema.tables should have prevented this.';
|
56
|
+
END;
|
57
|
+
|
58
|
+
END;
|
59
|
+
$$ LANGUAGE plpgsql;
|
60
|
+
|
61
|
+
|
62
|
+
SELECT pgmigrate.bootstrap_pg_migrate();
|
63
|
+
|
64
|
+
-- verifies that the specified migration name has the expected ordinal. No exception is thrown if no migration
|
65
|
+
-- of this name exists, and no exception is thrown if the migration + ordinal pair is found on a single row.
|
66
|
+
-- Only if the migrtion is found with the wrong row is an exception thrown.
|
67
|
+
CREATE OR REPLACE FUNCTION pgmigrate.verify_against_existing_migrations(migration varchar(255), ordinal integer) RETURNS VOID AS $$
|
68
|
+
DECLARE
|
69
|
+
found_migration pgmigrate.pg_migrations;
|
70
|
+
BEGIN
|
71
|
+
BEGIN
|
72
|
+
EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration;
|
73
|
+
EXCEPTION
|
74
|
+
WHEN NO_DATA_FOUND THEN
|
75
|
+
-- if no data, then this migration is unrun. One more check remains...
|
76
|
+
-- if the last run migration's ordinal is 1 less than this one, we are ready to go.
|
77
|
+
IF coalesce((SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p), -1) <> ordinal - 1 THEN
|
78
|
+
RAISE EXCEPTION 'pg_migrate: code=missing_migration, migration=%, ordinal=%, last_ordinal=%', migration, ordinal, (SELECT MAX(p.ordinal) FROM pgmigrate.pg_migrations as p);
|
79
|
+
END IF;
|
80
|
+
|
81
|
+
RETURN;
|
82
|
+
WHEN TOO_MANY_ROWS THEN
|
83
|
+
-- this is certainly an odd scenario, because how could this happen unless the user dropped unique key on 'name' column?
|
84
|
+
RAISE EXCEPTION 'pg_migrate: code=pg_migrations_uniqueness_error, migration=%', migration;
|
85
|
+
END;
|
86
|
+
|
87
|
+
-- one row has been found; verify ordinal is correct
|
88
|
+
IF found_migration.ordinal <> ordinal THEN
|
89
|
+
RAISE EXCEPTION 'pg_migrate: code=incorrect_ordinal, migration=%, expected_ordinal=%, actual_ordinal', migration, ordinal, found_migration.ordinal;
|
90
|
+
END IF;
|
91
|
+
|
92
|
+
END;
|
93
|
+
$$ LANGUAGE plpgsql;
|
94
|
+
|
95
|
+
|
96
|
+
-- checks if the current script has been executed or not, and throws an exception if so
|
97
|
+
-- callers should check for 'pg_migrate: code=migration_exists' to know whether they should quietly ignore exception.
|
98
|
+
-- psql can only do this by calling \set ON_ERROR_STOP 1 (which is done by templates already)
|
99
|
+
CREATE OR REPLACE FUNCTION pgmigrate.bypass_existing_migration(migration varchar(255)) RETURNS VOID AS $$
|
100
|
+
DECLARE
|
101
|
+
found_migration pgmigrate.pg_migrations;
|
102
|
+
BEGIN
|
103
|
+
BEGIN
|
104
|
+
EXECUTE 'SELECT * FROM pgmigrate.pg_migrations WHERE name=$1' INTO STRICT found_migration USING migration ;
|
105
|
+
EXCEPTION
|
106
|
+
WHEN NO_DATA_FOUND THEN
|
107
|
+
-- if no data, then success. just return with no exception thrown
|
108
|
+
RETURN;
|
109
|
+
WHEN TOO_MANY_ROWS THEN
|
110
|
+
-- this path should never happen because this same condition is already checked via 'verify_against_existing_migrations'
|
111
|
+
RAISE EXCEPTION 'pg_migrate: code=pg_migrations_uniqueness_error, migration=%', migration;
|
112
|
+
END;
|
113
|
+
|
114
|
+
RAISE EXCEPTION 'pg_migrate: code=migration_exists, migration=%', migration;
|
115
|
+
END;
|
116
|
+
$$ LANGUAGE plpgsql;
|
117
|
+
|
118
|
+
|
119
|
+
-- used to verify that the migration being applied is the same as this set or newer. While the parameter
|
120
|
+
-- today is called 'manifest_version', in reality this is just the highest ordinal from the manifest.
|
121
|
+
-- so if we find that the database has a higher ordinal than the manifest that built this migration,
|
122
|
+
-- then we can kick this out
|
123
|
+
CREATE OR REPLACE FUNCTION pgmigrate.verify_manifest_is_not_old(manifest_version INTEGER) RETURNS VOID AS $$
|
124
|
+
DECLARE
|
125
|
+
max_ordinal INTEGER;
|
126
|
+
BEGIN
|
127
|
+
EXECUTE 'SELECT max(ordinal) FROM pgmigrate.pg_migrations' INTO max_ordinal;
|
128
|
+
|
129
|
+
IF max_ordinal > manifest_version THEN
|
130
|
+
RAISE EXCEPTION 'pg_migrate: code=old_manifest, max_ordinal_in_db=%, manifest_version=%', max_ordinal, manifest_version;
|
131
|
+
END IF;
|
132
|
+
END;
|
133
|
+
$$ LANGUAGE plpgsql;
|
134
|
+
|
135
|
+
|
136
|
+
-- used to mark a migration as finished
|
137
|
+
CREATE OR REPLACE FUNCTION pgmigrate.record_migration(migration varchar(255), ordinal INTEGER, template_version VARCHAR(255), builder_version VARCHAR(255)) RETURNS VOID AS $$
|
138
|
+
DECLARE
|
139
|
+
found_pg_migrate_id BIGINT;
|
140
|
+
migrator_version VARCHAR(255);
|
141
|
+
BEGIN
|
142
|
+
|
143
|
+
EXECUTE 'SELECT current_setting(''application_name'')' INTO migrator_version;
|
144
|
+
|
145
|
+
BEGIN
|
146
|
+
-- first look for existing pg_migrate row satisfying version columns
|
147
|
+
-- but if not found, create that row
|
148
|
+
-- in either case, found_pg_migrate_id will have the row id
|
149
|
+
EXECUTE 'SELECT id FROM pgmigrate.pg_migrate WHERE
|
150
|
+
template_version=$1 and builder_version=$2 and migrator_version=$3 and database_version=$4'
|
151
|
+
INTO found_pg_migrate_id USING template_version, builder_version, migrator_version, (select version());
|
152
|
+
EXCEPTION
|
153
|
+
WHEN NO_DATA_FOUND THEN
|
154
|
+
found_pg_migrate_id = NULL;
|
155
|
+
WHEN TOO_MANY_ROWS THEN
|
156
|
+
-- this path should never occur because of the multi-column index on pg_migrate
|
157
|
+
RAISE EXCEPTION 'pg_migrate: code=pg_migrate_uniqueness_error, migration=%, ordinal=%, template_version=%, builder_version=%, migrator_version=%, database_version', migration, ordinal, template_version, builder_version, migrator_version, (select version());
|
158
|
+
END;
|
159
|
+
|
160
|
+
IF found_pg_migrate_id IS NULL THEN
|
161
|
+
INSERT INTO pgmigrate.pg_migrate(id, template_version, builder_version, migrator_version, database_version)
|
162
|
+
VALUES (default, template_version, builder_version, migrator_version, (select version())) RETURNING id INTO found_pg_migrate_id;
|
163
|
+
END IF;
|
164
|
+
|
165
|
+
-- create a new record in pg_migrations table, ensuring this migration won't be run again
|
166
|
+
EXECUTE 'INSERT INTO pgmigrate.pg_migrations(name, ordinal, created, finalized, pg_migrate_id)
|
167
|
+
VALUES ($1, $2, CURRENT_TIMESTAMP, 1, $3)' USING migration, ordinal, found_pg_migrate_id;
|
168
|
+
|
169
|
+
END;
|
170
|
+
$$ LANGUAGE plpgsql;
|
171
|
+
|
172
|
+
COMMIT;
|
173
|
+
|
174
|
+
|
175
|
+
|
@@ -1,30 +1,30 @@
|
|
1
|
-
-- beginning pg_migrate header, migration=<%= migration_def.name %>
|
2
|
-
\set ON_ERROR_STOP 1
|
3
|
-
|
4
|
-
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
5
|
-
|
6
|
-
-- we want to ensure no one else is running this migration concurrently
|
7
|
-
LOCK TABLE pgmigrate.pg_migrations IN ACCESS EXCLUSIVE MODE;
|
8
|
-
|
9
|
-
SELECT pgmigrate.verify_manifest_is_not_old(<%= manifest_version %>);
|
10
|
-
|
11
|
-
SELECT pgmigrate.verify_against_existing_migrations('<%= migration_def.name %>', <%= migration_def.ordinal %>);
|
12
|
-
|
13
|
-
-- to allow exception in CHECK_IF_MIGRATED to cause rollback, not failure
|
14
|
-
\set ON_ERROR_STOP 0
|
15
|
-
|
16
|
-
SELECT pgmigrate.bypass_existing_migration('<%= migration_def.name %>');
|
17
|
-
|
18
|
-
-- if the content of the migration is bad, we want psql to stop.
|
19
|
-
\set ON_ERROR_STOP 1
|
20
|
-
|
21
|
-
-- beginning user sql, migration=<%= migration_def.name %>
|
22
|
-
|
23
|
-
<%= migration_content %>
|
24
|
-
|
25
|
-
-- beginning pg_migrate footer, migration=<%= migration_def.name %>
|
26
|
-
|
27
|
-
SELECT pgmigrate.record_migration('<%= migration_def.name %>', <%= migration_def.ordinal %>, '0.1.0', '<%= builder_version %>');
|
28
|
-
|
29
|
-
COMMIT;
|
30
|
-
-- end pg_migrate migration, migration=<%= migration_def.name %>
|
1
|
+
-- beginning pg_migrate header, migration=<%= migration_def.name %>
|
2
|
+
\set ON_ERROR_STOP 1
|
3
|
+
|
4
|
+
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
5
|
+
|
6
|
+
-- we want to ensure no one else is running this migration concurrently
|
7
|
+
LOCK TABLE pgmigrate.pg_migrations IN ACCESS EXCLUSIVE MODE;
|
8
|
+
|
9
|
+
SELECT pgmigrate.verify_manifest_is_not_old(<%= manifest_version %>);
|
10
|
+
|
11
|
+
SELECT pgmigrate.verify_against_existing_migrations('<%= migration_def.name %>', <%= migration_def.ordinal %>);
|
12
|
+
|
13
|
+
-- to allow exception in CHECK_IF_MIGRATED to cause rollback, not failure
|
14
|
+
\set ON_ERROR_STOP 0
|
15
|
+
|
16
|
+
SELECT pgmigrate.bypass_existing_migration('<%= migration_def.name %>');
|
17
|
+
|
18
|
+
-- if the content of the migration is bad, we want psql to stop.
|
19
|
+
\set ON_ERROR_STOP 1
|
20
|
+
|
21
|
+
-- beginning user sql, migration=<%= migration_def.name %>
|
22
|
+
|
23
|
+
<%= migration_content %>
|
24
|
+
|
25
|
+
-- beginning pg_migrate footer, migration=<%= migration_def.name %>
|
26
|
+
|
27
|
+
SELECT pgmigrate.record_migration('<%= migration_def.name %>', <%= migration_def.ordinal %>, '0.1.0', '<%= builder_version %>');
|
28
|
+
|
29
|
+
COMMIT;
|
30
|
+
-- end pg_migrate migration, migration=<%= migration_def.name %>
|
data/lib/pg_migrate/util.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
|
-
module PgMigrate
|
2
|
-
|
3
|
-
class Util
|
4
|
-
|
5
|
-
LOGGER = Logging.logger[self]
|
6
|
-
|
7
|
-
# recommended to create all connections via this method,
|
8
|
-
# so that we can put NOTICE/CONTEXT into logger instead of stderr
|
9
|
-
def self.create_conn(args)
|
10
|
-
conn = PG::Connection.open(args)
|
11
|
-
conn.set_notice_receiver do |result|
|
12
|
-
#result.res_status(result.result_status)
|
13
|
-
LOGGER.debug result.error_message
|
14
|
-
end
|
15
|
-
return conn
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.get_conn(connection_options)
|
19
|
-
if !connection_options[:pgconn].nil?
|
20
|
-
return connection_options[:pgconn]
|
21
|
-
elsif !connection_options[:connstring].nil?
|
22
|
-
create_conn(connection_options[:connstring])
|
23
|
-
elsif !connection_options[:connopts].nil?
|
24
|
-
return create_conn(connection_options[:connopts])
|
25
|
-
else
|
26
|
-
return create_conn(connection_options)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# the 'out-of-band' conn is a connection to a database that you aren't
|
31
|
-
# interested in modifying; it's basically a landing pad so that you can do:
|
32
|
-
# DROP DATABSE BLAH; CREATE DATABASE BLAH -- for testing
|
33
|
-
def self.get_oob_conn(connection_options)
|
34
|
-
|
35
|
-
if !connection_options[:oob_pgconn].nil?
|
36
|
-
return connection_options[:oob_pgconn]
|
37
|
-
elsif !connection_options[:oob_connstring].nil?
|
38
|
-
return create_conn(connection_options[:oob_connstring])
|
39
|
-
elsif !connection_options[:oob_connopts].nil?
|
40
|
-
return create_conn(connection_options[:oob_connopts])
|
41
|
-
else
|
42
|
-
return create_conn(connection_options)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# finds dbname from connection_options
|
47
|
-
def self.get_db_name(connection_options)
|
48
|
-
dbname = nil
|
49
|
-
if !connection_options[:pgconn].nil?
|
50
|
-
dbname = connection_options[:pgconn].db
|
51
|
-
elsif !connection_options[:connstring].nil?
|
52
|
-
connstring = connection_options[:connstring]
|
53
|
-
bits = connstring.split(" ")
|
54
|
-
bits.each do |bit|
|
55
|
-
if bit.start_with? "dbname="
|
56
|
-
dbname = bit["dbname=".length..-1]
|
57
|
-
break
|
58
|
-
end
|
59
|
-
end
|
60
|
-
elsif !connection_options[:connopts].nil?
|
61
|
-
dbname = connection_options[:connopts]["dbname"]
|
62
|
-
else
|
63
|
-
dbname = connection_options["dbname"]
|
64
|
-
end
|
65
|
-
|
66
|
-
if dbname.nil?
|
67
|
-
raise "db name is null. tried finding dbname in #{connection_options.inspect}"
|
68
|
-
end
|
69
|
-
|
70
|
-
return dbname
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
1
|
+
module PgMigrate
|
2
|
+
|
3
|
+
class Util
|
4
|
+
|
5
|
+
LOGGER = Logging.logger[self]
|
6
|
+
|
7
|
+
# recommended to create all connections via this method,
|
8
|
+
# so that we can put NOTICE/CONTEXT into logger instead of stderr
|
9
|
+
def self.create_conn(args)
|
10
|
+
conn = PG::Connection.open(args)
|
11
|
+
conn.set_notice_receiver do |result|
|
12
|
+
#result.res_status(result.result_status)
|
13
|
+
LOGGER.debug result.error_message
|
14
|
+
end
|
15
|
+
return conn
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get_conn(connection_options)
|
19
|
+
if !connection_options[:pgconn].nil?
|
20
|
+
return connection_options[:pgconn]
|
21
|
+
elsif !connection_options[:connstring].nil?
|
22
|
+
create_conn(connection_options[:connstring])
|
23
|
+
elsif !connection_options[:connopts].nil?
|
24
|
+
return create_conn(connection_options[:connopts])
|
25
|
+
else
|
26
|
+
return create_conn(connection_options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# the 'out-of-band' conn is a connection to a database that you aren't
|
31
|
+
# interested in modifying; it's basically a landing pad so that you can do:
|
32
|
+
# DROP DATABSE BLAH; CREATE DATABASE BLAH -- for testing
|
33
|
+
def self.get_oob_conn(connection_options)
|
34
|
+
|
35
|
+
if !connection_options[:oob_pgconn].nil?
|
36
|
+
return connection_options[:oob_pgconn]
|
37
|
+
elsif !connection_options[:oob_connstring].nil?
|
38
|
+
return create_conn(connection_options[:oob_connstring])
|
39
|
+
elsif !connection_options[:oob_connopts].nil?
|
40
|
+
return create_conn(connection_options[:oob_connopts])
|
41
|
+
else
|
42
|
+
return create_conn(connection_options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# finds dbname from connection_options
|
47
|
+
def self.get_db_name(connection_options)
|
48
|
+
dbname = nil
|
49
|
+
if !connection_options[:pgconn].nil?
|
50
|
+
dbname = connection_options[:pgconn].db
|
51
|
+
elsif !connection_options[:connstring].nil?
|
52
|
+
connstring = connection_options[:connstring]
|
53
|
+
bits = connstring.split(" ")
|
54
|
+
bits.each do |bit|
|
55
|
+
if bit.start_with? "dbname="
|
56
|
+
dbname = bit["dbname=".length..-1]
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
elsif !connection_options[:connopts].nil?
|
61
|
+
dbname = connection_options[:connopts]["dbname"]
|
62
|
+
else
|
63
|
+
dbname = connection_options["dbname"]
|
64
|
+
end
|
65
|
+
|
66
|
+
if dbname.nil?
|
67
|
+
raise "db name is null. tried finding dbname in #{connection_options.inspect}"
|
68
|
+
end
|
69
|
+
|
70
|
+
return dbname
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/pg_migrate/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module PgMigrate
|
2
|
-
VERSION = "0.1.
|
3
|
-
end
|
1
|
+
module PgMigrate
|
2
|
+
VERSION = "0.1.11"
|
3
|
+
end
|
data/lib/pg_migrate.rb
CHANGED
@@ -1,40 +1,40 @@
|
|
1
|
-
require 'logging'
|
2
|
-
require 'pg'
|
3
|
-
require 'thor'
|
4
|
-
require "pg_migrate/version"
|
5
|
-
require "pg_migrate/props"
|
6
|
-
require "pg_migrate/migration"
|
7
|
-
require "pg_migrate/sql_reader"
|
8
|
-
require "pg_migrate/manifest_reader"
|
9
|
-
require "pg_migrate/migrator"
|
10
|
-
require "pg_migrate/config_parser"
|
11
|
-
require "pg_migrate/builder"
|
12
|
-
require "pg_migrate/package"
|
13
|
-
require "pg_migrate/command_line"
|
14
|
-
require "pg_migrate/util"
|
15
|
-
|
16
|
-
# name of the manifest file
|
17
|
-
MANIFEST_FILENAME = 'manifest'
|
18
|
-
# name of the 'forward' migration folder
|
19
|
-
UP_DIRNAME = 'up'
|
20
|
-
# name of the 'backwards' migration folder
|
21
|
-
DOWN_DIRNAME = 'down'
|
22
|
-
# name of the 'test' migration folder
|
23
|
-
TESTDIRNAME = 'test'
|
24
|
-
# name of the bootstrap.sql file
|
25
|
-
BOOTSTRAP_FILENAME = "bootstrap.sql"
|
26
|
-
# built manifest version header
|
27
|
-
BUILDER_VERSION_HEADER ="# pg_migrate-"
|
28
|
-
# name of project configuration defaults
|
29
|
-
PG_CONFIG ='.pg_migrate'
|
30
|
-
|
31
|
-
|
32
|
-
### SQL CONSTANTS ###
|
33
|
-
PG_MIGRATE_TABLE = "pg_migrate"
|
34
|
-
PG_MIGRATIONS_TABLE = "pg_migrations"
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
module PgMigrate
|
39
|
-
# Your code goes here...
|
40
|
-
end
|
1
|
+
require 'logging'
|
2
|
+
require 'pg'
|
3
|
+
require 'thor'
|
4
|
+
require "pg_migrate/version"
|
5
|
+
require "pg_migrate/props"
|
6
|
+
require "pg_migrate/migration"
|
7
|
+
require "pg_migrate/sql_reader"
|
8
|
+
require "pg_migrate/manifest_reader"
|
9
|
+
require "pg_migrate/migrator"
|
10
|
+
require "pg_migrate/config_parser"
|
11
|
+
require "pg_migrate/builder"
|
12
|
+
require "pg_migrate/package"
|
13
|
+
require "pg_migrate/command_line"
|
14
|
+
require "pg_migrate/util"
|
15
|
+
|
16
|
+
# name of the manifest file
|
17
|
+
MANIFEST_FILENAME = 'manifest'
|
18
|
+
# name of the 'forward' migration folder
|
19
|
+
UP_DIRNAME = 'up'
|
20
|
+
# name of the 'backwards' migration folder
|
21
|
+
DOWN_DIRNAME = 'down'
|
22
|
+
# name of the 'test' migration folder
|
23
|
+
TESTDIRNAME = 'test'
|
24
|
+
# name of the bootstrap.sql file
|
25
|
+
BOOTSTRAP_FILENAME = "bootstrap.sql"
|
26
|
+
# built manifest version header
|
27
|
+
BUILDER_VERSION_HEADER ="# pg_migrate-"
|
28
|
+
# name of project configuration defaults
|
29
|
+
PG_CONFIG ='.pg_migrate'
|
30
|
+
|
31
|
+
|
32
|
+
### SQL CONSTANTS ###
|
33
|
+
PG_MIGRATE_TABLE = "pg_migrate"
|
34
|
+
PG_MIGRATIONS_TABLE = "pg_migrations"
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
module PgMigrate
|
39
|
+
# Your code goes here...
|
40
|
+
end
|