sequel 3.11.0 → 3.12.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.
Files changed (136) hide show
  1. data/CHANGELOG +70 -0
  2. data/Rakefile +1 -1
  3. data/doc/active_record.rdoc +896 -0
  4. data/doc/advanced_associations.rdoc +46 -31
  5. data/doc/association_basics.rdoc +14 -9
  6. data/doc/dataset_basics.rdoc +3 -3
  7. data/doc/migration.rdoc +1011 -0
  8. data/doc/model_hooks.rdoc +198 -0
  9. data/doc/querying.rdoc +811 -86
  10. data/doc/release_notes/3.12.0.txt +304 -0
  11. data/doc/sharding.rdoc +17 -0
  12. data/doc/sql.rdoc +537 -0
  13. data/doc/validations.rdoc +501 -0
  14. data/lib/sequel/adapters/jdbc.rb +19 -27
  15. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -7
  16. data/lib/sequel/adapters/mysql.rb +5 -4
  17. data/lib/sequel/adapters/odbc.rb +3 -2
  18. data/lib/sequel/adapters/shared/mssql.rb +7 -6
  19. data/lib/sequel/adapters/shared/mysql.rb +2 -7
  20. data/lib/sequel/adapters/shared/postgres.rb +2 -8
  21. data/lib/sequel/adapters/shared/sqlite.rb +2 -5
  22. data/lib/sequel/adapters/sqlite.rb +4 -4
  23. data/lib/sequel/core.rb +0 -1
  24. data/lib/sequel/database.rb +2 -1060
  25. data/lib/sequel/database/connecting.rb +227 -0
  26. data/lib/sequel/database/dataset.rb +58 -0
  27. data/lib/sequel/database/dataset_defaults.rb +127 -0
  28. data/lib/sequel/database/logging.rb +62 -0
  29. data/lib/sequel/database/misc.rb +246 -0
  30. data/lib/sequel/database/query.rb +390 -0
  31. data/lib/sequel/database/schema_generator.rb +7 -3
  32. data/lib/sequel/database/schema_methods.rb +351 -7
  33. data/lib/sequel/dataset/actions.rb +9 -2
  34. data/lib/sequel/dataset/misc.rb +6 -2
  35. data/lib/sequel/dataset/mutation.rb +3 -11
  36. data/lib/sequel/dataset/query.rb +49 -6
  37. data/lib/sequel/exceptions.rb +3 -0
  38. data/lib/sequel/extensions/migration.rb +395 -113
  39. data/lib/sequel/extensions/schema_dumper.rb +21 -13
  40. data/lib/sequel/model.rb +27 -25
  41. data/lib/sequel/model/associations.rb +72 -34
  42. data/lib/sequel/model/base.rb +74 -18
  43. data/lib/sequel/model/errors.rb +8 -1
  44. data/lib/sequel/plugins/active_model.rb +8 -0
  45. data/lib/sequel/plugins/association_pks.rb +87 -0
  46. data/lib/sequel/plugins/association_proxies.rb +8 -0
  47. data/lib/sequel/plugins/boolean_readers.rb +12 -6
  48. data/lib/sequel/plugins/caching.rb +14 -7
  49. data/lib/sequel/plugins/class_table_inheritance.rb +15 -9
  50. data/lib/sequel/plugins/composition.rb +2 -1
  51. data/lib/sequel/plugins/force_encoding.rb +10 -7
  52. data/lib/sequel/plugins/hook_class_methods.rb +12 -11
  53. data/lib/sequel/plugins/identity_map.rb +9 -0
  54. data/lib/sequel/plugins/instance_hooks.rb +23 -13
  55. data/lib/sequel/plugins/lazy_attributes.rb +4 -1
  56. data/lib/sequel/plugins/many_through_many.rb +18 -4
  57. data/lib/sequel/plugins/nested_attributes.rb +1 -0
  58. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  59. data/lib/sequel/plugins/rcte_tree.rb +9 -8
  60. data/lib/sequel/plugins/schema.rb +8 -0
  61. data/lib/sequel/plugins/serialization.rb +1 -3
  62. data/lib/sequel/plugins/sharding.rb +135 -0
  63. data/lib/sequel/plugins/single_table_inheritance.rb +117 -25
  64. data/lib/sequel/plugins/skip_create_refresh.rb +35 -0
  65. data/lib/sequel/plugins/string_stripper.rb +26 -0
  66. data/lib/sequel/plugins/tactical_eager_loading.rb +8 -0
  67. data/lib/sequel/plugins/timestamps.rb +15 -2
  68. data/lib/sequel/plugins/touch.rb +13 -0
  69. data/lib/sequel/plugins/update_primary_key.rb +48 -0
  70. data/lib/sequel/plugins/validation_class_methods.rb +8 -0
  71. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  72. data/lib/sequel/sql.rb +17 -20
  73. data/lib/sequel/version.rb +1 -1
  74. data/spec/adapters/postgres_spec.rb +5 -5
  75. data/spec/core/core_sql_spec.rb +17 -1
  76. data/spec/core/database_spec.rb +17 -5
  77. data/spec/core/dataset_spec.rb +31 -8
  78. data/spec/core/schema_generator_spec.rb +8 -1
  79. data/spec/core/schema_spec.rb +13 -0
  80. data/spec/extensions/association_pks_spec.rb +85 -0
  81. data/spec/extensions/hook_class_methods_spec.rb +9 -9
  82. data/spec/extensions/migration_spec.rb +339 -219
  83. data/spec/extensions/schema_dumper_spec.rb +28 -17
  84. data/spec/extensions/sharding_spec.rb +272 -0
  85. data/spec/extensions/single_table_inheritance_spec.rb +92 -4
  86. data/spec/extensions/skip_create_refresh_spec.rb +17 -0
  87. data/spec/extensions/string_stripper_spec.rb +23 -0
  88. data/spec/extensions/update_primary_key_spec.rb +65 -0
  89. data/spec/extensions/validation_class_methods_spec.rb +5 -5
  90. data/spec/files/bad_down_migration/001_create_alt_basic.rb +4 -0
  91. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +4 -0
  92. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  93. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  94. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +3 -0
  95. data/spec/files/bad_up_migration/001_create_alt_basic.rb +4 -0
  96. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +3 -0
  97. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +9 -0
  98. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +9 -0
  99. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +4 -0
  100. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +9 -0
  101. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +9 -0
  102. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +4 -0
  103. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +4 -0
  104. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  105. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +9 -0
  106. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +4 -0
  107. data/spec/files/integer_migrations/001_create_sessions.rb +9 -0
  108. data/spec/files/integer_migrations/002_create_nodes.rb +9 -0
  109. data/spec/files/integer_migrations/003_3_create_users.rb +4 -0
  110. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  111. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +9 -0
  112. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  113. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +9 -0
  114. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +4 -0
  115. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +4 -0
  116. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +4 -0
  117. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  118. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +4 -0
  119. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +9 -0
  120. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +9 -0
  121. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +4 -0
  122. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +9 -0
  123. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +9 -0
  124. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +4 -0
  125. data/spec/integration/eager_loader_test.rb +20 -20
  126. data/spec/integration/migrator_test.rb +187 -0
  127. data/spec/integration/plugin_test.rb +150 -0
  128. data/spec/integration/schema_test.rb +13 -2
  129. data/spec/model/associations_spec.rb +41 -14
  130. data/spec/model/base_spec.rb +69 -0
  131. data/spec/model/eager_loading_spec.rb +7 -3
  132. data/spec/model/record_spec.rb +79 -4
  133. data/spec/model/validations_spec.rb +21 -9
  134. metadata +66 -5
  135. data/doc/schema.rdoc +0 -36
  136. data/lib/sequel/database/schema_sql.rb +0 -320
@@ -0,0 +1,85 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::AssociationPks" do
4
+ before do
5
+ @db = MODEL_DB.clone
6
+ mod = Module.new do
7
+ def fetch_rows(sql)
8
+ case sql
9
+ when "SELECT id FROM albums WHERE (albums.artist_id = 1)"
10
+ yield({:id=>1})
11
+ yield({:id=>2})
12
+ yield({:id=>3})
13
+ when /SELECT tag_id FROM albums_tags WHERE \(album_id = (\d)\)/
14
+ yield({:tag_id=>1}) if $1 == '1'
15
+ yield({:tag_id=>2}) if $1 != '3'
16
+ yield({:tag_id=>3}) if $1 == '2'
17
+ end
18
+ end
19
+ end
20
+ @db.meta_def(:dataset) do |*opts|
21
+ ds = super(*opts)
22
+ ds.extend mod
23
+ ds
24
+ end
25
+ def @db.transaction(opts)
26
+ execute('BEGIN')
27
+ yield
28
+ execute('COMMIT')
29
+ end
30
+ @Artist = Class.new(Sequel::Model(@db[:artists]))
31
+ @Artist.columns :id
32
+ @Album= Class.new(Sequel::Model(@db[:albums]))
33
+ @Album.columns :id, :artist_id
34
+ @Tag = Class.new(Sequel::Model(@db[:tags]))
35
+ @Tag.columns :id
36
+ @Artist.plugin :association_pks
37
+ @Album.plugin :association_pks
38
+ @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
39
+ @Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
40
+ @db.reset
41
+ end
42
+
43
+ specify "should return correct associated pks for one_to_many associations" do
44
+ @Artist.load(:id=>1).album_pks.should == [1,2,3]
45
+ @Artist.load(:id=>2).album_pks.should == []
46
+ end
47
+
48
+ specify "should return correct associated pks for many_to_many associations" do
49
+ @Album.load(:id=>1).tag_pks.should == [1, 2]
50
+ @Album.load(:id=>2).tag_pks.should == [2, 3]
51
+ @Album.load(:id=>3).tag_pks.should == []
52
+ end
53
+
54
+ specify "should set associated pks correctly for a one_to_many association" do
55
+ @Artist.load(:id=>1).album_pks = [1, 2]
56
+ @db.sqls.should == ["UPDATE albums SET artist_id = 1 WHERE (id IN (1, 2))",
57
+ "UPDATE albums SET artist_id = NULL WHERE ((albums.artist_id = 1) AND (id NOT IN (1, 2)))"]
58
+ end
59
+
60
+ specify "should set associated pks correctly for a many_to_many association" do
61
+ @Album.load(:id=>2).tag_pks = [1, 3]
62
+ @db.sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
63
+ @db.sqls[1].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
64
+ end
65
+
66
+ specify "should use transactions if the object is configured to use transactions" do
67
+ artist = @Artist.load(:id=>1)
68
+ artist.use_transactions = true
69
+ artist.album_pks = [1, 2]
70
+ @db.sqls.should == ["BEGIN",
71
+ "UPDATE albums SET artist_id = 1 WHERE (id IN (1, 2))",
72
+ "UPDATE albums SET artist_id = NULL WHERE ((albums.artist_id = 1) AND (id NOT IN (1, 2)))",
73
+ "COMMIT"]
74
+ @db.reset
75
+
76
+ album = @Album.load(:id=>2)
77
+ album.use_transactions = true
78
+ album.tag_pks = [1, 3]
79
+ @db.sqls[0].should == "BEGIN"
80
+ @db.sqls[1].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
81
+ @db.sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
82
+ @db.sqls[3].should == "COMMIT"
83
+ end
84
+
85
+ end
@@ -135,38 +135,38 @@ describe "Model hooks" do
135
135
  $adds.should == ['456']
136
136
  end
137
137
 
138
- specify "should stop processing if a hook returns false" do
138
+ specify "should stop processing if a before hook returns false" do
139
139
  $flag = true
140
140
  $adds = []
141
141
 
142
142
  a = Class.new(Sequel::Model)
143
143
  a.class_eval do
144
- after_save {$adds << 'blah'; $flag}
145
- after_save {$adds << 'cruel'}
144
+ before_save {$adds << 'cruel'; $flag}
145
+ before_save {$adds << 'blah'; $flag}
146
146
  end
147
147
 
148
- a.new.after_save
148
+ a.new.before_save
149
149
  $adds.should == ['blah', 'cruel']
150
150
 
151
151
  # chain should not break on nil
152
152
  $adds = []
153
153
  $flag = nil
154
- a.new.after_save
154
+ a.new.before_save
155
155
  $adds.should == ['blah', 'cruel']
156
156
 
157
157
  $adds = []
158
158
  $flag = false
159
- a.new.after_save
159
+ a.new.before_save
160
160
  $adds.should == ['blah']
161
161
 
162
162
  b = Class.new(a)
163
163
  b.class_eval do
164
- after_save {$adds << 'mau'}
164
+ before_save {$adds << 'mau'}
165
165
  end
166
166
 
167
167
  $adds = []
168
- b.new.after_save
169
- $adds.should == ['blah']
168
+ b.new.before_save
169
+ $adds.should == ['mau', 'blah']
170
170
  end
171
171
  end
172
172
 
@@ -1,152 +1,120 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
- context "Migration classes" do
3
+ context "Migration.descendants" do
4
4
  before do
5
5
  Sequel::Migration.descendants.clear
6
6
  end
7
7
 
8
- specify "should be registred in Migration.descendants" do
8
+ specify "should include Migration subclasses" do
9
9
  @class = Class.new(Sequel::Migration)
10
10
 
11
11
  Sequel::Migration.descendants.should == [@class]
12
12
  end
13
13
 
14
- specify "should be registered in the right order" do
14
+ specify "should include Migration subclasses in order of creation" do
15
15
  @c1 = Class.new(Sequel::Migration)
16
16
  @c2 = Class.new(Sequel::Migration)
17
17
  @c3 = Class.new(Sequel::Migration)
18
18
 
19
19
  Sequel::Migration.descendants.should == [@c1, @c2, @c3]
20
20
  end
21
+
22
+ specify "should include SimpleMigration instances created by migration DSL" do
23
+ i1 = Sequel.migration{}
24
+ i2 = Sequel.migration{}
25
+ i3 = Sequel.migration{}
26
+
27
+ Sequel::Migration.descendants.should == [i1, i2, i3]
28
+ end
21
29
  end
22
30
 
23
- context "Migration#apply" do
31
+ context "Migration.apply" do
24
32
  before do
25
33
  @c = Class.new do
26
34
  define_method(:one) {|x| [1111, x]}
27
35
  define_method(:two) {|x| [2222, x]}
28
36
  end
29
37
  @db = @c.new
30
-
31
- @migration = Class.new(Sequel::Migration) do
32
- define_method(:up) {one(3333)}
33
- define_method(:down) {two(4444)}
34
- end
35
38
  end
36
39
 
37
40
  specify "should raise for an invalid direction" do
38
- proc {@migration.apply(@db, :hahaha)}.should raise_error(ArgumentError)
41
+ proc {Sequel::Migration.apply(@db, :hahaha)}.should raise_error(ArgumentError)
39
42
  end
40
43
 
41
- specify "should apply the up direction correctly" do
42
- @migration.apply(@db, :up).should == [1111, 3333]
43
- end
44
-
45
- specify "should apply the down direction correctly" do
46
- @migration.apply(@db, :down).should == [2222, 4444]
47
- end
48
- end
49
-
50
- MIGRATION_001 = %[
51
- class CreateSessions < Sequel::Migration
52
- def up
53
- create(1111)
54
- end
55
-
56
- def down
57
- drop(1111)
44
+ specify "should apply the up and down directions correctly" do
45
+ m = Class.new(Sequel::Migration) do
46
+ define_method(:up) {one(3333)}
47
+ define_method(:down) {two(4444)}
58
48
  end
49
+ m.apply(@db, :up).should == [1111, 3333]
50
+ m.apply(@db, :down).should == [2222, 4444]
59
51
  end
60
- ]
61
52
 
62
- MIGRATION_002 = %[
63
- class CreateNodes < Sequel::Migration
64
- def up
65
- create(2222)
66
- end
67
-
68
- def down
69
- drop(2222)
70
- end
53
+ specify "should have default up and down actions that do nothing" do
54
+ m = Class.new(Sequel::Migration)
55
+ m.apply(@db, :up).should == nil
56
+ m.apply(@db, :down).should == nil
71
57
  end
72
- ]
58
+ end
73
59
 
74
- MIGRATION_003 = %[
75
- class CreateUsers < Sequel::Migration
76
- def up
77
- create(3333)
78
- end
79
-
80
- def down
81
- drop(3333)
60
+ context "SimpleMigration#apply" do
61
+ before do
62
+ @c = Class.new do
63
+ define_method(:one) {|x| [1111, x]}
64
+ define_method(:two) {|x| [2222, x]}
82
65
  end
66
+ @db = @c.new
83
67
  end
84
- ]
85
-
86
- MIGRATION_005 = %[
87
- class CreateAttributes < Sequel::Migration
88
- def up
89
- create(5555)
90
- end
91
-
92
- def down
93
- drop(5555)
94
- end
68
+
69
+ specify "should raise for an invalid direction" do
70
+ proc {Sequel.migration{}.apply(@db, :hahaha)}.should raise_error(ArgumentError)
95
71
  end
96
- ]
97
-
98
- ALT_MIGRATION_001 = %[
99
- class CreateAltBasic < Sequel::Migration
100
- def up
101
- create(11111)
102
- end
103
-
104
- def down
105
- drop(11111)
72
+
73
+ specify "should apply the up and down directions correctly" do
74
+ m = Sequel.migration do
75
+ up{one(3333)}
76
+ down{two(4444)}
106
77
  end
78
+ m.apply(@db, :up).should == [1111, 3333]
79
+ m.apply(@db, :down).should == [2222, 4444]
107
80
  end
108
- ]
109
81
 
110
- ALT_MIGRATION_003 = %[
111
- class CreateAltAdvanced < Sequel::Migration
112
- def up
113
- create(33333)
114
- end
115
-
116
- def down
117
- drop(33333)
118
- end
82
+ specify "should have default up and down actions that do nothing" do
83
+ m = Sequel.migration{}
84
+ m.apply(@db, :up).should == nil
85
+ m.apply(@db, :down).should == nil
119
86
  end
120
- ]
87
+ end
121
88
 
122
- context "Sequel::Migrator" do
89
+ context "Sequel::IntegerMigrator" do
123
90
  before do
124
91
  dbc = Class.new(MockDatabase) do
125
- attr_reader :creates, :drops, :tables_created, :columns_created, :versions
92
+ attr_reader :drops, :tables_created, :columns_created, :versions
126
93
  def initialize(*args)
127
94
  super
128
- @creates = []
129
95
  @drops = []
130
96
  @tables_created = []
131
97
  @columns_created = []
132
98
  @versions = {}
133
99
  end
134
100
 
135
- def create(x); @creates << x; end
136
- def drop(x); @drops << x; end
101
+ def version; versions.values.first || 0; end
102
+ def creates; @tables_created.map{|x| y = x.to_s; y !~ /\Asm(\d+)/; $1.to_i if $1}.compact; end
103
+ def drop_table(*a); super; @drops.concat(a.map{|x| y = x.to_s; y !~ /\Asm(\d+)/; $1.to_i if $1}.compact); end
137
104
 
138
105
  def create_table(name, opts={}, &block)
139
106
  super
140
- @columns_created << / \(?(\w+) integer\)?\z/.match(sqls.last)[1].to_sym
107
+ @columns_created << / \(?(\w+) integer.*\)?\z/.match(sqls.last)[1].to_sym
141
108
  @tables_created << name
142
109
  end
143
110
 
144
111
  def dataset(opts={})
145
112
  ds = super
146
113
  ds.extend(Module.new do
114
+ def count; 1; end
147
115
  def columns; db.columns_created end
148
- def insert(h); db.versions.merge!(h); super(h) end
149
- def update(h); db.versions.merge!(h); super(h) end
116
+ def insert(h); db.versions.merge!(h); db.sqls << insert_sql(h) end
117
+ def update(h); db.versions.merge!(h); db.sqls << update_sql(h) end
150
118
  def fetch_rows(sql); db.execute(sql); yield(db.versions) unless db.versions.empty? end
151
119
  end)
152
120
  ds
@@ -158,175 +126,327 @@ context "Sequel::Migrator" do
158
126
  end
159
127
  @db = dbc.new
160
128
 
161
- @dirname = "migrate_#{$$}"
162
- Dir.mkdir(@dirname)
163
- File.open("#{@dirname}/001_create_sessions.rb", 'w') {|f| f << MIGRATION_001}
164
- File.open("#{@dirname}/002_create_nodes.rb", 'w') {|f| f << MIGRATION_002}
165
- File.open("#{@dirname}/003_create_users.rb", 'w') {|f| f << MIGRATION_003}
166
- File.open("#{@dirname}/005_5_create_attributes.rb", 'w') {|f| f << MIGRATION_005}
167
-
168
- @alt_dirname = "migrate_alt_#{$$}"
169
- Dir.mkdir(@alt_dirname)
170
- File.open("#{@alt_dirname}/001_create_alt_basic.rb", 'w') {|f| f << ALT_MIGRATION_001}
171
- File.open("#{@alt_dirname}/003_create_alt_advanced.rb", 'w') {|f| f << ALT_MIGRATION_003}
129
+ @dirname = "spec/files/integer_migrations"
172
130
  end
173
131
 
174
132
  after do
175
133
  Object.send(:remove_const, "CreateSessions") if Object.const_defined?("CreateSessions")
176
- Object.send(:remove_const, "CreateNodes") if Object.const_defined?("CreateNodes")
177
- Object.send(:remove_const, "CreateUsers") if Object.const_defined?("CreateUsers")
178
- Object.send(:remove_const, "CreateAttributes") if Object.const_defined?("CreateAttributes")
179
- Object.send(:remove_const, "CreateAltBasic") if Object.const_defined?("CreateAltBasic")
180
- Object.send(:remove_const, "CreateAltAdvanced") if Object.const_defined?("CreateAltAdvanced")
181
-
182
- File.delete("#{@dirname}/001_create_sessions.rb")
183
- File.delete("#{@dirname}/002_create_nodes.rb")
184
- File.delete("#{@dirname}/003_create_users.rb")
185
- File.delete("#{@dirname}/005_5_create_attributes.rb")
186
- Dir.rmdir(@dirname)
187
- File.delete("#{@alt_dirname}/001_create_alt_basic.rb")
188
- File.delete("#{@alt_dirname}/003_create_alt_advanced.rb")
189
- Dir.rmdir(@alt_dirname)
190
134
  end
191
135
 
192
- specify "#migration_files should return the list of files for a specified version range" do
193
- Sequel::Migrator.migration_files(@dirname, 1..1).map{|f| File.basename(f)}.should == ['001_create_sessions.rb']
194
- Sequel::Migrator.migration_files(@dirname, 1..3).map{|f| File.basename(f)}.should == ['001_create_sessions.rb', '002_create_nodes.rb', '003_create_users.rb']
195
- Sequel::Migrator.migration_files(@dirname, 3..6).map{|f| File.basename(f)}.should == ['003_create_users.rb', '005_5_create_attributes.rb']
196
- Sequel::Migrator.migration_files(@dirname, 7..8).map{|f| File.basename(f)}.should == []
197
- Sequel::Migrator.migration_files(@alt_dirname, 1..1).map{|f| File.basename(f)}.should == ['001_create_alt_basic.rb']
198
- Sequel::Migrator.migration_files(@alt_dirname, 1..3).map{|f| File.basename(f)}.should == ['001_create_alt_basic.rb','003_create_alt_advanced.rb']
136
+ specify "should raise and error if there is a missing integer migration version" do
137
+ proc{Sequel::Migrator.apply(@db, "spec/files/missing_integer_migrations")}.should raise_error(Sequel::Migrator::Error)
199
138
  end
200
-
201
- specify "#latest_migration_version should return the latest version available" do
202
- Sequel::Migrator.latest_migration_version(@dirname).should == 5
203
- Sequel::Migrator.latest_migration_version(@alt_dirname).should == 3
139
+
140
+ specify "should raise and error if there is a duplicate integer migration version" do
141
+ proc{Sequel::Migrator.apply(@db, "spec/files/duplicate_integer_migrations")}.should raise_error(Sequel::Migrator::Error)
204
142
  end
205
-
206
- specify "#migration_classes should load the migration classes for the specified range for the up direction" do
207
- Sequel::Migrator.migration_classes(@dirname, 3, 0, :up).should == [CreateSessions, CreateNodes, CreateUsers]
208
- Sequel::Migrator.migration_classes(@alt_dirname, 3, 0, :up).should == [CreateAltBasic, CreateAltAdvanced]
143
+
144
+ specify "should add a column name if it doesn't already exist in the schema_info table" do
145
+ @db.create_table(:schema_info){Integer :v}
146
+ @db.should_receive(:alter_table).with(:schema_info)
147
+ Sequel::Migrator.apply(@db, @dirname)
209
148
  end
210
-
211
- specify "#migration_classes should load the migration classes for the specified range for the down direction" do
212
- Sequel::Migrator.migration_classes(@dirname, 0, 5, :down).should == [CreateAttributes, CreateUsers, CreateNodes, CreateSessions]
213
- Sequel::Migrator.migration_classes(@alt_dirname, 0, 3, :down).should == [CreateAltAdvanced, CreateAltBasic]
149
+
150
+ specify "should automatically create the schema_info table with the version column" do
151
+ @db.table_exists?(:schema_info).should be_false
152
+ Sequel::Migrator.run(@db, @dirname, :target=>0)
153
+ @db.table_exists?(:schema_info).should be_true
154
+ @db.dataset.columns.should == [:version]
214
155
  end
215
-
216
- specify "#migration_classes should start from current + 1 for the up direction" do
217
- Sequel::Migrator.migration_classes(@dirname, 3, 1, :up).should == [CreateNodes, CreateUsers]
218
- Sequel::Migrator.migration_classes(@alt_dirname, 3, 2, :up).should == [CreateAltAdvanced]
156
+
157
+ specify "should allow specifying the table and columns" do
158
+ @db.table_exists?(:si).should be_false
159
+ Sequel::Migrator.run(@db, @dirname, :target=>0, :table=>:si, :column=>:sic)
160
+ @db.table_exists?(:si).should be_true
161
+ @db.dataset.columns.should == [:sic]
219
162
  end
220
163
 
221
- specify "#migration_classes should end on current + 1 for the down direction" do
222
- Sequel::Migrator.migration_classes(@dirname, 2, 5, :down).should == [CreateAttributes, CreateUsers]
223
- Sequel::Migrator.migration_classes(@alt_dirname, 2, 4, :down).should == [CreateAltAdvanced]
164
+ specify "should apply migrations correctly in the up direction if no target is given" do
165
+ Sequel::Migrator.apply(@db, @dirname)
166
+ @db.creates.should == [1111, 2222, 3333]
167
+ @db.version.should == 3
168
+ @db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.should == [1, 2, 3]
169
+ end
170
+
171
+ specify "should apply migrations correctly in the up direction with target" do
172
+ Sequel::Migrator.apply(@db, @dirname, 2)
173
+ @db.creates.should == [1111, 2222]
174
+ @db.version.should == 2
175
+ @db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.should == [1, 2]
224
176
  end
225
177
 
226
- specify "#schema_info_dataset should automatically create the schema_info table" do
227
- @db.table_exists?(:schema_info).should be_false
228
- Sequel::Migrator.schema_info_dataset(@db)
229
- @db.table_exists?(:schema_info).should be_true
230
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)"]
178
+ specify "should apply migrations correctly in the up direction with target and existing" do
179
+ Sequel::Migrator.apply(@db, @dirname, 2, 1)
180
+ @db.creates.should == [2222]
181
+ @db.version.should == 2
182
+ @db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.should == [2]
231
183
  end
232
184
 
233
- specify "should automatically create new APP_version column in schema_info" do
234
- @db.table_exists?(:schema_info).should be_false
235
- Sequel::Migrator.schema_info_dataset(@db, :column => :alt_version)
236
- @db.table_exists?(:schema_info).should be_true
237
- @db.sqls.should == ["CREATE TABLE schema_info (alt_version integer)"]
185
+ specify "should apply migrations correctly in the down direction with target" do
186
+ @db.create_table(:schema_info){Integer :version, :default=>0}
187
+ @db[:schema_info].insert(:version=>3)
188
+ @db.version.should == 3
189
+ Sequel::Migrator.apply(@db, @dirname, 0)
190
+ @db.drops.should == [3333, 2222, 1111]
191
+ @db.version.should == 0
192
+ @db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.should == [2, 1, 0]
238
193
  end
239
194
 
240
- specify "should automatically create new APP_version column in schema_info" do
241
- @db.table_exists?(:alt_table).should be_false
242
- Sequel::Migrator.schema_info_dataset(@db, :table => :alt_table)
243
- @db.table_exists?(:alt_table).should be_true
244
- Sequel::Migrator.schema_info_dataset(@db, :table => :alt_table, :column=>:alt_version)
245
- @db.sqls.should == ["CREATE TABLE alt_table (version integer)",
246
- "ALTER TABLE alt_table ADD COLUMN alt_version integer"]
195
+ specify "should apply migrations correctly in the down direction with target and existing" do
196
+ Sequel::Migrator.apply(@db, @dirname, 1, 2)
197
+ @db.drops.should == [2222]
198
+ @db.version.should == 1
199
+ @db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.should == [1]
247
200
  end
248
201
 
249
- specify "should return a dataset for the correct table" do
250
- Sequel::Migrator.schema_info_dataset(@db).first_source_alias.should == :schema_info
251
- Sequel::Migrator.schema_info_dataset(@db, :table=>:blah).first_source_alias.should == :blah
202
+ specify "should return the target version" do
203
+ Sequel::Migrator.apply(@db, @dirname, 3, 2).should == 3
204
+ Sequel::Migrator.apply(@db, @dirname, 0).should == 0
205
+ Sequel::Migrator.apply(@db, @dirname).should == 3
252
206
  end
253
-
254
- specify "should assume a migration version of 0 if no migration information exists in the database" do
255
- Sequel::Migrator.get_current_migration_version(@db).should == 0
256
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)", "SELECT * FROM schema_info LIMIT 1"]
207
+ end
208
+
209
+ context "Sequel::TimestampMigrator" do
210
+ before do
211
+ $sequel_migration_version = 0
212
+ $sequel_migration_files = []
213
+ @dsc = dsc = Class.new(MockDataset) do
214
+ def columns
215
+ case opts[:from].first
216
+ when :schema_info
217
+ [:version]
218
+ when :schema_migrations
219
+ [:filename]
220
+ when :sm
221
+ [:fn]
222
+ end
223
+ end
224
+
225
+ def fetch_rows(sql)
226
+ case opts[:from].first
227
+ when :schema_info
228
+ yield({:version=>$sequel_migration_version})
229
+ when :schema_migrations
230
+ $sequel_migration_files.sort.each{|f| yield(:filename=>f)}
231
+ when :sm
232
+ $sequel_migration_files.sort.each{|f| yield(:fn=>f)}
233
+ end
234
+ end
235
+
236
+ def insert(h={})
237
+ case opts[:from].first
238
+ when :schema_info
239
+ $sequel_migration_version = h.values.first
240
+ when :schema_migrations, :sm
241
+ $sequel_migration_files << h.values.first
242
+ end
243
+ end
244
+
245
+ def update(h={})
246
+ case opts[:from].first
247
+ when :schema_info
248
+ $sequel_migration_version = h.values.first
249
+ end
250
+ end
251
+
252
+ def delete
253
+ case opts[:from].first
254
+ when :schema_migrations, :sm
255
+ $sequel_migration_files.delete(opts[:where].args.last)
256
+ end
257
+ end
258
+ end
259
+ dbc = Class.new(MockDatabase) do
260
+ tables = {}
261
+ define_method(:dataset){|*a| dsc.new(self, *a)}
262
+ define_method(:create_table){|name, *args| tables[name] = true}
263
+ define_method(:drop_table){|*names| names.each{|n| tables.delete(n)}}
264
+ define_method(:table_exists?){|name| tables.has_key?(name)}
265
+ end
266
+ @db = dbc.new
267
+ @m = Sequel::Migrator
257
268
  end
258
- specify "should use the migration version stored in the database" do
259
- Sequel::Migrator.schema_info_dataset(@db).insert(:version => 4321)
260
- Sequel::Migrator.get_current_migration_version(@db).should == 4321
261
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)", "INSERT INTO schema_info (version) VALUES (4321)", "SELECT * FROM schema_info LIMIT 1"]
269
+
270
+ after do
271
+ Object.send(:remove_const, "CreateSessions") if Object.const_defined?("CreateSessions")
272
+ Object.send(:remove_const, "CreateArtists") if Object.const_defined?("CreateArtists")
273
+ Object.send(:remove_const, "CreateAlbums") if Object.const_defined?("CreateAlbums")
262
274
  end
263
275
 
264
- specify "should set the migration version stored in the database" do
265
- Sequel::Migrator.set_current_migration_version(@db, 6666)
266
- Sequel::Migrator.get_current_migration_version(@db).should == 6666
267
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)",
268
- "SELECT * FROM schema_info LIMIT 1",
269
- "INSERT INTO schema_info (version) VALUES (6666)",
270
- "SELECT * FROM schema_info LIMIT 1"]
276
+ specify "should handle migrating up or down all the way" do
277
+ @dir = 'spec/files/timestamped_migrations'
278
+ @m.apply(@db, @dir)
279
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
280
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
281
+ @m.apply(@db, @dir, 0)
282
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
283
+ @db[:schema_migrations].select_order_map(:filename).should == []
271
284
  end
272
-
273
- specify "should apply migrations correctly in the up direction" do
274
- Sequel::Migrator.apply(@db, @dirname, 3, 2)
275
- @db.creates.should == [3333]
276
-
277
- Sequel::Migrator.get_current_migration_version(@db).should == 3
278
285
 
279
- Sequel::Migrator.apply(@db, @dirname, 5)
280
- @db.creates.should == [3333, 5555]
286
+ specify "should handle migrating up or down to specific timestamps" do
287
+ @dir = 'spec/files/timestamped_migrations'
288
+ @m.apply(@db, @dir, 1273253851)
289
+ [:schema_migrations, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
290
+ @db.table_exists?(:sm3333).should be_false
291
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb'
292
+ @m.apply(@db, @dir, 1273253849)
293
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
294
+ @db.table_exists?(:sm1111).should be_true
295
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb'
296
+ end
281
297
 
282
- Sequel::Migrator.get_current_migration_version(@db).should == 5
283
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)",
284
- "SELECT * FROM schema_info LIMIT 1",
285
- "INSERT INTO schema_info (version) VALUES (3)",
286
- "SELECT * FROM schema_info LIMIT 1",
287
- "SELECT * FROM schema_info LIMIT 1",
288
- "SELECT * FROM schema_info LIMIT 1",
289
- "UPDATE schema_info SET version = 5",
290
- "SELECT * FROM schema_info LIMIT 1"]
298
+ specify "should apply all missing files when migrating up" do
299
+ @dir = 'spec/files/timestamped_migrations'
300
+ @m.apply(@db, @dir)
301
+ @dir = 'spec/files/interleaved_timestamped_migrations'
302
+ @m.apply(@db, @dir)
303
+ [:schema_migrations, :sm1111, :sm1122, :sm2222, :sm2233, :sm3333].each{|n| @db.table_exists?(n).should be_true}
304
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253850_create_artists.rb 1273253851_create_nodes.rb 1273253852_create_albums.rb 1273253853_3_create_users.rb'
291
305
  end
292
-
293
- specify "should apply migrations correctly in the down direction" do
294
- Sequel::Migrator.apply(@db, @dirname, 1, 5)
295
- @db.drops.should == [5555, 3333, 2222]
296
306
 
297
- Sequel::Migrator.get_current_migration_version(@db).should == 1
298
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)",
299
- "SELECT * FROM schema_info LIMIT 1",
300
- "INSERT INTO schema_info (version) VALUES (1)",
301
- "SELECT * FROM schema_info LIMIT 1"]
307
+ specify "should not apply down action to migrations where up action hasn't been applied" do
308
+ @dir = 'spec/files/timestamped_migrations'
309
+ @m.apply(@db, @dir)
310
+ @dir = 'spec/files/interleaved_timestamped_migrations'
311
+ @m.apply(@db, @dir, 0)
312
+ [:sm1111, :sm1122, :sm2222, :sm2233, :sm3333].each{|n| @db.table_exists?(n).should be_false}
313
+ @db[:schema_migrations].select_order_map(:filename).should == []
302
314
  end
303
315
 
304
- specify "should apply migrations up to the latest version if no target is given" do
305
- Sequel::Migrator.apply(@db, @dirname)
306
- @db.creates.should == [1111, 2222, 3333, 5555]
316
+ specify "should handle updating to a specific timestamp when interleaving migrations" do
317
+ @dir = 'spec/files/timestamped_migrations'
318
+ @m.apply(@db, @dir)
319
+ @dir = 'spec/files/interleaved_timestamped_migrations'
320
+ @m.apply(@db, @dir, 1273253851)
321
+ [:schema_migrations, :sm1111, :sm1122, :sm2222].each{|n| @db.table_exists?(n).should be_true}
322
+ [:sm2233, :sm3333].each{|n| @db.table_exists?(n).should be_false}
323
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253850_create_artists.rb 1273253851_create_nodes.rb'
324
+ end
325
+
326
+ specify "should correctly update schema_migrations table when an error occurs when migrating up or down" do
327
+ @dir = 'spec/files/bad_timestamped_migrations'
328
+ proc{@m.apply(@db, @dir)}.should raise_error
329
+ [:schema_migrations, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
330
+ @db.table_exists?(:sm3333).should be_false
331
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb'
332
+ proc{@m.apply(@db, @dir, 0)}.should raise_error
333
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
334
+ @db.table_exists?(:sm1111).should be_true
335
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb'
336
+ end
337
+
338
+ specify "should handle multiple migrations with the same timestamp correctly" do
339
+ @dir = 'spec/files/duplicate_timestamped_migrations'
340
+ @m.apply(@db, @dir)
341
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
342
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253853_create_nodes.rb 1273253853_create_users.rb'
343
+ @m.apply(@db, @dir, 1273253853)
344
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
345
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253853_create_nodes.rb 1273253853_create_users.rb'
346
+ @m.apply(@db, @dir, 1273253849)
347
+ [:sm1111].each{|n| @db.table_exists?(n).should be_true}
348
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
349
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb'
350
+ @m.apply(@db, @dir, 1273253848)
351
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
352
+ @db[:schema_migrations].select_order_map(:filename).should == []
353
+ end
354
+
355
+ specify "should convert schema_info table to schema_migrations table" do
356
+ @dir = 'spec/files/integer_migrations'
357
+ @m.apply(@db, @dir)
358
+ [:schema_info, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
359
+ [:schema_migrations, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
360
+
361
+ @dir = 'spec/files/convert_to_timestamp_migrations'
362
+ @m.apply(@db, @dir)
363
+ [:schema_info, :sm1111, :sm2222, :sm3333, :schema_migrations, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_true}
364
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb 1273253850_create_artists.rb 1273253852_create_albums.rb'
365
+
366
+ @m.apply(@db, @dir, 4)
367
+ [:schema_info, :schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
368
+ [:sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
369
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb'
307
370
 
308
- Sequel::Migrator.get_current_migration_version(@db).should == 5
309
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)",
310
- "SELECT * FROM schema_info LIMIT 1",
311
- "SELECT * FROM schema_info LIMIT 1",
312
- "INSERT INTO schema_info (version) VALUES (5)",
313
- "SELECT * FROM schema_info LIMIT 1"]
371
+ @m.apply(@db, @dir, 0)
372
+ [:schema_info, :schema_migrations].each{|n| @db.table_exists?(n).should be_true}
373
+ [:sm1111, :sm2222, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
374
+ @db[:schema_migrations].select_order_map(:filename).should == []
314
375
  end
315
376
 
316
- specify "should apply migrations down to 0 version correctly" do
317
- Sequel::Migrator.apply(@db, @dirname, 0, 5)
318
- @db.drops.should == [5555, 3333, 2222, 1111]
377
+ specify "should handle unapplied migrations when migrating schema_info table to schema_migrations table" do
378
+ @dir = 'spec/files/integer_migrations'
379
+ @m.apply(@db, @dir, 2)
380
+ [:schema_info, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
381
+ [:schema_migrations, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
319
382
 
320
- Sequel::Migrator.get_current_migration_version(@db).should == 0
321
- @db.sqls.should == ["CREATE TABLE schema_info (version integer)",
322
- "SELECT * FROM schema_info LIMIT 1",
323
- "INSERT INTO schema_info (version) VALUES (0)",
324
- "SELECT * FROM schema_info LIMIT 1"]
383
+ @dir = 'spec/files/convert_to_timestamp_migrations'
384
+ @m.apply(@db, @dir, 1273253850)
385
+ [:schema_info, :sm1111, :sm2222, :sm3333, :schema_migrations, :sm1122].each{|n| @db.table_exists?(n).should be_true}
386
+ [:sm2233].each{|n| @db.table_exists?(n).should be_false}
387
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb 1273253850_create_artists.rb'
388
+ end
389
+
390
+ specify "should handle unapplied migrations when migrating schema_info table to schema_migrations table and target is less than last integer migration version" do
391
+ @dir = 'spec/files/integer_migrations'
392
+ @m.apply(@db, @dir, 1)
393
+ [:schema_info, :sm1111].each{|n| @db.table_exists?(n).should be_true}
394
+ [:schema_migrations, :sm2222, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
395
+
396
+ @dir = 'spec/files/convert_to_timestamp_migrations'
397
+ @m.apply(@db, @dir, 2)
398
+ [:schema_info, :sm1111, :sm2222, :schema_migrations].each{|n| @db.table_exists?(n).should be_true}
399
+ [:sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
400
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb'
401
+
402
+ @m.apply(@db, @dir)
403
+ [:schema_info, :sm1111, :sm2222, :schema_migrations, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_true}
404
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb 1273253850_create_artists.rb 1273253852_create_albums.rb'
405
+ end
406
+
407
+ specify "should raise error for applied migrations not in file system" do
408
+ @dir = 'spec/files/timestamped_migrations'
409
+ @m.apply(@db, @dir)
410
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
411
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
412
+
413
+ @dir = 'spec/files/missing_timestamped_migrations'
414
+ proc{@m.apply(@db, @dir, 0)}.should raise_error(Sequel::Migrator::Error)
415
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
416
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
325
417
  end
326
418
 
327
- specify "should return the target version" do
328
- Sequel::Migrator.apply(@db, @dirname, 3, 2).should == 3
329
- Sequel::Migrator.apply(@db, @dirname, 0).should == 0
330
- Sequel::Migrator.apply(@db, @dirname).should == 5
419
+ specify "should raise error missing column name in existing schema_migrations table" do
420
+ @dir = 'spec/files/timestamped_migrations'
421
+ @m.apply(@db, @dir)
422
+ proc{@m.run(@db, @dir, :column=>:fn)}.should raise_error(Sequel::Migrator::Error)
423
+ end
424
+
425
+ specify "should handle migration filenames in a case insensitive manner" do
426
+ @dir = 'spec/files/uppercase_timestamped_migrations'
427
+ @m.apply(@db, @dir)
428
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
429
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
430
+ @dir = 'spec/files/timestamped_migrations'
431
+ @m.apply(@db, @dir, 0)
432
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
433
+ @db[:schema_migrations].select_order_map(:filename).should == []
434
+ end
435
+
436
+ specify "should :table and :column options" do
437
+ @dir = 'spec/files/timestamped_migrations'
438
+ @m.run(@db, @dir, :table=>:sm, :column=>:fn)
439
+ [:sm, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
440
+ @db[:sm].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
441
+ @m.run(@db, @dir, :target=>0, :table=>:sm, :column=>:fn)
442
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
443
+ @db[:sm].select_order_map(:fn).should == []
444
+ end
445
+
446
+ specify "should return nil" do
447
+ @dir = 'spec/files/timestamped_migrations'
448
+ @m.apply(@db, @dir, 1273253850).should == nil
449
+ @m.apply(@db, @dir, 0).should == nil
450
+ @m.apply(@db, @dir).should == nil
331
451
  end
332
452
  end