dbgeni 0.10.0
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 +7 -0
- data/Rakefile +29 -0
- data/bin/dbgeni +2 -0
- data/lib/dbgeni/base.rb +146 -0
- data/lib/dbgeni/base_code.rb +143 -0
- data/lib/dbgeni/blank_slate.rb +24 -0
- data/lib/dbgeni/cli.rb +96 -0
- data/lib/dbgeni/code.rb +235 -0
- data/lib/dbgeni/code_list.rb +60 -0
- data/lib/dbgeni/commands/code.rb +151 -0
- data/lib/dbgeni/commands/commands.rb +41 -0
- data/lib/dbgeni/commands/config.rb +36 -0
- data/lib/dbgeni/commands/dmls.rb +244 -0
- data/lib/dbgeni/commands/generate.rb +257 -0
- data/lib/dbgeni/commands/initialize.rb +41 -0
- data/lib/dbgeni/commands/migrations.rb +243 -0
- data/lib/dbgeni/commands/milestones.rb +52 -0
- data/lib/dbgeni/commands/new.rb +178 -0
- data/lib/dbgeni/config.rb +325 -0
- data/lib/dbgeni/connectors/connector.rb +59 -0
- data/lib/dbgeni/connectors/mysql.rb +146 -0
- data/lib/dbgeni/connectors/oracle.rb +149 -0
- data/lib/dbgeni/connectors/sqlite.rb +166 -0
- data/lib/dbgeni/connectors/sybase.rb +97 -0
- data/lib/dbgeni/dml_cli.rb +35 -0
- data/lib/dbgeni/environment.rb +161 -0
- data/lib/dbgeni/exceptions/exception.rb +69 -0
- data/lib/dbgeni/file_converter.rb +44 -0
- data/lib/dbgeni/initializers/initializer.rb +44 -0
- data/lib/dbgeni/initializers/mysql.rb +36 -0
- data/lib/dbgeni/initializers/oracle.rb +38 -0
- data/lib/dbgeni/initializers/sqlite.rb +33 -0
- data/lib/dbgeni/initializers/sybase.rb +34 -0
- data/lib/dbgeni/logger.rb +60 -0
- data/lib/dbgeni/migration.rb +302 -0
- data/lib/dbgeni/migration_cli.rb +204 -0
- data/lib/dbgeni/migration_list.rb +91 -0
- data/lib/dbgeni/migrators/migrator.rb +40 -0
- data/lib/dbgeni/migrators/migrator_interface.rb +51 -0
- data/lib/dbgeni/migrators/mysql.rb +82 -0
- data/lib/dbgeni/migrators/oracle.rb +211 -0
- data/lib/dbgeni/migrators/sqlite.rb +90 -0
- data/lib/dbgeni/migrators/sybase.rb +118 -0
- data/lib/dbgeni/plugin.rb +92 -0
- data/lib/dbgeni.rb +52 -0
- metadata +87 -0
@@ -0,0 +1,257 @@
|
|
1
|
+
def usage
|
2
|
+
puts <<-EOF
|
3
|
+
Usage:
|
4
|
+
|
5
|
+
The generate command is a helper to create appropriately named db migration
|
6
|
+
and code files.
|
7
|
+
|
8
|
+
Use --config-file to specify the config file to use. If none is specified
|
9
|
+
then a file called .dbgeni will be used if it is present in the current directory,
|
10
|
+
otherwise an error will be raised.
|
11
|
+
|
12
|
+
Usage:
|
13
|
+
dbgeni generate command parameters
|
14
|
+
|
15
|
+
The allowed commands are:
|
16
|
+
|
17
|
+
migration Generates a set of files for a new database migration. The only parameter
|
18
|
+
is a name for the migration:
|
19
|
+
dbgeni generate migration name_for_this_migration
|
20
|
+
|
21
|
+
dml_migration Generates a set of files for a new dml database migration. The only parameter
|
22
|
+
is a name for the migration:
|
23
|
+
dbgeni generate dml_migration name_for_this_migration
|
24
|
+
|
25
|
+
|
26
|
+
milestone Generates a milestone, which is like a tag on a particular migration indicating
|
27
|
+
that a migration completes a release of the application
|
28
|
+
dbgenu generate milestone name_for_milestone existing_migration_for_milestone
|
29
|
+
|
30
|
+
package Generates a pair of files for a plsql package with the given package name
|
31
|
+
dbgeni generate package my_package_name
|
32
|
+
|
33
|
+
procedure Generates a file for a stored procedure with the given procedure name
|
34
|
+
dbgeni generate procedure my_procedure_name
|
35
|
+
|
36
|
+
function Generates a file for a stored function with the given function name
|
37
|
+
dbgeni generate function my_procedure_name
|
38
|
+
|
39
|
+
trigger Generates a file for a trigger with the given trigger name
|
40
|
+
dbgeni generate trigger my_trigger_name
|
41
|
+
|
42
|
+
type Generates a file for a type definition with the given type name
|
43
|
+
dbgeni generate type my_type_name
|
44
|
+
|
45
|
+
EOF
|
46
|
+
end
|
47
|
+
|
48
|
+
if %w(-h --help).include? ARGV[0]
|
49
|
+
usage
|
50
|
+
exit(0)
|
51
|
+
end
|
52
|
+
|
53
|
+
command = ARGV.shift
|
54
|
+
name = ARGV.shift
|
55
|
+
|
56
|
+
unless name
|
57
|
+
puts "error: You must specify a name for the #{command}"
|
58
|
+
exit(1)
|
59
|
+
end
|
60
|
+
|
61
|
+
require 'fileutils'
|
62
|
+
|
63
|
+
config = DBGeni::Config.load_from_file($config_file)
|
64
|
+
|
65
|
+
case command
|
66
|
+
when 'migration', 'mig'
|
67
|
+
datestamp = Time.now.strftime('%Y%m%d%H%M')
|
68
|
+
%w(up down).each do |f|
|
69
|
+
filename = File.join(config.migration_directory, "#{datestamp}_#{f}_#{name}.sql")
|
70
|
+
puts "creating: #{filename}"
|
71
|
+
FileUtils.touch(filename)
|
72
|
+
end
|
73
|
+
when 'dml_migration', 'dml'
|
74
|
+
datestamp = Time.now.strftime('%Y%m%d%H%M')
|
75
|
+
%w(up down).each do |f|
|
76
|
+
filename = File.join(config.dml_directory, "#{datestamp}_#{f}_#{name}.sql")
|
77
|
+
puts "creating: #{filename}"
|
78
|
+
FileUtils.touch(filename)
|
79
|
+
end
|
80
|
+
when 'package', 'pkg'
|
81
|
+
filename = File.join(config.code_dir, "#{name}.pks")
|
82
|
+
if File.exists?(filename)
|
83
|
+
puts "exists: #{filename}"
|
84
|
+
else
|
85
|
+
puts "creating: #{filename}"
|
86
|
+
File.open(filename, 'w') do |f|
|
87
|
+
f.puts "create or replace package #{name}"
|
88
|
+
f.puts "as"
|
89
|
+
f.puts "begin"
|
90
|
+
f.puts ""
|
91
|
+
f.puts "end #{name};"
|
92
|
+
f.puts "/"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
filename = File.join(config.code_dir, "#{name}.pkb")
|
96
|
+
if File.exists?(filename)
|
97
|
+
puts "exists: #{filename}"
|
98
|
+
else
|
99
|
+
puts "creating: #{filename}"
|
100
|
+
File.open(filename, 'w') do |f|
|
101
|
+
f.puts "create or replace package body #{name}"
|
102
|
+
f.puts "as"
|
103
|
+
f.puts "begin"
|
104
|
+
f.puts ""
|
105
|
+
f.puts "end #{name};"
|
106
|
+
f.puts "/"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
when 'procedure', 'prc', 'proc'
|
110
|
+
filename = File.join(config.code_dir, "#{name}.prc")
|
111
|
+
if File.exists?(filename)
|
112
|
+
puts "exists: #{filename}"
|
113
|
+
else
|
114
|
+
puts "creating: #{filename}"
|
115
|
+
File.open(filename, 'w') do |f|
|
116
|
+
if config.db_type == 'oracle'
|
117
|
+
f.puts "create or replace procedure #{name}"
|
118
|
+
f.puts "as"
|
119
|
+
f.puts "begin"
|
120
|
+
f.puts " null;"
|
121
|
+
f.puts "end #{name};"
|
122
|
+
f.puts "/"
|
123
|
+
elsif config.db_type == 'mysql'
|
124
|
+
f.puts "delimiter $$"
|
125
|
+
f.puts "drop procedure if exists #{name}$$"
|
126
|
+
f.puts "create procedure #{name}()"
|
127
|
+
f.puts "begin"
|
128
|
+
f.puts "end$$"
|
129
|
+
elsif config.db_type == 'sybase'
|
130
|
+
f.puts "if exists (select 1 from sysobjects"
|
131
|
+
f.puts " where name = '#{name}'"
|
132
|
+
f.puts " and type in ('P', 'TR'))"
|
133
|
+
f.puts " drop proc #{name}"
|
134
|
+
f.puts "go"
|
135
|
+
f.puts ""
|
136
|
+
f.puts "create proc #{name}"
|
137
|
+
f.puts "as"
|
138
|
+
f.puts "return(0)"
|
139
|
+
f.puts "go"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
when 'function', 'fnc', 'func'
|
144
|
+
filename = File.join(config.code_dir, "#{name}.fnc")
|
145
|
+
if File.exists?(filename)
|
146
|
+
puts "exists: #{filename}"
|
147
|
+
else
|
148
|
+
puts "creating: #{filename}"
|
149
|
+
File.open(filename, 'w') do |f|
|
150
|
+
if config.db_type == 'oracle'
|
151
|
+
f.puts "create or replace function #{name}"
|
152
|
+
f.puts " return varchar2"
|
153
|
+
f.puts "as"
|
154
|
+
f.puts "begin"
|
155
|
+
f.puts " null;"
|
156
|
+
f.puts "end #{name};"
|
157
|
+
f.puts "/"
|
158
|
+
elsif config.db_type == 'mysql'
|
159
|
+
f.puts "delimiter $$"
|
160
|
+
f.puts "drop function if exists #{name}$$"
|
161
|
+
f.puts "create function #{name}()"
|
162
|
+
f.puts " returns varchar(10)"
|
163
|
+
f.puts "begin"
|
164
|
+
f.puts " return 'abcd';"
|
165
|
+
f.puts "end$$"
|
166
|
+
elsif config.db_type == 'sybase'
|
167
|
+
f.puts "if exists (select 1 from sysobjects"
|
168
|
+
f.puts " where name = '#{name}'"
|
169
|
+
f.puts " and type in ('P', 'TR'))"
|
170
|
+
f.puts " drop func #{name}"
|
171
|
+
f.puts "go"
|
172
|
+
f.puts ""
|
173
|
+
f.puts "create func #{name}"
|
174
|
+
f.puts " returns int"
|
175
|
+
f.puts "as"
|
176
|
+
f.puts " return(0)"
|
177
|
+
f.puts "go"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
when 'trigger', 'trg'
|
182
|
+
filename = File.join(config.code_dir, "#{name}.trg")
|
183
|
+
if File.exists?(filename)
|
184
|
+
puts "exists: #{filename}"
|
185
|
+
else
|
186
|
+
puts "creating: #{filename}"
|
187
|
+
File.open(filename, 'w') do |f|
|
188
|
+
if config.db_type == 'oracle'
|
189
|
+
f.puts "create or replace trigger #{name} before insert on TABLE"
|
190
|
+
f.puts "for each row"
|
191
|
+
f.puts "begin"
|
192
|
+
f.puts " null;"
|
193
|
+
f.puts "end;"
|
194
|
+
f.puts "/"
|
195
|
+
elsif config.db_type == 'mysql'
|
196
|
+
f.puts "delimiter $$"
|
197
|
+
f.puts "drop trigger if exists #{name}$$"
|
198
|
+
f.puts "CREATE TRIGGER #{name} BEFORE INSERT ON TABLE"
|
199
|
+
f.puts "FOR EACH ROW"
|
200
|
+
f.puts "BEGIN"
|
201
|
+
f.puts "END$$"
|
202
|
+
elsif config.db_type == 'sybase'
|
203
|
+
f.puts "if exists (select 1 from sysobjects"
|
204
|
+
f.puts " where name = '#{name}'"
|
205
|
+
f.puts " and type in ('P', 'TR'))"
|
206
|
+
f.puts " drop trigger #{name}"
|
207
|
+
f.puts "go"
|
208
|
+
f.puts ""
|
209
|
+
f.puts "create trigger #{name}"
|
210
|
+
f.puts "on MYTABLE"
|
211
|
+
f.puts "for insert, update"
|
212
|
+
f.puts ""
|
213
|
+
f.puts "go"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
when 'type', 'typ'
|
218
|
+
filename = File.join(config.code_dir, "#{name}.typ")
|
219
|
+
if File.exists?(filename)
|
220
|
+
puts "exists: #{filename}"
|
221
|
+
else
|
222
|
+
puts "creating: #{filename}"
|
223
|
+
File.open(filename, 'w') do |f|
|
224
|
+
f.puts "create or replace type #{name}"
|
225
|
+
f.puts "as"
|
226
|
+
f.puts "/"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
when 'milestone'
|
230
|
+
filename = File.join(config.migration_directory, "#{name}.milestone")
|
231
|
+
if File.exists?(filename)
|
232
|
+
puts "milestone already exists"
|
233
|
+
exit(1)
|
234
|
+
end
|
235
|
+
# The migration can be either the migration filename, or the internal :: name
|
236
|
+
migration = ARGV.shift
|
237
|
+
unless migration
|
238
|
+
puts "You must specify a migration for the milestone"
|
239
|
+
exit(1)
|
240
|
+
end
|
241
|
+
if migration =~ /::/ # internal name
|
242
|
+
migration = DBGeni::Migration.filename_from_internal_name(migration)
|
243
|
+
end
|
244
|
+
unless File.exists?(File.join(config.migration_directory, migration))
|
245
|
+
puts "The migration #{migration} does not exist"
|
246
|
+
exit(1)
|
247
|
+
end
|
248
|
+
File.open(filename, 'w') do |f|
|
249
|
+
f.puts migration
|
250
|
+
end
|
251
|
+
puts "creating: #{filename}"
|
252
|
+
else
|
253
|
+
puts "Error: #{command} is not a invalid generator"
|
254
|
+
exit(1)
|
255
|
+
end
|
256
|
+
|
257
|
+
exit(0)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
if %w(-h --help).include? ARGV[0]
|
2
|
+
puts <<-EOF
|
3
|
+
Usage: dbgeni initialize <--environment-name env_name> <--config-file path/to/config> <--username user> <--password password>
|
4
|
+
|
5
|
+
If config-file is not specified, then a file called .dbgeni in the current directory will be
|
6
|
+
used if it exists, otherwise an error will occurr
|
7
|
+
|
8
|
+
If there is more than one environment defined in the config file, then environment-name must
|
9
|
+
be specified.
|
10
|
+
|
11
|
+
-e can be used as an abbreviation for --environment-name
|
12
|
+
-c can be used as an abbreviation for --config-file
|
13
|
+
-u can be used as an abbreviation for --username
|
14
|
+
-p can be used as an abbreviation for --password
|
15
|
+
|
16
|
+
|
17
|
+
EOF
|
18
|
+
exit(0)
|
19
|
+
end
|
20
|
+
|
21
|
+
installer = $build_installer.call
|
22
|
+
|
23
|
+
begin
|
24
|
+
logger = DBGeni::Logger.instance
|
25
|
+
installer.initialize_database
|
26
|
+
logger.info "Database initialized successfully"
|
27
|
+
rescue DBGeni::DatabaseAlreadyInitialized
|
28
|
+
logger.error "The Database has already been initialized"
|
29
|
+
exit(1)
|
30
|
+
rescue DBGeni::NoInitializerForDBType
|
31
|
+
logger.error "There is no initializer for the db_type setting"
|
32
|
+
exit(1)
|
33
|
+
rescue DBGeni::NoConnectorForDBType
|
34
|
+
logger.error "There is no connector defined for the db_type setting"
|
35
|
+
exit(1)
|
36
|
+
end
|
37
|
+
|
38
|
+
exit(0)
|
39
|
+
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,243 @@
|
|
1
|
+
if %w(-h --help).include? ARGV[0]
|
2
|
+
puts <<-EOF
|
3
|
+
Usage: dbgeni migrations command <--environment-name env_name> <--config-file path/to/config> <--force> <--username user> <--password password>
|
4
|
+
|
5
|
+
If config-file is not specified, then a file called .dbgeni in the current directory will be
|
6
|
+
used if it exists, otherwise an error will occurr
|
7
|
+
|
8
|
+
If there is more than one environment defined in the config file, then environment-name must
|
9
|
+
be specified.
|
10
|
+
|
11
|
+
If --force is specified, the migration will run to completion and be marked as Completed even
|
12
|
+
if errors occur.
|
13
|
+
|
14
|
+
-e can be used as an abbreviation for --environment-name
|
15
|
+
-c can be used as an abbreviation for --config-file
|
16
|
+
-f can be used as an abbreviation for --force
|
17
|
+
-u can be used as an abbreviation for --username
|
18
|
+
-p can be used as an abbreviation for --password
|
19
|
+
|
20
|
+
|
21
|
+
Avaliable commands are:
|
22
|
+
|
23
|
+
Readonly
|
24
|
+
--------
|
25
|
+
|
26
|
+
list Prints out all available migrations
|
27
|
+
dbgeni migrations list --config-file /home/myapp/.dbgeni
|
28
|
+
|
29
|
+
applied Prints all migrations which have been applied to an environment
|
30
|
+
dbgeni migrations applied --environment-name test --config-file /home/myapp/.dbgeni
|
31
|
+
|
32
|
+
outstanding Prints all migrations which have not been applied to an environment
|
33
|
+
dbgeni migrations outstanding --environment-name test --config-file /home/myapp/.dbgeni
|
34
|
+
|
35
|
+
|
36
|
+
Destructive
|
37
|
+
-----------
|
38
|
+
|
39
|
+
apply Apply migrations to the given environment. Can specify:
|
40
|
+
|
41
|
+
all Apply all outstanding migrations
|
42
|
+
next Apply only the next migration and stop
|
43
|
+
until Apply upto and including the specified migration
|
44
|
+
specific migrations to apply
|
45
|
+
milestone Apply upto a specified milestone
|
46
|
+
|
47
|
+
dbgeni migrations apply all --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
48
|
+
dbgeni migrations apply next --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
49
|
+
dbgeni migrations apply until YYYYMMDDHHMM::Name1 --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
50
|
+
dbgeni migrations apply YYYYMMDDHHMM::Name1 YYYYMMDDHHMM::Name2 YYYYMMDDHHMM::Name3 --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
51
|
+
dbgeni migrations apply milestone release_1.0 --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
52
|
+
|
53
|
+
rollback Run the rollback script for a given migration. Can specify:
|
54
|
+
|
55
|
+
all Rollback everything that has even been applied
|
56
|
+
last Rollback the last migration applied
|
57
|
+
until Rollback from the last applied migration until and including the specified migration
|
58
|
+
specific migrations to rollback
|
59
|
+
|
60
|
+
dbgeni migrations rollback all --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
61
|
+
dbgeni migrations rollback last --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
62
|
+
dbgeni migrations rollback until YYYYMMDDHHMM::Name1 --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
63
|
+
dbgeni migrations rollback YYYYMMDDHHMM::Name1 YYYYMMDDHHMM::Name2 YYYYMMDDHHMM::Name3 --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
64
|
+
dbgeni migrations rollback milestone release_1.0 --environment-name test --config-file /home/myapp/.dbgeni <--force>
|
65
|
+
|
66
|
+
EOF
|
67
|
+
exit
|
68
|
+
end
|
69
|
+
|
70
|
+
command = ARGV.shift
|
71
|
+
|
72
|
+
installer = nil
|
73
|
+
installer = $build_installer.call
|
74
|
+
|
75
|
+
logger = DBGeni::Logger.instance
|
76
|
+
|
77
|
+
begin
|
78
|
+
case command
|
79
|
+
when 'list'
|
80
|
+
migrations = installer.migrations
|
81
|
+
if migrations.length == 0
|
82
|
+
logger.info "There are no migrations in #{installer.config.migration_directory}"
|
83
|
+
end
|
84
|
+
migrations.each do |m|
|
85
|
+
puts m.to_s
|
86
|
+
end
|
87
|
+
when 'applied'
|
88
|
+
applied = installer.applied_migrations
|
89
|
+
if applied.length == 0
|
90
|
+
logger.info "There are no applied migrations in #{installer.config.migration_directory}"
|
91
|
+
end
|
92
|
+
applied.each do |m|
|
93
|
+
puts m.to_s
|
94
|
+
end
|
95
|
+
when 'outstanding'
|
96
|
+
outstanding = installer.outstanding_migrations
|
97
|
+
if outstanding.length == 0
|
98
|
+
logger.info "There are no outstanding migrations in #{installer.config.migration_directory}"
|
99
|
+
end
|
100
|
+
outstanding.each do |m|
|
101
|
+
puts m.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
when 'apply'
|
105
|
+
sub_command = ARGV.shift
|
106
|
+
case sub_command
|
107
|
+
when 'all'
|
108
|
+
installer.apply_all_migrations($force)
|
109
|
+
when 'next'
|
110
|
+
installer.apply_next_migration($force)
|
111
|
+
when 'until', 'milestone'
|
112
|
+
migration_name = nil
|
113
|
+
if sub_command == 'milestone'
|
114
|
+
unless ARGV[0]
|
115
|
+
logger.error "A milestone must be specified"
|
116
|
+
exit(1)
|
117
|
+
end
|
118
|
+
unless File.exists? File.join(installer.config.migration_directory, "#{ARGV[0]}.milestone")
|
119
|
+
logger.error "The milestone #{ARGV[0]} does not exist"
|
120
|
+
exit(1)
|
121
|
+
end
|
122
|
+
migration_name = DBGeni::Migration.internal_name_from_filename(
|
123
|
+
DBGeni::Migration.get_milestone_migration(
|
124
|
+
installer.config.migration_directory, "#{ARGV[0]}.milestone"))
|
125
|
+
else
|
126
|
+
# a migration name needs to be the next parameter
|
127
|
+
migration_name = ARGV[0]
|
128
|
+
end
|
129
|
+
|
130
|
+
unless migration_name
|
131
|
+
logger.error "A migration name must be specified"
|
132
|
+
exit(1)
|
133
|
+
end
|
134
|
+
# and the migration needs to be in the correct format
|
135
|
+
unless migration_name =~ /^(\d{12})::/
|
136
|
+
logger.error "#{migration_name} is not a valid migration name"
|
137
|
+
exit(1)
|
138
|
+
end
|
139
|
+
installer.apply_until_migration(migration_name, $force)
|
140
|
+
when /^(\d{12})::/
|
141
|
+
# The param list are specific migration files, but in the internal format. One is
|
142
|
+
# stored in sub_command and the rest are in ARGV. Grab all params that match the
|
143
|
+
# parameter name format
|
144
|
+
files = ARGV.select{ |f| f =~ /^(\d{12})::/ }
|
145
|
+
files.unshift sub_command
|
146
|
+
installer.apply_list_of_migrations(files, $force)
|
147
|
+
else
|
148
|
+
logger.error "#{sub_command} is not a valid command"
|
149
|
+
end
|
150
|
+
|
151
|
+
when 'rollback'
|
152
|
+
sub_command = ARGV.shift
|
153
|
+
case sub_command
|
154
|
+
when 'all'
|
155
|
+
installer.rollback_all_migrations($force)
|
156
|
+
when 'last'
|
157
|
+
installer.rollback_last_migration($force)
|
158
|
+
when 'until', 'milestone'
|
159
|
+
migration_name = nil
|
160
|
+
if sub_command == 'milestone'
|
161
|
+
unless ARGV[0]
|
162
|
+
logger.error "You must specify a milestone"
|
163
|
+
exit(1)
|
164
|
+
end
|
165
|
+
unless File.exists? File.join(installer.config.migration_directory, "#{ARGV[0]}.milestone")
|
166
|
+
logger.error "The milestone #{ARGV[0]} does not exist"
|
167
|
+
exit(1)
|
168
|
+
end
|
169
|
+
migration_name = DBGeni::Migration.internal_name_from_filename(
|
170
|
+
DBGeni::Migration.get_milestone_migration(
|
171
|
+
installer.config.migration_directory, "#{ARGV[0]}.milestone"))
|
172
|
+
else
|
173
|
+
# a migration name needs to be the next parameter
|
174
|
+
migration_name = ARGV[0]
|
175
|
+
end
|
176
|
+
|
177
|
+
unless migration_name
|
178
|
+
logger.error "A migration name must be specified"
|
179
|
+
exit(1)
|
180
|
+
end
|
181
|
+
# and the migration needs to be in the correct format
|
182
|
+
unless migration_name =~ /^(\d{12})::/
|
183
|
+
logger.error "#{migration_name} is not a valid migration name"
|
184
|
+
exit(1)
|
185
|
+
end
|
186
|
+
installer.rollback_until_migration(migration_name, $force)
|
187
|
+
when /^(\d{12})::/
|
188
|
+
# The param list are specific migration files, but in the internal format. One is
|
189
|
+
# stored in sub_command and the rest are in ARGV. Grab all params that match the
|
190
|
+
# parameter name format
|
191
|
+
files = ARGV.select{ |f| f =~ /^(\d{12})::/ }
|
192
|
+
files.unshift sub_command
|
193
|
+
installer.rollback_list_of_migrations(files, $force)
|
194
|
+
# migrations = files.map {|f| DBGeni::Migration.initialize_from_internal_name(installer.config.migration_directory, f)}
|
195
|
+
# # Now attempt to run each migration ... backwards for rollback
|
196
|
+
# migrations.sort{|x,y| y.migration_file <=> x.migration_file}.each do |m|
|
197
|
+
# installer.rollback_migration(m, $force)
|
198
|
+
# end
|
199
|
+
else
|
200
|
+
logger.error "#{sub_command} is not a valid command"
|
201
|
+
end
|
202
|
+
else
|
203
|
+
logger.error "#{command} is not a valid command"
|
204
|
+
end
|
205
|
+
rescue DBGeni::NoOutstandingMigrations => e
|
206
|
+
logger.info "There are no outstanding migrations to apply"
|
207
|
+
exit(0)
|
208
|
+
rescue DBGeni::MigrationApplyFailed => e
|
209
|
+
logger.error "There was a problem #{command == 'rollback' ? 'rolling back' : 'applying' } #{e.to_s}"
|
210
|
+
exit(1)
|
211
|
+
rescue DBGeni::MigrationAlreadyApplied => e
|
212
|
+
logger.error "The migration is already applied #{e.to_s}"
|
213
|
+
exit(1)
|
214
|
+
rescue DBGeni::MigrationFileNotExist => e
|
215
|
+
logger.error "The migration file #{e.to_s} does not exist"
|
216
|
+
exit(1)
|
217
|
+
rescue DBGeni:: DatabaseNotInitialized => e
|
218
|
+
logger.error "The database needs to be initialized with the command dbgeni initialize"
|
219
|
+
exit(1)
|
220
|
+
rescue DBGeni::NoAppliedMigrations => e
|
221
|
+
logger.error "There are no applied migrations to rollback"
|
222
|
+
exit(1)
|
223
|
+
rescue DBGeni::MigrationNotApplied => e
|
224
|
+
logger.error "#{e.to_s} has not been applied so cannot be rolledback"
|
225
|
+
exit(1)
|
226
|
+
rescue DBGeni::MigrationNotOutstanding => e
|
227
|
+
logger.error "#{e.to_s} does not exist or is not outstanding"
|
228
|
+
exit(1)
|
229
|
+
rescue DBGeni::DBCLINotOnPath => e
|
230
|
+
logger.error "The command line interface for the database is not on the path (sqlite3, sqlplus)"
|
231
|
+
exit(1)
|
232
|
+
rescue DBGeni::MilestoneHasNoMigration => e
|
233
|
+
logger.error "The milestone does not contain a valid migration"
|
234
|
+
exit(1)
|
235
|
+
rescue DBGeni::PluginDirectoryNotAccessible => e
|
236
|
+
logger.error "The plugin directory specified in config is not accessable: #{e.to_s}"
|
237
|
+
exit(1)
|
238
|
+
rescue DBGeni::PluginDoesNotRespondToRun
|
239
|
+
logger.error "A pluggin was loaded that does not have a run method: #{e.to_s}"
|
240
|
+
exit(1)
|
241
|
+
end
|
242
|
+
|
243
|
+
exit(0)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
if %w(-h --help).include? ARGV[0]
|
2
|
+
puts <<-EOF
|
3
|
+
|
4
|
+
The milestone command can be used to list milestones.
|
5
|
+
|
6
|
+
Usage: dbgeni milestones command <--environment-name env_name> <--config-file path/to/config> <--force>
|
7
|
+
|
8
|
+
If config-file is not specified, then a file called .dbgeni in the current directory will be
|
9
|
+
used if it exists, otherwise an error will occurr
|
10
|
+
|
11
|
+
If there is more than one environment defined in the config file, then environment-name must
|
12
|
+
be specified.
|
13
|
+
|
14
|
+
If --force is specified, the migration will run to completion and be marked as Completed even
|
15
|
+
if errors occur.
|
16
|
+
|
17
|
+
-e can be used as an abbreviation for --environment-name
|
18
|
+
-c can be used as an abbreviation for --config-file
|
19
|
+
-f can be used as an abbreviation for --force
|
20
|
+
|
21
|
+
|
22
|
+
Avaliable commands are:
|
23
|
+
|
24
|
+
list Prints out all available milestones
|
25
|
+
dbgeni milestones list
|
26
|
+
|
27
|
+
EOF
|
28
|
+
exit(0)
|
29
|
+
end
|
30
|
+
|
31
|
+
command = ARGV.shift
|
32
|
+
|
33
|
+
installer = nil
|
34
|
+
installer = $build_installer.call
|
35
|
+
|
36
|
+
begin
|
37
|
+
case command
|
38
|
+
when 'list'
|
39
|
+
milestones = Dir.entries(installer.config.migration_directory).grep(/milestone$/)
|
40
|
+
if milestones.length == 0
|
41
|
+
puts "There are no milestones in the migrations_directory"
|
42
|
+
exit(1)
|
43
|
+
end
|
44
|
+
milestones.each do |m|
|
45
|
+
puts m.gsub(/\.milestone/, '')
|
46
|
+
end
|
47
|
+
else
|
48
|
+
puts "#{command} is an invalid command"
|
49
|
+
exit(1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|