sequel 4.14.0 → 4.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +32 -0
- data/README.rdoc +3 -3
- data/Rakefile +1 -1
- data/doc/opening_databases.rdoc +20 -2
- data/doc/release_notes/4.15.0.txt +56 -0
- data/doc/testing.rdoc +10 -4
- data/lib/sequel/adapters/fdbsql.rb +285 -0
- data/lib/sequel/adapters/informix.rb +15 -0
- data/lib/sequel/adapters/jdbc/fdbsql.rb +65 -0
- data/lib/sequel/adapters/mock.rb +1 -0
- data/lib/sequel/adapters/shared/fdbsql.rb +550 -0
- data/lib/sequel/adapters/shared/postgres.rb +23 -10
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +10 -3
- data/lib/sequel/dataset/placeholder_literalizer.rb +7 -0
- data/lib/sequel/extensions/date_arithmetic.rb +5 -0
- data/lib/sequel/extensions/migration.rb +2 -2
- data/lib/sequel/extensions/pg_array.rb +15 -1
- data/lib/sequel/extensions/pg_json.rb +3 -0
- data/lib/sequel/extensions/pg_json_ops.rb +4 -4
- data/lib/sequel/extensions/schema_dumper.rb +9 -1
- data/lib/sequel/model/associations.rb +70 -21
- data/lib/sequel/plugins/active_model.rb +7 -2
- data/lib/sequel/plugins/many_through_many.rb +1 -0
- data/lib/sequel/plugins/pg_array_associations.rb +2 -1
- data/lib/sequel/plugins/split_values.rb +64 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/fdbsql_spec.rb +429 -0
- data/spec/adapters/informix_spec.rb +6 -0
- data/spec/adapters/postgres_spec.rb +49 -1
- data/spec/adapters/spec_helper.rb +6 -1
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/placeholder_literalizer_spec.rb +10 -0
- data/spec/extensions/date_arithmetic_spec.rb +7 -0
- data/spec/extensions/many_through_many_spec.rb +14 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/pg_array_associations_spec.rb +9 -0
- data/spec/extensions/pg_json_ops_spec.rb +4 -8
- data/spec/extensions/schema_dumper_spec.rb +9 -0
- data/spec/extensions/spec_helper.rb +3 -0
- data/spec/extensions/split_values_spec.rb +22 -0
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +1 -1
- data/spec/integration/eager_loader_test.rb +1 -1
- data/spec/integration/plugin_test.rb +3 -2
- data/spec/integration/prepared_statement_test.rb +3 -3
- data/spec/integration/schema_test.rb +3 -3
- data/spec/integration/spec_helper.rb +6 -1
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/model/association_reflection_spec.rb +29 -0
- data/spec/model/associations_spec.rb +36 -0
- data/spec/model/eager_loading_spec.rb +14 -0
- data/spec/model/spec_helper.rb +3 -0
- data/spec/rspec_helper.rb +4 -0
- 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
|
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)
|
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, :
|
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
|
116
|
-
@l[@jb.to_record].should == "jsonb_to_record(j
|
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
|
123
|
-
@l[@jb.to_recordset].should == "jsonb_to_recordset(j
|
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"
|
@@ -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", [:
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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)
|
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, :
|
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
|
+
|