ardm-migrations 1.2.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/.gitignore +35 -0
- data/.travis.yml +11 -0
- data/Gemfile +53 -0
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +4 -0
- data/ardm-migrations.gemspec +27 -0
- data/db/migrations/1_create_people_table.rb +12 -0
- data/db/migrations/2_add_dob_to_people.rb +13 -0
- data/db/migrations/config.rb +4 -0
- data/examples/Rakefile +144 -0
- data/examples/sample_migration.rb +58 -0
- data/examples/sample_migration_spec.rb +50 -0
- data/lib/ardm-migrations.rb +1 -0
- data/lib/dm-migrations/adapters/dm-do-adapter.rb +295 -0
- data/lib/dm-migrations/adapters/dm-mysql-adapter.rb +299 -0
- data/lib/dm-migrations/adapters/dm-oracle-adapter.rb +332 -0
- data/lib/dm-migrations/adapters/dm-postgres-adapter.rb +159 -0
- data/lib/dm-migrations/adapters/dm-sqlite-adapter.rb +96 -0
- data/lib/dm-migrations/adapters/dm-sqlserver-adapter.rb +177 -0
- data/lib/dm-migrations/adapters/dm-yaml-adapter.rb +23 -0
- data/lib/dm-migrations/auto_migration.rb +239 -0
- data/lib/dm-migrations/exceptions/duplicate_migration.rb +6 -0
- data/lib/dm-migrations/migration.rb +300 -0
- data/lib/dm-migrations/migration_runner.rb +85 -0
- data/lib/dm-migrations/sql/column.rb +5 -0
- data/lib/dm-migrations/sql/mysql.rb +61 -0
- data/lib/dm-migrations/sql/postgres.rb +82 -0
- data/lib/dm-migrations/sql/sqlite.rb +51 -0
- data/lib/dm-migrations/sql/table.rb +15 -0
- data/lib/dm-migrations/sql/table_creator.rb +109 -0
- data/lib/dm-migrations/sql/table_modifier.rb +57 -0
- data/lib/dm-migrations/sql.rb +5 -0
- data/lib/dm-migrations/version.rb +5 -0
- data/lib/dm-migrations.rb +3 -0
- data/lib/spec/example/migration_example_group.rb +73 -0
- data/lib/spec/matchers/migration_matchers.rb +106 -0
- data/spec/integration/auto_migration_spec.rb +553 -0
- data/spec/integration/auto_upgrade_spec.rb +40 -0
- data/spec/integration/migration_runner_spec.rb +89 -0
- data/spec/integration/migration_spec.rb +157 -0
- data/spec/integration/sql_spec.rb +250 -0
- data/spec/isolated/require_after_setup_spec.rb +30 -0
- data/spec/isolated/require_before_setup_spec.rb +30 -0
- data/spec/isolated/require_spec.rb +25 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/unit/migration_spec.rb +453 -0
- data/spec/unit/sql/column_spec.rb +14 -0
- data/spec/unit/sql/postgres_spec.rb +97 -0
- data/spec/unit/sql/sqlite_extensions_spec.rb +108 -0
- data/spec/unit/sql/table_creator_spec.rb +94 -0
- data/spec/unit/sql/table_modifier_spec.rb +49 -0
- data/spec/unit/sql/table_spec.rb +28 -0
- data/spec/unit/sql_spec.rb +7 -0
- data/tasks/spec.rake +38 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +150 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
module SQL
|
2
|
+
class TableModifier
|
3
|
+
extend DataMapper::Property::Lookup
|
4
|
+
|
5
|
+
attr_accessor :table_name, :opts, :statements, :adapter
|
6
|
+
|
7
|
+
def initialize(adapter, table_name, opts = {}, &block)
|
8
|
+
@adapter = adapter
|
9
|
+
@table_name = table_name.to_s
|
10
|
+
@opts = (opts)
|
11
|
+
|
12
|
+
@statements = []
|
13
|
+
|
14
|
+
self.instance_eval &block
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_column(name, type, opts = {})
|
18
|
+
column = SQL::TableCreator::Column.new(@adapter, name, type, opts)
|
19
|
+
@statements << "ALTER TABLE #{quoted_table_name} ADD COLUMN #{column.to_sql}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def drop_column(name)
|
23
|
+
# raise NotImplemented for SQLite3. Can't ALTER TABLE, need to copy table.
|
24
|
+
# We'd have to inspect it, and we can't, since we aren't executing any queries yet.
|
25
|
+
# TODO instead of building the SQL queries when executing the block, create AddColumn,
|
26
|
+
# AlterColumn and DropColumn objects that get #to_sql'd
|
27
|
+
if name.is_a?(Array)
|
28
|
+
name.each{ |n| drop_column(n) }
|
29
|
+
else
|
30
|
+
@statements << "ALTER TABLE #{quoted_table_name} DROP COLUMN #{quote_column_name(name)}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method :drop_columns, :drop_column
|
34
|
+
|
35
|
+
def rename_column(name, new_name, opts = {})
|
36
|
+
# raise NotImplemented for SQLite3
|
37
|
+
@statements << "ALTER TABLE #{quoted_table_name} RENAME COLUMN #{quote_column_name(name)} TO #{quote_column_name(new_name)}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def change_column(name, type, opts = {})
|
41
|
+
column = SQL::TableCreator::Column.new(@adapter, name, type, opts)
|
42
|
+
@statements << @adapter.change_column_type_statement(table_name, column)
|
43
|
+
end
|
44
|
+
|
45
|
+
def quote_column_name(name)
|
46
|
+
@adapter.send(:quote_name, name.to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
def quoted_table_name
|
50
|
+
@adapter.send(:quote_name, table_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_sql
|
54
|
+
@statements.join(';')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec/matchers/migration_matchers'
|
2
|
+
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
module Spec
|
6
|
+
module Example
|
7
|
+
class MigrationExampleGroup < Spec::Example::ExampleGroup
|
8
|
+
include Spec::Matchers::Migration
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
if this_migration.adapter.supports_schema_transactions?
|
12
|
+
run_prereq_migrations
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
if ! this_migration.adapter.supports_schema_transactions?
|
18
|
+
run_prereq_migrations
|
19
|
+
else
|
20
|
+
this_migration.adapter.begin_transaction
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
after(:each) do
|
25
|
+
if this_migration.adapter.supports_schema_transactions?
|
26
|
+
this_migration.adapter.rollback_transaction
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
after(:all) do
|
31
|
+
this_migration.adapter.recreate_database
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_prereq_migrations
|
35
|
+
"running n-1 migrations"
|
36
|
+
all_databases.each do |db|
|
37
|
+
db.adapter.recreate_database
|
38
|
+
end
|
39
|
+
@@migrations.sort.each do |migration|
|
40
|
+
break if migration.name.to_s == migration_name.to_s
|
41
|
+
migration.perform_up
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_migration
|
46
|
+
this_migration.perform_up
|
47
|
+
end
|
48
|
+
|
49
|
+
def migration_name
|
50
|
+
@migration_name ||= self.class.instance_variable_get("@description_text").to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def all_databases
|
54
|
+
@@migrations.map { |m| m.database }.uniq
|
55
|
+
end
|
56
|
+
|
57
|
+
def this_migration
|
58
|
+
@@migrations.select { |m| m.name.to_s == migration_name }.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def select(sql)
|
62
|
+
this_migration.adapter.select(sql)
|
63
|
+
end
|
64
|
+
|
65
|
+
def table(table_name)
|
66
|
+
this_migration.adapter.table(table_name)
|
67
|
+
end
|
68
|
+
|
69
|
+
Spec::Example::ExampleGroupFactory.register(:migration, self)
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Spec
|
2
|
+
module Matchers
|
3
|
+
module Migration
|
4
|
+
|
5
|
+
def have_table(table_name)
|
6
|
+
HaveTableMatcher.new(table_name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def have_column(column_name)
|
10
|
+
HaveColumnMatcher.new(column_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def permit_null
|
14
|
+
NullableColumnMatcher.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def be_primary_key
|
18
|
+
PrimaryKeyMatcher.new
|
19
|
+
end
|
20
|
+
|
21
|
+
class HaveTableMatcher
|
22
|
+
|
23
|
+
attr_accessor :table_name, :repository
|
24
|
+
|
25
|
+
def initialize(table_name)
|
26
|
+
@table_name = table_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def matches?(repository)
|
30
|
+
repository.adapter.storage_exists?(table_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_message
|
34
|
+
%(expected #{repository} to have table '#{table_name}')
|
35
|
+
end
|
36
|
+
|
37
|
+
def negative_failure_message
|
38
|
+
%(expected #{repository} to not have table '#{table_name}')
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
class HaveColumnMatcher
|
44
|
+
|
45
|
+
attr_accessor :table, :column_name
|
46
|
+
|
47
|
+
def initialize(column_name)
|
48
|
+
@column_name = column_name
|
49
|
+
end
|
50
|
+
|
51
|
+
def matches?(table)
|
52
|
+
@table = table
|
53
|
+
table.columns.map { |c| c.name }.include?(column_name.to_s)
|
54
|
+
end
|
55
|
+
|
56
|
+
def failure_message
|
57
|
+
%(expected #{table} to have column '#{column_name}')
|
58
|
+
end
|
59
|
+
|
60
|
+
def negative_failure_message
|
61
|
+
%(expected #{table} to not have column '#{column_name}')
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class NullableColumnMatcher
|
67
|
+
|
68
|
+
attr_accessor :column
|
69
|
+
|
70
|
+
def matches?(column)
|
71
|
+
@column = column
|
72
|
+
! column.not_null
|
73
|
+
end
|
74
|
+
|
75
|
+
def failure_message
|
76
|
+
%(expected #{column.name} to permit NULL)
|
77
|
+
end
|
78
|
+
|
79
|
+
def negative_failure_message
|
80
|
+
%(expected #{column.name} to be NOT NULL)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class PrimaryKeyMatcher
|
86
|
+
|
87
|
+
attr_accessor :column
|
88
|
+
|
89
|
+
def matches?(column)
|
90
|
+
@column = column
|
91
|
+
column.primary_key
|
92
|
+
end
|
93
|
+
|
94
|
+
def failure_message
|
95
|
+
%(expected #{column.name} to be PRIMARY KEY)
|
96
|
+
end
|
97
|
+
|
98
|
+
def negative_failure_message
|
99
|
+
%(expected #{column.name} to not be PRIMARY KEY)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|