sequel 3.21.0 → 3.31.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 (225) hide show
  1. data/CHANGELOG +485 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +37 -19
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +249 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/dataset_filtering.rdoc +8 -0
  8. data/doc/mass_assignment.rdoc +54 -0
  9. data/doc/migration.rdoc +15 -538
  10. data/doc/model_hooks.rdoc +72 -27
  11. data/doc/opening_databases.rdoc +89 -50
  12. data/doc/prepared_statements.rdoc +40 -13
  13. data/doc/reflection.rdoc +8 -2
  14. data/doc/release_notes/3.22.0.txt +39 -0
  15. data/doc/release_notes/3.23.0.txt +172 -0
  16. data/doc/release_notes/3.24.0.txt +420 -0
  17. data/doc/release_notes/3.25.0.txt +88 -0
  18. data/doc/release_notes/3.26.0.txt +88 -0
  19. data/doc/release_notes/3.27.0.txt +82 -0
  20. data/doc/release_notes/3.28.0.txt +304 -0
  21. data/doc/release_notes/3.29.0.txt +459 -0
  22. data/doc/release_notes/3.30.0.txt +135 -0
  23. data/doc/release_notes/3.31.0.txt +146 -0
  24. data/doc/schema_modification.rdoc +547 -0
  25. data/doc/sharding.rdoc +7 -1
  26. data/doc/testing.rdoc +129 -0
  27. data/doc/transactions.rdoc +137 -0
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  30. data/lib/sequel/adapters/ado.rb +40 -18
  31. data/lib/sequel/adapters/amalgalite.rb +17 -9
  32. data/lib/sequel/adapters/db2.rb +175 -86
  33. data/lib/sequel/adapters/dbi.rb +15 -15
  34. data/lib/sequel/adapters/do/mysql.rb +5 -7
  35. data/lib/sequel/adapters/do/postgres.rb +0 -5
  36. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/do.rb +17 -36
  38. data/lib/sequel/adapters/firebird.rb +27 -208
  39. data/lib/sequel/adapters/ibmdb.rb +448 -0
  40. data/lib/sequel/adapters/informix.rb +6 -23
  41. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  42. data/lib/sequel/adapters/jdbc/db2.rb +45 -0
  43. data/lib/sequel/adapters/jdbc/derby.rb +247 -0
  44. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  45. data/lib/sequel/adapters/jdbc/h2.rb +56 -29
  46. data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
  47. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  48. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  49. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  50. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  51. data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
  52. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  53. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  54. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  55. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  56. data/lib/sequel/adapters/jdbc.rb +231 -78
  57. data/lib/sequel/adapters/mock.rb +335 -0
  58. data/lib/sequel/adapters/mysql.rb +82 -184
  59. data/lib/sequel/adapters/mysql2.rb +26 -25
  60. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  61. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  62. data/lib/sequel/adapters/odbc.rb +28 -9
  63. data/lib/sequel/adapters/openbase.rb +3 -5
  64. data/lib/sequel/adapters/oracle.rb +351 -53
  65. data/lib/sequel/adapters/postgres.rb +194 -33
  66. data/lib/sequel/adapters/shared/access.rb +32 -9
  67. data/lib/sequel/adapters/shared/db2.rb +321 -0
  68. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  69. data/lib/sequel/adapters/shared/informix.rb +53 -0
  70. data/lib/sequel/adapters/shared/mssql.rb +231 -106
  71. data/lib/sequel/adapters/shared/mysql.rb +181 -63
  72. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +231 -41
  74. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  75. data/lib/sequel/adapters/shared/progress.rb +4 -7
  76. data/lib/sequel/adapters/shared/sqlite.rb +201 -57
  77. data/lib/sequel/adapters/sqlite.rb +29 -21
  78. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  79. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  80. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  81. data/lib/sequel/adapters/swift.rb +5 -5
  82. data/lib/sequel/adapters/tinytds.rb +160 -19
  83. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  84. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  85. data/lib/sequel/ast_transformer.rb +190 -0
  86. data/lib/sequel/connection_pool/threaded.rb +3 -2
  87. data/lib/sequel/connection_pool.rb +1 -1
  88. data/lib/sequel/core.rb +46 -5
  89. data/lib/sequel/database/connecting.rb +5 -6
  90. data/lib/sequel/database/dataset.rb +4 -4
  91. data/lib/sequel/database/dataset_defaults.rb +59 -1
  92. data/lib/sequel/database/logging.rb +1 -1
  93. data/lib/sequel/database/misc.rb +104 -19
  94. data/lib/sequel/database/query.rb +153 -58
  95. data/lib/sequel/database/schema_generator.rb +17 -7
  96. data/lib/sequel/database/schema_methods.rb +59 -29
  97. data/lib/sequel/dataset/actions.rb +231 -76
  98. data/lib/sequel/dataset/features.rb +91 -8
  99. data/lib/sequel/dataset/graph.rb +38 -11
  100. data/lib/sequel/dataset/misc.rb +50 -23
  101. data/lib/sequel/dataset/mutation.rb +5 -6
  102. data/lib/sequel/dataset/prepared_statements.rb +48 -27
  103. data/lib/sequel/dataset/query.rb +236 -43
  104. data/lib/sequel/dataset/sql.rb +665 -253
  105. data/lib/sequel/dataset.rb +8 -0
  106. data/lib/sequel/exceptions.rb +4 -0
  107. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  108. data/lib/sequel/extensions/migration.rb +6 -4
  109. data/lib/sequel/extensions/named_timezones.rb +5 -0
  110. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  111. data/lib/sequel/extensions/to_dot.rb +95 -83
  112. data/lib/sequel/model/associations.rb +1020 -337
  113. data/lib/sequel/model/base.rb +414 -132
  114. data/lib/sequel/model/errors.rb +1 -1
  115. data/lib/sequel/model/exceptions.rb +5 -1
  116. data/lib/sequel/model.rb +15 -8
  117. data/lib/sequel/plugins/association_pks.rb +22 -4
  118. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  119. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  120. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  121. data/lib/sequel/plugins/force_encoding.rb +6 -6
  122. data/lib/sequel/plugins/identity_map.rb +114 -7
  123. data/lib/sequel/plugins/many_through_many.rb +65 -7
  124. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  125. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  126. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  127. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  128. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  129. data/lib/sequel/plugins/serialization.rb +88 -44
  130. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  131. data/lib/sequel/plugins/sharding.rb +21 -54
  132. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  133. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  134. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  135. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  136. data/lib/sequel/sql.rb +109 -52
  137. data/lib/sequel/timezones.rb +57 -38
  138. data/lib/sequel/version.rb +1 -1
  139. data/spec/adapters/db2_spec.rb +146 -0
  140. data/spec/adapters/mssql_spec.rb +111 -29
  141. data/spec/adapters/mysql_spec.rb +135 -123
  142. data/spec/adapters/oracle_spec.rb +49 -77
  143. data/spec/adapters/postgres_spec.rb +267 -78
  144. data/spec/adapters/spec_helper.rb +6 -5
  145. data/spec/adapters/sqlite_spec.rb +35 -21
  146. data/spec/core/connection_pool_spec.rb +71 -92
  147. data/spec/core/core_sql_spec.rb +21 -30
  148. data/spec/core/database_spec.rb +788 -512
  149. data/spec/core/dataset_spec.rb +1073 -1053
  150. data/spec/core/expression_filters_spec.rb +159 -42
  151. data/spec/core/mock_adapter_spec.rb +419 -0
  152. data/spec/core/object_graph_spec.rb +86 -114
  153. data/spec/core/schema_generator_spec.rb +3 -3
  154. data/spec/core/schema_spec.rb +298 -38
  155. data/spec/core/spec_helper.rb +6 -48
  156. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  157. data/spec/extensions/association_dependencies_spec.rb +2 -12
  158. data/spec/extensions/association_pks_spec.rb +66 -32
  159. data/spec/extensions/caching_spec.rb +23 -50
  160. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  161. data/spec/extensions/columns_introspection_spec.rb +91 -0
  162. data/spec/extensions/composition_spec.rb +18 -13
  163. data/spec/extensions/dataset_associations_spec.rb +199 -0
  164. data/spec/extensions/defaults_setter_spec.rb +64 -0
  165. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  166. data/spec/extensions/identity_map_spec.rb +114 -22
  167. data/spec/extensions/instance_filters_spec.rb +11 -21
  168. data/spec/extensions/instance_hooks_spec.rb +53 -0
  169. data/spec/extensions/json_serializer_spec.rb +4 -5
  170. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  171. data/spec/extensions/list_spec.rb +17 -39
  172. data/spec/extensions/many_through_many_spec.rb +283 -250
  173. data/spec/extensions/migration_spec.rb +35 -32
  174. data/spec/extensions/named_timezones_spec.rb +23 -3
  175. data/spec/extensions/nested_attributes_spec.rb +97 -88
  176. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  177. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  178. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  179. data/spec/extensions/prepared_statements_spec.rb +53 -0
  180. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  181. data/spec/extensions/pretty_table_spec.rb +1 -6
  182. data/spec/extensions/rcte_tree_spec.rb +41 -43
  183. data/spec/extensions/schema_dumper_spec.rb +5 -8
  184. data/spec/extensions/schema_spec.rb +13 -21
  185. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  186. data/spec/extensions/serialization_spec.rb +72 -43
  187. data/spec/extensions/sharding_spec.rb +66 -140
  188. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  189. data/spec/extensions/spec_helper.rb +13 -61
  190. data/spec/extensions/sql_expr_spec.rb +20 -60
  191. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  192. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  193. data/spec/extensions/timestamps_spec.rb +6 -6
  194. data/spec/extensions/to_dot_spec.rb +4 -7
  195. data/spec/extensions/touch_spec.rb +13 -14
  196. data/spec/extensions/tree_spec.rb +11 -26
  197. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  198. data/spec/extensions/update_primary_key_spec.rb +30 -24
  199. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  200. data/spec/extensions/validation_helpers_spec.rb +16 -35
  201. data/spec/extensions/xml_serializer_spec.rb +16 -4
  202. data/spec/integration/associations_test.rb +537 -21
  203. data/spec/integration/database_test.rb +4 -2
  204. data/spec/integration/dataset_test.rb +461 -65
  205. data/spec/integration/eager_loader_test.rb +19 -21
  206. data/spec/integration/model_test.rb +80 -1
  207. data/spec/integration/plugin_test.rb +304 -116
  208. data/spec/integration/prepared_statement_test.rb +212 -122
  209. data/spec/integration/schema_test.rb +161 -30
  210. data/spec/integration/spec_helper.rb +39 -30
  211. data/spec/integration/timezone_test.rb +38 -12
  212. data/spec/integration/transaction_test.rb +172 -5
  213. data/spec/integration/type_test.rb +17 -3
  214. data/spec/model/association_reflection_spec.rb +201 -7
  215. data/spec/model/associations_spec.rb +865 -662
  216. data/spec/model/base_spec.rb +275 -95
  217. data/spec/model/dataset_methods_spec.rb +7 -27
  218. data/spec/model/eager_loading_spec.rb +677 -676
  219. data/spec/model/hooks_spec.rb +309 -67
  220. data/spec/model/model_spec.rb +222 -168
  221. data/spec/model/plugins_spec.rb +24 -13
  222. data/spec/model/record_spec.rb +381 -218
  223. data/spec/model/spec_helper.rb +13 -71
  224. data/spec/model/validations_spec.rb +11 -0
  225. metadata +115 -73
@@ -6,30 +6,55 @@ describe "Database schema parser" do
6
6
  @iom = INTEGRATION_DB.identifier_output_method
7
7
  @iim = INTEGRATION_DB.identifier_input_method
8
8
  @defsch = INTEGRATION_DB.default_schema
9
- clear_sqls
9
+ @qi = INTEGRATION_DB.quote_identifiers?
10
10
  end
11
11
  after do
12
12
  INTEGRATION_DB.identifier_output_method = @iom
13
13
  INTEGRATION_DB.identifier_input_method = @iim
14
14
  INTEGRATION_DB.default_schema = @defsch
15
+ INTEGRATION_DB.quote_identifiers = @qi
15
16
  INTEGRATION_DB.drop_table(:items) if INTEGRATION_DB.table_exists?(:items)
16
17
  end
17
18
 
18
- specify "should handle a database with a identifier_output_method" do
19
+ specify "should handle a database with a identifier methods" do
19
20
  INTEGRATION_DB.identifier_output_method = :reverse
20
21
  INTEGRATION_DB.identifier_input_method = :reverse
22
+ INTEGRATION_DB.quote_identifiers = true
21
23
  INTEGRATION_DB.default_schema = nil if INTEGRATION_DB.default_schema
22
24
  INTEGRATION_DB.create_table!(:items){Integer :number}
23
- INTEGRATION_DB.schema(:items, :reload=>true).should be_a_kind_of(Array)
24
- INTEGRATION_DB.schema(:items, :reload=>true).first.first.should == :number
25
+ begin
26
+ INTEGRATION_DB.schema(:items, :reload=>true).should be_a_kind_of(Array)
27
+ INTEGRATION_DB.schema(:items, :reload=>true).first.first.should == :number
28
+ ensure
29
+ INTEGRATION_DB.drop_table(:items)
30
+ end
31
+ end
32
+
33
+ specify "should handle a dataset with identifier methods different than the database's" do
34
+ INTEGRATION_DB.identifier_output_method = :reverse
35
+ INTEGRATION_DB.identifier_input_method = :reverse
36
+ INTEGRATION_DB.quote_identifiers = true
37
+ INTEGRATION_DB.default_schema = nil if INTEGRATION_DB.default_schema
38
+ INTEGRATION_DB.create_table!(:items){Integer :number}
39
+ INTEGRATION_DB.identifier_output_method = @iom
40
+ INTEGRATION_DB.identifier_input_method = @iim
41
+ ds = INTEGRATION_DB[:items]
42
+ ds.identifier_output_method = :reverse
43
+ ds.identifier_input_method = :reverse
44
+ begin
45
+ INTEGRATION_DB.schema(ds, :reload=>true).should be_a_kind_of(Array)
46
+ INTEGRATION_DB.schema(ds, :reload=>true).first.first.should == :number
47
+ ensure
48
+ INTEGRATION_DB.identifier_output_method = :reverse
49
+ INTEGRATION_DB.identifier_input_method = :reverse
50
+ INTEGRATION_DB.drop_table(:items)
51
+ end
25
52
  end
26
53
 
27
54
  specify "should not issue an sql query if the schema has been loaded unless :reload is true" do
28
55
  INTEGRATION_DB.create_table!(:items){Integer :number}
29
56
  INTEGRATION_DB.schema(:items, :reload=>true)
30
- clear_sqls
31
57
  INTEGRATION_DB.schema(:items)
32
- clear_sqls
33
58
  INTEGRATION_DB.schema(:items, :reload=>true)
34
59
  end
35
60
 
@@ -56,11 +81,10 @@ describe "Database schema parser" do
56
81
  col_info = col.last
57
82
  col_info.should be_a_kind_of(Hash)
58
83
  col_info[:type].should == :integer
59
- clear_sqls
60
84
  INTEGRATION_DB.schema(:items)
61
85
  end
62
86
 
63
- cspecify "should parse primary keys from the schema properly", [proc{|db| db.adapter_scheme != :jdbc}, :mssql] do
87
+ specify "should parse primary keys from the schema properly" do
64
88
  INTEGRATION_DB.create_table!(:items){Integer :number}
65
89
  INTEGRATION_DB.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == []
66
90
  INTEGRATION_DB.create_table!(:items){primary_key :number}
@@ -85,7 +109,7 @@ describe "Database schema parser" do
85
109
  INTEGRATION_DB.schema(:items).first.last[:ruby_default].should == 'blah'
86
110
  end
87
111
 
88
- specify "should parse types from the schema properly" do
112
+ cspecify "should parse types from the schema properly", [:jdbc, :db2], :oracle do
89
113
  INTEGRATION_DB.create_table!(:items){Integer :number}
90
114
  INTEGRATION_DB.schema(:items).first.last[:type].should == :integer
91
115
  INTEGRATION_DB.create_table!(:items){Fixnum :number}
@@ -156,7 +180,6 @@ describe "Database schema modifiers" do
156
180
  before do
157
181
  @db = INTEGRATION_DB
158
182
  @ds = @db[:items]
159
- clear_sqls
160
183
  end
161
184
  after do
162
185
  @db.drop_table(:items) if @db.table_exists?(:items)
@@ -174,6 +197,24 @@ describe "Database schema modifiers" do
174
197
  @db.create_table!(:items, :temp=>true){Integer :number}
175
198
  end
176
199
 
200
+ specify "should have create_table? only create the table if it doesn't already exist" do
201
+ @db.create_table!(:items){String :a}
202
+ @db.create_table?(:items){String :b}
203
+ @db[:items].columns.should == [:a]
204
+ @db.drop_table(:items) rescue nil
205
+ @db.create_table?(:items){String :b}
206
+ @db[:items].columns.should == [:b]
207
+ end
208
+
209
+ specify "should have create_table? work correctly with indexes" do
210
+ @db.create_table!(:items){String :a, :index=>true}
211
+ @db.create_table?(:items){String :b, :index=>true}
212
+ @db[:items].columns.should == [:a]
213
+ @db.drop_table(:items) rescue nil
214
+ @db.create_table?(:items){String :b, :index=>true}
215
+ @db[:items].columns.should == [:b]
216
+ end
217
+
177
218
  specify "should rename tables correctly" do
178
219
  @db.drop_table(:items) rescue nil
179
220
  @db.create_table!(:items2){Integer :number}
@@ -215,24 +256,34 @@ describe "Database schema modifiers" do
215
256
  specify "should add columns to tables correctly" do
216
257
  @db.create_table!(:items){Integer :number}
217
258
  @ds.insert(:number=>10)
218
- @db.alter_table(:items){add_column :name, :text}
259
+ @db.alter_table(:items){add_column :name, String}
219
260
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name]
220
261
  @ds.columns!.should == [:number, :name]
221
262
  @ds.all.should == [{:number=>10, :name=>nil}]
222
263
  end
223
264
 
224
- cspecify "should add primary key columns to tables correctly", :h2 do
265
+ cspecify "should add primary key columns to tables correctly", :h2, :derby do
225
266
  @db.create_table!(:items){Integer :number}
226
267
  @ds.insert(:number=>10)
227
268
  @db.alter_table(:items){add_primary_key :id}
228
269
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :id]
229
270
  @ds.columns!.should == [:number, :id]
230
271
  @ds.map(:number).should == [10]
272
+ proc{@ds.insert(:id=>@ds.map(:id).first)}.should raise_error
273
+ end
274
+
275
+ specify "should drop primary key constraints from tables correctly" do
276
+ @db.create_table!(:items){Integer :number; primary_key [:number], :name=>:items_pk}
277
+ @ds.insert(:number=>10)
278
+ @db.alter_table(:items){drop_constraint :items_pk, :type=>:primary_key}
279
+ @ds.map(:number).should == [10]
280
+ proc{@ds.insert(10)}.should_not raise_error
231
281
  end
232
282
 
233
283
  specify "should add foreign key columns to tables correctly" do
234
284
  @db.create_table!(:items){primary_key :id}
235
- i = @ds.insert
285
+ @ds.insert
286
+ i = @ds.get(:id)
236
287
  @db.alter_table(:items){add_foreign_key :item_id, :items}
237
288
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
238
289
  @ds.columns!.should == [:id, :item_id]
@@ -269,7 +320,7 @@ describe "Database schema modifiers" do
269
320
  proc{@ds.insert(:n=>nil)}.should raise_error(Sequel::DatabaseError)
270
321
  end
271
322
 
272
- specify "should set column NULL/NOT NULL correctly" do
323
+ cspecify "should set column NULL/NOT NULL correctly", [:jdbc, :db2], [:db2] do
273
324
  @db.create_table!(:items, :engine=>:InnoDB){Integer :id}
274
325
  @ds.insert(:id=>10)
275
326
  @db.alter_table(:items){set_column_allow_null :id, false}
@@ -277,7 +328,7 @@ describe "Database schema modifiers" do
277
328
  @ds.columns!.should == [:id]
278
329
  proc{@ds.insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
279
330
  @db.alter_table(:items){set_column_allow_null :id, true}
280
- @ds.insert
331
+ @ds.insert(:id=>nil)
281
332
  @ds.all.should == [{:id=>10}, {:id=>nil}]
282
333
  end
283
334
 
@@ -291,27 +342,60 @@ describe "Database schema modifiers" do
291
342
  @ds.all.should == [{:id=>10}, {:id=>20}]
292
343
  end
293
344
 
294
- specify "should set column types correctly" do
345
+ cspecify "should set column types correctly", [:jdbc, :db2], [:db2], :oracle do
295
346
  @db.create_table!(:items){Integer :id}
296
347
  @ds.insert(:id=>10)
297
348
  @db.alter_table(:items){set_column_type :id, String}
298
349
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
299
350
  @ds.columns!.should == [:id]
300
- @ds.insert(:id=>20)
351
+ @ds.insert(:id=>'20')
301
352
  @ds.all.should == [{:id=>"10"}, {:id=>"20"}]
302
353
  end
303
354
 
304
- cspecify "should add unique constraints and foreign key table constraints correctly", :sqlite do
305
- @db.create_table!(:items){Integer :id; Integer :item_id}
355
+ specify "should add unnamed unique constraints and foreign key table constraints correctly" do
356
+ @db.create_table!(:items, :engine=>:InnoDB){Integer :id; Integer :item_id}
306
357
  @db.alter_table(:items) do
307
358
  add_unique_constraint [:item_id, :id]
308
359
  add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
309
360
  end
310
361
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
311
362
  @ds.columns!.should == [:id, :item_id]
363
+ proc{@ds.insert(1, 1)}.should_not raise_error
364
+ proc{@ds.insert(1, 1)}.should raise_error
365
+ proc{@ds.insert(1, 2)}.should raise_error
366
+ end
367
+
368
+ specify "should add named unique constraints and foreign key table constraints correctly" do
369
+ @db.create_table!(:items, :engine=>:InnoDB){Integer :id, :null=>false; Integer :item_id, :null=>false}
370
+ @db.alter_table(:items) do
371
+ add_unique_constraint [:item_id, :id], :name=>:unique_iii
372
+ add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id], :name=>:fk_iii
373
+ end
374
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
375
+ @ds.columns!.should == [:id, :item_id]
376
+ proc{@ds.insert(1, 1)}.should_not raise_error
377
+ proc{@ds.insert(1, 1)}.should raise_error
378
+ proc{@ds.insert(1, 2)}.should raise_error
379
+ end
380
+
381
+ specify "should drop unique constraints and foreign key table constraints correctly" do
382
+ @db.create_table!(:items) do
383
+ Integer :id
384
+ Integer :item_id
385
+ unique [:item_id, :id], :name=>:items_uk
386
+ foreign_key [:id, :item_id], :items, :key=>[:item_id, :id], :name=>:items_fk
387
+ end
388
+ @db.alter_table(:items) do
389
+ drop_constraint(:items_fk, :type=>:foreign_key)
390
+ drop_constraint(:items_uk, :type=>:unique)
391
+ end
392
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
393
+ @ds.columns!.should == [:id, :item_id]
394
+ proc{@ds.insert(1, 2)}.should_not raise_error
395
+ proc{@ds.insert(1, 2)}.should_not raise_error
312
396
  end
313
397
 
314
- cspecify "should remove columns from tables correctly", :h2, :mssql do
398
+ cspecify "should remove columns from tables correctly", :h2, :mssql, [:jdbc, :db2], :hsqldb do
315
399
  @db.create_table!(:items) do
316
400
  primary_key :id
317
401
  String :name
@@ -332,7 +416,7 @@ describe "Database schema modifiers" do
332
416
  @ds.columns!.should == [:id]
333
417
  end
334
418
 
335
- specify "should remove multiple columns in a single alter_table block" do
419
+ cspecify "should remove multiple columns in a single alter_table block", [:jdbc, :db2] do
336
420
  @db.create_table!(:items) do
337
421
  primary_key :id
338
422
  String :name
@@ -362,25 +446,72 @@ describe "Database#tables" do
362
446
  "xxxxx#{@@xxxxx += 1}"
363
447
  end
364
448
  end
365
- @iom = INTEGRATION_DB.identifier_output_method
366
- @iim = INTEGRATION_DB.identifier_input_method
367
- clear_sqls
449
+ @db = INTEGRATION_DB
450
+ @db.create_table(:sequel_test_table){Integer :a}
451
+ @db.create_view :sequel_test_view, @db[:sequel_test_table]
452
+ @iom = @db.identifier_output_method
453
+ @iim = @db.identifier_input_method
368
454
  end
369
455
  after do
370
- INTEGRATION_DB.identifier_output_method = @iom
371
- INTEGRATION_DB.identifier_input_method = @iim
456
+ @db.identifier_output_method = @iom
457
+ @db.identifier_input_method = @iim
458
+ @db.drop_view :sequel_test_view
459
+ @db.drop_table :sequel_test_table
460
+ end
461
+
462
+ specify "should return an array of symbols" do
463
+ ts = @db.tables
464
+ ts.should be_a_kind_of(Array)
465
+ ts.each{|t| t.should be_a_kind_of(Symbol)}
466
+ ts.should include(:sequel_test_table)
467
+ ts.should_not include(:sequel_test_view)
468
+ end
469
+
470
+ specify "should respect the database's identifier_output_method" do
471
+ @db.identifier_output_method = :xxxxx
472
+ @db.identifier_input_method = :xxxxx
473
+ @db.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
474
+ end
475
+ end
476
+ end
477
+
478
+ begin
479
+ INTEGRATION_DB.views
480
+ rescue Sequel::NotImplemented
481
+ rescue
482
+ describe "Database#views" do
483
+ before do
484
+ class ::String
485
+ @@xxxxx = 0
486
+ def xxxxx
487
+ "xxxxx#{@@xxxxx += 1}"
488
+ end
489
+ end
490
+ @db = INTEGRATION_DB
491
+ @db.create_table(:sequel_test_table){Integer :a}
492
+ @db.create_view :sequel_test_view, @db[:sequel_test_table]
493
+ @iom = @db.identifier_output_method
494
+ @iim = @db.identifier_input_method
495
+ end
496
+ after do
497
+ @db.identifier_output_method = @iom
498
+ @db.identifier_input_method = @iim
499
+ @db.drop_view :sequel_test_view
500
+ @db.drop_table :sequel_test_table
372
501
  end
373
502
 
374
503
  specify "should return an array of symbols" do
375
- ts = INTEGRATION_DB.tables
504
+ ts = @db.views
376
505
  ts.should be_a_kind_of(Array)
377
506
  ts.each{|t| t.should be_a_kind_of(Symbol)}
507
+ ts.should_not include(:sequel_test_table)
508
+ ts.should include(:sequel_test_view)
378
509
  end
379
510
 
380
511
  specify "should respect the database's identifier_output_method" do
381
- INTEGRATION_DB.identifier_output_method = :xxxxx
382
- INTEGRATION_DB.identifier_input_method = :xxxxx
383
- INTEGRATION_DB.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
512
+ @db.identifier_output_method = :xxxxx
513
+ @db.identifier_input_method = :xxxxx
514
+ @db.views.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
384
515
  end
385
516
  end
386
517
  end
@@ -9,12 +9,12 @@ begin
9
9
  rescue LoadError
10
10
  end
11
11
 
12
- Sequel::Model.use_transactions = false
12
+ if ENV['SEQUEL_COLUMNS_INTROSPECTION']
13
+ Sequel.extension :columns_introspection
14
+ Sequel::Dataset.introspect_all_columns
15
+ end
13
16
 
14
- $sqls = []
15
- def clear_sqls
16
- $sqls.clear
17
- end
17
+ Sequel::Model.use_transactions = false
18
18
 
19
19
  unless defined?(RSpec)
20
20
  module Spec::Matchers
@@ -29,45 +29,45 @@ unless defined?(RSpec)
29
29
  end
30
30
  end
31
31
 
32
- (defined?(RSpec) ? RSpec::Core::ExampleGroup : Spec::Example::ExampleGroup).class_eval do
33
- def log
34
- begin
35
- INTEGRATION_DB.loggers << Logger.new(STDOUT)
36
- yield
37
- ensure
38
- INTEGRATION_DB.loggers.pop
39
- end
40
- end
41
-
42
- def self.log_specify(message, &block)
43
- specify(message){log{instance_eval(&block)}}
44
- end
45
-
46
- def self.cspecify(message, *checked, &block)
47
- pending = false
32
+ def Sequel.guarded?(*checked)
33
+ unless ENV['SEQUEL_NO_PENDING']
48
34
  checked.each do |c|
49
35
  case c
50
36
  when INTEGRATION_DB.database_type
51
- pending = c
37
+ return c
52
38
  when Array
53
39
  case c.length
54
40
  when 1
55
- pending = c if c.first == INTEGRATION_DB.adapter_scheme
41
+ return c if c.first == INTEGRATION_DB.adapter_scheme
56
42
  when 2
57
43
  if c.first.is_a?(Proc)
58
- pending = c if c.first.call(INTEGRATION_DB) && c.last == INTEGRATION_DB.database_type
44
+ return c if c.first.call(INTEGRATION_DB) && c.last == INTEGRATION_DB.database_type
59
45
  elsif c.last.is_a?(Proc)
60
- pending = c if c.first == INTEGRATION_DB.adapter_scheme && c.last.call(INTEGRATION_DB)
46
+ return c if c.first == INTEGRATION_DB.adapter_scheme && c.last.call(INTEGRATION_DB)
61
47
  else
62
- pending = c if c.first == INTEGRATION_DB.adapter_scheme && c.last == INTEGRATION_DB.database_type
48
+ return c if c.first == INTEGRATION_DB.adapter_scheme && c.last == INTEGRATION_DB.database_type
63
49
  end
64
50
  when 3
65
- pending = c if c[0] == INTEGRATION_DB.adapter_scheme && c[1] == INTEGRATION_DB.database_type && c[2].call(INTEGRATION_DB)
51
+ return c if c[0] == INTEGRATION_DB.adapter_scheme && c[1] == INTEGRATION_DB.database_type && c[2].call(INTEGRATION_DB)
66
52
  end
67
53
  end
68
- break if pending
69
54
  end
70
- if pending
55
+ end
56
+ false
57
+ end
58
+
59
+ (defined?(RSpec) ? RSpec::Core::ExampleGroup : Spec::Example::ExampleGroup).class_eval do
60
+ def log
61
+ begin
62
+ INTEGRATION_DB.loggers << Logger.new(STDOUT)
63
+ yield
64
+ ensure
65
+ INTEGRATION_DB.loggers.pop
66
+ end
67
+ end
68
+
69
+ def self.cspecify(message, *checked, &block)
70
+ if pending = Sequel.guarded?(*checked)
71
71
  specify(message){pending("Not yet working on #{Array(pending).join(', ')}", &block)}
72
72
  else
73
73
  specify(message, &block)
@@ -82,5 +82,14 @@ if defined?(INTEGRATION_DB) || defined?(INTEGRATION_URL) || ENV['SEQUEL_INTEGRAT
82
82
  #INTEGRATION_DB.instance_variable_set(:@server_version, 80100)
83
83
  end
84
84
  else
85
- INTEGRATION_DB = Sequel.sqlite('', :quote_identifiers=>false)
85
+ INTEGRATION_DB = Sequel.sqlite
86
+ end
87
+
88
+ if INTEGRATION_DB.adapter_scheme == :ibmdb
89
+ def INTEGRATION_DB.drop_table(*tables)
90
+ super
91
+ rescue Sequel::DatabaseError
92
+ disconnect
93
+ super
94
+ end
86
95
  end
@@ -1,15 +1,17 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  describe "Sequel timezone support" do
4
- def test_timezone
4
+ def test_timezone(timezone=Sequel.application_timezone)
5
+ tz = timezone
6
+ Sequel.datetime_class = Time
5
7
  # Tests should cover both DST and non-DST times.
6
8
  [Time.now, Time.local(2010,1,1,12), Time.local(2010,6,1,12)].each do |t|
7
9
  @db[:t].insert(t)
8
10
  t2 = @db[:t].single_value
9
- t2 = Sequel.database_to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
11
+ t2 = @db.to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
10
12
  (t2 - t).should be_within(2).of(0)
11
- t2.utc_offset.should == 0 if Sequel.application_timezone == :utc
12
- t2.utc_offset.should == t.getlocal.utc_offset if Sequel.application_timezone == :local
13
+ t2.utc_offset.should == 0 if timezone == :utc
14
+ t2.utc_offset.should == t.getlocal.utc_offset if timezone == :local
13
15
  @db[:t].delete
14
16
  end
15
17
 
@@ -19,10 +21,10 @@ describe "Sequel timezone support" do
19
21
  [DateTime.now, DateTime.civil(2010,1,1,12,0,0,local_std_offset), DateTime.civil(2010,6,1,12,0,0,local_dst_offset)].each do |dt|
20
22
  @db[:t].insert(dt)
21
23
  dt2 = @db[:t].single_value
22
- dt2 = Sequel.database_to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
24
+ dt2 = @db.to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
23
25
  (dt2 - dt).should be_within(0.00002).of(0)
24
- dt2.offset.should == 0 if Sequel.application_timezone == :utc
25
- dt2.offset.should == dt.offset if Sequel.application_timezone == :local
26
+ dt2.offset.should == 0 if timezone == :utc
27
+ dt2.offset.should == dt.offset if timezone == :local
26
28
  @db[:t].delete
27
29
  end
28
30
  end
@@ -32,30 +34,54 @@ describe "Sequel timezone support" do
32
34
  @db.create_table!(:t){DateTime :t}
33
35
  end
34
36
  after do
35
- @db.drop_table(:t)
37
+ @db.timezone = nil
36
38
  Sequel.default_timezone = nil
37
39
  Sequel.datetime_class = Time
40
+ @db.drop_table(:t)
38
41
  end
39
42
 
40
- cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, proc{|db| db.database_type != :sqlite}] do
43
+ cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
41
44
  Sequel.database_timezone = :utc
42
45
  Sequel.application_timezone = :local
43
46
  test_timezone
47
+ Sequel.database_timezone = nil
48
+ @db.timezone = :utc
49
+ test_timezone
44
50
  end
45
51
 
46
- cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, proc{|db| db.database_type != :sqlite}] do
52
+ cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
47
53
  Sequel.database_timezone = :local
48
54
  Sequel.application_timezone = :utc
49
55
  test_timezone
56
+ Sequel.database_timezone = nil
57
+ @db.timezone = :local
58
+ test_timezone
50
59
  end
51
60
 
52
- cspecify "should support using UTC for both database storage and for application", [:swift], [:do, proc{|db| db.database_type != :sqlite}] do
61
+ cspecify "should support using UTC for both database storage and for application", [:swift], [:do, :mysql], [:do, :postgres], [:oracle] do
53
62
  Sequel.default_timezone = :utc
54
63
  test_timezone
64
+ Sequel.database_timezone = :local
65
+ @db.timezone = :utc
66
+ test_timezone
55
67
  end
56
68
 
57
- cspecify "should support using local time for both database storage and for application", [:do, proc{|db| db.database_type != :sqlite}] do
69
+ cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle] do
58
70
  Sequel.default_timezone = :local
59
71
  test_timezone
72
+ Sequel.database_timezone = :utc
73
+ @db.timezone = :local
74
+ test_timezone
75
+ end
76
+
77
+ specify "should allow overriding the database_timezone on a per-database basis" do
78
+ Sequel.database_timezone = :utc
79
+ @db.timezone = :local
80
+ t = Time.now
81
+ @db[:t].insert(t)
82
+ s = @db[:t].get(:t.cast(String))
83
+ if o = Date._parse(s)[:offset]
84
+ o.should == t.utc_offset
85
+ end
60
86
  end
61
87
  end