pg_migrate 0.1.11 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- 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 -29
- 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.12"
|
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
|