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.
Files changed (89) hide show
  1. data/CHANGELOG +40 -0
  2. data/README.rdoc +2 -2
  3. data/doc/advanced_associations.rdoc +12 -0
  4. data/doc/bin_sequel.rdoc +144 -0
  5. data/doc/migration.rdoc +1 -1
  6. data/doc/object_model.rdoc +29 -0
  7. data/doc/release_notes/3.41.0.txt +155 -0
  8. data/lib/sequel/adapters/ado.rb +4 -4
  9. data/lib/sequel/adapters/amalgalite.rb +0 -5
  10. data/lib/sequel/adapters/cubrid.rb +2 -2
  11. data/lib/sequel/adapters/db2.rb +9 -5
  12. data/lib/sequel/adapters/dbi.rb +4 -6
  13. data/lib/sequel/adapters/do.rb +4 -5
  14. data/lib/sequel/adapters/firebird.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +2 -3
  16. data/lib/sequel/adapters/informix.rb +0 -6
  17. data/lib/sequel/adapters/jdbc.rb +11 -7
  18. data/lib/sequel/adapters/jdbc/db2.rb +22 -0
  19. data/lib/sequel/adapters/jdbc/derby.rb +5 -5
  20. data/lib/sequel/adapters/jdbc/h2.rb +0 -5
  21. data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
  22. data/lib/sequel/adapters/jdbc/sqlserver.rb +6 -0
  23. data/lib/sequel/adapters/mock.rb +3 -3
  24. data/lib/sequel/adapters/mysql.rb +7 -7
  25. data/lib/sequel/adapters/mysql2.rb +0 -5
  26. data/lib/sequel/adapters/odbc.rb +4 -4
  27. data/lib/sequel/adapters/openbase.rb +4 -6
  28. data/lib/sequel/adapters/oracle.rb +14 -6
  29. data/lib/sequel/adapters/postgres.rb +12 -8
  30. data/lib/sequel/adapters/shared/db2.rb +5 -0
  31. data/lib/sequel/adapters/shared/firebird.rb +10 -0
  32. data/lib/sequel/adapters/shared/mssql.rb +43 -1
  33. data/lib/sequel/adapters/shared/mysql.rb +1 -0
  34. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +1 -1
  35. data/lib/sequel/adapters/shared/postgres.rb +12 -0
  36. data/lib/sequel/adapters/shared/sqlite.rb +32 -0
  37. data/lib/sequel/adapters/sqlite.rb +9 -8
  38. data/lib/sequel/adapters/swift.rb +3 -8
  39. data/lib/sequel/adapters/tinytds.rb +5 -5
  40. data/lib/sequel/connection_pool.rb +13 -19
  41. data/lib/sequel/connection_pool/sharded_single.rb +12 -12
  42. data/lib/sequel/connection_pool/sharded_threaded.rb +37 -17
  43. data/lib/sequel/connection_pool/single.rb +6 -3
  44. data/lib/sequel/connection_pool/threaded.rb +33 -13
  45. data/lib/sequel/database/connecting.rb +28 -1
  46. data/lib/sequel/database/logging.rb +1 -1
  47. data/lib/sequel/database/misc.rb +2 -5
  48. data/lib/sequel/database/query.rb +2 -2
  49. data/lib/sequel/database/schema_generator.rb +1 -1
  50. data/lib/sequel/database/schema_methods.rb +3 -0
  51. data/lib/sequel/dataset/query.rb +8 -4
  52. data/lib/sequel/dataset/sql.rb +7 -0
  53. data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
  54. data/lib/sequel/extensions/connection_validator.rb +109 -0
  55. data/lib/sequel/extensions/pg_array.rb +2 -0
  56. data/lib/sequel/extensions/pg_hstore.rb +2 -0
  57. data/lib/sequel/extensions/pg_json.rb +4 -0
  58. data/lib/sequel/extensions/pg_range.rb +1 -0
  59. data/lib/sequel/extensions/pg_row.rb +4 -0
  60. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  61. data/lib/sequel/plugins/single_table_inheritance.rb +53 -10
  62. data/lib/sequel/plugins/touch.rb +18 -6
  63. data/lib/sequel/plugins/validation_class_methods.rb +1 -0
  64. data/lib/sequel/plugins/validation_helpers.rb +3 -1
  65. data/lib/sequel/sql.rb +61 -19
  66. data/lib/sequel/version.rb +1 -1
  67. data/spec/adapters/firebird_spec.rb +52 -38
  68. data/spec/adapters/mssql_spec.rb +67 -0
  69. data/spec/adapters/mysql_spec.rb +192 -116
  70. data/spec/adapters/postgres_spec.rb +133 -70
  71. data/spec/adapters/spec_helper.rb +7 -0
  72. data/spec/adapters/sqlite_spec.rb +34 -1
  73. data/spec/core/connection_pool_spec.rb +79 -75
  74. data/spec/core/database_spec.rb +9 -4
  75. data/spec/core/dataset_spec.rb +15 -0
  76. data/spec/core/expression_filters_spec.rb +40 -2
  77. data/spec/extensions/connection_validator_spec.rb +118 -0
  78. data/spec/extensions/pg_array_spec.rb +4 -0
  79. data/spec/extensions/single_table_inheritance_spec.rb +42 -0
  80. data/spec/extensions/touch_spec.rb +40 -0
  81. data/spec/extensions/validation_class_methods_spec.rb +19 -1
  82. data/spec/extensions/validation_helpers_spec.rb +17 -0
  83. data/spec/integration/database_test.rb +14 -0
  84. data/spec/integration/dataset_test.rb +3 -3
  85. data/spec/integration/plugin_test.rb +41 -12
  86. data/spec/integration/schema_test.rb +14 -0
  87. data/spec/integration/spec_helper.rb +7 -0
  88. data/spec/integration/type_test.rb +3 -0
  89. 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
- @d.select(:name).sql.should == 'SELECT "name" FROM "test"'
78
- @d.select(Sequel.lit('COUNT(*)')).sql.should == 'SELECT COUNT(*) FROM "test"'
79
- @d.select(Sequel.function(:max, :value)).sql.should == 'SELECT max("value") FROM "test"'
80
- @d.select(Sequel.function(:NOW)).sql.should == 'SELECT NOW() FROM "test"'
81
- @d.select(Sequel.function(:max, :items__value)).sql.should == 'SELECT max("items"."value") FROM "test"'
82
- @d.order(Sequel.desc(:name)).sql.should == 'SELECT * FROM "test" ORDER BY "name" DESC'
83
- @d.select(Sequel.lit('test.name AS item_name')).sql.should == 'SELECT test.name AS item_name FROM "test"'
84
- @d.select(Sequel.lit('"name"')).sql.should == 'SELECT "name" FROM "test"'
85
- @d.select(Sequel.lit('max(test."name") AS "max_name"')).sql.should == 'SELECT max(test."name") AS "max_name" FROM "test"'
86
- @d.insert_sql(:x => :y).should =~ /\AINSERT INTO "test" \("x"\) VALUES \("y"\)( RETURNING NULL)?\z/
87
-
88
- if check_sqls
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
- @d.reverse_order(:name).sql.should == 'SELECT * FROM "test" ORDER BY "name" DESC'
98
- @d.reverse_order(Sequel.desc(:name)).sql.should == 'SELECT * FROM "test" ORDER BY "name" ASC'
99
- @d.reverse_order(:name, Sequel.desc(:test)).sql.should == 'SELECT * FROM "test" ORDER BY "name" DESC, "test" ASC'
100
- @d.reverse_order(Sequel.desc(:name), :test).sql.should == 'SELECT * FROM "test" ORDER BY "name" ASC, "test" DESC'
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
- @db.sqls.should == ['BEGIN', 'COMMIT']
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
- @db.sqls.grep(/synchronous/).should == ["SET LOCAL synchronous_commit = local"]
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
- @db.sqls.grep(/synchronous/).should == ["SET LOCAL synchronous_commit = remote_write"]
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
- @db.sqls.should == ['CREATE INDEX CONCURRENTLY "test_name_value_index" ON "test" ("name", "value")'] if check_sqls
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
- @db.sqls.should == ['DROP INDEX IF EXISTS "tnv1"']
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
- @db.sqls.should == ['DROP INDEX "tnv2" CASCADE']
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
- @db.sqls.should == ['DROP INDEX CONCURRENTLY "tnv2"']
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
- @db.sqls.should == [
515
- 'CREATE TABLE "posts" ("title" text, "body" text, "user_id" integer)',
516
- 'CREATE INDEX "posts_user_id_index" ON "posts" USING btree ("user_id" int4_ops)'
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
- @db.sqls.should == [
523
- %{CREATE TABLE "posts" ("title" text, "body" text)},
524
- %{CREATE INDEX "posts_title_body_index" ON "posts" USING gin (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))))},
525
- %{CREATE INDEX "posts_title_index" ON "posts" USING gin (to_tsvector('french'::regconfig, (COALESCE("title", ''))))}
526
- ] if check_sqls
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
- @db.sqls.should == [
537
- %{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('simple'::regconfig, 'rails'))},
538
- %{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))) @@ to_tsquery('simple'::regconfig, 'yowsa | rails'))},
539
- %{SELECT * FROM "posts" WHERE (to_tsvector('french'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('french'::regconfig, 'scooby'))}] if check_sqls
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
- @db.sqls.should == [
548
- 'CREATE TABLE "posts" ("geom" box)',
549
- 'CREATE INDEX "posts_geom_index" ON "posts" USING gist ("geom")'
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
- @db.sqls.should == [
556
- 'CREATE TABLE "posts" ("title" varchar(5))',
557
- 'CREATE INDEX "posts_title_index" ON "posts" USING hash ("title")'
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
- @db.sqls.should == [
564
- 'CREATE TABLE "posts" ("title" varchar(5))',
565
- 'CREATE UNIQUE INDEX "posts_title_index" ON "posts" USING btree ("title")'
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
- @db.sqls.should == [
572
- 'CREATE TABLE "posts" ("title" varchar(5))',
573
- 'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
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
- @db.sqls.should == [
580
- 'CREATE TABLE "posts" ("title" varchar(5))',
581
- 'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
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
- @db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2), (3, 4)', 'COMMIT']
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
- @db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"' if check_sqls
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
- @db.sqls.length.should == 6
1128
- @db.sqls.clear
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
- @db.sqls.length.should == 15
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
- if check_sqls
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')}
@@ -51,4 +51,11 @@ end
51
51
  specify(message, &block)
52
52
  end
53
53
  end
54
+
55
+ def check_sqls
56
+ yield unless ENV['SEQUEL_NO_CHECK_SQLS']
57
+ end
58
+ def self.check_sqls
59
+ yield unless ENV['SEQUEL_NO_CHECK_SQLS']
60
+ end
54
61
  end
@@ -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
- end
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
- @cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| @max_size=3}, :max_connections=>@max_size)) {:got_connection}
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(CONNECTION_POOL_DEFAULTS){@c.new}
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
- @pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1)) {@invoked_count += 1; 'herro'}
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)) {@invoked_count += 1}
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)){@invoked_count += 1}
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)) {@invoked_count += 1}
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(@cp_opts.merge(:max_connections=>1, :pool_timeout=>0, :disconnection_proc=>proc{|c| raise Sequel::Error})) {@invoked_count += 1}
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)){@invoked_count += 1}
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)){@invoked_count += 1}
381
+ @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:disconnect))
371
382
  d = []
372
- @pool.disconnection_proc = proc{|c| d << c}
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) {@invoked_count += 1}
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) {@invoked_count += 1}
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
- @pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{})) {{:id => @count += 1}}
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.disconnect {|c| conns << c}
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.disconnect {|c| conns << c}
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(CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}})){|server| "#{server}#{@invoked_counts[server] += 1}"}
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
- @pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:servers_hash=>Hash.new(:read_only), :servers=>{:read_only=>{}})){|server| "#{server}#{@invoked_counts[server] += 1}"}
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=>{}})){|server| "#{server}#{@invoked_counts[server] += 1}"}
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.disconnect{|c| conns << c}
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=>{}}){|s| s}
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=>{}}){|s| s}
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=>{}}){|s| s}
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(:servers=>{:server1=>{}}, :disconnection_proc=>proc{|c| dc << c}){|s| s}
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=>{}}){|s| s}
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=>{}}){|s| s}
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(:servers=>{:server1=>{}}, :disconnection_proc=>proc{|c| dc << c}){|s| s}
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(ST_CONNECTION_POOL_DEFAULTS){1234}
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(ST_CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| conn = c})){1234}
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
- @pool = Sequel::ConnectionPool.get_pool(ST_CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| @max_size=3}, :servers=>{:read_only=>{}})){|server| server}
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{|c| conns << c}
818
- conns.sort_by{|x| x.to_s}.should == [:default, :read_only]
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({}){123}
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({}){123}
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({}){123}
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({}){123}.hold{|c| x = c}
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({}){|c| [c, c]}.hold{|c| x = c}
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]}){|c| 123}.hold{}
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({}){|c| raise Exception}.hold{}}.should raise_error(Sequel::DatabaseConnectionError)
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({}){}.hold{}}.should raise_error(Sequel::DatabaseConnectionError)
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(:disconnection_proc=>proc{|c| x = c}){123}.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
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 calls the :disconnection_proc option with the connection" do
914
+ specify "should have a disconnect method that disconnects the connection" do
904
915
  x = nil
905
- c = @class.new(:disconnection_proc=>proc{|c| x = c}){123}
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({}){o}
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({}){123}.servers.should == [:default]
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({}){123}
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