sequel 3.11.0 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.
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