sequel 3.8.0 → 3.9.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 (65) hide show
  1. data/CHANGELOG +48 -0
  2. data/Rakefile +6 -28
  3. data/bin/sequel +7 -2
  4. data/doc/release_notes/3.9.0.txt +233 -0
  5. data/lib/sequel/adapters/ado.rb +4 -8
  6. data/lib/sequel/adapters/amalgalite.rb +1 -1
  7. data/lib/sequel/adapters/dbi.rb +3 -3
  8. data/lib/sequel/adapters/do.rb +7 -13
  9. data/lib/sequel/adapters/jdbc.rb +10 -16
  10. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  11. data/lib/sequel/adapters/mysql.rb +10 -23
  12. data/lib/sequel/adapters/odbc.rb +6 -10
  13. data/lib/sequel/adapters/postgres.rb +0 -5
  14. data/lib/sequel/adapters/shared/mssql.rb +17 -9
  15. data/lib/sequel/adapters/shared/mysql.rb +16 -7
  16. data/lib/sequel/adapters/shared/sqlite.rb +5 -0
  17. data/lib/sequel/adapters/sqlite.rb +2 -1
  18. data/lib/sequel/connection_pool.rb +67 -349
  19. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  20. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  21. data/lib/sequel/connection_pool/single.rb +29 -0
  22. data/lib/sequel/connection_pool/threaded.rb +150 -0
  23. data/lib/sequel/core.rb +46 -15
  24. data/lib/sequel/database.rb +11 -9
  25. data/lib/sequel/dataset/convenience.rb +23 -0
  26. data/lib/sequel/dataset/graph.rb +2 -2
  27. data/lib/sequel/dataset/query.rb +9 -5
  28. data/lib/sequel/dataset/sql.rb +87 -12
  29. data/lib/sequel/extensions/inflector.rb +8 -1
  30. data/lib/sequel/extensions/schema_dumper.rb +3 -4
  31. data/lib/sequel/model/associations.rb +5 -43
  32. data/lib/sequel/model/base.rb +9 -2
  33. data/lib/sequel/model/default_inflections.rb +1 -1
  34. data/lib/sequel/model/exceptions.rb +11 -1
  35. data/lib/sequel/model/inflections.rb +8 -1
  36. data/lib/sequel/model/plugins.rb +2 -12
  37. data/lib/sequel/plugins/active_model.rb +5 -0
  38. data/lib/sequel/plugins/association_dependencies.rb +1 -1
  39. data/lib/sequel/plugins/many_through_many.rb +1 -1
  40. data/lib/sequel/plugins/optimistic_locking.rb +65 -0
  41. data/lib/sequel/plugins/single_table_inheritance.rb +14 -3
  42. data/lib/sequel/plugins/validation_helpers.rb +2 -2
  43. data/lib/sequel/sql.rb +2 -2
  44. data/lib/sequel/timezones.rb +2 -2
  45. data/lib/sequel/version.rb +1 -1
  46. data/spec/adapters/mssql_spec.rb +19 -0
  47. data/spec/adapters/mysql_spec.rb +4 -0
  48. data/spec/adapters/postgres_spec.rb +180 -0
  49. data/spec/adapters/spec_helper.rb +15 -1
  50. data/spec/core/connection_pool_spec.rb +119 -78
  51. data/spec/core/database_spec.rb +41 -50
  52. data/spec/core/dataset_spec.rb +115 -4
  53. data/spec/extensions/active_model_spec.rb +40 -34
  54. data/spec/extensions/boolean_readers_spec.rb +1 -1
  55. data/spec/extensions/migration_spec.rb +43 -38
  56. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  57. data/spec/extensions/schema_dumper_spec.rb +4 -4
  58. data/spec/extensions/single_table_inheritance_spec.rb +19 -11
  59. data/spec/integration/dataset_test.rb +44 -1
  60. data/spec/integration/plugin_test.rb +39 -0
  61. data/spec/integration/prepared_statement_test.rb +58 -7
  62. data/spec/integration/spec_helper.rb +4 -0
  63. data/spec/model/eager_loading_spec.rb +24 -0
  64. data/spec/model/validations_spec.rb +5 -1
  65. metadata +114 -106
@@ -66,7 +66,7 @@ end
66
66
  describe "Sequel::Database dump methods" do
67
67
  before do
68
68
  @d = Sequel::Database.new
69
- @d.meta_def(:tables){[:t1, :t2]}
69
+ @d.meta_def(:tables){|o| [:t1, :t2]}
70
70
  @d.meta_def(:schema) do |t, *o|
71
71
  case t
72
72
  when :t1
@@ -131,7 +131,7 @@ END_MIG
131
131
  end
132
132
 
133
133
  it "should sort table names when dumping a migration" do
134
- @d.meta_def(:tables){[:t2, :t1]}
134
+ @d.meta_def(:tables){|o| [:t2, :t1]}
135
135
  @d.dump_schema_migration.should == <<-END_MIG
136
136
  Class.new(Sequel::Migration) do
137
137
  def up
@@ -210,7 +210,7 @@ END_MIG
210
210
  end
211
211
 
212
212
  it "should support dumping just indexes as a migration" do
213
- @d.meta_def(:tables){[:t1]}
213
+ @d.meta_def(:tables){|o| [:t1]}
214
214
  @d.meta_def(:indexes) do |t|
215
215
  {:i1=>{:columns=>[:c1], :unique=>false},
216
216
  :t1_c2_c1_index=>{:columns=>[:c2, :c1], :unique=>true}}
@@ -311,7 +311,7 @@ create_table(:x) do
311
311
  String :c26, :fixed=>true
312
312
  String :c27, :fixed=>true
313
313
  String :c28
314
- String :c29
314
+ String :c29, :size=>255
315
315
  String :c30, :size=>30
316
316
  String :c31
317
317
  String :c32
@@ -41,8 +41,8 @@ describe Sequel::Model, "#sti_key" do
41
41
  end
42
42
  StiTest.all.collect{|x| x.class}.should == [StiTest, StiTestSub1, StiTestSub2]
43
43
  StiTest.dataset.sql.should == "SELECT * FROM sti_tests"
44
- StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (blah = 'StiTestSub1')"
45
- StiTestSub2.dataset.sql.should == "SELECT * FROM sti_tests WHERE (blah = 'StiTestSub2')"
44
+ StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (sti_tests.blah = 'StiTestSub1')"
45
+ StiTestSub2.dataset.sql.should == "SELECT * FROM sti_tests WHERE (sti_tests.blah = 'StiTestSub2')"
46
46
  end
47
47
 
48
48
  it "should return rows with the correct class based on the polymorphic_key value" do
@@ -54,13 +54,6 @@ describe Sequel::Model, "#sti_key" do
54
54
  StiTest.all.collect{|x| x.class}.should == [StiTest, StiTestSub1, StiTestSub2]
55
55
  end
56
56
 
57
- it "should fallback to the main class if polymophic_key value is NULL" do
58
- def @ds.fetch_rows(sql)
59
- yield({:kind=>nil})
60
- end
61
- StiTest.all.collect{|x| x.class}.should == [StiTest]
62
- end
63
-
64
57
  it "should fallback to the main class if the given class does not exist" do
65
58
  def @ds.fetch_rows(sql)
66
59
  yield({:kind=>'StiTestSub3'})
@@ -68,6 +61,21 @@ describe Sequel::Model, "#sti_key" do
68
61
  StiTest.all.collect{|x| x.class}.should == [StiTest]
69
62
  end
70
63
 
64
+ it "should fallback to the main class if the sti_key field is empty or nil without calling constantize" do
65
+ called = false
66
+ StiTest.meta_def(:constantize) do |s|
67
+ called = true
68
+ Object
69
+ end
70
+ StiTest.plugin :single_table_inheritance, :kind
71
+ def @ds.fetch_rows(sql)
72
+ yield({:kind=>''})
73
+ yield({:kind=>nil})
74
+ end
75
+ StiTest.all.collect{|x| x.class}.should == [StiTest, StiTest]
76
+ called.should == false
77
+ end
78
+
71
79
  it "should add a before_create hook that sets the model class name for the key" do
72
80
  StiTest.new.save
73
81
  StiTestSub1.new.save
@@ -82,7 +90,7 @@ describe Sequel::Model, "#sti_key" do
82
90
 
83
91
  it "should add a filter to model datasets inside subclasses hook to only retreive objects with the matching key" do
84
92
  StiTest.dataset.sql.should == "SELECT * FROM sti_tests"
85
- StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (kind = 'StiTestSub1')"
86
- StiTestSub2.dataset.sql.should == "SELECT * FROM sti_tests WHERE (kind = 'StiTestSub2')"
93
+ StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (sti_tests.kind = 'StiTestSub1')"
94
+ StiTestSub2.dataset.sql.should == "SELECT * FROM sti_tests WHERE (sti_tests.kind = 'StiTestSub2')"
87
95
  end
88
96
  end
@@ -715,6 +715,14 @@ describe "Sequel::Dataset DSL support" do
715
715
  @ds.exclude(:a=>nil).all.should == [{:a=>20, :b=>nil}]
716
716
  end
717
717
 
718
+ it "should work with arrays as hash values" do
719
+ @ds.insert(20, 10)
720
+ @ds.filter(:a=>[10]).all.should == []
721
+ @ds.filter(:a=>[20, 10]).all.should == [{:a=>20, :b=>10}]
722
+ @ds.exclude(:a=>[10]).all.should == [{:a=>20, :b=>10}]
723
+ @ds.exclude(:a=>[20, 10]).all.should == []
724
+ end
725
+
718
726
  it "should work with ranges as hash values" do
719
727
  @ds.insert(20, 10)
720
728
  @ds.filter(:a=>(10..30)).all.should == [{:a=>20, :b=>10}]
@@ -733,7 +741,7 @@ describe "Sequel::Dataset DSL support" do
733
741
  @ds.filter({15=>20}.case(0, :a) > 0).all.should == []
734
742
  end
735
743
 
736
- it "should work multiple value arrays" do
744
+ it "should work with multiple value arrays" do
737
745
  @ds.insert(20, 10)
738
746
  @ds.quote_identifiers = false
739
747
  @ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
@@ -746,6 +754,41 @@ describe "Sequel::Dataset DSL support" do
746
754
  @ds.exclude([:a, :b]=>[[20, 10], [1, 2]].sql_array).all.should == []
747
755
  @ds.exclude([:a, :b]=>[[10, 10], [20, 20]].sql_array).all.should == [{:a=>20, :b=>10}]
748
756
  end
757
+
758
+ it "should work with IN/NOT in with datasets" do
759
+ @ds.insert(20, 10)
760
+ ds = @ds.unordered
761
+ @ds.quote_identifiers = false
762
+
763
+ @ds.filter(:a=>ds.select(:a)).all.should == [{:a=>20, :b=>10}]
764
+ @ds.filter(:a=>ds.select(:a).where(:a=>15)).all.should == []
765
+ @ds.exclude(:a=>ds.select(:a)).all.should == []
766
+ @ds.exclude(:a=>ds.select(:a).where(:a=>15)).all.should == [{:a=>20, :b=>10}]
767
+
768
+ @ds.filter([:a, :b]=>ds.select(:a, :b)).all.should == [{:a=>20, :b=>10}]
769
+ @ds.filter([:a, :b]=>ds.select(:b, :a)).all.should == []
770
+ @ds.exclude([:a, :b]=>ds.select(:a, :b)).all.should == []
771
+ @ds.exclude([:a, :b]=>ds.select(:b, :a)).all.should == [{:a=>20, :b=>10}]
772
+
773
+ @ds.filter([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.should == []
774
+ @ds.exclude([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.should == [{:a=>20, :b=>10}]
775
+ end
776
+
777
+ specify "should work empty arrays" do
778
+ @ds.insert(20, 10)
779
+ @ds.filter(:a=>[]).all.should == []
780
+ @ds.exclude(:a=>[]).all.should == [{:a=>20, :b=>10}]
781
+ @ds.filter([:a, :b]=>[]).all.should == []
782
+ @ds.exclude([:a, :b]=>[]).all.should == [{:a=>20, :b=>10}]
783
+ end
784
+
785
+ specify "should work empty arrays with nulls" do
786
+ @ds.insert(nil, nil)
787
+ @ds.filter(:a=>[]).all.should == []
788
+ @ds.exclude(:a=>[]).all.should == [{:a=>nil, :b=>nil}]
789
+ @ds.filter([:a, :b]=>[]).all.should == []
790
+ @ds.exclude([:a, :b]=>[]).all.should == [{:a=>nil, :b=>nil}]
791
+ end
749
792
 
750
793
  it "should work multiple conditions" do
751
794
  @ds.insert(20, 10)
@@ -443,3 +443,42 @@ describe "Serialization plugin" do
443
443
  Item.first.stuff.should == Item.new
444
444
  end
445
445
  end
446
+
447
+ describe "OptimisticLocking plugin" do
448
+ before do
449
+ @db = INTEGRATION_DB
450
+ @db.create_table!(:people) do
451
+ primary_key :id
452
+ String :name
453
+ Integer :lock_version, :default=>0, :null=>false
454
+ end
455
+ class ::Person < Sequel::Model(@db)
456
+ plugin :optimistic_locking
457
+ create(:name=>'John')
458
+ end
459
+ end
460
+ after do
461
+ @db.drop_table(:people)
462
+ Object.send(:remove_const, :Person)
463
+ end
464
+
465
+ specify "should raise an error when updating a stale record" do
466
+ p1 = Person[1]
467
+ p2 = Person[1]
468
+ p1.update(:name=>'Jim')
469
+ proc{p2.update(:name=>'Bob')}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
470
+ end
471
+
472
+ specify "should raise an error when destroying a stale record" do
473
+ p1 = Person[1]
474
+ p2 = Person[1]
475
+ p1.update(:name=>'Jim')
476
+ proc{p2.destroy}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
477
+ end
478
+
479
+ specify "should not raise an error when updating the same record twice" do
480
+ p1 = Person[1]
481
+ p1.update(:name=>'Jim')
482
+ proc{p1.update(:name=>'Bob')}.should_not raise_error
483
+ end
484
+ end
@@ -49,36 +49,46 @@ describe "Prepared Statements and Bound Arguments" do
49
49
  @ds.filter(:number=>@ds.ba(:$n)).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
50
50
  end
51
51
 
52
- specify "should support placeholder literal strings" do
52
+ specify "should support placeholder literal strings with call" do
53
53
  @ds.filter("number = ?", @ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
54
54
  end
55
55
 
56
- specify "should support named placeholder literal strings and handle multiple named placeholders correctly" do
56
+ specify "should support named placeholder literal strings and handle multiple named placeholders correctly with call" do
57
57
  @ds.filter("number = :n", :n=>@ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
58
58
  @ds.insert(:number=>20)
59
59
  @ds.insert(:number=>30)
60
60
  @ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>@ds.ba(:$n3), :n2=>@ds.ba(:$n2), :n1=>@ds.ba(:$n1)).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
61
61
  end
62
62
 
63
- specify "should support datasets with static sql and placeholders" do
63
+ specify "should support datasets with static sql and placeholders with call" do
64
64
  INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].call(:select, :n=>10).should == [{:id=>1, :number=>10}]
65
65
  end
66
66
 
67
- specify "should support subselects" do
67
+ specify "should support subselects with call" do
68
68
  @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
69
69
  end
70
70
 
71
- specify "should support subselects with literal strings" do
71
+ specify "should support subselects with literal strings with call" do
72
72
  @ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", @ds.ba(:$n))).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
73
73
  end
74
74
 
75
- specify "should support subselects with static sql and placeholders" do
75
+ specify "should support subselects with static sql and placeholders with call" do
76
76
  @ds.filter(:id=>:$i, :number=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
77
77
  end
78
78
 
79
- specify "should support subselects of subselects" do
79
+ specify "should support subselects of subselects with call" do
80
80
  @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n)))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
81
81
  end
82
+
83
+ specify "should support using a bound variable for a limit and offset" do
84
+ @ds.insert(:number=>20)
85
+ ds = @ds.limit(@ds.ba(:$n), @ds.ba(:$n2)).order(:id)
86
+ ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
87
+ ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
88
+ ds.call(:select, :n=>1, :n2=>2).should == []
89
+ ds.call(:select, :n=>2, :n2=>0).should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
90
+ ds.call(:select, :n=>2, :n2=>1).should == [{:id=>2, :number=>20}]
91
+ end
82
92
 
83
93
  specify "should support bound variables with insert" do
84
94
  @ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n))
@@ -115,6 +125,47 @@ describe "Prepared Statements and Bound Arguments" do
115
125
  end
116
126
  end
117
127
 
128
+ specify "should support placeholder literal strings with prepare" do
129
+ @ds.filter("number = ?", @ds.ba(:$n)).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
130
+ end
131
+
132
+ specify "should support named placeholder literal strings and handle multiple named placeholders correctly with prepare" do
133
+ @ds.filter("number = :n", :n=>@ds.ba(:$n)).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
134
+ @ds.insert(:number=>20)
135
+ @ds.insert(:number=>30)
136
+ @ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>@ds.ba(:$n3), :n2=>@ds.ba(:$n2), :n1=>@ds.ba(:$n1)).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
137
+ end
138
+
139
+ specify "should support datasets with static sql and placeholders with prepare" do
140
+ INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
141
+ end
142
+
143
+ specify "should support subselects with prepare" do
144
+ @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
145
+ end
146
+
147
+ specify "should support subselects with literal strings with prepare" do
148
+ @ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", @ds.ba(:$n))).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
149
+ end
150
+
151
+ specify "should support subselects with static sql and placeholders with prepare" do
152
+ @ds.filter(:id=>:$i, :number=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
153
+ end
154
+
155
+ specify "should support subselects of subselects with prepare" do
156
+ @ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n)))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
157
+ end
158
+
159
+ specify "should support using a prepared_statement for a limit and offset" do
160
+ @ds.insert(:number=>20)
161
+ ps = @ds.limit(@ds.ba(:$n), @ds.ba(:$n2)).order(:id).prepare(:select, :seq_select)
162
+ ps.call(:n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
163
+ ps.call(:n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
164
+ ps.call(:n=>1, :n2=>2).should == []
165
+ ps.call(:n=>2, :n2=>0).should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
166
+ ps.call(:n=>2, :n2=>1).should == [{:id=>2, :number=>20}]
167
+ end
168
+
118
169
  specify "should support prepared statements with insert" do
119
170
  @ds.prepare(:insert, :insert_n, :number=>@ds.ba(:$n))
120
171
  INTEGRATION_DB.call(:insert_n, :n=>20)
@@ -25,6 +25,10 @@ class Spec::Example::ExampleGroup
25
25
  INTEGRATION_DB.loggers.pop
26
26
  end
27
27
  end
28
+
29
+ def self.log_specify(message, &block)
30
+ specify(message){log{instance_eval(&block)}}
31
+ end
28
32
 
29
33
  def self.cspecify(message, *checked, &block)
30
34
  pending = false
@@ -1343,4 +1343,28 @@ describe Sequel::Model, "#eager_graph" do
1343
1343
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1344
1344
  as.first.inner_genres.should == [GraphGenre.load(:id=>5), GraphGenre.load(:id=>6)]
1345
1345
  end
1346
+
1347
+ it "should handle eager loading with schemas and aliases of different types" do
1348
+ GraphAlbum.eager_graph(:band).join(:s__genres, [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1349
+ GraphAlbum.eager_graph(:band).join(:genres.qualify(:s), [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1350
+ GraphAlbum.eager_graph(:band).join(:s__b.as('genres'), [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.b AS genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1351
+ GraphAlbum.eager_graph(:band).join(:s__b, [:b_id], :genres.identifier).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.b AS genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1352
+ GraphAlbum.eager_graph(:band).join(:genres.identifier, [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1353
+ GraphAlbum.eager_graph(:band).join('genres', [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1354
+ end
1355
+
1356
+ it "should raise errors if invalid aliases or table styles are used" do
1357
+ proc{GraphAlbum.from_self(:alias=>:bands.qualify(:s)).eager_graph(:band)}.should raise_error(Sequel::Error)
1358
+ proc{GraphAlbum.from('?'.lit(:bands)).eager_graph(:band)}.should raise_error(Sequel::Error)
1359
+ end
1360
+
1361
+ it "should eagerly load schema qualified tables correctly with joins" do
1362
+ c1 = Class.new(GraphAlbum)
1363
+ c2 = Class.new(GraphGenre)
1364
+ c1.dataset = c1.dataset.from(:s__a)
1365
+ c2.dataset = c2.dataset.from(:s__g)
1366
+ c1.many_to_many :a_genres, :class=>c2, :left_primary_key=>:id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:s__ag
1367
+ ds = c1.join(:s__t, [:b_id]).eager_graph(:a_genres)
1368
+ ds.sql.should == 'SELECT a.id, a_genres.id AS a_genres_id FROM (SELECT * FROM s.a INNER JOIN s.t USING (b_id)) AS a LEFT OUTER JOIN s.ag AS ag ON (ag.album_id = a.id) LEFT OUTER JOIN s.g AS a_genres ON (a_genres.id = ag.genre_id)'
1369
+ end
1346
1370
  end
@@ -104,6 +104,10 @@ describe Sequel::Model do
104
104
  @o.errors[:score].should == ['too low']
105
105
  @o.errors[:blah].should be_empty
106
106
  end
107
+
108
+ specify "should allow raising of ValidationFailed with a string" do
109
+ proc{raise Sequel::ValidationFailed, "no reason"}.should raise_error(Sequel::ValidationFailed, "no reason")
110
+ end
107
111
  end
108
112
 
109
113
  describe "Model#save" do
@@ -139,7 +143,7 @@ describe "Model#save" do
139
143
  end
140
144
 
141
145
  specify "should raise error if validations fail and raise_on_save_faiure is true" do
142
- proc{@m.save}.should raise_error(Sequel::ValidationFailed)
146
+ proc{@m.save}.should raise_error(Sequel::ValidationFailed){ |e| e.errors.should == @m.errors }
143
147
  end
144
148
 
145
149
  specify "should return nil if validations fail and raise_on_save_faiure is false" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-04 00:00:00 -08:00
12
+ date: 2010-03-04 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -23,6 +23,7 @@ extra_rdoc_files:
23
23
  - README.rdoc
24
24
  - CHANGELOG
25
25
  - COPYING
26
+ - doc/advanced_associations.rdoc
26
27
  - doc/cheat_sheet.rdoc
27
28
  - doc/dataset_filtering.rdoc
28
29
  - doc/opening_databases.rdoc
@@ -30,9 +31,8 @@ extra_rdoc_files:
30
31
  - doc/reflection.rdoc
31
32
  - doc/schema.rdoc
32
33
  - doc/sharding.rdoc
33
- - doc/advanced_associations.rdoc
34
34
  - doc/virtual_rows.rdoc
35
- - doc/release_notes/3.8.0.txt
35
+ - doc/release_notes/1.0.txt
36
36
  - doc/release_notes/1.1.txt
37
37
  - doc/release_notes/1.3.txt
38
38
  - doc/release_notes/1.4.0.txt
@@ -56,16 +56,23 @@ extra_rdoc_files:
56
56
  - doc/release_notes/3.3.0.txt
57
57
  - doc/release_notes/3.4.0.txt
58
58
  - doc/release_notes/3.5.0.txt
59
- - doc/release_notes/1.0.txt
60
59
  - doc/release_notes/3.6.0.txt
61
60
  - doc/release_notes/3.7.0.txt
61
+ - doc/release_notes/3.8.0.txt
62
+ - doc/release_notes/3.9.0.txt
62
63
  files:
63
64
  - COPYING
64
65
  - CHANGELOG
65
66
  - README.rdoc
66
67
  - Rakefile
67
68
  - bin/sequel
68
- - doc/release_notes/3.8.0.txt
69
+ - doc/advanced_associations.rdoc
70
+ - doc/cheat_sheet.rdoc
71
+ - doc/dataset_filtering.rdoc
72
+ - doc/opening_databases.rdoc
73
+ - doc/prepared_statements.rdoc
74
+ - doc/reflection.rdoc
75
+ - doc/release_notes/1.0.txt
69
76
  - doc/release_notes/1.1.txt
70
77
  - doc/release_notes/1.3.txt
71
78
  - doc/release_notes/1.4.0.txt
@@ -89,31 +96,22 @@ files:
89
96
  - doc/release_notes/3.3.0.txt
90
97
  - doc/release_notes/3.4.0.txt
91
98
  - doc/release_notes/3.5.0.txt
92
- - doc/release_notes/1.0.txt
93
99
  - doc/release_notes/3.6.0.txt
94
100
  - doc/release_notes/3.7.0.txt
95
- - doc/cheat_sheet.rdoc
96
- - doc/dataset_filtering.rdoc
97
- - doc/opening_databases.rdoc
98
- - doc/prepared_statements.rdoc
99
- - doc/reflection.rdoc
101
+ - doc/release_notes/3.8.0.txt
102
+ - doc/release_notes/3.9.0.txt
100
103
  - doc/schema.rdoc
101
104
  - doc/sharding.rdoc
102
- - doc/advanced_associations.rdoc
103
105
  - doc/virtual_rows.rdoc
104
- - spec/model/validations_spec.rb
105
- - spec/model/associations_spec.rb
106
- - spec/model/base_spec.rb
107
- - spec/model/dataset_methods_spec.rb
108
- - spec/model/eager_loading_spec.rb
109
- - spec/model/hooks_spec.rb
110
- - spec/model/inflector_spec.rb
111
- - spec/model/model_spec.rb
112
- - spec/model/plugins_spec.rb
113
- - spec/model/record_spec.rb
114
- - spec/model/spec_helper.rb
115
- - spec/model/association_reflection_spec.rb
116
- - spec/core/version_spec.rb
106
+ - spec/adapters/firebird_spec.rb
107
+ - spec/adapters/informix_spec.rb
108
+ - spec/adapters/mssql_spec.rb
109
+ - spec/adapters/mysql_spec.rb
110
+ - spec/adapters/oracle_spec.rb
111
+ - spec/adapters/postgres_spec.rb
112
+ - spec/adapters/spec_helper.rb
113
+ - spec/adapters/sqlite_spec.rb
114
+ - spec/core/connection_pool_spec.rb
117
115
  - spec/core/core_sql_spec.rb
118
116
  - spec/core/database_spec.rb
119
117
  - spec/core/dataset_spec.rb
@@ -122,8 +120,8 @@ files:
122
120
  - spec/core/schema_generator_spec.rb
123
121
  - spec/core/schema_spec.rb
124
122
  - spec/core/spec_helper.rb
125
- - spec/core/connection_pool_spec.rb
126
- - spec/extensions/validation_helpers_spec.rb
123
+ - spec/core/version_spec.rb
124
+ - spec/extensions/active_model_spec.rb
127
125
  - spec/extensions/association_dependencies_spec.rb
128
126
  - spec/extensions/association_proxies_spec.rb
129
127
  - spec/extensions/blank_spec.rb
@@ -137,13 +135,14 @@ files:
137
135
  - spec/extensions/instance_hooks_spec.rb
138
136
  - spec/extensions/lazy_attributes_spec.rb
139
137
  - spec/extensions/looser_typecasting_spec.rb
140
- - spec/extensions/query_spec.rb
141
138
  - spec/extensions/migration_spec.rb
142
139
  - spec/extensions/many_through_many_spec.rb
143
140
  - spec/extensions/named_timezones_spec.rb
144
141
  - spec/extensions/nested_attributes_spec.rb
142
+ - spec/extensions/optimistic_locking_spec.rb
145
143
  - spec/extensions/pagination_spec.rb
146
144
  - spec/extensions/pretty_table_spec.rb
145
+ - spec/extensions/query_spec.rb
147
146
  - spec/extensions/schema_dumper_spec.rb
148
147
  - spec/extensions/schema_spec.rb
149
148
  - spec/extensions/serialization_spec.rb
@@ -153,13 +152,13 @@ files:
153
152
  - spec/extensions/string_date_time_spec.rb
154
153
  - spec/extensions/subclasses_spec.rb
155
154
  - spec/extensions/tactical_eager_loading_spec.rb
156
- - spec/extensions/timestamps_spec.rb
157
155
  - spec/extensions/thread_local_timezones_spec.rb
156
+ - spec/extensions/timestamps_spec.rb
158
157
  - spec/extensions/touch_spec.rb
159
158
  - spec/extensions/typecast_on_load_spec.rb
160
159
  - spec/extensions/validation_class_methods_spec.rb
161
- - spec/extensions/active_model_spec.rb
162
- - spec/integration/type_test.rb
160
+ - spec/extensions/validation_helpers_spec.rb
161
+ - spec/integration/associations_test.rb
163
162
  - spec/integration/database_test.rb
164
163
  - spec/integration/dataset_test.rb
165
164
  - spec/integration/eager_loader_test.rb
@@ -170,29 +169,97 @@ files:
170
169
  - spec/integration/spec_helper.rb
171
170
  - spec/integration/timezone_test.rb
172
171
  - spec/integration/transaction_test.rb
173
- - spec/integration/associations_test.rb
174
- - spec/adapters/sqlite_spec.rb
175
- - spec/adapters/informix_spec.rb
176
- - spec/adapters/mssql_spec.rb
177
- - spec/adapters/mysql_spec.rb
178
- - spec/adapters/oracle_spec.rb
179
- - spec/adapters/postgres_spec.rb
180
- - spec/adapters/spec_helper.rb
181
- - spec/adapters/firebird_spec.rb
172
+ - spec/integration/type_test.rb
173
+ - spec/model/association_reflection_spec.rb
174
+ - spec/model/associations_spec.rb
175
+ - spec/model/base_spec.rb
176
+ - spec/model/dataset_methods_spec.rb
177
+ - spec/model/eager_loading_spec.rb
178
+ - spec/model/hooks_spec.rb
179
+ - spec/model/inflector_spec.rb
180
+ - spec/model/model_spec.rb
181
+ - spec/model/plugins_spec.rb
182
+ - spec/model/record_spec.rb
183
+ - spec/model/spec_helper.rb
184
+ - spec/model/validations_spec.rb
182
185
  - spec/rcov.opts
183
186
  - spec/spec_config.rb.example
184
187
  - spec/spec_config.rb
188
+ - lib/sequel.rb
189
+ - lib/sequel/adapters/ado.rb
190
+ - lib/sequel/adapters/ado/mssql.rb
191
+ - lib/sequel/adapters/amalgalite.rb
192
+ - lib/sequel/adapters/db2.rb
193
+ - lib/sequel/adapters/dbi.rb
194
+ - lib/sequel/adapters/do.rb
195
+ - lib/sequel/adapters/do/mysql.rb
196
+ - lib/sequel/adapters/do/postgres.rb
197
+ - lib/sequel/adapters/do/sqlite.rb
198
+ - lib/sequel/adapters/firebird.rb
199
+ - lib/sequel/adapters/informix.rb
200
+ - lib/sequel/adapters/jdbc.rb
201
+ - lib/sequel/adapters/jdbc/h2.rb
202
+ - lib/sequel/adapters/jdbc/mssql.rb
203
+ - lib/sequel/adapters/jdbc/mysql.rb
204
+ - lib/sequel/adapters/jdbc/oracle.rb
205
+ - lib/sequel/adapters/jdbc/postgresql.rb
206
+ - lib/sequel/adapters/jdbc/sqlite.rb
207
+ - lib/sequel/adapters/mysql.rb
208
+ - lib/sequel/adapters/odbc.rb
209
+ - lib/sequel/adapters/odbc/mssql.rb
210
+ - lib/sequel/adapters/openbase.rb
211
+ - lib/sequel/adapters/oracle.rb
212
+ - lib/sequel/adapters/postgres.rb
213
+ - lib/sequel/adapters/shared/mssql.rb
214
+ - lib/sequel/adapters/shared/mysql.rb
215
+ - lib/sequel/adapters/shared/oracle.rb
216
+ - lib/sequel/adapters/shared/postgres.rb
217
+ - lib/sequel/adapters/shared/progress.rb
218
+ - lib/sequel/adapters/shared/sqlite.rb
219
+ - lib/sequel/adapters/sqlite.rb
220
+ - lib/sequel/adapters/utils/stored_procedures.rb
221
+ - lib/sequel/connection_pool.rb
222
+ - lib/sequel/connection_pool/sharded_single.rb
223
+ - lib/sequel/connection_pool/sharded_threaded.rb
224
+ - lib/sequel/connection_pool/single.rb
225
+ - lib/sequel/connection_pool/threaded.rb
226
+ - lib/sequel/core.rb
227
+ - lib/sequel/core_sql.rb
228
+ - lib/sequel/database.rb
185
229
  - lib/sequel/database/schema_generator.rb
186
230
  - lib/sequel/database/schema_methods.rb
187
231
  - lib/sequel/database/schema_sql.rb
188
- - lib/sequel/model/errors.rb
232
+ - lib/sequel/dataset.rb
233
+ - lib/sequel/dataset/actions.rb
234
+ - lib/sequel/dataset/convenience.rb
235
+ - lib/sequel/dataset/features.rb
236
+ - lib/sequel/dataset/graph.rb
237
+ - lib/sequel/dataset/prepared_statements.rb
238
+ - lib/sequel/dataset/query.rb
239
+ - lib/sequel/dataset/sql.rb
240
+ - lib/sequel/exceptions.rb
241
+ - lib/sequel/extensions/blank.rb
242
+ - lib/sequel/extensions/inflector.rb
243
+ - lib/sequel/extensions/looser_typecasting.rb
244
+ - lib/sequel/extensions/migration.rb
245
+ - lib/sequel/extensions/named_timezones.rb
246
+ - lib/sequel/extensions/pagination.rb
247
+ - lib/sequel/extensions/pretty_table.rb
248
+ - lib/sequel/extensions/query.rb
249
+ - lib/sequel/extensions/schema_dumper.rb
250
+ - lib/sequel/extensions/sql_expr.rb
251
+ - lib/sequel/extensions/string_date_time.rb
252
+ - lib/sequel/extensions/thread_local_timezones.rb
253
+ - lib/sequel/metaprogramming.rb
254
+ - lib/sequel/model.rb
255
+ - lib/sequel/model/associations.rb
189
256
  - lib/sequel/model/base.rb
190
257
  - lib/sequel/model/default_inflections.rb
191
- - lib/sequel/model/associations.rb
258
+ - lib/sequel/model/errors.rb
192
259
  - lib/sequel/model/exceptions.rb
193
260
  - lib/sequel/model/inflections.rb
194
261
  - lib/sequel/model/plugins.rb
195
- - lib/sequel/plugins/validation_helpers.rb
262
+ - lib/sequel/plugins/active_model.rb
196
263
  - lib/sequel/plugins/association_dependencies.rb
197
264
  - lib/sequel/plugins/association_proxies.rb
198
265
  - lib/sequel/plugins/boolean_readers.rb
@@ -205,79 +272,20 @@ files:
205
272
  - lib/sequel/plugins/lazy_attributes.rb
206
273
  - lib/sequel/plugins/many_through_many.rb
207
274
  - lib/sequel/plugins/nested_attributes.rb
275
+ - lib/sequel/plugins/optimistic_locking.rb
208
276
  - lib/sequel/plugins/schema.rb
209
277
  - lib/sequel/plugins/serialization.rb
210
- - lib/sequel/plugins/single_table_inheritance.rb
211
278
  - lib/sequel/plugins/subclasses.rb
279
+ - lib/sequel/plugins/single_table_inheritance.rb
212
280
  - lib/sequel/plugins/tactical_eager_loading.rb
213
281
  - lib/sequel/plugins/timestamps.rb
214
282
  - lib/sequel/plugins/touch.rb
215
283
  - lib/sequel/plugins/typecast_on_load.rb
216
284
  - lib/sequel/plugins/validation_class_methods.rb
217
- - lib/sequel/plugins/active_model.rb
218
- - lib/sequel/extensions/thread_local_timezones.rb
219
- - lib/sequel/extensions/inflector.rb
220
- - lib/sequel/extensions/looser_typecasting.rb
221
- - lib/sequel/extensions/migration.rb
222
- - lib/sequel/extensions/named_timezones.rb
223
- - lib/sequel/extensions/pagination.rb
224
- - lib/sequel/extensions/pretty_table.rb
225
- - lib/sequel/extensions/query.rb
226
- - lib/sequel/extensions/schema_dumper.rb
227
- - lib/sequel/extensions/sql_expr.rb
228
- - lib/sequel/extensions/string_date_time.rb
229
- - lib/sequel/extensions/blank.rb
230
- - lib/sequel/dataset/graph.rb
231
- - lib/sequel/dataset/convenience.rb
232
- - lib/sequel/dataset/features.rb
233
- - lib/sequel/dataset/actions.rb
234
- - lib/sequel/dataset/prepared_statements.rb
235
- - lib/sequel/dataset/query.rb
236
- - lib/sequel/dataset/sql.rb
237
- - lib/sequel/adapters/do/mysql.rb
238
- - lib/sequel/adapters/do/postgres.rb
239
- - lib/sequel/adapters/do/sqlite.rb
240
- - lib/sequel/adapters/ado/mssql.rb
241
- - lib/sequel/adapters/shared/mssql.rb
242
- - lib/sequel/adapters/shared/mysql.rb
243
- - lib/sequel/adapters/shared/oracle.rb
244
- - lib/sequel/adapters/shared/postgres.rb
245
- - lib/sequel/adapters/shared/progress.rb
246
- - lib/sequel/adapters/shared/sqlite.rb
247
- - lib/sequel/adapters/odbc/mssql.rb
248
- - lib/sequel/adapters/jdbc/h2.rb
249
- - lib/sequel/adapters/jdbc/mssql.rb
250
- - lib/sequel/adapters/jdbc/mysql.rb
251
- - lib/sequel/adapters/jdbc/oracle.rb
252
- - lib/sequel/adapters/jdbc/postgresql.rb
253
- - lib/sequel/adapters/jdbc/sqlite.rb
254
- - lib/sequel/adapters/utils/stored_procedures.rb
255
- - lib/sequel/adapters/ado.rb
256
- - lib/sequel/adapters/firebird.rb
257
- - lib/sequel/adapters/informix.rb
258
- - lib/sequel/adapters/jdbc.rb
259
- - lib/sequel/adapters/dbi.rb
260
- - lib/sequel/adapters/mysql.rb
261
- - lib/sequel/adapters/odbc.rb
262
- - lib/sequel/adapters/db2.rb
263
- - lib/sequel/adapters/openbase.rb
264
- - lib/sequel/adapters/oracle.rb
265
- - lib/sequel/adapters/postgres.rb
266
- - lib/sequel/adapters/amalgalite.rb
267
- - lib/sequel/adapters/sqlite.rb
268
- - lib/sequel/adapters/do.rb
269
- - lib/sequel/exceptions.rb
270
- - lib/sequel/metaprogramming.rb
271
- - lib/sequel/model.rb
285
+ - lib/sequel/plugins/validation_helpers.rb
272
286
  - lib/sequel/sql.rb
273
287
  - lib/sequel/timezones.rb
274
288
  - lib/sequel/version.rb
275
- - lib/sequel/connection_pool.rb
276
- - lib/sequel/core.rb
277
- - lib/sequel/core_sql.rb
278
- - lib/sequel/database.rb
279
- - lib/sequel/dataset.rb
280
- - lib/sequel.rb
281
289
  - lib/sequel_core.rb
282
290
  - lib/sequel_model.rb
283
291
  has_rdoc: true