sequel 4.14.0 → 4.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/README.rdoc +3 -3
  4. data/Rakefile +1 -1
  5. data/doc/opening_databases.rdoc +20 -2
  6. data/doc/release_notes/4.15.0.txt +56 -0
  7. data/doc/testing.rdoc +10 -4
  8. data/lib/sequel/adapters/fdbsql.rb +285 -0
  9. data/lib/sequel/adapters/informix.rb +15 -0
  10. data/lib/sequel/adapters/jdbc/fdbsql.rb +65 -0
  11. data/lib/sequel/adapters/mock.rb +1 -0
  12. data/lib/sequel/adapters/shared/fdbsql.rb +550 -0
  13. data/lib/sequel/adapters/shared/postgres.rb +23 -10
  14. data/lib/sequel/database/connecting.rb +1 -1
  15. data/lib/sequel/database/schema_methods.rb +10 -3
  16. data/lib/sequel/dataset/placeholder_literalizer.rb +7 -0
  17. data/lib/sequel/extensions/date_arithmetic.rb +5 -0
  18. data/lib/sequel/extensions/migration.rb +2 -2
  19. data/lib/sequel/extensions/pg_array.rb +15 -1
  20. data/lib/sequel/extensions/pg_json.rb +3 -0
  21. data/lib/sequel/extensions/pg_json_ops.rb +4 -4
  22. data/lib/sequel/extensions/schema_dumper.rb +9 -1
  23. data/lib/sequel/model/associations.rb +70 -21
  24. data/lib/sequel/plugins/active_model.rb +7 -2
  25. data/lib/sequel/plugins/many_through_many.rb +1 -0
  26. data/lib/sequel/plugins/pg_array_associations.rb +2 -1
  27. data/lib/sequel/plugins/split_values.rb +64 -0
  28. data/lib/sequel/version.rb +1 -1
  29. data/spec/adapters/fdbsql_spec.rb +429 -0
  30. data/spec/adapters/informix_spec.rb +6 -0
  31. data/spec/adapters/postgres_spec.rb +49 -1
  32. data/spec/adapters/spec_helper.rb +6 -1
  33. data/spec/adapters/sqlite_spec.rb +1 -1
  34. data/spec/core/placeholder_literalizer_spec.rb +10 -0
  35. data/spec/extensions/date_arithmetic_spec.rb +7 -0
  36. data/spec/extensions/many_through_many_spec.rb +14 -0
  37. data/spec/extensions/migration_spec.rb +3 -3
  38. data/spec/extensions/pg_array_associations_spec.rb +9 -0
  39. data/spec/extensions/pg_json_ops_spec.rb +4 -8
  40. data/spec/extensions/schema_dumper_spec.rb +9 -0
  41. data/spec/extensions/spec_helper.rb +3 -0
  42. data/spec/extensions/split_values_spec.rb +22 -0
  43. data/spec/integration/database_test.rb +1 -1
  44. data/spec/integration/dataset_test.rb +1 -1
  45. data/spec/integration/eager_loader_test.rb +1 -1
  46. data/spec/integration/plugin_test.rb +3 -2
  47. data/spec/integration/prepared_statement_test.rb +3 -3
  48. data/spec/integration/schema_test.rb +3 -3
  49. data/spec/integration/spec_helper.rb +6 -1
  50. data/spec/integration/timezone_test.rb +1 -1
  51. data/spec/model/association_reflection_spec.rb +29 -0
  52. data/spec/model/associations_spec.rb +36 -0
  53. data/spec/model/eager_loading_spec.rb +14 -0
  54. data/spec/model/spec_helper.rb +3 -0
  55. data/spec/rspec_helper.rb +4 -0
  56. metadata +10 -2
@@ -91,4 +91,10 @@ describe "A Informix dataset" do
91
91
  @d.order(:value).first.should == {:name => 'abc', :value => 123}
92
92
  @d.order(:value).last.should == {:name => 'def', :value => 789}
93
93
  end
94
+
95
+ specify "should return last inserted id" do
96
+ first = @d.insert :name => 'abc', :value => 123
97
+ second = @d.insert :name => 'abc', :value => 123
98
+ (second - first).should == 1
99
+ end
94
100
  end
@@ -276,6 +276,12 @@ describe "A PostgreSQL database" do
276
276
  Sequel.connect(DB.opts.merge(:notice_receiver=>proc{|r| a = r.result_error_message})){|db| db.do("BEGIN\nRAISE WARNING 'foo';\nEND;")}
277
277
  a.should == "WARNING: foo\n"
278
278
  end if DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && DB.server_version >= 90000
279
+
280
+ specify "should support creating foreign tables" do
281
+ # This only tests the SQL created, because a true test using file_fdw or postgres_fdw
282
+ # requires superuser permissions, and you should not be running the tests as a superuser.
283
+ DB.send(:create_table_sql, :t, DB.create_table_generator{Integer :a}, :foreign=>:f, :options=>{:o=>1}).should == 'CREATE FOREIGN TABLE "t" ("a" integer) SERVER "f" OPTIONS (o \'1\')'
284
+ end
279
285
  end
280
286
 
281
287
  describe "A PostgreSQL database with domain types" do
@@ -2091,6 +2097,48 @@ describe 'PostgreSQL array handling' do
2091
2097
  @ds.insert(rs.first)
2092
2098
  @ds.all.should == rs
2093
2099
  end
2100
+
2101
+ @db.create_table!(:items) do
2102
+ column :x, 'xml[]'
2103
+ column :m, 'money[]'
2104
+ column :b, 'bit[]'
2105
+ column :vb, 'bit varying[]'
2106
+ column :u, 'uuid[]'
2107
+ column :xi, 'xid[]'
2108
+ column :c, 'cid[]'
2109
+ column :n, 'name[]'
2110
+ column :t, 'tid[]'
2111
+ column :i, 'int2vector[]'
2112
+ column :o, 'oidvector[]'
2113
+ end
2114
+ @tp.call.should == [:xml_array, :money_array, :bit_array, :varbit_array, :uuid_array, :xid_array, :cid_array, :name_array, :tid_array, :int2vector_array, :oidvector_array]
2115
+ @ds.insert(Sequel.pg_array(['<a></a>'], :xml),
2116
+ Sequel.pg_array(['1'], :money),
2117
+ Sequel.pg_array(['1'], :bit),
2118
+ Sequel.pg_array(['10'], :varbit),
2119
+ Sequel.pg_array(['c0f24910-39e7-11e4-916c-0800200c9a66'], :uuid),
2120
+ Sequel.pg_array(['12'], :xid),
2121
+ Sequel.pg_array(['12'], :cid),
2122
+ Sequel.pg_array(['N'], :name),
2123
+ Sequel.pg_array(['(1,2)'], :tid),
2124
+ Sequel.pg_array(['1 2'], :int2vector),
2125
+ Sequel.pg_array(['1 2'], :oidvector))
2126
+ @ds.count.should == 1
2127
+ if @native
2128
+ rs = @ds.all
2129
+ r = rs.first
2130
+ m = r.delete(:m)
2131
+ m.should_not be_a_kind_of(Array)
2132
+ m.to_a.should be_a_kind_of(Array)
2133
+ m.first.should be_a_kind_of(String)
2134
+ r.should == {:x=>['<a></a>'], :b=>['1'], :vb=>['10'], :u=>['c0f24910-39e7-11e4-916c-0800200c9a66'], :xi=>['12'], :c=>['12'], :n=>['N'], :t=>['(1,2)'], :i=>['1 2'], :o=>['1 2']}
2135
+ rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
2136
+ rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
2137
+ r[:m] = m
2138
+ @ds.delete
2139
+ @ds.insert(r)
2140
+ @ds.all.should == rs
2141
+ end
2094
2142
  end
2095
2143
 
2096
2144
  specify 'insert and retrieve empty arrays' do
@@ -2693,7 +2741,7 @@ describe 'PostgreSQL json type' do
2693
2741
  @db.get(jo.typeof).should == 'object'
2694
2742
  @db.get(ja.typeof).should == 'array'
2695
2743
  @db.from(ja.array_elements_text.as(:v)).select_map(:v).map{|s| s.gsub(' ', '')}.should == ['2', '3', '["a","b"]']
2696
- @db.from(jo.to_record(true).as(:v, [Sequel.lit('a integer'), Sequel.lit('b text')])).select_map(:a).should == [1]
2744
+ @db.from(jo.to_record.as(:v, [Sequel.lit('a integer'), Sequel.lit('b text')])).select_map(:a).should == [1]
2697
2745
  @db.from(pg_json.call([{'a'=>1, 'b'=>1}]).op.to_recordset.as(:v, [Sequel.lit('a integer'), Sequel.lit('b integer')])).select_map(:a).should == [1]
2698
2746
 
2699
2747
  if json_type == :jsonb
@@ -16,6 +16,7 @@ rescue LoadError
16
16
  end
17
17
 
18
18
  Sequel::Database.extension :columns_introspection if ENV['SEQUEL_COLUMNS_INTROSPECTION']
19
+ Sequel::Model.cache_associations = false if ENV['SEQUEL_NO_CACHE_ASSOCIATIONS']
19
20
  Sequel.cache_anonymous_models = false
20
21
 
21
22
  class Sequel::Database
@@ -50,7 +51,11 @@ RSPEC_EXAMPLE_GROUP.class_eval do
50
51
  end
51
52
  end
52
53
  if pending
53
- specify(message){pending("Not yet working on #{Array(pending).join(', ')}", &block)}
54
+ specify(message) do
55
+ method = RSPEC_SKIP_PENDING && !ENV['SEQUEL_NO_SKIP_PENDING'] ? :skip : :pending
56
+ send(method, "Not yet working on #{Array(pending).join(', ')}")
57
+ instance_eval(&block)
58
+ end
54
59
  else
55
60
  specify(message, &block)
56
61
  end
@@ -123,7 +123,7 @@ describe "An SQLite database" do
123
123
  proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
124
124
  end
125
125
 
126
- cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :amalgalite, :swift do
126
+ cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :swift do
127
127
  @db.create_table!(:fk){timestamp :t; datetime :d}
128
128
  @db.use_timestamp_timezones = true
129
129
  t1 = Time.at(1)
@@ -121,6 +121,16 @@ describe "Dataset::PlaceholderLiteralizer" do
121
121
  @db.sqls.should == ["SELECT * FROM items WHERE (a = 2)"]
122
122
  end
123
123
 
124
+ specify "should support modifying dataset used on per-call basis with #run" do
125
+ loader = @c.loader(@ds){|pl, ds| ds.where(:a=>pl.arg)}
126
+ loader.with_dataset do |ds|
127
+ ds = ds.clone
128
+ ds.row_proc = lambda{|row| [row]}
129
+ ds
130
+ end.all(1).should == [[@h]]
131
+ @db.sqls.should == ["SELECT * FROM items WHERE (a = 1)"]
132
+ end
133
+
124
134
  specify "should literalize args as NULL if :placeholder_literal_null is set" do
125
135
  loader = @c.loader(@ds){|pl, ds| ds.where(pl.arg=>:a).clone(:placeholder_literal_null=>true)}
126
136
  loader.sql(1).should == "SELECT * FROM items WHERE (NULL = a)"
@@ -142,6 +142,13 @@ describe "date_arithmetic extension" do
142
142
  db.literal(Sequel.date_add(:a, @h2)).should == "(CAST(a AS timestamp) + 1 years + 1 months + 1 days + 1 hours + 1 minutes + 1 seconds)"
143
143
  end
144
144
 
145
+ it "should correctly literalize on Fdbsql" do
146
+ db = dbf.call(:fdbsql)
147
+ db.literal(Sequel.date_add(:a, @h0)).should == "CAST(a AS timestamp)"
148
+ db.literal(Sequel.date_add(:a, @h1)).should == "(a + INTERVAL 1 day)"
149
+ db.literal(Sequel.date_add(:a, @h2)).should == "(a + INTERVAL 1 year + INTERVAL 1 month + INTERVAL 1 day + INTERVAL 1 hour + INTERVAL 1 minute + INTERVAL 1 second)"
150
+ end
151
+
145
152
  specify "should raise error if literalizing on an unsupported database" do
146
153
  db = Sequel.mock
147
154
  db.extension :date_arithmetic
@@ -21,6 +21,20 @@ describe Sequel::Model, "many_through_many" do
21
21
  Object.send(:remove_const, :Tag)
22
22
  end
23
23
 
24
+ it "should raise an error if current class does not have a primary key, and :left_primary_key is not specified" do
25
+ @c1.no_primary_key
26
+ proc{@c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]}.should raise_error(Sequel::Error)
27
+ DB.sqls.should == []
28
+ end
29
+
30
+ it "should raise an error if associated class does not have a primary key, and :right_primary_key is not specified" do
31
+ @c2.no_primary_key
32
+ @c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
33
+ n = @c1.load(:id => 1234)
34
+ proc{n.tags}.should raise_error(Sequel::Error)
35
+ DB.sqls.should == []
36
+ end
37
+
24
38
  it "should populate :key_hash and :id_map option correctly for custom eager loaders" do
25
39
  khs = []
26
40
  pr = proc{|h| khs << [h[:key_hash], h[:id_map]]}
@@ -138,7 +138,7 @@ describe "Reversible Migrations with Sequel.migration{change{}}" do
138
138
  add_spatial_index :e, :name=>'e_s'
139
139
  rename_column :e, :g
140
140
  end
141
- create_view(:c, 'SELECT * FROM b')
141
+ create_view(:c, 'SELECT * FROM b', :foo=>:bar)
142
142
  create_join_table(:cat_id=>:cats, :dog_id=>:dogs)
143
143
  end
144
144
  end
@@ -163,7 +163,7 @@ describe "Reversible Migrations with Sequel.migration{change{}}" do
163
163
  [:add_spatial_index, :e, {:name=>"e_s"}],
164
164
  [:rename_column, :e, :g]]
165
165
  ],
166
- [:create_view, :c, "SELECT * FROM b"],
166
+ [:create_view, :c, "SELECT * FROM b", {:foo=>:bar}],
167
167
  [:create_join_table, {:cat_id=>:cats, :dog_id=>:dogs}]]
168
168
  end
169
169
 
@@ -172,7 +172,7 @@ describe "Reversible Migrations with Sequel.migration{change{}}" do
172
172
  Sequel.migration{change(&p)}.apply(@db, :down)
173
173
  @db.actions.should == [
174
174
  [:drop_join_table, {:cat_id=>:cats, :dog_id=>:dogs}],
175
- [:drop_view, :c],
175
+ [:drop_view, :c, {:foo=>:bar}],
176
176
  [:alter_table, [
177
177
  [:rename_column, :g, :e],
178
178
  [:drop_index, :e, {:name=>"e_s"}],
@@ -148,6 +148,15 @@ describe Sequel::Model, "pg_array_associations" do
148
148
  @c2.filter(:artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE ((tags.id * 3) IN (SELECT unnest(artists.tag_ids[1:2]) FROM artists WHERE (id = 1)))"
149
149
  end
150
150
 
151
+ it "should raise an error if associated model does not have a primary key, and :primary_key is not specified" do
152
+ @c1.no_primary_key
153
+ @c2.no_primary_key
154
+ @c1.pg_array_to_many :tags, :clone=>:tags
155
+ proc{@o1.tags}.should raise_error(Sequel::Error)
156
+ proc{@c2.many_to_pg_array :artists, :clone=>:artists}.should raise_error(Sequel::Error)
157
+ @db.sqls.should == []
158
+ end
159
+
151
160
  it "should support a :key option" do
152
161
  @c1.pg_array_to_many :tags, :clone=>:tags, :key=>:tag2_ids
153
162
  @c2.many_to_pg_array :artists, :clone=>:artists, :key=>:tag2_ids
@@ -112,17 +112,13 @@ describe "Sequel::Postgres::JSONOp" do
112
112
  end
113
113
 
114
114
  it "should have #to_record use the json_to_record function" do
115
- @l[@j.to_record].should == "json_to_record(j, false)"
116
- @l[@jb.to_record].should == "jsonb_to_record(j, false)"
117
- @l[@j.to_record(true)].should == "json_to_record(j, true)"
118
- @l[@jb.to_record(true)].should == "jsonb_to_record(j, true)"
115
+ @l[@j.to_record].should == "json_to_record(j)"
116
+ @l[@jb.to_record].should == "jsonb_to_record(j)"
119
117
  end
120
118
 
121
119
  it "should have #to_recordset use the json_to_recordsetfunction" do
122
- @l[@j.to_recordset].should == "json_to_recordset(j, false)"
123
- @l[@jb.to_recordset].should == "jsonb_to_recordset(j, false)"
124
- @l[@j.to_recordset(true)].should == "json_to_recordset(j, true)"
125
- @l[@jb.to_recordset(true)].should == "jsonb_to_recordset(j, true)"
120
+ @l[@j.to_recordset].should == "json_to_recordset(j)"
121
+ @l[@jb.to_recordset].should == "jsonb_to_recordset(j)"
126
122
  end
127
123
 
128
124
  it "should have #populate use the json_populate_record function" do
@@ -753,6 +753,15 @@ end
753
753
  END_MIG
754
754
  end
755
755
 
756
+ it "should force specify :null option for MySQL timestamp columns when using :same_db" do
757
+ @d.meta_def(:database_type){:mysql}
758
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'timestamp', :primary_key=>true, :allow_null=>true}]]}
759
+ @d.dump_table_schema(:t3, :same_db=>true).should == "create_table(:t3) do\n column :c1, \"timestamp\", :null=>true\n \n primary_key [:c1]\nend"
760
+
761
+ @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'timestamp', :primary_key=>true, :allow_null=>false}]]}
762
+ @d.dump_table_schema(:t3, :same_db=>true).should == "create_table(:t3) do\n column :c1, \"timestamp\", :null=>false\n \n primary_key [:c1]\nend"
763
+ end
764
+
756
765
  it "should use separate primary_key call with non autoincrementable types" do
757
766
  @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'varchar(8)', :primary_key=>true}]]}
758
767
  @d.dump_table_schema(:t3).should == "create_table(:t3) do\n String :c1, :size=>8\n \n primary_key [:c1]\nend"
@@ -91,3 +91,6 @@ if ENV['SEQUEL_COLUMNS_INTROSPECTION']
91
91
  Sequel::Database.extension :columns_introspection
92
92
  Sequel::Mock::Dataset.send(:include, Sequel::ColumnsIntrospection)
93
93
  end
94
+ if ENV['SEQUEL_NO_CACHE_ASSOCIATIONS']
95
+ Sequel::Model.cache_associations = false
96
+ end
@@ -0,0 +1,22 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::SplitValues" do
4
+ it "should skip the refresh after saving a new object" do
5
+ c = Class.new(Sequel::Model(:a))
6
+ c.columns :id, :x
7
+ c.plugin :split_values
8
+ c.dataset._fetch = {:id=>1, :x=>2, :y=>3}
9
+ o = c.first
10
+ c.db.reset
11
+
12
+ o.should == c.load(:id=>1, :x=>2)
13
+ o[:id].should == 1
14
+ o[:x].should == 2
15
+ o[:y].should == 3
16
+ {c.load(:id=>1, :x=>2)=>4}[o].should == 4
17
+ o.values.should == {:id=>1, :x=>2}
18
+
19
+ o.save
20
+ c.db.sqls.should == ["UPDATE a SET x = 2 WHERE (id = 1)"]
21
+ end
22
+ end
@@ -53,7 +53,7 @@ describe Sequel::Database do
53
53
  proc{@db[:test].update(:a=>'1', :b=>'2')}.should raise_error(Sequel::UniqueConstraintViolation)
54
54
  end
55
55
 
56
- cspecify "should raise Sequel::CheckConstraintViolation when a check constraint is violated", :mysql, [:db2], [proc{|db| db.sqlite_version < 30802}, :sqlite] do
56
+ cspecify "should raise Sequel::CheckConstraintViolation when a check constraint is violated", :mysql, [:db2], [proc{|db| db.sqlite_version < 30802}, :sqlite], :fdbsql do
57
57
  @db.create_table!(:test){String :a; check Sequel.~(:a=>'1')}
58
58
  proc{@db[:test].insert('1')}.should raise_error(Sequel::CheckConstraintViolation)
59
59
  @db[:test].insert('2')
@@ -851,7 +851,7 @@ describe Sequel::SQL::Constants do
851
851
  d.to_s.should == Date.today.to_s
852
852
  end
853
853
 
854
- cspecify "should have working CURRENT_TIME", [:do, :mysql], [:jdbc, :sqlite], [:mysql2] do
854
+ cspecify "should have working CURRENT_TIME", [:jdbc, :sqlite], [:mysql2] do
855
855
  @db.create_table!(:constants){Time :t, :only_time=>true}
856
856
  @ds.insert(:t=>Sequel::CURRENT_TIME)
857
857
  (Time.now - @c[@ds.get(:t)]).should be_within(60).of(0)
@@ -330,7 +330,7 @@ describe "Polymorphic Associations" do
330
330
  end
331
331
  class ::Asset < Sequel::Model
332
332
  m = method(:constantize)
333
- many_to_one :attachable, :reciprocal=>:assets,
333
+ many_to_one :attachable, :reciprocal=>:assets, :reciprocal_type=>:one_to_many,
334
334
  :setter=>(proc do |attachable|
335
335
  self[:attachable_id] = (attachable.pk if attachable)
336
336
  self[:attachable_type] = (attachable.class.name if attachable)
@@ -334,7 +334,7 @@ describe "Many Through Many Plugin" do
334
334
  c.exclude(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
335
335
  end
336
336
 
337
- specify "should handle extreme case with 5 join tables" do
337
+ cspecify "should handle extreme case with 5 join tables", :fdbsql do
338
338
  Artist.many_through_many :related_albums, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id], [:artists, :id, :id], [:albums_artists, :artist_id, :album_id]], :class=>Album, :distinct=>true
339
339
  @db[:albums_artists].delete
340
340
  @album1.add_artist(@artist1)
@@ -455,6 +455,7 @@ describe "Tactical Eager Loading Plugin" do
455
455
  before(:all) do
456
456
  @db = DB
457
457
  @db.instance_variable_set(:@schemas, {})
458
+ @db.drop_table?(:albums_artists) # work around fdbsql disconnect bug
458
459
  @db.create_table!(:artists) do
459
460
  primary_key :id
460
461
  String :name
@@ -2068,7 +2069,7 @@ describe "Sequel::Plugins::ConstraintValidations" do
2068
2069
  it_should_behave_like "constraint validations"
2069
2070
  end
2070
2071
  end
2071
- end
2072
+ end unless DB.database_type == :fdbsql # doesn't handle check constraints
2072
2073
 
2073
2074
  describe "date_arithmetic extension" do
2074
2075
  asd = begin
@@ -161,7 +161,7 @@ describe "Prepared Statements and Bound Arguments" do
161
161
  @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.should == [20]
162
162
  end
163
163
 
164
- specify "should support prepared statements being called multiple times with different arguments" do
164
+ cspecify "should support prepared statements being called multiple times with different arguments", [:jdbc, :fdbsql] do
165
165
  @ds.filter(:numb=>:$n).prepare(:select, :select_n)
166
166
  @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
167
167
  @db.call(:select_n, :n=>0).should == []
@@ -304,7 +304,7 @@ describe "Bound Argument Types" do
304
304
  @ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
305
305
  end
306
306
 
307
- cspecify "should handle datetime type with fractional seconds", [:do], [:mysql2], [:jdbc, :sqlite], [:tinytds], [:oracle] do
307
+ cspecify "should handle datetime type with fractional seconds", [:do, :postgres], [:jdbc, :sqlite], [:oracle] do
308
308
  Sequel.datetime_class = DateTime
309
309
  fract_time = DateTime.parse('2010-10-12 13:14:15.500000')
310
310
  @ds.prepare(:update, :ps_datetime_up, :dt=>:$x).call(:x=>fract_time)
@@ -315,7 +315,7 @@ describe "Bound Argument Types" do
315
315
  @ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
316
316
  end
317
317
 
318
- cspecify "should handle time type with fractional seconds", [:do], [:jdbc, :sqlite], [:oracle], [:swift, :postgres] do
318
+ cspecify "should handle time type with fractional seconds", [:do, :postgres], [:jdbc, :sqlite], [:oracle], [:swift, :postgres] do
319
319
  fract_time = @vs[:t] + 0.5
320
320
  @ds.prepare(:update, :ps_time_up, :t=>:$x).call(:x=>fract_time)
321
321
  @ds.literal(@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>fract_time)[:t]).should == @ds.literal(fract_time)
@@ -364,7 +364,7 @@ describe "Database schema modifiers" do
364
364
  end
365
365
  end
366
366
 
367
- specify "should create temporary tables without raising an exception" do
367
+ cspecify "should create temporary tables without raising an exception", :fdbsql do
368
368
  @db.create_table!(:items_temp, :temp=>true){Integer :number}
369
369
  end
370
370
 
@@ -420,7 +420,7 @@ describe "Database schema modifiers" do
420
420
  @ds.insert([10])
421
421
  end
422
422
 
423
- specify "should be able to specify constraint names for column constraints" do
423
+ cspecify "should be able to specify constraint names for column constraints", :fdbsql do
424
424
  @db.create_table!(:items2){primary_key :id, :primary_key_constraint_name=>:foo_pk}
425
425
  @db.create_table!(:items){foreign_key :id, :items2, :unique=>true, :foreign_key_constraint_name => :foo_fk, :unique_constraint_name => :foo_uk, :null=>false}
426
426
  @db.alter_table(:items){drop_constraint :foo_fk, :type=>:foreign_key; drop_constraint :foo_uk, :type=>:unique}
@@ -681,7 +681,7 @@ describe "Database schema modifiers" do
681
681
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
682
682
  end
683
683
 
684
- cspecify "should work correctly with many operations in a single alter_table call", [:jdbc, :db2], [:db2] do
684
+ cspecify "should work correctly with many operations in a single alter_table call", [:jdbc, :db2], [:db2], :fdbsql do
685
685
  @db.create_table!(:items) do
686
686
  primary_key :id
687
687
  String :name2
@@ -17,6 +17,7 @@ end
17
17
  Sequel::Deprecation.backtrace_filter = lambda{|line, lineno| lineno < 4 || line =~ /_(spec|test)\.rb/}
18
18
 
19
19
  Sequel::Database.extension :columns_introspection if ENV['SEQUEL_COLUMNS_INTROSPECTION']
20
+ Sequel::Model.cache_associations = false if ENV['SEQUEL_NO_CACHE_ASSOCIATIONS']
20
21
  Sequel::Model.use_transactions = false
21
22
  Sequel.cache_anonymous_models = false
22
23
 
@@ -74,7 +75,11 @@ RSPEC_EXAMPLE_GROUP.class_eval do
74
75
 
75
76
  def self.cspecify(message, *checked, &block)
76
77
  if pending = Sequel.guarded?(*checked)
77
- specify(message){pending("Not yet working on #{Array(pending).map{|x| x.is_a?(Proc) ? :proc : x}.join(', ')}", &block)}
78
+ specify(message) do
79
+ method = RSPEC_SKIP_PENDING && !ENV['SEQUEL_NO_SKIP_PENDING'] ? :skip : :pending
80
+ send(method, "Not yet working on #{Array(pending).map{|x| x.is_a?(Proc) ? :proc : x}.join(', ')}")
81
+ instance_eval(&block)
82
+ end
78
83
  else
79
84
  specify(message, &block)
80
85
  end
@@ -65,7 +65,7 @@ describe "Sequel timezone support" do
65
65
  test_timezone
66
66
  end
67
67
 
68
- cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle], [:swift, :postgres], [:swift, :mysql] do
68
+ cspecify "should support using local time for both database storage and for application", [:do, :postgres], [:oracle], [:swift, :postgres], [:swift, :mysql] do
69
69
  Sequel.default_timezone = :local
70
70
  test_timezone
71
71
  Sequel.database_timezone = :utc
@@ -64,6 +64,13 @@ describe Sequel::Model::Associations::AssociationReflection, "#reciprocal" do
64
64
  @c.association_reflection(:c).reciprocal.should == :xx
65
65
  end
66
66
 
67
+ it "should not raise an error if some reciprocal associations have invalid associated classes" do
68
+ @c = Class.new(Sequel::Model(:foo))
69
+ @c.one_to_many :sadfakloasdfioas
70
+ @c.many_to_one :c, :class=>@c
71
+ proc{@c.association_reflection(:c).reciprocal}.should_not raise_error
72
+ end
73
+
67
74
  it "should require the associated class is the current class to be a reciprocal" do
68
75
  ParParent.many_to_one :par_parent_two, :key=>:blah
69
76
  ParParent.many_to_one :par_parent_three, :key=>:blah
@@ -469,3 +476,25 @@ describe Sequel::Model, " association reflection methods" do
469
476
  c.instance_methods.map{|x| x.to_s}.should include('parent')
470
477
  end
471
478
  end
479
+
480
+ describe Sequel::Model::Associations::AssociationReflection, "with caching disabled" do
481
+ before do
482
+ @c = Class.new(Sequel::Model(:foo))
483
+ end
484
+ after do
485
+ Object.send(:remove_const, :ParParent)
486
+ end
487
+
488
+ it "should not cache metadata" do
489
+ class ::ParParent < Sequel::Model; end
490
+ c = ParParent
491
+ @c.cache_associations = false
492
+ @c.many_to_one :c, :class=>:ParParent
493
+ @c.association_reflection(:c).associated_class.should == c
494
+ Object.send(:remove_const, :ParParent)
495
+ class ::ParParent < Sequel::Model; end
496
+ c = ParParent
497
+ @c.association_reflection(:c).associated_class.should == c
498
+ end
499
+ end
500
+