sequel 3.23.0 → 3.24.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 (76) hide show
  1. data/CHANGELOG +64 -0
  2. data/doc/association_basics.rdoc +43 -5
  3. data/doc/model_hooks.rdoc +64 -27
  4. data/doc/prepared_statements.rdoc +8 -4
  5. data/doc/reflection.rdoc +8 -2
  6. data/doc/release_notes/3.23.0.txt +1 -1
  7. data/doc/release_notes/3.24.0.txt +420 -0
  8. data/lib/sequel/adapters/db2.rb +8 -1
  9. data/lib/sequel/adapters/firebird.rb +25 -9
  10. data/lib/sequel/adapters/informix.rb +4 -19
  11. data/lib/sequel/adapters/jdbc.rb +34 -17
  12. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  13. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  14. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  15. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  16. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  17. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  18. data/lib/sequel/adapters/postgres.rb +30 -1
  19. data/lib/sequel/adapters/shared/access.rb +10 -0
  20. data/lib/sequel/adapters/shared/informix.rb +45 -0
  21. data/lib/sequel/adapters/shared/mssql.rb +82 -8
  22. data/lib/sequel/adapters/shared/mysql.rb +25 -7
  23. data/lib/sequel/adapters/shared/postgres.rb +39 -6
  24. data/lib/sequel/adapters/shared/sqlite.rb +57 -5
  25. data/lib/sequel/adapters/sqlite.rb +8 -3
  26. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  27. data/lib/sequel/ast_transformer.rb +190 -0
  28. data/lib/sequel/core.rb +1 -1
  29. data/lib/sequel/database/misc.rb +6 -0
  30. data/lib/sequel/database/query.rb +33 -3
  31. data/lib/sequel/database/schema_methods.rb +6 -2
  32. data/lib/sequel/dataset/features.rb +6 -0
  33. data/lib/sequel/dataset/prepared_statements.rb +17 -2
  34. data/lib/sequel/dataset/query.rb +17 -0
  35. data/lib/sequel/dataset/sql.rb +2 -53
  36. data/lib/sequel/exceptions.rb +4 -0
  37. data/lib/sequel/extensions/to_dot.rb +95 -83
  38. data/lib/sequel/model.rb +5 -0
  39. data/lib/sequel/model/associations.rb +80 -14
  40. data/lib/sequel/model/base.rb +182 -55
  41. data/lib/sequel/model/exceptions.rb +3 -1
  42. data/lib/sequel/plugins/association_pks.rb +6 -4
  43. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  44. data/lib/sequel/plugins/many_through_many.rb +8 -3
  45. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  46. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  47. data/lib/sequel/plugins/prepared_statements_safe.rb +72 -0
  48. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  49. data/lib/sequel/sql.rb +8 -0
  50. data/lib/sequel/version.rb +1 -1
  51. data/spec/adapters/postgres_spec.rb +43 -18
  52. data/spec/core/connection_pool_spec.rb +56 -77
  53. data/spec/core/database_spec.rb +25 -0
  54. data/spec/core/dataset_spec.rb +127 -16
  55. data/spec/core/expression_filters_spec.rb +13 -0
  56. data/spec/core/schema_spec.rb +6 -1
  57. data/spec/extensions/association_pks_spec.rb +7 -0
  58. data/spec/extensions/defaults_setter_spec.rb +64 -0
  59. data/spec/extensions/many_through_many_spec.rb +60 -4
  60. data/spec/extensions/nested_attributes_spec.rb +1 -0
  61. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  62. data/spec/extensions/prepared_statements_safe_spec.rb +69 -0
  63. data/spec/extensions/prepared_statements_spec.rb +72 -0
  64. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  65. data/spec/extensions/to_dot_spec.rb +3 -5
  66. data/spec/integration/associations_test.rb +155 -1
  67. data/spec/integration/dataset_test.rb +8 -1
  68. data/spec/integration/plugin_test.rb +119 -0
  69. data/spec/integration/prepared_statement_test.rb +72 -1
  70. data/spec/integration/schema_test.rb +66 -8
  71. data/spec/integration/transaction_test.rb +40 -0
  72. data/spec/model/associations_spec.rb +349 -8
  73. data/spec/model/base_spec.rb +59 -0
  74. data/spec/model/hooks_spec.rb +161 -0
  75. data/spec/model/record_spec.rb +24 -0
  76. metadata +21 -4
@@ -485,3 +485,62 @@ describe Sequel::Model, ".[] optimization" do
485
485
  @c[1]
486
486
  end
487
487
  end
488
+
489
+ describe "Model datasets #with_pk" do
490
+ before do
491
+ @c = Class.new(Sequel::Model(:a))
492
+ @ds = @c.dataset
493
+ def @ds.fetch_rows(sql)
494
+ db << sql
495
+ yield(:id=>1)
496
+ end
497
+ @sqls = MODEL_DB.sqls
498
+ @sqls.clear
499
+ end
500
+
501
+ it "should return the first record where the primary key matches" do
502
+ @ds.with_pk(1).should == @c.load(:id=>1)
503
+ @sqls.should == ["SELECT * FROM a WHERE (id = 1) LIMIT 1"]
504
+ end
505
+
506
+ it "should handle existing filters" do
507
+ @ds.filter(:a=>2).with_pk(1)
508
+ @sqls.should == ["SELECT * FROM a WHERE ((a = 2) AND (id = 1)) LIMIT 1"]
509
+ end
510
+
511
+ it "should work with string values" do
512
+ @ds.with_pk("foo")
513
+ @sqls.should == ["SELECT * FROM a WHERE (id = 'foo') LIMIT 1"]
514
+ end
515
+
516
+ it "should handle an array for composite primary keys" do
517
+ @c.set_primary_key :id1, :id2
518
+ @ds.with_pk([1, 2])
519
+ @sqls.should == ["SELECT * FROM a WHERE ((id1 = 1) AND (id2 = 2)) LIMIT 1"]
520
+ end
521
+
522
+ it "should raise an error if a single primary key is given when a composite primary key should be used" do
523
+ @c.set_primary_key :id1, :id2
524
+ proc{@ds.with_pk(1)}.should raise_error(Sequel::Error)
525
+ end
526
+
527
+ it "should raise an error if a composite primary key is given when a single primary key should be used" do
528
+ proc{@ds.with_pk([1, 2])}.should raise_error(Sequel::Error)
529
+ end
530
+
531
+ it "should raise an error if the wrong number of composite keys is given" do
532
+ @c.set_primary_key :id1, :id2
533
+ proc{@ds.with_pk([1, 2, 3])}.should raise_error(Sequel::Error)
534
+ end
535
+
536
+ it "should have #[] consider an integer as a primary key lookup" do
537
+ @ds[1].should == @c.load(:id=>1)
538
+ @sqls.should == ["SELECT * FROM a WHERE (id = 1) LIMIT 1"]
539
+ end
540
+
541
+ it "should not have #[] consider a string as a primary key lookup" do
542
+ @ds['foo'].should == @c.load(:id=>1)
543
+ @sqls.should == ["SELECT * FROM a WHERE (foo) LIMIT 1"]
544
+ end
545
+
546
+ end
@@ -268,4 +268,165 @@ describe "Model#before_validation && Model#after_validation" do
268
268
  @c.load(:id => 2233).save.should == nil
269
269
  MODEL_DB.sqls.should == []
270
270
  end
271
+
272
+ specify "#valid? should return false if before_validation returns false" do
273
+ @c.send(:define_method, :before_validation){false}
274
+ @c.load(:id => 2233).valid?.should == false
275
+ end
276
+ end
277
+
278
+ describe "Model around filters" do
279
+ before do
280
+ MODEL_DB.reset
281
+
282
+ @c = Class.new(Sequel::Model(:items))
283
+ @c.class_eval do
284
+ columns :id, :x
285
+ def _save_refresh(*a) end
286
+ end
287
+ end
288
+
289
+ specify "around_create should be called around new record creation" do
290
+ @c.class_eval do
291
+ def around_create
292
+ MODEL_DB << 'ac_before'
293
+ super
294
+ MODEL_DB << 'ac_after'
295
+ end
296
+ end
297
+ @c.create(:x => 2)
298
+ MODEL_DB.sqls.should == [ 'ac_before', 'INSERT INTO items (x) VALUES (2)', 'ac_after' ]
299
+ end
300
+
301
+ specify "around_delete should be called around record destruction" do
302
+ @c.class_eval do
303
+ def around_destroy
304
+ MODEL_DB << 'ad_before'
305
+ super
306
+ MODEL_DB << 'ad_after'
307
+ end
308
+ end
309
+ @c.load(:id=>1, :x => 2).destroy
310
+ MODEL_DB.sqls.should == [ 'ad_before', 'DELETE FROM items WHERE (id = 1)', 'ad_after' ]
311
+ end
312
+
313
+ specify "around_update should be called around updating existing records" do
314
+ @c.class_eval do
315
+ def around_update
316
+ MODEL_DB << 'au_before'
317
+ super
318
+ MODEL_DB << 'au_after'
319
+ end
320
+ end
321
+ @c.load(:id=>1, :x => 2).save
322
+ MODEL_DB.sqls.should == [ 'au_before', 'UPDATE items SET x = 2 WHERE (id = 1)', 'au_after' ]
323
+ end
324
+
325
+ specify "around_update should be called around saving both new and existing records, around either after_create and after_update" do
326
+ @c.class_eval do
327
+ def around_update
328
+ MODEL_DB << 'au_before'
329
+ super
330
+ MODEL_DB << 'au_after'
331
+ end
332
+ def around_create
333
+ MODEL_DB << 'ac_before'
334
+ super
335
+ MODEL_DB << 'ac_after'
336
+ end
337
+ def around_save
338
+ MODEL_DB << 'as_before'
339
+ super
340
+ MODEL_DB << 'as_after'
341
+ end
342
+ end
343
+ @c.create(:x => 2)
344
+ MODEL_DB.sqls.should == [ 'as_before', 'ac_before', 'INSERT INTO items (x) VALUES (2)', 'ac_after', 'as_after' ]
345
+ MODEL_DB.sqls.clear
346
+ @c.load(:id=>1, :x => 2).save
347
+ MODEL_DB.sqls.should == [ 'as_before', 'au_before', 'UPDATE items SET x = 2 WHERE (id = 1)', 'au_after', 'as_after' ]
348
+ end
349
+
350
+ specify "around_validation should be called around validating records" do
351
+ @c.class_eval do
352
+ def around_validation
353
+ MODEL_DB << 'av_before'
354
+ super
355
+ MODEL_DB << 'av_after'
356
+ end
357
+ def validate
358
+ MODEL_DB << 'validate'
359
+ end
360
+ end
361
+ @c.new(:x => 2).valid?.should == true
362
+ MODEL_DB.sqls.should == [ 'av_before', 'validate', 'av_after' ]
363
+ end
364
+
365
+ specify "around_validation should be able to catch validation errors and modify them" do
366
+ @c.class_eval do
367
+ def validate
368
+ errors.add(:x, 'foo')
369
+ end
370
+ end
371
+ @c.new(:x => 2).valid?.should == false
372
+ @c.class_eval do
373
+ def around_validation
374
+ super
375
+ errors.clear
376
+ end
377
+ end
378
+ @c.new(:x => 2).valid?.should == true
379
+ end
380
+
381
+ specify "around_create that doesn't call super should raise a HookFailed" do
382
+ @c.send(:define_method, :around_create){}
383
+ proc{@c.create(:x => 2)}.should raise_error(Sequel::HookFailed)
384
+ end
385
+
386
+ specify "around_update that doesn't call super should raise a HookFailed" do
387
+ @c.send(:define_method, :around_update){}
388
+ proc{@c.load(:x => 2).save}.should raise_error(Sequel::HookFailed)
389
+ end
390
+
391
+ specify "around_save that doesn't call super should raise a HookFailed" do
392
+ @c.send(:define_method, :around_save){}
393
+ proc{@c.create(:x => 2)}.should raise_error(Sequel::HookFailed)
394
+ proc{@c.load(:x => 2).save}.should raise_error(Sequel::HookFailed)
395
+ end
396
+
397
+ specify "around_destroy that doesn't call super should raise a HookFailed" do
398
+ @c.send(:define_method, :around_destroy){}
399
+ proc{@c.load(:x => 2).destroy}.should raise_error(Sequel::HookFailed)
400
+ end
401
+
402
+ specify "around_validation that doesn't call super should raise a HookFailed" do
403
+ @c.send(:define_method, :around_validation){}
404
+ proc{@c.new.save}.should raise_error(Sequel::HookFailed)
405
+ end
406
+
407
+ specify "around_validation that doesn't call super should have valid? return false" do
408
+ @c.send(:define_method, :around_validation){}
409
+ @c.new.valid?.should == false
410
+ end
411
+
412
+ specify "around_* that doesn't call super should return nil if raise_on_save_failure is false" do
413
+ @c.raise_on_save_failure = false
414
+
415
+ o = @c.load(:id => 1)
416
+ o.meta_def(:around_save){}
417
+ o.save.should == nil
418
+
419
+ o = @c.load(:id => 1)
420
+ o.meta_def(:around_update){}
421
+ o.save.should == nil
422
+
423
+ o = @c.new
424
+ o.meta_def(:around_create){}
425
+ o.save.should == nil
426
+
427
+ o = @c.new
428
+ o.meta_def(:around_validation){}
429
+ o.save.should == nil
430
+ end
431
+
271
432
  end
@@ -52,6 +52,7 @@ describe "Model#save" do
52
52
 
53
53
  it "should use dataset's insert_select method if present" do
54
54
  ds = @c.dataset = @c.dataset.clone
55
+ def ds.supports_insert_select?() true end
55
56
  def ds.insert_select(hash)
56
57
  execute("INSERT INTO items (y) VALUES (2)")
57
58
  {:y=>2}
@@ -1167,6 +1168,29 @@ describe Sequel::Model, "#initialize" do
1167
1168
  m.values.should == {:x => 2}
1168
1169
  end
1169
1170
  end
1171
+
1172
+ describe Sequel::Model, "#initialize_set" do
1173
+ before do
1174
+ @c = Class.new(Sequel::Model){columns :id, :x, :y}
1175
+ end
1176
+
1177
+ specify "should be called by initialize to set the column values" do
1178
+ @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1179
+ @c.new(:x => 2).values.should == {:y => 3}
1180
+ end
1181
+
1182
+ specify "should be called with the hash given to initialize " do
1183
+ x = nil
1184
+ @c.send(:define_method, :initialize_set){|y| x = y}
1185
+ @c.new(:x => 2)
1186
+ x.should == {:x => 2}
1187
+ end
1188
+
1189
+ specify "should not cause columns modified by the method to be considered as changed" do
1190
+ @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1191
+ @c.new(:x => 2).changed_columns.should == []
1192
+ end
1193
+ end
1170
1194
 
1171
1195
  describe Sequel::Model, ".create" do
1172
1196
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- hash: 91
4
+ hash: 103
5
5
  prerelease: false
6
6
  segments:
7
7
  - 3
8
- - 23
8
+ - 24
9
9
  - 0
10
- version: 3.23.0
10
+ version: 3.24.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeremy Evans
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-02 00:00:00 -07:00
18
+ date: 2011-06-01 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -87,6 +87,7 @@ extra_rdoc_files:
87
87
  - doc/release_notes/3.21.0.txt
88
88
  - doc/release_notes/3.22.0.txt
89
89
  - doc/release_notes/3.23.0.txt
90
+ - doc/release_notes/3.24.0.txt
90
91
  files:
91
92
  - MIT-LICENSE
92
93
  - CHANGELOG
@@ -141,6 +142,7 @@ files:
141
142
  - doc/release_notes/3.21.0.txt
142
143
  - doc/release_notes/3.22.0.txt
143
144
  - doc/release_notes/3.23.0.txt
145
+ - doc/release_notes/3.24.0.txt
144
146
  - doc/sharding.rdoc
145
147
  - doc/sql.rdoc
146
148
  - doc/virtual_rows.rdoc
@@ -221,6 +223,11 @@ files:
221
223
  - spec/extensions/to_dot_spec.rb
222
224
  - spec/extensions/association_autoreloading_spec.rb
223
225
  - spec/extensions/serialization_modification_detection_spec.rb
226
+ - spec/extensions/defaults_setter_spec.rb
227
+ - spec/extensions/prepared_statements_spec.rb
228
+ - spec/extensions/prepared_statements_safe_spec.rb
229
+ - spec/extensions/prepared_statements_with_pk_spec.rb
230
+ - spec/extensions/prepared_statements_associations_spec.rb
224
231
  - spec/extensions/columns_introspection_spec.rb
225
232
  - spec/integration/associations_test.rb
226
233
  - spec/integration/database_test.rb
@@ -310,6 +317,9 @@ files:
310
317
  - lib/sequel/adapters/jdbc/postgresql.rb
311
318
  - lib/sequel/adapters/jdbc/sqlite.rb
312
319
  - lib/sequel/adapters/jdbc/as400.rb
320
+ - lib/sequel/adapters/jdbc/informix.rb
321
+ - lib/sequel/adapters/jdbc/jtds.rb
322
+ - lib/sequel/adapters/jdbc/sqlserver.rb
313
323
  - lib/sequel/adapters/mysql.rb
314
324
  - lib/sequel/adapters/odbc.rb
315
325
  - lib/sequel/adapters/odbc/mssql.rb
@@ -323,6 +333,7 @@ files:
323
333
  - lib/sequel/adapters/shared/progress.rb
324
334
  - lib/sequel/adapters/shared/sqlite.rb
325
335
  - lib/sequel/adapters/shared/access.rb
336
+ - lib/sequel/adapters/shared/informix.rb
326
337
  - lib/sequel/adapters/sqlite.rb
327
338
  - lib/sequel/adapters/utils/stored_procedures.rb
328
339
  - lib/sequel/adapters/mysql2.rb
@@ -418,9 +429,15 @@ files:
418
429
  - lib/sequel/plugins/xml_serializer.rb
419
430
  - lib/sequel/plugins/association_autoreloading.rb
420
431
  - lib/sequel/plugins/serialization_modification_detection.rb
432
+ - lib/sequel/plugins/defaults_setter.rb
433
+ - lib/sequel/plugins/prepared_statements.rb
434
+ - lib/sequel/plugins/prepared_statements_safe.rb
435
+ - lib/sequel/plugins/prepared_statements_with_pk.rb
436
+ - lib/sequel/plugins/prepared_statements_associations.rb
421
437
  - lib/sequel/sql.rb
422
438
  - lib/sequel/timezones.rb
423
439
  - lib/sequel/version.rb
440
+ - lib/sequel/ast_transformer.rb
424
441
  - lib/sequel_core.rb
425
442
  - lib/sequel_model.rb
426
443
  has_rdoc: true