sequel 4.9.0 → 4.10.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 (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