sequel 3.46.0 → 3.47.0

Sign up to get free protection for your applications and to get access to all the features.
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