sequel 3.40.0 → 3.41.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.
- data/CHANGELOG +40 -0
- data/README.rdoc +2 -2
- data/doc/advanced_associations.rdoc +12 -0
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/migration.rdoc +1 -1
- data/doc/object_model.rdoc +29 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/lib/sequel/adapters/ado.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +0 -5
- data/lib/sequel/adapters/cubrid.rb +2 -2
- data/lib/sequel/adapters/db2.rb +9 -5
- data/lib/sequel/adapters/dbi.rb +4 -6
- data/lib/sequel/adapters/do.rb +4 -5
- data/lib/sequel/adapters/firebird.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +2 -3
- data/lib/sequel/adapters/informix.rb +0 -6
- data/lib/sequel/adapters/jdbc.rb +11 -7
- data/lib/sequel/adapters/jdbc/db2.rb +22 -0
- data/lib/sequel/adapters/jdbc/derby.rb +5 -5
- data/lib/sequel/adapters/jdbc/h2.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +6 -0
- data/lib/sequel/adapters/mock.rb +3 -3
- data/lib/sequel/adapters/mysql.rb +7 -7
- data/lib/sequel/adapters/mysql2.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +4 -4
- data/lib/sequel/adapters/openbase.rb +4 -6
- data/lib/sequel/adapters/oracle.rb +14 -6
- data/lib/sequel/adapters/postgres.rb +12 -8
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/firebird.rb +10 -0
- data/lib/sequel/adapters/shared/mssql.rb +43 -1
- data/lib/sequel/adapters/shared/mysql.rb +1 -0
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +12 -0
- data/lib/sequel/adapters/shared/sqlite.rb +32 -0
- data/lib/sequel/adapters/sqlite.rb +9 -8
- data/lib/sequel/adapters/swift.rb +3 -8
- data/lib/sequel/adapters/tinytds.rb +5 -5
- data/lib/sequel/connection_pool.rb +13 -19
- data/lib/sequel/connection_pool/sharded_single.rb +12 -12
- data/lib/sequel/connection_pool/sharded_threaded.rb +37 -17
- data/lib/sequel/connection_pool/single.rb +6 -3
- data/lib/sequel/connection_pool/threaded.rb +33 -13
- data/lib/sequel/database/connecting.rb +28 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +2 -5
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +3 -0
- data/lib/sequel/dataset/query.rb +8 -4
- data/lib/sequel/dataset/sql.rb +7 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/pg_array.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -0
- data/lib/sequel/extensions/pg_json.rb +4 -0
- data/lib/sequel/extensions/pg_range.rb +1 -0
- data/lib/sequel/extensions/pg_row.rb +4 -0
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +53 -10
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/validation_class_methods.rb +1 -0
- data/lib/sequel/plugins/validation_helpers.rb +3 -1
- data/lib/sequel/sql.rb +61 -19
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +52 -38
- data/spec/adapters/mssql_spec.rb +67 -0
- data/spec/adapters/mysql_spec.rb +192 -116
- data/spec/adapters/postgres_spec.rb +133 -70
- data/spec/adapters/spec_helper.rb +7 -0
- data/spec/adapters/sqlite_spec.rb +34 -1
- data/spec/core/connection_pool_spec.rb +79 -75
- data/spec/core/database_spec.rb +9 -4
- data/spec/core/dataset_spec.rb +15 -0
- data/spec/core/expression_filters_spec.rb +40 -2
- data/spec/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/pg_array_spec.rb +4 -0
- data/spec/extensions/single_table_inheritance_spec.rb +42 -0
- data/spec/extensions/touch_spec.rb +40 -0
- data/spec/extensions/validation_class_methods_spec.rb +19 -1
- data/spec/extensions/validation_helpers_spec.rb +17 -0
- data/spec/integration/database_test.rb +14 -0
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/plugin_test.rb +41 -12
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/spec_helper.rb +7 -0
- data/spec/integration/type_test.rb +3 -0
- metadata +9 -3
@@ -6,14 +6,6 @@ unless defined?(POSTGRES_DB)
|
|
6
6
|
end
|
7
7
|
INTEGRATION_DB = POSTGRES_DB unless defined?(INTEGRATION_DB)
|
8
8
|
|
9
|
-
# Automatic parameterization changes the SQL used, so don't check
|
10
|
-
# for expected SQL if it is being used.
|
11
|
-
if defined?(Sequel::Postgres::AutoParameterize)
|
12
|
-
check_sqls = false
|
13
|
-
else
|
14
|
-
check_sqls = true
|
15
|
-
end
|
16
|
-
|
17
9
|
def POSTGRES_DB.sqls
|
18
10
|
(@sqls ||= [])
|
19
11
|
end
|
@@ -25,6 +17,37 @@ POSTGRES_DB.loggers << logger
|
|
25
17
|
|
26
18
|
#POSTGRES_DB.instance_variable_set(:@server_version, 80200)
|
27
19
|
|
20
|
+
describe "PostgreSQL", '#create_table' do
|
21
|
+
before do
|
22
|
+
@db = POSTGRES_DB
|
23
|
+
POSTGRES_DB.sqls.clear
|
24
|
+
end
|
25
|
+
after do
|
26
|
+
@db.drop_table?(:tmp_dolls)
|
27
|
+
@db.drop_table?(:unlogged_dolls)
|
28
|
+
end
|
29
|
+
|
30
|
+
specify "should create a temporary table" do
|
31
|
+
@db.create_table(:tmp_dolls, :temp => true){text :name}
|
32
|
+
check_sqls do
|
33
|
+
@db.sqls.should == ['CREATE TEMPORARY TABLE "tmp_dolls" ("name" text)']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should create an unlogged table" do
|
38
|
+
@db.create_table(:unlogged_dolls, :unlogged => true){text :name}
|
39
|
+
check_sqls do
|
40
|
+
@db.sqls.should == ['CREATE UNLOGGED TABLE "unlogged_dolls" ("name" text)']
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
specify "should not allow to pass both :temp and :unlogged" do
|
45
|
+
proc do
|
46
|
+
@db.create_table(:temp_unlogged_dolls, :temp => true, :unlogged => true){text :name}
|
47
|
+
end.should raise_error(Sequel::Error, "can't provide both :temp and :unlogged to create_table")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
28
51
|
describe "A PostgreSQL database" do
|
29
52
|
before(:all) do
|
30
53
|
@db = POSTGRES_DB
|
@@ -74,18 +97,18 @@ describe "A PostgreSQL dataset" do
|
|
74
97
|
end
|
75
98
|
|
76
99
|
specify "should quote columns and tables using double quotes if quoting identifiers" do
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
100
|
+
check_sqls do
|
101
|
+
@d.select(:name).sql.should == 'SELECT "name" FROM "test"'
|
102
|
+
@d.select(Sequel.lit('COUNT(*)')).sql.should == 'SELECT COUNT(*) FROM "test"'
|
103
|
+
@d.select(Sequel.function(:max, :value)).sql.should == 'SELECT max("value") FROM "test"'
|
104
|
+
@d.select(Sequel.function(:NOW)).sql.should == 'SELECT NOW() FROM "test"'
|
105
|
+
@d.select(Sequel.function(:max, :items__value)).sql.should == 'SELECT max("items"."value") FROM "test"'
|
106
|
+
@d.order(Sequel.desc(:name)).sql.should == 'SELECT * FROM "test" ORDER BY "name" DESC'
|
107
|
+
@d.select(Sequel.lit('test.name AS item_name')).sql.should == 'SELECT test.name AS item_name FROM "test"'
|
108
|
+
@d.select(Sequel.lit('"name"')).sql.should == 'SELECT "name" FROM "test"'
|
109
|
+
@d.select(Sequel.lit('max(test."name") AS "max_name"')).sql.should == 'SELECT max(test."name") AS "max_name" FROM "test"'
|
110
|
+
@d.insert_sql(:x => :y).should =~ /\AINSERT INTO "test" \("x"\) VALUES \("y"\)( RETURNING NULL)?\z/
|
111
|
+
|
89
112
|
@d.select(Sequel.function(:test, :abc, 'hello')).sql.should == "SELECT test(\"abc\", 'hello') FROM \"test\""
|
90
113
|
@d.select(Sequel.function(:test, :abc__def, 'hello')).sql.should == "SELECT test(\"abc\".\"def\", 'hello') FROM \"test\""
|
91
114
|
@d.select(Sequel.function(:test, :abc__def, 'hello').as(:x2)).sql.should == "SELECT test(\"abc\".\"def\", 'hello') AS \"x2\" FROM \"test\""
|
@@ -94,10 +117,12 @@ describe "A PostgreSQL dataset" do
|
|
94
117
|
end
|
95
118
|
|
96
119
|
specify "should quote fields correctly when reversing the order if quoting identifiers" do
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
120
|
+
check_sqls do
|
121
|
+
@d.reverse_order(:name).sql.should == 'SELECT * FROM "test" ORDER BY "name" DESC'
|
122
|
+
@d.reverse_order(Sequel.desc(:name)).sql.should == 'SELECT * FROM "test" ORDER BY "name" ASC'
|
123
|
+
@d.reverse_order(:name, Sequel.desc(:test)).sql.should == 'SELECT * FROM "test" ORDER BY "name" DESC, "test" ASC'
|
124
|
+
@d.reverse_order(Sequel.desc(:name), :test).sql.should == 'SELECT * FROM "test" ORDER BY "name" ASC, "test" DESC'
|
125
|
+
end
|
101
126
|
end
|
102
127
|
|
103
128
|
specify "should support regexps" do
|
@@ -175,17 +200,23 @@ describe "A PostgreSQL dataset" do
|
|
175
200
|
|
176
201
|
@db.sqls.clear
|
177
202
|
@db.transaction(:synchronous=>nil){}
|
178
|
-
|
203
|
+
check_sqls do
|
204
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
205
|
+
end
|
179
206
|
|
180
207
|
if @db.server_version >= 90100
|
181
208
|
@db.sqls.clear
|
182
209
|
@db.transaction(:synchronous=>:local){}
|
183
|
-
|
210
|
+
check_sqls do
|
211
|
+
@db.sqls.grep(/synchronous/).should == ["SET LOCAL synchronous_commit = local"]
|
212
|
+
end
|
184
213
|
|
185
214
|
if @db.server_version >= 90200
|
186
215
|
@db.sqls.clear
|
187
216
|
@db.transaction(:synchronous=>:remote_write){}
|
188
|
-
|
217
|
+
check_sqls do
|
218
|
+
@db.sqls.grep(/synchronous/).should == ["SET LOCAL synchronous_commit = remote_write"]
|
219
|
+
end
|
189
220
|
end
|
190
221
|
end
|
191
222
|
end
|
@@ -210,28 +241,36 @@ describe "A PostgreSQL dataset" do
|
|
210
241
|
|
211
242
|
specify "should support creating indexes concurrently" do
|
212
243
|
@db.add_index :test, [:name, :value], :concurrently=>true
|
213
|
-
|
244
|
+
check_sqls do
|
245
|
+
@db.sqls.should == ['CREATE INDEX CONCURRENTLY "test_name_value_index" ON "test" ("name", "value")']
|
246
|
+
end
|
214
247
|
end
|
215
248
|
|
216
249
|
specify "should support dropping indexes only if they already exist" do
|
217
250
|
@db.add_index :test, [:name, :value], :name=>'tnv1'
|
218
251
|
@db.sqls.clear
|
219
252
|
@db.drop_index :test, [:name, :value], :if_exists=>true, :name=>'tnv1'
|
220
|
-
|
253
|
+
check_sqls do
|
254
|
+
@db.sqls.should == ['DROP INDEX IF EXISTS "tnv1"']
|
255
|
+
end
|
221
256
|
end
|
222
257
|
|
223
258
|
specify "should support CASCADE when dropping indexes" do
|
224
259
|
@db.add_index :test, [:name, :value], :name=>'tnv2'
|
225
260
|
@db.sqls.clear
|
226
261
|
@db.drop_index :test, [:name, :value], :cascade=>true, :name=>'tnv2'
|
227
|
-
|
262
|
+
check_sqls do
|
263
|
+
@db.sqls.should == ['DROP INDEX "tnv2" CASCADE']
|
264
|
+
end
|
228
265
|
end
|
229
266
|
|
230
267
|
specify "should support dropping indexes concurrently" do
|
231
268
|
@db.add_index :test, [:name, :value], :name=>'tnv2'
|
232
269
|
@db.sqls.clear
|
233
270
|
@db.drop_index :test, [:name, :value], :concurrently=>true, :name=>'tnv2'
|
234
|
-
|
271
|
+
check_sqls do
|
272
|
+
@db.sqls.should == ['DROP INDEX CONCURRENTLY "tnv2"']
|
273
|
+
end
|
235
274
|
end if POSTGRES_DB.server_version >= 90200
|
236
275
|
|
237
276
|
specify "#lock should lock table if inside a transaction" do
|
@@ -511,19 +550,23 @@ describe "A PostgreSQL database" do
|
|
511
550
|
|
512
551
|
specify "should support opclass specification" do
|
513
552
|
@db.create_table(:posts){text :title; text :body; integer :user_id; index(:user_id, :opclass => :int4_ops, :type => :btree)}
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
553
|
+
check_sqls do
|
554
|
+
@db.sqls.should == [
|
555
|
+
'CREATE TABLE "posts" ("title" text, "body" text, "user_id" integer)',
|
556
|
+
'CREATE INDEX "posts_user_id_index" ON "posts" USING btree ("user_id" int4_ops)'
|
557
|
+
]
|
558
|
+
end
|
518
559
|
end
|
519
560
|
|
520
561
|
specify "should support fulltext indexes and searching" do
|
521
562
|
@db.create_table(:posts){text :title; text :body; full_text_index [:title, :body]; full_text_index :title, :language => 'french'}
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
563
|
+
check_sqls do
|
564
|
+
@db.sqls.should == [
|
565
|
+
%{CREATE TABLE "posts" ("title" text, "body" text)},
|
566
|
+
%{CREATE INDEX "posts_title_body_index" ON "posts" USING gin (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))))},
|
567
|
+
%{CREATE INDEX "posts_title_index" ON "posts" USING gin (to_tsvector('french'::regconfig, (COALESCE("title", ''))))}
|
568
|
+
]
|
569
|
+
end
|
527
570
|
|
528
571
|
@db[:posts].insert(:title=>'ruby rails', :body=>'yowsa')
|
529
572
|
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
@@ -533,10 +576,12 @@ describe "A PostgreSQL database" do
|
|
533
576
|
@db[:posts].full_text_search(:title, 'rails').all.should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
534
577
|
@db[:posts].full_text_search([:title, :body], ['yowsa', 'rails']).all.should == [:title=>'ruby rails', :body=>'yowsa']
|
535
578
|
@db[:posts].full_text_search(:title, 'scooby', :language => 'french').all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
579
|
+
check_sqls do
|
580
|
+
@db.sqls.should == [
|
581
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('simple'::regconfig, 'rails'))},
|
582
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))) @@ to_tsquery('simple'::regconfig, 'yowsa | rails'))},
|
583
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('french'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('french'::regconfig, 'scooby'))}]
|
584
|
+
end
|
540
585
|
|
541
586
|
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
542
587
|
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
@@ -544,42 +589,52 @@ describe "A PostgreSQL database" do
|
|
544
589
|
|
545
590
|
specify "should support spatial indexes" do
|
546
591
|
@db.create_table(:posts){box :geom; spatial_index [:geom]}
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
592
|
+
check_sqls do
|
593
|
+
@db.sqls.should == [
|
594
|
+
'CREATE TABLE "posts" ("geom" box)',
|
595
|
+
'CREATE INDEX "posts_geom_index" ON "posts" USING gist ("geom")'
|
596
|
+
]
|
597
|
+
end
|
551
598
|
end
|
552
599
|
|
553
600
|
specify "should support indexes with index type" do
|
554
601
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'hash'}
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
602
|
+
check_sqls do
|
603
|
+
@db.sqls.should == [
|
604
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
605
|
+
'CREATE INDEX "posts_title_index" ON "posts" USING hash ("title")'
|
606
|
+
]
|
607
|
+
end
|
559
608
|
end
|
560
609
|
|
561
610
|
specify "should support unique indexes with index type" do
|
562
611
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'btree', :unique => true}
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
612
|
+
check_sqls do
|
613
|
+
@db.sqls.should == [
|
614
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
615
|
+
'CREATE UNIQUE INDEX "posts_title_index" ON "posts" USING btree ("title")'
|
616
|
+
]
|
617
|
+
end
|
567
618
|
end
|
568
619
|
|
569
620
|
specify "should support partial indexes" do
|
570
621
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
622
|
+
check_sqls do
|
623
|
+
@db.sqls.should == [
|
624
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
625
|
+
'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
|
626
|
+
]
|
627
|
+
end
|
575
628
|
end
|
576
629
|
|
577
630
|
specify "should support identifiers for table names in indicies" do
|
578
631
|
@db.create_table(Sequel::SQL::Identifier.new(:posts)){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
632
|
+
check_sqls do
|
633
|
+
@db.sqls.should == [
|
634
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
635
|
+
'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
|
636
|
+
]
|
637
|
+
end
|
583
638
|
end
|
584
639
|
|
585
640
|
specify "should support renaming tables" do
|
@@ -602,7 +657,9 @@ describe "Postgres::Dataset#import" do
|
|
602
657
|
|
603
658
|
specify "#import should a single insert statement" do
|
604
659
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
605
|
-
|
660
|
+
check_sqls do
|
661
|
+
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2), (3, 4)', 'COMMIT']
|
662
|
+
end
|
606
663
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
607
664
|
end
|
608
665
|
|
@@ -646,7 +703,9 @@ describe "Postgres::Dataset#insert" do
|
|
646
703
|
|
647
704
|
specify "should use INSERT RETURNING" do
|
648
705
|
@ds.insert(:value=>10).should == 1
|
649
|
-
|
706
|
+
check_sqls do
|
707
|
+
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"'
|
708
|
+
end
|
650
709
|
end
|
651
710
|
|
652
711
|
specify "should have insert_select insert the record and return the inserted record" do
|
@@ -1124,10 +1183,14 @@ if POSTGRES_DB.adapter_scheme == :postgres
|
|
1124
1183
|
specify "should respect the :rows_per_fetch option" do
|
1125
1184
|
@db.sqls.clear
|
1126
1185
|
@ds.use_cursor.all
|
1127
|
-
|
1128
|
-
|
1186
|
+
check_sqls do
|
1187
|
+
@db.sqls.length.should == 6
|
1188
|
+
@db.sqls.clear
|
1189
|
+
end
|
1129
1190
|
@ds.use_cursor(:rows_per_fetch=>100).all
|
1130
|
-
|
1191
|
+
check_sqls do
|
1192
|
+
@db.sqls.length.should == 15
|
1193
|
+
end
|
1131
1194
|
end
|
1132
1195
|
|
1133
1196
|
specify "should handle returning inside block" do
|
@@ -1396,7 +1459,7 @@ describe 'PostgreSQL special float handling' do
|
|
1396
1459
|
@db.drop_table?(:test5)
|
1397
1460
|
end
|
1398
1461
|
|
1399
|
-
|
1462
|
+
check_sqls do
|
1400
1463
|
specify 'should quote NaN' do
|
1401
1464
|
nan = 0.0/0.0
|
1402
1465
|
@ds.insert_sql(:value => nan).should == %q{INSERT INTO "test5" ("value") VALUES ('NaN')}
|
@@ -595,4 +595,37 @@ describe "A SQLite database" do
|
|
595
595
|
@db.drop_column :a, :b
|
596
596
|
@db.indexes(:a).should == {:a_a_index=>{:unique=>false, :columns=>[:a]}}
|
597
597
|
end
|
598
|
-
|
598
|
+
|
599
|
+
specify "should have support for various #transaction modes" do
|
600
|
+
sqls = []
|
601
|
+
@db.loggers << (l=Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new)
|
602
|
+
|
603
|
+
@db.transaction(:mode => :immediate) do
|
604
|
+
sqls.last.should == "BEGIN IMMEDIATE TRANSACTION"
|
605
|
+
end
|
606
|
+
@db.transaction(:mode => :exclusive) do
|
607
|
+
sqls.last.should == "BEGIN EXCLUSIVE TRANSACTION"
|
608
|
+
end
|
609
|
+
@db.transaction(:mode => :deferred) do
|
610
|
+
sqls.last.should == "BEGIN DEFERRED TRANSACTION"
|
611
|
+
end
|
612
|
+
@db.transaction do
|
613
|
+
sqls.last.should == Sequel::Database::SQL_BEGIN
|
614
|
+
end
|
615
|
+
|
616
|
+
@db.transaction_mode.should == nil
|
617
|
+
@db.transaction_mode = :immediate
|
618
|
+
@db.transaction_mode.should == :immediate
|
619
|
+
@db.transaction do
|
620
|
+
sqls.last.should == "BEGIN IMMEDIATE TRANSACTION"
|
621
|
+
end
|
622
|
+
@db.transaction(:mode => :exclusive) do
|
623
|
+
sqls.last.should == "BEGIN EXCLUSIVE TRANSACTION"
|
624
|
+
end
|
625
|
+
|
626
|
+
proc {@db.transaction_mode = :invalid}.should raise_error(Sequel::Error)
|
627
|
+
|
628
|
+
@db.transaction_mode.should == :immediate
|
629
|
+
proc {@db.transaction(:mode => :invalid) {}}.should raise_error(Sequel::Error)
|
630
|
+
end
|
631
|
+
end
|
@@ -1,9 +1,18 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
2
2
|
CONNECTION_POOL_DEFAULTS = {:pool_timeout=>5, :pool_sleep_time=>0.001, :max_connections=>4}
|
3
3
|
|
4
|
+
mock_db = lambda do |*a, &b|
|
5
|
+
db = Sequel.mock
|
6
|
+
db.meta_def(:connect){|c| b.arity == 1 ? b.call(c) : b.call} if b
|
7
|
+
if b2 = a.shift
|
8
|
+
db.meta_def(:disconnect_connection){|c| b2.arity == 1 ? b2.call(c) : b2.call}
|
9
|
+
end
|
10
|
+
db
|
11
|
+
end
|
12
|
+
|
4
13
|
describe "An empty ConnectionPool" do
|
5
14
|
before do
|
6
|
-
@cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS)
|
15
|
+
@cpool = Sequel::ConnectionPool.get_pool(mock_db.call, CONNECTION_POOL_DEFAULTS)
|
7
16
|
end
|
8
17
|
|
9
18
|
specify "should have no available connections" do
|
@@ -21,24 +30,25 @@ end
|
|
21
30
|
|
22
31
|
describe "ConnectionPool options" do
|
23
32
|
specify "should support string option values" do
|
24
|
-
cpool = Sequel::ConnectionPool.get_pool({:max_connections=>'5', :pool_timeout=>'3', :pool_sleep_time=>'0.01'})
|
33
|
+
cpool = Sequel::ConnectionPool.get_pool(mock_db.call, {:max_connections=>'5', :pool_timeout=>'3', :pool_sleep_time=>'0.01'})
|
25
34
|
cpool.max_size.should == 5
|
26
35
|
cpool.instance_variable_get(:@timeout).should == 3
|
27
36
|
cpool.instance_variable_get(:@sleep_time).should == 0.01
|
28
37
|
end
|
29
38
|
|
30
39
|
specify "should raise an error unless size is positive" do
|
31
|
-
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>0)}.should raise_error(Sequel::Error)
|
32
|
-
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>-10)}.should raise_error(Sequel::Error)
|
33
|
-
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>'-10')}.should raise_error(Sequel::Error)
|
34
|
-
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>'0')}.should raise_error(Sequel::Error)
|
40
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>0)}.should raise_error(Sequel::Error)
|
41
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>-10)}.should raise_error(Sequel::Error)
|
42
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'-10')}.should raise_error(Sequel::Error)
|
43
|
+
lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'0')}.should raise_error(Sequel::Error)
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
38
47
|
describe "A connection pool handling connections" do
|
39
48
|
before do
|
40
49
|
@max_size = 2
|
41
|
-
|
50
|
+
msp = proc{@max_size=3}
|
51
|
+
@cpool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){:got_connection}, CONNECTION_POOL_DEFAULTS.merge(:max_connections=>@max_size))
|
42
52
|
end
|
43
53
|
|
44
54
|
specify "#hold should increment #created_count" do
|
@@ -127,11 +137,11 @@ end
|
|
127
137
|
describe "ConnectionPool#hold" do
|
128
138
|
before do
|
129
139
|
value = 0
|
130
|
-
@c = Class.new do
|
140
|
+
c = @c = Class.new do
|
131
141
|
define_method(:initialize){value += 1}
|
132
142
|
define_method(:value){value}
|
133
143
|
end
|
134
|
-
@pool = Sequel::ConnectionPool.get_pool(
|
144
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{c.new}, CONNECTION_POOL_DEFAULTS)
|
135
145
|
end
|
136
146
|
|
137
147
|
specify "should pass the result of the connection maker proc to the supplied block" do
|
@@ -158,7 +168,8 @@ end
|
|
158
168
|
describe "A connection pool with a max size of 1" do
|
159
169
|
before do
|
160
170
|
@invoked_count = 0
|
161
|
-
|
171
|
+
icp = proc{@invoked_count += 1}
|
172
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{icp.call; 'herro'}, CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1))
|
162
173
|
end
|
163
174
|
|
164
175
|
specify "should let only one thread access the connection at any time" do
|
@@ -229,7 +240,7 @@ end
|
|
229
240
|
|
230
241
|
shared_examples_for "A threaded connection pool" do
|
231
242
|
specify "should not have all_connections yield connections allocated to other threads" do
|
232
|
-
pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
|
243
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
|
233
244
|
q, q1 = Queue.new, Queue.new
|
234
245
|
t = Thread.new do
|
235
246
|
pool.hold do |c1|
|
@@ -246,7 +257,7 @@ shared_examples_for "A threaded connection pool" do
|
|
246
257
|
end
|
247
258
|
|
248
259
|
specify "should not have all_connections yield all available connections" do
|
249
|
-
pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
|
260
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
|
250
261
|
q, q1 = Queue.new, Queue.new
|
251
262
|
b = []
|
252
263
|
t = Thread.new do
|
@@ -270,7 +281,7 @@ shared_examples_for "A threaded connection pool" do
|
|
270
281
|
specify "should raise a PoolTimeout error if a connection couldn't be acquired before timeout" do
|
271
282
|
x = nil
|
272
283
|
q, q1 = Queue.new, Queue.new
|
273
|
-
pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
|
284
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
|
274
285
|
t = Thread.new{pool.hold{|c| q1.push nil; q.pop}}
|
275
286
|
q1.pop
|
276
287
|
proc{pool.hold{|c|}}.should raise_error(Sequel::PoolTimeout)
|
@@ -279,7 +290,7 @@ shared_examples_for "A threaded connection pool" do
|
|
279
290
|
end
|
280
291
|
|
281
292
|
it "should not add a disconnected connection back to the pool if the disconnection_proc raises an error" do
|
282
|
-
pool = Sequel::ConnectionPool.get_pool(
|
293
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| raise Sequel::Error}, &@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
|
283
294
|
proc{pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::Error)
|
284
295
|
pool.available_connections.length.should == 0
|
285
296
|
end
|
@@ -354,7 +365,7 @@ shared_examples_for "A threaded connection pool" do
|
|
354
365
|
end
|
355
366
|
|
356
367
|
specify "should store connections in a queue if :connection_handling=>:queue" do
|
357
|
-
@pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:connection_handling=>:queue))
|
368
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:queue))
|
358
369
|
c2 = nil
|
359
370
|
c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
|
360
371
|
@pool.size.should == 2
|
@@ -367,9 +378,9 @@ shared_examples_for "A threaded connection pool" do
|
|
367
378
|
end
|
368
379
|
|
369
380
|
specify "should not store connections if :connection_handling=>:disconnect" do
|
370
|
-
@pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:connection_handling=>:disconnect))
|
381
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:disconnect))
|
371
382
|
d = []
|
372
|
-
@pool.
|
383
|
+
@pool.db.meta_def(:disconnect_connection){|c| d << c}
|
373
384
|
c = @pool.hold do |cc|
|
374
385
|
cc.should == 1
|
375
386
|
Thread.new{@pool.hold{|cc2| cc2.should == 2}}.join
|
@@ -392,8 +403,9 @@ end
|
|
392
403
|
describe "Threaded Unsharded Connection Pool" do
|
393
404
|
before do
|
394
405
|
@invoked_count = 0
|
406
|
+
@icpp = proc{@invoked_count += 1}
|
395
407
|
@cp_opts = CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)
|
396
|
-
@pool = Sequel::ConnectionPool.get_pool(@cp_opts)
|
408
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts)
|
397
409
|
end
|
398
410
|
|
399
411
|
it_should_behave_like "A threaded connection pool"
|
@@ -402,8 +414,9 @@ end
|
|
402
414
|
describe "Threaded Sharded Connection Pool" do
|
403
415
|
before do
|
404
416
|
@invoked_count = 0
|
417
|
+
@icpp = proc{@invoked_count += 1}
|
405
418
|
@cp_opts = CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{})
|
406
|
-
@pool = Sequel::ConnectionPool.get_pool(@cp_opts)
|
419
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts)
|
407
420
|
end
|
408
421
|
|
409
422
|
it_should_behave_like "A threaded connection pool"
|
@@ -412,7 +425,8 @@ end
|
|
412
425
|
describe "ConnectionPool#disconnect" do
|
413
426
|
before do
|
414
427
|
@count = 0
|
415
|
-
|
428
|
+
cp = proc{@count += 1}
|
429
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{{:id => cp.call}}, CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{}))
|
416
430
|
threads = []
|
417
431
|
q, q1 = Queue.new, Queue.new
|
418
432
|
5.times {|i| threads << Thread.new {@pool.hold {|c| q1.push nil; q.pop}}}
|
@@ -426,7 +440,8 @@ describe "ConnectionPool#disconnect" do
|
|
426
440
|
@pool.available_connections.size.should == 5
|
427
441
|
@pool.available_connections.each {|c| c[:id].should_not be_nil}
|
428
442
|
conns = []
|
429
|
-
@pool.
|
443
|
+
@pool.db.meta_def(:disconnect_connection){|c| conns << c}
|
444
|
+
@pool.disconnect
|
430
445
|
conns.size.should == 5
|
431
446
|
end
|
432
447
|
|
@@ -442,7 +457,8 @@ describe "ConnectionPool#disconnect" do
|
|
442
457
|
@pool.available_connections.size.should == 4
|
443
458
|
@pool.available_connections.each {|c| c.should_not be(conn)}
|
444
459
|
conns = []
|
445
|
-
@pool.
|
460
|
+
@pool.db.meta_def(:disconnect_connection){|c| conns << c}
|
461
|
+
@pool.disconnect
|
446
462
|
conns.size.should == 4
|
447
463
|
@pool.size.should == 1
|
448
464
|
end
|
@@ -452,8 +468,8 @@ end
|
|
452
468
|
|
453
469
|
describe "A connection pool with multiple servers" do
|
454
470
|
before do
|
455
|
-
@invoked_counts = Hash.new(0)
|
456
|
-
@pool = Sequel::ConnectionPool.get_pool(
|
471
|
+
ic = @invoked_counts = Hash.new(0)
|
472
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}}))
|
457
473
|
end
|
458
474
|
|
459
475
|
specify "#all_connections should return connections for all servers" do
|
@@ -494,7 +510,8 @@ describe "A connection pool with multiple servers" do
|
|
494
510
|
end
|
495
511
|
|
496
512
|
specify "should support a :servers_hash option used for converting the server argument" do
|
497
|
-
|
513
|
+
ic = @invoked_counts
|
514
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers_hash=>Hash.new(:read_only), :servers=>{:read_only=>{}}))
|
498
515
|
@pool.hold(:blah) do |c1|
|
499
516
|
c1.should == "read_only1"
|
500
517
|
@pool.hold(:blah) do |c2|
|
@@ -505,7 +522,7 @@ describe "A connection pool with multiple servers" do
|
|
505
522
|
end
|
506
523
|
end
|
507
524
|
|
508
|
-
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:servers_hash=>Hash.new{|h,k| raise Sequel::Error}, :servers=>{:read_only=>{}}))
|
525
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers_hash=>Hash.new{|h,k| raise Sequel::Error}, :servers=>{:read_only=>{}}))
|
509
526
|
proc{@pool.hold(:blah){|c1|}}.should raise_error(Sequel::Error)
|
510
527
|
end
|
511
528
|
|
@@ -542,7 +559,8 @@ describe "A connection pool with multiple servers" do
|
|
542
559
|
conns = []
|
543
560
|
@pool.size.should == 1
|
544
561
|
@pool.size(:read_only).should == 1
|
545
|
-
@pool.
|
562
|
+
@pool.db.meta_def(:disconnect_connection){|c| conns << c}
|
563
|
+
@pool.disconnect
|
546
564
|
conns.sort.should == %w'default1 read_only1'
|
547
565
|
@pool.size.should == 0
|
548
566
|
@pool.size(:read_only).should == 0
|
@@ -551,7 +569,7 @@ describe "A connection pool with multiple servers" do
|
|
551
569
|
end
|
552
570
|
|
553
571
|
specify "#add_servers should add new servers to the pool" do
|
554
|
-
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}})
|
572
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
555
573
|
|
556
574
|
pool.hold{}
|
557
575
|
pool.hold(:server2){}
|
@@ -582,7 +600,7 @@ describe "A connection pool with multiple servers" do
|
|
582
600
|
end
|
583
601
|
|
584
602
|
specify "#add_servers should ignore existing keys" do
|
585
|
-
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}})
|
603
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
586
604
|
|
587
605
|
pool.allocated.length.should == 0
|
588
606
|
pool.allocated(:server1).length.should == 0
|
@@ -628,7 +646,7 @@ describe "A connection pool with multiple servers" do
|
|
628
646
|
end
|
629
647
|
|
630
648
|
specify "#remove_servers should disconnect available connections immediately" do
|
631
|
-
pool = Sequel::ConnectionPool.get_pool(:max_connections=>5, :servers=>{:server1=>{}})
|
649
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :max_connections=>5, :servers=>{:server1=>{}})
|
632
650
|
threads = []
|
633
651
|
q, q1 = Queue.new, Queue.new
|
634
652
|
5.times {|i| threads << Thread.new {pool.hold(:server1){|c| q1.push nil; q.pop}}}
|
@@ -643,7 +661,7 @@ describe "A connection pool with multiple servers" do
|
|
643
661
|
|
644
662
|
specify "#remove_servers should disconnect connections in use as soon as they are returned to the pool" do
|
645
663
|
dc = []
|
646
|
-
pool = Sequel::ConnectionPool.get_pool(
|
664
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| dc << c}){|c| c}, :servers=>{:server1=>{}})
|
647
665
|
c1 = nil
|
648
666
|
pool.hold(:server1) do |c|
|
649
667
|
pool.size(:server1).should == 1
|
@@ -658,7 +676,7 @@ describe "A connection pool with multiple servers" do
|
|
658
676
|
end
|
659
677
|
|
660
678
|
specify "#remove_servers should remove server related data structures immediately" do
|
661
|
-
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}})
|
679
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
662
680
|
pool.available_connections(:server1).should == []
|
663
681
|
pool.allocated(:server1).should == {}
|
664
682
|
pool.remove_servers([:server1])
|
@@ -667,14 +685,14 @@ describe "A connection pool with multiple servers" do
|
|
667
685
|
end
|
668
686
|
|
669
687
|
specify "#remove_servers should not allow the removal of the default server" do
|
670
|
-
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}})
|
688
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
|
671
689
|
proc{pool.remove_servers([:server1])}.should_not raise_error
|
672
690
|
proc{pool.remove_servers([:default])}.should raise_error(Sequel::Error)
|
673
691
|
end
|
674
692
|
|
675
693
|
specify "#remove_servers should ignore servers that have already been removed" do
|
676
694
|
dc = []
|
677
|
-
pool = Sequel::ConnectionPool.get_pool(
|
695
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| dc << c}){|c| c}, :servers=>{:server1=>{}})
|
678
696
|
c1 = nil
|
679
697
|
pool.hold(:server1) do |c|
|
680
698
|
pool.size(:server1).should == 1
|
@@ -694,7 +712,7 @@ ST_CONNECTION_POOL_DEFAULTS = CONNECTION_POOL_DEFAULTS.merge(:single_threaded=>t
|
|
694
712
|
|
695
713
|
describe "SingleConnectionPool" do
|
696
714
|
before do
|
697
|
-
@pool = Sequel::ConnectionPool.get_pool(
|
715
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{1234}, ST_CONNECTION_POOL_DEFAULTS)
|
698
716
|
end
|
699
717
|
|
700
718
|
specify "should provide a #hold method" do
|
@@ -706,7 +724,7 @@ describe "SingleConnectionPool" do
|
|
706
724
|
specify "should provide a #disconnect method" do
|
707
725
|
conn = nil
|
708
726
|
x = nil
|
709
|
-
pool = Sequel::ConnectionPool.get_pool(
|
727
|
+
pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| conn = c}){1234}, ST_CONNECTION_POOL_DEFAULTS)
|
710
728
|
pool.hold{|c| x = c}
|
711
729
|
x.should == 1234
|
712
730
|
pool.disconnect
|
@@ -717,7 +735,8 @@ end
|
|
717
735
|
describe "A single threaded pool with multiple servers" do
|
718
736
|
before do
|
719
737
|
@max_size=2
|
720
|
-
|
738
|
+
msp = proc{@max_size += 1}
|
739
|
+
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){|c| c}, ST_CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}}))
|
721
740
|
end
|
722
741
|
|
723
742
|
specify "#all_connections should return connections for all servers" do
|
@@ -811,11 +830,10 @@ describe "A single threaded pool with multiple servers" do
|
|
811
830
|
specify "#disconnect should disconnect from all servers" do
|
812
831
|
@pool.hold(:read_only){}
|
813
832
|
@pool.hold{}
|
814
|
-
conns = []
|
815
833
|
@pool.conn.should == :default
|
816
834
|
@pool.conn(:read_only).should == :read_only
|
817
|
-
@pool.disconnect
|
818
|
-
|
835
|
+
@pool.disconnect
|
836
|
+
@max_size.should == 4
|
819
837
|
@pool.conn.should == nil
|
820
838
|
@pool.conn(:read_only).should == nil
|
821
839
|
end
|
@@ -836,14 +854,18 @@ describe "A single threaded pool with multiple servers" do
|
|
836
854
|
end
|
837
855
|
|
838
856
|
shared_examples_for "All connection pools classes" do
|
857
|
+
specify "should have pool_type return a symbol" do
|
858
|
+
@class.new(mock_db.call{123}, {}).pool_type.should be_a_kind_of(Symbol)
|
859
|
+
end
|
860
|
+
|
839
861
|
specify "should have all_connections yield current and available connections" do
|
840
|
-
p = @class.new({}
|
862
|
+
p = @class.new(mock_db.call{123}, {})
|
841
863
|
p.hold{|c| p.all_connections{|c1| c.should == c1}}
|
842
864
|
end
|
843
865
|
|
844
866
|
specify "should be able to modify after_connect proc after the pool is created" do
|
845
867
|
a = []
|
846
|
-
p = @class.new({}
|
868
|
+
p = @class.new(mock_db.call{123}, {})
|
847
869
|
p.after_connect = pr = proc{|c| a << c}
|
848
870
|
p.after_connect.should == pr
|
849
871
|
a.should == []
|
@@ -851,77 +873,56 @@ shared_examples_for "All connection pools classes" do
|
|
851
873
|
a.should == [123]
|
852
874
|
end
|
853
875
|
|
854
|
-
specify "should be able to modify disconnection_proc after the pool is created" do
|
855
|
-
a = []
|
856
|
-
p = @class.new({}){123}
|
857
|
-
p.disconnection_proc = pr = proc{|c| a << c}
|
858
|
-
p.disconnection_proc.should == pr
|
859
|
-
p.hold{}
|
860
|
-
a.should == []
|
861
|
-
p.disconnect
|
862
|
-
a.should == [123]
|
863
|
-
end
|
864
|
-
|
865
876
|
specify "should not raise an error when disconnecting twice" do
|
866
|
-
c = @class.new({}
|
877
|
+
c = @class.new(mock_db.call{123}, {})
|
867
878
|
proc{c.disconnect}.should_not raise_error
|
868
879
|
proc{c.disconnect}.should_not raise_error
|
869
880
|
end
|
870
881
|
|
871
882
|
specify "should yield a connection created by the initialize block to hold" do
|
872
883
|
x = nil
|
873
|
-
@class.new({}
|
884
|
+
@class.new(mock_db.call{123}, {}).hold{|c| x = c}
|
874
885
|
x.should == 123
|
875
886
|
end
|
876
887
|
|
877
888
|
specify "should have the initialize block accept a shard/server argument" do
|
878
889
|
x = nil
|
879
|
-
@class.new({
|
890
|
+
@class.new(mock_db.call{|c| [c, c]}, {}).hold{|c| x = c}
|
880
891
|
x.should == [:default, :default]
|
881
892
|
end
|
882
893
|
|
883
894
|
specify "should have respect an :after_connect proc that is called with each newly created connection" do
|
884
895
|
x = nil
|
885
|
-
@class.new(:after_connect=>proc{|c| x = [c, c]})
|
896
|
+
@class.new(mock_db.call{123}, :after_connect=>proc{|c| x = [c, c]}).hold{}
|
886
897
|
x.should == [123, 123]
|
887
898
|
end
|
888
899
|
|
889
900
|
specify "should raise a DatabaseConnectionError if the connection raises an exception" do
|
890
|
-
proc{@class.new({
|
901
|
+
proc{@class.new(mock_db.call{|c| raise Exception}, {}).hold{}}.should raise_error(Sequel::DatabaseConnectionError)
|
891
902
|
end
|
892
903
|
|
893
904
|
specify "should raise a DatabaseConnectionError if the initialize block returns nil" do
|
894
|
-
proc{@class.new({}
|
905
|
+
proc{@class.new(mock_db.call{}, {}).hold{}}.should raise_error(Sequel::DatabaseConnectionError)
|
895
906
|
end
|
896
907
|
|
897
908
|
specify "should call the disconnection_proc option if the hold block raises a DatabaseDisconnectError" do
|
898
909
|
x = nil
|
899
|
-
proc{@class.new(
|
910
|
+
proc{c = @class.new(mock_db.call(proc{|c| x = c}){123}).hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
900
911
|
x.should == 123
|
901
912
|
end
|
902
913
|
|
903
|
-
specify "should have a disconnect method that
|
914
|
+
specify "should have a disconnect method that disconnects the connection" do
|
904
915
|
x = nil
|
905
|
-
c = @class.new(
|
916
|
+
c = @class.new(mock_db.call(proc{|c| x = c}){123})
|
906
917
|
c.hold{}
|
907
918
|
x.should == nil
|
908
919
|
c.disconnect
|
909
920
|
x.should == 123
|
910
921
|
end
|
911
922
|
|
912
|
-
specify "should have a disconnect method that calls the given block with the connection" do
|
913
|
-
x = nil
|
914
|
-
y = nil
|
915
|
-
c = @class.new(:disconnection_proc=>proc{|c| x = c}){123}
|
916
|
-
c.hold{}
|
917
|
-
c.disconnect{|c| y = c}
|
918
|
-
x.should == nil
|
919
|
-
y.should == 123
|
920
|
-
end
|
921
|
-
|
922
923
|
specify "should have a reentrent hold method" do
|
923
924
|
o = Object.new
|
924
|
-
c = @class.new({}
|
925
|
+
c = @class.new(mock_db.call{o}, {})
|
925
926
|
c.hold do |x|
|
926
927
|
x.should == o
|
927
928
|
c.hold do |x1|
|
@@ -934,11 +935,11 @@ shared_examples_for "All connection pools classes" do
|
|
934
935
|
end
|
935
936
|
|
936
937
|
specify "should have a servers method that returns an array of shard/server symbols" do
|
937
|
-
@class.new({}
|
938
|
+
@class.new(mock_db.call{123}, {}).servers.should == [:default]
|
938
939
|
end
|
939
940
|
|
940
941
|
specify "should have a servers method that returns an array of shard/server symbols" do
|
941
|
-
c = @class.new({}
|
942
|
+
c = @class.new(mock_db.call{123}, {})
|
942
943
|
c.size.should == 0
|
943
944
|
c.hold{}
|
944
945
|
c.size.should == 1
|
@@ -948,6 +949,9 @@ end
|
|
948
949
|
Sequel::ConnectionPool::CONNECTION_POOL_MAP.keys.each do |k, v|
|
949
950
|
opts = {:single_threaded=>k, :servers=>(v ? {} : nil)}
|
950
951
|
describe "Connection pool with #{opts.inspect}" do
|
952
|
+
before(:all) do
|
953
|
+
Sequel::ConnectionPool.send(:get_pool, mock_db.call, opts)
|
954
|
+
end
|
951
955
|
before do
|
952
956
|
@class = Sequel::ConnectionPool.send(:connection_pool_class, opts)
|
953
957
|
end
|