sequel 3.28.0 → 3.29.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 (148) hide show
  1. data/CHANGELOG +119 -3
  2. data/Rakefile +5 -3
  3. data/bin/sequel +1 -5
  4. data/doc/model_hooks.rdoc +9 -1
  5. data/doc/opening_databases.rdoc +49 -40
  6. data/doc/prepared_statements.rdoc +27 -6
  7. data/doc/release_notes/3.28.0.txt +2 -2
  8. data/doc/release_notes/3.29.0.txt +459 -0
  9. data/doc/sharding.rdoc +7 -1
  10. data/doc/testing.rdoc +18 -9
  11. data/doc/transactions.rdoc +41 -1
  12. data/lib/sequel/adapters/ado.rb +28 -17
  13. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  14. data/lib/sequel/adapters/amalgalite.rb +11 -7
  15. data/lib/sequel/adapters/db2.rb +122 -70
  16. data/lib/sequel/adapters/dbi.rb +15 -15
  17. data/lib/sequel/adapters/do.rb +5 -36
  18. data/lib/sequel/adapters/do/mysql.rb +0 -5
  19. data/lib/sequel/adapters/do/postgres.rb +0 -5
  20. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  21. data/lib/sequel/adapters/firebird.rb +3 -6
  22. data/lib/sequel/adapters/ibmdb.rb +24 -16
  23. data/lib/sequel/adapters/informix.rb +2 -4
  24. data/lib/sequel/adapters/jdbc.rb +47 -11
  25. data/lib/sequel/adapters/jdbc/as400.rb +5 -24
  26. data/lib/sequel/adapters/jdbc/db2.rb +0 -5
  27. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  28. data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
  29. data/lib/sequel/adapters/jdbc/h2.rb +10 -12
  30. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  31. data/lib/sequel/adapters/jdbc/informix.rb +0 -5
  32. data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
  34. data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
  36. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
  38. data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
  39. data/lib/sequel/adapters/mock.rb +315 -0
  40. data/lib/sequel/adapters/mysql.rb +64 -51
  41. data/lib/sequel/adapters/mysql2.rb +15 -9
  42. data/lib/sequel/adapters/odbc.rb +13 -6
  43. data/lib/sequel/adapters/odbc/db2.rb +0 -4
  44. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  45. data/lib/sequel/adapters/openbase.rb +2 -4
  46. data/lib/sequel/adapters/oracle.rb +333 -51
  47. data/lib/sequel/adapters/postgres.rb +80 -27
  48. data/lib/sequel/adapters/shared/access.rb +0 -6
  49. data/lib/sequel/adapters/shared/db2.rb +13 -15
  50. data/lib/sequel/adapters/shared/firebird.rb +6 -6
  51. data/lib/sequel/adapters/shared/mssql.rb +23 -18
  52. data/lib/sequel/adapters/shared/mysql.rb +6 -6
  53. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  54. data/lib/sequel/adapters/shared/oracle.rb +185 -30
  55. data/lib/sequel/adapters/shared/postgres.rb +35 -18
  56. data/lib/sequel/adapters/shared/progress.rb +0 -6
  57. data/lib/sequel/adapters/shared/sqlite.rb +116 -37
  58. data/lib/sequel/adapters/sqlite.rb +16 -8
  59. data/lib/sequel/adapters/swift.rb +5 -5
  60. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  61. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  62. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  63. data/lib/sequel/adapters/tinytds.rb +13 -10
  64. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
  65. data/lib/sequel/core.rb +40 -0
  66. data/lib/sequel/database/connecting.rb +1 -2
  67. data/lib/sequel/database/dataset.rb +3 -3
  68. data/lib/sequel/database/dataset_defaults.rb +58 -0
  69. data/lib/sequel/database/misc.rb +62 -2
  70. data/lib/sequel/database/query.rb +113 -49
  71. data/lib/sequel/database/schema_methods.rb +7 -2
  72. data/lib/sequel/dataset/actions.rb +37 -19
  73. data/lib/sequel/dataset/features.rb +24 -0
  74. data/lib/sequel/dataset/graph.rb +7 -6
  75. data/lib/sequel/dataset/misc.rb +11 -3
  76. data/lib/sequel/dataset/mutation.rb +2 -3
  77. data/lib/sequel/dataset/prepared_statements.rb +6 -4
  78. data/lib/sequel/dataset/query.rb +46 -15
  79. data/lib/sequel/dataset/sql.rb +28 -4
  80. data/lib/sequel/extensions/named_timezones.rb +5 -0
  81. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  82. data/lib/sequel/model.rb +2 -1
  83. data/lib/sequel/model/associations.rb +115 -33
  84. data/lib/sequel/model/base.rb +91 -31
  85. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  86. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  87. data/lib/sequel/plugins/force_encoding.rb +6 -6
  88. data/lib/sequel/plugins/identity_map.rb +1 -1
  89. data/lib/sequel/plugins/many_through_many.rb +6 -10
  90. data/lib/sequel/plugins/prepared_statements.rb +12 -1
  91. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
  92. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  93. data/lib/sequel/plugins/serialization.rb +6 -1
  94. data/lib/sequel/plugins/sharding.rb +0 -5
  95. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  96. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  97. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  98. data/lib/sequel/timezones.rb +42 -42
  99. data/lib/sequel/version.rb +1 -1
  100. data/spec/adapters/mssql_spec.rb +29 -29
  101. data/spec/adapters/mysql_spec.rb +86 -104
  102. data/spec/adapters/oracle_spec.rb +48 -76
  103. data/spec/adapters/postgres_spec.rb +98 -33
  104. data/spec/adapters/spec_helper.rb +0 -5
  105. data/spec/adapters/sqlite_spec.rb +24 -21
  106. data/spec/core/connection_pool_spec.rb +9 -15
  107. data/spec/core/core_sql_spec.rb +20 -31
  108. data/spec/core/database_spec.rb +491 -227
  109. data/spec/core/dataset_spec.rb +638 -1051
  110. data/spec/core/expression_filters_spec.rb +0 -1
  111. data/spec/core/mock_adapter_spec.rb +378 -0
  112. data/spec/core/object_graph_spec.rb +48 -114
  113. data/spec/core/schema_generator_spec.rb +3 -3
  114. data/spec/core/schema_spec.rb +51 -114
  115. data/spec/core/spec_helper.rb +3 -90
  116. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  117. data/spec/extensions/dataset_associations_spec.rb +199 -0
  118. data/spec/extensions/instance_hooks_spec.rb +71 -0
  119. data/spec/extensions/named_timezones_spec.rb +22 -2
  120. data/spec/extensions/nested_attributes_spec.rb +3 -0
  121. data/spec/extensions/schema_spec.rb +1 -1
  122. data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
  123. data/spec/extensions/serialization_spec.rb +5 -8
  124. data/spec/extensions/spec_helper.rb +4 -0
  125. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  126. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  127. data/spec/integration/associations_test.rb +123 -12
  128. data/spec/integration/dataset_test.rb +140 -47
  129. data/spec/integration/eager_loader_test.rb +19 -21
  130. data/spec/integration/model_test.rb +80 -1
  131. data/spec/integration/plugin_test.rb +179 -128
  132. data/spec/integration/prepared_statement_test.rb +92 -91
  133. data/spec/integration/schema_test.rb +42 -23
  134. data/spec/integration/spec_helper.rb +25 -31
  135. data/spec/integration/timezone_test.rb +38 -12
  136. data/spec/integration/transaction_test.rb +161 -34
  137. data/spec/integration/type_test.rb +3 -3
  138. data/spec/model/association_reflection_spec.rb +83 -7
  139. data/spec/model/associations_spec.rb +393 -676
  140. data/spec/model/base_spec.rb +186 -116
  141. data/spec/model/dataset_methods_spec.rb +7 -27
  142. data/spec/model/eager_loading_spec.rb +343 -867
  143. data/spec/model/hooks_spec.rb +160 -79
  144. data/spec/model/model_spec.rb +118 -165
  145. data/spec/model/plugins_spec.rb +7 -13
  146. data/spec/model/record_spec.rb +138 -207
  147. data/spec/model/spec_helper.rb +10 -73
  148. metadata +14 -8
@@ -48,6 +48,10 @@ class MockDatabase < Sequel::Database
48
48
  self.identifier_input_method = nil
49
49
  self.identifier_output_method = nil
50
50
  attr_reader :sqls
51
+
52
+ def connect(opts)
53
+ Object.new
54
+ end
51
55
 
52
56
  def execute(sql, opts={})
53
57
  @sqls ||= []
@@ -39,7 +39,27 @@ describe "Sequel thread_local_timezones extension" do
39
39
  end
40
40
 
41
41
  it "should be thread safe" do
42
- [Thread.new{Sequel.thread_application_timezone = :utc; sleep 0.03; Sequel.application_timezone.should == :utc},
43
- Thread.new{sleep 0.01; Sequel.thread_application_timezone = :local; sleep 0.01; Sequel.application_timezone.should == :local}].each{|x| x.join}
42
+ q, q1, q2 = Queue.new, Queue.new, Queue.new
43
+ tz1, tz2 = nil, nil
44
+ t1 = Thread.new do
45
+ Sequel.thread_application_timezone = :utc
46
+ q2.push nil
47
+ q.pop
48
+ tz1 = Sequel.application_timezone
49
+ end
50
+ t2 = Thread.new do
51
+ Sequel.thread_application_timezone = :local
52
+ q2.push nil
53
+ q1.pop
54
+ tz2 = Sequel.application_timezone
55
+ end
56
+ q2.pop
57
+ q2.pop
58
+ q.push nil
59
+ q1.push nil
60
+ t1.join
61
+ t2.join
62
+ tz1.should == :utc
63
+ tz2.should == :local
44
64
  end
45
65
  end
@@ -2,22 +2,17 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe Sequel::Model, "TypecastOnLoad plugin" do
4
4
  before do
5
- @db = Sequel::Database.new({})
5
+ @db = Sequel.mock(:fetch=>{:id=>1, :b=>"1", :y=>"0"}, :columns=>[:id, :b, :y])
6
6
  def @db.schema(*args)
7
7
  [[:id, {}], [:y, {:type=>:boolean, :db_type=>'tinyint(1)'}], [:b, {:type=>:integer, :db_type=>'integer'}]]
8
8
  end
9
9
  @c = Class.new(Sequel::Model(@db[:items])) do
10
- include(Module.new{def _refresh(ds); values[:b] = b.to_s; self; end})
11
10
  attr_accessor :bset
12
11
  def b=(x)
13
12
  self.bset = true
14
13
  super
15
14
  end
16
15
  end
17
- @c.instance_eval do
18
- @columns = [:id, :b, :y]
19
- def columns; @columns; end
20
- end
21
16
  end
22
17
 
23
18
  specify "should call setter method with value when loading the object, for all given columns" do
@@ -8,7 +8,7 @@ shared_examples_for "eager limit strategies" do
8
8
  diff_album = @diff_album.call
9
9
  al, ar, t = @pr.call
10
10
 
11
- a = Artist.eager(:first_album, :last_album).all
11
+ a = Artist.eager(:first_album, :last_album).order(:name).all
12
12
  a.should == [@artist, ar]
13
13
  a.first.first_album.should == @album
14
14
  a.first.last_album.should == diff_album
@@ -20,7 +20,7 @@ shared_examples_for "eager limit strategies" do
20
20
  a.first.last_album.values.should == diff_album.values
21
21
 
22
22
  same_album = @same_album.call
23
- a = Artist.eager(:first_album).all
23
+ a = Artist.eager(:first_album).order(:name).all
24
24
  a.should == [@artist, ar]
25
25
  [@album, same_album].should include(a.first.first_album)
26
26
  a.last.first_album.should == nil
@@ -51,6 +51,9 @@ shared_examples_for "eager limit strategies" do
51
51
  end
52
52
 
53
53
  specify "should correctly handle limits and offsets when eager loading many_to_many associations" do
54
+ if @els == {:eager_limit_strategy=>:correlated_subquery} && Sequel.guarded?(:derby)
55
+ pending("Derby errors with correlated subqueries on many_to_many associations")
56
+ end
54
57
  Album.many_to_many :first_two_tags, {:clone=>:first_two_tags}.merge(@els) if @els
55
58
  Album.many_to_many :second_two_tags, {:clone=>:second_two_tags}.merge(@els) if @els
56
59
  Album.many_to_many :last_two_tags, {:clone=>:last_two_tags}.merge(@els) if @els
@@ -73,6 +76,9 @@ shared_examples_for "eager limit strategies" do
73
76
  end
74
77
 
75
78
  specify "should correctly handle limits and offsets when eager loading many_through_many associations" do
79
+ if @els == {:eager_limit_strategy=>:correlated_subquery} && Sequel.guarded?(:derby)
80
+ pending("Derby errors with correlated subqueries on many_through_many associations")
81
+ end
76
82
  Artist.many_through_many :first_two_tags, {:clone=>:first_two_tags}.merge(@els) if @els
77
83
  Artist.many_through_many :second_two_tags, {:clone=>:second_two_tags}.merge(@els) if @els
78
84
  Artist.many_through_many :last_two_tags, {:clone=>:last_two_tags}.merge(@els) if @els
@@ -102,6 +108,7 @@ shared_examples_for "regular and composite key associations" do
102
108
  @artist.first_album.should == nil
103
109
  @artist.albums.should == []
104
110
  @album.tags.should == []
111
+ @album.alias_tags.should == []
105
112
  @tag.albums.should == []
106
113
  end
107
114
 
@@ -117,6 +124,7 @@ shared_examples_for "regular and composite key associations" do
117
124
  @artist.first_album.should == @album
118
125
  @artist.albums.should == [@album]
119
126
  @album.tags.should == [@tag]
127
+ @album.alias_tags.should == [@tag]
120
128
  @tag.albums.should == [@album]
121
129
  end
122
130
 
@@ -133,6 +141,7 @@ shared_examples_for "regular and composite key associations" do
133
141
  @artist.first_album.should == @album
134
142
  @artist.albums.should == [@album]
135
143
  @album.tags.should == [@tag]
144
+ @album.alias_tags.should == [@tag]
136
145
  @tag.albums.should == [@album]
137
146
  end
138
147
 
@@ -144,6 +153,7 @@ shared_examples_for "regular and composite key associations" do
144
153
  Artist.filter(:first_album=>@album).all.should == [@artist]
145
154
  Album.filter(:artist=>@artist).all.should == [@album]
146
155
  Album.filter(:tags=>@tag).all.should == [@album]
156
+ Album.filter(:alias_tags=>@tag).all.should == [@album]
147
157
  Tag.filter(:albums=>@album).all.should == [@tag]
148
158
  Album.filter(:artist=>@artist, :tags=>@tag).all.should == [@album]
149
159
  @artist.albums_dataset.filter(:tags=>@tag).all.should == [@album]
@@ -158,6 +168,7 @@ shared_examples_for "regular and composite key associations" do
158
168
  Artist.exclude(:first_album=>@album).all.should == [artist]
159
169
  Album.exclude(:artist=>@artist).all.should == [album]
160
170
  Album.exclude(:tags=>@tag).all.should == [album]
171
+ Album.exclude(:alias_tags=>@tag).all.should == [album]
161
172
  Tag.exclude(:albums=>@album).all.should == [tag]
162
173
  Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [album]
163
174
  end
@@ -171,6 +182,7 @@ shared_examples_for "regular and composite key associations" do
171
182
  Artist.filter(:first_album=>[@album, album]).all.should == [@artist]
172
183
  Album.filter(:artist=>[@artist, artist]).all.should == [@album]
173
184
  Album.filter(:tags=>[@tag, tag]).all.should == [@album]
185
+ Album.filter(:alias_tags=>[@tag, tag]).all.should == [@album]
174
186
  Tag.filter(:albums=>[@album, album]).all.should == [@tag]
175
187
  Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
176
188
  @artist.albums_dataset.filter(:tags=>[@tag, tag]).all.should == [@album]
@@ -181,6 +193,7 @@ shared_examples_for "regular and composite key associations" do
181
193
  Artist.filter(:first_album=>[@album, album]).all.should == [@artist]
182
194
  Album.filter(:artist=>[@artist, artist]).all.should == [@album]
183
195
  Album.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
196
+ Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
184
197
  Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
185
198
  Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
186
199
 
@@ -190,6 +203,7 @@ shared_examples_for "regular and composite key associations" do
190
203
  Artist.filter(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
191
204
  Album.filter(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
192
205
  Album.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
206
+ Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
193
207
  Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
194
208
  Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
195
209
  end
@@ -201,6 +215,7 @@ shared_examples_for "regular and composite key associations" do
201
215
  Artist.exclude(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
202
216
  Album.exclude(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
203
217
  Album.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
218
+ Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
204
219
  Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
205
220
  Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
206
221
 
@@ -211,6 +226,7 @@ shared_examples_for "regular and composite key associations" do
211
226
  Artist.exclude(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [artist]
212
227
  Album.exclude(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [album]
213
228
  Album.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
229
+ Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
214
230
  Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [tag]
215
231
  Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
216
232
 
@@ -220,6 +236,7 @@ shared_examples_for "regular and composite key associations" do
220
236
  Artist.exclude(:first_album=>[@album, album]).all.should == [artist]
221
237
  Album.exclude(:artist=>[@artist, artist]).all.should == [album]
222
238
  Album.exclude(:tags=>[@tag, tag]).all.should == []
239
+ Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
223
240
  Tag.exclude(:albums=>[@album, album]).all.should == []
224
241
  Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [album]
225
242
 
@@ -229,6 +246,7 @@ shared_examples_for "regular and composite key associations" do
229
246
  Artist.exclude(:first_album=>[@album, album]).all.should == []
230
247
  Album.exclude(:artist=>[@artist, artist]).all.should == []
231
248
  Album.exclude(:tags=>[@tag, tag]).all.should == []
249
+ Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
232
250
  Tag.exclude(:albums=>[@album, album]).all.should == []
233
251
  Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == []
234
252
  end
@@ -238,6 +256,7 @@ shared_examples_for "regular and composite key associations" do
238
256
  Artist.exclude(:first_album=>@album).all.should == [@artist]
239
257
  Album.exclude(:artist=>@artist).all.should == [@album]
240
258
  Album.exclude(:tags=>@tag).all.should == [@album]
259
+ Album.exclude(:alias_tags=>@tag).all.should == [@album]
241
260
  Tag.exclude(:albums=>@album).all.should == [@tag]
242
261
  Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [@album]
243
262
 
@@ -248,11 +267,15 @@ shared_examples_for "regular and composite key associations" do
248
267
  specify "should handle NULL values in join table correctly when filtering/excluding many_to_many associations" do
249
268
  @ins.call
250
269
  Album.exclude(:tags=>@tag).all.should == [@album]
270
+ Album.exclude(:alias_tags=>@tag).all.should == [@album]
251
271
  @album.add_tag(@tag)
252
272
  Album.filter(:tags=>@tag).all.should == [@album]
273
+ Album.filter(:alias_tags=>@tag).all.should == [@album]
253
274
  album, artist, tag = @pr.call
254
275
  Album.exclude(:tags=>@tag).all.should == [album]
276
+ Album.exclude(:alias_tags=>@tag).all.should == [album]
255
277
  Album.exclude(:tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
278
+ Album.exclude(:alias_tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
256
279
  end
257
280
 
258
281
  specify "should work correctly when filtering by association datasets" do
@@ -274,6 +297,9 @@ shared_examples_for "regular and composite key associations" do
274
297
  Album.filter(:tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == [@album, album]
275
298
  Album.filter(:tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
276
299
  Album.filter(:tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
300
+ Album.filter(:alias_tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == [@album, album]
301
+ Album.filter(:alias_tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
302
+ Album.filter(:alias_tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
277
303
  Tag.filter(:albums=>Album.dataset).all.sort_by{|x| x.pk}.should == [@tag, tag]
278
304
  Tag.filter(:albums=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [tag]
279
305
  Tag.filter(:albums=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
@@ -295,17 +321,70 @@ shared_examples_for "regular and composite key associations" do
295
321
  Album.exclude(:tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == []
296
322
  Album.exclude(:tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
297
323
  Album.exclude(:tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
324
+ Album.exclude(:alias_tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == []
325
+ Album.exclude(:alias_tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
326
+ Album.exclude(:alias_tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
298
327
  Tag.exclude(:albums=>Album.dataset).all.sort_by{|x| x.pk}.should == []
299
328
  Tag.exclude(:albums=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@tag]
300
329
  Tag.exclude(:albums=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@tag, tag]
301
330
  end
302
331
 
332
+ specify "should have working dataset associations" do
333
+ album, artist, tag = @pr.call
334
+
335
+ Tag.albums.all.should == []
336
+ Album.artists.all.should == []
337
+ Album.tags.all.should == []
338
+ Album.alias_tags.all.should == []
339
+ Artist.albums.all.should == []
340
+ Artist.tags.all.should == []
341
+ Artist.albums.tags.all.should == []
342
+
343
+ @album.update(:artist => @artist)
344
+ @album.add_tag(@tag)
345
+
346
+ Tag.albums.all.should == [@album]
347
+ Album.artists.all.should == [@artist]
348
+ Album.tags.all.should == [@tag]
349
+ Album.alias_tags.all.should == [@tag]
350
+ Artist.albums.all.should == [@album]
351
+ Artist.tags.all.should == [@tag]
352
+ Artist.albums.tags.all.should == [@tag]
353
+
354
+ album.add_tag(tag)
355
+ album.update(:artist => artist)
356
+
357
+ Tag.albums.order(:name).all.should == [@album, album]
358
+ Album.artists.order(:name).all.should == [@artist, artist]
359
+ Album.tags.order(:name).all.should == [@tag, tag]
360
+ Album.alias_tags.order(:name).all.should == [@tag, tag]
361
+ Artist.albums.order(:name).all.should == [@album, album]
362
+ Artist.tags.order(:name).all.should == [@tag, tag]
363
+ Artist.albums.tags.order(:name).all.should == [@tag, tag]
364
+
365
+ Tag.filter(Tag.qualified_primary_key_hash(tag.pk)).albums.all.should == [album]
366
+ Album.filter(Album.qualified_primary_key_hash(album.pk)).artists.all.should == [artist]
367
+ Album.filter(Album.qualified_primary_key_hash(album.pk)).tags.all.should == [tag]
368
+ Album.filter(Album.qualified_primary_key_hash(album.pk)).alias_tags.all.should == [tag]
369
+ Artist.filter(Artist.qualified_primary_key_hash(artist.pk)).albums.all.should == [album]
370
+ Artist.filter(Artist.qualified_primary_key_hash(artist.pk)).tags.all.should == [tag]
371
+ Artist.filter(Artist.qualified_primary_key_hash(artist.pk)).albums.tags.all.should == [tag]
372
+
373
+ Artist.filter(Artist.qualified_primary_key_hash(artist.pk)).albums.filter(Album.qualified_primary_key_hash(album.pk)).tags.all.should == [tag]
374
+ Artist.filter(Artist.qualified_primary_key_hash(@artist.pk)).albums.filter(Album.qualified_primary_key_hash(@album.pk)).tags.all.should == [@tag]
375
+ Artist.filter(Artist.qualified_primary_key_hash(@artist.pk)).albums.filter(Album.qualified_primary_key_hash(album.pk)).tags.all.should == []
376
+ Artist.filter(Artist.qualified_primary_key_hash(artist.pk)).albums.filter(Album.qualified_primary_key_hash(@album.pk)).tags.all.should == []
377
+ end
378
+
303
379
  specify "should have remove methods work" do
304
380
  @album.update(:artist => @artist)
305
381
  @album.add_tag(@tag)
306
382
 
307
383
  @album.update(:artist => nil)
308
384
  @album.remove_tag(@tag)
385
+
386
+ @album.add_alias_tag(@tag)
387
+ @album.remove_alias_tag(@tag)
309
388
 
310
389
  @album.reload
311
390
  @artist.reload
@@ -315,6 +394,12 @@ shared_examples_for "regular and composite key associations" do
315
394
  @artist.albums.should == []
316
395
  @album.tags.should == []
317
396
  @tag.albums.should == []
397
+
398
+ @album.add_alias_tag(@tag)
399
+ @album.remove_alias_tag(@tag)
400
+
401
+ @album.reload
402
+ @album.alias_tags.should == []
318
403
  end
319
404
 
320
405
  specify "should have remove_all methods work" do
@@ -332,17 +417,24 @@ shared_examples_for "regular and composite key associations" do
332
417
  @artist.albums.should == []
333
418
  @album.tags.should == []
334
419
  @tag.albums.should == []
420
+
421
+ @album.add_alias_tag(@tag)
422
+ @album.remove_all_alias_tags
423
+
424
+ @album.reload
425
+ @album.alias_tags.should == []
335
426
  end
336
427
 
337
428
  specify "should eager load via eager correctly" do
338
429
  @album.update(:artist => @artist)
339
430
  @album.add_tag(@tag)
340
431
 
341
- a = Artist.eager(:albums=>:tags).eager(:first_album).all
432
+ a = Artist.eager(:albums=>[:tags, :alias_tags]).eager(:first_album).all
342
433
  a.should == [@artist]
343
434
  a.first.albums.should == [@album]
344
435
  a.first.first_album.should == @album
345
436
  a.first.albums.first.tags.should == [@tag]
437
+ a.first.albums.first.alias_tags.should == [@tag]
346
438
 
347
439
  a = Tag.eager(:albums=>:artist).all
348
440
  a.should == [@tag]
@@ -372,11 +464,12 @@ shared_examples_for "regular and composite key associations" do
372
464
  @album.update(:artist => @artist)
373
465
  @album.add_tag(@tag)
374
466
 
375
- a = Artist.eager_graph(:albums=>:tags).eager_graph(:first_album).all
467
+ a = Artist.eager_graph(:albums=>[:tags, :alias_tags]).eager_graph(:first_album).all
376
468
  a.should == [@artist]
377
469
  a.first.albums.should == [@album]
378
470
  a.first.first_album.should == @album
379
471
  a.first.albums.first.tags.should == [@tag]
472
+ a.first.albums.first.alias_tags.should == [@tag]
380
473
 
381
474
  a = Tag.eager_graph(:albums=>:artist).all
382
475
  a.should == [@tag]
@@ -415,7 +508,7 @@ shared_examples_for "regular and composite key associations" do
415
508
  end
416
509
 
417
510
  describe "Sequel::Model Simple Associations" do
418
- before do
511
+ before(:all) do
419
512
  @db = INTEGRATION_DB
420
513
  [:albums_tags, :tags, :albums, :artists].each{|t| @db.drop_table(t) rescue nil}
421
514
  @db.create_table(:artists) do
@@ -435,8 +528,12 @@ describe "Sequel::Model Simple Associations" do
435
528
  foreign_key :album_id, :albums
436
529
  foreign_key :tag_id, :tags
437
530
  end
531
+ end
532
+ before do
533
+ [:albums_tags, :tags, :albums, :artists].each{|t| @db[t].delete}
438
534
  class ::Artist < Sequel::Model(@db)
439
- one_to_many :albums
535
+ plugin :dataset_associations
536
+ one_to_many :albums, :order=>:name
440
537
  one_to_one :first_album, :class=>:Album, :order=>:name
441
538
  one_to_one :last_album, :class=>:Album, :order=>:name.desc
442
539
  one_to_many :first_two_albums, :class=>:Album, :order=>:name, :limit=>2
@@ -449,13 +546,16 @@ describe "Sequel::Model Simple Associations" do
449
546
  many_through_many :last_two_tags, :clone=>:tags, :order=>:tags__name.desc, :limit=>2
450
547
  end
451
548
  class ::Album < Sequel::Model(@db)
549
+ plugin :dataset_associations
452
550
  many_to_one :artist
453
551
  many_to_many :tags, :right_key=>:tag_id
552
+ many_to_many :alias_tags, :clone=>:tags, :join_table=>:albums_tags___at
454
553
  many_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
455
554
  many_to_many :second_two_tags, :clone=>:tags, :order=>:name, :limit=>[2, 1]
456
555
  many_to_many :last_two_tags, :clone=>:tags, :order=>:name.desc, :limit=>2
457
556
  end
458
557
  class ::Tag < Sequel::Model(@db)
558
+ plugin :dataset_associations
459
559
  many_to_many :albums
460
560
  end
461
561
  @album = Album.create(:name=>'Al')
@@ -469,9 +569,11 @@ describe "Sequel::Model Simple Associations" do
469
569
  @ins = lambda{@db[:albums_tags].insert(:tag_id=>@tag.id)}
470
570
  end
471
571
  after do
472
- @db.drop_table(:albums_tags, :tags, :albums, :artists)
473
572
  [:Tag, :Album, :Artist].each{|x| Object.send(:remove_const, x)}
474
573
  end
574
+ after(:all) do
575
+ @db.drop_table(:albums_tags, :tags, :albums, :artists)
576
+ end
475
577
 
476
578
  it_should_behave_like "regular and composite key associations"
477
579
 
@@ -480,7 +582,7 @@ describe "Sequel::Model Simple Associations" do
480
582
  @els = {:eager_limit_strategy=>:correlated_subquery}
481
583
  end
482
584
  it_should_behave_like "eager limit strategies"
483
- end unless [:mysql, :db2].include?(INTEGRATION_DB.database_type)
585
+ end unless Sequel.guarded?(:mysql, :db2, :oracle)
484
586
 
485
587
  specify "should handle aliased tables when eager_graphing" do
486
588
  @album.update(:artist => @artist)
@@ -588,7 +690,7 @@ describe "Sequel::Model Simple Associations" do
588
690
  end
589
691
 
590
692
  describe "Sequel::Model Composite Key Associations" do
591
- before do
693
+ before(:all) do
592
694
  @db = INTEGRATION_DB
593
695
  [:albums_tags, :tags, :albums, :artists].each{|t| @db.drop_table(t) rescue nil}
594
696
  @db.create_table(:artists) do
@@ -620,10 +722,14 @@ describe "Sequel::Model Composite Key Associations" do
620
722
  foreign_key [:album_id1, :album_id2], :albums
621
723
  foreign_key [:tag_id1, :tag_id2], :tags
622
724
  end
725
+ end
726
+ before do
727
+ [:albums_tags, :tags, :albums, :artists].each{|t| @db[t].delete}
623
728
  class ::Artist < Sequel::Model(@db)
729
+ plugin :dataset_associations
624
730
  set_primary_key :id1, :id2
625
731
  unrestrict_primary_key
626
- one_to_many :albums, :key=>[:artist_id1, :artist_id2]
732
+ one_to_many :albums, :key=>[:artist_id1, :artist_id2], :order=>:name
627
733
  one_to_one :first_album, :clone=>:albums, :order=>:name
628
734
  one_to_one :last_album, :clone=>:albums, :order=>:name.desc
629
735
  one_to_many :first_two_albums, :clone=>:albums, :order=>:name, :limit=>2
@@ -636,15 +742,18 @@ describe "Sequel::Model Composite Key Associations" do
636
742
  many_through_many :last_two_tags, :clone=>:tags, :order=>:tags__name.desc, :limit=>2
637
743
  end
638
744
  class ::Album < Sequel::Model(@db)
745
+ plugin :dataset_associations
639
746
  set_primary_key :id1, :id2
640
747
  unrestrict_primary_key
641
748
  many_to_one :artist, :key=>[:artist_id1, :artist_id2]
642
749
  many_to_many :tags, :left_key=>[:album_id1, :album_id2], :right_key=>[:tag_id1, :tag_id2]
750
+ many_to_many :alias_tags, :clone=>:tags, :join_table=>:albums_tags___at
643
751
  many_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
644
752
  many_to_many :second_two_tags, :clone=>:tags, :order=>:name, :limit=>[2, 1]
645
753
  many_to_many :last_two_tags, :clone=>:tags, :order=>:name.desc, :limit=>2
646
754
  end
647
755
  class ::Tag < Sequel::Model(@db)
756
+ plugin :dataset_associations
648
757
  set_primary_key :id1, :id2
649
758
  unrestrict_primary_key
650
759
  many_to_many :albums, :right_key=>[:album_id1, :album_id2], :left_key=>[:tag_id1, :tag_id2]
@@ -660,9 +769,11 @@ describe "Sequel::Model Composite Key Associations" do
660
769
  @ins = lambda{@db[:albums_tags].insert(:tag_id1=>@tag.id1, :tag_id2=>@tag.id2)}
661
770
  end
662
771
  after do
663
- @db.drop_table(:albums_tags, :tags, :albums, :artists)
664
772
  [:Tag, :Album, :Artist].each{|x| Object.send(:remove_const, x)}
665
773
  end
774
+ after(:all) do
775
+ @db.drop_table(:albums_tags, :tags, :albums, :artists)
776
+ end
666
777
 
667
778
  it_should_behave_like "regular and composite key associations"
668
779
 
@@ -671,7 +782,7 @@ describe "Sequel::Model Composite Key Associations" do
671
782
  @els = {:eager_limit_strategy=>:correlated_subquery}
672
783
  end
673
784
  it_should_behave_like "eager limit strategies"
674
- end if INTEGRATION_DB.dataset.supports_multiple_column_in? && ![:mysql, :db2].include?(INTEGRATION_DB.database_type)
785
+ end if INTEGRATION_DB.dataset.supports_multiple_column_in? && !Sequel.guarded?(:mysql, :db2, :oracle)
675
786
 
676
787
  specify "should have add method accept hashes and create new records" do
677
788
  @artist.remove_all_albums