sequel 4.14.0 → 4.15.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 (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
+