sequel 3.21.0 → 3.32.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 (234) hide show
  1. data/CHANGELOG +539 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +20 -6
  4. data/Rakefile +37 -19
  5. data/bin/sequel +1 -5
  6. data/doc/advanced_associations.rdoc +17 -0
  7. data/doc/association_basics.rdoc +293 -43
  8. data/doc/dataset_basics.rdoc +4 -4
  9. data/doc/dataset_filtering.rdoc +8 -0
  10. data/doc/mass_assignment.rdoc +54 -0
  11. data/doc/migration.rdoc +15 -538
  12. data/doc/model_hooks.rdoc +72 -27
  13. data/doc/opening_databases.rdoc +89 -50
  14. data/doc/prepared_statements.rdoc +40 -13
  15. data/doc/reflection.rdoc +8 -2
  16. data/doc/release_notes/3.22.0.txt +39 -0
  17. data/doc/release_notes/3.23.0.txt +172 -0
  18. data/doc/release_notes/3.24.0.txt +420 -0
  19. data/doc/release_notes/3.25.0.txt +88 -0
  20. data/doc/release_notes/3.26.0.txt +88 -0
  21. data/doc/release_notes/3.27.0.txt +82 -0
  22. data/doc/release_notes/3.28.0.txt +304 -0
  23. data/doc/release_notes/3.29.0.txt +459 -0
  24. data/doc/release_notes/3.30.0.txt +135 -0
  25. data/doc/release_notes/3.31.0.txt +146 -0
  26. data/doc/release_notes/3.32.0.txt +202 -0
  27. data/doc/schema_modification.rdoc +547 -0
  28. data/doc/sharding.rdoc +7 -1
  29. data/doc/testing.rdoc +129 -0
  30. data/doc/transactions.rdoc +137 -0
  31. data/doc/virtual_rows.rdoc +2 -2
  32. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  33. data/lib/sequel/adapters/ado.rb +40 -18
  34. data/lib/sequel/adapters/amalgalite.rb +17 -9
  35. data/lib/sequel/adapters/db2.rb +175 -86
  36. data/lib/sequel/adapters/dbi.rb +15 -15
  37. data/lib/sequel/adapters/do/mysql.rb +5 -7
  38. data/lib/sequel/adapters/do/postgres.rb +0 -5
  39. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  40. data/lib/sequel/adapters/do.rb +17 -36
  41. data/lib/sequel/adapters/firebird.rb +27 -208
  42. data/lib/sequel/adapters/ibmdb.rb +448 -0
  43. data/lib/sequel/adapters/informix.rb +6 -23
  44. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  45. data/lib/sequel/adapters/jdbc/db2.rb +52 -0
  46. data/lib/sequel/adapters/jdbc/derby.rb +260 -0
  47. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  48. data/lib/sequel/adapters/jdbc/h2.rb +66 -30
  49. data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
  50. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  51. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  52. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  53. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  54. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  55. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  58. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  59. data/lib/sequel/adapters/jdbc.rb +231 -78
  60. data/lib/sequel/adapters/mock.rb +339 -0
  61. data/lib/sequel/adapters/mysql.rb +85 -184
  62. data/lib/sequel/adapters/mysql2.rb +26 -25
  63. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  64. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  65. data/lib/sequel/adapters/odbc.rb +28 -9
  66. data/lib/sequel/adapters/openbase.rb +3 -5
  67. data/lib/sequel/adapters/oracle.rb +355 -53
  68. data/lib/sequel/adapters/postgres.rb +194 -33
  69. data/lib/sequel/adapters/shared/access.rb +32 -9
  70. data/lib/sequel/adapters/shared/db2.rb +328 -0
  71. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  72. data/lib/sequel/adapters/shared/informix.rb +53 -0
  73. data/lib/sequel/adapters/shared/mssql.rb +278 -107
  74. data/lib/sequel/adapters/shared/mysql.rb +203 -65
  75. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  76. data/lib/sequel/adapters/shared/oracle.rb +237 -46
  77. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  78. data/lib/sequel/adapters/shared/progress.rb +5 -8
  79. data/lib/sequel/adapters/shared/sqlite.rb +200 -50
  80. data/lib/sequel/adapters/sqlite.rb +29 -21
  81. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  82. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  83. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  84. data/lib/sequel/adapters/swift.rb +5 -5
  85. data/lib/sequel/adapters/tinytds.rb +160 -19
  86. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  87. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  88. data/lib/sequel/ast_transformer.rb +190 -0
  89. data/lib/sequel/connection_pool/threaded.rb +3 -2
  90. data/lib/sequel/connection_pool.rb +1 -1
  91. data/lib/sequel/core.rb +68 -5
  92. data/lib/sequel/database/connecting.rb +5 -6
  93. data/lib/sequel/database/dataset.rb +4 -4
  94. data/lib/sequel/database/dataset_defaults.rb +59 -1
  95. data/lib/sequel/database/logging.rb +1 -1
  96. data/lib/sequel/database/misc.rb +104 -19
  97. data/lib/sequel/database/query.rb +163 -59
  98. data/lib/sequel/database/schema_generator.rb +17 -7
  99. data/lib/sequel/database/schema_methods.rb +59 -29
  100. data/lib/sequel/dataset/actions.rb +240 -76
  101. data/lib/sequel/dataset/features.rb +91 -8
  102. data/lib/sequel/dataset/graph.rb +38 -11
  103. data/lib/sequel/dataset/misc.rb +50 -23
  104. data/lib/sequel/dataset/mutation.rb +12 -7
  105. data/lib/sequel/dataset/prepared_statements.rb +59 -27
  106. data/lib/sequel/dataset/query.rb +236 -43
  107. data/lib/sequel/dataset/sql.rb +676 -267
  108. data/lib/sequel/dataset.rb +8 -0
  109. data/lib/sequel/exceptions.rb +4 -0
  110. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  111. data/lib/sequel/extensions/migration.rb +6 -4
  112. data/lib/sequel/extensions/named_timezones.rb +5 -0
  113. data/lib/sequel/extensions/query.rb +1 -1
  114. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  115. data/lib/sequel/extensions/to_dot.rb +95 -83
  116. data/lib/sequel/model/associations.rb +1081 -344
  117. data/lib/sequel/model/base.rb +420 -133
  118. data/lib/sequel/model/errors.rb +1 -1
  119. data/lib/sequel/model/exceptions.rb +5 -1
  120. data/lib/sequel/model.rb +20 -10
  121. data/lib/sequel/plugins/active_model.rb +13 -1
  122. data/lib/sequel/plugins/association_pks.rb +22 -4
  123. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  124. data/lib/sequel/plugins/composition.rb +43 -10
  125. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  126. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  127. data/lib/sequel/plugins/force_encoding.rb +6 -6
  128. data/lib/sequel/plugins/identity_map.rb +114 -7
  129. data/lib/sequel/plugins/many_through_many.rb +68 -7
  130. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  131. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  132. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  133. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  134. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  135. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  136. data/lib/sequel/plugins/serialization.rb +98 -49
  137. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  138. data/lib/sequel/plugins/sharding.rb +21 -54
  139. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  140. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  141. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  142. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  143. data/lib/sequel/sql.rb +109 -52
  144. data/lib/sequel/timezones.rb +57 -38
  145. data/lib/sequel/version.rb +1 -1
  146. data/spec/adapters/db2_spec.rb +146 -0
  147. data/spec/adapters/mssql_spec.rb +135 -30
  148. data/spec/adapters/mysql_spec.rb +244 -212
  149. data/spec/adapters/oracle_spec.rb +67 -77
  150. data/spec/adapters/postgres_spec.rb +267 -78
  151. data/spec/adapters/spec_helper.rb +6 -5
  152. data/spec/adapters/sqlite_spec.rb +35 -21
  153. data/spec/core/connection_pool_spec.rb +71 -92
  154. data/spec/core/core_sql_spec.rb +21 -30
  155. data/spec/core/database_spec.rb +789 -512
  156. data/spec/core/dataset_spec.rb +1176 -1061
  157. data/spec/core/expression_filters_spec.rb +159 -42
  158. data/spec/core/mock_adapter_spec.rb +419 -0
  159. data/spec/core/object_graph_spec.rb +86 -114
  160. data/spec/core/schema_generator_spec.rb +3 -3
  161. data/spec/core/schema_spec.rb +298 -38
  162. data/spec/core/spec_helper.rb +6 -48
  163. data/spec/extensions/active_model_spec.rb +13 -0
  164. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  165. data/spec/extensions/association_dependencies_spec.rb +2 -12
  166. data/spec/extensions/association_pks_spec.rb +66 -32
  167. data/spec/extensions/caching_spec.rb +23 -50
  168. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  169. data/spec/extensions/columns_introspection_spec.rb +91 -0
  170. data/spec/extensions/composition_spec.rb +18 -13
  171. data/spec/extensions/dataset_associations_spec.rb +199 -0
  172. data/spec/extensions/defaults_setter_spec.rb +64 -0
  173. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  174. data/spec/extensions/identity_map_spec.rb +114 -22
  175. data/spec/extensions/instance_filters_spec.rb +11 -21
  176. data/spec/extensions/instance_hooks_spec.rb +53 -0
  177. data/spec/extensions/json_serializer_spec.rb +4 -5
  178. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  179. data/spec/extensions/list_spec.rb +17 -39
  180. data/spec/extensions/many_through_many_spec.rb +283 -250
  181. data/spec/extensions/migration_spec.rb +35 -32
  182. data/spec/extensions/named_timezones_spec.rb +23 -3
  183. data/spec/extensions/nested_attributes_spec.rb +97 -88
  184. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  185. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  186. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  187. data/spec/extensions/prepared_statements_spec.rb +53 -0
  188. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  189. data/spec/extensions/pretty_table_spec.rb +1 -6
  190. data/spec/extensions/query_spec.rb +6 -0
  191. data/spec/extensions/rcte_tree_spec.rb +41 -43
  192. data/spec/extensions/schema_dumper_spec.rb +5 -8
  193. data/spec/extensions/schema_spec.rb +13 -21
  194. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  195. data/spec/extensions/serialization_spec.rb +81 -43
  196. data/spec/extensions/sharding_spec.rb +66 -140
  197. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  198. data/spec/extensions/spec_helper.rb +13 -61
  199. data/spec/extensions/sql_expr_spec.rb +20 -60
  200. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  201. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  202. data/spec/extensions/timestamps_spec.rb +6 -6
  203. data/spec/extensions/to_dot_spec.rb +4 -7
  204. data/spec/extensions/touch_spec.rb +13 -14
  205. data/spec/extensions/tree_spec.rb +11 -26
  206. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  207. data/spec/extensions/update_primary_key_spec.rb +30 -24
  208. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  209. data/spec/extensions/validation_helpers_spec.rb +16 -35
  210. data/spec/extensions/xml_serializer_spec.rb +16 -4
  211. data/spec/integration/associations_test.rb +661 -21
  212. data/spec/integration/database_test.rb +4 -2
  213. data/spec/integration/dataset_test.rb +500 -67
  214. data/spec/integration/eager_loader_test.rb +19 -21
  215. data/spec/integration/model_test.rb +80 -1
  216. data/spec/integration/plugin_test.rb +367 -119
  217. data/spec/integration/prepared_statement_test.rb +222 -125
  218. data/spec/integration/schema_test.rb +217 -39
  219. data/spec/integration/spec_helper.rb +39 -30
  220. data/spec/integration/timezone_test.rb +38 -12
  221. data/spec/integration/transaction_test.rb +182 -5
  222. data/spec/integration/type_test.rb +17 -3
  223. data/spec/model/association_reflection_spec.rb +201 -7
  224. data/spec/model/associations_spec.rb +955 -662
  225. data/spec/model/base_spec.rb +275 -95
  226. data/spec/model/dataset_methods_spec.rb +7 -27
  227. data/spec/model/eager_loading_spec.rb +677 -676
  228. data/spec/model/hooks_spec.rb +349 -67
  229. data/spec/model/model_spec.rb +222 -168
  230. data/spec/model/plugins_spec.rb +24 -13
  231. data/spec/model/record_spec.rb +381 -218
  232. data/spec/model/spec_helper.rb +13 -71
  233. data/spec/model/validations_spec.rb +11 -0
  234. metadata +117 -73
@@ -1,35 +1,59 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
- if INTEGRATION_DB.respond_to?(:schema_parse_table, true)
4
3
  describe "Database schema parser" do
5
4
  before do
6
5
  @iom = INTEGRATION_DB.identifier_output_method
7
6
  @iim = INTEGRATION_DB.identifier_input_method
8
7
  @defsch = INTEGRATION_DB.default_schema
9
- clear_sqls
8
+ @qi = INTEGRATION_DB.quote_identifiers?
10
9
  end
11
10
  after do
12
11
  INTEGRATION_DB.identifier_output_method = @iom
13
12
  INTEGRATION_DB.identifier_input_method = @iim
14
13
  INTEGRATION_DB.default_schema = @defsch
14
+ INTEGRATION_DB.quote_identifiers = @qi
15
15
  INTEGRATION_DB.drop_table(:items) if INTEGRATION_DB.table_exists?(:items)
16
16
  end
17
17
 
18
- specify "should handle a database with a identifier_output_method" do
18
+ specify "should handle a database with a identifier methods" do
19
19
  INTEGRATION_DB.identifier_output_method = :reverse
20
20
  INTEGRATION_DB.identifier_input_method = :reverse
21
+ INTEGRATION_DB.quote_identifiers = true
21
22
  INTEGRATION_DB.default_schema = nil if INTEGRATION_DB.default_schema
22
23
  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
24
+ begin
25
+ INTEGRATION_DB.schema(:items, :reload=>true).should be_a_kind_of(Array)
26
+ INTEGRATION_DB.schema(:items, :reload=>true).first.first.should == :number
27
+ ensure
28
+ INTEGRATION_DB.drop_table(:items)
29
+ end
30
+ end
31
+
32
+ specify "should handle a dataset with identifier methods different than the database's" do
33
+ INTEGRATION_DB.identifier_output_method = :reverse
34
+ INTEGRATION_DB.identifier_input_method = :reverse
35
+ INTEGRATION_DB.quote_identifiers = true
36
+ INTEGRATION_DB.default_schema = nil if INTEGRATION_DB.default_schema
37
+ INTEGRATION_DB.create_table!(:items){Integer :number}
38
+ INTEGRATION_DB.identifier_output_method = @iom
39
+ INTEGRATION_DB.identifier_input_method = @iim
40
+ ds = INTEGRATION_DB[:items]
41
+ ds.identifier_output_method = :reverse
42
+ ds.identifier_input_method = :reverse
43
+ begin
44
+ INTEGRATION_DB.schema(ds, :reload=>true).should be_a_kind_of(Array)
45
+ INTEGRATION_DB.schema(ds, :reload=>true).first.first.should == :number
46
+ ensure
47
+ INTEGRATION_DB.identifier_output_method = :reverse
48
+ INTEGRATION_DB.identifier_input_method = :reverse
49
+ INTEGRATION_DB.drop_table(:items)
50
+ end
25
51
  end
26
52
 
27
53
  specify "should not issue an sql query if the schema has been loaded unless :reload is true" do
28
54
  INTEGRATION_DB.create_table!(:items){Integer :number}
29
55
  INTEGRATION_DB.schema(:items, :reload=>true)
30
- clear_sqls
31
56
  INTEGRATION_DB.schema(:items)
32
- clear_sqls
33
57
  INTEGRATION_DB.schema(:items, :reload=>true)
34
58
  end
35
59
 
@@ -56,11 +80,10 @@ describe "Database schema parser" do
56
80
  col_info = col.last
57
81
  col_info.should be_a_kind_of(Hash)
58
82
  col_info[:type].should == :integer
59
- clear_sqls
60
83
  INTEGRATION_DB.schema(:items)
61
84
  end
62
85
 
63
- cspecify "should parse primary keys from the schema properly", [proc{|db| db.adapter_scheme != :jdbc}, :mssql] do
86
+ specify "should parse primary keys from the schema properly" do
64
87
  INTEGRATION_DB.create_table!(:items){Integer :number}
65
88
  INTEGRATION_DB.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == []
66
89
  INTEGRATION_DB.create_table!(:items){primary_key :number}
@@ -85,7 +108,7 @@ describe "Database schema parser" do
85
108
  INTEGRATION_DB.schema(:items).first.last[:ruby_default].should == 'blah'
86
109
  end
87
110
 
88
- specify "should parse types from the schema properly" do
111
+ cspecify "should parse types from the schema properly", [:jdbc, :db2], :oracle do
89
112
  INTEGRATION_DB.create_table!(:items){Integer :number}
90
113
  INTEGRATION_DB.schema(:items).first.last[:type].should == :integer
91
114
  INTEGRATION_DB.create_table!(:items){Fixnum :number}
@@ -113,14 +136,17 @@ describe "Database schema parser" do
113
136
  INTEGRATION_DB.create_table!(:items){FalseClass :number}
114
137
  INTEGRATION_DB.schema(:items).first.last[:type].should == :boolean
115
138
  end
116
- end
117
- end
139
+ end if INTEGRATION_DB.respond_to?(:schema_parse_table, true)
118
140
 
119
- begin
141
+ test_indexes = begin
120
142
  INTEGRATION_DB.drop_table(:blah) rescue nil
121
143
  INTEGRATION_DB.indexes(:blah)
144
+ true
122
145
  rescue Sequel::NotImplemented
146
+ false
123
147
  rescue
148
+ true
149
+ end
124
150
  describe "Database index parsing" do
125
151
  after do
126
152
  INTEGRATION_DB.drop_table(:items)
@@ -149,14 +175,12 @@ describe "Database index parsing" do
149
175
  INTEGRATION_DB.create_table!(:items){Integer :n; Integer :a; primary_key [:n, :a]}
150
176
  INTEGRATION_DB.indexes(:items).should == {}
151
177
  end
152
- end
153
- end
178
+ end if test_indexes
154
179
 
155
180
  describe "Database schema modifiers" do
156
181
  before do
157
182
  @db = INTEGRATION_DB
158
183
  @ds = @db[:items]
159
- clear_sqls
160
184
  end
161
185
  after do
162
186
  @db.drop_table(:items) if @db.table_exists?(:items)
@@ -174,6 +198,24 @@ describe "Database schema modifiers" do
174
198
  @db.create_table!(:items, :temp=>true){Integer :number}
175
199
  end
176
200
 
201
+ specify "should have create_table? only create the table if it doesn't already exist" do
202
+ @db.create_table!(:items){String :a}
203
+ @db.create_table?(:items){String :b}
204
+ @db[:items].columns.should == [:a]
205
+ @db.drop_table(:items) rescue nil
206
+ @db.create_table?(:items){String :b}
207
+ @db[:items].columns.should == [:b]
208
+ end
209
+
210
+ specify "should have create_table? work correctly with indexes" do
211
+ @db.create_table!(:items){String :a, :index=>true}
212
+ @db.create_table?(:items){String :b, :index=>true}
213
+ @db[:items].columns.should == [:a]
214
+ @db.drop_table(:items) rescue nil
215
+ @db.create_table?(:items){String :b, :index=>true}
216
+ @db[:items].columns.should == [:b]
217
+ end
218
+
177
219
  specify "should rename tables correctly" do
178
220
  @db.drop_table(:items) rescue nil
179
221
  @db.create_table!(:items2){Integer :number}
@@ -215,24 +257,34 @@ describe "Database schema modifiers" do
215
257
  specify "should add columns to tables correctly" do
216
258
  @db.create_table!(:items){Integer :number}
217
259
  @ds.insert(:number=>10)
218
- @db.alter_table(:items){add_column :name, :text}
260
+ @db.alter_table(:items){add_column :name, String}
219
261
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name]
220
262
  @ds.columns!.should == [:number, :name]
221
263
  @ds.all.should == [{:number=>10, :name=>nil}]
222
264
  end
223
265
 
224
- cspecify "should add primary key columns to tables correctly", :h2 do
266
+ cspecify "should add primary key columns to tables correctly", :h2, :derby do
225
267
  @db.create_table!(:items){Integer :number}
226
268
  @ds.insert(:number=>10)
227
269
  @db.alter_table(:items){add_primary_key :id}
228
270
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :id]
229
271
  @ds.columns!.should == [:number, :id]
230
272
  @ds.map(:number).should == [10]
273
+ proc{@ds.insert(:id=>@ds.map(:id).first)}.should raise_error
274
+ end
275
+
276
+ specify "should drop primary key constraints from tables correctly" do
277
+ @db.create_table!(:items){Integer :number; primary_key [:number], :name=>:items_pk}
278
+ @ds.insert(:number=>10)
279
+ @db.alter_table(:items){drop_constraint :items_pk, :type=>:primary_key}
280
+ @ds.map(:number).should == [10]
281
+ proc{@ds.insert(10)}.should_not raise_error
231
282
  end
232
283
 
233
284
  specify "should add foreign key columns to tables correctly" do
234
285
  @db.create_table!(:items){primary_key :id}
235
- i = @ds.insert
286
+ @ds.insert
287
+ i = @ds.get(:id)
236
288
  @db.alter_table(:items){add_foreign_key :item_id, :items}
237
289
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
238
290
  @ds.columns!.should == [:id, :item_id]
@@ -269,7 +321,22 @@ describe "Database schema modifiers" do
269
321
  proc{@ds.insert(:n=>nil)}.should raise_error(Sequel::DatabaseError)
270
322
  end
271
323
 
272
- specify "should set column NULL/NOT NULL correctly" do
324
+ specify "should rename columns when the table is referenced by a foreign key" do
325
+ begin
326
+ @db.create_table!(:itemsfk){primary_key :id; Integer :a}
327
+ @db.create_table!(:items){foreign_key :id, :itemsfk}
328
+ @db[:itemsfk].insert(:a=>10)
329
+ @ds.insert(:id=>1)
330
+ @db.alter_table(:itemsfk){rename_column :a, :b}
331
+ @db[:itemsfk].insert(:b=>20)
332
+ @ds.insert(:id=>2)
333
+ @db[:itemsfk].select_order_map([:id, :b]).should == [[1, 10], [2, 20]]
334
+ ensure
335
+ @db.drop_table(:items, :itemsfk)
336
+ end
337
+ end
338
+
339
+ cspecify "should set column NULL/NOT NULL correctly", [:jdbc, :db2], [:db2] do
273
340
  @db.create_table!(:items, :engine=>:InnoDB){Integer :id}
274
341
  @ds.insert(:id=>10)
275
342
  @db.alter_table(:items){set_column_allow_null :id, false}
@@ -277,7 +344,7 @@ describe "Database schema modifiers" do
277
344
  @ds.columns!.should == [:id]
278
345
  proc{@ds.insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
279
346
  @db.alter_table(:items){set_column_allow_null :id, true}
280
- @ds.insert
347
+ @ds.insert(:id=>nil)
281
348
  @ds.all.should == [{:id=>10}, {:id=>nil}]
282
349
  end
283
350
 
@@ -291,27 +358,89 @@ describe "Database schema modifiers" do
291
358
  @ds.all.should == [{:id=>10}, {:id=>20}]
292
359
  end
293
360
 
294
- specify "should set column types correctly" do
361
+ cspecify "should set column types correctly", [:jdbc, :db2], [:db2], :oracle do
295
362
  @db.create_table!(:items){Integer :id}
296
363
  @ds.insert(:id=>10)
297
364
  @db.alter_table(:items){set_column_type :id, String}
298
365
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
299
366
  @ds.columns!.should == [:id]
300
- @ds.insert(:id=>20)
367
+ @ds.insert(:id=>'20')
301
368
  @ds.all.should == [{:id=>"10"}, {:id=>"20"}]
302
369
  end
303
370
 
304
- cspecify "should add unique constraints and foreign key table constraints correctly", :sqlite do
305
- @db.create_table!(:items){Integer :id; Integer :item_id}
371
+ cspecify "should set column types without modifying NULL/NOT NULL", [:jdbc, :db2], [:db2], :oracle, :derby do
372
+ @db.create_table!(:items){Integer :id, :null=>false, :default=>2}
373
+ proc{@ds.insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
374
+ @db.alter_table(:items){set_column_type :id, String}
375
+ proc{@ds.insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
376
+
377
+ @db.create_table!(:items){Integer :id}
378
+ @ds.insert(:id=>nil)
379
+ @db.alter_table(:items){set_column_type :id, String}
380
+ @ds.insert(:id=>nil)
381
+ @ds.map(:id).should == [nil, nil]
382
+ end
383
+
384
+ cspecify "should set column types without modifying defaults", [:jdbc, :db2], [:db2], :oracle, :derby do
385
+ @db.create_table!(:items){Integer :id, :default=>0}
386
+ @ds.insert
387
+ @ds.map(:id).should == [0]
388
+ @db.alter_table(:items){set_column_type :id, String}
389
+ @ds.insert
390
+ @ds.map(:id).should == ['0', '0']
391
+
392
+ @db.create_table!(:items){String :id, :default=>'a'}
393
+ @ds.insert
394
+ @ds.map(:id).should == %w'a'
395
+ @db.alter_table(:items){set_column_type :id, String, :size=>1}
396
+ @ds.insert
397
+ @ds.map(:id).should == %w'a a'
398
+ end
399
+
400
+ specify "should add unnamed unique constraints and foreign key table constraints correctly" do
401
+ @db.create_table!(:items, :engine=>:InnoDB){Integer :id; Integer :item_id}
306
402
  @db.alter_table(:items) do
307
403
  add_unique_constraint [:item_id, :id]
308
404
  add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
309
405
  end
310
406
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
311
407
  @ds.columns!.should == [:id, :item_id]
408
+ proc{@ds.insert(1, 1)}.should_not raise_error
409
+ proc{@ds.insert(1, 1)}.should raise_error
410
+ proc{@ds.insert(1, 2)}.should raise_error
411
+ end
412
+
413
+ specify "should add named unique constraints and foreign key table constraints correctly" do
414
+ @db.create_table!(:items, :engine=>:InnoDB){Integer :id, :null=>false; Integer :item_id, :null=>false}
415
+ @db.alter_table(:items) do
416
+ add_unique_constraint [:item_id, :id], :name=>:unique_iii
417
+ add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id], :name=>:fk_iii
418
+ end
419
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
420
+ @ds.columns!.should == [:id, :item_id]
421
+ proc{@ds.insert(1, 1)}.should_not raise_error
422
+ proc{@ds.insert(1, 1)}.should raise_error
423
+ proc{@ds.insert(1, 2)}.should raise_error
424
+ end
425
+
426
+ specify "should drop unique constraints and foreign key table constraints correctly" do
427
+ @db.create_table!(:items) do
428
+ Integer :id
429
+ Integer :item_id
430
+ unique [:item_id, :id], :name=>:items_uk
431
+ foreign_key [:id, :item_id], :items, :key=>[:item_id, :id], :name=>:items_fk
432
+ end
433
+ @db.alter_table(:items) do
434
+ drop_constraint(:items_fk, :type=>:foreign_key)
435
+ drop_constraint(:items_uk, :type=>:unique)
436
+ end
437
+ @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
438
+ @ds.columns!.should == [:id, :item_id]
439
+ proc{@ds.insert(1, 2)}.should_not raise_error
440
+ proc{@ds.insert(1, 2)}.should_not raise_error
312
441
  end
313
442
 
314
- cspecify "should remove columns from tables correctly", :h2, :mssql do
443
+ cspecify "should remove columns from tables correctly", :h2, :mssql, [:jdbc, :db2], :hsqldb do
315
444
  @db.create_table!(:items) do
316
445
  primary_key :id
317
446
  String :name
@@ -332,7 +461,7 @@ describe "Database schema modifiers" do
332
461
  @ds.columns!.should == [:id]
333
462
  end
334
463
 
335
- specify "should remove multiple columns in a single alter_table block" do
464
+ cspecify "should remove multiple columns in a single alter_table block", [:jdbc, :db2] do
336
465
  @db.create_table!(:items) do
337
466
  primary_key :id
338
467
  String :name
@@ -350,10 +479,12 @@ describe "Database schema modifiers" do
350
479
  end
351
480
  end
352
481
 
353
- begin
482
+ test_tables = begin
354
483
  INTEGRATION_DB.tables
484
+ true
355
485
  rescue Sequel::NotImplemented
356
- rescue
486
+ false
487
+ end
357
488
  describe "Database#tables" do
358
489
  before do
359
490
  class ::String
@@ -362,25 +493,72 @@ describe "Database#tables" do
362
493
  "xxxxx#{@@xxxxx += 1}"
363
494
  end
364
495
  end
365
- @iom = INTEGRATION_DB.identifier_output_method
366
- @iim = INTEGRATION_DB.identifier_input_method
367
- clear_sqls
496
+ @db = INTEGRATION_DB
497
+ @db.create_table(:sequel_test_table){Integer :a}
498
+ @db.create_view :sequel_test_view, @db[:sequel_test_table]
499
+ @iom = @db.identifier_output_method
500
+ @iim = @db.identifier_input_method
368
501
  end
369
502
  after do
370
- INTEGRATION_DB.identifier_output_method = @iom
371
- INTEGRATION_DB.identifier_input_method = @iim
503
+ @db.identifier_output_method = @iom
504
+ @db.identifier_input_method = @iim
505
+ @db.drop_view :sequel_test_view
506
+ @db.drop_table :sequel_test_table
372
507
  end
373
508
 
374
509
  specify "should return an array of symbols" do
375
- ts = INTEGRATION_DB.tables
510
+ ts = @db.tables
376
511
  ts.should be_a_kind_of(Array)
377
512
  ts.each{|t| t.should be_a_kind_of(Symbol)}
513
+ ts.should include(:sequel_test_table)
514
+ ts.should_not include(:sequel_test_view)
378
515
  end
379
516
 
380
517
  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/}
518
+ @db.identifier_output_method = :xxxxx
519
+ @db.identifier_input_method = :xxxxx
520
+ @db.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
384
521
  end
522
+ end if test_tables
523
+
524
+ test_views = begin
525
+ INTEGRATION_DB.views
526
+ true
527
+ rescue Sequel::NotImplemented
528
+ false
385
529
  end
386
- end
530
+ describe "Database#views" do
531
+ before do
532
+ class ::String
533
+ @@xxxxx = 0
534
+ def xxxxx
535
+ "xxxxx#{@@xxxxx += 1}"
536
+ end
537
+ end
538
+ @db = INTEGRATION_DB
539
+ @db.create_table(:sequel_test_table){Integer :a}
540
+ @db.create_view :sequel_test_view, @db[:sequel_test_table]
541
+ @iom = @db.identifier_output_method
542
+ @iim = @db.identifier_input_method
543
+ end
544
+ after do
545
+ @db.identifier_output_method = @iom
546
+ @db.identifier_input_method = @iim
547
+ @db.drop_view :sequel_test_view
548
+ @db.drop_table :sequel_test_table
549
+ end
550
+
551
+ specify "should return an array of symbols" do
552
+ ts = @db.views
553
+ ts.should be_a_kind_of(Array)
554
+ ts.each{|t| t.should be_a_kind_of(Symbol)}
555
+ ts.should_not include(:sequel_test_table)
556
+ ts.should include(:sequel_test_view)
557
+ end
558
+
559
+ specify "should respect the database's identifier_output_method" do
560
+ @db.identifier_output_method = :xxxxx
561
+ @db.identifier_input_method = :xxxxx
562
+ @db.views.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
563
+ end
564
+ end if test_views
@@ -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