sequel 3.21.0 → 3.28.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 (158) hide show
  1. data/CHANGELOG +294 -0
  2. data/README.rdoc +20 -6
  3. data/Rakefile +20 -15
  4. data/doc/association_basics.rdoc +210 -43
  5. data/doc/dataset_basics.rdoc +4 -4
  6. data/doc/mass_assignment.rdoc +54 -0
  7. data/doc/migration.rdoc +15 -538
  8. data/doc/model_hooks.rdoc +64 -27
  9. data/doc/opening_databases.rdoc +37 -10
  10. data/doc/prepared_statements.rdoc +16 -10
  11. data/doc/reflection.rdoc +8 -2
  12. data/doc/release_notes/3.22.0.txt +39 -0
  13. data/doc/release_notes/3.23.0.txt +172 -0
  14. data/doc/release_notes/3.24.0.txt +420 -0
  15. data/doc/release_notes/3.25.0.txt +88 -0
  16. data/doc/release_notes/3.26.0.txt +88 -0
  17. data/doc/release_notes/3.27.0.txt +82 -0
  18. data/doc/release_notes/3.28.0.txt +304 -0
  19. data/doc/schema_modification.rdoc +547 -0
  20. data/doc/testing.rdoc +106 -0
  21. data/doc/transactions.rdoc +97 -0
  22. data/doc/virtual_rows.rdoc +2 -2
  23. data/lib/sequel/adapters/ado.rb +12 -1
  24. data/lib/sequel/adapters/amalgalite.rb +4 -0
  25. data/lib/sequel/adapters/db2.rb +95 -58
  26. data/lib/sequel/adapters/do.rb +12 -0
  27. data/lib/sequel/adapters/firebird.rb +25 -203
  28. data/lib/sequel/adapters/ibmdb.rb +440 -0
  29. data/lib/sequel/adapters/informix.rb +4 -19
  30. data/lib/sequel/adapters/jdbc/as400.rb +0 -7
  31. data/lib/sequel/adapters/jdbc/db2.rb +49 -0
  32. data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
  33. data/lib/sequel/adapters/jdbc/h2.rb +16 -5
  34. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  35. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  36. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  37. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  38. data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
  39. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
  40. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  41. data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
  42. data/lib/sequel/adapters/jdbc.rb +62 -29
  43. data/lib/sequel/adapters/mysql.rb +22 -139
  44. data/lib/sequel/adapters/mysql2.rb +9 -14
  45. data/lib/sequel/adapters/odbc/db2.rb +21 -0
  46. data/lib/sequel/adapters/odbc.rb +15 -3
  47. data/lib/sequel/adapters/oracle.rb +17 -1
  48. data/lib/sequel/adapters/postgres.rb +111 -16
  49. data/lib/sequel/adapters/shared/access.rb +21 -0
  50. data/lib/sequel/adapters/shared/db2.rb +290 -0
  51. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  52. data/lib/sequel/adapters/shared/informix.rb +45 -0
  53. data/lib/sequel/adapters/shared/mssql.rb +85 -47
  54. data/lib/sequel/adapters/shared/mysql.rb +50 -7
  55. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
  56. data/lib/sequel/adapters/shared/oracle.rb +0 -4
  57. data/lib/sequel/adapters/shared/postgres.rb +75 -43
  58. data/lib/sequel/adapters/shared/sqlite.rb +56 -8
  59. data/lib/sequel/adapters/sqlite.rb +12 -11
  60. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  61. data/lib/sequel/adapters/tinytds.rb +139 -7
  62. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
  63. data/lib/sequel/ast_transformer.rb +190 -0
  64. data/lib/sequel/connection_pool/threaded.rb +3 -2
  65. data/lib/sequel/connection_pool.rb +1 -1
  66. data/lib/sequel/core.rb +6 -5
  67. data/lib/sequel/database/connecting.rb +5 -5
  68. data/lib/sequel/database/dataset.rb +1 -1
  69. data/lib/sequel/database/dataset_defaults.rb +1 -1
  70. data/lib/sequel/database/logging.rb +1 -1
  71. data/lib/sequel/database/misc.rb +38 -17
  72. data/lib/sequel/database/query.rb +50 -19
  73. data/lib/sequel/database/schema_generator.rb +8 -5
  74. data/lib/sequel/database/schema_methods.rb +52 -27
  75. data/lib/sequel/dataset/actions.rb +167 -48
  76. data/lib/sequel/dataset/features.rb +57 -8
  77. data/lib/sequel/dataset/graph.rb +1 -1
  78. data/lib/sequel/dataset/misc.rb +39 -20
  79. data/lib/sequel/dataset/mutation.rb +3 -3
  80. data/lib/sequel/dataset/prepared_statements.rb +29 -14
  81. data/lib/sequel/dataset/query.rb +182 -32
  82. data/lib/sequel/dataset/sql.rb +31 -58
  83. data/lib/sequel/dataset.rb +8 -0
  84. data/lib/sequel/exceptions.rb +4 -0
  85. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  86. data/lib/sequel/extensions/migration.rb +6 -4
  87. data/lib/sequel/extensions/to_dot.rb +95 -83
  88. data/lib/sequel/model/associations.rb +893 -309
  89. data/lib/sequel/model/base.rb +302 -105
  90. data/lib/sequel/model/errors.rb +1 -1
  91. data/lib/sequel/model/exceptions.rb +5 -1
  92. data/lib/sequel/model.rb +13 -7
  93. data/lib/sequel/plugins/association_pks.rb +22 -4
  94. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  95. data/lib/sequel/plugins/identity_map.rb +113 -6
  96. data/lib/sequel/plugins/many_through_many.rb +67 -5
  97. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  98. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  99. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  100. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  101. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  102. data/lib/sequel/plugins/sharding.rb +12 -20
  103. data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
  104. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  105. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  106. data/lib/sequel/sql.rb +107 -51
  107. data/lib/sequel/timezones.rb +12 -3
  108. data/lib/sequel/version.rb +1 -1
  109. data/spec/adapters/db2_spec.rb +146 -0
  110. data/spec/adapters/mssql_spec.rb +36 -0
  111. data/spec/adapters/mysql_spec.rb +36 -19
  112. data/spec/adapters/postgres_spec.rb +115 -28
  113. data/spec/adapters/spec_helper.rb +6 -0
  114. data/spec/adapters/sqlite_spec.rb +11 -0
  115. data/spec/core/connection_pool_spec.rb +62 -77
  116. data/spec/core/database_spec.rb +244 -287
  117. data/spec/core/dataset_spec.rb +383 -34
  118. data/spec/core/expression_filters_spec.rb +159 -41
  119. data/spec/core/schema_spec.rb +326 -3
  120. data/spec/core/spec_helper.rb +45 -0
  121. data/spec/extensions/association_pks_spec.rb +38 -0
  122. data/spec/extensions/columns_introspection_spec.rb +91 -0
  123. data/spec/extensions/defaults_setter_spec.rb +64 -0
  124. data/spec/extensions/identity_map_spec.rb +162 -0
  125. data/spec/extensions/many_through_many_spec.rb +195 -20
  126. data/spec/extensions/migration_spec.rb +17 -17
  127. data/spec/extensions/nested_attributes_spec.rb +1 -0
  128. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  129. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  130. data/spec/extensions/prepared_statements_spec.rb +72 -0
  131. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  132. data/spec/extensions/schema_dumper_spec.rb +2 -2
  133. data/spec/extensions/schema_spec.rb +12 -20
  134. data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
  135. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  136. data/spec/extensions/spec_helper.rb +3 -1
  137. data/spec/extensions/to_dot_spec.rb +3 -5
  138. data/spec/extensions/xml_serializer_spec.rb +16 -4
  139. data/spec/integration/associations_test.rb +405 -15
  140. data/spec/integration/database_test.rb +4 -2
  141. data/spec/integration/dataset_test.rb +240 -20
  142. data/spec/integration/plugin_test.rb +142 -5
  143. data/spec/integration/prepared_statement_test.rb +174 -95
  144. data/spec/integration/schema_test.rb +128 -16
  145. data/spec/integration/spec_helper.rb +15 -0
  146. data/spec/integration/transaction_test.rb +40 -0
  147. data/spec/integration/type_test.rb +16 -2
  148. data/spec/model/association_reflection_spec.rb +91 -0
  149. data/spec/model/associations_spec.rb +476 -5
  150. data/spec/model/base_spec.rb +91 -1
  151. data/spec/model/eager_loading_spec.rb +519 -31
  152. data/spec/model/hooks_spec.rb +161 -0
  153. data/spec/model/model_spec.rb +89 -2
  154. data/spec/model/plugins_spec.rb +17 -0
  155. data/spec/model/record_spec.rb +184 -12
  156. data/spec/model/spec_helper.rb +5 -0
  157. data/spec/model/validations_spec.rb +11 -0
  158. metadata +85 -34
@@ -397,6 +397,12 @@ describe "Database#tables" do
397
397
  end
398
398
  end
399
399
 
400
+ describe "Database#views" do
401
+ specify "should raise Sequel::NotImplemented" do
402
+ proc {Sequel::Database.new.views}.should raise_error(Sequel::NotImplemented)
403
+ end
404
+ end
405
+
400
406
  describe "Database#indexes" do
401
407
  specify "should raise Sequel::NotImplemented" do
402
408
  proc {Sequel::Database.new.indexes(:table)}.should raise_error(Sequel::NotImplemented)
@@ -472,225 +478,6 @@ describe "Database#test_connection" do
472
478
  end
473
479
  end
474
480
 
475
- class DummyDataset < Sequel::Dataset
476
- def first
477
- raise if @opts[:from] == [:a]
478
- true
479
- end
480
- end
481
-
482
- class DummyDatabase < Sequel::Database
483
- attr_reader :sqls
484
-
485
- def execute(sql, opts={})
486
- @sqls ||= []
487
- @sqls << sql
488
- end
489
-
490
- def transaction; yield; end
491
-
492
- def dataset
493
- DummyDataset.new(self)
494
- end
495
- end
496
-
497
- describe "Database#create_table" do
498
- before do
499
- @db = DummyDatabase.new
500
- end
501
-
502
- specify "should construct proper SQL" do
503
- @db.create_table :test do
504
- primary_key :id, :integer, :null => false
505
- column :name, :text
506
- index :name, :unique => true
507
- end
508
- @db.sqls.should == [
509
- 'CREATE TABLE test (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
510
- 'CREATE UNIQUE INDEX test_name_index ON test (name)'
511
- ]
512
- end
513
-
514
- specify "should create a temporary table" do
515
- @db.create_table :test_tmp, :temp => true do
516
- primary_key :id, :integer, :null => false
517
- column :name, :text
518
- index :name, :unique => true
519
- end
520
-
521
- @db.sqls.should == [
522
- 'CREATE TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
523
- 'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)'
524
- ]
525
- end
526
- end
527
-
528
- describe "Database#alter_table" do
529
- before do
530
- @db = DummyDatabase.new
531
- end
532
-
533
- specify "should construct proper SQL" do
534
- @db.alter_table :xyz do
535
- add_column :aaa, :text, :null => false, :unique => true
536
- drop_column :bbb
537
- rename_column :ccc, :ddd
538
- set_column_type :eee, :integer
539
- set_column_default :hhh, 'abcd'
540
-
541
- add_index :fff, :unique => true
542
- drop_index :ggg
543
- end
544
-
545
- @db.sqls.should == [
546
- 'ALTER TABLE xyz ADD COLUMN aaa text NOT NULL UNIQUE',
547
- 'ALTER TABLE xyz DROP COLUMN bbb',
548
- 'ALTER TABLE xyz RENAME COLUMN ccc TO ddd',
549
- 'ALTER TABLE xyz ALTER COLUMN eee TYPE integer',
550
- "ALTER TABLE xyz ALTER COLUMN hhh SET DEFAULT 'abcd'",
551
-
552
- 'CREATE UNIQUE INDEX xyz_fff_index ON xyz (fff)',
553
- 'DROP INDEX xyz_ggg_index'
554
- ]
555
- end
556
- end
557
-
558
- describe "Database#add_column" do
559
- before do
560
- @db = DummyDatabase.new
561
- end
562
-
563
- specify "should construct proper SQL" do
564
- @db.add_column :test, :name, :text, :unique => true
565
- @db.sqls.should == [
566
- 'ALTER TABLE test ADD COLUMN name text UNIQUE'
567
- ]
568
- end
569
- end
570
-
571
- describe "Database#drop_column" do
572
- before do
573
- @db = DummyDatabase.new
574
- end
575
-
576
- specify "should construct proper SQL" do
577
- @db.drop_column :test, :name
578
- @db.sqls.should == [
579
- 'ALTER TABLE test DROP COLUMN name'
580
- ]
581
- end
582
- end
583
-
584
- describe "Database#rename_column" do
585
- before do
586
- @db = DummyDatabase.new
587
- end
588
-
589
- specify "should construct proper SQL" do
590
- @db.rename_column :test, :abc, :def
591
- @db.sqls.should == [
592
- 'ALTER TABLE test RENAME COLUMN abc TO def'
593
- ]
594
- end
595
- end
596
-
597
- describe "Database#set_column_type" do
598
- before do
599
- @db = DummyDatabase.new
600
- end
601
-
602
- specify "should construct proper SQL" do
603
- @db.set_column_type :test, :name, :integer
604
- @db.sqls.should == [
605
- 'ALTER TABLE test ALTER COLUMN name TYPE integer'
606
- ]
607
- end
608
- end
609
-
610
- describe "Database#set_column_default" do
611
- before do
612
- @db = DummyDatabase.new
613
- end
614
-
615
- specify "should construct proper SQL" do
616
- @db.set_column_default :test, :name, 'zyx'
617
- @db.sqls.should == [
618
- "ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"
619
- ]
620
- end
621
- end
622
-
623
- describe "Database#add_index" do
624
- before do
625
- @db = DummyDatabase.new
626
- end
627
-
628
- specify "should construct proper SQL" do
629
- @db.add_index :test, :name, :unique => true
630
- @db.sqls.should == [
631
- 'CREATE UNIQUE INDEX test_name_index ON test (name)'
632
- ]
633
- end
634
-
635
- specify "should accept multiple columns" do
636
- @db.add_index :test, [:one, :two]
637
- @db.sqls.should == [
638
- 'CREATE INDEX test_one_two_index ON test (one, two)'
639
- ]
640
- end
641
- end
642
-
643
- describe "Database#drop_index" do
644
- before do
645
- @db = DummyDatabase.new
646
- end
647
-
648
- specify "should construct proper SQL" do
649
- @db.drop_index :test, :name
650
- @db.sqls.should == [
651
- 'DROP INDEX test_name_index'
652
- ]
653
- end
654
-
655
- end
656
-
657
- class Dummy2Database < Sequel::Database
658
- attr_reader :sql
659
- def execute(sql); @sql = sql; end
660
- def transaction; yield; end
661
- end
662
-
663
- describe "Database#drop_table" do
664
- before do
665
- @db = DummyDatabase.new
666
- end
667
-
668
- specify "should construct proper SQL" do
669
- @db.drop_table :test
670
- @db.sqls.should == ['DROP TABLE test']
671
- end
672
-
673
- specify "should accept multiple table names" do
674
- @db.drop_table :a, :bb, :ccc
675
- @db.sqls.should == [
676
- 'DROP TABLE a',
677
- 'DROP TABLE bb',
678
- 'DROP TABLE ccc'
679
- ]
680
- end
681
- end
682
-
683
- describe "Database#rename_table" do
684
- before do
685
- @db = DummyDatabase.new
686
- end
687
-
688
- specify "should construct proper SQL" do
689
- @db.rename_table :abc, :xyz
690
- @db.sqls.should == ['ALTER TABLE abc RENAME TO xyz']
691
- end
692
- end
693
-
694
481
  describe "Database#table_exists?" do
695
482
  specify "should try to select the first record from the table's dataset" do
696
483
  db2 = DummyDatabase.new
@@ -795,6 +582,25 @@ describe "Database#transaction" do
795
582
  t.join
796
583
  @db.transactions.should be_empty
797
584
  end
585
+
586
+ if (!defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or RUBY_ENGINE == 'rbx') and RUBY_VERSION < '1.9'
587
+ specify "should handle Thread#kill for transactions inside threads" do
588
+ q = Queue.new
589
+ q1 = Queue.new
590
+ t = Thread.new do
591
+ @db.transaction do
592
+ @db.execute 'DROP TABLE test'
593
+ q1.push nil
594
+ q.pop
595
+ @db.execute 'DROP TABLE test2'
596
+ end
597
+ end
598
+ q1.pop
599
+ t.kill
600
+ t.join
601
+ @db.sql.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
602
+ end
603
+ end
798
604
  end
799
605
 
800
606
  describe "Database#transaction with savepoints" do
@@ -1249,74 +1055,6 @@ describe "Database#[]" do
1249
1055
  end
1250
1056
  end
1251
1057
 
1252
- describe "Database#create_view" do
1253
- before do
1254
- @db = DummyDatabase.new
1255
- end
1256
-
1257
- specify "should construct proper SQL with raw SQL" do
1258
- @db.create_view :test, "SELECT * FROM xyz"
1259
- @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1260
- @db.sqls.clear
1261
- @db.create_view :test.identifier, "SELECT * FROM xyz"
1262
- @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1263
- end
1264
-
1265
- specify "should construct proper SQL with dataset" do
1266
- @db.create_view :test, @db[:items].select(:a, :b).order(:c)
1267
- @db.sqls.should == ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
1268
- @db.sqls.clear
1269
- @db.create_view :test.qualify(:sch), @db[:items].select(:a, :b).order(:c)
1270
- @db.sqls.should == ['CREATE VIEW sch.test AS SELECT a, b FROM items ORDER BY c']
1271
- end
1272
- end
1273
-
1274
- describe "Database#create_or_replace_view" do
1275
- before do
1276
- @db = DummyDatabase.new
1277
- end
1278
-
1279
- specify "should construct proper SQL with raw SQL" do
1280
- @db.create_or_replace_view :test, "SELECT * FROM xyz"
1281
- @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT * FROM xyz']
1282
- @db.sqls.clear
1283
- @db.create_or_replace_view :sch__test, "SELECT * FROM xyz"
1284
- @db.sqls.should == ['CREATE OR REPLACE VIEW sch.test AS SELECT * FROM xyz']
1285
- end
1286
-
1287
- specify "should construct proper SQL with dataset" do
1288
- @db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
1289
- @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1290
- @db.sqls.clear
1291
- @db.create_or_replace_view :test.identifier, @db[:items].select(:a, :b).order(:c)
1292
- @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1293
- end
1294
- end
1295
-
1296
- describe "Database#drop_view" do
1297
- before do
1298
- @db = DummyDatabase.new
1299
- end
1300
-
1301
- specify "should construct proper SQL" do
1302
- @db.drop_view :test
1303
- @db.drop_view :test.identifier
1304
- @db.drop_view :sch__test
1305
- @db.drop_view :test.qualify(:sch)
1306
- @db.sqls.should == ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test', 'DROP VIEW sch.test']
1307
- end
1308
- end
1309
-
1310
- describe "Database#alter_table_sql" do
1311
- before do
1312
- @db = DummyDatabase.new
1313
- end
1314
-
1315
- specify "should raise error for an invalid op" do
1316
- proc {@db.send(:alter_table_sql, :mau, :op => :blah)}.should raise_error(Sequel::Error)
1317
- end
1318
- end
1319
-
1320
1058
  describe "Database#inspect" do
1321
1059
  before do
1322
1060
  @db = DummyDatabase.new
@@ -1594,6 +1332,225 @@ describe "Database#typecast_value" do
1594
1332
  proc{@db.typecast_value(:datetime, 4)}.should raise_error(Sequel::InvalidValue)
1595
1333
  end
1596
1334
 
1335
+ specify "should handle integers with leading 0 as base 10" do
1336
+ @db.typecast_value(:integer, "013").should == 13
1337
+ @db.typecast_value(:integer, "08").should == 8
1338
+ @db.typecast_value(:integer, "000013").should == 13
1339
+ @db.typecast_value(:integer, "000008").should == 8
1340
+ end
1341
+
1342
+ specify "should handle integers with leading 0x as base 16" do
1343
+ @db.typecast_value(:integer, "0x013").should == 19
1344
+ @db.typecast_value(:integer, "0x80").should == 128
1345
+ end
1346
+
1347
+ specify "should typecast blobs as as Sequel::SQL::Blob" do
1348
+ v = @db.typecast_value(:blob, "0x013")
1349
+ v.should be_a_kind_of(Sequel::SQL::Blob)
1350
+ v.should == Sequel::SQL::Blob.new("0x013")
1351
+ @db.typecast_value(:blob, v).object_id.should == v.object_id
1352
+ end
1353
+
1354
+ specify "should typecast boolean values to true, false, or nil" do
1355
+ @db.typecast_value(:boolean, false).should be_false
1356
+ @db.typecast_value(:boolean, 0).should be_false
1357
+ @db.typecast_value(:boolean, "0").should be_false
1358
+ @db.typecast_value(:boolean, 'f').should be_false
1359
+ @db.typecast_value(:boolean, 'false').should be_false
1360
+ @db.typecast_value(:boolean, true).should be_true
1361
+ @db.typecast_value(:boolean, 1).should be_true
1362
+ @db.typecast_value(:boolean, '1').should be_true
1363
+ @db.typecast_value(:boolean, 't').should be_true
1364
+ @db.typecast_value(:boolean, 'true').should be_true
1365
+ @db.typecast_value(:boolean, '').should be_nil
1366
+ end
1367
+
1368
+ specify "should typecast date values to Date" do
1369
+ @db.typecast_value(:date, Date.today).should == Date.today
1370
+ @db.typecast_value(:date, DateTime.now).should == Date.today
1371
+ @db.typecast_value(:date, Time.now).should == Date.today
1372
+ @db.typecast_value(:date, Date.today.to_s).should == Date.today
1373
+ @db.typecast_value(:date, :year=>Date.today.year, :month=>Date.today.month, :day=>Date.today.day).should == Date.today
1374
+ end
1375
+
1376
+ specify "should typecast datetime values to Sequel.datetime_class with correct timezone handling" do
1377
+ t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
1378
+ t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
1379
+ t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
1380
+ t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
1381
+ dt = DateTime.civil(2011, 1, 2, 3, 4, 5)
1382
+ r1 = defined?(Rational) ? Rational(t2.utc_offset, 86400) : t2.utc_offset/86400.0
1383
+ r2 = defined?(Rational) ? Rational((t - t2).to_i, 86400) : (t - t2).to_i/86400.0
1384
+ dt2 = DateTime.civil(2011, 1, 2, 3, 4, 5, r1)
1385
+ dt3 = DateTime.civil(2011, 1, 2, 3, 4, 5) - r2
1386
+ dt4 = DateTime.civil(2011, 1, 2, 3, 4, 5, r1) + r2
1387
+
1388
+ t.should == t4
1389
+ t2.should == t3
1390
+ dt.should == dt4
1391
+ dt2.should == dt3
1392
+
1393
+ check = proc do |i, o|
1394
+ v = @db.typecast_value(:datetime, i)
1395
+ v.should == o
1396
+ if o.is_a?(Time)
1397
+ v.utc_offset.should == o.utc_offset
1398
+ else
1399
+ v.offset.should == o.offset
1400
+ end
1401
+ end
1402
+ begin
1403
+ @db.typecast_value(:datetime, dt).should == t
1404
+ @db.typecast_value(:datetime, dt2).should == t2
1405
+ @db.typecast_value(:datetime, t).should == t
1406
+ @db.typecast_value(:datetime, t2).should == t2
1407
+ @db.typecast_value(:datetime, dt.to_s).should == t
1408
+ @db.typecast_value(:datetime, dt.strftime('%F %T')).should == t2
1409
+ @db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == Time.mktime(2011, 1, 2, 0, 0, 0)
1410
+ @db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec).should == t2
1411
+
1412
+ Sequel.datetime_class = DateTime
1413
+ @db.typecast_value(:datetime, dt).should == dt
1414
+ @db.typecast_value(:datetime, dt2).should == dt2
1415
+ @db.typecast_value(:datetime, t).should == dt
1416
+ @db.typecast_value(:datetime, t2).should == dt2
1417
+ @db.typecast_value(:datetime, dt.to_s).should == dt
1418
+ @db.typecast_value(:datetime, dt.strftime('%F %T')).should == dt
1419
+ @db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == DateTime.civil(2011, 1, 2, 0, 0, 0)
1420
+ @db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec).should == dt
1421
+
1422
+ Sequel.application_timezone = :utc
1423
+ Sequel.typecast_timezone = :local
1424
+ Sequel.datetime_class = Time
1425
+ check[dt, t]
1426
+ check[dt2, t3]
1427
+ check[t, t]
1428
+ check[t2, t3]
1429
+ check[dt.to_s, t]
1430
+ check[dt.strftime('%F %T'), t3]
1431
+ check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
1432
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t3]
1433
+
1434
+ Sequel.datetime_class = DateTime
1435
+ check[dt, dt]
1436
+ check[dt2, dt3]
1437
+ check[t, dt]
1438
+ check[t2, dt3]
1439
+ check[dt.to_s, dt]
1440
+ check[dt.strftime('%F %T'), dt3]
1441
+ check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
1442
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt3]
1443
+
1444
+ Sequel.typecast_timezone = :utc
1445
+ Sequel.datetime_class = Time
1446
+ check[dt, t]
1447
+ check[dt2, t3]
1448
+ check[t, t]
1449
+ check[t2, t3]
1450
+ check[dt.to_s, t]
1451
+ check[dt.strftime('%F %T'), t]
1452
+ check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
1453
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t]
1454
+
1455
+ Sequel.datetime_class = DateTime
1456
+ check[dt, dt]
1457
+ check[dt2, dt3]
1458
+ check[t, dt]
1459
+ check[t2, dt3]
1460
+ check[dt.to_s, dt]
1461
+ check[dt.strftime('%F %T'), dt]
1462
+ check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
1463
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt]
1464
+
1465
+ Sequel.application_timezone = :local
1466
+ Sequel.datetime_class = Time
1467
+ check[dt, t4]
1468
+ check[dt2, t2]
1469
+ check[t, t4]
1470
+ check[t2, t2]
1471
+ check[dt.to_s, t4]
1472
+ check[dt.strftime('%F %T'), t4]
1473
+ check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
1474
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t4]
1475
+
1476
+ Sequel.datetime_class = DateTime
1477
+ check[dt, dt4]
1478
+ check[dt2, dt2]
1479
+ check[t, dt4]
1480
+ check[t2, dt2]
1481
+ check[dt.to_s, dt4]
1482
+ check[dt.strftime('%F %T'), dt4]
1483
+ check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
1484
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt4]
1485
+
1486
+ Sequel.typecast_timezone = :local
1487
+ Sequel.datetime_class = Time
1488
+ check[dt, t4]
1489
+ check[dt2, t2]
1490
+ check[t, t4]
1491
+ check[t2, t2]
1492
+ check[dt.to_s, t4]
1493
+ check[dt.strftime('%F %T'), t2]
1494
+ check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
1495
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t2]
1496
+
1497
+ Sequel.datetime_class = DateTime
1498
+ check[dt, dt4]
1499
+ check[dt2, dt2]
1500
+ check[t, dt4]
1501
+ check[t2, dt2]
1502
+ check[dt.to_s, dt4]
1503
+ check[dt.strftime('%F %T'), dt2]
1504
+ check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
1505
+ check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt2]
1506
+
1507
+ ensure
1508
+ Sequel.default_timezone = nil
1509
+ Sequel.datetime_class = Time
1510
+ end
1511
+ end
1512
+
1513
+ specify "should typecast decimal values to BigDecimal" do
1514
+ [1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
1515
+ v = @db.typecast_value(:decimal, i)
1516
+ v.should be_a_kind_of(BigDecimal)
1517
+ v.should == BigDecimal.new('1.0')
1518
+ end
1519
+ end
1520
+
1521
+ specify "should typecast float values to Float" do
1522
+ [1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
1523
+ v = @db.typecast_value(:float, i)
1524
+ v.should be_a_kind_of(Float)
1525
+ v.should == 1.0
1526
+ end
1527
+ end
1528
+
1529
+ specify "should typecast string values to String" do
1530
+ [1.0, '1.0', '1.0'.to_sequel_blob].each do |i|
1531
+ v = @db.typecast_value(:string, i)
1532
+ v.should be_an_instance_of(String)
1533
+ v.should == "1.0"
1534
+ end
1535
+ end
1536
+
1537
+ specify "should typecast time values to SQLTime" do
1538
+ t = Time.now
1539
+ st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3)
1540
+ [st, Time.utc(t.year, t.month, t.day, 1, 2, 3), Time.local(t.year, t.month, t.day, 1, 2, 3), '01:02:03', {:hour=>1, :minute=>2, :second=>3}].each do |i|
1541
+ v = @db.typecast_value(:time, i)
1542
+ v.should be_an_instance_of(Sequel::SQLTime)
1543
+ v.should == st
1544
+ end
1545
+ end
1546
+
1547
+ specify "should correctly handle time value conversion to SQLTime with fractional seconds" do
1548
+ t = Time.now
1549
+ st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3, 500000)
1550
+ t = Time.local(t.year, t.month, t.day, 1, 2, 3, 500000)
1551
+ @db.typecast_value(:time, t).should == st
1552
+ end
1553
+
1597
1554
  specify "should have an underlying exception class available at wrapped_exception" do
1598
1555
  begin
1599
1556
  @db.typecast_value(:date, 'a')