sequel 2.10.0 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/CHANGELOG +51 -1
  2. data/README.rdoc +2 -2
  3. data/Rakefile +2 -2
  4. data/doc/advanced_associations.rdoc +6 -18
  5. data/doc/release_notes/1.0.txt +38 -0
  6. data/doc/release_notes/1.1.txt +143 -0
  7. data/doc/release_notes/1.3.txt +101 -0
  8. data/doc/release_notes/1.4.0.txt +53 -0
  9. data/doc/release_notes/1.5.0.txt +155 -0
  10. data/doc/release_notes/2.0.0.txt +298 -0
  11. data/doc/release_notes/2.1.0.txt +271 -0
  12. data/doc/release_notes/2.10.0.txt +328 -0
  13. data/doc/release_notes/2.11.0.txt +215 -0
  14. data/doc/release_notes/2.2.0.txt +253 -0
  15. data/doc/release_notes/2.3.0.txt +88 -0
  16. data/doc/release_notes/2.4.0.txt +106 -0
  17. data/doc/release_notes/2.5.0.txt +137 -0
  18. data/doc/release_notes/2.6.0.txt +157 -0
  19. data/doc/release_notes/2.7.0.txt +166 -0
  20. data/doc/release_notes/2.8.0.txt +171 -0
  21. data/doc/release_notes/2.9.0.txt +97 -0
  22. data/lib/sequel_core/adapters/ado.rb +3 -0
  23. data/lib/sequel_core/adapters/db2.rb +0 -11
  24. data/lib/sequel_core/adapters/dbi.rb +0 -11
  25. data/lib/sequel_core/adapters/do.rb +0 -12
  26. data/lib/sequel_core/adapters/firebird.rb +21 -16
  27. data/lib/sequel_core/adapters/informix.rb +1 -11
  28. data/lib/sequel_core/adapters/jdbc.rb +1 -13
  29. data/lib/sequel_core/adapters/jdbc/h2.rb +3 -11
  30. data/lib/sequel_core/adapters/jdbc/mysql.rb +0 -17
  31. data/lib/sequel_core/adapters/jdbc/postgresql.rb +3 -15
  32. data/lib/sequel_core/adapters/mysql.rb +31 -27
  33. data/lib/sequel_core/adapters/odbc.rb +34 -28
  34. data/lib/sequel_core/adapters/openbase.rb +0 -11
  35. data/lib/sequel_core/adapters/oracle.rb +11 -9
  36. data/lib/sequel_core/adapters/postgres.rb +14 -17
  37. data/lib/sequel_core/adapters/shared/mssql.rb +6 -15
  38. data/lib/sequel_core/adapters/shared/mysql.rb +29 -14
  39. data/lib/sequel_core/adapters/shared/oracle.rb +4 -0
  40. data/lib/sequel_core/adapters/shared/postgres.rb +30 -35
  41. data/lib/sequel_core/adapters/shared/progress.rb +4 -0
  42. data/lib/sequel_core/adapters/shared/sqlite.rb +73 -13
  43. data/lib/sequel_core/adapters/sqlite.rb +8 -18
  44. data/lib/sequel_core/adapters/utils/date_format.rb +21 -0
  45. data/lib/sequel_core/{dataset → adapters/utils}/stored_procedures.rb +0 -0
  46. data/lib/sequel_core/{dataset → adapters/utils}/unsupported.rb +0 -0
  47. data/lib/sequel_core/core_ext.rb +1 -1
  48. data/lib/sequel_core/core_sql.rb +9 -4
  49. data/lib/sequel_core/database.rb +63 -62
  50. data/lib/sequel_core/dataset.rb +9 -4
  51. data/lib/sequel_core/dataset/convenience.rb +10 -9
  52. data/lib/sequel_core/dataset/prepared_statements.rb +1 -1
  53. data/lib/sequel_core/dataset/sql.rb +130 -36
  54. data/lib/sequel_core/schema/sql.rb +2 -2
  55. data/lib/sequel_core/sql.rb +44 -51
  56. data/lib/sequel_core/version.rb +1 -1
  57. data/lib/sequel_model/associations.rb +25 -17
  58. data/lib/sequel_model/base.rb +35 -7
  59. data/lib/sequel_model/caching.rb +1 -6
  60. data/lib/sequel_model/record.rb +23 -5
  61. data/lib/sequel_model/validations.rb +20 -5
  62. data/spec/adapters/firebird_spec.rb +6 -1
  63. data/spec/adapters/mysql_spec.rb +12 -0
  64. data/spec/adapters/postgres_spec.rb +2 -2
  65. data/spec/adapters/sqlite_spec.rb +81 -2
  66. data/spec/integration/dataset_test.rb +2 -2
  67. data/spec/integration/type_test.rb +12 -2
  68. data/spec/sequel_core/core_sql_spec.rb +46 -12
  69. data/spec/sequel_core/database_spec.rb +24 -12
  70. data/spec/sequel_core/dataset_spec.rb +82 -32
  71. data/spec/sequel_core/schema_spec.rb +16 -0
  72. data/spec/sequel_model/associations_spec.rb +89 -0
  73. data/spec/sequel_model/base_spec.rb +66 -0
  74. data/spec/sequel_model/eager_loading_spec.rb +32 -0
  75. data/spec/sequel_model/record_spec.rb +9 -9
  76. data/spec/sequel_model/spec_helper.rb +3 -0
  77. data/spec/sequel_model/validations_spec.rb +63 -3
  78. metadata +41 -4
@@ -81,6 +81,13 @@ context "Dataset" do
81
81
  @dataset.literal(:a).should == 'a'
82
82
  end
83
83
 
84
+ specify "should have upcase_identifiers? method which returns whether identifiers are currently upcased" do
85
+ @dataset.upcase_identifiers = true
86
+ @dataset.upcase_identifiers?.should == true
87
+ @dataset.upcase_identifiers = false
88
+ @dataset.upcase_identifiers?.should == false
89
+ end
90
+
84
91
  specify "should have identifier_input_method= method which changes literalization of identifiers" do
85
92
  @dataset.identifier_input_method = :upcase
86
93
  @dataset.literal(:a).should == 'A'
@@ -696,6 +703,10 @@ context "Dataset#literal" do
696
703
  @dataset.literal("a\\'bc").should == "'a\\\\''bc'"
697
704
  end
698
705
 
706
+ specify "should escape blobs as strings by default" do
707
+ @dataset.literal('abc'.to_sequel_blob).should == "'abc'"
708
+ end
709
+
699
710
  specify "should literalize numbers properly" do
700
711
  @dataset.literal(1).should == "1"
701
712
  @dataset.literal(1.5).should == "1.5"
@@ -727,13 +738,19 @@ context "Dataset#literal" do
727
738
 
728
739
  specify "should literalize Time properly" do
729
740
  t = Time.now
730
- s = t.strftime("TIMESTAMP '%Y-%m-%d %H:%M:%S'")
741
+ s = t.strftime("'%Y-%m-%dT%H:%M:%S%z'").gsub(/(\d\d')\z/, ':\1')
742
+ @dataset.literal(t).should == s
743
+ end
744
+
745
+ specify "should literalize DateTime properly" do
746
+ t = DateTime.now
747
+ s = t.strftime("'%Y-%m-%dT%H:%M:%S%z'").gsub(/(\d\d')\z/, ':\1')
731
748
  @dataset.literal(t).should == s
732
749
  end
733
750
 
734
751
  specify "should literalize Date properly" do
735
752
  d = Date.today
736
- s = d.strftime("DATE '%Y-%m-%d'")
753
+ s = d.strftime("'%Y-%m-%d'")
737
754
  @dataset.literal(d).should == s
738
755
  end
739
756
 
@@ -867,6 +884,20 @@ context "Dataset#select" do
867
884
 
868
885
  @d.select(nil, 1, :x => :y).sql.should == "SELECT NULL, 1, x AS y FROM test"
869
886
  end
887
+
888
+ specify "should accept a block that yields a virtual row" do
889
+ @d.select{|o| o.a}.sql.should == 'SELECT a FROM test'
890
+ @d.select{|o| o.a(1)}.sql.should == 'SELECT a(1) FROM test'
891
+ @d.select{|o| o.a(1, 2)}.sql.should == 'SELECT a(1, 2) FROM test'
892
+ @d.select{|o| [o.a, o.a(1, 2)]}.sql.should == 'SELECT a, a(1, 2) FROM test'
893
+ end
894
+
895
+ specify "should merge regular arguments with argument returned from block" do
896
+ @d.select(:b){|o| o.a}.sql.should == 'SELECT b, a FROM test'
897
+ @d.select(:b, :c){|o| o.a(1)}.sql.should == 'SELECT b, c, a(1) FROM test'
898
+ @d.select(:b){|o| [o.a, o.a(1, 2)]}.sql.should == 'SELECT b, a, a(1, 2) FROM test'
899
+ @d.select(:b, :c){|o| [o.a, o.a(1, 2)]}.sql.should == 'SELECT b, c, a, a(1, 2) FROM test'
900
+ end
870
901
  end
871
902
 
872
903
  context "Dataset#select_all" do
@@ -898,6 +929,11 @@ context "Dataset#select_more" do
898
929
  @d.select(:a).select_more(:b).sql.should == 'SELECT a, b FROM test'
899
930
  @d.select(:a.*).select_more(:b.*).sql.should == 'SELECT a.*, b.* FROM test'
900
931
  end
932
+
933
+ specify "should accept a block that yields a virtual row" do
934
+ @d.select(:a).select_more{|o| o.b}.sql.should == 'SELECT a, b FROM test'
935
+ @d.select(:a.*).select_more(:b.*){|o| o.b(1)}.sql.should == 'SELECT a.*, b.*, b(1) FROM test'
936
+ end
901
937
  end
902
938
 
903
939
  context "Dataset#order" do
@@ -934,6 +970,20 @@ context "Dataset#order" do
934
970
  @dataset.order(:bah).order(nil).sql.should ==
935
971
  'SELECT * FROM test'
936
972
  end
973
+
974
+ specify "should accept a block that yields a virtual row" do
975
+ @dataset.order{|o| o.a}.sql.should == 'SELECT * FROM test ORDER BY a'
976
+ @dataset.order{|o| o.a(1)}.sql.should == 'SELECT * FROM test ORDER BY a(1)'
977
+ @dataset.order{|o| o.a(1, 2)}.sql.should == 'SELECT * FROM test ORDER BY a(1, 2)'
978
+ @dataset.order{|o| [o.a, o.a(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY a, a(1, 2)'
979
+ end
980
+
981
+ specify "should merge regular arguments with argument returned from block" do
982
+ @dataset.order(:b){|o| o.a}.sql.should == 'SELECT * FROM test ORDER BY b, a'
983
+ @dataset.order(:b, :c){|o| o.a(1)}.sql.should == 'SELECT * FROM test ORDER BY b, c, a(1)'
984
+ @dataset.order(:b){|o| [o.a, o.a(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY b, a, a(1, 2)'
985
+ @dataset.order(:b, :c){|o| [o.a, o.a(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY b, c, a, a(1, 2)'
986
+ end
937
987
  end
938
988
 
939
989
  context "Dataset#unfiltered" do
@@ -958,6 +1008,21 @@ context "Dataset#unordered" do
958
1008
  end
959
1009
  end
960
1010
 
1011
+ context "Dataset#with_sql" do
1012
+ setup do
1013
+ @dataset = Sequel::Dataset.new(nil).from(:test)
1014
+ end
1015
+
1016
+ specify "should remove use static sql" do
1017
+ @dataset.with_sql('SELECT 1 FROM test').sql.should == 'SELECT 1 FROM test'
1018
+ end
1019
+
1020
+ specify "should keep row_proc and transform" do
1021
+ @dataset.with_sql('SELECT 1 FROM test').row_proc.should == @dataset.row_proc
1022
+ @dataset.with_sql('SELECT 1 FROM test').instance_variable_get(:@transform).should == @dataset.instance_variable_get(:@transform)
1023
+ end
1024
+ end
1025
+
961
1026
  context "Dataset#order_by" do
962
1027
  setup do
963
1028
  @dataset = Sequel::Dataset.new(nil).from(:test)
@@ -1003,6 +1068,11 @@ context "Dataset#order_more" do
1003
1068
  @dataset.order(:name).order_more(:stamp.desc).sql.should ==
1004
1069
  'SELECT * FROM test ORDER BY name, stamp DESC'
1005
1070
  end
1071
+
1072
+ specify "should accept a block that yields a virtual row" do
1073
+ @dataset.order(:a).order_more{|o| o.b}.sql.should == 'SELECT * FROM test ORDER BY a, b'
1074
+ @dataset.order(:a, :b).order_more(:c, :d){|o| [o.e, o.f(1, 2)]}.sql.should == 'SELECT * FROM test ORDER BY a, b, c, d, e, f(1, 2)'
1075
+ end
1006
1076
  end
1007
1077
 
1008
1078
  context "Dataset#reverse_order" do
@@ -1186,7 +1256,7 @@ context "Dataset#uniq" do
1186
1256
  specify "should accept an expression list" do
1187
1257
  @dataset.uniq(:a, :b).sql.should == 'SELECT DISTINCT ON (a, b) name FROM test'
1188
1258
 
1189
- @dataset.uniq(:stamp.cast_as(:integer), :node_id=>nil).sql.should == 'SELECT DISTINCT ON (cast(stamp AS integer), (node_id IS NULL)) name FROM test'
1259
+ @dataset.uniq(:stamp.cast_as(:integer), :node_id=>nil).sql.should == 'SELECT DISTINCT ON (CAST(stamp AS integer), (node_id IS NULL)) name FROM test'
1190
1260
  end
1191
1261
 
1192
1262
  specify "should do a subselect for count" do
@@ -1961,6 +2031,15 @@ context "Dataset#get" do
1961
2031
  specify "should work with aliased fields" do
1962
2032
  @d.get(:x__b.as(:name)).should == "SELECT x.b AS name FROM test LIMIT 1"
1963
2033
  end
2034
+
2035
+ specify "should accept a block that yields a virtual row" do
2036
+ @d.get{|o| o.x__b.as(:name)}.should == "SELECT x.b AS name FROM test LIMIT 1"
2037
+ @d.get{|o| o.x(1).as(:name)}.should == "SELECT x(1) AS name FROM test LIMIT 1"
2038
+ end
2039
+
2040
+ specify "should raise an error if both a regular argument and block argument are used" do
2041
+ proc{@d.get(:name){|o| o.x__b.as(:name)}}.should raise_error(Sequel::Error)
2042
+ end
1964
2043
  end
1965
2044
 
1966
2045
  context "Dataset#set_row_proc" do
@@ -3396,32 +3475,3 @@ context "Sequel::Dataset#each" do
3396
3475
  end
3397
3476
  end
3398
3477
  end
3399
-
3400
- context Sequel::Dataset::UnsupportedIntersectExcept do
3401
- before do
3402
- @ds = Sequel::Dataset.new(nil).from(:items)
3403
- @ds2 = Sequel::Dataset.new(nil).from(:i)
3404
- @ds.extend(Sequel::Dataset::UnsupportedIntersectExcept)
3405
- end
3406
-
3407
- specify "should raise an error if INTERSECT or EXCEPT is USED" do
3408
- @ds.union(@ds2).sql.should == 'SELECT * FROM items UNION SELECT * FROM i'
3409
- proc{@ds.intersect(@ds2)}.should raise_error(Sequel::Error)
3410
- proc{@ds.except(@ds2)}.should raise_error(Sequel::Error)
3411
- end
3412
- end
3413
-
3414
- context Sequel::Dataset::UnsupportedIntersectExceptAll do
3415
- before do
3416
- @ds = Sequel::Dataset.new(nil).from(:items)
3417
- @ds2 = Sequel::Dataset.new(nil).from(:i)
3418
- @ds.extend(Sequel::Dataset::UnsupportedIntersectExceptAll)
3419
- end
3420
-
3421
- specify "should raise an error if INTERSECT or EXCEPT is USED" do
3422
- @ds.intersect(@ds2).sql.should == 'SELECT * FROM items INTERSECT SELECT * FROM i'
3423
- @ds.except(@ds2).sql.should == 'SELECT * FROM items EXCEPT SELECT * FROM i'
3424
- proc{@ds.intersect(@ds2, true)}.should raise_error(Sequel::Error)
3425
- proc{@ds.except(@ds2, true)}.should raise_error(Sequel::Error)
3426
- end
3427
- end
@@ -327,6 +327,22 @@ context "DB#create_table" do
327
327
  @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id)", "CREATE INDEX cats_name_index ON cats (name)"]
328
328
  end
329
329
 
330
+ specify "should accept functional indexes" do
331
+ @db.create_table(:cats) do
332
+ integer :id
333
+ index :lower.sql_function(:name)
334
+ end
335
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_lower_name__index ON cats (lower(name))"]
336
+ end
337
+
338
+ specify "should accept indexes with identifiers" do
339
+ @db.create_table(:cats) do
340
+ integer :id
341
+ index :lower__name.identifier
342
+ end
343
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_lower__name_index ON cats (lower__name)"]
344
+ end
345
+
330
346
  specify "should accept custom index names" do
331
347
  @db.create_table(:cats) do
332
348
  integer :id
@@ -15,6 +15,34 @@ describe Sequel::Model, "associate" do
15
15
  klass.association_reflection(:"par_parent1s").associated_class.should == ParParent
16
16
  klass.association_reflection(:"par_parent2s").associated_class.should == ParParent
17
17
  end
18
+
19
+ it "should add a model_object and association_reflection accessors to the dataset, and return it with the current model object" do
20
+ MODEL_DB.reset
21
+ klass = Class.new(Sequel::Model(:nodes)) do
22
+ columns :id, :a_id
23
+ end
24
+ mod = Module.new do
25
+ def blah
26
+ filter{|o| o.__send__(association_reflection[:key]) > model_object.id*2}
27
+ end
28
+ end
29
+
30
+ klass.associate :many_to_one, :a, :class=>klass
31
+ klass.associate :one_to_many, :bs, :key=>:b_id, :class=>klass, :extend=>mod
32
+ klass.associate :many_to_many, :cs, :class=>klass
33
+
34
+ node = klass.load(:id=>1)
35
+ node.a_dataset.model_object.should == node
36
+ node.bs_dataset.model_object.should == node
37
+ node.cs_dataset.model_object.should == node
38
+
39
+ node.a_dataset.association_reflection.should == klass.association_reflection(:a)
40
+ node.bs_dataset.association_reflection.should == klass.association_reflection(:bs)
41
+ node.cs_dataset.association_reflection.should == klass.association_reflection(:cs)
42
+
43
+ node.bs_dataset.blah.sql.should == 'SELECT * FROM nodes WHERE ((nodes.b_id = 1) AND (b_id > 2))'
44
+ end
45
+
18
46
  it "should allow extending the dataset with :extend option" do
19
47
  MODEL_DB.reset
20
48
  klass = Class.new(Sequel::Model(:nodes)) do
@@ -41,6 +69,34 @@ describe Sequel::Model, "associate" do
41
69
  node.cs_dataset.blah.should == 1
42
70
  node.cs_dataset.blar.should == 2
43
71
  end
72
+
73
+ it "should clone an existing association with the :clone option" do
74
+ MODEL_DB.reset
75
+ klass = Class.new(Sequel::Model(:nodes))
76
+
77
+ klass.many_to_one(:par_parent, :order=>:a){1}
78
+ klass.one_to_many(:par_parent1s, :class=>'ParParent', :limit=>12){4}
79
+ klass.many_to_many(:par_parent2s, :class=>:ParParent, :uniq=>true){2}
80
+
81
+ klass.many_to_one :par, :clone=>:par_parent, :select=>:b
82
+ klass.one_to_many :par1s, :clone=>:par_parent1s, :order=>:b, :limit=>10, :block=>nil
83
+ klass.many_to_many(:par2s, :clone=>:par_parent2s, :order=>:c){3}
84
+
85
+ klass.association_reflection(:par).associated_class.should == ParParent
86
+ klass.association_reflection(:par1s).associated_class.should == ParParent
87
+ klass.association_reflection(:par2s).associated_class.should == ParParent
88
+
89
+ klass.association_reflection(:par)[:order].should == :a
90
+ klass.association_reflection(:par).select.should == :b
91
+ klass.association_reflection(:par)[:block].call.should == 1
92
+ klass.association_reflection(:par1s)[:limit].should == 10
93
+ klass.association_reflection(:par1s)[:order].should == :b
94
+ klass.association_reflection(:par1s)[:block].should == nil
95
+ klass.association_reflection(:par2s)[:after_load].length.should == 1
96
+ klass.association_reflection(:par2s)[:order].should == :c
97
+ klass.association_reflection(:par2s)[:block].call.should == 3
98
+ end
99
+
44
100
  end
45
101
 
46
102
  describe Sequel::Model, "many_to_one" do
@@ -117,6 +173,17 @@ describe Sequel::Model, "many_to_one" do
117
173
  MODEL_DB.sqls.should == ["SELECT id, name FROM nodes WHERE (nodes.id = 567) LIMIT 1"]
118
174
  end
119
175
 
176
+ it "should use :conditions option if given" do
177
+ @c2.many_to_one :parent, :class => @c2, :key => :blah, :conditions=>{:a=>32}
178
+ @c2.new(:id => 1, :blah => 567).parent
179
+ MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 567) AND (a = 32)) LIMIT 1"]
180
+
181
+ @c2.many_to_one :parent, :class => @c2, :key => :blah, :conditions=>:a
182
+ MODEL_DB.sqls.clear
183
+ @c2.new(:id => 1, :blah => 567).parent
184
+ MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 567) AND a) LIMIT 1"]
185
+ end
186
+
120
187
  it "should support :order, :limit (only for offset), and :dataset options, as well as a block" do
121
188
  c2 = @c2
122
189
  @c2.many_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{c2.filter(:parent_id=>pk)}, :limit=>[10,20], :order=>:name do |ds|
@@ -594,6 +661,15 @@ describe Sequel::Model, "one_to_many" do
594
661
  n.attributes_dataset.sql.should == "SELECT id, name FROM attributes WHERE (attributes.node_id = 1234)"
595
662
  end
596
663
 
664
+ it "should support a conditions option" do
665
+ @c2.one_to_many :attributes, :class => @c1, :conditions => {:a=>32}
666
+ n = @c2.new(:id => 1234)
667
+ n.attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND (a = 32))"
668
+ @c2.one_to_many :attributes, :class => @c1, :conditions => ~:a
669
+ n = @c2.new(:id => 1234)
670
+ n.attributes_dataset.sql.should == "SELECT * FROM attributes WHERE ((attributes.node_id = 1234) AND NOT a)"
671
+ end
672
+
597
673
  it "should support an order option" do
598
674
  @c2.one_to_many :attributes, :class => @c1, :order => :kind
599
675
 
@@ -1152,6 +1228,19 @@ describe Sequel::Model, "many_to_many" do
1152
1228
  a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234))'
1153
1229
  end
1154
1230
 
1231
+ it "should support a conditions option" do
1232
+ @c2.many_to_many :attributes, :class => @c1, :conditions => {:a=>32}
1233
+ n = @c2.new(:id => 1234)
1234
+ a = n.attributes_dataset
1235
+ a.should be_a_kind_of(Sequel::Dataset)
1236
+ a.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)'
1237
+ @c2.many_to_many :attributes, :class => @c1, :conditions => ['a = ?', 32]
1238
+ n = @c2.new(:id => 1234)
1239
+ a = n.attributes_dataset
1240
+ a.should be_a_kind_of(Sequel::Dataset)
1241
+ a.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)'
1242
+ end
1243
+
1155
1244
  it "should support an order option" do
1156
1245
  @c2.many_to_many :attributes, :class => @c1, :order => :blah
1157
1246
 
@@ -417,3 +417,69 @@ describe Sequel::Model, ".strict_param_setting" do
417
417
  proc{@c.new(:z=>1)}.should_not raise_error
418
418
  end
419
419
  end
420
+
421
+ describe Sequel::Model, ".[] optimization" do
422
+ setup do
423
+ @c = Class.new(Sequel::Model(:a))
424
+ @c.instance_eval do
425
+ def simple_table
426
+ @simple_table
427
+ end
428
+ end
429
+ end
430
+
431
+ it "should set simple_pk to the literalized primary key column name if a single primary key" do
432
+ @c.simple_pk.should == 'id'
433
+ @c.set_primary_key :b
434
+ @c.simple_pk.should == 'b'
435
+ @c.set_primary_key :b__a.identifier
436
+ @c.simple_pk.should == 'b__a'
437
+ end
438
+
439
+ it "should have simple_pk be blank if compound or no primary key" do
440
+ @c.no_primary_key
441
+ @c.simple_pk.should == nil
442
+ @c.set_primary_key :b, :a
443
+ @c.simple_pk.should == nil
444
+ end
445
+
446
+ it "should have simple table set if passed a Symbol to set_dataset" do
447
+ @c.set_dataset :a
448
+ @c.simple_table.should == 'a'
449
+ @c.set_dataset :b
450
+ @c.simple_table.should == 'b'
451
+ @c.set_dataset :b__a
452
+ @c.simple_table.should == 'b.a'
453
+ end
454
+
455
+ it "should have simple_table = nil if passed a dataset to set_dataset" do
456
+ @c.set_dataset @c.db[:a]
457
+ @c.simple_table.should == nil
458
+ end
459
+
460
+ it "should have simple_table superclasses setting if inheriting" do
461
+ @c.set_dataset :a
462
+ Class.new(@c).simple_table.should == 'a'
463
+ @c.instance_variable_set(:@simple_table, nil)
464
+ Class.new(@c).simple_table.should == nil
465
+ @c.instance_variable_set(:@simple_table, "'b'")
466
+ Class.new(@c).simple_table.should == "'b'"
467
+ end
468
+
469
+ it "should have simple_table = nil if inheriting and sti_key is set" do
470
+ @c.set_sti_key :x
471
+ Class.new(@c).simple_table.should == nil
472
+ end
473
+
474
+ it "should use Dataset#with_sql if simple_table and simple_pk are true" do
475
+ @c.set_dataset :a
476
+ @c.dataset.should_receive(:with_sql).and_return(@c.dataset)
477
+ @c[1]
478
+ end
479
+
480
+ it "should not use Dataset#with_sql if either simple_table or simple_pk is nil" do
481
+ @c.set_dataset @c.dataset
482
+ @c.dataset.should_not_receive(:with_sql)
483
+ @c[1]
484
+ end
485
+ end
@@ -328,6 +328,27 @@ describe Sequel::Model, "#eager" do
328
328
  MODEL_DB.sqls.length.should == 2
329
329
  end
330
330
 
331
+ it "should respect :conditions when eagerly loading" do
332
+ EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>{:a=>32}
333
+ a = EagerBandMember.eager(:good_bands).all
334
+ a.should be_a_kind_of(Array)
335
+ a.size.should == 1
336
+ a.first.should be_a_kind_of(EagerBandMember)
337
+ a.first.values.should == {:id => 5}
338
+ MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (a = 32) ORDER BY id']
339
+ a = a.first
340
+ a.good_bands.should be_a_kind_of(Array)
341
+ a.good_bands.size.should == 1
342
+ a.good_bands.first.should be_a_kind_of(EagerBand)
343
+ a.good_bands.first.values.should == {:id => 2}
344
+ MODEL_DB.sqls.length.should == 2
345
+
346
+ MODEL_DB.sqls.clear
347
+ EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>"x = 1"
348
+ a = EagerBandMember.eager(:good_bands).all
349
+ MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (x = 1) ORDER BY id']
350
+ end
351
+
331
352
  it "should respect :order when eagerly loading" do
332
353
  a = EagerBandMember.eager(:bands).all
333
354
  a.should be_a_kind_of(Array)
@@ -1019,6 +1040,17 @@ describe Sequel::Model, "#eager_graph" do
1019
1040
  GraphAlbum.eager_graph(:inner_genres).sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums INNER JOIN ag ON (ag.album_id = albums.id) RIGHT OUTER JOIN genres AS inner_genres ON (inner_genres.id = ag.genre_id)'
1020
1041
  end
1021
1042
 
1043
+ it "should respect the association's :conditions option" do
1044
+ GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :conditions=>{:active=>true}
1045
+ GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS active_band ON ((active_band.id = albums.band_id) AND (active_band.active = 't'))"
1046
+
1047
+ GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :conditions=>{:id=>(0..100)}
1048
+ GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON ((right_tracks.album_id = albums.id) AND ((right_tracks.id >= 0) AND (right_tracks.id <= 100)))'
1049
+
1050
+ GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :conditions=>{true=>:active}
1051
+ GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
1052
+ end
1053
+
1022
1054
  it "should respect the association's :graph_conditions option" do
1023
1055
  GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_conditions=>{:active=>true}
1024
1056
  GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS active_band ON ((active_band.id = albums.band_id) AND (active_band.active = 't'))"