sequel 3.46.0 → 3.47.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 (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +96 -0
  3. data/Rakefile +7 -1
  4. data/bin/sequel +6 -4
  5. data/doc/active_record.rdoc +1 -1
  6. data/doc/advanced_associations.rdoc +14 -35
  7. data/doc/association_basics.rdoc +66 -4
  8. data/doc/migration.rdoc +4 -0
  9. data/doc/opening_databases.rdoc +6 -0
  10. data/doc/postgresql.rdoc +302 -0
  11. data/doc/release_notes/3.47.0.txt +270 -0
  12. data/doc/security.rdoc +6 -0
  13. data/lib/sequel/adapters/ibmdb.rb +9 -9
  14. data/lib/sequel/adapters/jdbc.rb +22 -7
  15. data/lib/sequel/adapters/jdbc/postgresql.rb +7 -2
  16. data/lib/sequel/adapters/mock.rb +2 -0
  17. data/lib/sequel/adapters/postgres.rb +44 -13
  18. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  19. data/lib/sequel/adapters/shared/mysql.rb +2 -2
  20. data/lib/sequel/adapters/shared/postgres.rb +94 -55
  21. data/lib/sequel/adapters/shared/sqlite.rb +3 -1
  22. data/lib/sequel/adapters/sqlite.rb +2 -2
  23. data/lib/sequel/adapters/utils/pg_types.rb +1 -14
  24. data/lib/sequel/adapters/utils/split_alter_table.rb +3 -3
  25. data/lib/sequel/connection_pool/threaded.rb +1 -1
  26. data/lib/sequel/core.rb +1 -1
  27. data/lib/sequel/database/connecting.rb +2 -2
  28. data/lib/sequel/database/features.rb +5 -0
  29. data/lib/sequel/database/misc.rb +47 -5
  30. data/lib/sequel/database/query.rb +2 -2
  31. data/lib/sequel/dataset/actions.rb +4 -2
  32. data/lib/sequel/dataset/misc.rb +1 -1
  33. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  34. data/lib/sequel/dataset/query.rb +8 -6
  35. data/lib/sequel/dataset/sql.rb +8 -6
  36. data/lib/sequel/extensions/constraint_validations.rb +5 -2
  37. data/lib/sequel/extensions/migration.rb +10 -8
  38. data/lib/sequel/extensions/pagination.rb +3 -0
  39. data/lib/sequel/extensions/pg_array.rb +85 -25
  40. data/lib/sequel/extensions/pg_hstore.rb +8 -1
  41. data/lib/sequel/extensions/pg_hstore_ops.rb +4 -1
  42. data/lib/sequel/extensions/pg_inet.rb +16 -13
  43. data/lib/sequel/extensions/pg_interval.rb +6 -2
  44. data/lib/sequel/extensions/pg_json.rb +18 -11
  45. data/lib/sequel/extensions/pg_range.rb +17 -2
  46. data/lib/sequel/extensions/pg_range_ops.rb +7 -5
  47. data/lib/sequel/extensions/pg_row.rb +29 -12
  48. data/lib/sequel/extensions/pretty_table.rb +3 -0
  49. data/lib/sequel/extensions/query.rb +3 -0
  50. data/lib/sequel/extensions/schema_caching.rb +2 -0
  51. data/lib/sequel/extensions/schema_dumper.rb +3 -1
  52. data/lib/sequel/extensions/select_remove.rb +3 -0
  53. data/lib/sequel/model.rb +8 -2
  54. data/lib/sequel/model/associations.rb +39 -27
  55. data/lib/sequel/model/base.rb +99 -38
  56. data/lib/sequel/model/plugins.rb +25 -0
  57. data/lib/sequel/plugins/association_autoreloading.rb +27 -22
  58. data/lib/sequel/plugins/association_dependencies.rb +1 -7
  59. data/lib/sequel/plugins/auto_validations.rb +110 -0
  60. data/lib/sequel/plugins/boolean_readers.rb +1 -6
  61. data/lib/sequel/plugins/caching.rb +6 -13
  62. data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
  63. data/lib/sequel/plugins/composition.rb +14 -7
  64. data/lib/sequel/plugins/constraint_validations.rb +2 -13
  65. data/lib/sequel/plugins/defaults_setter.rb +1 -6
  66. data/lib/sequel/plugins/dirty.rb +8 -0
  67. data/lib/sequel/plugins/error_splitter.rb +54 -0
  68. data/lib/sequel/plugins/force_encoding.rb +1 -5
  69. data/lib/sequel/plugins/hook_class_methods.rb +1 -6
  70. data/lib/sequel/plugins/input_transformer.rb +79 -0
  71. data/lib/sequel/plugins/instance_filters.rb +7 -1
  72. data/lib/sequel/plugins/instance_hooks.rb +7 -1
  73. data/lib/sequel/plugins/json_serializer.rb +5 -10
  74. data/lib/sequel/plugins/lazy_attributes.rb +20 -7
  75. data/lib/sequel/plugins/list.rb +1 -6
  76. data/lib/sequel/plugins/many_through_many.rb +1 -2
  77. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +23 -39
  78. data/lib/sequel/plugins/optimistic_locking.rb +1 -5
  79. data/lib/sequel/plugins/pg_row.rb +4 -2
  80. data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -7
  81. data/lib/sequel/plugins/prepared_statements.rb +1 -5
  82. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -11
  83. data/lib/sequel/plugins/rcte_tree.rb +2 -2
  84. data/lib/sequel/plugins/serialization.rb +11 -13
  85. data/lib/sequel/plugins/serialization_modification_detection.rb +13 -1
  86. data/lib/sequel/plugins/single_table_inheritance.rb +4 -4
  87. data/lib/sequel/plugins/static_cache.rb +67 -19
  88. data/lib/sequel/plugins/string_stripper.rb +7 -27
  89. data/lib/sequel/plugins/subclasses.rb +3 -5
  90. data/lib/sequel/plugins/tactical_eager_loading.rb +2 -2
  91. data/lib/sequel/plugins/timestamps.rb +2 -7
  92. data/lib/sequel/plugins/touch.rb +5 -8
  93. data/lib/sequel/plugins/tree.rb +1 -6
  94. data/lib/sequel/plugins/typecast_on_load.rb +1 -5
  95. data/lib/sequel/plugins/update_primary_key.rb +26 -14
  96. data/lib/sequel/plugins/validation_class_methods.rb +31 -16
  97. data/lib/sequel/plugins/validation_helpers.rb +50 -26
  98. data/lib/sequel/plugins/xml_serializer.rb +3 -6
  99. data/lib/sequel/sql.rb +1 -1
  100. data/lib/sequel/version.rb +1 -1
  101. data/spec/adapters/postgres_spec.rb +131 -15
  102. data/spec/adapters/sqlite_spec.rb +1 -1
  103. data/spec/core/connection_pool_spec.rb +16 -17
  104. data/spec/core/database_spec.rb +111 -40
  105. data/spec/core/dataset_spec.rb +65 -74
  106. data/spec/core/expression_filters_spec.rb +6 -5
  107. data/spec/core/object_graph_spec.rb +0 -1
  108. data/spec/core/schema_spec.rb +23 -23
  109. data/spec/core/spec_helper.rb +5 -1
  110. data/spec/extensions/association_dependencies_spec.rb +1 -1
  111. data/spec/extensions/association_proxies_spec.rb +1 -1
  112. data/spec/extensions/auto_validations_spec.rb +90 -0
  113. data/spec/extensions/caching_spec.rb +6 -0
  114. data/spec/extensions/class_table_inheritance_spec.rb +8 -1
  115. data/spec/extensions/composition_spec.rb +12 -5
  116. data/spec/extensions/constraint_validations_spec.rb +4 -4
  117. data/spec/extensions/core_refinements_spec.rb +29 -79
  118. data/spec/extensions/dirty_spec.rb +14 -0
  119. data/spec/extensions/error_splitter_spec.rb +18 -0
  120. data/spec/extensions/identity_map_spec.rb +0 -1
  121. data/spec/extensions/input_transformer_spec.rb +54 -0
  122. data/spec/extensions/instance_filters_spec.rb +6 -0
  123. data/spec/extensions/instance_hooks_spec.rb +12 -1
  124. data/spec/extensions/json_serializer_spec.rb +0 -1
  125. data/spec/extensions/lazy_attributes_spec.rb +64 -55
  126. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  127. data/spec/extensions/many_through_many_spec.rb +3 -4
  128. data/spec/extensions/many_to_one_pk_lookup_spec.rb +53 -15
  129. data/spec/extensions/migration_spec.rb +16 -0
  130. data/spec/extensions/null_dataset_spec.rb +1 -1
  131. data/spec/extensions/pg_array_spec.rb +48 -1
  132. data/spec/extensions/pg_hstore_ops_spec.rb +10 -2
  133. data/spec/extensions/pg_hstore_spec.rb +5 -0
  134. data/spec/extensions/pg_inet_spec.rb +5 -0
  135. data/spec/extensions/pg_interval_spec.rb +7 -3
  136. data/spec/extensions/pg_json_spec.rb +6 -1
  137. data/spec/extensions/pg_range_ops_spec.rb +4 -1
  138. data/spec/extensions/pg_range_spec.rb +5 -0
  139. data/spec/extensions/pg_row_plugin_spec.rb +13 -0
  140. data/spec/extensions/pg_row_spec.rb +28 -19
  141. data/spec/extensions/pg_typecast_on_load_spec.rb +6 -1
  142. data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
  143. data/spec/extensions/query_literals_spec.rb +1 -1
  144. data/spec/extensions/rcte_tree_spec.rb +2 -2
  145. data/spec/extensions/schema_spec.rb +2 -2
  146. data/spec/extensions/serialization_modification_detection_spec.rb +8 -0
  147. data/spec/extensions/serialization_spec.rb +15 -1
  148. data/spec/extensions/sharding_spec.rb +1 -1
  149. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  150. data/spec/extensions/static_cache_spec.rb +59 -9
  151. data/spec/extensions/tactical_eager_loading_spec.rb +19 -4
  152. data/spec/extensions/update_primary_key_spec.rb +17 -1
  153. data/spec/extensions/validation_class_methods_spec.rb +25 -0
  154. data/spec/extensions/validation_helpers_spec.rb +59 -3
  155. data/spec/integration/associations_test.rb +5 -5
  156. data/spec/integration/eager_loader_test.rb +32 -63
  157. data/spec/integration/model_test.rb +2 -2
  158. data/spec/integration/plugin_test.rb +88 -56
  159. data/spec/integration/prepared_statement_test.rb +1 -1
  160. data/spec/integration/schema_test.rb +1 -1
  161. data/spec/integration/timezone_test.rb +0 -1
  162. data/spec/integration/transaction_test.rb +0 -1
  163. data/spec/model/association_reflection_spec.rb +1 -1
  164. data/spec/model/associations_spec.rb +106 -84
  165. data/spec/model/base_spec.rb +4 -4
  166. data/spec/model/eager_loading_spec.rb +8 -8
  167. data/spec/model/model_spec.rb +27 -9
  168. data/spec/model/plugins_spec.rb +71 -0
  169. data/spec/model/record_spec.rb +99 -13
  170. metadata +12 -2
@@ -618,7 +618,7 @@ describe "A SQLite database" do
618
618
 
619
619
  specify "should have support for various #transaction modes" do
620
620
  sqls = []
621
- @db.loggers << (l=Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new)
621
+ @db.loggers << Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new
622
622
 
623
623
  @db.transaction(:mode => :immediate) do
624
624
  sqls.last.should == "BEGIN IMMEDIATE TRANSACTION"
@@ -3,9 +3,9 @@ CONNECTION_POOL_DEFAULTS = {:pool_timeout=>5, :pool_sleep_time=>0.001, :max_conn
3
3
 
4
4
  mock_db = lambda do |*a, &b|
5
5
  db = Sequel.mock
6
- db.meta_def(:connect){|c| b.arity == 1 ? b.call(c) : b.call} if b
6
+ (class << db; self end).send(:define_method, :connect){|c| b.arity == 1 ? b.call(c) : b.call} if b
7
7
  if b2 = a.shift
8
- db.meta_def(:disconnect_connection){|c| b2.arity == 1 ? b2.call(c) : b2.call}
8
+ (class << db; self end).send(:define_method, :disconnect_connection){|c| b2.arity == 1 ? b2.call(c) : b2.call}
9
9
  end
10
10
  db
11
11
  end
@@ -100,7 +100,7 @@ describe "A connection pool handling connections" do
100
100
  @cpool.created_count.should <= @max_size
101
101
  end
102
102
 
103
- specify ":disconnection_proc option should set the disconnection proc to use" do
103
+ specify "database's disconnect connection method should be called when a disconnect is detected" do
104
104
  @max_size.should == 2
105
105
  proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
106
106
  @max_size.should == 3
@@ -144,7 +144,7 @@ describe "ConnectionPool#hold" do
144
144
  @pool = Sequel::ConnectionPool.get_pool(mock_db.call{c.new}, CONNECTION_POOL_DEFAULTS)
145
145
  end
146
146
 
147
- specify "should pass the result of the connection maker proc to the supplied block" do
147
+ specify "shoulda use the database's connect method to get new connections" do
148
148
  res = nil
149
149
  @pool.hold {|c| res = c}
150
150
  res.should be_a_kind_of(@c)
@@ -156,7 +156,7 @@ describe "ConnectionPool#hold" do
156
156
 
157
157
  specify "should be re-entrant by the same thread" do
158
158
  cc = nil
159
- @pool.hold {|c| @pool.hold {|c| @pool.hold {|c| cc = c}}}
159
+ @pool.hold {|c| @pool.hold {|c1| @pool.hold {|c2| cc = c2}}}
160
160
  cc.should be_a_kind_of(@c)
161
161
  end
162
162
 
@@ -220,10 +220,10 @@ describe "A connection pool with a max size of 1" do
220
220
  c1, c2, c3 = nil
221
221
  @pool.hold do |c|
222
222
  c1 = c
223
- @pool.hold do |c|
224
- c2 = c
225
- @pool.hold do |c|
226
- c3 = c
223
+ @pool.hold do |cc2|
224
+ c2 = cc2
225
+ @pool.hold do |cc3|
226
+ c3 = cc3
227
227
  end
228
228
  end
229
229
  end
@@ -295,7 +295,6 @@ shared_examples_for "A threaded connection pool" do
295
295
  end
296
296
 
297
297
  specify "should raise a PoolTimeout error if a connection couldn't be acquired before timeout" do
298
- x = nil
299
298
  q, q1 = Queue.new, Queue.new
300
299
  pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
301
300
  t = Thread.new{pool.hold{|c| q1.push nil; q.pop}}
@@ -396,8 +395,8 @@ shared_examples_for "A threaded connection pool" do
396
395
  specify "should not store connections if :connection_handling=>:disconnect" do
397
396
  @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:disconnect))
398
397
  d = []
399
- @pool.db.meta_def(:disconnect_connection){|c| d << c}
400
- c = @pool.hold do |cc|
398
+ meta_def(@pool.db, :disconnect_connection){|c| d << c}
399
+ @pool.hold do |cc|
401
400
  cc.should == 1
402
401
  Thread.new{@pool.hold{|cc2| cc2.should == 2}}.join
403
402
  d.should == [2]
@@ -456,7 +455,7 @@ describe "ConnectionPool#disconnect" do
456
455
  @pool.available_connections.size.should == 5
457
456
  @pool.available_connections.each {|c| c[:id].should_not be_nil}
458
457
  conns = []
459
- @pool.db.meta_def(:disconnect_connection){|c| conns << c}
458
+ meta_def(@pool.db, :disconnect_connection){|c| conns << c}
460
459
  @pool.disconnect
461
460
  conns.size.should == 5
462
461
  end
@@ -473,7 +472,7 @@ describe "ConnectionPool#disconnect" do
473
472
  @pool.available_connections.size.should == 4
474
473
  @pool.available_connections.each {|c| c.should_not be(conn)}
475
474
  conns = []
476
- @pool.db.meta_def(:disconnect_connection){|c| conns << c}
475
+ meta_def(@pool.db, :disconnect_connection){|c| conns << c}
477
476
  @pool.disconnect
478
477
  conns.size.should == 4
479
478
  @pool.size.should == 1
@@ -575,7 +574,7 @@ describe "A connection pool with multiple servers" do
575
574
  conns = []
576
575
  @pool.size.should == 1
577
576
  @pool.size(:read_only).should == 1
578
- @pool.db.meta_def(:disconnect_connection){|c| conns << c}
577
+ meta_def(@pool.db, :disconnect_connection){|c| conns << c}
579
578
  @pool.disconnect
580
579
  conns.sort.should == %w'default1 read_only1'
581
580
  @pool.size.should == 0
@@ -923,13 +922,13 @@ shared_examples_for "All connection pools classes" do
923
922
 
924
923
  specify "should call the disconnection_proc option if the hold block raises a DatabaseDisconnectError" do
925
924
  x = nil
926
- proc{c = @class.new(mock_db.call(proc{|c| x = c}){123}).hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
925
+ proc{@class.new(mock_db.call(proc{|c| x = c}){123}).hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
927
926
  x.should == 123
928
927
  end
929
928
 
930
929
  specify "should have a disconnect method that disconnects the connection" do
931
930
  x = nil
932
- c = @class.new(mock_db.call(proc{|c| x = c}){123})
931
+ c = @class.new(mock_db.call(proc{|c1| x = c1}){123})
933
932
  c.hold{}
934
933
  x.should == nil
935
934
  c.disconnect
@@ -43,10 +43,10 @@ describe "A new Database" do
43
43
  Sequel::Database.new(:max_connections => 10).pool.max_size.should == 10
44
44
  end
45
45
 
46
- specify "should pass the supplied block to the connection pool" do
46
+ specify "should have the connection pool use the connect method to get connections" do
47
47
  cc = nil
48
48
  d = Sequel::Database.new
49
- d.meta_def(:connect){|c| 1234}
49
+ meta_def(d, :connect){|c| 1234}
50
50
  d.synchronize {|c| cc = c}
51
51
  cc.should == 1234
52
52
  end
@@ -204,6 +204,11 @@ describe "A new Database" do
204
204
  specify "should populate :adapter option when using connection string" do
205
205
  Sequel.connect('mock:/').opts[:adapter].should == "mock"
206
206
  end
207
+
208
+ specify "should respect the :keep_reference option for not keeping a reference in Sequel::DATABASES" do
209
+ db = Sequel.connect('mock:///?keep_reference=f')
210
+ Sequel::DATABASES.should_not include(db)
211
+ end
207
212
  end
208
213
 
209
214
  describe "Database#disconnect" do
@@ -343,7 +348,7 @@ describe "Database#uri" do
343
348
  end
344
349
 
345
350
  describe "Database.adapter_scheme and #adapter_scheme" do
346
- specify "should return the database schema" do
351
+ specify "should return the database scheme" do
347
352
  Sequel::Database.adapter_scheme.should be_nil
348
353
 
349
354
  @c = Class.new(Sequel::Database) do
@@ -470,7 +475,7 @@ describe "Database#extend_datasets" do
470
475
  @db[:t].select(:a, :b).sql.should == 'SELECT a, b FROM t ORDER BY a, b'
471
476
  end
472
477
 
473
- specify "should reapply settings if dataset_class is chagned" do
478
+ specify "should reapply settings if dataset_class is changed" do
474
479
  c = Class.new(Sequel::Dataset)
475
480
  @db.dataset_class = c
476
481
  @db.dataset_class.superclass.should == c
@@ -568,11 +573,11 @@ end
568
573
  describe "Database#synchronize" do
569
574
  before do
570
575
  @db = Sequel::Database.new(:max_connections => 1)
571
- @db.meta_def(:connect){|c| 12345}
576
+ meta_def(@db, :connect){|c| 12345}
572
577
  end
573
578
 
574
579
  specify "should wrap the supplied block in pool.hold" do
575
- q, q1, q2, q3 = Queue.new, Queue.new, Queue.new, Queue.new
580
+ q, q1, q2 = Queue.new, Queue.new, Queue.new
576
581
  c1, c2 = nil
577
582
  t1 = Thread.new{@db.synchronize{|c| c1 = c; q.push nil; q1.pop}; q.push nil}
578
583
  q.pop
@@ -593,7 +598,7 @@ describe "Database#test_connection" do
593
598
  before do
594
599
  @db = Sequel::Database.new
595
600
  pr = proc{@test = rand(100)}
596
- @db.meta_def(:connect){|c| pr.call}
601
+ meta_def(@db, :connect){|c| pr.call}
597
602
  end
598
603
 
599
604
  specify "should attempt to get a connection" do
@@ -611,7 +616,7 @@ describe "Database#test_connection" do
611
616
  end
612
617
 
613
618
  describe "Database#table_exists?" do
614
- specify "should try to select the first record from the table's dataset" do
619
+ specify "should test existence by selecting a row from the table's dataset" do
615
620
  db = Sequel.mock(:fetch=>[Sequel::Error, [], [{:a=>1}]])
616
621
  db.table_exists?(:a).should be_false
617
622
  db.sqls.should == ["SELECT NULL FROM a LIMIT 1"]
@@ -627,7 +632,7 @@ shared_examples_for "Database#transaction" do
627
632
  end
628
633
 
629
634
  specify "should support transaction isolation levels" do
630
- @db.meta_def(:supports_transaction_isolation_levels?){true}
635
+ meta_def(@db, :supports_transaction_isolation_levels?){true}
631
636
  [:uncommitted, :committed, :repeatable, :serializable].each do |l|
632
637
  @db.transaction(:isolation=>l){@db.run "DROP TABLE #{l}"}
633
638
  end
@@ -638,7 +643,7 @@ shared_examples_for "Database#transaction" do
638
643
  end
639
644
 
640
645
  specify "should allow specifying a default transaction isolation level" do
641
- @db.meta_def(:supports_transaction_isolation_levels?){true}
646
+ meta_def(@db, :supports_transaction_isolation_levels?){true}
642
647
  [:uncommitted, :committed, :repeatable, :serializable].each do |l|
643
648
  @db.transaction_isolation_level = l
644
649
  @db.transaction{@db.run "DROP TABLE #{l}"}
@@ -715,7 +720,6 @@ shared_examples_for "Database#transaction" do
715
720
  transaction do
716
721
  execute 'DROP TABLE test;'
717
722
  return
718
- execute 'DROP TABLE test2;';
719
723
  end
720
724
  end
721
725
  @db.ret_commit
@@ -731,8 +735,8 @@ shared_examples_for "Database#transaction" do
731
735
 
732
736
  specify "should handle errors when sending BEGIN" do
733
737
  ec = Class.new(StandardError)
734
- @db.meta_def(:database_error_classes){[ec]}
735
- @db.meta_def(:log_connection_execute){|c, sql| sql =~ /BEGIN/ ? raise(ec, 'bad') : super(c, sql)}
738
+ meta_def(@db, :database_error_classes){[ec]}
739
+ meta_def(@db, :log_connection_execute){|c, sql| sql =~ /BEGIN/ ? raise(ec, 'bad') : super(c, sql)}
736
740
  begin
737
741
  @db.transaction{@db.execute 'DROP TABLE test;'}
738
742
  rescue Sequel::DatabaseError => e
@@ -744,8 +748,8 @@ shared_examples_for "Database#transaction" do
744
748
 
745
749
  specify "should handle errors when sending COMMIT" do
746
750
  ec = Class.new(StandardError)
747
- @db.meta_def(:database_error_classes){[ec]}
748
- @db.meta_def(:log_connection_execute){|c, sql| sql =~ /COMMIT/ ? raise(ec, 'bad') : super(c, sql)}
751
+ meta_def(@db, :database_error_classes){[ec]}
752
+ meta_def(@db, :log_connection_execute){|c, sql| sql =~ /COMMIT/ ? raise(ec, 'bad') : super(c, sql)}
749
753
  begin
750
754
  @db.transaction{@db.execute 'DROP TABLE test;'}
751
755
  rescue Sequel::DatabaseError => e
@@ -757,8 +761,8 @@ shared_examples_for "Database#transaction" do
757
761
 
758
762
  specify "should handle errors when sending ROLLBACK" do
759
763
  ec = Class.new(StandardError)
760
- @db.meta_def(:database_error_classes){[ec]}
761
- @db.meta_def(:log_connection_execute){|c, sql| sql =~ /ROLLBACK/ ? raise(ec, 'bad') : super(c, sql)}
764
+ meta_def(@db, :database_error_classes){[ec]}
765
+ meta_def(@db, :log_connection_execute){|c, sql| sql =~ /ROLLBACK/ ? raise(ec, 'bad') : super(c, sql)}
762
766
  begin
763
767
  @db.transaction{raise ArgumentError, 'asdf'}
764
768
  rescue Sequel::DatabaseError => e
@@ -815,17 +819,17 @@ shared_examples_for "Database#transaction" do
815
819
  @db.sqls.should == ['BEGIN', 'ROLLBACK']
816
820
  @db.transaction(:rollback=>:always){1}.should be_nil
817
821
  @db.sqls.should == ['BEGIN', 'ROLLBACK']
818
- catch (:foo) do
822
+ catch(:foo) do
819
823
  @db.transaction(:rollback=>:always){throw :foo}
820
824
  end
821
825
  @db.sqls.should == ['BEGIN', 'ROLLBACK']
822
826
  end
823
827
 
824
828
  specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
825
- @db.meta_def(:commit_transaction){raise ArgumentError}
829
+ meta_def(@db, :commit_transaction){raise ArgumentError}
826
830
  lambda{@db.transaction{}}.should raise_error(ArgumentError)
827
831
 
828
- @db.meta_def(:database_error_classes){[ArgumentError]}
832
+ meta_def(@db, :database_error_classes){[ArgumentError]}
829
833
  lambda{@db.transaction{}}.should raise_error(Sequel::DatabaseError)
830
834
  end
831
835
 
@@ -942,13 +946,13 @@ shared_examples_for "Database#transaction" do
942
946
  end
943
947
 
944
948
  specify "should raise an error if you attempt to use after_commit inside a prepared transaction" do
945
- @db.meta_def(:supports_prepared_transactions?){true}
949
+ meta_def(@db, :supports_prepared_transactions?){true}
946
950
  proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{@db.execute('foo')}}}.should raise_error(Sequel::Error)
947
951
  @db.sqls.should == ['BEGIN', 'ROLLBACK']
948
952
  end
949
953
 
950
954
  specify "should raise an error if you attempt to use after_rollback inside a prepared transaction" do
951
- @db.meta_def(:supports_prepared_transactions?){true}
955
+ meta_def(@db, :supports_prepared_transactions?){true}
952
956
  proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{@db.execute('foo')}}}.should raise_error(Sequel::Error)
953
957
  @db.sqls.should == ['BEGIN', 'ROLLBACK']
954
958
  end
@@ -962,7 +966,7 @@ describe "Database#transaction with savepoint support" do
962
966
  it_should_behave_like "Database#transaction"
963
967
 
964
968
  specify "should support after_commit inside savepoints" do
965
- @db.meta_def(:supports_savepoints?){true}
969
+ meta_def(@db, :supports_savepoints?){true}
966
970
  @db.transaction do
967
971
  @db.after_commit{@db.execute('foo')}
968
972
  @db.transaction(:savepoint=>true){@db.after_commit{@db.execute('bar')}}
@@ -972,7 +976,7 @@ describe "Database#transaction with savepoint support" do
972
976
  end
973
977
 
974
978
  specify "should support after_rollback inside savepoints" do
975
- @db.meta_def(:supports_savepoints?){true}
979
+ meta_def(@db, :supports_savepoints?){true}
976
980
  @db.transaction do
977
981
  @db.after_rollback{@db.execute('foo')}
978
982
  @db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
@@ -983,15 +987,15 @@ describe "Database#transaction with savepoint support" do
983
987
  end
984
988
 
985
989
  specify "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
986
- @db.meta_def(:supports_savepoints?){true}
987
- @db.meta_def(:supports_prepared_transactions?){true}
990
+ meta_def(@db, :supports_savepoints?){true}
991
+ meta_def(@db, :supports_prepared_transactions?){true}
988
992
  proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
989
993
  @db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
990
994
  end
991
995
 
992
996
  specify "should raise an error if you attempt to use after_rollback inside a savepoint in a prepared transaction" do
993
- @db.meta_def(:supports_savepoints?){true}
994
- @db.meta_def(:supports_prepared_transactions?){true}
997
+ meta_def(@db, :supports_savepoints?){true}
998
+ meta_def(@db, :supports_prepared_transactions?){true}
995
999
  proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
996
1000
  @db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
997
1001
  end
@@ -1000,7 +1004,7 @@ end
1000
1004
  describe "Database#transaction without savepoint support" do
1001
1005
  before do
1002
1006
  @db = Sequel.mock(:servers=>{:test=>{}})
1003
- @db.meta_def(:supports_savepoints?){false}
1007
+ meta_def(@db, :supports_savepoints?){false}
1004
1008
  end
1005
1009
 
1006
1010
  it_should_behave_like "Database#transaction"
@@ -1058,7 +1062,7 @@ describe "Database#transaction with savepoints" do
1058
1062
  @db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1059
1063
  end
1060
1064
 
1061
- specify "should not use a savepoints if no transaction is in progress" do
1065
+ specify "should not use a savepoint if no transaction is in progress" do
1062
1066
  @db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}
1063
1067
  @db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
1064
1068
  end
@@ -1073,7 +1077,6 @@ describe "Database#transaction with savepoints" do
1073
1077
  transaction do
1074
1078
  execute 'DROP TABLE test;'
1075
1079
  return
1076
- execute 'DROP TABLE test2;';
1077
1080
  end
1078
1081
  end
1079
1082
  @db.ret_commit
@@ -1086,7 +1089,6 @@ describe "Database#transaction with savepoints" do
1086
1089
  transaction(:savepoint=>true) do
1087
1090
  execute 'DROP TABLE test;'
1088
1091
  return
1089
- execute 'DROP TABLE test2;';
1090
1092
  end
1091
1093
  end
1092
1094
  end
@@ -1131,11 +1133,11 @@ describe "Database#transaction with savepoints" do
1131
1133
  end
1132
1134
 
1133
1135
  specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
1134
- @db.meta_def(:commit_transaction){raise ArgumentError}
1136
+ meta_def(@db, :commit_transaction){raise ArgumentError}
1135
1137
  lambda{@db.transaction{}}.should raise_error(ArgumentError)
1136
1138
  lambda{@db.transaction{@db.transaction(:savepoint=>true){}}}.should raise_error(ArgumentError)
1137
1139
 
1138
- @db.meta_def(:database_error_classes){[ArgumentError]}
1140
+ meta_def(@db, :database_error_classes){[ArgumentError]}
1139
1141
  lambda{@db.transaction{}}.should raise_error(Sequel::DatabaseError)
1140
1142
  lambda{@db.transaction{@db.transaction(:savepoint=>true){}}}.should raise_error(Sequel::DatabaseError)
1141
1143
  end
@@ -1200,6 +1202,7 @@ describe "A Database adapter with a scheme" do
1200
1202
  Sequel.send(:def_adapter_method, :ccc)
1201
1203
  Sequel.ccc('db', :host=>'localhost', &p).should == returnValue
1202
1204
  @ccc::DISCONNECTS.should == [z, y, x]
1205
+ class << Sequel; remove_method(:ccc) end
1203
1206
  end
1204
1207
 
1205
1208
  specify "should be accessible through Sequel.<adapter>" do
@@ -1223,6 +1226,7 @@ describe "A Database adapter with a scheme" do
1223
1226
  c = Sequel.ccc(:database => 'mydb', :host => 'localhost')
1224
1227
  c.should be_a_kind_of(@ccc)
1225
1228
  c.opts.values_at(:adapter, :database, :host, :adapter_class).should == [:ccc, 'mydb', 'localhost', @ccc]
1229
+ class << Sequel; remove_method(:ccc) end
1226
1230
  end
1227
1231
 
1228
1232
  specify "should be accessible through Sequel.connect with options" do
@@ -1340,7 +1344,7 @@ describe "A single threaded database" do
1340
1344
  before do
1341
1345
  conn = 1234567
1342
1346
  @db = Sequel::Database.new(:single_threaded => true)
1343
- @db.meta_def(:connect) do |c|
1347
+ meta_def(@db, :connect) do |c|
1344
1348
  conn += 1
1345
1349
  end
1346
1350
  end
@@ -1692,7 +1696,7 @@ describe "Database#each_server" do
1692
1696
  @db.each_server do |db|
1693
1697
  dbs << db
1694
1698
  Sequel::DATABASES.should include(db)
1695
- db.meta_def(:disconnect){dcs << db}
1699
+ meta_def(db, :disconnect){dcs << db}
1696
1700
  end
1697
1701
  dbs.each do |db|
1698
1702
  Sequel::DATABASES.should_not include(db)
@@ -2099,6 +2103,18 @@ describe "Database#schema_autoincrementing_primary_key?" do
2099
2103
  end
2100
2104
  end
2101
2105
 
2106
+ describe "Database#supports_schema_parsing?" do
2107
+ specify "should be false by default" do
2108
+ Sequel::Database.new.supports_schema_parsing?.should == false
2109
+ end
2110
+
2111
+ specify "should be true if the database implements schema_parse_table" do
2112
+ db = Sequel::Database.new
2113
+ def db.schema_parse_table(*) end
2114
+ db.supports_schema_parsing?.should == true
2115
+ end
2116
+ end
2117
+
2102
2118
  describe "Database#supports_deferrable_constraints?" do
2103
2119
  specify "should be false by default" do
2104
2120
  Sequel::Database.new.supports_deferrable_constraints?.should == false
@@ -2136,8 +2152,8 @@ describe "Database#supports_savepoints_in_prepared_transactions?" do
2136
2152
 
2137
2153
  specify "should be true if both savepoints and prepared transactions are supported" do
2138
2154
  db = Sequel::Database.new
2139
- db.meta_def(:supports_savepoints?){true}
2140
- db.meta_def(:supports_prepared_transactions?){true}
2155
+ meta_def(db, :supports_savepoints?){true}
2156
+ meta_def(db, :supports_prepared_transactions?){true}
2141
2157
  db.supports_savepoints_in_prepared_transactions?.should == true
2142
2158
  end
2143
2159
  end
@@ -2259,25 +2275,31 @@ describe "Database extensions" do
2259
2275
  before(:all) do
2260
2276
  class << Sequel
2261
2277
  alias _extension extension
2278
+ remove_method :extension
2262
2279
  def extension(*)
2263
2280
  end
2264
2281
  end
2265
2282
  end
2266
2283
  after(:all) do
2267
2284
  class << Sequel
2285
+ remove_method :extension
2268
2286
  alias extension _extension
2287
+ remove_method :_extension
2269
2288
  end
2270
2289
  end
2271
2290
  before do
2272
2291
  @db = Sequel.mock
2273
2292
  end
2293
+ after do
2294
+ Sequel::Database.instance_variable_set(:@initialize_hook, Proc.new {|db| })
2295
+ end
2274
2296
 
2275
- specify "should be able to register an extension with a module Database#extension extend the module" do
2297
+ specify "should be able to register an extension with a module have Database#extension extend the module" do
2276
2298
  Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
2277
2299
  @db.extension(:foo).a.should == 1
2278
2300
  end
2279
2301
 
2280
- specify "should be able to register an extension with a block and Database#extension call the block" do
2302
+ specify "should be able to register an extension with a block and have Database#extension call the block" do
2281
2303
  @db.quote_identifiers = false
2282
2304
  Sequel::Database.register_extension(:foo){|db| db.quote_identifiers = true}
2283
2305
  @db.extension(:foo).quote_identifiers?.should be_true
@@ -2311,6 +2333,16 @@ describe "Database extensions" do
2311
2333
  specify "should raise an Error if attempting to load an incompatible extension" do
2312
2334
  proc{@db.extension(:foo2)}.should raise_error(Sequel::Error)
2313
2335
  end
2336
+
2337
+ specify "should be able to load an extension into all future Databases with Database.extension" do
2338
+ Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
2339
+ Sequel::Database.register_extension(:bar, Module.new{def b; 2; end})
2340
+ Sequel::Database.extension(:foo, :bar)
2341
+ @db.should_not respond_to(:a)
2342
+ @db.should_not respond_to(:b)
2343
+ Sequel.mock.a.should == 1
2344
+ Sequel.mock.b.should == 2
2345
+ end
2314
2346
  end
2315
2347
 
2316
2348
  describe "Database specific exception classes" do
@@ -2339,3 +2371,42 @@ describe "Database specific exception classes" do
2339
2371
  proc{@db.get(1)}.should raise_error(Sequel::SerializationFailure)
2340
2372
  end
2341
2373
  end
2374
+
2375
+ describe "Database.after_initialize" do
2376
+ after do
2377
+ Sequel::Database.instance_variable_set(:@initialize_hook, Proc.new {|db| })
2378
+ end
2379
+
2380
+ specify "should allow a block to be run after each new instance is created" do
2381
+ Sequel::Database.after_initialize{|db| db.sql_log_level = :debug }
2382
+ db = Sequel.mock
2383
+ db.sql_log_level.should == :debug
2384
+ end
2385
+
2386
+ specify "should allow multiple hooks to be registered" do
2387
+ Sequel::Database.after_initialize{|db| db.sql_log_level = :debug }
2388
+ Sequel::Database.after_initialize{|db| db.loggers << 11 }
2389
+
2390
+ db = Sequel.mock
2391
+
2392
+ db.sql_log_level.should == :debug
2393
+ db.loggers.should include(11)
2394
+ end
2395
+
2396
+ specify "should raise an error if registration is called without a block" do
2397
+ proc {
2398
+ Sequel::Database.after_initialize
2399
+ }.should raise_error(Sequel::Error, /must provide block/i)
2400
+ end
2401
+ end
2402
+
2403
+ describe "Database#schema_type_class" do
2404
+ specify "should return the class or array of classes for the given type symbol" do
2405
+ db = Sequel.mock
2406
+ {:string=>String, :integer=>Integer, :date=>Date, :datetime=>[Time, DateTime],
2407
+ :time=>Sequel::SQLTime, :boolean=>[TrueClass, FalseClass], :float=>Float, :decimal=>BigDecimal,
2408
+ :blob=>Sequel::SQL::Blob}.each do |sym, klass|
2409
+ db.schema_type_class(sym).should == klass
2410
+ end
2411
+ end
2412
+ end