sequel 4.42.1 → 4.43.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 +35 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/doc/release_notes/4.43.0.txt +87 -0
- data/doc/sql.rdoc +26 -27
- data/doc/testing.rdoc +2 -0
- data/doc/validations.rdoc +1 -1
- data/lib/sequel/adapters/ado.rb +5 -0
- data/lib/sequel/adapters/cubrid.rb +5 -0
- data/lib/sequel/adapters/ibmdb.rb +5 -0
- data/lib/sequel/adapters/jdbc.rb +6 -0
- data/lib/sequel/adapters/jdbc/derby.rb +5 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +9 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +5 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -0
- data/lib/sequel/adapters/mock.rb +12 -9
- data/lib/sequel/adapters/mysql.rb +6 -0
- data/lib/sequel/adapters/mysql2.rb +7 -2
- data/lib/sequel/adapters/oracle.rb +5 -0
- data/lib/sequel/adapters/shared/db2.rb +7 -1
- data/lib/sequel/adapters/shared/mssql.rb +5 -0
- data/lib/sequel/adapters/shared/mysql.rb +8 -1
- data/lib/sequel/adapters/shared/oracle.rb +20 -12
- data/lib/sequel/adapters/shared/postgres.rb +11 -2
- data/lib/sequel/adapters/shared/sqlanywhere.rb +6 -0
- data/lib/sequel/adapters/shared/sqlite.rb +29 -0
- data/lib/sequel/adapters/sqlanywhere.rb +5 -0
- data/lib/sequel/adapters/sqlite.rb +13 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/single.rb +15 -6
- data/lib/sequel/database/dataset.rb +3 -0
- data/lib/sequel/database/misc.rb +22 -1
- data/lib/sequel/database/query.rb +2 -4
- data/lib/sequel/dataset/actions.rb +0 -1
- data/lib/sequel/dataset/misc.rb +2 -4
- data/lib/sequel/dataset/query.rb +23 -6
- data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
- data/lib/sequel/extensions/_model_pg_row.rb +47 -0
- data/lib/sequel/extensions/looser_typecasting.rb +2 -0
- data/lib/sequel/extensions/migration.rb +12 -1
- data/lib/sequel/extensions/pg_array.rb +6 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -1
- data/lib/sequel/extensions/pg_range.rb +6 -0
- data/lib/sequel/extensions/pg_row.rb +8 -0
- data/lib/sequel/model/associations.rb +3 -1
- data/lib/sequel/model/base.rb +14 -3
- data/lib/sequel/plugins/constraint_validations.rb +1 -8
- data/lib/sequel/plugins/instance_filters.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +1 -40
- data/lib/sequel/plugins/prepared_statements.rb +51 -20
- data/lib/sequel/plugins/prepared_statements_associations.rb +22 -4
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +9 -1
- data/lib/sequel/plugins/sharding.rb +5 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/spec_helper.rb +4 -0
- data/spec/core/connection_pool_spec.rb +10 -0
- data/spec/core/database_spec.rb +29 -0
- data/spec/extensions/blacklist_security_spec.rb +4 -4
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/force_encoding_spec.rb +3 -2
- data/spec/extensions/identifier_mangling_spec.rb +7 -0
- data/spec/extensions/instance_filters_spec.rb +1 -0
- data/spec/extensions/migration_spec.rb +19 -0
- data/spec/extensions/pg_array_spec.rb +5 -0
- data/spec/extensions/pg_range_spec.rb +5 -0
- data/spec/extensions/pg_row_spec.rb +9 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +45 -1
- data/spec/extensions/prepared_statements_spec.rb +138 -41
- data/spec/extensions/prepared_statements_with_pk_spec.rb +7 -0
- data/spec/extensions/serialization_spec.rb +6 -6
- data/spec/extensions/single_table_inheritance_spec.rb +3 -3
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/integration/associations_test.rb +2 -2
- data/spec/integration/dataset_test.rb +0 -4
- data/spec/integration/eager_loader_test.rb +5 -5
- data/spec/integration/plugin_test.rb +8 -6
- data/spec/integration/schema_test.rb +2 -2
- data/spec/integration/spec_helper.rb +10 -0
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +5 -5
- data/spec/model/associations_spec.rb +13 -6
- data/spec/model/base_spec.rb +1 -1
- data/spec/model/hooks_spec.rb +4 -4
- data/spec/model/model_spec.rb +2 -2
- data/spec/model/record_spec.rb +17 -18
- metadata +6 -2
@@ -14,6 +14,13 @@ describe "identifier_mangling extension" do
|
|
14
14
|
db.quote_identifiers?.must_equal true
|
15
15
|
end
|
16
16
|
|
17
|
+
it "should respect the :quote_identifiers setting" do
|
18
|
+
db = Sequel::Database.new(:identifier_mangling=>true)
|
19
|
+
db.quote_identifiers?.must_equal false
|
20
|
+
db.quote_identifiers = true
|
21
|
+
db.quote_identifiers?.must_equal true
|
22
|
+
end
|
23
|
+
|
17
24
|
it "should upcase on input and downcase on output by default" do
|
18
25
|
db = Sequel::Database.new(:identifier_mangling=>true)
|
19
26
|
db.send(:identifier_input_method_default).must_equal :upcase
|
@@ -39,6 +39,7 @@ describe "instance_filters plugin" do
|
|
39
39
|
|
40
40
|
@p = @c.load(:id=>1, :name=>'John', :num=>1)
|
41
41
|
@p.instance_variable_set(:@this, @p.this.with_numrows(1))
|
42
|
+
@c.instance_variable_set(:@fast_instance_delete_sql, nil)
|
42
43
|
@p.destroy
|
43
44
|
DB.sqls.must_equal ["DELETE FROM people WHERE (id = 1)"]
|
44
45
|
@p.instance_filter(:name=>'Jim')
|
@@ -772,4 +772,23 @@ describe "Sequel::TimestampMigrator" do
|
|
772
772
|
Sequel::TimestampMigrator.run(@db, "spec/files/transaction_unspecified_migrations", :use_transactions=>false)
|
773
773
|
@db.sqls.must_equal ["SELECT NULL AS nil FROM schema_migrations LIMIT 1", "CREATE TABLE schema_migrations (filename varchar(255) PRIMARY KEY)", "SELECT NULL AS nil FROM schema_info LIMIT 1", "SELECT filename FROM schema_migrations ORDER BY filename", "CREATE TABLE sm11111 (smc1 integer)", "INSERT INTO schema_migrations (filename) VALUES ('001_create_alt_basic.rb')", "CREATE TABLE sm (smc1 integer)", "INSERT INTO schema_migrations (filename) VALUES ('002_create_basic.rb')"]
|
774
774
|
end
|
775
|
+
|
776
|
+
it "should use shorter primary key field on MySQL if creating schema migrations table fails" do
|
777
|
+
def @db.database_type; :mysql end
|
778
|
+
def @db.execute_ddl(sql, *)
|
779
|
+
super
|
780
|
+
raise Sequel::DatabaseError, "Specified key was too long; max key length is 767 bytes" if sql =~ /varchar\(255\)/
|
781
|
+
end
|
782
|
+
Sequel::TimestampMigrator.run(@db, "spec/files/transaction_unspecified_migrations", :use_transactions=>false)
|
783
|
+
@db.sqls.must_equal ["SELECT NULL AS nil FROM schema_migrations LIMIT 1", "CREATE TABLE schema_migrations (filename varchar(255) PRIMARY KEY)", "CREATE TABLE schema_migrations (filename varchar(190) PRIMARY KEY)", "SELECT NULL AS nil FROM schema_info LIMIT 1", "SELECT filename FROM schema_migrations ORDER BY filename", "CREATE TABLE sm11111 (smc1 integer)", "INSERT INTO schema_migrations (filename) VALUES ('001_create_alt_basic.rb')", "CREATE TABLE sm (smc1 integer)", "INSERT INTO schema_migrations (filename) VALUES ('002_create_basic.rb')"]
|
784
|
+
end
|
785
|
+
|
786
|
+
it "should not use shorter primary key field on other databases if creating schema migrations table fails" do
|
787
|
+
def @db.execute_ddl(sql, *)
|
788
|
+
super
|
789
|
+
raise Sequel::DatabaseError, "Specified key was too long; max key length is 767 bytes" if sql =~ /varchar\(255\)/
|
790
|
+
end
|
791
|
+
proc{Sequel::TimestampMigrator.run(@db, "spec/files/transaction_unspecified_migrations", :use_transactions=>false)}.must_raise Sequel::DatabaseError
|
792
|
+
@db.sqls.must_equal ["SELECT NULL AS nil FROM schema_migrations LIMIT 1", "CREATE TABLE schema_migrations (filename varchar(255) PRIMARY KEY)"]
|
793
|
+
end
|
775
794
|
end
|
@@ -330,6 +330,11 @@ describe "pg_array extension" do
|
|
330
330
|
@db.literal(Sequel::Postgres::PG_TYPES[3].call('{}')).must_equal "'{}'::blah[]"
|
331
331
|
end
|
332
332
|
|
333
|
+
it "should not support registering custom array types on a per-Database basis for frozen databases" do
|
334
|
+
@db.freeze
|
335
|
+
proc{@db.register_array_type('banana', :oid=>7865){|s| s}}.must_raise RuntimeError, TypeError
|
336
|
+
end
|
337
|
+
|
333
338
|
it "should support registering custom array types on a per-Database basis" do
|
334
339
|
@db.register_array_type('banana', :oid=>7865){|s| s}
|
335
340
|
@db.typecast_value(:banana_array, []).class.must_equal(Sequel::Postgres::PGArray)
|
@@ -170,6 +170,11 @@ describe "pg_range extension" do
|
|
170
170
|
Sequel::Postgres::PG_TYPES[331].call('[1,3)').must_be_kind_of(@R)
|
171
171
|
end
|
172
172
|
|
173
|
+
it "should not support registering custom range types on a per-Database basis for frozen databases" do
|
174
|
+
@db.freeze
|
175
|
+
proc{@db.register_range_type('banana', :oid=>7865){|s| s}}.must_raise RuntimeError, TypeError
|
176
|
+
end
|
177
|
+
|
173
178
|
it "should support registering custom range types on a per-Database basis" do
|
174
179
|
@db.register_range_type('banana', :oid=>7865){|s| s}
|
175
180
|
@db.typecast_value(:banana, '[1,2]').class.must_equal(Sequel::Postgres::PGRange)
|
@@ -231,6 +231,15 @@ describe "pg_row extension" do
|
|
231
231
|
@db.literal(p1.call('(1,b)')).must_equal "ROW(1, 'bb')::foo.bar"
|
232
232
|
end
|
233
233
|
|
234
|
+
it "should not allow registering on a frozen database" do
|
235
|
+
@db.conversion_procs[4] = proc{|s| s.to_i}
|
236
|
+
@db.conversion_procs[5] = proc{|s| s * 2}
|
237
|
+
@db.fetch = [[], [{:oid=>1, :typrelid=>2, :typarray=>3}], [{:attname=>'bar', :atttypid=>4}, {:attname=>'baz', :atttypid=>5}]]
|
238
|
+
c = proc{|h| [h]}
|
239
|
+
@db.freeze
|
240
|
+
proc{@db.register_row_type(:foo, :converter=>c)}.must_raise RuntimeError, TypeError
|
241
|
+
end
|
242
|
+
|
234
243
|
it "should allow registering with a custom converter" do
|
235
244
|
@db.conversion_procs[4] = proc{|s| s.to_i}
|
236
245
|
@db.conversion_procs[5] = proc{|s| s * 2}
|
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
3
3
|
describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
4
4
|
before do
|
5
|
-
@db = Sequel.mock
|
5
|
+
@db = Sequel.mock(:servers=>{:foo=>{}})
|
6
6
|
@db.extend_datasets do
|
7
7
|
def select_sql
|
8
8
|
sql = super
|
@@ -52,6 +52,43 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
52
52
|
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) WHERE (albums.artist_id = 1) LIMIT 1 -- prepared"]
|
53
53
|
end
|
54
54
|
|
55
|
+
it "should run correct shard for associations when also using sharding plugin" do
|
56
|
+
@Artist.plugin :sharding
|
57
|
+
@Album.plugin :sharding
|
58
|
+
|
59
|
+
@Artist.load(:id=>1).set_server(:foo).albums
|
60
|
+
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE (albums.artist_id = 1) -- prepared -- foo"]
|
61
|
+
|
62
|
+
@Artist.load(:id=>1).set_server(:foo).album
|
63
|
+
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE (albums.artist_id = 1) LIMIT 1 -- prepared -- foo"]
|
64
|
+
|
65
|
+
@Album.load(:id=>1, :artist_id=>2).set_server(:foo).artist
|
66
|
+
@db.sqls.must_equal ["SELECT id, id2 FROM artists WHERE (artists.id = 2) LIMIT 1 -- prepared -- foo"]
|
67
|
+
|
68
|
+
@Album.load(:id=>1, :artist_id=>2).set_server(:foo).tags
|
69
|
+
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 1) -- prepared -- foo"]
|
70
|
+
|
71
|
+
@Album.load(:id=>1, :artist_id=>2).set_server(:foo).tag
|
72
|
+
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 1) LIMIT 1 -- prepared -- foo"]
|
73
|
+
|
74
|
+
@Artist.load(:id=>1).set_server(:foo).tags
|
75
|
+
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) WHERE (albums.artist_id = 1) -- prepared -- foo"]
|
76
|
+
|
77
|
+
@Artist.load(:id=>1).set_server(:foo).tag
|
78
|
+
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) WHERE (albums.artist_id = 1) LIMIT 1 -- prepared -- foo"]
|
79
|
+
|
80
|
+
@Tag.plugin :sharding
|
81
|
+
@Tag.plugin :prepared_statements_associations
|
82
|
+
@Tag.many_to_many :albums, :class=>@Album, :join_table=>:albums_tags, :left_key=>:tag_id
|
83
|
+
@Tag.load(:id=>1).set_server(:foo).albums
|
84
|
+
@db.sqls.must_equal ["SELECT albums.id, albums.artist_id, albums.id2, albums.artist_id2 FROM albums INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE (albums_tags.tag_id = 1) -- prepared -- foo"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should not override the shard for associations if not using the sharding plugin" do
|
88
|
+
@Artist.load(:id=>1).set_server(:foo).albums
|
89
|
+
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE (albums.artist_id = 1) -- prepared"]
|
90
|
+
end
|
91
|
+
|
55
92
|
it "should run correct SQL for composite key associations" do
|
56
93
|
@Artist.one_to_many :albums, :class=>@Album, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
57
94
|
@Artist.one_to_one :album, :class=>@Album, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
@@ -156,4 +193,11 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
156
193
|
@Artist.load(:id=>1).oalbums
|
157
194
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
158
195
|
end
|
196
|
+
|
197
|
+
it "should work correctly when using an instance specific association" do
|
198
|
+
tag = @Tag
|
199
|
+
@Artist.many_to_one :tag, :key=>nil, :read_only=>true, :dataset=>proc{tag.where(:id=>id).limit(1)}, :reciprocal=>nil, :reciprocal_type=>nil
|
200
|
+
@Artist.load(:id=>1).tag.must_be_nil
|
201
|
+
@db.sqls.must_equal ["SELECT * FROM tags WHERE (id = 1) LIMIT 1"]
|
202
|
+
end
|
159
203
|
end
|
@@ -5,6 +5,7 @@ describe "prepared_statements plugin" do
|
|
5
5
|
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
6
6
|
@c = Class.new(Sequel::Model(@db[:people]))
|
7
7
|
@c.columns :id, :name, :i
|
8
|
+
@c.set_primary_key :id
|
8
9
|
@columns = "id, name, i"
|
9
10
|
@c.plugin :prepared_statements
|
10
11
|
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
@@ -12,11 +13,6 @@ describe "prepared_statements plugin" do
|
|
12
13
|
@db.sqls
|
13
14
|
end
|
14
15
|
|
15
|
-
it "should correctly lookup by primary key" do
|
16
|
-
@c[1].must_equal @p
|
17
|
-
@db.sqls.must_equal ["SELECT id, name, i FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
18
|
-
end
|
19
|
-
|
20
16
|
it "should correctly lookup by primary key for joined dataset" do
|
21
17
|
@c.dataset = @c.dataset.from(:people, :people2)
|
22
18
|
@db.sqls
|
@@ -24,22 +20,46 @@ describe "prepared_statements plugin" do
|
|
24
20
|
@db.sqls.must_equal ["SELECT * FROM people, people2 WHERE (people.id = 1) LIMIT 1 -- read_only"]
|
25
21
|
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
it "should use prepared statements for pk lookups only if default is not optimized" do
|
24
|
+
@c.send(:use_prepared_statements_for_pk_lookup?).must_equal false
|
25
|
+
@c.set_primary_key [:id, :name]
|
26
|
+
@c.send(:use_prepared_statements_for_pk_lookup?).must_equal true
|
27
|
+
@c.set_primary_key :id
|
28
|
+
@c.dataset = @c.dataset.from(:people, :people2)
|
29
|
+
@c.send(:use_prepared_statements_for_pk_lookup?).must_equal false
|
30
|
+
@c.dataset = @db[:people].select(:id, :name, :i)
|
31
|
+
@c.send(:use_prepared_statements_for_pk_lookup?).must_equal true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should use prepared statements for refreshes if default is not optimized" do
|
35
|
+
@p.send(:use_prepared_statements_for?, :refresh).must_equal false
|
36
|
+
@c.set_primary_key [:id, :name]
|
37
|
+
@p.send(:use_prepared_statements_for?, :refresh).must_equal true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use prepared statements for deletes if default is not optimized" do
|
41
|
+
@p.send(:use_prepared_statements_for?, :delete).must_equal false
|
42
|
+
@c.set_primary_key [:id, :name]
|
43
|
+
@p.send(:use_prepared_statements_for?, :delete).must_equal true
|
44
|
+
end
|
32
45
|
|
46
|
+
it "should use prepared statements for deletes if default on Oracle and DB2" do
|
47
|
+
def @db.database_type; :oracle end
|
48
|
+
@p.send(:use_prepared_statements_for?, :delete).must_equal true
|
49
|
+
def @db.database_type; :db2 end
|
50
|
+
@p.send(:use_prepared_statements_for?, :delete).must_equal true
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should raise Error for unsupported prepared statement types" do
|
54
|
+
proc{@p.send(:use_prepared_statements_for?, :foo)}.must_raise Sequel::Error
|
55
|
+
end
|
56
|
+
|
57
|
+
prepared_statements_spec = shared_description do
|
33
58
|
it "should correctly update instance" do
|
34
59
|
@p.update(:name=>'bar').must_equal @c.load(:id=>1, :name=>'bar', :i => 2)
|
35
60
|
@db.sqls.must_equal ["UPDATE people SET name = 'bar' WHERE (id = 1)"]
|
36
61
|
end
|
37
62
|
|
38
|
-
it "should correctly create instance" do
|
39
|
-
@c.create(:name=>'foo').must_equal @c.load(:id=>1, :name=>'foo', :i => 2)
|
40
|
-
@db.sqls.must_equal ["INSERT INTO people (name) VALUES ('foo')", "SELECT #{@columns} FROM people WHERE (id = 1) LIMIT 1"]
|
41
|
-
end
|
42
|
-
|
43
63
|
it "should correctly create instance if dataset supports insert_select" do
|
44
64
|
@c.dataset_module do
|
45
65
|
def supports_insert_select?
|
@@ -61,51 +81,128 @@ describe "prepared_statements plugin" do
|
|
61
81
|
end
|
62
82
|
end
|
63
83
|
|
64
|
-
describe "when #use_prepared_statements_for? returns
|
84
|
+
describe "when #use_prepared_statements_for? returns true" do
|
65
85
|
before do
|
66
|
-
@
|
67
|
-
|
86
|
+
@c.class_eval do
|
87
|
+
def self.use_prepared_statements_for_pk_lookup?; true end
|
88
|
+
def use_prepared_statements_for?(type) true end
|
89
|
+
end
|
68
90
|
end
|
69
91
|
|
70
92
|
include prepared_statements_spec
|
71
|
-
end
|
72
93
|
|
73
|
-
|
94
|
+
it "should correctly create instance" do
|
95
|
+
@c.create(:name=>'foo').must_equal @c.load(:id=>1, :name=>'foo', :i => 2)
|
96
|
+
@db.sqls.must_equal ["INSERT INTO people (name) VALUES ('foo')", "SELECT #{@columns} FROM people WHERE (id = 1) LIMIT 1"]
|
97
|
+
end
|
74
98
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
99
|
+
it "should correctly lookup by primary key" do
|
100
|
+
@c[1].must_equal @p
|
101
|
+
@db.sqls.must_equal ["SELECT id, name, i FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
102
|
+
end
|
80
103
|
|
81
|
-
|
82
|
-
|
83
|
-
@
|
104
|
+
it "should correctly delete instance" do
|
105
|
+
@p.destroy.must_equal @p
|
106
|
+
@db.sqls.must_equal ["DELETE FROM people WHERE (id = 1)"]
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should correctly delete instance when specifying server" do
|
110
|
+
@p.set_server(:read_only).destroy.must_equal @p
|
111
|
+
@db.sqls.must_equal ["DELETE FROM people WHERE (id = 1) -- read_only"]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should correctly update instance when specifying server" do
|
115
|
+
@p.set_server(:read_only).update(:name=>'bar').must_equal @c.load(:id=>1, :name=>'bar', :i => 2)
|
116
|
+
@db.sqls.must_equal ["UPDATE people SET name = 'bar' WHERE (id = 1) -- read_only"]
|
84
117
|
end
|
85
118
|
|
86
|
-
it "should correctly
|
119
|
+
it "should correctly create instance when specifying server" do
|
120
|
+
@c.new(:name=>'foo').set_server(:read_only).save.must_equal @c.load(:id=>1, :name=>'foo', :i => 2)
|
121
|
+
@db.sqls.must_equal ["INSERT INTO people (name) VALUES ('foo') -- read_only", "SELECT #{@columns} FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should correctly create instance if dataset supports insert_select when specifying server" do
|
125
|
+
@c.dataset_module do
|
126
|
+
def supports_insert_select?
|
127
|
+
true
|
128
|
+
end
|
129
|
+
def supports_returning?(type)
|
130
|
+
true
|
131
|
+
end
|
132
|
+
def insert_select(h)
|
133
|
+
cache_set(:_fetch, :id=>1, :name=>'foo', :i => 2)
|
134
|
+
server(:default).with_sql_first(insert_select_sql(h))
|
135
|
+
end
|
136
|
+
def insert_select_sql(*v)
|
137
|
+
"#{insert_sql(*v)} RETURNING #{(opts[:returning] && !opts[:returning].empty?) ? opts[:returning].map{|c| literal(c)}.join(', ') : '*'}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
@c.new(:name=>'foo').set_server(:read_only).save.must_equal @c.load(:id=>1, :name=>'foo', :i => 2)
|
141
|
+
@db.sqls.must_equal ["INSERT INTO people (name) VALUES ('foo') RETURNING #{@columns} -- read_only"]
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should work correctly when subclassing" do
|
145
|
+
c = Class.new(@c)
|
146
|
+
c[1].must_equal c.load(:id=>1, :name=>'foo', :i=>2)
|
147
|
+
@db.sqls.must_equal ["SELECT id, name, i FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should correctly handle without schema type when placeholder type specifiers are required" do
|
151
|
+
@c.dataset = @ds.with_extend{def requires_placeholder_type_specifiers?; true end}
|
87
152
|
@c[1].must_equal @p
|
88
153
|
@db.sqls.must_equal ["SELECT id, name, i FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
89
154
|
end
|
90
155
|
|
91
|
-
it "should correctly handle with schema type" do
|
92
|
-
@c.
|
93
|
-
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
156
|
+
it "should correctly handle with schema type when placeholder type specifiers are required" do
|
157
|
+
@c.dataset = @ds.with_extend do
|
158
|
+
def requires_placeholder_type_specifiers?; true end
|
159
|
+
def prepare(*)
|
160
|
+
super.with_extend do
|
161
|
+
def literal_symbol_append(sql, v)
|
162
|
+
if @opts[:bind_vars] && (match = /\A\$(.*)\z/.match(v.to_s))
|
163
|
+
s = match[1].split('__')[0].to_sym
|
164
|
+
if prepared_arg?(s)
|
165
|
+
literal_append(sql, prepared_arg(s))
|
166
|
+
else
|
167
|
+
sql << v.to_s
|
168
|
+
end
|
169
|
+
else
|
170
|
+
super
|
171
|
+
end
|
101
172
|
end
|
102
|
-
else
|
103
|
-
super
|
104
173
|
end
|
105
174
|
end
|
106
175
|
end
|
176
|
+
@c.db_schema[:id][:type] = :integer
|
107
177
|
@c[1].must_equal @p
|
108
178
|
@db.sqls.must_equal ["SELECT id, name, i FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
109
179
|
end
|
110
180
|
end
|
181
|
+
|
182
|
+
describe "when #use_prepared_statements_for? returns false" do
|
183
|
+
before do
|
184
|
+
@columns = "*"
|
185
|
+
@c.class_eval do
|
186
|
+
def self.use_prepared_statements_for_pk_lookup?; false end
|
187
|
+
def use_prepared_statements_for?(type) false end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
include prepared_statements_spec
|
192
|
+
|
193
|
+
it "should correctly create instance" do
|
194
|
+
@c.create(:name=>'foo').must_equal @c.load(:id=>1, :name=>'foo', :i => 2)
|
195
|
+
@db.sqls.must_equal ["INSERT INTO people (name) VALUES ('foo')", "SELECT #{@columns} FROM people WHERE id = 1"]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should correctly lookup by primary key" do
|
199
|
+
@c[1].must_equal @p
|
200
|
+
@db.sqls.must_equal ["SELECT * FROM people WHERE id = 1 -- read_only"]
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should correctly delete instance" do
|
204
|
+
@p.destroy.must_equal @p
|
205
|
+
@db.sqls.must_equal ["DELETE FROM people WHERE id = 1"]
|
206
|
+
end
|
207
|
+
end
|
111
208
|
end
|
@@ -28,4 +28,11 @@ describe "prepared_statements_with_pk plugin" do
|
|
28
28
|
@c.dataset.filter{id > 2}[1].must_equal @p
|
29
29
|
@c.db.sqls.must_equal ["SELECT * FROM people WHERE ((id > 2) AND (people.id = 1)) LIMIT 1 -- read_only"]
|
30
30
|
end
|
31
|
+
|
32
|
+
it "should respect explicitly set server" do
|
33
|
+
@c.dataset.filter(:name=>'foo')[1].must_equal @p
|
34
|
+
@c.db.sqls.must_equal ["SELECT * FROM people WHERE ((name = 'foo') AND (people.id = 1)) LIMIT 1 -- read_only"]
|
35
|
+
@c.dataset.server(:default).filter(:name=>'foo')[1].must_equal @p
|
36
|
+
@c.db.sqls.must_equal ["SELECT * FROM people WHERE ((name = 'foo') AND (people.id = 1)) LIMIT 1"]
|
37
|
+
end
|
31
38
|
end
|
@@ -108,7 +108,7 @@ describe "Serialization plugin" do
|
|
108
108
|
DB.sqls.must_equal ["SELECT * FROM items LIMIT 1",
|
109
109
|
"UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)",
|
110
110
|
"INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')",
|
111
|
-
"SELECT * FROM items WHERE
|
111
|
+
"SELECT * FROM items WHERE id = 10"]
|
112
112
|
end
|
113
113
|
|
114
114
|
it "should translate values to and from marshal serialization format using accessor methods" do
|
@@ -128,7 +128,7 @@ describe "Serialization plugin" do
|
|
128
128
|
DB.sqls.must_equal ["SELECT * FROM items LIMIT 1",
|
129
129
|
"UPDATE items SET abc = '#{[Marshal.dump(23)].pack('m')}' WHERE (id = 1)",
|
130
130
|
"INSERT INTO items (abc) VALUES ('#{[Marshal.dump([1, 2, 3])].pack('m')}')",
|
131
|
-
"SELECT * FROM items WHERE
|
131
|
+
"SELECT * FROM items WHERE id = 10"]
|
132
132
|
end
|
133
133
|
|
134
134
|
it "should handle old non-base-64 encoded marshal serialization format" do
|
@@ -169,7 +169,7 @@ describe "Serialization plugin" do
|
|
169
169
|
DB.sqls.must_equal ["SELECT * FROM items LIMIT 1",
|
170
170
|
"UPDATE items SET abc = '#{[23].to_json}' WHERE (id = 1)",
|
171
171
|
"INSERT INTO items (abc) VALUES ('#{[1,2,3].to_json}')",
|
172
|
-
"SELECT * FROM items WHERE
|
172
|
+
"SELECT * FROM items WHERE id = 10"]
|
173
173
|
end
|
174
174
|
|
175
175
|
it "should translate values to and from arbitrary callables using accessor methods" do
|
@@ -190,7 +190,7 @@ describe "Serialization plugin" do
|
|
190
190
|
DB.sqls.must_equal ["SELECT * FROM items LIMIT 1",
|
191
191
|
"UPDATE items SET abc = 'oof' WHERE (id = 1)",
|
192
192
|
"INSERT INTO items (abc) VALUES ('rab')",
|
193
|
-
"SELECT * FROM items WHERE
|
193
|
+
"SELECT * FROM items WHERE id = 10"]
|
194
194
|
end
|
195
195
|
|
196
196
|
it "should handle registration of custom serializer/deserializer pairs" do
|
@@ -213,7 +213,7 @@ describe "Serialization plugin" do
|
|
213
213
|
DB.sqls.must_equal ["SELECT * FROM items LIMIT 1",
|
214
214
|
"UPDATE items SET abc = 'oof' WHERE (id = 1)",
|
215
215
|
"INSERT INTO items (abc) VALUES ('rab')",
|
216
|
-
"SELECT * FROM items WHERE
|
216
|
+
"SELECT * FROM items WHERE id = 10"]
|
217
217
|
end
|
218
218
|
|
219
219
|
it "should copy serialization formats and columns to subclasses" do
|
@@ -233,7 +233,7 @@ describe "Serialization plugin" do
|
|
233
233
|
DB.sqls.must_equal ["SELECT * FROM items LIMIT 1",
|
234
234
|
"UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)",
|
235
235
|
"INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')",
|
236
|
-
"SELECT * FROM items WHERE
|
236
|
+
"SELECT * FROM items WHERE id = 10"]
|
237
237
|
end
|
238
238
|
|
239
239
|
it "should clear the deserialized columns when refreshing" do
|