sequel 4.9.0 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +79 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/Rakefile +2 -12
  6. data/bin/sequel +1 -0
  7. data/doc/advanced_associations.rdoc +82 -25
  8. data/doc/association_basics.rdoc +21 -22
  9. data/doc/core_extensions.rdoc +1 -1
  10. data/doc/opening_databases.rdoc +7 -0
  11. data/doc/release_notes/4.10.0.txt +226 -0
  12. data/doc/security.rdoc +1 -0
  13. data/doc/testing.rdoc +7 -7
  14. data/doc/transactions.rdoc +8 -0
  15. data/lib/sequel/adapters/jdbc.rb +160 -168
  16. data/lib/sequel/adapters/jdbc/db2.rb +17 -18
  17. data/lib/sequel/adapters/jdbc/derby.rb +5 -28
  18. data/lib/sequel/adapters/jdbc/h2.rb +11 -22
  19. data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
  20. data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
  21. data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
  22. data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
  23. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
  24. data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
  25. data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
  26. data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
  27. data/lib/sequel/adapters/openbase.rb +1 -7
  28. data/lib/sequel/adapters/postgres.rb +1 -1
  29. data/lib/sequel/adapters/shared/access.rb +3 -6
  30. data/lib/sequel/adapters/shared/cubrid.rb +24 -9
  31. data/lib/sequel/adapters/shared/db2.rb +13 -5
  32. data/lib/sequel/adapters/shared/firebird.rb +16 -16
  33. data/lib/sequel/adapters/shared/informix.rb +2 -5
  34. data/lib/sequel/adapters/shared/mssql.rb +72 -63
  35. data/lib/sequel/adapters/shared/mysql.rb +72 -40
  36. data/lib/sequel/adapters/shared/oracle.rb +27 -15
  37. data/lib/sequel/adapters/shared/postgres.rb +24 -44
  38. data/lib/sequel/adapters/shared/progress.rb +1 -5
  39. data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
  40. data/lib/sequel/adapters/shared/sqlite.rb +21 -6
  41. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
  42. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
  43. data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
  44. data/lib/sequel/core.rb +14 -9
  45. data/lib/sequel/database/dataset_defaults.rb +1 -0
  46. data/lib/sequel/database/misc.rb +12 -0
  47. data/lib/sequel/database/query.rb +4 -1
  48. data/lib/sequel/database/schema_methods.rb +3 -2
  49. data/lib/sequel/database/transactions.rb +47 -17
  50. data/lib/sequel/dataset/features.rb +12 -2
  51. data/lib/sequel/dataset/mutation.rb +2 -0
  52. data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
  53. data/lib/sequel/dataset/prepared_statements.rb +6 -0
  54. data/lib/sequel/dataset/query.rb +1 -1
  55. data/lib/sequel/dataset/sql.rb +132 -70
  56. data/lib/sequel/extensions/columns_introspection.rb +1 -1
  57. data/lib/sequel/extensions/null_dataset.rb +8 -4
  58. data/lib/sequel/extensions/pg_array.rb +4 -4
  59. data/lib/sequel/extensions/pg_row.rb +1 -0
  60. data/lib/sequel/model/associations.rb +468 -188
  61. data/lib/sequel/model/base.rb +88 -13
  62. data/lib/sequel/plugins/association_pks.rb +23 -64
  63. data/lib/sequel/plugins/auto_validations.rb +3 -2
  64. data/lib/sequel/plugins/dataset_associations.rb +1 -3
  65. data/lib/sequel/plugins/many_through_many.rb +18 -65
  66. data/lib/sequel/plugins/pg_array_associations.rb +97 -86
  67. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  68. data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
  69. data/lib/sequel/plugins/rcte_tree.rb +12 -16
  70. data/lib/sequel/plugins/sharding.rb +21 -3
  71. data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
  72. data/lib/sequel/plugins/subclasses.rb +1 -9
  73. data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
  74. data/lib/sequel/plugins/tree.rb +2 -2
  75. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  76. data/lib/sequel/version.rb +1 -1
  77. data/spec/adapters/mssql_spec.rb +57 -15
  78. data/spec/adapters/mysql_spec.rb +11 -0
  79. data/spec/bin_spec.rb +2 -2
  80. data/spec/core/database_spec.rb +38 -4
  81. data/spec/core/dataset_spec.rb +45 -7
  82. data/spec/core/placeholder_literalizer_spec.rb +17 -0
  83. data/spec/core/schema_spec.rb +6 -1
  84. data/spec/extensions/active_model_spec.rb +18 -9
  85. data/spec/extensions/association_pks_spec.rb +20 -18
  86. data/spec/extensions/association_proxies_spec.rb +9 -9
  87. data/spec/extensions/auto_validations_spec.rb +6 -0
  88. data/spec/extensions/columns_introspection_spec.rb +1 -0
  89. data/spec/extensions/constraint_validations_spec.rb +3 -1
  90. data/spec/extensions/many_through_many_spec.rb +191 -111
  91. data/spec/extensions/pg_array_associations_spec.rb +133 -103
  92. data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
  93. data/spec/extensions/rcte_tree_spec.rb +35 -27
  94. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
  95. data/spec/extensions/sharding_spec.rb +2 -2
  96. data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
  97. data/spec/extensions/to_dot_spec.rb +1 -0
  98. data/spec/extensions/touch_spec.rb +2 -2
  99. data/spec/integration/associations_test.rb +130 -37
  100. data/spec/integration/dataset_test.rb +17 -0
  101. data/spec/integration/model_test.rb +17 -0
  102. data/spec/integration/schema_test.rb +14 -0
  103. data/spec/integration/transaction_test.rb +25 -1
  104. data/spec/model/association_reflection_spec.rb +63 -24
  105. data/spec/model/associations_spec.rb +104 -57
  106. data/spec/model/base_spec.rb +14 -1
  107. data/spec/model/class_dataset_methods_spec.rb +1 -0
  108. data/spec/model/eager_loading_spec.rb +221 -74
  109. data/spec/model/model_spec.rb +119 -1
  110. metadata +4 -2
@@ -157,6 +157,14 @@ describe "Simple Dataset operations" do
157
157
  rows = []
158
158
  @ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5, :strategy=>:filter, :filter_values=>proc{|row, _| [row[:number] * 2]}){|row| rows << row}
159
159
  rows.should == (1..100).map{|i| {:id=>i, :number=>i*10}}
160
+
161
+ if DB.adapter_scheme == :jdbc
162
+ # check retrival with varying fetch sizes
163
+ array = (1..100).to_a
164
+ [1, 2, 5, 10, 33, 50, 100, 1000].each do |i|
165
+ @ds.with_fetch_size(i).select_order_map(:id).should == array
166
+ end
167
+ end
160
168
  end
161
169
 
162
170
  specify "should fetch all results correctly" do
@@ -187,6 +195,15 @@ describe "Simple Dataset operations" do
187
195
  @ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
188
196
  end
189
197
 
198
+ specify "should fetch correctly with just offset" do
199
+ @ds.order(:id).offset(0).all.should == [{:id=>1, :number=>10}]
200
+ @ds.order(:id).offset(1).all.should == []
201
+ @ds.insert(:number=>20)
202
+ @ds.order(:id).offset(0).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
203
+ @ds.order(:id).offset(1).all.should == [{:id=>2, :number=>20}]
204
+ @ds.order(:id).offset(2).all.should == []
205
+ end
206
+
190
207
  specify "should fetch correctly with a limit and offset using seperate methods" do
191
208
  @ds.order(:id).limit(2).offset(0).all.should == [{:id=>1, :number=>10}]
192
209
  @ds.order(:id).limit(2).offset(1).all.should == []
@@ -22,6 +22,23 @@ describe "Sequel::Model basic support" do
22
22
  Item.find(:name=>'J').should == Item.load(:id=>1, :name=>'J')
23
23
  end
24
24
 
25
+ specify ".finder should create method that returns first matching item" do
26
+ def Item.by_name(name) where(:name=>name) end
27
+ Item.finder :by_name
28
+ Item.first_by_name('J').should == nil
29
+ Item.create(:name=>'J')
30
+ Item.first_by_name('J').should == Item.load(:id=>1, :name=>'J')
31
+ Item.first_by_name(['J', 'K']).should == Item.load(:id=>1, :name=>'J')
32
+ end
33
+
34
+ specify ".prepared_finder should create method that returns first matching item" do
35
+ def Item.by_name(name) where(:name=>name) end
36
+ Item.prepared_finder :by_name
37
+ Item.first_by_name('J').should == nil
38
+ Item.create(:name=>'J')
39
+ Item.first_by_name('J').should == Item.load(:id=>1, :name=>'J')
40
+ end
41
+
25
42
  specify ".find_or_create should return first matching item, or create it if it doesn't exist" do
26
43
  Item.all.should == []
27
44
  Item.find_or_create(:name=>'J').should == Item.load(:id=>1, :name=>'J')
@@ -266,6 +266,10 @@ describe "Database schema modifiers" do
266
266
  @db[:items2].all.should == [{:number=>10}]
267
267
  end
268
268
 
269
+ specify "should not raise an error if table doesn't exist when using drop_table :if_exists" do
270
+ proc{@db.drop_table(:items, :if_exists=>true)}.should_not raise_error
271
+ end if DB.supports_drop_table_if_exists?
272
+
269
273
  describe "views" do
270
274
  before do
271
275
  @db.drop_view(:items_view) rescue nil
@@ -287,6 +291,16 @@ describe "Database schema modifiers" do
287
291
  @db[:items_view].map(:n).should == [1]
288
292
  end
289
293
 
294
+ specify "should drop views correctly" do
295
+ @db.create_view(:items_view, @ds.where(:number=>1))
296
+ @db.drop_view(:items_view)
297
+ proc{@db[:items_view].map(:number)}.should raise_error(Sequel::DatabaseError)
298
+ end
299
+
300
+ specify "should not raise an error if view doesn't exist when using drop_view :if_exists" do
301
+ proc{@db.drop_view(:items_view, :if_exists=>true)}.should_not raise_error
302
+ end if DB.supports_drop_table_if_exists?
303
+
290
304
  specify "should create or replace views correctly" do
291
305
  @db.create_or_replace_view(:items_view, @ds.where(:number=>1))
292
306
  @db[:items_view].map(:number).should == [1]
@@ -84,7 +84,7 @@ describe "Database transactions" do
84
84
  end
85
85
 
86
86
  if DB.supports_savepoints?
87
- cspecify "should support nested transactions through savepoints using the savepoint option", [:jdbc, :sqlite] do
87
+ specify "should support nested transactions through savepoints using the savepoint option" do
88
88
  @db.transaction do
89
89
  @d << {:name => '1'}
90
90
  @db.transaction(:savepoint=>true) do
@@ -107,6 +107,30 @@ describe "Database transactions" do
107
107
 
108
108
  @d.order(:name).map(:name).should == %w{1 4 5 6}
109
109
  end
110
+
111
+ specify "should support nested transactions through savepoints using the auto_savepoint option" do
112
+ @db.transaction(:auto_savepoint=>true) do
113
+ @d << {:name => '1'}
114
+ @db.transaction do
115
+ @d << {:name => '2'}
116
+ @db.transaction do
117
+ @d << {:name => '3'}
118
+ raise Sequel::Rollback
119
+ end
120
+ end
121
+ @d << {:name => '4'}
122
+ @db.transaction(:auto_savepoint=>true) do
123
+ @d << {:name => '6'}
124
+ @db.transaction do
125
+ @d << {:name => '7'}
126
+ raise Sequel::Rollback
127
+ end
128
+ end
129
+ @d << {:name => '5'}
130
+ end
131
+
132
+ @d.order(:name).map(:name).should == %w{1 4 5 6}
133
+ end
110
134
  end
111
135
 
112
136
  specify "should handle returning inside of the block by committing" do
@@ -282,9 +282,10 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
282
282
  end
283
283
  end
284
284
 
285
- describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strategy" do
285
+ describe Sequel::Model::Associations::AssociationReflection, "#filter_by_associations_limit_strategy" do
286
286
  before do
287
- @c = Class.new(Sequel::Model(:a))
287
+ @db = Sequel.mock
288
+ @c = Class.new(Sequel::Model(@db[:a]))
288
289
  end
289
290
  after do
290
291
  Sequel::Model.default_eager_limit_strategy = true
@@ -292,53 +293,83 @@ describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strat
292
293
 
293
294
  it "should be nil by default for *_one associations" do
294
295
  @c.many_to_one :c, :class=>@c
295
- @c.association_reflection(:c).eager_limit_strategy.should be_nil
296
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
296
297
  @c.one_to_one :c, :class=>@c
297
- @c.association_reflection(:c).eager_limit_strategy.should be_nil
298
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
299
+ @c.one_through_one :c, :class=>@c
300
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
298
301
  end
299
302
 
300
- it "should be :ruby by default for *_many associations" do
303
+ it "should be :correlated_subquery by default for one_to_many and one_to_one with :order associations" do
304
+ @c.one_to_one :c, :class=>@c, :order=>:a
305
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should == :correlated_subquery
301
306
  @c.one_to_many :cs, :class=>@c, :limit=>1
302
- @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
307
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :correlated_subquery
308
+ end
309
+
310
+ it "should be :ruby by default for many_to_many and one_through_one with :order associations" do
311
+ @c.one_through_one :c, :class=>@c, :order=>:a
312
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should == :ruby
303
313
  @c.many_to_many :cs, :class=>@c, :limit=>1
304
- @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
314
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :ruby
305
315
  end
306
316
 
307
- it "should be nil for many_to_one associations" do
317
+ it "should be nil for many_to_one associations even if :eager_limit_strategy or :filter_limit_strategy is used" do
308
318
  @c.many_to_one :c, :class=>@c, :eager_limit_strategy=>true
309
- @c.association_reflection(:c).eager_limit_strategy.should be_nil
319
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
310
320
  @c.many_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
311
- @c.association_reflection(:c).eager_limit_strategy.should be_nil
321
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
322
+ @c.many_to_one :c, :class=>@c, :filter_limit_strategy=>true
323
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
312
324
  end
313
325
 
314
326
  it "should be a symbol for other associations if given a symbol" do
315
327
  @c.one_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
316
- @c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
328
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should == :distinct_on
317
329
  @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>:window_function, :limit=>1
318
- @c.association_reflection(:cs).eager_limit_strategy.should == :window_function
330
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :window_function
319
331
  end
320
332
 
321
333
  it "should use :distinct_on for one_to_one associations if picking and the association dataset supports ordered distinct on" do
322
334
  def (@c.dataset).supports_ordered_distinct_on?() true end
323
335
  @c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
324
- @c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
336
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should == :distinct_on
325
337
  end
326
338
 
327
339
  it "should use :window_function for associations if picking and the association dataset supports window functions" do
328
340
  def (@c.dataset).supports_window_functions?() true end
329
341
  @c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
330
- @c.association_reflection(:c).eager_limit_strategy.should == :window_function
342
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should == :window_function
331
343
  @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
332
- @c.association_reflection(:cs).eager_limit_strategy.should == :window_function
344
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :window_function
333
345
  @c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
334
- @c.association_reflection(:cs).eager_limit_strategy.should == :window_function
346
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :window_function
335
347
  end
336
348
 
337
- it "should use :ruby for *_many associations if picking and the association dataset doesn't window functions" do
349
+ it "should use :ruby for one_to_many associations if the database doesn't support limits in subqueries" do
350
+ def (@c.dataset).supports_limits_in_correlated_subqueries?; false; end
338
351
  @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
339
- @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
352
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :ruby
353
+ end
354
+
355
+ it "should use :ruby for one_to_many associations if offset doesn't work in correlated subqueries and an offset is used" do
356
+ def (@c.dataset).supports_offsets_in_correlated_subqueries?; false; end
357
+ @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
358
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :correlated_subquery
359
+ @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>[1, 1]
360
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :ruby
361
+ end
362
+
363
+ it "should use :ruby for one_to_many associations if composite primary key is used and database does not multiple columns in IN" do
364
+ def (@c.dataset).supports_multiple_column_in?; false; end
365
+ @c.set_primary_key [:id, :id2]
366
+ @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1, :key=>[:id, :id2]
367
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :ruby
368
+ end
369
+
370
+ it "should use :ruby for many_to_many associations if picking and the association dataset doesn't window functions" do
340
371
  @c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
341
- @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
372
+ @c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :ruby
342
373
  end
343
374
 
344
375
  it "should respect Model.default_eager_limit_strategy to *_many associations" do
@@ -348,24 +379,32 @@ describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strat
348
379
  c.dataset = :a
349
380
  c.default_eager_limit_strategy.should == :window_function
350
381
  c.one_to_many :cs, :class=>c, :limit=>1
351
- c.association_reflection(:cs).eager_limit_strategy.should == :window_function
382
+ c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :window_function
352
383
  c.many_to_many :cs, :class=>c, :limit=>1
353
- c.association_reflection(:cs).eager_limit_strategy.should == :window_function
384
+ c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :window_function
354
385
 
355
386
  Sequel::Model.default_eager_limit_strategy = true
356
387
  c = Class.new(Sequel::Model)
357
388
  c.dataset = :a
358
389
  c.one_to_many :cs, :class=>c, :limit=>1
359
- c.association_reflection(:cs).eager_limit_strategy.should == :ruby
390
+ c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :correlated_subquery
360
391
  def (c.dataset).supports_window_functions?() true end
361
392
  c.many_to_many :cs, :class=>c, :limit=>1
362
- c.association_reflection(:cs).eager_limit_strategy.should == :window_function
393
+ c.association_reflection(:cs).send(:filter_by_associations_limit_strategy).should == :window_function
363
394
  end
364
395
 
365
396
  it "should ignore Model.default_eager_limit_strategy for one_to_one associations" do
366
397
  @c.default_eager_limit_strategy = :window_function
367
398
  @c.one_to_one :c, :class=>@c
368
- @c.association_reflection(:c).eager_limit_strategy.should be_nil
399
+ @c.association_reflection(:c).send(:filter_by_associations_limit_strategy).should be_nil
400
+ end
401
+ end
402
+
403
+ describe Sequel::Model::Associations::AssociationReflection, "#apply_eager_dataset_changes" do
404
+ it "should apply the eager block as well as the association options to the dataset" do
405
+ @c = Class.new(Sequel::Model(:foo))
406
+ @c.one_to_many :cs, :class=>@c, :select=>:a, :order=>:b do |ds| ds.where(:c) end
407
+ @c.association_reflection(:cs).apply_eager_dataset_changes(@c.dataset).sql.should == 'SELECT a FROM foo WHERE c ORDER BY b'
369
408
  end
370
409
  end
371
410
 
@@ -1860,19 +1860,19 @@ describe Sequel::Model, "many_to_many" do
1860
1860
 
1861
1861
  it "should use implicit key values and join table if omitted" do
1862
1862
  @c2.many_to_many :attributes, :class => @c1
1863
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
1863
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1864
1864
  end
1865
1865
 
1866
1866
  it "should use implicit key values and join table if omitted" do
1867
1867
  @c2.one_through_one :attribute, :class => @c1
1868
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
1868
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
1869
1869
  end
1870
1870
 
1871
1871
  it "should use implicit class if omitted" do
1872
1872
  begin
1873
1873
  class ::Tag < Sequel::Model; end
1874
1874
  @c2.many_to_many :tags
1875
- @c2.new(:id => 1234).tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
1875
+ @c2.new(:id => 1234).tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.tag_id = tags.id) WHERE (nodes_tags.node_id = 1234)'
1876
1876
  ensure
1877
1877
  Object.send(:remove_const, :Tag)
1878
1878
  end
@@ -1884,7 +1884,7 @@ describe Sequel::Model, "many_to_many" do
1884
1884
  class Tag < Sequel::Model; end
1885
1885
  end
1886
1886
  @c2.many_to_many :tags, :class=>'::Historical::Tag'
1887
- @c2.new(:id => 1234).tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
1887
+ @c2.new(:id => 1234).tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.tag_id = tags.id) WHERE (nodes_tags.node_id = 1234)'
1888
1888
  ensure
1889
1889
  Object.send(:remove_const, :Historical)
1890
1890
  end
@@ -1892,41 +1892,41 @@ describe Sequel::Model, "many_to_many" do
1892
1892
 
1893
1893
  it "should respect :eager_loader_predicate_key when lazily loading" do
1894
1894
  @c2.many_to_many :attributes, :class => @c1, :eager_loading_predicate_key=>Sequel.subscript(:attributes_nodes__node_id, 0)
1895
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id[0] = 1234))'
1895
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id[0] = 1234)'
1896
1896
  end
1897
1897
 
1898
1898
  it "should use explicit key values and join table if given" do
1899
1899
  @c2.many_to_many :attributes, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
1900
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234))'
1900
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON (attribute2node.attributeid = attributes.id) WHERE (attribute2node.nodeid = 1234)'
1901
1901
  end
1902
1902
 
1903
1903
  it "should support a conditions option" do
1904
1904
  @c2.many_to_many :attributes, :class => @c1, :conditions => {:a=>32}
1905
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32)'
1905
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234))'
1906
1906
 
1907
1907
  @c2.many_to_many :attributes, :class => @c1, :conditions => ['a = ?', 32]
1908
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32)'
1908
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234))'
1909
1909
  @c2.new(:id => 1234).attributes.should == [@c1.load({})]
1910
1910
  end
1911
1911
 
1912
1912
  it "should support an order option" do
1913
1913
  @c2.many_to_many :attributes, :class => @c1, :order => :blah
1914
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah'
1914
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah'
1915
1915
  end
1916
1916
 
1917
1917
  it "should support an array for the order option" do
1918
1918
  @c2.many_to_many :attributes, :class => @c1, :order => [:blah1, :blah2]
1919
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah1, blah2'
1919
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah1, blah2'
1920
1920
  end
1921
1921
 
1922
1922
  it "should support :left_primary_key and :right_primary_key options" do
1923
1923
  @c2.many_to_many :attributes, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
1924
- @c2.new(:id => 1234, :xxx=>5).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.yyy) AND (attributes_nodes.node_id = 5))'
1924
+ @c2.new(:id => 1234, :xxx=>5).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.yyy) WHERE (attributes_nodes.node_id = 5)'
1925
1925
  end
1926
1926
 
1927
1927
  it "should support composite keys" do
1928
1928
  @c2.many_to_many :attributes, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :y]
1929
- @c2.load(:id => 1234, :x=>5).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.r1 = attributes.id) AND (attributes_nodes.r2 = attributes.y) AND (attributes_nodes.l1 = 1234) AND (attributes_nodes.l2 = 5))'
1929
+ @c2.load(:id => 1234, :x=>5).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.r1 = attributes.id) AND (attributes_nodes.r2 = attributes.y)) WHERE ((attributes_nodes.l1 = 1234) AND (attributes_nodes.l2 = 5))'
1930
1930
  end
1931
1931
 
1932
1932
  it "should not issue query if not all keys have values" do
@@ -1951,13 +1951,13 @@ describe Sequel::Model, "many_to_many" do
1951
1951
  it "should support a select option" do
1952
1952
  @c2.many_to_many :attributes, :class => @c1, :select => :blah
1953
1953
 
1954
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
1954
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1955
1955
  end
1956
1956
 
1957
1957
  it "should support an array for the select option" do
1958
1958
  @c2.many_to_many :attributes, :class => @c1, :select => [Sequel::SQL::ColumnAll.new(:attributes), :attribute_nodes__blah2]
1959
1959
 
1960
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
1960
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1961
1961
  end
1962
1962
 
1963
1963
  it "should accept a block" do
@@ -1967,7 +1967,7 @@ describe Sequel::Model, "many_to_many" do
1967
1967
 
1968
1968
  n = @c2.new(:id => 1234)
1969
1969
  n.xxx = 555
1970
- n.attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555)'
1970
+ n.attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555))'
1971
1971
  end
1972
1972
 
1973
1973
  it "should allow the :order option while accepting a block" do
@@ -1977,7 +1977,7 @@ describe Sequel::Model, "many_to_many" do
1977
1977
 
1978
1978
  n = @c2.new(:id => 1234)
1979
1979
  n.xxx = 555
1980
- n.attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555) ORDER BY blah1, blah2'
1980
+ n.attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555)) ORDER BY blah1, blah2'
1981
1981
  end
1982
1982
 
1983
1983
  it "should support a :dataset option that is used instead of the default" do
@@ -1994,7 +1994,7 @@ describe Sequel::Model, "many_to_many" do
1994
1994
  end
1995
1995
 
1996
1996
  it "should support a :dataset option that accepts the reflection as an argument" do
1997
- @c2.many_to_many :attributes, :class => @c1, :dataset=>lambda{|opts| opts.associated_dataset.join_table(:natural, :an).filter(:an__nodeid=>pk)}, :order=> :a, :limit=>10, :select=>nil do |ds|
1997
+ @c2.many_to_many :attributes, :class => @c1, :dataset=>lambda{|opts| opts.associated_class.natural_join(:an).filter(:an__nodeid=>pk)}, :order=> :a, :limit=>10, :select=>nil do |ds|
1998
1998
  ds.filter(:xxx => @xxx)
1999
1999
  end
2000
2000
 
@@ -2007,9 +2007,9 @@ describe Sequel::Model, "many_to_many" do
2007
2007
 
2008
2008
  it "should support a :limit option" do
2009
2009
  @c2.many_to_many :attributes, :class => @c1 , :limit=>10
2010
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 10'
2010
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 10'
2011
2011
  @c2.many_to_many :attributes, :class => @c1 , :limit=>[10, 10]
2012
- @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 10 OFFSET 10'
2012
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 10 OFFSET 10'
2013
2013
  end
2014
2014
 
2015
2015
  it "should have the :eager option affect the _dataset method" do
@@ -2021,7 +2021,7 @@ describe Sequel::Model, "many_to_many" do
2021
2021
  @c2.many_to_many :attributes, :class => @c1, :join_table => :attribute2node___attributes_nodes
2022
2022
  n = @c2.load(:id => 1234)
2023
2023
  a = @c1.load(:id => 2345)
2024
- n.attributes_dataset.sql.should == "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))"
2024
+ n.attributes_dataset.sql.should == "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)"
2025
2025
  a.should == n.add_attribute(a)
2026
2026
  a.should == n.remove_attribute(a)
2027
2027
  n.remove_all_attributes
@@ -2062,7 +2062,6 @@ describe Sequel::Model, "many_to_many" do
2062
2062
  @c2.many_to_many :attributes, :class => @c1
2063
2063
 
2064
2064
  n = @c2.load(:id => 1234)
2065
- a = @c1.load(:id => 2345)
2066
2065
  @c1.dataset._fetch = []
2067
2066
  proc{n.add_attribute(2345)}.should raise_error(Sequel::NoMatchingRow)
2068
2067
  DB.sqls.should == ["SELECT * FROM attributes WHERE id = 2345"]
@@ -2100,7 +2099,7 @@ describe Sequel::Model, "many_to_many" do
2100
2099
  n = @c2.new(:id => 1234)
2101
2100
  @c1.dataset._fetch = {:id=>234}
2102
2101
  n.remove_attribute(234).should == @c1.load(:id => 234)
2103
- DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (attributes.id = 234) LIMIT 1",
2102
+ DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (attributes.id = 234)) LIMIT 1",
2104
2103
  "DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
2105
2104
  end
2106
2105
 
@@ -2192,8 +2191,8 @@ describe Sequel::Model, "many_to_many" do
2192
2191
  @c1.dataset._fetch = {:id=>234, :y=>8}
2193
2192
  @c1.load(:id => 234, :y=>8).should == n.remove_attribute([234, 8])
2194
2193
  sqls = DB.sqls
2195
- ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE ((attributes.id = 234) AND (attributes.y = 8)) LIMIT 1",
2196
- "SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE ((attributes.y = 8) AND (attributes.id = 234)) LIMIT 1"].should include(sqls.shift)
2194
+ ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (attributes.id = 234) AND (attributes.y = 8)) LIMIT 1",
2195
+ "SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (attributes.y = 8) AND (attributes.id = 234)) LIMIT 1"].should include(sqls.shift)
2197
2196
  sqls.should == ["DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 234))"]
2198
2197
  end
2199
2198
 
@@ -2255,7 +2254,7 @@ describe Sequel::Model, "many_to_many" do
2255
2254
  @c2.many_to_many :attributes, :class => @c1
2256
2255
 
2257
2256
  @c2.new(:id => 1234).attributes.should == [@c1.load({})]
2258
- DB.sqls.should == ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))']
2257
+ DB.sqls.should == ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)']
2259
2258
  end
2260
2259
 
2261
2260
  it "should populate cache when accessed" do
@@ -2282,7 +2281,7 @@ describe Sequel::Model, "many_to_many" do
2282
2281
  n = @c2.new(:id => 1234)
2283
2282
  n.associations[:attributes] = 42
2284
2283
  n.attributes(true).should_not == 42
2285
- DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))"]
2284
+ DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)"]
2286
2285
  end
2287
2286
 
2288
2287
  it "should add item to cache if it exists when calling add_" do
@@ -2608,7 +2607,7 @@ describe Sequel::Model, "many_to_many" do
2608
2607
 
2609
2608
  it "should support a :distinct option that uses the DISTINCT clause" do
2610
2609
  @c2.many_to_many :attributes, :class => @c1, :distinct=>true
2611
- @c2.load(:id=>10).attributes_dataset.sql.should == "SELECT DISTINCT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 10))"
2610
+ @c2.load(:id=>10).attributes_dataset.sql.should == "SELECT DISTINCT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 10)"
2612
2611
  end
2613
2612
 
2614
2613
  it "should not apply association options when removing all associated records" do
@@ -2625,7 +2624,7 @@ describe Sequel::Model, "many_to_many" do
2625
2624
  end
2626
2625
  @c1.dataset._fetch = {:id=>2}
2627
2626
  @c2.load(:id=>1).remove_attribute(2)
2628
- DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1)) WHERE ((join_table_att = 3) AND (attributes.id = 2)) LIMIT 1",
2627
+ DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1) AND (join_table_att = 3) AND (attributes.id = 2)) LIMIT 1",
2629
2628
  "DELETE FROM attributes_nodes WHERE ((node_id = 1) AND (attribute_id = 2))"]
2630
2629
  end
2631
2630
  end
@@ -2657,46 +2656,46 @@ describe Sequel::Model, "one_through_one" do
2657
2656
 
2658
2657
  it "should use implicit key values and join table if omitted" do
2659
2658
  @c2.one_through_one :attribute, :class => @c1
2660
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
2659
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
2661
2660
  end
2662
2661
 
2663
2662
  it "should respect :eager_loader_predicate_key when lazily loading" do
2664
2663
  @c2.one_through_one :attribute, :class => @c1, :eager_loading_predicate_key=>Sequel.subscript(:attributes_nodes__node_id, 0)
2665
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id[0] = 1234)) LIMIT 1'
2664
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id[0] = 1234) LIMIT 1'
2666
2665
  end
2667
2666
 
2668
2667
  it "should use explicit key values and join table if given" do
2669
2668
  @c2.one_through_one :attribute, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
2670
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234)) LIMIT 1'
2669
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON (attribute2node.attributeid = attributes.id) WHERE (attribute2node.nodeid = 1234) LIMIT 1'
2671
2670
  end
2672
2671
 
2673
2672
  it "should support a conditions option" do
2674
2673
  @c2.one_through_one :attribute, :class => @c1, :conditions => {:a=>32}
2675
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32) LIMIT 1'
2674
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
2676
2675
 
2677
2676
  @c2.one_through_one :attribute, :class => @c1, :conditions => ['a = ?', 32]
2678
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (a = 32) LIMIT 1'
2677
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((a = 32) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
2679
2678
  @c2.new(:id => 1234).attribute.should == @c1.load({})
2680
2679
  end
2681
2680
 
2682
2681
  it "should support an order option" do
2683
2682
  @c2.one_through_one :attribute, :class => @c1, :order => :blah
2684
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah LIMIT 1'
2683
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah LIMIT 1'
2685
2684
  end
2686
2685
 
2687
2686
  it "should support an array for the order option" do
2688
2687
  @c2.one_through_one :attribute, :class => @c1, :order => [:blah1, :blah2]
2689
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah1, blah2 LIMIT 1'
2688
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) ORDER BY blah1, blah2 LIMIT 1'
2690
2689
  end
2691
2690
 
2692
2691
  it "should support :left_primary_key and :right_primary_key options" do
2693
2692
  @c2.one_through_one :attribute, :class => @c1, :left_primary_key=>:xxx, :right_primary_key=>:yyy
2694
- @c2.new(:id => 1234, :xxx=>5).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.yyy) AND (attributes_nodes.node_id = 5)) LIMIT 1'
2693
+ @c2.new(:id => 1234, :xxx=>5).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.yyy) WHERE (attributes_nodes.node_id = 5) LIMIT 1'
2695
2694
  end
2696
2695
 
2697
2696
  it "should support composite keys" do
2698
2697
  @c2.one_through_one :attribute, :class => @c1, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :left_primary_key=>[:id, :x], :right_primary_key=>[:id, :y]
2699
- @c2.load(:id => 1234, :x=>5).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.r1 = attributes.id) AND (attributes_nodes.r2 = attributes.y) AND (attributes_nodes.l1 = 1234) AND (attributes_nodes.l2 = 5)) LIMIT 1'
2698
+ @c2.load(:id => 1234, :x=>5).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.r1 = attributes.id) AND (attributes_nodes.r2 = attributes.y)) WHERE ((attributes_nodes.l1 = 1234) AND (attributes_nodes.l2 = 5)) LIMIT 1'
2700
2699
  end
2701
2700
 
2702
2701
  it "should not issue query if not all keys have values" do
@@ -2721,13 +2720,13 @@ describe Sequel::Model, "one_through_one" do
2721
2720
  it "should support a select option" do
2722
2721
  @c2.one_through_one :attribute, :class => @c1, :select => :blah
2723
2722
 
2724
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
2723
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
2725
2724
  end
2726
2725
 
2727
2726
  it "should support an array for the select option" do
2728
2727
  @c2.one_through_one :attribute, :class => @c1, :select => [Sequel::SQL::ColumnAll.new(:attributes), :attribute_nodes__blah2]
2729
2728
 
2730
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1'
2729
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1'
2731
2730
  end
2732
2731
 
2733
2732
  it "should accept a block" do
@@ -2737,7 +2736,7 @@ describe Sequel::Model, "one_through_one" do
2737
2736
 
2738
2737
  n = @c2.new(:id => 1234)
2739
2738
  n.xxx = 555
2740
- n.attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555) LIMIT 1'
2739
+ n.attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555)) LIMIT 1'
2741
2740
  end
2742
2741
 
2743
2742
  it "should allow the :order option while accepting a block" do
@@ -2747,7 +2746,7 @@ describe Sequel::Model, "one_through_one" do
2747
2746
 
2748
2747
  n = @c2.new(:id => 1234)
2749
2748
  n.xxx = 555
2750
- n.attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555) ORDER BY blah1, blah2 LIMIT 1'
2749
+ n.attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE ((attributes_nodes.node_id = 1234) AND (xxx = 555)) ORDER BY blah1, blah2 LIMIT 1'
2751
2750
  end
2752
2751
 
2753
2752
  it "should support a :dataset option that is used instead of the default" do
@@ -2764,7 +2763,7 @@ describe Sequel::Model, "one_through_one" do
2764
2763
  end
2765
2764
 
2766
2765
  it "should support a :dataset option that accepts the reflection as an argument" do
2767
- @c2.one_through_one :attribute, :class => @c1, :dataset=>lambda{|opts| opts.associated_dataset.join_table(:natural, :an).filter(:an__nodeid=>pk)}, :order=> :a, :select=>nil do |ds|
2766
+ @c2.one_through_one :attribute, :class => @c1, :dataset=>lambda{|opts| opts.associated_class.natural_join(:an).filter(:an__nodeid=>pk)}, :order=> :a, :select=>nil do |ds|
2768
2767
  ds.filter(:xxx => @xxx)
2769
2768
  end
2770
2769
 
@@ -2777,7 +2776,7 @@ describe Sequel::Model, "one_through_one" do
2777
2776
 
2778
2777
  it "should support a :limit option to specify an offset" do
2779
2778
  @c2.one_through_one :attribute, :class => @c1 , :limit=>[nil, 10]
2780
- @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1 OFFSET 10'
2779
+ @c2.new(:id => 1234).attribute_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1 OFFSET 10'
2781
2780
  end
2782
2781
 
2783
2782
  it "should have the :eager option affect the _dataset method" do
@@ -2788,14 +2787,12 @@ describe Sequel::Model, "one_through_one" do
2788
2787
  it "should handle an aliased join table" do
2789
2788
  @c2.one_through_one :attribute, :class => @c1, :join_table => :attribute2node___attributes_nodes
2790
2789
  n = @c2.load(:id => 1234)
2791
- a = @c1.load(:id => 2345)
2792
- n.attribute_dataset.sql.should == "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1"
2790
+ n.attribute_dataset.sql.should == "SELECT attributes.* FROM attributes INNER JOIN attribute2node AS attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1"
2793
2791
  end
2794
2792
 
2795
2793
  it "should raise an error if the model object doesn't have a valid primary key" do
2796
2794
  @c2.one_through_one :attribute, :class => @c1
2797
2795
  a = @c2.new
2798
- n = @c1.load(:id=>123)
2799
2796
  proc{a.attribute_dataset}.should raise_error(Sequel::Error)
2800
2797
  end
2801
2798
 
@@ -2803,7 +2800,7 @@ describe Sequel::Model, "one_through_one" do
2803
2800
  @c2.one_through_one :attribute, :class => @c1
2804
2801
 
2805
2802
  @c2.new(:id => 1234).attribute.should == @c1.load({})
2806
- DB.sqls.should == ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1']
2803
+ DB.sqls.should == ['SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1']
2807
2804
  end
2808
2805
 
2809
2806
  it "should populate cache when accessed" do
@@ -2830,7 +2827,7 @@ describe Sequel::Model, "one_through_one" do
2830
2827
  n = @c2.new(:id => 1234)
2831
2828
  n.associations[:attribute] = 42
2832
2829
  n.attribute(true).should_not == 42
2833
- DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) LIMIT 1"]
2830
+ DB.sqls.should == ["SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234) LIMIT 1"]
2834
2831
  end
2835
2832
 
2836
2833
  it "should not add associations methods directly to class" do
@@ -2861,7 +2858,7 @@ describe Sequel::Model, "one_through_one" do
2861
2858
 
2862
2859
  it "should support a :distinct option that uses the DISTINCT clause" do
2863
2860
  @c2.one_through_one :attribute, :class => @c1, :distinct=>true
2864
- @c2.load(:id=>10).attribute_dataset.sql.should == "SELECT DISTINCT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 10)) LIMIT 1"
2861
+ @c2.load(:id=>10).attribute_dataset.sql.should == "SELECT DISTINCT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 10) LIMIT 1"
2865
2862
  end
2866
2863
  end
2867
2864
 
@@ -2888,6 +2885,7 @@ describe "Filtering by associations" do
2888
2885
 
2889
2886
  many_to_one :artist, :class=>artist, :key=>:artist_id
2890
2887
  one_to_many :tracks, :class=>track, :key=>:album_id
2888
+ one_to_one :track, :class=>track, :key=>:album_id
2891
2889
  one_to_one :album_info, :class=>album_info, :key=>:album_id
2892
2890
  many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags, :right_key=>:tag_id
2893
2891
 
@@ -2937,6 +2935,9 @@ describe "Filtering by associations" do
2937
2935
  one_through_one :al_ctag, :clone=>:l_ctag, :conditions=>c
2938
2936
  end
2939
2937
  end
2938
+ after do
2939
+ @Album.default_eager_limit_strategy = true
2940
+ end
2940
2941
 
2941
2942
  it "should be able to filter on many_to_one associations" do
2942
2943
  @Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id = 3)'
@@ -2994,6 +2995,47 @@ describe "Filtering by associations" do
2994
2995
  @Album.filter(:l_track=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
2995
2996
  end
2996
2997
 
2998
+ it "should be able to filter on one_to_one associations with :filter_limit_strategy" do
2999
+ @Album.one_to_one :l_track2, :clone=>:track, :filter_limit_strategy=>:window_function
3000
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
3001
+ end
3002
+
3003
+ it "should be able to filter on one_to_one associations with :eager_limit_strategy" do
3004
+ @Album.one_to_one :l_track2, :clone=>:track, :eager_limit_strategy=>:window_function
3005
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
3006
+ end
3007
+
3008
+ it "should be able to filter on one_to_one associations with :order and :filter_limit_strategy" do
3009
+ @Album.one_to_one :l_track2, :clone=>:l_track, :filter_limit_strategy=>:window_function
3010
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
3011
+ end
3012
+
3013
+ it "should be able to filter on one_to_one associations with :order and :eager_limit_strategy" do
3014
+ @Album.one_to_one :l_track2, :clone=>:l_track, :eager_limit_strategy=>:window_function
3015
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
3016
+ end
3017
+
3018
+ it "should be able to filter on one_to_one associations with :order and Model.default_eager_limit_strategy" do
3019
+ @Album.default_eager_limit_strategy = :window_function
3020
+ @Album.one_to_one :l_track2, :clone=>:l_track
3021
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1))) AND (tracks.id = 5))))"
3022
+ end
3023
+
3024
+ it "should be able to filter on one_to_one associations with :order and :eager_limit_strategy=>:union" do
3025
+ @Album.one_to_one :l_track2, :clone=>:l_track, :eager_limit_strategy=>:union
3026
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
3027
+ end
3028
+
3029
+ it "should be able to filter on one_to_one associations with :order and :eager_limit_strategy=>:ruby" do
3030
+ @Album.one_to_one :l_track2, :clone=>:l_track, :eager_limit_strategy=>:ruby
3031
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id) tracks.id FROM tracks ORDER BY tracks.album_id, name)) AND (tracks.id = 5))))"
3032
+ end
3033
+
3034
+ it "should be able to filter on one_to_one associations with :filter_limit_strategy :correlated_subquery" do
3035
+ @Album.one_to_one :l_track2, :clone=>:track, :filter_limit_strategy=>:correlated_subquery
3036
+ @Album.filter(:l_track2=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1)) AND (tracks.id = 5))))"
3037
+ end
3038
+
2997
3039
  it "should be able to filter on many_to_many associations with :limit" do
2998
3040
  @Album.filter(:l_tags=>@Tag.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((albums_tags.album_id IS NOT NULL) AND ((albums_tags.album_id, tags.id) IN (SELECT b, c FROM (SELECT albums_tags.album_id AS b, tags.id AS c, row_number() OVER (PARTITION BY albums_tags.album_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id)) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 3))))"
2999
3041
  end
@@ -3070,6 +3112,11 @@ describe "Filtering by associations" do
3070
3112
  @Album.filter(:l_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id1, tracks.album_id2) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tracks.id = 5))))"
3071
3113
  end
3072
3114
 
3115
+ it "should be able to filter on one_to_many associations with composite keys and :filter_limit_strategy :correlated_subquery" do
3116
+ @Album.one_to_one :l_ctracks2, :clone=>:l_ctracks, :filter_limit_strategy=>:correlated_subquery
3117
+ @Album.filter(:l_ctracks2=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE ((t1.album_id1 = tracks.album_id1) AND (t1.album_id2 = tracks.album_id2)) LIMIT 1)) AND (tracks.id = 5))))"
3118
+ end
3119
+
3073
3120
  it "should be able to filter on one_to_one associations with :order and composite keys" do
3074
3121
  @Album.filter(:l_ctrack=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT DISTINCT ON (tracks.album_id1, tracks.album_id2) tracks.id FROM tracks ORDER BY tracks.album_id1, tracks.album_id2, name)) AND (tracks.id = 5))))"
3075
3122
  end
@@ -3814,9 +3861,9 @@ describe "Sequel::Model Associations with clashing column names" do
3814
3861
  @Foo.first.bar.should == @bar
3815
3862
  @db.sqls.should == ["SELECT * FROM foos LIMIT 1", "SELECT * FROM bars WHERE (bars.object_id = 2) LIMIT 1"]
3816
3863
  @Foo.first.mtmbars.should == [@bar]
3817
- @db.sqls.should == ["SELECT * FROM foos LIMIT 1", "SELECT bars.* FROM bars INNER JOIN bars_foos ON ((bars_foos.object_id = bars.object_id) AND (bars_foos.foo_id = 2))"]
3864
+ @db.sqls.should == ["SELECT * FROM foos LIMIT 1", "SELECT bars.* FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE (bars_foos.foo_id = 2)"]
3818
3865
  @Bar.first.mtmfoos.should == [@foo]
3819
- @db.sqls.should == ["SELECT * FROM bars LIMIT 1", "SELECT foos.* FROM foos INNER JOIN bars_foos ON ((bars_foos.foo_id = foos.object_id) AND (bars_foos.object_id = 2))"]
3866
+ @db.sqls.should == ["SELECT * FROM bars LIMIT 1", "SELECT foos.* FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE (bars_foos.object_id = 2)"]
3820
3867
  end
3821
3868
 
3822
3869
  it "should have working eager loading methods" do
@@ -3828,10 +3875,10 @@ describe "Sequel::Model Associations with clashing column names" do
3828
3875
  @db.sqls.should == ["SELECT * FROM foos", "SELECT * FROM bars WHERE (bars.object_id IN (2))"]
3829
3876
  @db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
3830
3877
  @Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
3831
- @db.sqls.should == ["SELECT * FROM foos", "SELECT bars.*, bars_foos.foo_id AS x_foreign_key_x FROM bars INNER JOIN bars_foos ON ((bars_foos.object_id = bars.object_id) AND (bars_foos.foo_id IN (2)))"]
3878
+ @db.sqls.should == ["SELECT * FROM foos", "SELECT bars.*, bars_foos.foo_id AS x_foreign_key_x FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE (bars_foos.foo_id IN (2))"]
3832
3879
  @db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
3833
3880
  @Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
3834
- @db.sqls.should == ["SELECT * FROM bars", "SELECT foos.*, bars_foos.object_id AS x_foreign_key_x FROM foos INNER JOIN bars_foos ON ((bars_foos.foo_id = foos.object_id) AND (bars_foos.object_id IN (2)))"]
3881
+ @db.sqls.should == ["SELECT * FROM bars", "SELECT foos.*, bars_foos.object_id AS x_foreign_key_x FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE (bars_foos.object_id IN (2))"]
3835
3882
  end
3836
3883
 
3837
3884
  it "should have working eager graphing methods" do
@@ -3963,9 +4010,9 @@ describe "Sequel::Model Associations with non-column expression keys" do
3963
4010
  @Foo.first.bar.should == @bar
3964
4011
  @db.sqls.should == ["SELECT * FROM foos LIMIT 1", "SELECT * FROM bars WHERE (bars.object_ids[0] = 2) LIMIT 1"]
3965
4012
  @Foo.first.mtmbars.should == [@bar]
3966
- @db.sqls.should == ["SELECT * FROM foos LIMIT 1", "SELECT bars.* FROM bars INNER JOIN bars_foos ON ((bars_foos.bar_ids[0] = bars.object_ids[0]) AND (bars_foos.foo_ids[0] = 2))"]
4013
+ @db.sqls.should == ["SELECT * FROM foos LIMIT 1", "SELECT bars.* FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE (bars_foos.foo_ids[0] = 2)"]
3967
4014
  @Bar.first.mtmfoos.should == [@foo]
3968
- @db.sqls.should == ["SELECT * FROM bars LIMIT 1", "SELECT foos.* FROM foos INNER JOIN bars_foos ON ((bars_foos.foo_ids[0] = foos.object_ids[0]) AND (bars_foos.bar_ids[0] = 2))"]
4015
+ @db.sqls.should == ["SELECT * FROM bars LIMIT 1", "SELECT foos.* FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE (bars_foos.bar_ids[0] = 2)"]
3969
4016
  end
3970
4017
 
3971
4018
  it "should have working eager loading methods" do
@@ -3977,10 +4024,10 @@ describe "Sequel::Model Associations with non-column expression keys" do
3977
4024
  @db.sqls.should == ["SELECT * FROM foos", "SELECT * FROM bars WHERE (bars.object_ids[0] IN (2))"]
3978
4025
  @db.fetch = [[{:id=>1, :object_ids=>[2]}], [{:id=>1, :object_ids=>[2], :x_foreign_key_x=>2}]]
3979
4026
  @Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
3980
- @db.sqls.should == ["SELECT * FROM foos", "SELECT bars.*, bars_foos.foo_ids[0] AS x_foreign_key_x FROM bars INNER JOIN bars_foos ON ((bars_foos.bar_ids[0] = bars.object_ids[0]) AND (bars_foos.foo_ids[0] IN (2)))"]
4027
+ @db.sqls.should == ["SELECT * FROM foos", "SELECT bars.*, bars_foos.foo_ids[0] AS x_foreign_key_x FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE (bars_foos.foo_ids[0] IN (2))"]
3981
4028
  @db.fetch = [[{:id=>1, :object_ids=>[2]}], [{:id=>1, :object_ids=>[2], :x_foreign_key_x=>2}]]
3982
4029
  @Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
3983
- @db.sqls.should == ["SELECT * FROM bars", "SELECT foos.*, bars_foos.bar_ids[0] AS x_foreign_key_x FROM foos INNER JOIN bars_foos ON ((bars_foos.foo_ids[0] = foos.object_ids[0]) AND (bars_foos.bar_ids[0] IN (2)))"]
4030
+ @db.sqls.should == ["SELECT * FROM bars", "SELECT foos.*, bars_foos.bar_ids[0] AS x_foreign_key_x FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE (bars_foos.bar_ids[0] IN (2))"]
3984
4031
  end
3985
4032
 
3986
4033
  it "should have working eager graphing methods" do