sequel 3.33.0 → 3.34.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 (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