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.
- 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
|
+
|