sql_migrations 2.2.1 → 2.4.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 +4 -4
- data/.rubocop.yml +2 -0
- data/README.md +10 -17
- data/Rakefile +1 -1
- data/lib/sql_migrations.rb +23 -39
- data/lib/sql_migrations/config.rb +46 -41
- data/lib/sql_migrations/database.rb +14 -22
- data/lib/sql_migrations/file.rb +67 -0
- data/lib/sql_migrations/migration.rb +1 -5
- data/lib/sql_migrations/script.rb +93 -0
- data/lib/sql_migrations/seed.rb +1 -5
- data/lib/sql_migrations/tasks/{list.rake → scripts.rake} +3 -3
- data/lib/sql_migrations/version.rb +1 -1
- data/spec/features/config_spec.rb +1 -1
- data/spec/features/{schema_table_spec.rb → history_table_spec.rb} +3 -3
- data/spec/features/migration_order_spec.rb +1 -1
- data/spec/features/migration_spec.rb +25 -6
- data/spec/features/scripts_spec.rb +71 -0
- data/spec/features/seed_spec.rb +2 -2
- data/spec/spec_helper.rb +5 -5
- data/sql_migrations.gemspec +2 -2
- metadata +13 -17
- data/lib/sql_migrations/fixture.rb +0 -13
- data/lib/sql_migrations/script_file.rb +0 -59
- data/lib/sql_migrations/sql_script.rb +0 -70
- data/lib/sql_migrations/tasks/seed_test.rake +0 -10
- data/spec/features/fixture_spec.rb +0 -22
- data/spec/features/sql_scripts_spec.rb +0 -47
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4cd2f64f3d6c5864d8a53ee00437de877d31c07d
|
|
4
|
+
data.tar.gz: 3975b9223a91de17766cb2deb74c733de7717422
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e24cc1c8994f34a3c6238a6a7b838a405e4f21c92964671c3b6554d774663df12a140125bc17214d4623aef2da55588c3b814ebe910208424dc11fd2b391701c
|
|
7
|
+
data.tar.gz: 840fa00ad8010e4c9911328a05d53287660f3f7266598b5e91278eb215c9fea651ec928da23fdb04728766edf24bf848be225e8abc8c3ad8b80bf5016f08422a
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
Simple standalone migrations you can use with plain SQL.
|
|
7
7
|
|
|
8
|
-
This gives you possibility to execute migrations, seed datebase (on production and in test environment
|
|
8
|
+
This gives you possibility to execute migrations, seed datebase (on production and in test environment) in non-Ruby projects.
|
|
9
9
|
`sql-migrations` can work with multiple different databases, and support many db adapters.
|
|
10
10
|
|
|
11
11
|
## Why ?
|
|
@@ -105,14 +105,14 @@ For example, if you work on old Zend 1 project, and you want to take benefit fro
|
|
|
105
105
|
If you have multi-statement migrations you should provide `separator` configuration variable in `options` block. `options` key is optional in YAML.
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
4. Migrations/seeds
|
|
108
|
+
4. Migrations/seeds can be executed using rake tasks. So you will need to create `Rakefile`:
|
|
109
109
|
|
|
110
110
|
```ruby
|
|
111
111
|
require 'bundler'
|
|
112
112
|
Bundler.require
|
|
113
113
|
|
|
114
114
|
SqlMigrations::Config.load!('db/config/databases.yml')
|
|
115
|
-
SqlMigrations.load_tasks
|
|
115
|
+
SqlMigrations.load_tasks!
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
You can also create Rake tasks by yourself:
|
|
@@ -147,22 +147,19 @@ For example, if you work on old Zend 1 project, and you want to take benefit fro
|
|
|
147
147
|
|
|
148
148
|
## Usage
|
|
149
149
|
|
|
150
|
-
1. Valid migration/seeds
|
|
150
|
+
1. Valid migration/seeds file names match against regexp `/(\d{8})_(\d{6})_(.*)?\.sql/`. So valid filenames would be:
|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
20150303_180100_test_migration.sql
|
|
154
154
|
20150303_180100_whatever_description_of_seed.sql
|
|
155
|
-
20150303_180100_fixture1.sql
|
|
156
155
|
|
|
157
156
|
You can put plain SQL into that files.
|
|
158
157
|
|
|
159
|
-
2. It is possible to create migration files
|
|
158
|
+
2. It is possible to create migration files and seed files inside following directory structure:
|
|
160
159
|
|
|
161
160
|
db/
|
|
162
161
|
migrations/
|
|
163
162
|
20150303_180100_test_migration.sql
|
|
164
|
-
fixtures/
|
|
165
|
-
20150303_180100_fixture1.sql
|
|
166
163
|
seeds/
|
|
167
164
|
20150303_180100_whatever_description_of_seed.sql
|
|
168
165
|
|
|
@@ -172,14 +169,11 @@ For example, if you work on old Zend 1 project, and you want to take benefit fro
|
|
|
172
169
|
migrations/
|
|
173
170
|
default/
|
|
174
171
|
second_db/
|
|
175
|
-
fixtures/
|
|
176
|
-
default/
|
|
177
|
-
second_db/
|
|
178
172
|
seeds/
|
|
179
173
|
default/
|
|
180
174
|
second_db/
|
|
181
175
|
|
|
182
|
-
`default/` directory is optional, you can put migrations/seed data
|
|
176
|
+
`default/` directory is optional, you can put migrations/seed data for default database in base directories:
|
|
183
177
|
|
|
184
178
|
db/
|
|
185
179
|
migrations/
|
|
@@ -197,8 +191,7 @@ For example, if you work on old Zend 1 project, and you want to take benefit fro
|
|
|
197
191
|
|
|
198
192
|
rake sqlmigrations:db:migrate # Run migrations
|
|
199
193
|
rake sqlmigrations:db:seed # Seed database
|
|
200
|
-
rake sqlmigrations:db:
|
|
201
|
-
rake sqlmigrations:files:list # List found migration and seed files
|
|
194
|
+
rake sqlmigrations:db:scripts # List all scripts found
|
|
202
195
|
|
|
203
196
|
|
|
204
197
|
5. Then, run tasks:
|
|
@@ -210,15 +203,15 @@ For example, if you work on old Zend 1 project, and you want to take benefit fro
|
|
|
210
203
|
# this will seed database with initial data
|
|
211
204
|
rake sqlmigrations:db:seed
|
|
212
205
|
|
|
213
|
-
# this will list all migrations/seed files
|
|
214
|
-
rake sqlmigration:
|
|
206
|
+
# this will list all migrations/seed files that where found
|
|
207
|
+
rake sqlmigration:db:scripts
|
|
215
208
|
|
|
216
209
|
6. Environment variables
|
|
217
210
|
|
|
218
211
|
If you want to run migration on different database (for example test) specify ENV:
|
|
219
212
|
|
|
220
213
|
ENV=test rake sqlmigrations:db:migrate
|
|
221
|
-
ENV=test rake sqlmigrations:db:
|
|
214
|
+
ENV=test rake sqlmigrations:db:seed
|
|
222
215
|
|
|
223
216
|
or in production:
|
|
224
217
|
|
data/Rakefile
CHANGED
data/lib/sql_migrations.rb
CHANGED
|
@@ -1,57 +1,41 @@
|
|
|
1
|
-
require 'sequel'
|
|
2
|
-
require 'yaml'
|
|
3
|
-
require 'find'
|
|
4
|
-
require 'benchmark'
|
|
5
|
-
require 'time'
|
|
6
|
-
require 'erb'
|
|
7
|
-
|
|
8
1
|
require 'sql_migrations/version'
|
|
9
2
|
require 'sql_migrations/database'
|
|
10
3
|
require 'sql_migrations/config'
|
|
11
|
-
require 'sql_migrations/
|
|
12
|
-
require 'sql_migrations/
|
|
4
|
+
require 'sql_migrations/file'
|
|
5
|
+
require 'sql_migrations/script'
|
|
13
6
|
require 'sql_migrations/migration'
|
|
14
7
|
require 'sql_migrations/seed'
|
|
15
|
-
require 'sql_migrations/fixture'
|
|
16
8
|
|
|
17
9
|
# SqlMigrations
|
|
18
10
|
#
|
|
19
11
|
module SqlMigrations
|
|
20
|
-
|
|
21
|
-
def load_tasks
|
|
22
|
-
load 'sql_migrations/tasks/migrate.rake'
|
|
23
|
-
load 'sql_migrations/tasks/seed.rake'
|
|
24
|
-
load 'sql_migrations/tasks/seed_test.rake'
|
|
25
|
-
load 'sql_migrations/tasks/list.rake'
|
|
26
|
-
end
|
|
12
|
+
extend self
|
|
27
13
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
def migrate
|
|
15
|
+
databases(&:migrate)
|
|
16
|
+
end
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
def seed
|
|
19
|
+
databases(&:seed)
|
|
20
|
+
end
|
|
35
21
|
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
def scripts
|
|
23
|
+
Config.databases.each do |name, _config|
|
|
24
|
+
Migration.find(name).each { |migration| puts migration }
|
|
25
|
+
Seed.find(name).each { |seed| puts seed }
|
|
38
26
|
end
|
|
27
|
+
end
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Fixture.find(name).each { |fixture| puts fixture }
|
|
45
|
-
end
|
|
29
|
+
def databases
|
|
30
|
+
Config.databases.each do |name, config|
|
|
31
|
+
db = Database.new(name, config)
|
|
32
|
+
yield db if block_given?
|
|
46
33
|
end
|
|
34
|
+
end
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
db = Database.new(name, config)
|
|
53
|
-
yield db
|
|
54
|
-
end
|
|
55
|
-
end
|
|
36
|
+
def load_tasks!
|
|
37
|
+
load 'sql_migrations/tasks/migrate.rake'
|
|
38
|
+
load 'sql_migrations/tasks/seed.rake'
|
|
39
|
+
load 'sql_migrations/tasks/scripts.rake'
|
|
56
40
|
end
|
|
57
41
|
end
|
|
@@ -1,54 +1,59 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'erb'
|
|
3
|
+
|
|
1
4
|
module SqlMigrations
|
|
2
|
-
# Configuration
|
|
5
|
+
# Configuration module
|
|
3
6
|
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
7
|
+
module Config
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
def load!(config_file, env = nil)
|
|
11
|
+
@env = (env || ENV['ENV'] || ENV['RAKE_ENV'] || :development).to_sym
|
|
12
|
+
config = get_config_for_env_from_file(config_file)
|
|
13
|
+
@databases = config[:databases]
|
|
14
|
+
@options = config[:options]
|
|
15
|
+
{ databases: @databases, options: @options }
|
|
16
|
+
end
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
def env
|
|
19
|
+
@env
|
|
20
|
+
end
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
def databases
|
|
23
|
+
get_config_required(:@databases)
|
|
24
|
+
end
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
def options
|
|
27
|
+
get_config_optional(:@options)
|
|
28
|
+
end
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
config_value = instance_variable_get(config_variable)
|
|
28
|
-
if config_value.nil? || config_value.empty?
|
|
29
|
-
raise "No configuration for `#{config_variable.to_s[1..-1]}` !"
|
|
30
|
-
end
|
|
31
|
-
config_value
|
|
32
|
-
end
|
|
30
|
+
private
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
def get_config_required(config_variable)
|
|
33
|
+
config_value = instance_variable_get(config_variable)
|
|
34
|
+
if config_value.nil? || config_value.empty?
|
|
35
|
+
raise "No configuration for `#{config_variable.to_s[1..-1]}` !"
|
|
37
36
|
end
|
|
37
|
+
config_value
|
|
38
|
+
end
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
def get_config_optional(config_variable)
|
|
41
|
+
config_value = instance_variable_get(config_variable)
|
|
42
|
+
(config_value.nil? || config_value.empty?) ? {} : config_value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def get_config_for_env_from_file(file)
|
|
46
|
+
yaml_hash = YAML.load(ERB.new(::File.new(file).read).result)
|
|
47
|
+
config = symbolize_keys(yaml_hash)[@env]
|
|
48
|
+
raise LoadError, "No configuration for `#{@env}` environment found !" unless config
|
|
49
|
+
config
|
|
50
|
+
end
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
+
def symbolize_keys(hash)
|
|
53
|
+
hash.each_with_object({}) do |(key, value), new_hash|
|
|
54
|
+
new_key = key.is_a?(String) ? key.to_sym : key
|
|
55
|
+
new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
|
|
56
|
+
new_hash[new_key] = new_value
|
|
52
57
|
end
|
|
53
58
|
end
|
|
54
59
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
require 'sequel'
|
|
2
|
+
|
|
1
3
|
module SqlMigrations
|
|
2
4
|
# Class that represents database gem will connect to
|
|
3
5
|
#
|
|
4
6
|
class Database
|
|
5
|
-
|
|
7
|
+
HISTORY_TABLE = :sqlmigrations_schema
|
|
6
8
|
attr_reader :name, :driver
|
|
7
9
|
|
|
8
10
|
def initialize(name, options)
|
|
@@ -19,38 +21,28 @@ module SqlMigrations
|
|
|
19
21
|
install_table
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
def
|
|
24
|
+
def migrate
|
|
23
25
|
migrations = Migration.find(@name)
|
|
24
26
|
if !migrations.empty?
|
|
25
27
|
puts "[i] Executing migrations for `#{@name}` database"
|
|
26
28
|
migrations.each { |migration| migration.execute(self) }
|
|
27
29
|
else
|
|
28
|
-
puts "[i] No
|
|
30
|
+
puts "[i] No migrations for `#{@name}` database"
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
def
|
|
34
|
+
def seed
|
|
33
35
|
seeds = Seed.find(@name)
|
|
34
36
|
if !seeds.empty?
|
|
35
37
|
puts "[i] Seeding `#{@name}` database"
|
|
36
38
|
seeds.each { |seed| seed.execute(self) }
|
|
37
39
|
else
|
|
38
|
-
puts "[i] No
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def seed_with_fixtures
|
|
43
|
-
fixtures = Fixture.find(@name)
|
|
44
|
-
if !fixtures.empty?
|
|
45
|
-
puts "[i] Seeding `#{@name}` database with fixtures"
|
|
46
|
-
fixtures.each { |fixture| fixture.execute(self) }
|
|
47
|
-
else
|
|
48
|
-
puts "[i] No new fixturess for `#{@name}` database"
|
|
40
|
+
puts "[i] No seeds for `#{@name}` database"
|
|
49
41
|
end
|
|
50
42
|
end
|
|
51
43
|
|
|
52
|
-
def
|
|
53
|
-
@driver[
|
|
44
|
+
def history
|
|
45
|
+
@driver[HISTORY_TABLE]
|
|
54
46
|
end
|
|
55
47
|
|
|
56
48
|
private
|
|
@@ -66,17 +58,17 @@ module SqlMigrations
|
|
|
66
58
|
end
|
|
67
59
|
|
|
68
60
|
def install_table
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
puts "[!] Installing `#{
|
|
72
|
-
@driver.create_table(
|
|
61
|
+
return if @driver.table_exists?(HISTORY_TABLE)
|
|
62
|
+
|
|
63
|
+
puts "[!] Installing `#{HISTORY_TABLE}` history table"
|
|
64
|
+
@driver.create_table(HISTORY_TABLE) do
|
|
73
65
|
# rubocop:disable Style/SingleSpaceBeforeFirstArg
|
|
74
66
|
primary_key :id
|
|
75
67
|
Bignum :time
|
|
76
68
|
DateTime :executed
|
|
77
69
|
String :name
|
|
78
70
|
String :type
|
|
79
|
-
index
|
|
71
|
+
index [:time, :type]
|
|
80
72
|
# rubocop:enable Style/SingleSpaceBeforeFirstArg
|
|
81
73
|
end
|
|
82
74
|
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module SqlMigrations
|
|
2
|
+
# Class that represents script file
|
|
3
|
+
#
|
|
4
|
+
class File
|
|
5
|
+
attr_reader :name, :time, :date, :datetime, :database, :type, :path
|
|
6
|
+
|
|
7
|
+
def initialize(path, database, type)
|
|
8
|
+
@path = path
|
|
9
|
+
@database = database
|
|
10
|
+
@type = type.to_s
|
|
11
|
+
|
|
12
|
+
@file, @base, @parent = elements(path)
|
|
13
|
+
@date, @time, @name = match(@file) if @file
|
|
14
|
+
@datetime = (@date.to_s + @time.to_s).to_i
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def valid?
|
|
18
|
+
[@name, @time, @date, @database, directories?].all?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def content
|
|
22
|
+
::File.read(@path)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ==(other)
|
|
26
|
+
datetime == other.datetime
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
@file.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def elements(path)
|
|
36
|
+
_filename, _base_directory, _parent_directory =
|
|
37
|
+
path.split(::File::SEPARATOR).last(3).reverse
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def match(filename)
|
|
41
|
+
_, date, time, name =
|
|
42
|
+
filename.match(/^(\d{8})_(\d{6})_(.*)?\.sql$/).to_a
|
|
43
|
+
[date, time, name]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def directories?
|
|
47
|
+
if @database == :default
|
|
48
|
+
file_in_type_base_directory? || file_in_database_directory?
|
|
49
|
+
else
|
|
50
|
+
file_in_database_directory?
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def file_in_type_base_directory?
|
|
55
|
+
@base == "#{@type}s"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def file_in_type_parent_directory?
|
|
59
|
+
@parent == "#{@type}s"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def file_in_database_directory?
|
|
63
|
+
file_in_type_parent_directory? &&
|
|
64
|
+
(@base == @database.to_s)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
module SqlMigrations
|
|
2
2
|
# Migration class
|
|
3
3
|
#
|
|
4
|
-
class Migration <
|
|
4
|
+
class Migration < Script
|
|
5
5
|
def self.find(database_name)
|
|
6
6
|
super(database_name, :migration)
|
|
7
7
|
end
|
|
8
|
-
|
|
9
|
-
def to_s
|
|
10
|
-
"Migration #{@name} for `#{@database_name}` database, datetime: #{@date + @time}"
|
|
11
|
-
end
|
|
12
8
|
end
|
|
13
9
|
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'sequel'
|
|
2
|
+
require 'find'
|
|
3
|
+
require 'benchmark'
|
|
4
|
+
require 'time'
|
|
5
|
+
|
|
6
|
+
module SqlMigrations
|
|
7
|
+
# SqlScript class
|
|
8
|
+
#
|
|
9
|
+
class Script
|
|
10
|
+
DELEGATED = [:name, :date, :time, :datetime, :type, :content, :path]
|
|
11
|
+
attr_reader(*DELEGATED)
|
|
12
|
+
|
|
13
|
+
def initialize(file)
|
|
14
|
+
@file = file
|
|
15
|
+
|
|
16
|
+
DELEGATED.each do |method|
|
|
17
|
+
instance_variable_set("@#{method}", file.send(method))
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def execute(db)
|
|
22
|
+
@database = db
|
|
23
|
+
return false unless new?
|
|
24
|
+
driver = @database.driver
|
|
25
|
+
begin
|
|
26
|
+
driver.transaction do
|
|
27
|
+
@benchmark = Benchmark.measure do
|
|
28
|
+
statements.each { |query| driver.run(query) }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
rescue
|
|
32
|
+
puts "[-] Error while executing #{@type} #{@name} !"
|
|
33
|
+
raise
|
|
34
|
+
else
|
|
35
|
+
true & on_success
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.find(database, type)
|
|
40
|
+
files = []
|
|
41
|
+
|
|
42
|
+
Find.find(Dir.pwd) do |path|
|
|
43
|
+
file = File.new(path, database, type)
|
|
44
|
+
|
|
45
|
+
raise "Duplicate time for #{type}s: #{files.find { |f| f == file }}, #{file}" if
|
|
46
|
+
file.valid? && files.include?(file)
|
|
47
|
+
|
|
48
|
+
files << file if file.valid?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
files.sort_by(&:datetime).map { |file| new(file) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def statements
|
|
55
|
+
separator = Config.options[:separator]
|
|
56
|
+
if separator
|
|
57
|
+
statements = @content.split(separator)
|
|
58
|
+
statements.collect!(&:strip)
|
|
59
|
+
statements.reject(&:empty?)
|
|
60
|
+
else
|
|
61
|
+
[content]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_s
|
|
66
|
+
"#{@type.capitalize} `#{@path}` for `#{@file.database}` database"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def new?
|
|
72
|
+
history = @database.history
|
|
73
|
+
last = history.order(Sequel.asc(:time)).where(type: @type).last
|
|
74
|
+
is_new = history.where(time: @datetime, type: @type).count == 0
|
|
75
|
+
|
|
76
|
+
if is_new && !last.nil?
|
|
77
|
+
if last[:time] > @datetime
|
|
78
|
+
raise "#{@type.capitalize} #{@name} has time BEFORE last one recorded !"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
is_new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def on_success
|
|
85
|
+
puts "[+] Successfully executed #{@type}, name: #{@name}"
|
|
86
|
+
puts " #{type.capitalize} file: #{@date}_#{@time}_#{@name}.sql"
|
|
87
|
+
puts " Benchmark: #{@benchmark}"
|
|
88
|
+
|
|
89
|
+
@database.history.insert(time: @datetime, name: @name,
|
|
90
|
+
type: @type, executed: DateTime.now)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/sql_migrations/seed.rb
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
module SqlMigrations
|
|
2
2
|
# Seed class
|
|
3
3
|
#
|
|
4
|
-
class Seed <
|
|
4
|
+
class Seed < Script
|
|
5
5
|
def self.find(database_name)
|
|
6
6
|
super(database_name, :seed)
|
|
7
7
|
end
|
|
8
|
-
|
|
9
|
-
def to_s
|
|
10
|
-
"Seed data #{@name} for `#{@database_name}` database, datetime: #{@date + @time}"
|
|
11
|
-
end
|
|
12
8
|
end
|
|
13
9
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
describe '
|
|
1
|
+
describe 'history table in database' do
|
|
2
2
|
before do
|
|
3
3
|
allow(SqlMigrations::Config).to receive(:databases) { { default: {} } }
|
|
4
4
|
end
|
|
@@ -7,7 +7,7 @@ describe 'schema table in database' do
|
|
|
7
7
|
expect do
|
|
8
8
|
@database = SqlMigrations::Database.new(:default, adapter: :sqlite)
|
|
9
9
|
end.to output("[+] Connected to `default` database using sqlite adapter\n" \
|
|
10
|
-
"[!] Installing `sqlmigrations_schema
|
|
10
|
+
"[!] Installing `sqlmigrations_schema` history table\n").to_stdout
|
|
11
11
|
expect(@database.driver.table_exists?(:sqlmigrations_schema)).to be true
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -19,7 +19,7 @@ describe 'schema table in database' do
|
|
|
19
19
|
DateTime :executed
|
|
20
20
|
String :name
|
|
21
21
|
String :type
|
|
22
|
-
index
|
|
22
|
+
index [:time, :type]
|
|
23
23
|
# rubocop:enable Style/SingleSpaceBeforeFirstArg
|
|
24
24
|
end
|
|
25
25
|
expect do
|
|
@@ -6,7 +6,7 @@ describe 'migrations valid order support engine' do
|
|
|
6
6
|
f.puts 'CREATE TABLE test_table(col_int INTEGER, col_str STRING)'
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
@database
|
|
9
|
+
@database = SqlMigrations::Database.new(:default, adapter: :sqlite)
|
|
10
10
|
migration = SqlMigrations::Migration.find(:default).first
|
|
11
11
|
migration.execute(@database)
|
|
12
12
|
|
|
@@ -4,8 +4,10 @@ describe 'migration' do
|
|
|
4
4
|
File.open('/migrations/20150305_154010_test_migration.sql', 'w') do |f|
|
|
5
5
|
f.puts 'CREATE TABLE test_table(col_int INTEGER, col_str STRING)'
|
|
6
6
|
end
|
|
7
|
+
|
|
7
8
|
allow(SqlMigrations::Config).to receive(:databases) { { default: { development: {} } } }
|
|
8
9
|
@migration = SqlMigrations::Migration.find(:default).first
|
|
10
|
+
@database = SqlMigrations::Database.new(:default, adapter: :sqlite)
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
it 'should be found and initialized' do
|
|
@@ -24,11 +26,28 @@ describe 'migration' do
|
|
|
24
26
|
expect(@migration.name).to eql('test_migration')
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
context 'executing migrations' do
|
|
30
|
+
subject { -> { @database.migrate } }
|
|
31
|
+
|
|
32
|
+
it 'should be properly executed' do
|
|
33
|
+
subject.call
|
|
34
|
+
expect(@sqlite_db.table_exists?(:test_table)).to be true
|
|
35
|
+
expect(@sqlite_db[:test_table].columns).to include(:col_int)
|
|
36
|
+
expect(@sqlite_db[:test_table].columns).to include(:col_str)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'invalid migration' do
|
|
40
|
+
before do
|
|
41
|
+
File.open('/migrations/20150825_184010_invalid_migration.sql', 'w') do |f|
|
|
42
|
+
f.puts 'CREATE this_is_error TABLE invalid'
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should print warning about invalid migration' do
|
|
47
|
+
expect { subject.call }
|
|
48
|
+
.to output(/Error while executing migration invalid_migration !/).to_stdout
|
|
49
|
+
.and raise_error(Sequel::DatabaseError)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
33
52
|
end
|
|
34
53
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# rubocop:disable Metrics/LineLength
|
|
2
|
+
describe 'sql scripts' do
|
|
3
|
+
before do
|
|
4
|
+
allow(SqlMigrations::Config).to receive(:databases) { { default: {}, test2_db: {} } }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
context 'valid scripts set' do
|
|
8
|
+
before do
|
|
9
|
+
Dir.mkdir('/migrations')
|
|
10
|
+
Dir.mkdir('/seeds')
|
|
11
|
+
|
|
12
|
+
File.open('/migrations/20150305_154010_first_test_migration.sql', 'w') do |f|
|
|
13
|
+
f.puts 'CREATE TABLE first_test_table(col_int1 INTEGER, col_str1 STRING)'
|
|
14
|
+
end
|
|
15
|
+
File.open('/migrations/20150305_154011_second_test_migration.sql', 'w') do |f|
|
|
16
|
+
f.puts 'CREATE TABLE second_test_table(col_int2 INTEGER, col_str2 STRING)'
|
|
17
|
+
end
|
|
18
|
+
File.open('/seeds/20150305_154010_test_seed.sql', 'w') do |f|
|
|
19
|
+
f.puts 'INSERT INTO first_test_table(col_int1, col_str1) VALUES(123, "test_string1")'
|
|
20
|
+
f.puts 'INSERT INTO second_test_table(col_int2, col_str2) VALUES(456, "test_string2")'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
Dir.mkdir('/migrations/test2_db')
|
|
24
|
+
File.open('/migrations/test2_db/20150511_144000_second_db_test_migration.sql', 'w') do |f|
|
|
25
|
+
f.puts 'CREATE TABLE second_db_test_table(col_int1 INTEGER, col_str1 STRING)'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Dir.mkdir('/migrations/default')
|
|
29
|
+
File.open('/migrations/default//20150511_144100_default_db_test2_migration.sql', 'w') do |f|
|
|
30
|
+
f.puts 'CREATE TABLE default_db_test2_table(col_int1 INTEGER, col_str1 STRING)'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should be found' do
|
|
35
|
+
expect { SqlMigrations.scripts }.to \
|
|
36
|
+
output("Migration `/migrations/20150305_154010_first_test_migration.sql` for `default` database\n" \
|
|
37
|
+
"Migration `/migrations/20150305_154011_second_test_migration.sql` for `default` database\n" \
|
|
38
|
+
"Migration `/migrations/default/20150511_144100_default_db_test2_migration.sql` for `default` database\n" \
|
|
39
|
+
"Seed `/seeds/20150305_154010_test_seed.sql` for `default` database\n" \
|
|
40
|
+
"Migration `/migrations/test2_db/20150511_144000_second_db_test_migration.sql` for `test2_db` database\n"
|
|
41
|
+
).to_stdout
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'should raise an error if two files of same type with same timestamp are present' do
|
|
45
|
+
File.open('/migrations/default/20150511_144100_duplicated_timestamp_migration.sql', 'w') do |f|
|
|
46
|
+
f.puts 'CREATE TABLE duplicated_migration(col_int1 INTEGER)'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
expect { SqlMigrations.scripts }.to raise_error(RuntimeError, /Duplicate time for migrations: .*/)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'invalid files' do
|
|
54
|
+
before do
|
|
55
|
+
Dir.mkdir('/migrations')
|
|
56
|
+
File.open('/migrations/20150511_144100_test_migration.sql', 'w') do |f|
|
|
57
|
+
f.puts 'CREATE TABLE test_migration(col_int1 INTEGER)'
|
|
58
|
+
end
|
|
59
|
+
File.open('/migrations/.20150511_144100_testp_migration.sql.swp', 'w') do |f|
|
|
60
|
+
f.puts 'CREATE TABLE testd_migration(col_int1 INTEGER)'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should not find .*sw? files' do
|
|
65
|
+
expect { SqlMigrations.scripts }
|
|
66
|
+
.to output("Migration `/migrations/20150511_144100_test_migration.sql` for `default` database\n")
|
|
67
|
+
.to_stdout
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
# rubocop:enable Metrics/LineLength
|
data/spec/features/seed_spec.rb
CHANGED
|
@@ -10,8 +10,8 @@ describe 'seed' do
|
|
|
10
10
|
end
|
|
11
11
|
allow(SqlMigrations::Config).to receive(:databases) { { default: { development: {} } } }
|
|
12
12
|
database = SqlMigrations::Database.new(:default, adapter: :sqlite)
|
|
13
|
-
database.
|
|
14
|
-
database.
|
|
13
|
+
database.migrate
|
|
14
|
+
database.seed
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it 'should be properly execute' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
require 'bundler/setup'
|
|
2
|
-
require 'memfs'
|
|
3
1
|
require 'simplecov'
|
|
2
|
+
require 'memfs'
|
|
3
|
+
require 'pp' # `superclass mismatch for class File` workaround
|
|
4
4
|
|
|
5
5
|
SimpleCov.start
|
|
6
|
-
|
|
6
|
+
require 'sql_migrations'
|
|
7
7
|
|
|
8
8
|
RSpec.configure do |config|
|
|
9
9
|
config.profile_examples = 2
|
|
@@ -16,11 +16,11 @@ RSpec.configure do |config|
|
|
|
16
16
|
MemFs.activate!
|
|
17
17
|
# Reset configuration for every test suite
|
|
18
18
|
SqlMigrations::Config.instance_eval('@databases = nil; @options = nil')
|
|
19
|
-
@stdout, $stdout = $stdout, StringIO.new
|
|
19
|
+
@stdout, $stdout = $stdout, StringIO.new # Catch STDOUT do variable
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
config.after do
|
|
23
|
-
$stdout, @stdout = @stdout, nil
|
|
23
|
+
$stdout, @stdout = @stdout, nil # Reassign STDOUT
|
|
24
24
|
MemFs.deactivate!
|
|
25
25
|
end
|
|
26
26
|
end
|
data/sql_migrations.gemspec
CHANGED
|
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.require_paths = ['lib']
|
|
19
19
|
|
|
20
20
|
# rubocop:disable Style/SingleSpaceBeforeFirstArg
|
|
21
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
|
21
|
+
spec.add_development_dependency 'rspec', '~> 3.3'
|
|
22
22
|
spec.add_development_dependency 'sqlite3', '~> 1.3.10'
|
|
23
23
|
spec.add_development_dependency 'memfs', '~> 0.4.3'
|
|
24
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
|
24
|
+
spec.add_development_dependency 'rubocop', '~> 0.33'
|
|
25
25
|
spec.add_development_dependency 'simplecov', '~> 0.10.0'
|
|
26
26
|
spec.add_dependency 'bundler', '~> 1.7'
|
|
27
27
|
spec.add_dependency 'rake', '~> 10.0'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sql_migrations
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Grzegorz Bizon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 3.
|
|
19
|
+
version: '3.3'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 3.
|
|
26
|
+
version: '3.3'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: sqlite3
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -58,14 +58,14 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 0.
|
|
61
|
+
version: '0.33'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 0.
|
|
68
|
+
version: '0.33'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: simplecov
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -140,24 +140,21 @@ files:
|
|
|
140
140
|
- lib/sql_migrations.rb
|
|
141
141
|
- lib/sql_migrations/config.rb
|
|
142
142
|
- lib/sql_migrations/database.rb
|
|
143
|
-
- lib/sql_migrations/
|
|
143
|
+
- lib/sql_migrations/file.rb
|
|
144
144
|
- lib/sql_migrations/migration.rb
|
|
145
|
-
- lib/sql_migrations/
|
|
145
|
+
- lib/sql_migrations/script.rb
|
|
146
146
|
- lib/sql_migrations/seed.rb
|
|
147
|
-
- lib/sql_migrations/sql_script.rb
|
|
148
|
-
- lib/sql_migrations/tasks/list.rake
|
|
149
147
|
- lib/sql_migrations/tasks/migrate.rake
|
|
148
|
+
- lib/sql_migrations/tasks/scripts.rake
|
|
150
149
|
- lib/sql_migrations/tasks/seed.rake
|
|
151
|
-
- lib/sql_migrations/tasks/seed_test.rake
|
|
152
150
|
- lib/sql_migrations/version.rb
|
|
153
151
|
- spec/features/config_spec.rb
|
|
154
|
-
- spec/features/
|
|
152
|
+
- spec/features/history_table_spec.rb
|
|
155
153
|
- spec/features/migration_multistatement_spec.rb
|
|
156
154
|
- spec/features/migration_order_spec.rb
|
|
157
155
|
- spec/features/migration_spec.rb
|
|
158
|
-
- spec/features/
|
|
156
|
+
- spec/features/scripts_spec.rb
|
|
159
157
|
- spec/features/seed_spec.rb
|
|
160
|
-
- spec/features/sql_scripts_spec.rb
|
|
161
158
|
- spec/spec_helper.rb
|
|
162
159
|
- sql_migrations.gemspec
|
|
163
160
|
homepage: http://github.com/grzesiek/sql_migrations
|
|
@@ -186,12 +183,11 @@ specification_version: 4
|
|
|
186
183
|
summary: Simple standalone migrations you can use with plain SQL
|
|
187
184
|
test_files:
|
|
188
185
|
- spec/features/config_spec.rb
|
|
189
|
-
- spec/features/
|
|
186
|
+
- spec/features/history_table_spec.rb
|
|
190
187
|
- spec/features/migration_multistatement_spec.rb
|
|
191
188
|
- spec/features/migration_order_spec.rb
|
|
192
189
|
- spec/features/migration_spec.rb
|
|
193
|
-
- spec/features/
|
|
190
|
+
- spec/features/scripts_spec.rb
|
|
194
191
|
- spec/features/seed_spec.rb
|
|
195
|
-
- spec/features/sql_scripts_spec.rb
|
|
196
192
|
- spec/spec_helper.rb
|
|
197
193
|
has_rdoc:
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
module SqlMigrations
|
|
2
|
-
# Fixture class
|
|
3
|
-
#
|
|
4
|
-
class Fixture < SqlScript
|
|
5
|
-
def self.find(database_name)
|
|
6
|
-
super(database_name, :fixture)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def to_s
|
|
10
|
-
"Fixture #{@name} for `#{@database_name}` database, datetime: #{@date + @time}"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
module SqlMigrations
|
|
2
|
-
# Class representing script file
|
|
3
|
-
#
|
|
4
|
-
class ScriptFile
|
|
5
|
-
attr_reader :name, :time, :date, :database_name, :path
|
|
6
|
-
|
|
7
|
-
def initialize(path, database_name, type)
|
|
8
|
-
@filename,
|
|
9
|
-
@base_directory,
|
|
10
|
-
@parent_directory = path_elements(path)
|
|
11
|
-
@path = path
|
|
12
|
-
@type = type.to_s
|
|
13
|
-
@database_name = database_name
|
|
14
|
-
@date, @time, @name = match_regexp(@filename) if @filename
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def content
|
|
18
|
-
File.read(@path)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def valid?
|
|
22
|
-
(@name && @time && @date && @database_name && matches_directories?) ? true : false
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
def path_elements(path)
|
|
28
|
-
_filename, _base_directory, _parent_directory =
|
|
29
|
-
path.split(File::SEPARATOR).last(3).reverse
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def match_regexp(filename)
|
|
33
|
-
_, date, time, name =
|
|
34
|
-
filename.match(/(\d{8})_(\d{6})_(.*)?\.sql/).to_a
|
|
35
|
-
[date, time, name]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def matches_directories?
|
|
39
|
-
if @database_name == :default
|
|
40
|
-
file_in_type_base_directory? || file_in_database_directory?
|
|
41
|
-
else
|
|
42
|
-
file_in_database_directory?
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def file_in_type_base_directory?
|
|
47
|
-
@base_directory == "#{@type}s"
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def file_in_type_parent_directory?
|
|
51
|
-
@parent_directory == "#{@type}s"
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def file_in_database_directory?
|
|
55
|
-
file_in_type_parent_directory? &&
|
|
56
|
-
(@base_directory == @database_name.to_s)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
module SqlMigrations
|
|
2
|
-
# SqlScript class
|
|
3
|
-
#
|
|
4
|
-
class SqlScript < ScriptFile
|
|
5
|
-
def initialize(path, database_name, type)
|
|
6
|
-
super
|
|
7
|
-
@datetime = (@date.to_s + @time.to_s).to_i
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def execute(db)
|
|
11
|
-
@database = db
|
|
12
|
-
return false unless new?
|
|
13
|
-
driver = @database.driver
|
|
14
|
-
begin
|
|
15
|
-
driver.transaction do
|
|
16
|
-
@benchmark = Benchmark.measure do
|
|
17
|
-
statements.each { |query| driver.run(query) }
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
rescue
|
|
21
|
-
puts "[-] Error while executing #{@type} #{@name} !"
|
|
22
|
-
raise
|
|
23
|
-
else
|
|
24
|
-
true & on_success
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def statements
|
|
29
|
-
separator = Config.options[:separator]
|
|
30
|
-
if separator
|
|
31
|
-
statements = content.split(separator)
|
|
32
|
-
statements.collect!(&:strip)
|
|
33
|
-
statements.reject(&:empty?)
|
|
34
|
-
else
|
|
35
|
-
[content]
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def self.find(database_name, type)
|
|
40
|
-
scripts = []
|
|
41
|
-
Find.find(Dir.pwd) do |path|
|
|
42
|
-
candidate = new(path, database_name, type)
|
|
43
|
-
scripts << candidate if candidate.valid?
|
|
44
|
-
end
|
|
45
|
-
scripts.sort_by { |file| (file.date + file.time).to_i }
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def new?
|
|
51
|
-
schema = @database.schema_dataset
|
|
52
|
-
last = schema.order(Sequel.asc(:time)).where(type: @type).last
|
|
53
|
-
is_new = schema.where(time: @datetime, type: @type).count == 0
|
|
54
|
-
if is_new && !last.nil?
|
|
55
|
-
if last[:time] > @datetime
|
|
56
|
-
raise "#{@type.capitalize} #{@name} has time BEFORE last one recorded !"
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
is_new
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def on_success
|
|
63
|
-
puts "[+] Successfully executed #{@type}, name: #{@name}"
|
|
64
|
-
puts " #{@type.capitalize} file: #{@date}_#{@time}_#{@name}.sql"
|
|
65
|
-
puts " Benchmark: #{@benchmark}"
|
|
66
|
-
schema = @database.schema_dataset
|
|
67
|
-
schema.insert(time: @datetime, name: @name, type: @type, executed: DateTime.now)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
describe 'fixture' do
|
|
2
|
-
before do
|
|
3
|
-
Dir.mkdir('/migrations')
|
|
4
|
-
File.open('/migrations/20150305_154010_test_migration.sql', 'w') do |f|
|
|
5
|
-
f.puts 'CREATE TABLE test_table_fixture(col_int INTEGER, col_str STRING)'
|
|
6
|
-
end
|
|
7
|
-
Dir.mkdir('/fixtures')
|
|
8
|
-
File.open('/fixtures/20150305_154012_test_fixture.sql', 'w') do |f|
|
|
9
|
-
f.puts 'INSERT INTO test_table_fixture VALUES(12, "test_string_fixture")'
|
|
10
|
-
end
|
|
11
|
-
allow(SqlMigrations::Config).to receive(:databases) { { default: { development: {} } } }
|
|
12
|
-
database = SqlMigrations::Database.new(:default, adapter: :sqlite)
|
|
13
|
-
database.execute_migrations
|
|
14
|
-
database.seed_with_fixtures
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it 'should be properly executed' do
|
|
18
|
-
expect(@sqlite_db.table_exists?(:test_table_fixture)).to be true
|
|
19
|
-
expect(@sqlite_db[:test_table_fixture].first)
|
|
20
|
-
.to eq(col_int: 12, col_str: 'test_string_fixture')
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# rubocop:disable Metrics/LineLength
|
|
2
|
-
describe 'sql scripts' do
|
|
3
|
-
before do
|
|
4
|
-
Dir.mkdir('/migrations')
|
|
5
|
-
Dir.mkdir('/fixtures')
|
|
6
|
-
Dir.mkdir('/seeds')
|
|
7
|
-
|
|
8
|
-
File.open('/migrations/20150305_154010_first_test_migration.sql', 'w') do |f|
|
|
9
|
-
f.puts 'CREATE TABLE first_test_table(col_int1 INTEGER, col_str1 STRING)'
|
|
10
|
-
end
|
|
11
|
-
File.open('/migrations/20150305_154011_second_test_migration.sql', 'w') do |f|
|
|
12
|
-
f.puts 'CREATE TABLE second_test_table(col_int2 INTEGER, col_str2 STRING)'
|
|
13
|
-
end
|
|
14
|
-
File.open('/seeds/20150305_154010_test_seed.sql', 'w') do |f|
|
|
15
|
-
f.puts 'INSERT INTO first_test_table(col_int1, col_str1) VALUES(123, "test_string1")'
|
|
16
|
-
f.puts 'INSERT INTO second_test_table(col_int2, col_str2) VALUES(456, "test_string2")'
|
|
17
|
-
end
|
|
18
|
-
File.open('/fixtures/20150518_154012_test_fixture.sql', 'w') do |f|
|
|
19
|
-
f.puts 'INSERT INTO first_test2_table(col_int1, col_str1) VALUES(2123, "2test_string1")'
|
|
20
|
-
f.puts 'INSERT INTO second_test2_table(col_int2, col_str2) VALUES(2456, "2test_string2")'
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
Dir.mkdir('/migrations/test2_db')
|
|
24
|
-
File.open('/migrations/test2_db/20150511_144000_second_db_test_migration.sql', 'w') do |f|
|
|
25
|
-
f.puts 'CREATE TABLE second_db_test_table(col_int1 INTEGER, col_str1 STRING)'
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
Dir.mkdir('/migrations/default')
|
|
29
|
-
File.open('/migrations/default//20150511_144100_default_db_test2_migration.sql', 'w') do |f|
|
|
30
|
-
f.puts 'CREATE TABLE default_db_test2_table(col_int1 INTEGER, col_str1 STRING)'
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
allow(SqlMigrations::Config).to receive(:databases) { { default: {}, test2_db: {} } }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it 'should be found' do
|
|
37
|
-
expect { SqlMigrations.list_files }.to \
|
|
38
|
-
output("Migration first_test_migration for `default` database, datetime: 20150305154010\n" \
|
|
39
|
-
"Migration second_test_migration for `default` database, datetime: 20150305154011\n" \
|
|
40
|
-
"Migration default_db_test2_migration for `default` database, datetime: 20150511144100\n" \
|
|
41
|
-
"Seed data test_seed for `default` database, datetime: 20150305154010\n" \
|
|
42
|
-
"Fixture test_fixture for `default` database, datetime: 20150518154012\n" \
|
|
43
|
-
"Migration second_db_test_migration for `test2_db` database, datetime: 20150511144000\n"
|
|
44
|
-
).to_stdout
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
# rubocop:enable Metrics/LineLength
|