sequel 3.33.0 → 3.34.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/CHANGELOG +140 -0
  2. data/Rakefile +7 -0
  3. data/bin/sequel +22 -2
  4. data/doc/dataset_basics.rdoc +1 -1
  5. data/doc/mass_assignment.rdoc +3 -1
  6. data/doc/querying.rdoc +28 -4
  7. data/doc/reflection.rdoc +23 -3
  8. data/doc/release_notes/3.34.0.txt +671 -0
  9. data/doc/schema_modification.rdoc +18 -2
  10. data/doc/virtual_rows.rdoc +49 -0
  11. data/lib/sequel/adapters/do/mysql.rb +0 -5
  12. data/lib/sequel/adapters/ibmdb.rb +9 -4
  13. data/lib/sequel/adapters/jdbc.rb +9 -4
  14. data/lib/sequel/adapters/jdbc/h2.rb +8 -2
  15. data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
  16. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -0
  17. data/lib/sequel/adapters/jdbc/sqlite.rb +19 -0
  18. data/lib/sequel/adapters/mock.rb +24 -3
  19. data/lib/sequel/adapters/mysql.rb +29 -50
  20. data/lib/sequel/adapters/mysql2.rb +13 -28
  21. data/lib/sequel/adapters/oracle.rb +8 -2
  22. data/lib/sequel/adapters/postgres.rb +115 -20
  23. data/lib/sequel/adapters/shared/db2.rb +1 -1
  24. data/lib/sequel/adapters/shared/mssql.rb +14 -3
  25. data/lib/sequel/adapters/shared/mysql.rb +59 -11
  26. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  27. data/lib/sequel/adapters/shared/oracle.rb +1 -1
  28. data/lib/sequel/adapters/shared/postgres.rb +127 -30
  29. data/lib/sequel/adapters/shared/sqlite.rb +55 -38
  30. data/lib/sequel/adapters/sqlite.rb +9 -3
  31. data/lib/sequel/adapters/swift.rb +2 -2
  32. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  33. data/lib/sequel/adapters/swift/postgres.rb +10 -0
  34. data/lib/sequel/ast_transformer.rb +4 -0
  35. data/lib/sequel/connection_pool.rb +8 -0
  36. data/lib/sequel/connection_pool/sharded_single.rb +5 -0
  37. data/lib/sequel/connection_pool/sharded_threaded.rb +17 -0
  38. data/lib/sequel/connection_pool/single.rb +5 -0
  39. data/lib/sequel/connection_pool/threaded.rb +14 -0
  40. data/lib/sequel/core.rb +24 -3
  41. data/lib/sequel/database/connecting.rb +24 -14
  42. data/lib/sequel/database/dataset_defaults.rb +1 -0
  43. data/lib/sequel/database/misc.rb +16 -25
  44. data/lib/sequel/database/query.rb +20 -2
  45. data/lib/sequel/database/schema_generator.rb +2 -2
  46. data/lib/sequel/database/schema_methods.rb +120 -23
  47. data/lib/sequel/dataset/actions.rb +91 -18
  48. data/lib/sequel/dataset/features.rb +5 -0
  49. data/lib/sequel/dataset/prepared_statements.rb +6 -2
  50. data/lib/sequel/dataset/sql.rb +68 -51
  51. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  52. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +18 -13
  53. data/lib/sequel/extensions/migration.rb +4 -0
  54. data/lib/sequel/extensions/null_dataset.rb +90 -0
  55. data/lib/sequel/extensions/pg_array.rb +460 -0
  56. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  57. data/lib/sequel/extensions/pg_auto_parameterize.rb +174 -0
  58. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  59. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  60. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  61. data/lib/sequel/extensions/pretty_table.rb +5 -71
  62. data/lib/sequel/extensions/query_literals.rb +79 -0
  63. data/lib/sequel/extensions/schema_caching.rb +76 -0
  64. data/lib/sequel/extensions/schema_dumper.rb +227 -31
  65. data/lib/sequel/extensions/select_remove.rb +35 -0
  66. data/lib/sequel/extensions/sql_expr.rb +4 -110
  67. data/lib/sequel/extensions/to_dot.rb +1 -1
  68. data/lib/sequel/model.rb +11 -2
  69. data/lib/sequel/model/associations.rb +35 -7
  70. data/lib/sequel/model/base.rb +159 -36
  71. data/lib/sequel/no_core_ext.rb +2 -0
  72. data/lib/sequel/plugins/caching.rb +25 -18
  73. data/lib/sequel/plugins/composition.rb +1 -1
  74. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  75. data/lib/sequel/plugins/identity_map.rb +11 -3
  76. data/lib/sequel/plugins/instance_filters.rb +10 -0
  77. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  78. data/lib/sequel/plugins/nested_attributes.rb +4 -3
  79. data/lib/sequel/plugins/prepared_statements.rb +3 -1
  80. data/lib/sequel/plugins/prepared_statements_associations.rb +5 -1
  81. data/lib/sequel/plugins/schema.rb +7 -2
  82. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  83. data/lib/sequel/plugins/static_cache.rb +99 -0
  84. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  85. data/lib/sequel/sql.rb +417 -7
  86. data/lib/sequel/version.rb +1 -1
  87. data/spec/adapters/firebird_spec.rb +1 -1
  88. data/spec/adapters/mssql_spec.rb +12 -15
  89. data/spec/adapters/mysql_spec.rb +81 -23
  90. data/spec/adapters/postgres_spec.rb +444 -77
  91. data/spec/adapters/spec_helper.rb +2 -0
  92. data/spec/adapters/sqlite_spec.rb +8 -8
  93. data/spec/core/connection_pool_spec.rb +85 -0
  94. data/spec/core/database_spec.rb +29 -5
  95. data/spec/core/dataset_spec.rb +171 -3
  96. data/spec/core/expression_filters_spec.rb +364 -0
  97. data/spec/core/mock_adapter_spec.rb +17 -3
  98. data/spec/core/schema_spec.rb +133 -0
  99. data/spec/extensions/association_dependencies_spec.rb +13 -13
  100. data/spec/extensions/caching_spec.rb +26 -3
  101. data/spec/extensions/class_table_inheritance_spec.rb +2 -2
  102. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +23 -94
  103. data/spec/extensions/force_encoding_spec.rb +4 -2
  104. data/spec/extensions/hook_class_methods_spec.rb +5 -2
  105. data/spec/extensions/identity_map_spec.rb +17 -0
  106. data/spec/extensions/instance_filters_spec.rb +1 -1
  107. data/spec/extensions/lazy_attributes_spec.rb +2 -2
  108. data/spec/extensions/list_spec.rb +4 -4
  109. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  110. data/spec/extensions/migration_spec.rb +6 -2
  111. data/spec/extensions/nested_attributes_spec.rb +20 -0
  112. data/spec/extensions/null_dataset_spec.rb +85 -0
  113. data/spec/extensions/optimistic_locking_spec.rb +2 -2
  114. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  115. data/spec/extensions/pg_array_spec.rb +196 -0
  116. data/spec/extensions/pg_auto_parameterize_spec.rb +64 -0
  117. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  118. data/spec/extensions/pg_hstore_spec.rb +195 -0
  119. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  120. data/spec/extensions/prepared_statements_spec.rb +4 -0
  121. data/spec/extensions/pretty_table_spec.rb +6 -0
  122. data/spec/extensions/query_literals_spec.rb +168 -0
  123. data/spec/extensions/schema_caching_spec.rb +41 -0
  124. data/spec/extensions/schema_dumper_spec.rb +231 -11
  125. data/spec/extensions/schema_spec.rb +14 -2
  126. data/spec/extensions/select_remove_spec.rb +38 -0
  127. data/spec/extensions/sharding_spec.rb +6 -6
  128. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  129. data/spec/extensions/spec_helper.rb +2 -1
  130. data/spec/extensions/sql_expr_spec.rb +28 -19
  131. data/spec/extensions/static_cache_spec.rb +145 -0
  132. data/spec/extensions/touch_spec.rb +1 -1
  133. data/spec/extensions/typecast_on_load_spec.rb +9 -1
  134. data/spec/integration/associations_test.rb +6 -6
  135. data/spec/integration/database_test.rb +1 -1
  136. data/spec/integration/dataset_test.rb +89 -26
  137. data/spec/integration/migrator_test.rb +2 -3
  138. data/spec/integration/model_test.rb +3 -3
  139. data/spec/integration/plugin_test.rb +85 -22
  140. data/spec/integration/prepared_statement_test.rb +28 -8
  141. data/spec/integration/schema_test.rb +78 -7
  142. data/spec/integration/spec_helper.rb +1 -0
  143. data/spec/integration/timezone_test.rb +1 -1
  144. data/spec/integration/transaction_test.rb +4 -6
  145. data/spec/integration/type_test.rb +2 -2
  146. data/spec/model/associations_spec.rb +94 -8
  147. data/spec/model/base_spec.rb +4 -4
  148. data/spec/model/hooks_spec.rb +2 -2
  149. data/spec/model/model_spec.rb +19 -7
  150. data/spec/model/record_spec.rb +135 -58
  151. data/spec/model/spec_helper.rb +1 -0
  152. metadata +35 -7
@@ -13,7 +13,7 @@ describe "Prepared Statements and Bound Arguments" do
13
13
  @pr = @ds.requires_placeholder_type_specifiers? ? proc{|i| :"#{i}__integer"} : proc{|i| i}
14
14
  end
15
15
  after do
16
- @db.drop_table(:items)
16
+ @db.drop_table?(:items)
17
17
  end
18
18
 
19
19
  specify "should support bound variables when selecting" do
@@ -22,6 +22,7 @@ describe "Prepared Statements and Bound Arguments" do
22
22
  @ds.filter(:numb=>:$n).call(:first, :n=>10).should == {:id=>1, :numb=>10}
23
23
  @ds.filter(:numb=>:$n).call([:map, :numb], :n=>10).should == [10]
24
24
  @ds.filter(:numb=>:$n).call([:to_hash, :id, :numb], :n=>10).should == {1=>10}
25
+ @ds.filter(:numb=>:$n).call([:to_hash_groups, :id, :numb], :n=>10).should == {1=>[10]}
25
26
  end
26
27
 
27
28
  specify "should support blocks for select, all, and map " do
@@ -252,16 +253,16 @@ describe "Bound Argument Types" do
252
253
  end
253
254
  @ds = @db[:items]
254
255
  @vs = {:d=>Date.civil(2010, 10, 11), :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(20101010), :file=>Sequel::SQL::Blob.new('blob'), :b=>true}
256
+ end
257
+ before do
258
+ @ds.delete
255
259
  @ds.insert(@vs)
256
- @ds.meta_def(:ba) do |sym, type|
257
- prepared_arg_placeholder == '$' ? :"#{sym}__#{type}" : sym
258
- end
259
260
  end
260
261
  after do
261
262
  Sequel.datetime_class = Time
262
263
  end
263
264
  after(:all) do
264
- @db.drop_table(:items)
265
+ @db.drop_table?(:items)
265
266
  end
266
267
 
267
268
  cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite], :oracle do
@@ -273,14 +274,33 @@ describe "Bound Argument Types" do
273
274
  @ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
274
275
  end
275
276
 
276
- cspecify "should handle time type", [:do], [:jdbc, :sqlite], [:oracle] do
277
+ cspecify "should handle datetime type with fractional seconds", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds], [:oracle] do
278
+ Sequel.datetime_class = DateTime
279
+ fract_time = DateTime.parse('2010-10-12 13:14:15.500000')
280
+ @ds.prepare(:update, :ps_datetime_up, :dt=>:$x).call(:x=>fract_time)
281
+ @ds.literal(@ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>fract_time)[:dt]).should == @ds.literal(fract_time)
282
+ end
283
+
284
+ cspecify "should handle time type", [:do], [:jdbc, :sqlite], [:swift], [:oracle] do
277
285
  @ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
278
286
  end
279
287
 
288
+ cspecify "should handle time type with fractional seconds", [:do], [:jdbc, :sqlite], [:oracle] do
289
+ fract_time = @vs[:t] + 0.5
290
+ @ds.prepare(:update, :ps_time_up, :t=>:$x).call(:x=>fract_time)
291
+ @ds.literal(@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>fract_time)[:t]).should == @ds.literal(fract_time)
292
+ end
293
+
280
294
  cspecify "should handle blob type", [:swift], [:odbc], [:jdbc, :db2], :oracle, :derby do
281
295
  @ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
282
296
  end
283
297
 
298
+ cspecify "should handle blob type with embedded zeros", [:swift], [:odbc], [:jdbc, :db2], :oracle, :derby do
299
+ zero_blob = Sequel::SQL::Blob.new("a\0"*100)
300
+ @ds.prepare(:update, :ps_blob_up, :file=>:$x).call(:x=>zero_blob)
301
+ @ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>zero_blob)[:file].should == zero_blob
302
+ end
303
+
284
304
  cspecify "should handle float type", [:swift, :sqlite] do
285
305
  @ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
286
306
  end
@@ -306,7 +326,7 @@ describe "Dataset#unbind" do
306
326
  @u = proc{|ds| ds, bv = ds.unbind; ds.call(:first, bv)}
307
327
  end
308
328
  after do
309
- INTEGRATION_DB.drop_table(:items) rescue nil
329
+ INTEGRATION_DB.drop_table?(:items)
310
330
  end
311
331
 
312
332
  specify "should unbind values assigned to equality and inequality statements" do
@@ -334,7 +354,7 @@ describe "Dataset#unbind" do
334
354
  @u[@ds.filter{c > 0}].should == {:c=>BigDecimal.new('1.1')}
335
355
  end
336
356
 
337
- cspecify "should handle dates and times", [:do], [:jdbc, :mssql], [:jdbc, :sqlite], [:tinytds], :oracle do
357
+ cspecify "should handle dates and times", [:do], [:jdbc, :mssql], [:jdbc, :sqlite], [:swift], [:tinytds], :oracle do
338
358
  @ct[Date, Date.today]
339
359
  @u[@ds.filter(:c=>Date.today)].should == {:c=>Date.today}
340
360
  t = Time.now
@@ -12,7 +12,7 @@ describe "Database schema parser" do
12
12
  INTEGRATION_DB.identifier_input_method = @iim
13
13
  INTEGRATION_DB.default_schema = @defsch
14
14
  INTEGRATION_DB.quote_identifiers = @qi
15
- INTEGRATION_DB.drop_table(:items) if INTEGRATION_DB.table_exists?(:items)
15
+ INTEGRATION_DB.drop_table?(:items)
16
16
  end
17
17
 
18
18
  specify "should handle a database with a identifier methods" do
@@ -139,7 +139,7 @@ describe "Database schema parser" do
139
139
  end if INTEGRATION_DB.respond_to?(:schema_parse_table, true)
140
140
 
141
141
  test_indexes = begin
142
- INTEGRATION_DB.drop_table(:blah) rescue nil
142
+ INTEGRATION_DB.drop_table?(:blah)
143
143
  INTEGRATION_DB.indexes(:blah)
144
144
  true
145
145
  rescue Sequel::NotImplemented
@@ -149,7 +149,7 @@ rescue
149
149
  end
150
150
  describe "Database index parsing" do
151
151
  after do
152
- INTEGRATION_DB.drop_table(:items)
152
+ INTEGRATION_DB.drop_table?(:items)
153
153
  end
154
154
 
155
155
  specify "should parse indexes into a hash" do
@@ -177,13 +177,69 @@ describe "Database index parsing" do
177
177
  end
178
178
  end if test_indexes
179
179
 
180
+ test_foreign_key_list = begin
181
+ INTEGRATION_DB.drop_table?(:blah)
182
+ INTEGRATION_DB.foreign_key_list(:blah)
183
+ true
184
+ rescue Sequel::NotImplemented
185
+ false
186
+ rescue
187
+ true
188
+ end
189
+ describe "Database foreign key parsing" do
190
+ before do
191
+ @db = INTEGRATION_DB
192
+ @pr = lambda do |table, *expected|
193
+ actual = @db.foreign_key_list(table).sort_by{|c| c[:columns].map{|s| s.to_s}.join << (c[:key]||[]).map{|s| s.to_s}.join}.map{|v| v.values_at(:columns, :table, :key)}
194
+ actual.zip(expected).each do |a, e|
195
+ if e.last.first == :pk
196
+ if a.last == nil
197
+ a.pop
198
+ e.pop
199
+ else
200
+ e.last.shift
201
+ end
202
+ end
203
+ a.should == e
204
+ end
205
+ actual.length.should == expected.length
206
+ end
207
+ end
208
+ after do
209
+ @db.drop_table?(:b, :a)
210
+ end
211
+
212
+ specify "should parse foreign key information into an array of hashes" do
213
+ @db.create_table!(:a, :engine=>:InnoDB){primary_key :c; Integer :d; index :d, :unique=>true}
214
+ @db.create_table!(:b, :engine=>:InnoDB){foreign_key :e, :a}
215
+ @pr[:a]
216
+ @pr[:b, [[:e], :a, [:pk, :c]]]
217
+
218
+ @db.alter_table(:b){add_foreign_key :f, :a, :key=>[:d]}
219
+ @pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:d]]]
220
+
221
+ @db.alter_table(:b){add_foreign_key [:f], :a, :key=>[:c]}
222
+ @pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:c]], [[:f], :a, [:d]]]
223
+
224
+ @db.alter_table(:a){add_index [:d, :c], :unique=>true}
225
+ @db.alter_table(:b){add_foreign_key [:f, :e], :a, :key=>[:d, :c]}
226
+ @pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:c]], [[:f], :a, [:d]], [[:f, :e], :a, [:d, :c]]]
227
+ end
228
+
229
+ specify "should handle composite foreign and primary keys" do
230
+ @db.create_table!(:a, :engine=>:InnoDB){Integer :b; Integer :c; primary_key [:b, :c]; index [:c, :b], :unique=>true}
231
+ @db.create_table!(:b, :engine=>:InnoDB){Integer :e; Integer :f; foreign_key [:e, :f], :a; foreign_key [:f, :e], :a, :key=>[:c, :b]}
232
+ @pr[:b, [[:e, :f], :a, [:pk, :b, :c]], [[:f, :e], :a, [:c, :b]]]
233
+ end
234
+ end if test_foreign_key_list
235
+
180
236
  describe "Database schema modifiers" do
181
237
  before do
182
238
  @db = INTEGRATION_DB
183
239
  @ds = @db[:items]
184
240
  end
185
241
  after do
186
- @db.drop_table(:items) if @db.table_exists?(:items)
242
+ @db.drop_table?(:items)
187
243
  end
188
244
 
189
245
  specify "should create tables correctly" do
@@ -194,6 +250,21 @@ describe "Database schema modifiers" do
194
250
  @ds.columns!.should == [:number]
195
251
  end
196
252
 
253
+ describe "join tables" do
254
+ after do
255
+ @db.drop_join_table(:cat_id=>:cats, :dog_id=>:dogs) if @db.table_exists?(:cats_dogs)
256
+ @db.drop_table(:cats, :dogs)
257
+ @db.table_exists?(:cats_dogs).should == false
258
+ end
259
+
260
+ specify "should create join tables correctly" do
261
+ @db.create_table!(:cats){primary_key :id}
262
+ @db.create_table!(:dogs){primary_key :id}
263
+ @db.create_join_table(:cat_id=>:cats, :dog_id=>:dogs)
264
+ @db.table_exists?(:cats_dogs).should == true
265
+ end
266
+ end
267
+
197
268
  specify "should create temporary tables without raising an exception" do
198
269
  @db.create_table!(:items, :temp=>true){Integer :number}
199
270
  end
@@ -202,7 +273,7 @@ describe "Database schema modifiers" do
202
273
  @db.create_table!(:items){String :a}
203
274
  @db.create_table?(:items){String :b}
204
275
  @db[:items].columns.should == [:a]
205
- @db.drop_table(:items) rescue nil
276
+ @db.drop_table?(:items)
206
277
  @db.create_table?(:items){String :b}
207
278
  @db[:items].columns.should == [:b]
208
279
  end
@@ -211,13 +282,13 @@ describe "Database schema modifiers" do
211
282
  @db.create_table!(:items){String :a, :index=>true}
212
283
  @db.create_table?(:items){String :b, :index=>true}
213
284
  @db[:items].columns.should == [:a]
214
- @db.drop_table(:items) rescue nil
285
+ @db.drop_table?(:items)
215
286
  @db.create_table?(:items){String :b, :index=>true}
216
287
  @db[:items].columns.should == [:b]
217
288
  end
218
289
 
219
290
  specify "should rename tables correctly" do
220
- @db.drop_table(:items) rescue nil
291
+ @db.drop_table?(:items)
221
292
  @db.create_table!(:items2){Integer :number}
222
293
  @db.rename_table(:items2, :items)
223
294
  @db.table_exists?(:items).should == true
@@ -15,6 +15,7 @@ if ENV['SEQUEL_COLUMNS_INTROSPECTION']
15
15
  end
16
16
 
17
17
  Sequel::Model.use_transactions = false
18
+ Sequel::Model.cache_anonymous_models = false
18
19
 
19
20
  unless defined?(RSpec)
20
21
  module Spec::Matchers
@@ -66,7 +66,7 @@ describe "Sequel timezone support" do
66
66
  test_timezone
67
67
  end
68
68
 
69
- cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle] do
69
+ cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle], [:swift, :postgres], [:swift, :mysql] do
70
70
  Sequel.default_timezone = :local
71
71
  test_timezone
72
72
  Sequel.database_timezone = :utc
@@ -3,15 +3,14 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
3
3
  describe "Database transactions" do
4
4
  before(:all) do
5
5
  @db = INTEGRATION_DB
6
- @db.drop_table(:items) if @db.table_exists?(:items)
7
- @db.create_table(:items, :engine=>'InnoDB'){String :name; Integer :value}
6
+ @db.create_table!(:items, :engine=>'InnoDB'){String :name; Integer :value}
8
7
  @d = @db[:items]
9
8
  end
10
9
  before do
11
10
  @d.delete
12
11
  end
13
12
  after(:all) do
14
- @db.drop_table(:items) if @db.table_exists?(:items)
13
+ @db.drop_table?(:items)
15
14
  end
16
15
 
17
16
  specify "should support transactions" do
@@ -265,12 +264,11 @@ if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' &&
265
264
  describe "Database transactions and Thread#kill" do
266
265
  before do
267
266
  @db = INTEGRATION_DB
268
- @db.drop_table(:items) if @db.table_exists?(:items)
269
- @db.create_table(:items, :engine=>'InnoDB'){String :name; Integer :value}
267
+ @db.create_table!(:items, :engine=>'InnoDB'){String :name; Integer :value}
270
268
  @d = @db[:items]
271
269
  end
272
270
  after do
273
- @db.drop_table(:items) if @db.table_exists?(:items)
271
+ @db.drop_table?(:items)
274
272
  end
275
273
 
276
274
  specify "should handle transactions inside threads" do
@@ -33,7 +33,7 @@ describe "Supported types" do
33
33
  ds.all.should == [{:number=>2}]
34
34
  end
35
35
 
36
- specify "should support generic bignum type" do
36
+ cspecify "should support generic bignum type", [:swift, :sqlite] do
37
37
  ds = create_items_table_with_column(:number, Bignum)
38
38
  ds.insert(:number => 2**34)
39
39
  ds.all.should == [{:number=>2**34}]
@@ -68,7 +68,7 @@ describe "Supported types" do
68
68
  ds.first[:dat].to_s.should == d.to_s
69
69
  end
70
70
 
71
- cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :postgres], [:jdbc, :sqlite], [:mysql2], [:tinytds], :oracle do
71
+ cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :sqlite], [:mysql2], [:tinytds], :oracle do
72
72
  ds = create_items_table_with_column(:tim, Time, :only_time=>true)
73
73
  t = Sequel::SQLTime.now
74
74
  ds.insert(:tim => t)
@@ -653,7 +653,7 @@ describe Sequel::Model, "one_to_one" do
653
653
  it "should add a setter method" do
654
654
  @c2.one_to_one :attribute, :class => @c1
655
655
  attrib = @c1.new(:id=>3)
656
- @c1.dataset._fetch = {:id=>3}
656
+ @c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>3}
657
657
  @c2.new(:id => 1234).attribute = attrib
658
658
  sqls = MODEL_DB.sqls
659
659
  ['INSERT INTO attributes (node_id, id) VALUES (1234, 3)',
@@ -692,7 +692,7 @@ describe Sequel::Model, "one_to_one" do
692
692
  it "should have the setter method respect the :primary_key option" do
693
693
  @c2.one_to_one :attribute, :class => @c1, :primary_key=>:xxx
694
694
  attrib = @c1.new(:id=>3)
695
- @c1.dataset._fetch = {:id=>3}
695
+ @c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>3}
696
696
  @c2.new(:id => 1234, :xxx=>5).attribute = attrib
697
697
  sqls = MODEL_DB.sqls
698
698
  ['INSERT INTO attributes (node_id, id) VALUES (5, 3)',
@@ -836,7 +836,7 @@ describe Sequel::Model, "one_to_one" do
836
836
 
837
837
  d = @c2.new(:id => 1)
838
838
  f = @c2.new(:id => 3, :node_id=> 4321)
839
- @c2.dataset._fetch = {:id => 3, :node_id=>1}
839
+ @c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 3, :node_id=>1}
840
840
  d.parent = f
841
841
  f.values.should == {:id => 3, :node_id=>1}
842
842
  d.parent.should == f
@@ -854,7 +854,7 @@ describe Sequel::Model, "one_to_one" do
854
854
  @c2.one_to_one :parent, :class => @c2, :primary_key=>:blah
855
855
  d = @c2.new(:id => 1, :blah => 3)
856
856
  e = @c2.new(:id => 4321, :node_id=>444)
857
- @c2.dataset._fetch = {:id => 4321, :node_id => 3}
857
+ @c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 4321, :node_id => 3}
858
858
  d.parent = e
859
859
  e.values.should == {:id => 4321, :node_id => 3}
860
860
  sqls = MODEL_DB.sqls
@@ -867,7 +867,7 @@ describe Sequel::Model, "one_to_one" do
867
867
  @c2.one_to_one :parent, :class => @c2, :key=>:blah
868
868
  d = @c2.new(:id => 3)
869
869
  e = @c2.new(:id => 4321, :blah=>444)
870
- @c2.dataset._fetch = {:id => 4321, :blah => 3}
870
+ @c2.dataset._fetch = @c2.instance_dataset._fetch = {:id => 4321, :blah => 3}
871
871
  d.parent = e
872
872
  e.values.should == {:id => 4321, :blah => 3}
873
873
  sqls = MODEL_DB.sqls
@@ -1181,7 +1181,7 @@ describe Sequel::Model, "one_to_many" do
1181
1181
 
1182
1182
  n = @c2.load(:id => 1234)
1183
1183
  a = @c1.new(:id => 234)
1184
- @c1.dataset._fetch = {:node_id => 1234, :id => 234}
1184
+ @c1.dataset._fetch = @c1.instance_dataset._fetch = {:node_id => 1234, :id => 234}
1185
1185
  a.should == n.add_attribute(a)
1186
1186
  sqls = MODEL_DB.sqls
1187
1187
  sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
@@ -1213,7 +1213,7 @@ describe Sequel::Model, "one_to_many" do
1213
1213
  @c2.one_to_many :attributes, :class => @c1
1214
1214
  n = @c2.new(:id => 1234)
1215
1215
  MODEL_DB.reset
1216
- @c1.dataset._fetch = {:node_id => 1234, :id => 234}
1216
+ @c1.dataset._fetch = @c1.instance_dataset._fetch = {:node_id => 1234, :id => 234}
1217
1217
  n.add_attribute(:id => 234).should == @c1.load(:node_id => 1234, :id => 234)
1218
1218
  sqls = MODEL_DB.sqls
1219
1219
  sqls.shift.should =~ /INSERT INTO attributes \((node_)?id, (node_)?id\) VALUES \(1?234, 1?234\)/
@@ -1969,7 +1969,7 @@ describe Sequel::Model, "many_to_many" do
1969
1969
  @c2.many_to_many :attributes, :class => @c1
1970
1970
 
1971
1971
  n = @c2.load(:id => 1234)
1972
- @c1.dataset._fetch = {:id=>1}
1972
+ @c1.dataset._fetch = @c1.instance_dataset._fetch = {:id=>1}
1973
1973
  n.add_attribute(:id => 1).should == @c1.load(:id => 1)
1974
1974
  sqls = MODEL_DB.sqls
1975
1975
  ['INSERT INTO attributes_nodes (node_id, attribute_id) VALUES (1234, 1)',
@@ -3017,3 +3017,89 @@ describe "Sequel::Model Associations with clashing column names" do
3017
3017
  @bar.mtmfoos.should == []
3018
3018
  end
3019
3019
  end
3020
+
3021
+ describe "Model#pk_or_nil" do
3022
+ before do
3023
+ @m = Class.new(Sequel::Model)
3024
+ @m.columns :id, :x, :y
3025
+ end
3026
+
3027
+ it "should be default return the value of the :id column" do
3028
+ m = @m.load(:id => 111, :x => 2, :y => 3)
3029
+ m.pk_or_nil.should == 111
3030
+ end
3031
+
3032
+ it "should be return the primary key value for custom primary key" do
3033
+ @m.set_primary_key :x
3034
+ m = @m.load(:id => 111, :x => 2, :y => 3)
3035
+ m.pk_or_nil.should == 2
3036
+ end
3037
+
3038
+ it "should be return the primary key value for composite primary key" do
3039
+ @m.set_primary_key [:y, :x]
3040
+ m = @m.load(:id => 111, :x => 2, :y => 3)
3041
+ m.pk_or_nil.should == [3, 2]
3042
+ end
3043
+
3044
+ it "should raise if no primary key" do
3045
+ @m.set_primary_key nil
3046
+ m = @m.new(:id => 111, :x => 2, :y => 3)
3047
+ m.pk_or_nil.should be_nil
3048
+
3049
+ @m.no_primary_key
3050
+ m = @m.new(:id => 111, :x => 2, :y => 3)
3051
+ m.pk_or_nil.should be_nil
3052
+ end
3053
+ end
3054
+
3055
+ describe Sequel::Model, "#refresh" do
3056
+ before do
3057
+ @c = Class.new(Sequel::Model(:items)) do
3058
+ unrestrict_primary_key
3059
+ columns :id, :x
3060
+ end
3061
+ MODEL_DB.reset
3062
+ end
3063
+
3064
+ specify "should remove cached associations" do
3065
+ @c.many_to_one :node, :class=>@c
3066
+ @m = @c.new(:id => 555)
3067
+ @m.associations[:node] = 15
3068
+ @m.reload
3069
+ @m.associations.should == {}
3070
+ end
3071
+ end
3072
+
3073
+ describe "Model#freeze" do
3074
+ before do
3075
+ class ::Album < Sequel::Model
3076
+ columns :id
3077
+ class B < Sequel::Model
3078
+ columns :id, :album_id
3079
+ many_to_one :album, :class=>Album
3080
+ end
3081
+ one_to_one :b, :key=>:album_id, :class=>B
3082
+ end
3083
+ @o = Album.load(:id=>1).freeze
3084
+ MODEL_DB.sqls
3085
+ end
3086
+ after do
3087
+ Object.send(:remove_const, :Album)
3088
+ end
3089
+
3090
+ it "should freeze the object's associations" do
3091
+ @o.associations.frozen?.should be_true
3092
+ end
3093
+
3094
+ it "should not break associations getters" do
3095
+ Album::B.dataset._fetch = {:album_id=>1, :id=>2}
3096
+ @o.b.should == Album::B.load(:id=>2, :album_id=>1)
3097
+ @o.associations[:b].should be_nil
3098
+ end
3099
+
3100
+ it "should not break reciprocal associations" do
3101
+ b = Album::B.load(:id=>2, :album_id=>nil)
3102
+ b.album = @o
3103
+ @o.associations[:b].should be_nil
3104
+ end
3105
+ end