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
@@ -12,10 +12,10 @@ describe "Eagerly loading a tree structure" do
12
12
  one_to_many :children, :key=>:parent_id
13
13
 
14
14
  # Only useful when eager loading
15
- many_to_one :ancestors, :eager_loader=>(proc do |key_hash, nodes, associations|
15
+ many_to_one :ancestors, :eager_loader=>(proc do |eo|
16
16
  # Handle cases where the root node has the same parent_id as primary_key
17
17
  # and also when it is NULL
18
- non_root_nodes = nodes.reject do |n|
18
+ non_root_nodes = eo[:rows].reject do |n|
19
19
  if [nil, n.pk].include?(n.parent_id)
20
20
  # Make sure root nodes have their parent association set to nil
21
21
  n.associations[:parent] = nil
@@ -36,9 +36,9 @@ describe "Eagerly loading a tree structure" do
36
36
  end
37
37
  end
38
38
  end)
39
- many_to_one :descendants, :eager_loader=>(proc do |key_hash, nodes, associations|
39
+ many_to_one :descendants, :eager_loader=>(proc do |eo|
40
40
  id_map = {}
41
- nodes.each do |n|
41
+ eo[:rows].each do |n|
42
42
  # Initialize an empty array of child associations for each parent node
43
43
  n.associations[:children] = []
44
44
  # Populate identity map of nodes
@@ -186,9 +186,9 @@ describe "has_many :through has_many and has_one :through belongs_to" do
186
186
  inv.client.associations[:firm] = inv.associations[:firm] = firm
187
187
  end
188
188
  end), \
189
- :eager_loader=>(proc do |key_hash, firms, associations|
190
- id_map = key_hash[Firm.primary_key]
191
- firms.each{|firm| firm.associations[:invoices] = []}
189
+ :eager_loader=>(proc do |eo|
190
+ id_map = eo[:key_hash][Firm.primary_key]
191
+ eo[:rows].each{|firm| firm.associations[:invoices] = []}
192
192
  Invoice.eager_graph(:client).filter(:client__firm_id=>id_map.keys).all do |inv|
193
193
  id_map[inv.client.firm_id].each do |firm|
194
194
  firm.associations[:invoices] << inv
@@ -222,9 +222,9 @@ describe "has_many :through has_many and has_one :through belongs_to" do
222
222
  end
223
223
  inv.associations[:client] ||= firm.associations[:invoice_client]
224
224
  end), \
225
- :eager_loader=>(proc do |key_hash, invoices, associations|
225
+ :eager_loader=>(proc do |eo|
226
226
  id_map = {}
227
- invoices.each do |inv|
227
+ eo[:rows].each do |inv|
228
228
  inv.associations[:firm] = nil
229
229
  (id_map[inv.client_id] ||= []) << inv
230
230
  end
@@ -338,9 +338,9 @@ describe "Polymorphic Associations" do
338
338
  klass = m.call(attachable_type)
339
339
  klass.filter(klass.primary_key=>attachable_id)
340
340
  end), \
341
- :eager_loader=>(proc do |key_hash, assets, associations|
341
+ :eager_loader=>(proc do |eo|
342
342
  id_map = {}
343
- assets.each do |asset|
343
+ eo[:rows].each do |asset|
344
344
  asset.associations[:attachable] = nil
345
345
  ((id_map[asset.attachable_type] ||= {})[asset.attachable_id] ||= []) << asset
346
346
  end
@@ -492,9 +492,9 @@ describe "many_to_one/one_to_many not referencing primary key" do
492
492
  class ::Client < Sequel::Model
493
493
  one_to_many :invoices, :reciprocal=>:client, \
494
494
  :dataset=>proc{Invoice.filter(:client_name=>name)}, \
495
- :eager_loader=>(proc do |key_hash, clients, associations|
495
+ :eager_loader=>(proc do |eo|
496
496
  id_map = {}
497
- clients.each do |client|
497
+ eo[:rows].each do |client|
498
498
  id_map[client.name] = client
499
499
  client.associations[:invoices] = []
500
500
  end
@@ -526,9 +526,9 @@ describe "many_to_one/one_to_many not referencing primary key" do
526
526
  class ::Invoice < Sequel::Model
527
527
  many_to_one :client, :key=>:client_name, \
528
528
  :dataset=>proc{Client.filter(:name=>client_name)}, \
529
- :eager_loader=>(proc do |key_hash, invoices, associations|
530
- id_map = key_hash[:client_name]
531
- invoices.each{|inv| inv.associations[:client] = nil}
529
+ :eager_loader=>(proc do |eo|
530
+ id_map = eo[:key_hash][:client_name]
531
+ eo[:rows].each{|inv| inv.associations[:client] = nil}
532
532
  Client.filter(:name=>id_map.keys).all do |client|
533
533
  id_map[client.name].each{|inv| inv.associations[:client] = client}
534
534
  end
@@ -626,13 +626,13 @@ describe "statistics associations" do
626
626
  class ::Project < Sequel::Model
627
627
  many_to_one :ticket_hours, :read_only=>true, :key=>:id, :class=>:Ticket,
628
628
  :dataset=>proc{Ticket.filter(:project_id=>id).select{sum(hours).as(hours)}},
629
- :eager_loader=>(proc do |kh, projects, a|
630
- projects.each{|p| p.associations[:ticket_hours] = nil}
631
- Ticket.filter(:project_id=>kh[:id].keys).
629
+ :eager_loader=>(proc do |eo|
630
+ eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
631
+ Ticket.filter(:project_id=>eo[:key_hash][:id].keys).
632
632
  group(:project_id).
633
633
  select{[project_id.as(project_id), sum(hours).as(hours)]}.
634
634
  all do |t|
635
- p = kh[:id][t.values.delete(:project_id)].first
635
+ p = eo[:key_hash][:id][t.values.delete(:project_id)].first
636
636
  p.associations[:ticket_hours] = t
637
637
  end
638
638
  end)
@@ -0,0 +1,187 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+
3
+ Sequel.extension :migration
4
+ describe Sequel::Migrator do
5
+ before do
6
+ @db = INTEGRATION_DB
7
+ @m = Sequel::Migrator
8
+ end
9
+ after do
10
+ [:schema_info, :schema_migrations, :sm1111, :sm1122, :sm2222, :sm2233, :sm3333, :sm11111, :sm22222].each{|n| @db.drop_table(n) rescue nil}
11
+ end
12
+
13
+ specify "should be able to migrate up and down all the way successfully" do
14
+ @dir = 'spec/files/integer_migrations'
15
+ @m.apply(@db, @dir)
16
+ [:schema_info, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
17
+ @db[:schema_info].get(:version).should == 3
18
+ @m.apply(@db, @dir, 0)
19
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
20
+ @db[:schema_info].get(:version).should == 0
21
+ end
22
+
23
+ specify "should be able to migrate up and down to specific versions successfully" do
24
+ @dir = 'spec/files/integer_migrations'
25
+ @m.apply(@db, @dir, 2)
26
+ [:schema_info, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
27
+ @db.table_exists?(:sm3333).should be_false
28
+ @db[:schema_info].get(:version).should == 2
29
+ @m.apply(@db, @dir, 1)
30
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
31
+ @db.table_exists?(:sm1111).should be_true
32
+ @db[:schema_info].get(:version).should == 1
33
+ end
34
+
35
+ specify "should correctly set migration version to the last successful migration if the migration raises an error when migrating up" do
36
+ @dir = 'spec/files/bad_up_migration'
37
+ proc{@m.apply(@db, @dir)}.should raise_error
38
+ [:schema_info, :sm11111].each{|n| @db.table_exists?(n).should be_true}
39
+ @db.table_exists?(:sm22222).should be_false
40
+ @db[:schema_info].get(:version).should == 1
41
+ @m.apply(@db, @dir, 0)
42
+ [:sm11111, :sm22222].each{|n| @db.table_exists?(n).should be_false}
43
+ @db[:schema_info].get(:version).should == 0
44
+ end
45
+
46
+ specify "should correctly set migration version to the last successful migration if the migration raises an error when migrating down" do
47
+ @dir = 'spec/files/bad_down_migration'
48
+ @m.apply(@db, @dir)
49
+ [:schema_info, :sm11111, :sm22222].each{|n| @db.table_exists?(n).should be_true}
50
+ @db[:schema_info].get(:version).should == 2
51
+ proc{@m.apply(@db, @dir, 0)}.should raise_error
52
+ [:sm22222].each{|n| @db.table_exists?(n).should be_false}
53
+ @db.table_exists?(:sm11111).should be_true
54
+ @db[:schema_info].get(:version).should == 1
55
+ end
56
+
57
+ specify "should handle migrating up or down all the way with timestamped migrations" do
58
+ @dir = 'spec/files/timestamped_migrations'
59
+ @m.apply(@db, @dir)
60
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
61
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
62
+ @m.apply(@db, @dir, 0)
63
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
64
+ @db[:schema_migrations].select_order_map(:filename).should == []
65
+ end
66
+
67
+ specify "should handle migrating up or down to specific timestamps with timestamped migrations" do
68
+ @dir = 'spec/files/timestamped_migrations'
69
+ @m.apply(@db, @dir, 1273253851)
70
+ [:schema_migrations, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
71
+ @db.table_exists?(:sm3333).should be_false
72
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb'
73
+ @m.apply(@db, @dir, 1273253849)
74
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
75
+ @db.table_exists?(:sm1111).should be_true
76
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb'
77
+ end
78
+
79
+ specify "should apply all missing files when migrating up with timestamped migrations" do
80
+ @dir = 'spec/files/timestamped_migrations'
81
+ @m.apply(@db, @dir)
82
+ @dir = 'spec/files/interleaved_timestamped_migrations'
83
+ @m.apply(@db, @dir)
84
+ [:schema_migrations, :sm1111, :sm1122, :sm2222, :sm2233, :sm3333].each{|n| @db.table_exists?(n).should be_true}
85
+ @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'
86
+ end
87
+
88
+ specify "should not apply down action to migrations where up action hasn't been applied" do
89
+ @dir = 'spec/files/timestamped_migrations'
90
+ @m.apply(@db, @dir)
91
+ @dir = 'spec/files/interleaved_timestamped_migrations'
92
+ @m.apply(@db, @dir, 0)
93
+ [:sm1111, :sm1122, :sm2222, :sm2233, :sm3333].each{|n| @db.table_exists?(n).should be_false}
94
+ @db[:schema_migrations].select_order_map(:filename).should == []
95
+ end
96
+
97
+ specify "should handle updating to a specific timestamp when interleaving migrations with timestamps" do
98
+ @dir = 'spec/files/timestamped_migrations'
99
+ @m.apply(@db, @dir)
100
+ @dir = 'spec/files/interleaved_timestamped_migrations'
101
+ @m.apply(@db, @dir, 1273253851)
102
+ [:schema_migrations, :sm1111, :sm1122, :sm2222].each{|n| @db.table_exists?(n).should be_true}
103
+ [:sm2233, :sm3333].each{|n| @db.table_exists?(n).should be_false}
104
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253850_create_artists.rb 1273253851_create_nodes.rb'
105
+ end
106
+
107
+ specify "should correctly update schema_migrations table when an error occurs when migrating up or down using timestamped migrations" do
108
+ @dir = 'spec/files/bad_timestamped_migrations'
109
+ proc{@m.apply(@db, @dir)}.should raise_error
110
+ [:schema_migrations, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
111
+ @db.table_exists?(:sm3333).should be_false
112
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb'
113
+ proc{@m.apply(@db, @dir, 0)}.should raise_error
114
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
115
+ @db.table_exists?(:sm1111).should be_true
116
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb'
117
+ end
118
+
119
+ specify "should handle multiple migrations with the same timestamp correctly" do
120
+ @dir = 'spec/files/duplicate_timestamped_migrations'
121
+ @m.apply(@db, @dir)
122
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
123
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253853_create_nodes.rb 1273253853_create_users.rb'
124
+ @m.apply(@db, @dir, 1273253853)
125
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
126
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb 1273253853_create_nodes.rb 1273253853_create_users.rb'
127
+ @m.apply(@db, @dir, 1273253849)
128
+ [:sm1111].each{|n| @db.table_exists?(n).should be_true}
129
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
130
+ @db[:schema_migrations].select_order_map(:filename).should == %w'1273253849_create_sessions.rb'
131
+ @m.apply(@db, @dir, 1273253848)
132
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_false}
133
+ @db[:schema_migrations].select_order_map(:filename).should == []
134
+ end
135
+
136
+ specify "should convert schema_info table to schema_migrations table" do
137
+ @dir = 'spec/files/integer_migrations'
138
+ @m.apply(@db, @dir)
139
+ [:schema_info, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
140
+ [:schema_migrations, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
141
+
142
+ @dir = 'spec/files/convert_to_timestamp_migrations'
143
+ @m.apply(@db, @dir)
144
+ [:schema_info, :sm1111, :sm2222, :sm3333, :schema_migrations, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_true}
145
+ @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'
146
+
147
+ @m.apply(@db, @dir, 4)
148
+ [:schema_info, :schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).should be_true}
149
+ [:sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
150
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb'
151
+
152
+ @m.apply(@db, @dir, 0)
153
+ [:schema_info, :schema_migrations].each{|n| @db.table_exists?(n).should be_true}
154
+ [:sm1111, :sm2222, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
155
+ @db[:schema_migrations].select_order_map(:filename).should == []
156
+ end
157
+
158
+ specify "should handle unapplied migrations when migrating schema_info table to schema_migrations table" do
159
+ @dir = 'spec/files/integer_migrations'
160
+ @m.apply(@db, @dir, 2)
161
+ [:schema_info, :sm1111, :sm2222].each{|n| @db.table_exists?(n).should be_true}
162
+ [:schema_migrations, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
163
+
164
+ @dir = 'spec/files/convert_to_timestamp_migrations'
165
+ @m.apply(@db, @dir, 1273253850)
166
+ [:schema_info, :sm1111, :sm2222, :sm3333, :schema_migrations, :sm1122].each{|n| @db.table_exists?(n).should be_true}
167
+ [:sm2233].each{|n| @db.table_exists?(n).should be_false}
168
+ @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'
169
+ end
170
+
171
+ specify "should handle unapplied migrations when migrating schema_info table to schema_migrations table and target is less than last integer migration version" do
172
+ @dir = 'spec/files/integer_migrations'
173
+ @m.apply(@db, @dir, 1)
174
+ [:schema_info, :sm1111].each{|n| @db.table_exists?(n).should be_true}
175
+ [:schema_migrations, :sm2222, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
176
+
177
+ @dir = 'spec/files/convert_to_timestamp_migrations'
178
+ @m.apply(@db, @dir, 2)
179
+ [:schema_info, :sm1111, :sm2222, :schema_migrations].each{|n| @db.table_exists?(n).should be_true}
180
+ [:sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_false}
181
+ @db[:schema_migrations].select_order_map(:filename).should == %w'001_create_sessions.rb 002_create_nodes.rb'
182
+
183
+ @m.apply(@db, @dir)
184
+ [:schema_info, :sm1111, :sm2222, :schema_migrations, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).should be_true}
185
+ @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'
186
+ end
187
+ end
@@ -812,3 +812,153 @@ describe "Instance Filters plugin" do
812
812
  proc{@i.destroy}.should raise_error(Sequel::Error)
813
813
  end
814
814
  end
815
+
816
+ describe "UpdatePrimaryKey plugin" do
817
+ before do
818
+ @db = INTEGRATION_DB
819
+ @db.create_table!(:t) do
820
+ Integer :a, :primary_key=>true
821
+ Integer :b
822
+ end
823
+ @ds = @db[:t]
824
+ @ds.insert(:a=>1, :b=>3)
825
+ @c = Class.new(Sequel::Model(@ds))
826
+ @c.set_primary_key(:a)
827
+ @c.unrestrict_primary_key
828
+ @c.plugin :update_primary_key
829
+ end
830
+ after do
831
+ @db.drop_table(:t)
832
+ end
833
+
834
+ specify "should handle regular updates" do
835
+ @c.first.update(:b=>4)
836
+ @db[:t].all.should == [{:a=>1, :b=>4}]
837
+ @c.first.set(:b=>5).save
838
+ @db[:t].all.should == [{:a=>1, :b=>5}]
839
+ @c.first.set(:b=>6).save(:b)
840
+ @db[:t].all.should == [{:a=>1, :b=>6}]
841
+ end
842
+
843
+ specify "should handle updating the primary key field with another field" do
844
+ @c.first.update(:a=>2, :b=>4)
845
+ @db[:t].all.should == [{:a=>2, :b=>4}]
846
+ end
847
+
848
+ specify "should handle updating just the primary key field when saving changes" do
849
+ @c.first.update(:a=>2)
850
+ @db[:t].all.should == [{:a=>2, :b=>3}]
851
+ @c.first.set(:a=>3).save(:a)
852
+ @db[:t].all.should == [{:a=>3, :b=>3}]
853
+ end
854
+
855
+ specify "should handle saving after modifying the primary key field with another field" do
856
+ @c.first.set(:a=>2, :b=>4).save
857
+ @db[:t].all.should == [{:a=>2, :b=>4}]
858
+ end
859
+
860
+ specify "should handle saving after modifying just the primary key field" do
861
+ @c.first.set(:a=>2).save
862
+ @db[:t].all.should == [{:a=>2, :b=>3}]
863
+ end
864
+
865
+ specify "should handle saving after updating the primary key" do
866
+ @c.first.update(:a=>2).update(:b=>4).set(:b=>5).save
867
+ @db[:t].all.should == [{:a=>2, :b=>5}]
868
+ end
869
+ end
870
+
871
+ describe "AssociationPks plugin" do
872
+ before do
873
+ @db = INTEGRATION_DB
874
+ @db.create_table!(:artists) do
875
+ primary_key :id
876
+ String :name
877
+ end
878
+ @db.create_table!(:albums) do
879
+ primary_key :id
880
+ String :name
881
+ foreign_key :artist_id, :artists
882
+ end
883
+ @db.create_table!(:tags) do
884
+ primary_key :id
885
+ String :name
886
+ end
887
+ @db.create_table!(:albums_tags) do
888
+ foreign_key :album_id, :albums
889
+ foreign_key :tag_id, :tags
890
+ end
891
+ class ::Artist < Sequel::Model
892
+ plugin :association_pks
893
+ one_to_many :albums, :order=>:id
894
+ end
895
+ class ::Album < Sequel::Model
896
+ plugin :association_pks
897
+ many_to_many :tags, :order=>:id
898
+ end
899
+ class ::Tag < Sequel::Model
900
+ end
901
+
902
+ @ar1 =@db[:artists].insert(:name=>'YJM')
903
+ @ar2 =@db[:artists].insert(:name=>'AS')
904
+ @al1 =@db[:albums].insert(:name=>'RF', :artist_id=>@ar1)
905
+ @al2 =@db[:albums].insert(:name=>'MO', :artist_id=>@ar1)
906
+ @al3 =@db[:albums].insert(:name=>'T', :artist_id=>@ar1)
907
+ @t1 = @db[:tags].insert(:name=>'A')
908
+ @t2 = @db[:tags].insert(:name=>'B')
909
+ @t3 = @db[:tags].insert(:name=>'C')
910
+ {@al1=>[@t1, @t2, @t3], @al2=>[@t2]}.each do |aid, tids|
911
+ tids.each{|tid| @db[:albums_tags].insert([aid, tid])}
912
+ end
913
+ end
914
+ after do
915
+ @db.drop_table :albums_tags, :tags, :albums, :artists
916
+ [:Artist, :Album, :Tag].each{|s| Object.send(:remove_const, s)}
917
+ end
918
+
919
+ specify "should return correct associated pks for one_to_many associations" do
920
+ Artist.order(:id).all.map{|a| a.album_pks}.should == [[@al1, @al2, @al3], []]
921
+ end
922
+
923
+ specify "should return correct associated pks for many_to_many associations" do
924
+ Album.order(:id).all.map{|a| a.tag_pks.sort}.should == [[@t1, @t2, @t3], [@t2], []]
925
+ end
926
+
927
+ specify "should set associated pks correctly for a one_to_many association" do
928
+ Artist.use_transactions = true
929
+ Album.order(:id).select_map(:artist_id).should == [@ar1, @ar1, @ar1]
930
+
931
+ Artist[@ar2].album_pks = [@t1, @t3]
932
+ Artist[@ar1].album_pks.should == [@t2]
933
+ Album.order(:id).select_map(:artist_id).should == [@ar2, @ar1, @ar2]
934
+
935
+ Artist[@ar1].album_pks = [@t1]
936
+ Artist[@ar2].album_pks.should == [@t3]
937
+ Album.order(:id).select_map(:artist_id).should == [@ar1, nil, @ar2]
938
+
939
+ Artist[@ar1].album_pks = [@t1, @t2]
940
+ Artist[@ar2].album_pks.should == [@t3]
941
+ Album.order(:id).select_map(:artist_id).should == [@ar1, @ar1, @ar2]
942
+ end
943
+
944
+ specify "should set associated pks correctly for a many_to_many association" do
945
+ Artist.use_transactions = true
946
+ @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).should == [@t1, @t2, @t3]
947
+ Album[@al1].tag_pks = [@t1, @t3]
948
+ @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).should == [@t1, @t3]
949
+ Album[@al1].tag_pks = []
950
+ @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).should == []
951
+
952
+ @db[:albums_tags].filter(:album_id=>@al2).select_order_map(:tag_id).should == [@t2]
953
+ Album[@al2].tag_pks = [@t1, @t2]
954
+ @db[:albums_tags].filter(:album_id=>@al2).select_order_map(:tag_id).should == [@t1, @t2]
955
+ Album[@al2].tag_pks = []
956
+ @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).should == []
957
+
958
+ @db[:albums_tags].filter(:album_id=>@al3).select_order_map(:tag_id).should == []
959
+ Album[@al3].tag_pks = [@t1, @t3]
960
+ @db[:albums_tags].filter(:album_id=>@al3).select_order_map(:tag_id).should == [@t1, @t3]
961
+ Album[@al3].tag_pks = []
962
+ @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).should == []
963
+ end
964
+ end
@@ -109,7 +109,11 @@ describe "Database schema parser" do
109
109
  end
110
110
  end
111
111
 
112
- if INTEGRATION_DB.respond_to?(:indexes)
112
+ begin
113
+ INTEGRATION_DB.drop_table(:blah) rescue nil
114
+ INTEGRATION_DB.indexes(:blah)
115
+ rescue Sequel::NotImplemented
116
+ rescue
113
117
  describe "Database index parsing" do
114
118
  after do
115
119
  INTEGRATION_DB.drop_table(:items)
@@ -159,6 +163,10 @@ describe "Database schema modifiers" do
159
163
  @ds.columns!.should == [:number]
160
164
  end
161
165
 
166
+ specify "should create temporary tables without raising an exception" do
167
+ @db.create_table!(:items, :temp=>true){Integer :number}
168
+ end
169
+
162
170
  specify "should rename tables correctly" do
163
171
  @db.drop_table(:items) rescue nil
164
172
  @db.create_table!(:items2){Integer :number}
@@ -328,7 +336,10 @@ describe "Database schema modifiers" do
328
336
  end
329
337
  end
330
338
 
331
- if INTEGRATION_DB.respond_to?(:tables)
339
+ begin
340
+ INTEGRATION_DB.tables
341
+ rescue Sequel::NotImplemented
342
+ rescue
332
343
  describe "Database#tables" do
333
344
  before do
334
345
  class ::String